Closed
Description
Originally reported as #60593, and appears to be caused by #54592, this is my reduction:
common.rs
pub static STATIC: u8 = 0;
pub fn get() -> *const u8 { &STATIC }
plugin.rs
extern crate common;
#[no_mangle]
pub fn run() {
println!("plugin: {:p}", common::get as *const ());
assert_eq!(common::get(), &common::STATIC as *const _);
}
driver.rs
extern crate common;
fn main() {
println!("driver: {:p}", common::get as *const ());
// You can comment this line to make it work.
assert_eq!(common::get(), &common::STATIC as *const _);
unsafe {
extern "C" {
fn dlopen(filename: *const u8, flag: i32) -> *mut u8;
fn dlsym(handle: *mut u8, symbol: *const u8) -> *const u8;
}
std::mem::transmute::<*const u8, fn()>(dlsym(
dlopen(b"./libplugin.so\0".as_ptr(), 1),
b"run\0".as_ptr(),
))()
}
}
How to run it:
RELEASE=nightly-2018-10-11
rustup toolchain add $RELEASE
echo 'System toolchain versions:'
ldd --version | head -n1 | sed 's/^ldd //'
ld.bfd --version | head -n1
ld.gold --version | head -n1
echo
rustc +$RELEASE common.rs --crate-type=lib
# You can change this from dylib to cdylib to make it work.
rustc +$RELEASE plugin.rs --crate-type=dylib -L.
# You can uncomment -Z plt=yes to make it work.
rustc +$RELEASE driver.rs -L. # -Z plt=yes
./driver
I was able to try this out with NixOS 18.03 and 18.09 releases, via:
NIX_PATH=nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-18.03.tar.gz \
nix-shell -p stdenv --run ./test.sh
NIX_PATH=nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-18.09.tar.gz \
nix-shell -p stdenv --run ./test.sh
Example of failure (using a NixOS 18.03 toolchain):
info: syncing channel updates for 'nightly-2018-10-12-x86_64-unknown-linux-gnu'
nightly-2018-10-12-x86_64-unknown-linux-gnu unchanged - rustc 1.31.0-nightly (77af31408 2018-10-11)
System toolchain versions:
(GNU libc) 2.26
GNU ld (GNU Binutils) 2.28.1
GNU gold (GNU Binutils 2.28.1) 1.14
driver: 0x55d244a55820
plugin: 0x55d244a55820
thread 'main' panicked at 'assertion failed: `(left == right)`
left: `0x55d244a9e7ac`,
right: `0x7f87a69b3f19`', plugin.rs:5:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.
Example of success (by switching to NixOS 18.09):
info: syncing channel updates for 'nightly-2018-10-12-x86_64-unknown-linux-gnu'
nightly-2018-10-12-x86_64-unknown-linux-gnu unchanged - rustc 1.31.0-nightly (77af31408 2018-10-11)
System toolchain versions:
(GNU libc) 2.27
GNU ld (GNU Binutils) 2.30
GNU gold (GNU Binutils 2.30) 1.15
driver: 0x5649e7dbf4f0
plugin: 0x7fca6df40930
Other ways to get it to succeed:
- use a Rust version before Support for disabling PLT for better function call performance #54592 (e.g.
RELEASE=nightly-2018-10-11
) - pass
-Z plt=yes
when compilingdriver
- restores pre-Support for disabling PLT for better function call performance #54592 behavior
- change the crate type of
plugin
tocdylib
(instead ofdylib
)- presumably
common::get
is private in that case? - not a general fix AFAIK, but I'm not sure how to repro with
cdylib
- presumably
- don't call
common::get
indriver
common::get
won't get looked up early, which meansdriver
's copy won't overrideplugin
's (within the context of affected toolchains)
- set
RTLD_DEEPBIND
when callingdlopen
common::get
fromdriver
is ignored when looking up the use fromplugin
cc @alexcrichton @rust-lang/compiler