-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DONTMERGE] Aarch64 unwinding support #7
base: master
Are you sure you want to change the base?
Conversation
First of all, I really like what you did with the asm/glue code. Obviously I can't comment much on the AArch64 specifics as I'm not familiar with them. What stuck out to me though is that you changed Registers to zero-initialize all registers. Is there a specific reason for this?
I think finding the right way to abstract the register state is a hard problem, especially when it comes to something like cross-platform compatibility. Perhaps a trait based solution may be the right choice ( |
Fun: rust-lang/rust#52836. This is what causes the segfault I believe. Guess I'll move to global_asm. |
If you mean https://github.com/roblabla/unwind-rs/blob/652553568bc8d2ee89bd05d17bbacdc04e35c367/unwind/src/registers.rs#L9, that's totally a mistake. Should have put None in there - or even better, called out to Default::default(). Fixing it. I think I'll first PR something that works properly, and then have a follow-up PR refactoring Registers in something with a bit less overhead. I'm personally interested in having something low-overhead because the context I'll be using this in might have a fairly small stack (I believe 8KB), so storing excess data might cause issues. |
Fixed a few more bugs. We are now triggering an assert while unwinding the stack with RUST_BACKTRACE=1.
It doesn't cause issues with RUST_BACKTRACE=0, because the unwinding stops before it hits the problematic frame. EDIT : The problematic frame seems to be the _start function. Hmm. |
So, if I'm reading this right, the FDE returned by |
In that case, why are you manually implementing
Sure, sounds good.
This is a tricky problem. From what I remember glibc's
Since it's not really DWARF it makes sense that dwarfdump doesn't support it. I'm not aware of any tools, I just stared at hexdumps. |
I'm implementing default manually because derive(Default) doesn't work for arrays bigger than 32. That's also why I removed derive(PartialEq) and derive(Eq). I didn't bother reimplementing those because they were unused as far as I could see. |
Oh, of course, I forgot about that. |
So yeah, I checked both the .eh_frame_hdr (through tons of logs) and .eh_frame (through dwarfdump), and the I'm going to attempt compiling gcc's libunwind with tracing information, and compile the demo against it. Maybe that will reveal what's wrong.
|
So, I managed to make a stopgap solution. I made I've played around with various libraries. GCC's libunwind sadly has no debug. However, I can tell its _Unwind_Backtrace returns END_OF_STACK. Nongnu's libunwind returns ENOINFO, so it has the same problem we do. I haven't tried llvm's Libunwind, it's next on my list. |
b1b05ab
to
a7a6d62
Compare
Hey. So I'm currently working on a 32-bit x86 port of the unwinder. This code is kinda old, and I'm not quite sure what's necessary to bring it upstream. I'm thinking of submitting a subset of this PR that just refactors the existing code to be backend agnostic, on top of which this PR (and a new one) will build to add aarch64 and x86 support. |
Considering that I've been tied up in other projects for quite some time now now and will be for the near future at least I'm open to merging pretty much any reasonable patch. In other words, feel free to submit whatever you think makes sense and I will gladly review and merge all of it. |
Hey,
This is not ready to be merged yet, but I figured I'd submit the PR early to get some feedback.
So I added a partially working unwinder for AArch64 (there are still a few bugs lurking, RUST_BACKTRACE=1 causes a segfault for some reason, trace segfaults). It runs the example demo properly though.
In order to restore callee-saved SIMD Vector registers, I had to bump the size of Registers from 32 to 96. This causes a bit of a problem: Registers now have an overhead of 96 * 8 = 768 bytes. I feel like that might be a bit huge.
In truth, I don't need that many bytes: many of the registers in that space are reserved. I only have 64 actual registers that need to be stored, the "holes" are unused. I'm thinking that maybe I should merge LandingRegisters and Registers, and have DwarfRegister map to a field inside LandingRegisters ? Or maybe this is all premature optimization. I'm not sure :).
Now I just need to figure out why RUST_BACKTRACE=1 causes a segfault. For some reason, in the _Unwind_Backtrace closure, the
trace
callback becomes invalid (it contains a pointer on the stack instead of a function pointer). I suppose I'm overflowing the stack somewhere 👀