Skip to content

Link to libatomic for 32-bit builds #53

Closed
@fhunleth

Description

libatomic functions are being put into executables for 32-bit platforms. 64-bit targets are unaffected (I checked aarch64 and riscv64). This seems to affect other projects like rust-openssl (see https://github.com/sfackler/rust-openssl/pull/1547/files). The fix hopefully is the same. Given my unfamiliarity with Rustler and RustlerPrecompiled, I'm not sure where the best place is to add the cargo:rustc-link-lib=dylib=atomic option that the rust-openssl PR had.

Specifically, this causes libraries using RustlerPrecompiled to fail to load. The error message for libexplorer-v0.5.4-nif-2.16-arm-unknown-linux-gnueabihf.so is that __atomic_store_8 can't be found.

Running readelf -d on libexplorer-v0.5.4-nif-2.16-arm-unknown-linux-gnueabihf.so shows the following:

Dynamic section at offset 0x1962b40 contains 33 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [librt.so.1]
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x00000001 (NEEDED)                     Shared library: [ld-linux-armhf.so.3]

You can see that libatomic.so.1 isn't in the list of needed shared libraries. However, if you run readelf -s on libexplorer-v0.5.4-nif-2.16-arm-unknown-linux-gnueabihf.so and grep for atomic, you'll see:

   66: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND __atomic_store_8
    83: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND __atomic_load_8
   105: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND __atomic_compare[...]
   151: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND __atomic_fetch_add_8

So libatomic is being used. Adding libatomic.so.1 to the needed shared libraries list fixes that. I manually added it with patchelf:

$ patchelf --add-needed libatomic.so.1 ./_build/rpi3_dev/lib/explorer/priv/native/libexplorer-v0.5.4-nif-2.16-arm-unknown-linux-gnueabihf.so
$ readelf -d ./_build/rpi3_dev/lib/explorer/priv/native/libexplorer-v0.5.4-nif-2.16-arm-unknown-linux-gnueabihf.so          bumblebee*

Dynamic section at offset 0x2247000 contains 34 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libatomic.so.1]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [librt.so.1]
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x00000001 (NEEDED)                     Shared library: [ld-linux-armhf.so.3]

Once I did that, explorer loaded and worked fine on the Raspberry Pi 3 which was being run in 32-bit mode w/ Nerves.

All that I believe that needs to be done is to add cargo:rustc-link-lib=dylib=atomic to the right place. Checking that it worked can be done with readelf -d, so there's no need to run on a Raspberry Pi 3 or anything. I don't know of a downside of unconditionally adding it for 32-bit Rust builds.

I hope this makes sense and there's a good place to put it.

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions