-
Notifications
You must be signed in to change notification settings - Fork 257
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
Expose each frame's canonical frame address (CFA) #339
Comments
Done in #341! |
@fitzgen @alexcrichton Now the code that was added as #341 introduces a method called "get_sp" which is implemented via _Unwind_GetCFA on the next inner frame. This is only correct if the CFA of a function equals the SP at function entry, which is not true on s390x. Now, I'm not completely sure what the right way to fix this is. If the intent of the function is actually to return the SP, then we'll need a different implementation on s390x. (I have a patch working that uses _Unwind_GetGR(ctx, 15) instead of _Unwind_GetCFA.) However, if the intent is really to return the CFA then maybe the function should be renamed? Also, in that case the users (at least the one in wasmtime) needs to fixed then. What do you suggest? |
I believe the intention turned out to be "expose a function to get the stack pointer register" and leave it up to applications to figure out how to infer the CFA from that. Seems fine though to have a s390x-specific part of the code which changes the implementation here! |
I think CFA is actually the right thing to expose. Unlike the stack pointer it is guaranteed to be stable for a single frame. The stack pointer may be changed by the compiler at any point. Where does Wasmtime need the stack pointer? |
Wasmtime uses the stack pointer during garbage collection, where it looks up stack maps. It is indeed the case that the stack pointer can change, but wasmtime creates stack maps that take the current SP into account. If this is changed to be CFA-relative instead, then the stack map creation needs to be updated accordingly. |
I see the discussion is still ongoing, but there's the implementation of a get_sp appropriate for s390x, if this is the way to go: |
|
The implementation in libunwind also seems buggy, that's true. It actually doesn't get used however (at least on typical Linux platforms), because nobody links against libunwind. Instead, we get _Unwind_GetCFA together with all the other _Unwind routines from the system libgcc (or sometimes glibc). At least there, _Unwind_GetCFA actually does return the correct CFA. As to which frame is involved, _Unwind_CFA returns the CFA of the current frame (i.e. the one where you pass the context in), while all the other routines, in particular _Unwind_GetIP and _Unwind_GetGR return register values from the previous frame. [ Therefore, it does make sense on most platforms to implement _Unwind_CFA (determine CFA of the current frame) in terms of unwinding the SP of the previous frame, because on most platforms the CFA of the current frame does indeed equal the value of SP on function entry, which is the SP of the previous frame. But again this is not correct on s390x. ] |
I think the |
Well, when I was debugging it today, I was stepping into libgcc, not any version of libunwind. |
Just checked again, and on my system the "wasmtime" binary I get from "cargo build" resolves all the _Unwind symbols dynamically against libgcc_s.so:
Not sure if this was the intent, but that's what happening right now (at least on my system) ... |
Very interesting! When I was debugging a few months ago I was definitely getting the SP-as-the-"CFA" behavior! Can't remember what lib it was coming from, but what I was seeing was consistent with the libunwind sources. I vaguely remember libgcc embedding its own vendored version of libunwind... Anyways, cleaning all this stuff up would definitely be nice! |
For the _Unwind routines, libgcc is definitely the "canonical" source. Sometimes that version is also "vendored" into glibc. Libunwind primarily defines its own API, but then also implements the _Unwind routines, but I think this is only really intended to be used for compatibility on systems that don't have libgcc (or glibc). In any case, as I said above, on most (non-s390x) platforms the previous-SP-as-CFA implementation is actually correct. |
Yes, this would be correct, but libunwind returns the current frame's SP, not the previous frame's SP! Anyways, if you can clean up the implementation and make it make sense, please go for it! |
Hmm, I don't see that -- the libunwind implementation of _Unwind_GetCFA is |
For better or worse there's like 100 copies of libunwind but most of the time each platform uses only one of them. Rust's musl target, for example, should use libunwind for statically linked binaries. macOS additionally uses libunwind from the system. As you've seen though the libgcc version is used for most other Linux targets. I don't really have a preference of what API to export here or what platforms it's supported on. It seems inevitable that this crate has the union of all platform capabilities and then documents specifically that each function only works on some platforms and not others. As implementations are figured out and/or become available we can fill things in though. |
In
libunwind
, this is_Unwind_GetCFA
.Pretty sure other unwinders will also expose this API.
Worst case scenario, we can go to the parent frame and ask for its stack pointer, which will be the base of the child frame 😆
The text was updated successfully, but these errors were encountered: