unresolved symbol imports in -pie musl binaries

69be26d
Opened by m4b at 2020-10-25 21:40:57

I've noticed that there are two unresolved symbols when a PIE is requested via the linker flags with nightly rustc's new musl target, e.g.:

rust/bin/rustc --target=x86_64-unknown-linux-musl -C link-args="-Wl,-pie" main.rs

yields a binary with two unresolved imports:

ELF X86_64 DYN @ 0x4f71
Imports (2)
          26e3a0 __dso_handle (0) ~> Unknown
          26e3a8 __cxa_thread_atexit_impl (0) ~> Unresolved

which you can see with objdump -R main:

0000000000270fd0 R_X86_64_GLOB_DAT  __cxa_thread_atexit_impl
0000000000271008 R_X86_64_64       __dso_handle

but 0 libraries (i.e., DT_NEEDED), so having unresolved imports without dynamic library dependencies is essentially an incoherent binary semantics. (Not having libraries is fine, in fact that's the point of the musl target, and the -pie flag should just make it able to be loaded anywhere in memory, but having unresolved imports without dependencies is where it becomes problematic)

Similarly, grepping through the assembly, it looks like __cxa_thread_atexit_impl isn't called by anyone, but __dso_handle does show up in an external rust linkage symbol (I have no idea what the function of the __rust_extern_with_linkage____X is):

015:    48 8d 15 ec 7f 26 00    lea    0x267fec(%rip),%rdx        # 271008 <_rust_extern_with_linkage___dso_handle>

As such, doesn't seem like it's a major problem, but it is very unusual, and again, the lack of dynamic library dependencies + unresolved symbol imports is a red flag, and should probably be investigated. My guess is that there is some weird interaction with the link-args flag and the generated link commands somehow.

  1. These probably both originated from thread local support, but because MUSL is basically a known entity we should perhaps remove those on MUSL?

    Or maybe there's a way to have that exist without emitting these imports?

    Alex Crichton at 2016-03-28 17:05:22

  2. Wow, nice find, that was fast! The weak extern linkage explains why the linker let's them into a final artifact with no libraries too.

    I'll have to examine what is going on in your link, not too familiar with this lib code. But it's a good lead, and I'll think about your second question.

    m4b at 2016-03-28 17:25:03

  3. Ah yeah the purpose of those is to basically lazily detect at runtime whether we have those symbols available to us to register thread-local destructors. Note that elsewhere, however, we use dlopen to "lazily link" against symbols to avoid adding restrictions on the glibc version we're using, so we may want to just apply the same strategy in this location as well.

    Alex Crichton at 2016-03-28 17:27:29

  4. I'm no longer seeing any of these relocations with the latest rustc. Can this issue be closed?

    Aaron Hill at 2020-10-25 21:40:57