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.