Skip to content

Commit 72b4d8c

Browse files
committed
Auto merge of #3723 - RalfJung:win-tls-callback, r=RalfJung
iter_exported_symbols: also walk used statics in local crate Since rust-lang/rust#126938 got reverted, we need a different approach. Fixes #3722
2 parents 2af694a + 6720f18 commit 72b4d8c

File tree

3 files changed

+43
-8
lines changed

3 files changed

+43
-8
lines changed

src/helpers.rs

+26-8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_hir::{
1414
def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE},
1515
};
1616
use rustc_index::IndexVec;
17+
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1718
use rustc_middle::middle::dependency_format::Linkage;
1819
use rustc_middle::middle::exported_symbols::ExportedSymbol;
1920
use rustc_middle::mir;
@@ -163,22 +164,39 @@ pub fn iter_exported_symbols<'tcx>(
163164
tcx: TyCtxt<'tcx>,
164165
mut f: impl FnMut(CrateNum, DefId) -> InterpResult<'tcx>,
165166
) -> InterpResult<'tcx> {
167+
// First, the symbols in the local crate. We can't use `exported_symbols` here as that
168+
// skips `#[used]` statics (since `reachable_set` skips them in binary crates).
169+
// So we walk all HIR items ourselves instead.
170+
let crate_items = tcx.hir_crate_items(());
171+
for def_id in crate_items.definitions() {
172+
let exported = tcx.def_kind(def_id).has_codegen_attrs() && {
173+
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
174+
codegen_attrs.contains_extern_indicator()
175+
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
176+
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED)
177+
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
178+
};
179+
if exported {
180+
f(LOCAL_CRATE, def_id.into())?;
181+
}
182+
}
183+
184+
// Next, all our dependencies.
166185
// `dependency_formats` includes all the transitive informations needed to link a crate,
167186
// which is what we need here since we need to dig out `exported_symbols` from all transitive
168187
// dependencies.
169188
let dependency_formats = tcx.dependency_formats(());
189+
// Find the dependencies of the executable we are running.
170190
let dependency_format = dependency_formats
171191
.iter()
172192
.find(|(crate_type, _)| *crate_type == CrateType::Executable)
173193
.expect("interpreting a non-executable crate");
174-
for cnum in iter::once(LOCAL_CRATE).chain(dependency_format.1.iter().enumerate().filter_map(
175-
|(num, &linkage)| {
176-
// We add 1 to the number because that's what rustc also does everywhere it
177-
// calls `CrateNum::new`...
178-
#[allow(clippy::arithmetic_side_effects)]
179-
(linkage != Linkage::NotLinked).then_some(CrateNum::new(num + 1))
180-
},
181-
)) {
194+
for cnum in dependency_format.1.iter().enumerate().filter_map(|(num, &linkage)| {
195+
// We add 1 to the number because that's what rustc also does everywhere it
196+
// calls `CrateNum::new`...
197+
#[allow(clippy::arithmetic_side_effects)]
198+
(linkage != Linkage::NotLinked).then_some(CrateNum::new(num + 1))
199+
}) {
182200
// We can ignore `_export_info` here: we are a Rust crate, and everything is exported
183201
// from a Rust crate.
184202
for &(symbol, _export_info) in tcx.exported_symbols(cnum) {

tests/pass/tls/win_tls_callback.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//! Ensure that we call Windows TLS callbacks in the local crate.
2+
//@only-target-windows
3+
// Calling eprintln in the callback seems to (re-)initialize some thread-local storage
4+
// and then leak the memory allocated for that. Let's just ignore these leaks,
5+
// that's not what this test is about.
6+
//@compile-flags: -Zmiri-ignore-leaks
7+
8+
#[link_section = ".CRT$XLB"]
9+
#[used] // Miri only considers explicitly `#[used]` statics for `lookup_link_section`
10+
pub static CALLBACK: unsafe extern "system" fn(*const (), u32, *const ()) = tls_callback;
11+
12+
unsafe extern "system" fn tls_callback(_h: *const (), _dw_reason: u32, _pv: *const ()) {
13+
eprintln!("in tls_callback");
14+
}
15+
16+
fn main() {}
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
in tls_callback

0 commit comments

Comments
 (0)