rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
96.21k stars 12.44k forks source link

External statics compile incorrectly when there's no #[link(... above the extern block #52748

Open MSxDOS opened 6 years ago

MSxDOS commented 6 years ago

External statics return stuff from incorrect memory locations when their extern blocks are not marked with #[link(name = "their_lib_name")] explicitly .

Environment

rustc 1.29.0-nightly (6a1c0637c 2018-07-23)`
binary: rustc
commit-hash: 6a1c0637ce44aeea6c60527f4c0e7fb33f2bcd0d
commit-date: 2018-07-23
host: x86_64-pc-windows-msvc
release: 1.29.0-nightly
LLVM version: 7.0

Example

Test cdylib type library called libtest:

// lib.rs
#[no_mangle] pub static AS_STATIC: u32 = 1337;
#[no_mangle] pub extern "C" fn as_function() -> u32 { 1337 }

Test binary (marked):

// main.rs
#[link(name = "libtest")]
extern "C" {
    pub static AS_STATIC: u32;
    pub fn as_function() -> u32;
}
fn main() {
    unsafe {
        println!(
            "Static: '{}' at {:p}\nFunction: '{}' at {:p}",
            AS_STATIC,
            &AS_STATIC as *const u32 ,
            as_function(),
            as_function as *const (),
        );
    }
}

Result - OK:

Static: '1337' at 0x7fef9bd2140
Function: '1337' at 0x13f5462b0

Now after removing #[link(name = "libtest")] from above the extern block in our test binary and instead linking via build script:

// build.rs
fn main() {
    println!("cargo:rustc-link-lib=dylib=libtest");
}

Result:

Static: '262284799' at 0x13fe062b0
Function: '1337' at 0x13fe062b6
retep998 commented 6 years ago

The #[link] is necessary for Rust to know whether it has to apply dllimport to the symbols in the extern block. While this doesn't matter as much for functions (because the linker can statically link a stub function that jumps to the dynamically linked version), for statics this is a dealbreaker because without dllimport the code is generated as if the static has a hardcoded address. and there's just no way for the linker to magic a solution. The bug here is that for some reason it is still linking successfully instead of failing to link.