Change:
The code in the following repository crashes with an ACCESS_VIOLATION on Windows: To reproduce, four things are needed: Using LLD linker Building with Thin LTO Splitting the main binary and a library. EDIT: Better reproducer can be found . The file: The file: Running will trigger the following output: This issue seems related to ThinLTO. It only occurs on windows. : <details<summaryBacktrace</summary<p</p</details
The reproducer::CHANNEL symbol gets mislinked. Here's where the symbol's address gets loaded into the register: ! If you check what's at that address, you find it's the beginning of the binary that is loaded as read only into the RAM: ! which later segfaults as that is interpreted as the Lazy's internal AtomicUsize, at which point everything goes wrong: ! The +crt-static is not necessary btw. It's a problem involving the fact that there's multiple crates, rust-lld and thin-lto.
ping windows
Hey Windows Group! This bug has been identified as a good "Windows candidate". In case it's useful, here are some [instructions] for tackling these sorts of bugs. Maybe take a look? Thanks! <3 [instructions]: https://rustc-dev- cc
We think this warrants a priority but feel free to adjust. Zulip thread at . Could be interesting checking since when we have this behaviour
With nearly the same set-up ( windows-msvc, rust-lld, thinlto, but without +crt-static), I also experienced in a project. After seeing this issue, I swapped out with the unstable std api . Rather than an access violation, the program panicked with the following The following example minimizes the type somewhat and combines it the first example. With the combination of windows-msvc, rust-lld, and thinlto, the panic occurs in rather than from the stubs. <details</summary</details<details<summarybacktrace</summary</details<details<summarymeta</summary</details
It looks like some variation of this issue was reported in , but eventually went away. Guess some form of the issue returned, or this issue is finding another way to trigger the underlying issue. A similar set-up was required to trigger the access violation edit: I am able to produce with with the minimal example created in the previous issue, which I will copy over here for convenience:
To avoid duplicated work: Is anyone working on a concise bug report for the LLVM project?
That is unfortunately still an issue with LLD from LLVM 13.
thanks for the reminder, adding so this gets prioritized during the T-compiler meeting. label +I-nominated
So, this LLVM issue definitively needs to be reported upstream along with an LLVM-IR reproducible. Seems that no on has yet owned this upstream bug report, so it's open for grab (and if you want to own it, please feel free to do so - thanks). () label -I-nominated
Bumping. It's this bug's one-year anniversary :tada:. I've tried to create a more minimal reproducer, but I don't have a whole lot of experience with LLVM stuff, so please forgive any blunders I might have made :sweatsmile: . The reproducer can be found , and is essentially a reduction of using and to remove as much unnecessary noise from the binary/asm/llvm. The LLVM IR is at The binary is very, very simple here. This is essentially the entire binary: ! At the bottom, we see the static that points to garbage, and the loads it and calls it (which segfaults due to jumping to a garbage address).
This still reproduces with lld 14.0.0 (and therefore the current nightly's ). and does that sound familiar to you ? (and if not, is the LLVM IR above enough for tracking this in a LLVM project issue ?)
It does not reproduce with (LLD 14.0.0) so should it be labelled as instead of just ?
ok, probably the situation has changed compared to . label -O-windows-msvc
Oh sorry, I just put it in the wrong order label +O-windows-msvc -O-windows
Has any progress been made here? We just ran into this issue too on rust 1.64.
I posted a fix in . Huge thanks to for creating the minimal repro which was instrumental in figuring out what was going on!
I did some investigating on why ThinLTO is required to reproduce this. It turns out ThinLTO is not generating (used for static linking) in the library unlike when ThinLTO is unused. This means that must generate it itself and it seems to struggle with that unlike . Another fix for this issue could be to also generate these for ThinLTO, though I don't know where these are generated. They don't appear in the LLVM bitcode at least.

Discussion:
use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::{bug, span_bug}; <ins> use rustc_session::config::Lto; </ins> use rustc_target::abi::{ AddressSpace, Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange, };

// 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. <del> !self.tcx.sess.opts.cg.linker_plugin_lto.enabled(); </del> <ins> !self.tcx.sess.opts.cg.linker_plugin_lto.enabled() && self.tcx.sess.lto() != Lto::Thin; </ins> // If this assertion triggers, there's something wrong with commandline // argument validation.

<ins> 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)() } } </ins>

<ins> // 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(); } </ins>