Skip to content

Commit 63a60b6

Browse files
authored
Rollup merge of rust-lang#96523 - nbdd0121:windows, r=petrochenkov
Add `@feat.00` symbol to symbols.o for COFF Fix rust-lang#96498 This is based on top of rust-lang#96444. r? `@petrochenkov`
2 parents 9b2452e + 0fce0db commit 63a60b6

File tree

7 files changed

+125
-2
lines changed

7 files changed

+125
-2
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+27
Original file line numberDiff line numberDiff line change
@@ -1696,6 +1696,33 @@ fn add_linked_symbol_object(
16961696
// so add an empty section.
16971697
if file.format() == object::BinaryFormat::Coff {
16981698
file.add_section(Vec::new(), ".text".into(), object::SectionKind::Text);
1699+
1700+
// We handle the name decoration of COFF targets in `symbol_export.rs`, so disable the
1701+
// default mangler in `object` crate.
1702+
file.set_mangling(object::write::Mangling::None);
1703+
1704+
// Add feature flags to the object file. On MSVC this is optional but LLD will complain if
1705+
// not present.
1706+
let mut feature = 0;
1707+
1708+
if file.architecture() == object::Architecture::I386 {
1709+
// Indicate that all SEH handlers are registered in .sxdata section.
1710+
// We don't have generate any code, so we don't need .sxdata section but LLD still
1711+
// expects us to set this bit (see #96498).
1712+
// Reference: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
1713+
feature |= 1;
1714+
}
1715+
1716+
file.add_symbol(object::write::Symbol {
1717+
name: "@feat.00".into(),
1718+
value: feature,
1719+
size: 0,
1720+
kind: object::SymbolKind::Data,
1721+
scope: object::SymbolScope::Compilation,
1722+
weak: false,
1723+
section: object::write::SymbolSection::Absolute,
1724+
flags: object::SymbolFlags::None,
1725+
});
16991726
}
17001727

17011728
for (sym, kind) in symbols.iter() {

compiler/rustc_codegen_ssa/src/back/linker.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1576,7 +1576,7 @@ pub(crate) fn linked_symbols(
15761576
for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
15771577
if info.level.is_below_threshold(export_threshold) || info.used {
15781578
symbols.push((
1579-
symbol_export::symbol_name_for_instance_in_crate(tcx, symbol, cnum),
1579+
symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, cnum),
15801580
info.kind,
15811581
));
15821582
}

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

+71-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_middle::middle::exported_symbols::{
1212
use rustc_middle::ty::query::{ExternProviders, Providers};
1313
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
1414
use rustc_middle::ty::Instance;
15-
use rustc_middle::ty::{SymbolName, TyCtxt};
15+
use rustc_middle::ty::{self, SymbolName, TyCtxt};
1616
use rustc_session::config::CrateType;
1717
use rustc_target::spec::SanitizerSet;
1818

@@ -493,6 +493,76 @@ pub fn symbol_name_for_instance_in_crate<'tcx>(
493493
}
494494
}
495495

496+
/// This is the symbol name of the given instance as seen by the linker.
497+
///
498+
/// On 32-bit Windows symbols are decorated according to their calling conventions.
499+
pub fn linking_symbol_name_for_instance_in_crate<'tcx>(
500+
tcx: TyCtxt<'tcx>,
501+
symbol: ExportedSymbol<'tcx>,
502+
instantiating_crate: CrateNum,
503+
) -> String {
504+
use rustc_target::abi::call::Conv;
505+
506+
let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate);
507+
508+
let target = &tcx.sess.target;
509+
if !target.is_like_windows {
510+
// Mach-O has a global "_" suffix and `object` crate will handle it.
511+
// ELF does not have any symbol decorations.
512+
return undecorated;
513+
}
514+
515+
let x86 = match &target.arch[..] {
516+
"x86" => true,
517+
"x86_64" => false,
518+
// Only x86/64 use symbol decorations.
519+
_ => return undecorated,
520+
};
521+
522+
let instance = match symbol {
523+
ExportedSymbol::NonGeneric(def_id) | ExportedSymbol::Generic(def_id, _)
524+
if tcx.is_static(def_id) =>
525+
{
526+
None
527+
}
528+
ExportedSymbol::NonGeneric(def_id) => Some(Instance::mono(tcx, def_id)),
529+
ExportedSymbol::Generic(def_id, substs) => Some(Instance::new(def_id, substs)),
530+
// DropGlue always use the Rust calling convention and thus follow the target's default
531+
// symbol decoration scheme.
532+
ExportedSymbol::DropGlue(..) => None,
533+
// NoDefId always follow the target's default symbol decoration scheme.
534+
ExportedSymbol::NoDefId(..) => None,
535+
};
536+
537+
let (conv, args) = instance
538+
.map(|i| {
539+
tcx.fn_abi_of_instance(ty::ParamEnv::reveal_all().and((i, ty::List::empty())))
540+
.unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed"))
541+
})
542+
.map(|fnabi| (fnabi.conv, &fnabi.args[..]))
543+
.unwrap_or((Conv::Rust, &[]));
544+
545+
// Decorate symbols with prefices, suffices and total number of bytes of arguments.
546+
// Reference: https://docs.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170
547+
let (prefix, suffix) = match conv {
548+
Conv::X86Fastcall => ("@", "@"),
549+
Conv::X86Stdcall => ("_", "@"),
550+
Conv::X86VectorCall => ("", "@@"),
551+
_ => {
552+
if x86 {
553+
undecorated.insert(0, '_');
554+
}
555+
return undecorated;
556+
}
557+
};
558+
559+
let args_in_bytes: u64 = args
560+
.iter()
561+
.map(|abi| abi.layout.size.bytes().next_multiple_of(target.pointer_width as u64 / 8))
562+
.sum();
563+
format!("{prefix}{undecorated}{suffix}{args_in_bytes}")
564+
}
565+
496566
fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> FxHashMap<DefId, String> {
497567
// Build up a map from DefId to a `NativeLib` structure, where
498568
// `NativeLib` internally contains information about

compiler/rustc_codegen_ssa/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#![feature(nll)]
88
#![feature(associated_type_bounds)]
99
#![feature(strict_provenance)]
10+
#![feature(int_roundings)]
1011
#![recursion_limit = "256"]
1112
#![allow(rustc::potential_query_instability)]
1213

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# only-windows
2+
# needs-rust-lld
3+
4+
-include ../../run-make-fulldeps/tools.mk
5+
6+
# Ensure that LLD can link
7+
all:
8+
$(RUSTC) -C linker=rust-lld foo.rs

src/test/run-make/issue-96498/foo.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#![crate_type = "cdylib"]
2+
3+
#[no_mangle]
4+
extern "C" fn foo() {}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// build-pass
2+
// only-x86-windows
3+
#![crate_type = "cdylib"]
4+
#![feature(abi_vectorcall)]
5+
6+
#[no_mangle]
7+
extern "stdcall" fn foo(_: bool) {}
8+
9+
#[no_mangle]
10+
extern "fastcall" fn bar(_: u8) {}
11+
12+
#[no_mangle]
13+
extern "vectorcall" fn baz(_: u16) {}

0 commit comments

Comments
 (0)