MINGW-packages: rust: fails on clang32

    = note: lld-link: error: undefined symbol: @rust_psm_on_stack@16
            >>> referenced by libpsm-a103c78323d6f2a6.rlib(x86_windows_gnu.o)

Oddly, https://github.com/rust-lang/stacker/blob/master/psm/src/arch/x86_windows_gnu.s#L63-L69

.def @rust_psm_on_stack@16
.scl 2
.type 32
.endef
.globl @rust_psm_on_stack@16
.p2align 4
@rust_psm_on_stack@20:

What’s up with that @20 ? Maybe that’s the cause?

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 46 (35 by maintainers)

Commits related to this issue

Most upvoted comments

Interesting it only seems to be cropping up on i686… I thought the setup heuristic applied to x86_64 too…

yeah, see https://learn.microsoft.com/en-us/previous-versions/aa905330(v=msdn.10)#installer-detection

Normally, a relocation against a symbol that has been GC’d away like this would end up as a linker error: https://github.com/llvm/llvm-project/blob/llvmorg-15.0.0/lld/COFF/Chunks.cpp#L352

However due to how the DWARF sections work, it’s expected to have such dangling references left out there, if things are GC’d, so it ignores that error for such sections: https://github.com/llvm/llvm-project/blob/llvmorg-15.0.0/lld/COFF/Chunks.cpp#L328-L333 (Also the error is entirely skipped for anything in mingw mode)

But now I found how this is fixed for the existing C++ cases: https://github.com/llvm/llvm-project/commit/7e0768329ca347e37c7bdb0da16b51cb3e7b7d8b

I made a patch for LLD that should fix it similarly for this symbol: https://reviews.llvm.org/D136879

I have started looking at this now, and I have almost nailed it down, but not quite.

I noticed that when running this test in wine, it didn’t hit the crash. (rustc.exe returns 1 as return code, though, while rustdoc.exe returns 101 though - is this expected?) And when comparing libunwind debug outputs to see where it differed, I noticed that the addresses differed (due to ASLR). To reduce differences, I removed the dynamicbase bit from rustdoc.exe, but then the crash vanished.

When comparing logs from the case in wine (and/or without dynamicbase) and the crashing case, there’s a personality pointer in the unwind data, which is supposed to be a null pointer - but when the executable is loaded at a different address, the pointer is non-null. I dug up the exact offset in the binary where this supposedly-null field is, and the binary has got a base relocation there. I.e., if your image normally has got a load address of 0x00400000 and you’ve got an address of 0x00401234, and at runtime, the image gets loaded at 0x00ff0000 - then that address should be rewritten to 0x00ff1234 too. Well, such a rewrite (base relocation) gets applied on the null pointer, so when the image is loaded at a non-default location, it’s no longer null.

Now why doesn’t this happen in the rustc.exe case where everything is in a DLL? I don’t know. Why doesn’t this happen for C++ unwind info? Apparently for the cases where we do have a null personality, we simply don’t encode any personality pointer in the unwind data. But here in the Rust generated dwarf unwind info, we have stored a literal pointer, which happens to be null, but ends up getting the base relocation applied.

To figure out why, I’d kinda want to look at how the code generation happens. Are you able to provide LLVM IR (bitcode file or textual) for the object file that contains the symbol __RNvCsak4nujc38YL_7rustdoc9main_args (and the object file itself, if you happen to have it lying around), so that I can run that code generation through (vanilla) LLVM to see what creates it? Or if it’s all generated by LTO or something similar, is it possible to get the input files to this - so I can reproduce generating it? I believe that this is a cornercase in dwarf unwind generation for COFF targets, which isn’t ever really triggered by the Clang generated stuff. Maybe…

Interesting it only seems to be cropping up on i686… I thought the setup heuristic applied to x86_64 too…

Terrific! That seems to have done the trick but there is new issue (we haven’t reached it previously): rust-installer.exe exits with Windows error 740: The requested operation requires elevation…

Trying to run it manually:

$ RUST_LOG=debug PATH=src/CLANG32/build/i686-pc-windows-gnu/stage2/bin:$PATH src/CLANG32/build/i686-pc-windows-gnu/stage0-tools-bin/rust-installer.exe
bash: src/CLANG32/build/i686-pc-windows-gnu/stage0-tools-bin/rust-installer.exe: Permission denied

So there is still more work to do on my end.

Small update: Noticed the exceptions do work for rustc.exe but are broken for other tools like rustdoc.exe (at least with my local changes to Rust source code). I’ve started CLion trial because I cannot use debuggers outside IDE and this is how it looks: image This is right before calling *p (highlighted line) which is going to segfault. Going to get some sleep right now and I’ll do more testing later.