Skip to content

Commit

Permalink
Rollup merge of rust-lang#103353 - wesleywiser:fix_lld_thinlto_msvc, …
Browse files Browse the repository at this point in the history
…r=michaelwoerister

Fix Access Violation when using lld & ThinLTO on windows-msvc

Users report an AV at runtime of the compiled binary when using lld and ThinLTO on windows-msvc. The AV occurs when accessing a static value which is defined in one crate but used in another. Based on the disassembly of the cross-crate use, it appears that the use is not correctly linked with the definition and is instead assigned a garbage pointer value.

If we look at the symbol tables for each crates' obj file, we can see what is happening:

*lib.obj*:

```
COFF SYMBOL TABLE
...
00E 00000000 SECT2  notype       External     | _ZN10reproducer7memrchr2FN17h612b61ca0e168901E
...
```

*bin.obj*:

```
COFF SYMBOL TABLE
...
010 00000000 UNDEF  notype       External     | __imp__ZN10reproducer7memrchr2FN17h612b61ca0e168901E
...
```

The use of the symbol has the "import" style symbol name but the declaration doesn't generate any symbol with the same name. As a result, linking the files generates a warning from lld:

> rust-lld: warning: bin.obj: locally defined symbol imported: reproducer::memrchr::FN::h612b61ca0e168901 (defined in lib.obj) [LNK4217]

and the symbol reference remains undefined at runtime leading to the AV.

To fix this, we just need to detect that we are performing ThinLTO (and thus, static linking) and omit the `dllimport` attribute on the extern item in LLVM IR.

Fixes rust-lang#81408
  • Loading branch information
Manishearth authored Nov 8, 2022
2 parents 254942c + 296489c commit 7b7a8c0
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 1 deletion.
4 changes: 3 additions & 1 deletion compiler/rustc_codegen_llvm/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use rustc_middle::mir::mono::MonoItem;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Instance, Ty};
use rustc_middle::{bug, span_bug};
use rustc_session::config::Lto;
use rustc_target::abi::{
AddressSpace, Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange,
};
Expand Down Expand Up @@ -303,7 +304,8 @@ impl<'ll> CodegenCx<'ll, '_> {
// ThinLTO can't handle this workaround in all cases, so we don't
// emit the attrs. Instead we make them unnecessary by disallowing
// dynamic linking when linker plugin based LTO is enabled.
!self.tcx.sess.opts.cg.linker_plugin_lto.enabled();
!self.tcx.sess.opts.cg.linker_plugin_lto.enabled() &&
self.tcx.sess.lto() != Lto::Thin;

// If this assertion triggers, there's something wrong with commandline
// argument validation.
Expand Down
13 changes: 13 additions & 0 deletions src/test/codegen/auxiliary/static_dllimport_aux.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use std::sync::atomic::{AtomicPtr, Ordering};

#[inline(always)]
pub fn memrchr() {
fn detect() {}

static CROSS_CRATE_STATIC_ITEM: AtomicPtr<()> = AtomicPtr::new(detect as *mut ());

unsafe {
let fun = CROSS_CRATE_STATIC_ITEM.load(Ordering::SeqCst);
std::mem::transmute::<*mut (), fn()>(fun)()
}
}
15 changes: 15 additions & 0 deletions src/test/codegen/issue-81408-dllimport-thinlto-windows.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// compile-flags: -O -C lto=thin -C prefer-dynamic=no
// only-windows
// aux-build:static_dllimport_aux.rs

// Test that on Windows, when performing ThinLTO, we do not mark cross-crate static items with
// dllimport because lld does not fix the symbol names for us.

extern crate static_dllimport_aux;

// CHECK-LABEL: @{{.+}}CROSS_CRATE_STATIC_ITEM{{.+}} =
// CHECK-SAME: external local_unnamed_addr global %"{{.+}}AtomicPtr

pub fn main() {
static_dllimport_aux::memrchr();
}

0 comments on commit 7b7a8c0

Please sign in to comment.