Skip to content

Commit 493c38b

Browse files
committedMar 17, 2025·
Auto merge of rust-lang#127173 - bjorn3:mangle_rustc_std_internal_symbol, r=wesleywiser,jieyouxu
Mangle rustc_std_internal_symbols functions This reduces the risk of issues when using a staticlib or rust dylib compiled with a different rustc version in a rust program. Currently this will either (in the case of staticlib) cause a linker error due to duplicate symbol definitions, or (in the case of rust dylibs) cause rustc_std_internal_symbols functions to be silently overridden. As rust gets more commonly used inside the implementation of libraries consumed with a C interface (like Spidermonkey, Ruby YJIT (curently has to do partial linking of all rust code to hide all symbols not part of the C api), the Rusticl OpenCL implementation in mesa) this is becoming much more of an issue. With this PR the only symbols remaining with an unmangled name are rust_eh_personality (LLVM doesn't allow renaming it) and `__rust_no_alloc_shim_is_unstable`. Helps mitigate rust-lang#104707 try-job: aarch64-gnu-debug try-job: aarch64-apple try-job: x86_64-apple-1 try-job: x86_64-mingw-1 try-job: i686-mingw-1 try-job: x86_64-msvc-1 try-job: i686-msvc-1 try-job: test-various try-job: armhf-gnu
2 parents 43a2e9d + bebc502 commit 493c38b

39 files changed

+342
-76
lines changed
 

‎compiler/rustc_codegen_cranelift/src/allocator.rs

+23-7
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ use rustc_ast::expand::allocator::{
77
};
88
use rustc_codegen_ssa::base::allocator_kind_for_codegen;
99
use rustc_session::config::OomStrategy;
10+
use rustc_symbol_mangling::mangle_internal_symbol;
1011

1112
use crate::prelude::*;
1213

1314
/// Returns whether an allocator shim was created
1415
pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool {
1516
let Some(kind) = allocator_kind_for_codegen(tcx) else { return false };
1617
codegen_inner(
18+
tcx,
1719
module,
1820
kind,
1921
tcx.alloc_error_handler_kind(()).unwrap(),
@@ -23,6 +25,7 @@ pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool {
2325
}
2426

2527
fn codegen_inner(
28+
tcx: TyCtxt<'_>,
2629
module: &mut dyn Module,
2730
kind: AllocatorKind,
2831
alloc_error_handler_kind: AllocatorKind,
@@ -62,8 +65,8 @@ fn codegen_inner(
6265
crate::common::create_wrapper_function(
6366
module,
6467
sig,
65-
&global_fn_name(method.name),
66-
&default_fn_name(method.name),
68+
&mangle_internal_symbol(tcx, &global_fn_name(method.name)),
69+
&mangle_internal_symbol(tcx, &default_fn_name(method.name)),
6770
);
6871
}
6972
}
@@ -76,19 +79,32 @@ fn codegen_inner(
7679
crate::common::create_wrapper_function(
7780
module,
7881
sig,
79-
"__rust_alloc_error_handler",
80-
&alloc_error_handler_name(alloc_error_handler_kind),
82+
&mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
83+
&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)),
8184
);
8285

83-
let data_id = module.declare_data(OomStrategy::SYMBOL, Linkage::Export, false, false).unwrap();
86+
let data_id = module
87+
.declare_data(
88+
&mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
89+
Linkage::Export,
90+
false,
91+
false,
92+
)
93+
.unwrap();
8494
let mut data = DataDescription::new();
8595
data.set_align(1);
8696
let val = oom_strategy.should_panic();
8797
data.define(Box::new([val]));
8898
module.define_data(data_id, &data).unwrap();
8999

90-
let data_id =
91-
module.declare_data(NO_ALLOC_SHIM_IS_UNSTABLE, Linkage::Export, false, false).unwrap();
100+
let data_id = module
101+
.declare_data(
102+
&mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE),
103+
Linkage::Export,
104+
false,
105+
false,
106+
)
107+
.unwrap();
92108
let mut data = DataDescription::new();
93109
data.set_align(1);
94110
data.define(Box::new([0]));

‎compiler/rustc_codegen_cranelift/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ extern crate rustc_index;
2626
extern crate rustc_metadata;
2727
extern crate rustc_session;
2828
extern crate rustc_span;
29+
extern crate rustc_symbol_mangling;
2930
extern crate rustc_target;
3031
#[macro_use]
3132
extern crate tracing;

‎compiler/rustc_codegen_gcc/src/allocator.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_ast::expand::allocator::{
88
use rustc_middle::bug;
99
use rustc_middle::ty::TyCtxt;
1010
use rustc_session::config::OomStrategy;
11+
use rustc_symbol_mangling::mangle_internal_symbol;
1112

1213
use crate::GccContext;
1314
#[cfg(feature = "master")]
@@ -53,8 +54,8 @@ pub(crate) unsafe fn codegen(
5354
panic!("invalid allocator output")
5455
}
5556
};
56-
let from_name = global_fn_name(method.name);
57-
let to_name = default_fn_name(method.name);
57+
let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name));
58+
let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name));
5859

5960
create_wrapper_function(tcx, context, &from_name, &to_name, &types, output);
6061
}
@@ -64,13 +65,13 @@ pub(crate) unsafe fn codegen(
6465
create_wrapper_function(
6566
tcx,
6667
context,
67-
"__rust_alloc_error_handler",
68-
alloc_error_handler_name(alloc_error_handler_kind),
68+
&mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
69+
&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)),
6970
&[usize, usize],
7071
None,
7172
);
7273

73-
let name = OomStrategy::SYMBOL.to_string();
74+
let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL);
7475
let global = context.new_global(None, GlobalKind::Exported, i8, name);
7576
#[cfg(feature = "master")]
7677
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
@@ -80,7 +81,7 @@ pub(crate) unsafe fn codegen(
8081
let value = context.new_rvalue_from_int(i8, value as i32);
8182
global.global_set_initializer_rvalue(value);
8283

83-
let name = NO_ALLOC_SHIM_IS_UNSTABLE.to_string();
84+
let name = mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE);
8485
let global = context.new_global(None, GlobalKind::Exported, i8, name);
8586
#[cfg(feature = "master")]
8687
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(

‎compiler/rustc_codegen_gcc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ extern crate rustc_metadata;
5252
extern crate rustc_middle;
5353
extern crate rustc_session;
5454
extern crate rustc_span;
55+
extern crate rustc_symbol_mangling;
5556
extern crate rustc_target;
5657

5758
// This prevents duplicating functions and statics that are already part of the host rustc process.

‎compiler/rustc_codegen_llvm/src/allocator.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _;
77
use rustc_middle::bug;
88
use rustc_middle::ty::TyCtxt;
99
use rustc_session::config::{DebugInfo, OomStrategy};
10+
use rustc_symbol_mangling::mangle_internal_symbol;
1011

1112
use crate::builder::SBuilder;
1213
use crate::declare::declare_simple_fn;
@@ -53,8 +54,8 @@ pub(crate) unsafe fn codegen(
5354
}
5455
};
5556

56-
let from_name = global_fn_name(method.name);
57-
let to_name = default_fn_name(method.name);
57+
let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name));
58+
let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name));
5859

5960
create_wrapper_function(tcx, &cx, &from_name, &to_name, &args, output, false);
6061
}
@@ -64,24 +65,24 @@ pub(crate) unsafe fn codegen(
6465
create_wrapper_function(
6566
tcx,
6667
&cx,
67-
"__rust_alloc_error_handler",
68-
alloc_error_handler_name(alloc_error_handler_kind),
68+
&mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
69+
&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)),
6970
&[usize, usize], // size, align
7071
None,
7172
true,
7273
);
7374

7475
unsafe {
7576
// __rust_alloc_error_handler_should_panic
76-
let name = OomStrategy::SYMBOL;
77-
let ll_g = cx.declare_global(name, i8);
77+
let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL);
78+
let ll_g = cx.declare_global(&name, i8);
7879
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
7980
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
8081
let llval = llvm::LLVMConstInt(i8, val as u64, False);
8182
llvm::set_initializer(ll_g, llval);
8283

83-
let name = NO_ALLOC_SHIM_IS_UNSTABLE;
84-
let ll_g = cx.declare_global(name, i8);
84+
let name = mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE);
85+
let ll_g = cx.declare_global(&name, i8);
8586
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
8687
let llval = llvm::LLVMConstInt(i8, 0, False);
8788
llvm::set_initializer(ll_g, llval);

‎compiler/rustc_codegen_llvm/src/context.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use rustc_session::config::{
2727
};
2828
use rustc_span::source_map::Spanned;
2929
use rustc_span::{DUMMY_SP, Span};
30+
use rustc_symbol_mangling::mangle_internal_symbol;
3031
use rustc_target::spec::{HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel};
3132
use smallvec::SmallVec;
3233

@@ -1199,7 +1200,7 @@ impl<'ll> CodegenCx<'ll, '_> {
11991200
Some(def_id) => self.get_static(def_id),
12001201
_ => {
12011202
let ty = self.type_struct(&[self.type_ptr(), self.type_ptr()], false);
1202-
self.declare_global("rust_eh_catch_typeinfo", ty)
1203+
self.declare_global(&mangle_internal_symbol(self.tcx, "rust_eh_catch_typeinfo"), ty)
12031204
}
12041205
};
12051206
self.eh_catch_typeinfo.set(Some(eh_catch_typeinfo));

‎compiler/rustc_codegen_llvm/src/intrinsic.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf};
1414
use rustc_middle::ty::{self, GenericArgsRef, Ty};
1515
use rustc_middle::{bug, span_bug};
1616
use rustc_span::{Span, Symbol, sym};
17+
use rustc_symbol_mangling::mangle_internal_symbol;
1718
use rustc_target::callconv::{FnAbi, PassMode};
1819
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
1920
use tracing::debug;
@@ -812,7 +813,10 @@ fn codegen_msvc_try<'ll>(
812813
let type_name = bx.const_bytes(b"rust_panic\0");
813814
let type_info =
814815
bx.const_struct(&[type_info_vtable, bx.const_null(bx.type_ptr()), type_name], false);
815-
let tydesc = bx.declare_global("__rust_panic_type_info", bx.val_ty(type_info));
816+
let tydesc = bx.declare_global(
817+
&mangle_internal_symbol(bx.tcx, "__rust_panic_type_info"),
818+
bx.val_ty(type_info),
819+
);
816820

817821
llvm::set_linkage(tydesc, llvm::Linkage::LinkOnceODRLinkage);
818822
if bx.cx.tcx.sess.target.supports_comdat() {

‎compiler/rustc_codegen_ssa/src/back/symbol_export.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::collections::hash_map::Entry::*;
22

3-
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE};
3+
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name};
44
use rustc_data_structures::unord::UnordMap;
55
use rustc_hir::def::DefKind;
66
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId};
@@ -13,6 +13,7 @@ use rustc_middle::query::LocalCrate;
1313
use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolName, Ty, TyCtxt};
1414
use rustc_middle::util::Providers;
1515
use rustc_session::config::{CrateType, OomStrategy};
16+
use rustc_symbol_mangling::mangle_internal_symbol;
1617
use rustc_target::callconv::Conv;
1718
use rustc_target::spec::{SanitizerSet, TlsModel};
1819
use tracing::debug;
@@ -219,8 +220,11 @@ fn exported_symbols_provider_local(
219220
if allocator_kind_for_codegen(tcx).is_some() {
220221
for symbol_name in ALLOCATOR_METHODS
221222
.iter()
222-
.map(|method| format!("__rust_{}", method.name))
223-
.chain(["__rust_alloc_error_handler".to_string(), OomStrategy::SYMBOL.to_string()])
223+
.map(|method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str()))
224+
.chain([
225+
mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
226+
mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
227+
])
224228
{
225229
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));
226230

@@ -234,8 +238,10 @@ fn exported_symbols_provider_local(
234238
));
235239
}
236240

237-
let exported_symbol =
238-
ExportedSymbol::NoDefId(SymbolName::new(tcx, NO_ALLOC_SHIM_IS_UNSTABLE));
241+
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(
242+
tcx,
243+
&mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE),
244+
));
239245
symbols.push((
240246
exported_symbol,
241247
SymbolExportInfo {

‎compiler/rustc_codegen_ssa/src/base.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
2828
use rustc_session::Session;
2929
use rustc_session::config::{self, CrateType, EntryFnType, OutputType};
3030
use rustc_span::{DUMMY_SP, Symbol, sym};
31+
use rustc_symbol_mangling::mangle_internal_symbol;
3132
use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt};
3233
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
3334
use tracing::{debug, info};
@@ -989,7 +990,12 @@ impl CrateInfo {
989990
.for_each(|(_, linked_symbols)| {
990991
let mut symbols = missing_weak_lang_items
991992
.iter()
992-
.map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text))
993+
.map(|item| {
994+
(
995+
format!("{prefix}{}", mangle_internal_symbol(tcx, item.as_str())),
996+
SymbolExportKind::Text,
997+
)
998+
})
993999
.collect::<Vec<_>>();
9941000
symbols.sort_unstable_by(|a, b| a.0.cmp(&b.0));
9951001
linked_symbols.extend(symbols);
@@ -1002,7 +1008,13 @@ impl CrateInfo {
10021008
// errors.
10031009
linked_symbols.extend(ALLOCATOR_METHODS.iter().map(|method| {
10041010
(
1005-
format!("{prefix}{}", global_fn_name(method.name).as_str()),
1011+
format!(
1012+
"{prefix}{}",
1013+
mangle_internal_symbol(
1014+
tcx,
1015+
global_fn_name(method.name).as_str()
1016+
)
1017+
),
10061018
SymbolExportKind::Text,
10071019
)
10081020
}));

‎compiler/rustc_codegen_ssa/src/codegen_attrs.rs

+7-13
Original file line numberDiff line numberDiff line change
@@ -601,25 +601,19 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
601601
// strippable by the linker.
602602
//
603603
// Additionally weak lang items have predetermined symbol names.
604-
if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
605-
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
606-
}
607604
if let Some((name, _)) = lang_items::extract(attrs)
608605
&& let Some(lang_item) = LangItem::from_name(name)
609-
&& let Some(link_name) = lang_item.link_name()
610606
{
611-
codegen_fn_attrs.export_name = Some(link_name);
612-
codegen_fn_attrs.link_name = Some(link_name);
607+
if WEAK_LANG_ITEMS.iter().any(|&l| l == lang_item) {
608+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
609+
}
610+
if let Some(link_name) = lang_item.link_name() {
611+
codegen_fn_attrs.export_name = Some(link_name);
612+
codegen_fn_attrs.link_name = Some(link_name);
613+
}
613614
}
614615
check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
615616

616-
// Internal symbols to the standard library all have no_mangle semantics in
617-
// that they have defined symbol names present in the function name. This
618-
// also applies to weak symbols where they all have known symbol names.
619-
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
620-
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
621-
}
622-
623617
// Any linkage to LLVM intrinsics for now forcibly marks them all as never
624618
// unwinds since LLVM sometimes can't handle codegen which `invoke`s
625619
// intrinsic functions.

‎compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

+1
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ impl CodegenFnAttrs {
174174
/// * `#[linkage]` is present
175175
pub fn contains_extern_indicator(&self) -> bool {
176176
self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
177+
|| self.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
177178
|| self.export_name.is_some()
178179
|| match self.linkage {
179180
// These are private, so make sure we don't try to consider

‎compiler/rustc_passes/src/check_attr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2203,7 +2203,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
22032203

22042204
fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) {
22052205
match target {
2206-
Target::Fn | Target::Static => {}
2206+
Target::Fn | Target::Static | Target::ForeignFn | Target::ForeignStatic => {}
22072207
_ => {
22082208
self.tcx
22092209
.dcx()

‎compiler/rustc_passes/src/reachable.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,7 @@ impl<'tcx> ReachableContext<'tcx> {
184184
CodegenFnAttrs::EMPTY
185185
};
186186
let is_extern = codegen_attrs.contains_extern_indicator();
187-
let std_internal =
188-
codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
189-
if is_extern || std_internal {
187+
if is_extern {
190188
self.reachable_symbols.insert(search_item);
191189
}
192190
} else {
@@ -426,7 +424,6 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
426424
}
427425
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
428426
codegen_attrs.contains_extern_indicator()
429-
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
430427
// FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by
431428
// `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their
432429
// `SymbolExportLevel::Rust` export level but may end up being exported in dylibs.

‎compiler/rustc_symbol_mangling/src/lib.rs

+37
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ mod v0;
112112
pub mod errors;
113113
pub mod test;
114114

115+
pub use v0::mangle_internal_symbol;
116+
115117
/// This function computes the symbol name for the given `instance` and the
116118
/// given instantiating crate. That is, if you know that instance X is
117119
/// instantiated in crate Y, this is the symbol name this instance would have.
@@ -183,6 +185,39 @@ fn compute_symbol_name<'tcx>(
183185
CodegenFnAttrs::EMPTY
184186
};
185187

188+
if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
189+
// Items marked as #[rustc_std_internal_symbol] need to have a fixed
190+
// symbol name because it is used to import items from another crate
191+
// without a direct dependency. As such it is not possible to look up
192+
// the mangled name for the `Instance` from the crate metadata of the
193+
// defining crate.
194+
// Weak lang items automatically get #[rustc_std_internal_symbol]
195+
// applied by the code computing the CodegenFnAttrs.
196+
// We are mangling all #[rustc_std_internal_symbol] items that don't
197+
// also have #[no_mangle] as a combination of the rustc version and the
198+
// unmangled linkage name. This is to ensure that if we link against a
199+
// staticlib compiled by a different rustc version, we don't get symbol
200+
// conflicts or even UB due to a different implementation/ABI. Rust
201+
// staticlibs currently export all symbols, including those that are
202+
// hidden in cdylibs.
203+
// We are using the v0 symbol mangling scheme here as we need to be
204+
// consistent across all crates and in some contexts the legacy symbol
205+
// mangling scheme can't be used. For example both the GCC backend and
206+
// Rust-for-Linux don't support some of the characters used by the
207+
// legacy symbol mangling scheme.
208+
let name = if tcx.is_foreign_item(def_id) {
209+
if let Some(name) = attrs.link_name { name } else { tcx.item_name(def_id) }
210+
} else {
211+
if let Some(name) = attrs.export_name { name } else { tcx.item_name(def_id) }
212+
};
213+
214+
if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) {
215+
return name.to_string();
216+
} else {
217+
return v0::mangle_internal_symbol(tcx, name.as_str());
218+
}
219+
}
220+
186221
// Foreign items by default use no mangling for their symbol name. There's a
187222
// few exceptions to this rule though:
188223
//
@@ -198,6 +233,8 @@ fn compute_symbol_name<'tcx>(
198233
// is present we mangle everything on wasm because the demangled form will
199234
// show up in the `wasm-import-name` custom attribute in LLVM IR.
200235
//
236+
// * `#[rustc_std_internal_symbol]` mangles the symbol name in a special way
237+
// both for exports and imports through foreign items. This is handled above.
201238
// [1]: https://bugs.llvm.org/show_bug.cgi?id=44316
202239
if tcx.is_foreign_item(def_id)
203240
&& (!tcx.sess.target.is_like_wasm

‎compiler/rustc_symbol_mangling/src/v0.rs

+51
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
use std::fmt::Write;
2+
use std::hash::Hasher;
23
use std::iter;
34
use std::ops::Range;
45

56
use rustc_abi::{ExternAbi, Integer};
67
use rustc_data_structures::base_n::ToBaseN;
78
use rustc_data_structures::fx::FxHashMap;
89
use rustc_data_structures::intern::Interned;
10+
use rustc_data_structures::stable_hasher::StableHasher;
11+
use rustc_hashes::Hash64;
912
use rustc_hir as hir;
1013
use rustc_hir::def::CtorKind;
1114
use rustc_hir::def_id::{CrateNum, DefId};
@@ -70,6 +73,54 @@ pub(super) fn mangle<'tcx>(
7073
std::mem::take(&mut cx.out)
7174
}
7275

76+
pub fn mangle_internal_symbol<'tcx>(tcx: TyCtxt<'tcx>, item_name: &str) -> String {
77+
if item_name == "rust_eh_personality" {
78+
// rust_eh_personality must not be renamed as LLVM hard-codes the name
79+
return "rust_eh_personality".to_owned();
80+
} else if item_name == "__rust_no_alloc_shim_is_unstable" {
81+
// Temporary back compat hack to give people the chance to migrate to
82+
// include #[rustc_std_internal_symbol].
83+
return "__rust_no_alloc_shim_is_unstable".to_owned();
84+
}
85+
86+
let prefix = "_R";
87+
let mut cx: SymbolMangler<'_> = SymbolMangler {
88+
tcx,
89+
start_offset: prefix.len(),
90+
paths: FxHashMap::default(),
91+
types: FxHashMap::default(),
92+
consts: FxHashMap::default(),
93+
binders: vec![],
94+
out: String::from(prefix),
95+
};
96+
97+
cx.path_append_ns(
98+
|cx| {
99+
cx.push("C");
100+
cx.push_disambiguator({
101+
let mut hasher = StableHasher::new();
102+
// Incorporate the rustc version to ensure #[rustc_std_internal_symbol] functions
103+
// get a different symbol name depending on the rustc version.
104+
//
105+
// RUSTC_FORCE_RUSTC_VERSION is ignored here as otherwise different we would get an
106+
// abi incompatibility with the standard library.
107+
hasher.write(tcx.sess.cfg_version.as_bytes());
108+
109+
let hash: Hash64 = hasher.finish();
110+
hash.as_u64()
111+
});
112+
cx.push_ident("__rustc");
113+
Ok(())
114+
},
115+
'v',
116+
0,
117+
item_name,
118+
)
119+
.unwrap();
120+
121+
std::mem::take(&mut cx.out)
122+
}
123+
73124
pub(super) fn mangle_typeid_for_trait_ref<'tcx>(
74125
tcx: TyCtxt<'tcx>,
75126
trait_ref: ty::ExistentialTraitRef<'tcx>,

‎library/alloc/src/alloc.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,28 @@ use core::ptr::{self, NonNull};
1010

1111
unsafe extern "Rust" {
1212
// These are the magic symbols to call the global allocator. rustc generates
13-
// them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute
13+
// them to call the global allocator if there is a `#[global_allocator]` attribute
1414
// (the code expanding that attribute macro generates those functions), or to call
1515
// the default implementations in std (`__rdl_alloc` etc. in `library/std/src/alloc.rs`)
1616
// otherwise.
17-
// The rustc fork of LLVM 14 and earlier also special-cases these function names to be able to optimize them
18-
// like `malloc`, `realloc`, and `free`, respectively.
1917
#[rustc_allocator]
2018
#[rustc_nounwind]
19+
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
2120
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
2221
#[rustc_deallocator]
2322
#[rustc_nounwind]
23+
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
2424
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
2525
#[rustc_reallocator]
2626
#[rustc_nounwind]
27+
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
2728
fn __rust_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8;
2829
#[rustc_allocator_zeroed]
2930
#[rustc_nounwind]
31+
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
3032
fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
3133

34+
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
3235
static __rust_no_alloc_shim_is_unstable: u8;
3336
}
3437

@@ -357,6 +360,7 @@ unsafe extern "Rust" {
357360
// This is the magic symbol to call the global alloc error handler. rustc generates
358361
// it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the
359362
// default implementations below (`__rdl_oom`) otherwise.
363+
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
360364
fn __rust_alloc_error_handler(size: usize, align: usize) -> !;
361365
}
362366

@@ -423,6 +427,7 @@ pub mod __alloc_error_handler {
423427
unsafe extern "Rust" {
424428
// This symbol is emitted by rustc next to __rust_alloc_error_handler.
425429
// Its value depends on the -Zoom={panic,abort} compiler option.
430+
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
426431
static __rust_alloc_error_handler_should_panic: u8;
427432
}
428433

‎library/panic_unwind/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,11 @@ cfg_if::cfg_if! {
7979
unsafe extern "C" {
8080
/// Handler in std called when a panic object is dropped outside of
8181
/// `catch_unwind`.
82+
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
8283
fn __rust_drop_panic() -> !;
8384

8485
/// Handler in std called when a foreign exception is caught.
86+
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
8587
fn __rust_foreign_exception() -> !;
8688
}
8789

‎library/std/src/alloc.rs

+1
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ fn default_alloc_error_hook(layout: Layout) {
348348
unsafe extern "Rust" {
349349
// This symbol is emitted by rustc next to __rust_alloc_error_handler.
350350
// Its value depends on the -Zoom={panic,abort} compiler option.
351+
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
351352
static __rust_alloc_error_handler_should_panic: u8;
352353
}
353354

‎library/std/src/panicking.rs

+2
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,14 @@ pub static EMPTY_PANIC: fn(&'static str) -> ! =
5555
// hook up these functions, but it is not this day!
5656
#[allow(improper_ctypes)]
5757
unsafe extern "C" {
58+
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
5859
fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static);
5960
}
6061

6162
unsafe extern "Rust" {
6263
/// `PanicPayload` lazily performs allocation only when needed (this avoids
6364
/// allocations when using the "abort" panic runtime).
65+
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
6466
fn __rust_start_panic(payload: &mut dyn PanicPayload) -> u32;
6567
}
6668

‎src/tools/miri/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ extern crate rustc_index;
7171
extern crate rustc_middle;
7272
extern crate rustc_session;
7373
extern crate rustc_span;
74+
extern crate rustc_symbol_mangling;
7475
extern crate rustc_target;
7576
// Linking `rustc_driver` pulls in the required object code as the rest of the rustc crates are
7677
// shipped only as rmeta files.

‎src/tools/miri/src/shims/extern_static.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Provides the `extern static` that this platform expects.
22
3+
use rustc_symbol_mangling::mangle_internal_symbol;
4+
35
use crate::*;
46

57
impl<'tcx> MiriMachine<'tcx> {
@@ -50,7 +52,11 @@ impl<'tcx> MiriMachine<'tcx> {
5052
// "__rust_alloc_error_handler_should_panic"
5153
let val = ecx.tcx.sess.opts.unstable_opts.oom.should_panic();
5254
let val = ImmTy::from_int(val, ecx.machine.layouts.u8);
53-
Self::alloc_extern_static(ecx, "__rust_alloc_error_handler_should_panic", val)?;
55+
Self::alloc_extern_static(
56+
ecx,
57+
&mangle_internal_symbol(*ecx.tcx, "__rust_alloc_error_handler_should_panic"),
58+
val,
59+
)?;
5460

5561
if ecx.target_os_is_unix() {
5662
// "environ" is mandated by POSIX.

‎src/tools/miri/src/shims/foreign_items.rs

+32-18
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_middle::mir::interpret::AllocInit;
1212
use rustc_middle::ty::Ty;
1313
use rustc_middle::{mir, ty};
1414
use rustc_span::Symbol;
15+
use rustc_symbol_mangling::mangle_internal_symbol;
1516
use rustc_target::callconv::{Conv, FnAbi};
1617

1718
use self::helpers::{ToHost, ToSoft};
@@ -51,17 +52,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
5152

5253
// Some shims forward to other MIR bodies.
5354
match link_name.as_str() {
54-
"__rust_alloc_error_handler" => {
55+
name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc_error_handler") => {
5556
// Forward to the right symbol that implements this function.
5657
let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else {
5758
// in real code, this symbol does not exist without an allocator
5859
throw_unsup_format!(
5960
"`__rust_alloc_error_handler` cannot be called when no alloc error handler is set"
6061
);
6162
};
62-
let name = alloc_error_handler_name(handler_kind);
63+
let name =
64+
mangle_internal_symbol(*this.tcx, alloc_error_handler_name(handler_kind));
6365
let handler = this
64-
.lookup_exported_symbol(Symbol::intern(name))?
66+
.lookup_exported_symbol(Symbol::intern(&name))?
6567
.expect("missing alloc error handler symbol");
6668
return interp_ok(Some(handler));
6769
}
@@ -136,15 +138,29 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
136138
// Find it if it was not cached.
137139
let mut instance_and_crate: Option<(ty::Instance<'_>, CrateNum)> = None;
138140
helpers::iter_exported_symbols(tcx, |cnum, def_id| {
141+
if tcx.is_foreign_item(def_id) {
142+
// Skip over imports of items
143+
return interp_ok(());
144+
}
145+
139146
let attrs = tcx.codegen_fn_attrs(def_id);
147+
// FIXME use tcx.symbol_name(instance) instead
140148
let symbol_name = if let Some(export_name) = attrs.export_name {
141149
export_name
142-
} else if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) {
150+
} else if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
151+
|| attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
152+
{
143153
tcx.item_name(def_id)
144154
} else {
145155
// Skip over items without an explicitly defined symbol name.
146156
return interp_ok(());
147157
};
158+
let symbol_name =
159+
if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
160+
Symbol::intern(&mangle_internal_symbol(tcx, symbol_name.as_str()))
161+
} else {
162+
symbol_name
163+
};
148164
if symbol_name == link_name {
149165
if let Some((original_instance, original_cnum)) = instance_and_crate {
150166
// Make sure we are consistent wrt what is 'first' and 'second'.
@@ -489,7 +505,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
489505
}
490506

491507
// Rust allocation
492-
"__rust_alloc" | "miri_alloc" => {
508+
name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc")
509+
|| name == "miri_alloc" =>
510+
{
493511
let default = |ecx: &mut MiriInterpCx<'tcx>| {
494512
// Only call `check_shim` when `#[global_allocator]` isn't used. When that
495513
// macro is used, we act like no shim exists, so that the exported function can run.
@@ -500,9 +518,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
500518
ecx.check_rustc_alloc_request(size, align)?;
501519

502520
let memory_kind = match link_name.as_str() {
503-
"__rust_alloc" => MiriMemoryKind::Rust,
504521
"miri_alloc" => MiriMemoryKind::Miri,
505-
_ => unreachable!(),
522+
_ => MiriMemoryKind::Rust,
506523
};
507524

508525
let ptr = ecx.allocate_ptr(
@@ -516,15 +533,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
516533
};
517534

518535
match link_name.as_str() {
519-
"__rust_alloc" => return this.emulate_allocator(default),
520536
"miri_alloc" => {
521537
default(this)?;
522538
return interp_ok(EmulateItemResult::NeedsReturn);
523539
}
524-
_ => unreachable!(),
540+
_ => return this.emulate_allocator(default),
525541
}
526542
}
527-
"__rust_alloc_zeroed" => {
543+
name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc_zeroed") => {
528544
return this.emulate_allocator(|this| {
529545
// See the comment for `__rust_alloc` why `check_shim` is only called in the
530546
// default case.
@@ -543,7 +559,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
543559
this.write_pointer(ptr, dest)
544560
});
545561
}
546-
"__rust_dealloc" | "miri_dealloc" => {
562+
name if name == mangle_internal_symbol(*this.tcx, "__rust_dealloc")
563+
|| name == "miri_dealloc" =>
564+
{
547565
let default = |ecx: &mut MiriInterpCx<'tcx>| {
548566
// See the comment for `__rust_alloc` why `check_shim` is only called in the
549567
// default case.
@@ -554,9 +572,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
554572
let align = ecx.read_target_usize(align)?;
555573

556574
let memory_kind = match link_name.as_str() {
557-
"__rust_dealloc" => MiriMemoryKind::Rust,
558575
"miri_dealloc" => MiriMemoryKind::Miri,
559-
_ => unreachable!(),
576+
_ => MiriMemoryKind::Rust,
560577
};
561578

562579
// No need to check old_size/align; we anyway check that they match the allocation.
@@ -568,17 +585,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
568585
};
569586

570587
match link_name.as_str() {
571-
"__rust_dealloc" => {
572-
return this.emulate_allocator(default);
573-
}
574588
"miri_dealloc" => {
575589
default(this)?;
576590
return interp_ok(EmulateItemResult::NeedsReturn);
577591
}
578-
_ => unreachable!(),
592+
_ => return this.emulate_allocator(default),
579593
}
580594
}
581-
"__rust_realloc" => {
595+
name if name == mangle_internal_symbol(*this.tcx, "__rust_realloc") => {
582596
return this.emulate_allocator(|this| {
583597
// See the comment for `__rust_alloc` why `check_shim` is only called in the
584598
// default case.

‎src/tools/miri/tests/fail/alloc/too_large.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
#![feature(rustc_attrs)]
2+
13
extern "Rust" {
4+
#[rustc_std_internal_symbol]
25
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
36
}
47

‎src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
// because rustc does not support alignments that large.
33
// https://github.com/rust-lang/miri/issues/3687
44

5+
#![feature(rustc_attrs)]
6+
57
extern "Rust" {
8+
#[rustc_std_internal_symbol]
69
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
710
}
811

‎src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
// Test non-power-of-two alignment.
2+
3+
#![feature(rustc_attrs)]
4+
25
extern "Rust" {
6+
#[rustc_std_internal_symbol]
37
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
48
}
59

‎src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// Avoid accidental synchronization via address reuse inside `thread::spawn`.
44
//@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
55

6+
#![feature(rustc_attrs)]
7+
68
use std::thread::spawn;
79

810
#[derive(Copy, Clone)]
@@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {}
1214
unsafe impl<T> Sync for EvilSend<T> {}
1315

1416
extern "Rust" {
17+
#[rustc_std_internal_symbol]
1518
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
1619
}
1720

‎src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// Avoid accidental synchronization via address reuse inside `thread::spawn`.
44
//@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
55

6+
#![feature(rustc_attrs)]
7+
68
use std::thread::spawn;
79

810
#[derive(Copy, Clone)]
@@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {}
1214
unsafe impl<T> Sync for EvilSend<T> {}
1315

1416
extern "Rust" {
17+
#[rustc_std_internal_symbol]
1518
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
1619
}
1720

‎src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// Avoid accidental synchronization via address reuse inside `thread::spawn`.
44
//@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
55

6+
#![feature(rustc_attrs)]
7+
68
use std::thread::spawn;
79

810
#[derive(Copy, Clone)]
@@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {}
1214
unsafe impl<T> Sync for EvilSend<T> {}
1315

1416
extern "Rust" {
17+
#[rustc_std_internal_symbol]
1518
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
1619
}
1720
pub fn main() {

‎src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// Avoid accidental synchronization via address reuse inside `thread::spawn`.
44
//@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
55

6+
#![feature(rustc_attrs)]
7+
68
use std::thread::spawn;
79

810
#[derive(Copy, Clone)]
@@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {}
1214
unsafe impl<T> Sync for EvilSend<T> {}
1315

1416
extern "Rust" {
17+
#[rustc_std_internal_symbol]
1518
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
1619
}
1720
pub fn main() {

‎src/tools/miri/tests/pass/function_calls/exported_symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ fn main() {
4040

4141
extern "Rust" {
4242
fn bar() -> i32;
43+
#[rustc_std_internal_symbol]
4344
fn baz() -> i32;
4445
fn qux() -> i32;
4546
}
@@ -63,6 +64,7 @@ fn main() {
6364

6465
extern "C" {
6566
fn bar() -> i32;
67+
#[rustc_std_internal_symbol]
6668
fn baz() -> i32;
6769
fn qux() -> i32;
6870
}

‎tests/codegen/alloc-optimisation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
pub fn alloc_test(data: u32) {
66
// CHECK-LABEL: @alloc_test
77
// CHECK-NEXT: start:
8-
// CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1
8+
// CHECK-NEXT: {{.*}} load volatile i8, ptr @{{.*}}__rust_no_alloc_shim_is_unstable, align 1
99
// CHECK-NEXT: ret void
1010
let x = Box::new(data);
1111
drop(x);

‎tests/codegen/box-uninit-bytes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,6 @@ pub fn box_lotsa_padding() -> Box<LotsaPadding> {
4141

4242
// Hide the `allocalign` attribute in the declaration of __rust_alloc
4343
// from the CHECK-NOT above, and also verify the attributes got set reasonably.
44-
// CHECK: declare {{(dso_local )?}}noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]
44+
// CHECK: declare {{(dso_local )?}}noalias noundef ptr @{{.*}}__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]
4545

4646
// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) {{(uwtable )?}}"alloc-family"="__rust_alloc" {{.*}} }

‎tests/codegen/dealloc-no-unwind.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ impl Drop for A {
1818
#[no_mangle]
1919
pub fn a(a: Box<i32>) {
2020
// CHECK-LABEL: define{{.*}}void @a
21-
// CHECK: call void @__rust_dealloc
21+
// CHECK: call void @{{.*}}__rust_dealloc
2222
// CHECK-NEXT: call void @foo
2323
let _a = A;
2424
drop(a);

‎tests/codegen/iter-repeat-n-trivial-drop.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN<NotCopy>) -> Option<NotCop
4747
#[no_mangle]
4848
// CHECK-LABEL: @vec_extend_via_iter_repeat_n
4949
pub fn vec_extend_via_iter_repeat_n() -> Vec<u8> {
50-
// CHECK: %[[ADDR:.+]] = tail call {{(noalias )?}}noundef dereferenceable_or_null(1234) ptr @__rust_alloc(i64 noundef {{(range\(i64 1, 0\) )?}}1234, i64 noundef {{(range\(i64 1, -9223372036854775807\) )?}}1)
50+
// CHECK: %[[ADDR:.+]] = tail call {{(noalias )?}}noundef dereferenceable_or_null(1234) ptr @{{.*}}__rust_alloc(i64 noundef {{(range\(i64 1, 0\) )?}}1234, i64 noundef {{(range\(i64 1, -9223372036854775807\) )?}}1)
5151
// CHECK: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(1234) %[[ADDR]], i8 42, i64 1234,
5252

5353
let n = 1234_usize;

‎tests/codegen/vec-calloc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,6 @@ pub fn vec_option_i32(n: usize) -> Vec<Option<i32>> {
177177
}
178178

179179
// Ensure that __rust_alloc_zeroed gets the right attributes for LLVM to optimize it away.
180-
// CHECK: declare noalias noundef ptr @__rust_alloc_zeroed(i64 noundef, i64 allocalign noundef) unnamed_addr [[RUST_ALLOC_ZEROED_ATTRS:#[0-9]+]]
180+
// CHECK: declare noalias noundef ptr @{{.*}}__rust_alloc_zeroed(i64 noundef, i64 allocalign noundef) unnamed_addr [[RUST_ALLOC_ZEROED_ATTRS:#[0-9]+]]
181181

182182
// CHECK-DAG: attributes [[RUST_ALLOC_ZEROED_ATTRS]] = { {{.*}} allockind("alloc,zeroed,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} }

‎tests/codegen/vec-optimizes-away.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
pub fn sum_me() -> i32 {
66
// CHECK-LABEL: @sum_me
77
// CHECK-NEXT: {{^.*:$}}
8-
// CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1
8+
// CHECK-NEXT: {{.*}} load volatile i8, ptr @{{.*}}__rust_no_alloc_shim_is_unstable, align 1
99
// CHECK-NEXT: ret i32 6
1010
vec![1, 2, 3].iter().sum::<i32>()
1111
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub fn public_rust_function() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub fn public_rust_function_from_exe() {}
2+
3+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Check that all symbols in cdylibs, staticlibs and bins are mangled
2+
//@ only-elf some object file formats create multiple symbols for each function with different names
3+
4+
use run_make_support::object::read::{Object, ObjectSymbol};
5+
use run_make_support::{bin_name, dynamic_lib_name, object, rfs, rustc, static_lib_name};
6+
7+
fn main() {
8+
let staticlib_name = static_lib_name("a_lib");
9+
let cdylib_name = dynamic_lib_name("a_lib");
10+
let exe_name = bin_name("an_executable");
11+
rustc().crate_type("cdylib").input("a_lib.rs").run();
12+
rustc().crate_type("staticlib").input("a_lib.rs").run();
13+
rustc().crate_type("bin").input("an_executable.rs").run();
14+
15+
symbols_check_archive(&staticlib_name);
16+
symbols_check(&cdylib_name);
17+
symbols_check(&exe_name);
18+
}
19+
20+
fn symbols_check_archive(path: &str) {
21+
let binary_data = rfs::read(path);
22+
let file = object::read::archive::ArchiveFile::parse(&*binary_data).unwrap();
23+
for symbol in file.symbols().unwrap().unwrap() {
24+
let symbol = symbol.unwrap();
25+
let name = strip_underscore_if_apple(std::str::from_utf8(symbol.name()).unwrap());
26+
if name.starts_with("_ZN") || name.starts_with("_R") {
27+
continue; // Correctly mangled
28+
}
29+
30+
let member_name =
31+
std::str::from_utf8(file.member(symbol.offset()).unwrap().name()).unwrap();
32+
if !member_name.ends_with(".rcgu.o") || member_name.contains("compiler_builtins") {
33+
continue; // All compiler-builtins symbols must remain unmangled
34+
}
35+
36+
if name == "__rust_no_alloc_shim_is_unstable" {
37+
continue; // FIXME remove exception once we mangle this symbol
38+
}
39+
40+
if name.contains("rust_eh_personality") {
41+
continue; // Unfortunately LLVM doesn't allow us to mangle this symbol
42+
}
43+
44+
panic!("Unmangled symbol found: {name}");
45+
}
46+
}
47+
48+
fn symbols_check(path: &str) {
49+
let binary_data = rfs::read(path);
50+
let file = object::File::parse(&*binary_data).unwrap();
51+
for symbol in file.symbols() {
52+
if !symbol.is_definition() || !symbol.is_global() {
53+
continue;
54+
}
55+
if symbol.is_weak() {
56+
continue; // Likely an intrinsic from compiler-builtins
57+
}
58+
let name = strip_underscore_if_apple(symbol.name().unwrap());
59+
if name.starts_with("_ZN") || name.starts_with("_R") {
60+
continue; // Correctly mangled
61+
}
62+
63+
if !name.contains("rust") {
64+
// Assume that this symbol doesn't originate from rustc. This may
65+
// be wrong, but even if so symbol_check_archive will likely
66+
// catch it.
67+
continue;
68+
}
69+
70+
if name == "__rust_no_alloc_shim_is_unstable" {
71+
continue; // FIXME remove exception once we mangle this symbol
72+
}
73+
74+
if name.contains("rust_eh_personality") {
75+
continue; // Unfortunately LLVM doesn't allow us to mangle this symbol
76+
}
77+
78+
panic!("Unmangled symbol found: {name}");
79+
}
80+
}
81+
82+
fn strip_underscore_if_apple(symbol: &str) -> &str {
83+
if cfg!(target_vendor = "apple") { symbol.strip_prefix("_").unwrap() } else { symbol }
84+
}

0 commit comments

Comments
 (0)
Please sign in to comment.