-
Notifications
You must be signed in to change notification settings - Fork 60
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
arbitrary_self_types_pointers_and_wrappers fails on aarch64 due to stack corruption with libgcc atomics #544
Comments
Sorry, I forgot about this. Did you build the sysroot with |
I followed the exact steps on the README:
|
When I try with |
Ok, I was asking because there are known issues and compiling the sysroot in release mode is a workaround for at least some of them as you can see here. This specific one looks very similar to the one I had in the above thread (was an atomic intrinsic, was jumping at address 0). This naked attribute isn't supported by GCC on Aarch64, but there's a PR in Rust that will change that so that it doesn't use the codegen naked attribute, so if this is indeed the issue we have here, that might solve the issue. Perhaps it would be worth a try compiling your reproducer above in release mode ( I won't have time to look at this soon though, but I can help you investigate after I recover from Covid-19. |
Take as much time as you need, I hope you feel better soon. As far as the reproducer, it's essentially a stripped down version of arbitrary_self_types_pointers_and_wrappers, which is the first test that depends on loading std |
I also don't think these intrinsics are declared with #[naked] but I could be wrong. I haven't looked at this in a while. https://doc.rust-lang.org/1.80.1/src/core/intrinsics.rs.html |
I just tried on Asahi Linux on a Mac M1 and both the example you posted above and I do have the test Which OS do you use? |
Accoring to the GDB version string OP uses Gentoo Linux. macOS has a slightly different ABI from the official calling convention specified by ARM (AAPCS) that is used by Linux. |
@bjorn3 , Antoyo's setup seems very similar to mine. I run arm64 linux, but my host os is MacOS, and I'm emulating gentoo linux on arm64 using QEMU. My CPU is an Apple M3 pro. |
@antoyo , I misunderstood your original --release-sysroot comment. ./y.sh build --sysroot --release --release-sysroot This combination results in arbitrary_self_types_pointers_and_wrappers passing. I'd guess this is the same issue as #242 (comment) comment points out. |
On aarch64, during the initialization of std, a compare_exchange_weak is called as part of std::thread::ThreadId::new, specifically line sysroot_src/library/std/src/thread/mod.rs:1190.
If I'm not mistaken, this calls out to a libgcc-implemented intrinsic, __aarch64_cas8_relax.
These intrinsics are documented here: https://github.com/llvm/llvm-project/blob/main/llvm/docs/Atomics.rst#libcalls-atomic
What appears to be happening, is that this intrinsic modifies $sp (presumably to return some argument to the caller?), however, it appears the generated rust does not expect $sp to be changed, resulting in the stored return address being set to a bogus value. When the frame is popped, we branch to some random value on the stack. This appears in GDB by observing that we branch to the "function" std::thread::ThreadId::new::COUNTER, who's "opcodes" are 0, which decodes to the udf, instruction on arm, causing a segfault (or bus error if we branch to 0x1, which appears in some other examples).
I've attached a reproducer that only depends on
core
to provide the intrinsic. The reproducer shows the following GDB log:ENV INFO:
Reproducer:
The text was updated successfully, but these errors were encountered: