-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
Segfault in _Backtrace_Unwind #47551
Comments
I ran into this as well. |
There doesn't seem to be any movement on the LLVM issue since I raised it, not even an assignee. Do you know if this is normal behaviour for them? Or if I've mis-raised the issue? |
Running into this as well at OneSignal |
I can reproduce this on latest stable on an open source project:
On the second run of the final command, the background process will segfault. |
After much investigation, I think there's two bugs here, one that LLVM's unwinder will consider unreadable memory as part of the The crash is specifically happening when trying to find unwind information for the frame above
This in and of itself isn't a huge problem, the The issue is that libunwind's logic for searching for FDE (frame description entry) for the parent frame is pretty all-encompassing and runs in many phases, and one of these crashes (sometimes) if there searched for address is not present in the unwind information). At a high level the process looks like (https://github.com/llvm-mirror/libunwind/blob/release_39/src/UnwindCursor.hpp#L1196)
For Rust x86_64 musl binaries, the compiler has provided DWARF unwind information, so we fall into the second bullet (https://github.com/llvm-mirror/libunwind/blob/release_39/src/UnwindCursor.hpp#L866):
Digging further, we see that the logic for scanning the
In each loop we check that the newly found CIE entry is in a reasonable place (between Unfortunately, as in the linked issue originally
So, what's the bug(s) here?
Either of these would fix this issue, probably both should be done? |
Ah, there's another possible route for the crash:
|
I've ran into this issue as well. What's the status of this? |
I've been looking at a proper fix for this and neither of the two paths I proposed above are yeilding simple results:
Another option would be for LLVM to skip walking the |
Here are two tested workarounds, neither very pretty, but both work: 1 - Custom link script
2 - Add a custom object
2, Add |
Hi! Is this still an issue? If so, is there perhaps a simpler way to reproduce this than the instructions linked above? |
The setup that's needed is:
So something like the following should trigger the fault:
This builds a huge Hedging words because I can't reproduce the issue on my development machine (I run out of RAM and get OOM-killered). |
Hmm, that doesn't seem to be sufficient (tested on the current stable and nightly). I get this output when building and running this on Arch Linux:
I also get the same output when using |
I noticed the wrong ehSectionEnd calculation independently and filed https://bugs.llvm.org/show_bug.cgi?id=46829. |
It looks like the gcc driver on Alpine adds the FWIW, it looks like LLVM's LLD linker automatically adds a terminator to the end of .eh_frame, even if one isn't present in the linker inputs, so that could be a workaround:
I think libunwind should stop scanning .eh_frame when it finds unwind info from .eh_frame_hdr (i.e. the GNU_EH_FRAME segment). |
Rustc's musl-targeting link includes:
I don't exactly know where the https://git.musl-libc.org/cgit/musl/tree/crt/x86_64/crtn.s
(Intriguingly there's also no I wouldn't expect to see a |
It looks like musl's crt1 is a C file, not assembly. crt/{S,r,}crt1.c When crtbegin and crtend were added to LLVM (https://reviews.llvm.org/D28791), there was some discussion about which project is responsible for which aspects of the CRT begin/end files. Apparently the status quo on Linux is that:
That is the case on my gLinux (i.e. Debian) system:
The .eh_frame terminator is usually in crtend, which is part of libgcc (not glibc or musl). LLVM's compiler-rt also provides crtbegin/crtend files. The gcc and clang drivers link a crtend object even for C programs. On Alpine, the gcc driver links a libgcc crtend object. It looks like rustc typically invokes the I see that rustc documents a lot of this at compiler/rustc_target/src/spec/crt_objects.rs
FWIW, it looks like the MinGW rustc target has rsbegin.rs and rsend.rs files. rsend.rs has the .eh_frame terminator. The unwinder needs the .eh_frame terminator, because the .eh_frame_hdr search table is optional, and because .eh_frame_hdr has the start address of .eh_frame, but not its size. (https://reviews.llvm.org/D86256 / https://reviews.llvm.org/D87750). I don't think it's reasonable to open the ELF file indicated by dlpi_name -- in principle, that duplicates the work done by the loader, and I can think of many specific things that wouldn't work. (e.g. the vdso, the executable w/glibc, Android's android_dlopen_ext and ability to map DSOs from zip files, unlinked files, etc). |
Using self-contained mode is not generally recommended for serious work. |
Here's a FIXME for improving the heuristic for musl targets: rust/compiler/rustc_codegen_ssa/src/back/link.rs Lines 1240 to 1243 in 6d3acf5
|
@petrochenkov Thanks for that, very interesting. I think there are two separate use cases for musl-targeting builds:
I'm worrying about the latter case and I think from above the fix for that is:
Some side questions:
|
In the latter case it would make sense to me for rustc to invoke an actual linker ( |
If we need to improve the self-contained mode specifically, then I think we can just ship the begin/end objects and link to them like gcc does obsoleting the comment cited in #47551 (comment). That appears to be the simplest solution. @bossmc |
Which |
I don't know, but looks like they should be compatible. |
For some targets, rustc uses a "CRT fallback", where it links CRT object files it ships instead of letting the host compiler link them. On musl, rustc currently links crt1, crti and crtn (provided by libc), but does not link crtbegin and crtend (provided by libgcc). In particular, crtend is responsible for terminating the .eh_frame section. Lack of terminator may result in segfaults during unwinding, as reported in rust-lang#47551 and encountered by the LLVM 12 update in rust-lang#81451. This patch links crtbegin and crtend for musl as well, following the table at the top of crt_objects.rs.
#82534 adds crtbegin/crtend objects to Rust distribution and links to them in self-contained mode as was suggested in #47551 (comment), so it should fix this issue. |
Link crtbegin/crtend on musl to terminate .eh_frame For some targets, rustc uses a "CRT fallback", where it links CRT object files it ships instead of letting the host compiler link them. On musl, rustc currently links crt1, crti and crtn (provided by libc), but does not link crtbegin and crtend (provided by libgcc). In particular, crtend is responsible for terminating the .eh_frame section. Lack of terminator may result in segfaults during unwinding, as reported in rust-lang#47551 and encountered by the LLVM 12 update in rust-lang#81451. This patch links crtbegin and crtend for musl as well, following the table at the top of crt_objects.rs. r? `@nagisa`
Link crtbegin/crtend on musl to terminate .eh_frame For some targets, rustc uses a "CRT fallback", where it links CRT object files it ships instead of letting the host compiler link them. On musl, rustc currently links crt1, crti and crtn (provided by libc), but does not link crtbegin and crtend (provided by libgcc). In particular, crtend is responsible for terminating the .eh_frame section. Lack of terminator may result in segfaults during unwinding, as reported in rust-lang#47551 and encountered by the LLVM 12 update in rust-lang#81451. This patch links crtbegin and crtend for musl as well, following the table at the top of crt_objects.rs. r? ``@nagisa``
I still have this problem with clang's compiler-rt: https://llvm.discourse.group/t/segfault-in-libunwind-during-cpu-profiling/5806/3 |
Upstream issue: https://bugs.llvm.org/show_bug.cgi?id=36005
The version of
libunwind
used in thex86_64-unknown-linux-musl
(and possibly thei686-...-musl
one too?) standard library has a bug where it will sometimes walk off the end of the segment containing the.eh_frame
section and segfault.I've struggled to reproduce this except in some proprietary code, but the backtrace looks like:
There's a proposed fix in the linked LLVM issue, which can possibly be patched into libunwind before building the musl target if taking an updated libunwind isn't possible.
The text was updated successfully, but these errors were encountered: