Auto merge of #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 https://github.com/rust-lang/rust/issues/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
This commit is contained in:
commit
493c38ba37
39 changed files with 342 additions and 76 deletions
|
@ -7,6 +7,7 @@ use rustc_ast::expand::allocator::{
|
||||||
};
|
};
|
||||||
use rustc_codegen_ssa::base::allocator_kind_for_codegen;
|
use rustc_codegen_ssa::base::allocator_kind_for_codegen;
|
||||||
use rustc_session::config::OomStrategy;
|
use rustc_session::config::OomStrategy;
|
||||||
|
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ use crate::prelude::*;
|
||||||
pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool {
|
pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool {
|
||||||
let Some(kind) = allocator_kind_for_codegen(tcx) else { return false };
|
let Some(kind) = allocator_kind_for_codegen(tcx) else { return false };
|
||||||
codegen_inner(
|
codegen_inner(
|
||||||
|
tcx,
|
||||||
module,
|
module,
|
||||||
kind,
|
kind,
|
||||||
tcx.alloc_error_handler_kind(()).unwrap(),
|
tcx.alloc_error_handler_kind(()).unwrap(),
|
||||||
|
@ -23,6 +25,7 @@ pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_inner(
|
fn codegen_inner(
|
||||||
|
tcx: TyCtxt<'_>,
|
||||||
module: &mut dyn Module,
|
module: &mut dyn Module,
|
||||||
kind: AllocatorKind,
|
kind: AllocatorKind,
|
||||||
alloc_error_handler_kind: AllocatorKind,
|
alloc_error_handler_kind: AllocatorKind,
|
||||||
|
@ -62,8 +65,8 @@ fn codegen_inner(
|
||||||
crate::common::create_wrapper_function(
|
crate::common::create_wrapper_function(
|
||||||
module,
|
module,
|
||||||
sig,
|
sig,
|
||||||
&global_fn_name(method.name),
|
&mangle_internal_symbol(tcx, &global_fn_name(method.name)),
|
||||||
&default_fn_name(method.name),
|
&mangle_internal_symbol(tcx, &default_fn_name(method.name)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,19 +79,32 @@ fn codegen_inner(
|
||||||
crate::common::create_wrapper_function(
|
crate::common::create_wrapper_function(
|
||||||
module,
|
module,
|
||||||
sig,
|
sig,
|
||||||
"__rust_alloc_error_handler",
|
&mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
|
||||||
&alloc_error_handler_name(alloc_error_handler_kind),
|
&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)),
|
||||||
);
|
);
|
||||||
|
|
||||||
let data_id = module.declare_data(OomStrategy::SYMBOL, Linkage::Export, false, false).unwrap();
|
let data_id = module
|
||||||
|
.declare_data(
|
||||||
|
&mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
|
||||||
|
Linkage::Export,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
let mut data = DataDescription::new();
|
let mut data = DataDescription::new();
|
||||||
data.set_align(1);
|
data.set_align(1);
|
||||||
let val = oom_strategy.should_panic();
|
let val = oom_strategy.should_panic();
|
||||||
data.define(Box::new([val]));
|
data.define(Box::new([val]));
|
||||||
module.define_data(data_id, &data).unwrap();
|
module.define_data(data_id, &data).unwrap();
|
||||||
|
|
||||||
let data_id =
|
let data_id = module
|
||||||
module.declare_data(NO_ALLOC_SHIM_IS_UNSTABLE, Linkage::Export, false, false).unwrap();
|
.declare_data(
|
||||||
|
&mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE),
|
||||||
|
Linkage::Export,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
let mut data = DataDescription::new();
|
let mut data = DataDescription::new();
|
||||||
data.set_align(1);
|
data.set_align(1);
|
||||||
data.define(Box::new([0]));
|
data.define(Box::new([0]));
|
||||||
|
|
|
@ -26,6 +26,7 @@ extern crate rustc_index;
|
||||||
extern crate rustc_metadata;
|
extern crate rustc_metadata;
|
||||||
extern crate rustc_session;
|
extern crate rustc_session;
|
||||||
extern crate rustc_span;
|
extern crate rustc_span;
|
||||||
|
extern crate rustc_symbol_mangling;
|
||||||
extern crate rustc_target;
|
extern crate rustc_target;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate tracing;
|
extern crate tracing;
|
||||||
|
|
|
@ -8,6 +8,7 @@ use rustc_ast::expand::allocator::{
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::config::OomStrategy;
|
use rustc_session::config::OomStrategy;
|
||||||
|
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||||
|
|
||||||
use crate::GccContext;
|
use crate::GccContext;
|
||||||
#[cfg(feature = "master")]
|
#[cfg(feature = "master")]
|
||||||
|
@ -53,8 +54,8 @@ pub(crate) unsafe fn codegen(
|
||||||
panic!("invalid allocator output")
|
panic!("invalid allocator output")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let from_name = global_fn_name(method.name);
|
let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name));
|
||||||
let to_name = default_fn_name(method.name);
|
let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name));
|
||||||
|
|
||||||
create_wrapper_function(tcx, context, &from_name, &to_name, &types, output);
|
create_wrapper_function(tcx, context, &from_name, &to_name, &types, output);
|
||||||
}
|
}
|
||||||
|
@ -64,13 +65,13 @@ pub(crate) unsafe fn codegen(
|
||||||
create_wrapper_function(
|
create_wrapper_function(
|
||||||
tcx,
|
tcx,
|
||||||
context,
|
context,
|
||||||
"__rust_alloc_error_handler",
|
&mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
|
||||||
alloc_error_handler_name(alloc_error_handler_kind),
|
&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)),
|
||||||
&[usize, usize],
|
&[usize, usize],
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
let name = OomStrategy::SYMBOL.to_string();
|
let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL);
|
||||||
let global = context.new_global(None, GlobalKind::Exported, i8, name);
|
let global = context.new_global(None, GlobalKind::Exported, i8, name);
|
||||||
#[cfg(feature = "master")]
|
#[cfg(feature = "master")]
|
||||||
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
|
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
|
||||||
|
@ -80,7 +81,7 @@ pub(crate) unsafe fn codegen(
|
||||||
let value = context.new_rvalue_from_int(i8, value as i32);
|
let value = context.new_rvalue_from_int(i8, value as i32);
|
||||||
global.global_set_initializer_rvalue(value);
|
global.global_set_initializer_rvalue(value);
|
||||||
|
|
||||||
let name = NO_ALLOC_SHIM_IS_UNSTABLE.to_string();
|
let name = mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE);
|
||||||
let global = context.new_global(None, GlobalKind::Exported, i8, name);
|
let global = context.new_global(None, GlobalKind::Exported, i8, name);
|
||||||
#[cfg(feature = "master")]
|
#[cfg(feature = "master")]
|
||||||
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
|
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
|
||||||
|
|
|
@ -52,6 +52,7 @@ extern crate rustc_metadata;
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
extern crate rustc_session;
|
extern crate rustc_session;
|
||||||
extern crate rustc_span;
|
extern crate rustc_span;
|
||||||
|
extern crate rustc_symbol_mangling;
|
||||||
extern crate rustc_target;
|
extern crate rustc_target;
|
||||||
|
|
||||||
// This prevents duplicating functions and statics that are already part of the host rustc process.
|
// This prevents duplicating functions and statics that are already part of the host rustc process.
|
||||||
|
|
|
@ -7,6 +7,7 @@ use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::config::{DebugInfo, OomStrategy};
|
use rustc_session::config::{DebugInfo, OomStrategy};
|
||||||
|
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||||
|
|
||||||
use crate::builder::SBuilder;
|
use crate::builder::SBuilder;
|
||||||
use crate::declare::declare_simple_fn;
|
use crate::declare::declare_simple_fn;
|
||||||
|
@ -53,8 +54,8 @@ pub(crate) unsafe fn codegen(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let from_name = global_fn_name(method.name);
|
let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name));
|
||||||
let to_name = default_fn_name(method.name);
|
let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name));
|
||||||
|
|
||||||
create_wrapper_function(tcx, &cx, &from_name, &to_name, &args, output, false);
|
create_wrapper_function(tcx, &cx, &from_name, &to_name, &args, output, false);
|
||||||
}
|
}
|
||||||
|
@ -64,8 +65,8 @@ pub(crate) unsafe fn codegen(
|
||||||
create_wrapper_function(
|
create_wrapper_function(
|
||||||
tcx,
|
tcx,
|
||||||
&cx,
|
&cx,
|
||||||
"__rust_alloc_error_handler",
|
&mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
|
||||||
alloc_error_handler_name(alloc_error_handler_kind),
|
&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)),
|
||||||
&[usize, usize], // size, align
|
&[usize, usize], // size, align
|
||||||
None,
|
None,
|
||||||
true,
|
true,
|
||||||
|
@ -73,15 +74,15 @@ pub(crate) unsafe fn codegen(
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// __rust_alloc_error_handler_should_panic
|
// __rust_alloc_error_handler_should_panic
|
||||||
let name = OomStrategy::SYMBOL;
|
let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL);
|
||||||
let ll_g = cx.declare_global(name, i8);
|
let ll_g = cx.declare_global(&name, i8);
|
||||||
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
|
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
|
||||||
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
|
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||||
let llval = llvm::LLVMConstInt(i8, val as u64, False);
|
let llval = llvm::LLVMConstInt(i8, val as u64, False);
|
||||||
llvm::set_initializer(ll_g, llval);
|
llvm::set_initializer(ll_g, llval);
|
||||||
|
|
||||||
let name = NO_ALLOC_SHIM_IS_UNSTABLE;
|
let name = mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE);
|
||||||
let ll_g = cx.declare_global(name, i8);
|
let ll_g = cx.declare_global(&name, i8);
|
||||||
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
|
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
|
||||||
let llval = llvm::LLVMConstInt(i8, 0, False);
|
let llval = llvm::LLVMConstInt(i8, 0, False);
|
||||||
llvm::set_initializer(ll_g, llval);
|
llvm::set_initializer(ll_g, llval);
|
||||||
|
|
|
@ -27,6 +27,7 @@ use rustc_session::config::{
|
||||||
};
|
};
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
use rustc_span::{DUMMY_SP, Span};
|
use rustc_span::{DUMMY_SP, Span};
|
||||||
|
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||||
use rustc_target::spec::{HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel};
|
use rustc_target::spec::{HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
|
@ -1199,7 +1200,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||||
Some(def_id) => self.get_static(def_id),
|
Some(def_id) => self.get_static(def_id),
|
||||||
_ => {
|
_ => {
|
||||||
let ty = self.type_struct(&[self.type_ptr(), self.type_ptr()], false);
|
let ty = self.type_struct(&[self.type_ptr(), self.type_ptr()], false);
|
||||||
self.declare_global("rust_eh_catch_typeinfo", ty)
|
self.declare_global(&mangle_internal_symbol(self.tcx, "rust_eh_catch_typeinfo"), ty)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.eh_catch_typeinfo.set(Some(eh_catch_typeinfo));
|
self.eh_catch_typeinfo.set(Some(eh_catch_typeinfo));
|
||||||
|
|
|
@ -14,6 +14,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf};
|
||||||
use rustc_middle::ty::{self, GenericArgsRef, Ty};
|
use rustc_middle::ty::{self, GenericArgsRef, Ty};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_span::{Span, Symbol, sym};
|
use rustc_span::{Span, Symbol, sym};
|
||||||
|
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||||
use rustc_target::callconv::{FnAbi, PassMode};
|
use rustc_target::callconv::{FnAbi, PassMode};
|
||||||
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
|
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
@ -812,7 +813,10 @@ fn codegen_msvc_try<'ll>(
|
||||||
let type_name = bx.const_bytes(b"rust_panic\0");
|
let type_name = bx.const_bytes(b"rust_panic\0");
|
||||||
let type_info =
|
let type_info =
|
||||||
bx.const_struct(&[type_info_vtable, bx.const_null(bx.type_ptr()), type_name], false);
|
bx.const_struct(&[type_info_vtable, bx.const_null(bx.type_ptr()), type_name], false);
|
||||||
let tydesc = bx.declare_global("__rust_panic_type_info", bx.val_ty(type_info));
|
let tydesc = bx.declare_global(
|
||||||
|
&mangle_internal_symbol(bx.tcx, "__rust_panic_type_info"),
|
||||||
|
bx.val_ty(type_info),
|
||||||
|
);
|
||||||
|
|
||||||
llvm::set_linkage(tydesc, llvm::Linkage::LinkOnceODRLinkage);
|
llvm::set_linkage(tydesc, llvm::Linkage::LinkOnceODRLinkage);
|
||||||
if bx.cx.tcx.sess.target.supports_comdat() {
|
if bx.cx.tcx.sess.target.supports_comdat() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::hash_map::Entry::*;
|
use std::collections::hash_map::Entry::*;
|
||||||
|
|
||||||
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE};
|
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name};
|
||||||
use rustc_data_structures::unord::UnordMap;
|
use rustc_data_structures::unord::UnordMap;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId};
|
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId};
|
||||||
|
@ -13,6 +13,7 @@ use rustc_middle::query::LocalCrate;
|
||||||
use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolName, Ty, TyCtxt};
|
use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolName, Ty, TyCtxt};
|
||||||
use rustc_middle::util::Providers;
|
use rustc_middle::util::Providers;
|
||||||
use rustc_session::config::{CrateType, OomStrategy};
|
use rustc_session::config::{CrateType, OomStrategy};
|
||||||
|
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||||
use rustc_target::callconv::Conv;
|
use rustc_target::callconv::Conv;
|
||||||
use rustc_target::spec::{SanitizerSet, TlsModel};
|
use rustc_target::spec::{SanitizerSet, TlsModel};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
@ -219,8 +220,11 @@ fn exported_symbols_provider_local(
|
||||||
if allocator_kind_for_codegen(tcx).is_some() {
|
if allocator_kind_for_codegen(tcx).is_some() {
|
||||||
for symbol_name in ALLOCATOR_METHODS
|
for symbol_name in ALLOCATOR_METHODS
|
||||||
.iter()
|
.iter()
|
||||||
.map(|method| format!("__rust_{}", method.name))
|
.map(|method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str()))
|
||||||
.chain(["__rust_alloc_error_handler".to_string(), OomStrategy::SYMBOL.to_string()])
|
.chain([
|
||||||
|
mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
|
||||||
|
mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
|
||||||
|
])
|
||||||
{
|
{
|
||||||
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));
|
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));
|
||||||
|
|
||||||
|
@ -234,8 +238,10 @@ fn exported_symbols_provider_local(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let exported_symbol =
|
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(
|
||||||
ExportedSymbol::NoDefId(SymbolName::new(tcx, NO_ALLOC_SHIM_IS_UNSTABLE));
|
tcx,
|
||||||
|
&mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE),
|
||||||
|
));
|
||||||
symbols.push((
|
symbols.push((
|
||||||
exported_symbol,
|
exported_symbol,
|
||||||
SymbolExportInfo {
|
SymbolExportInfo {
|
||||||
|
|
|
@ -28,6 +28,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_session::config::{self, CrateType, EntryFnType, OutputType};
|
use rustc_session::config::{self, CrateType, EntryFnType, OutputType};
|
||||||
use rustc_span::{DUMMY_SP, Symbol, sym};
|
use rustc_span::{DUMMY_SP, Symbol, sym};
|
||||||
|
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||||
use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt};
|
use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt};
|
||||||
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
|
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
|
||||||
use tracing::{debug, info};
|
use tracing::{debug, info};
|
||||||
|
@ -989,7 +990,12 @@ impl CrateInfo {
|
||||||
.for_each(|(_, linked_symbols)| {
|
.for_each(|(_, linked_symbols)| {
|
||||||
let mut symbols = missing_weak_lang_items
|
let mut symbols = missing_weak_lang_items
|
||||||
.iter()
|
.iter()
|
||||||
.map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text))
|
.map(|item| {
|
||||||
|
(
|
||||||
|
format!("{prefix}{}", mangle_internal_symbol(tcx, item.as_str())),
|
||||||
|
SymbolExportKind::Text,
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
symbols.sort_unstable_by(|a, b| a.0.cmp(&b.0));
|
symbols.sort_unstable_by(|a, b| a.0.cmp(&b.0));
|
||||||
linked_symbols.extend(symbols);
|
linked_symbols.extend(symbols);
|
||||||
|
@ -1002,7 +1008,13 @@ impl CrateInfo {
|
||||||
// errors.
|
// errors.
|
||||||
linked_symbols.extend(ALLOCATOR_METHODS.iter().map(|method| {
|
linked_symbols.extend(ALLOCATOR_METHODS.iter().map(|method| {
|
||||||
(
|
(
|
||||||
format!("{prefix}{}", global_fn_name(method.name).as_str()),
|
format!(
|
||||||
|
"{prefix}{}",
|
||||||
|
mangle_internal_symbol(
|
||||||
|
tcx,
|
||||||
|
global_fn_name(method.name).as_str()
|
||||||
|
)
|
||||||
|
),
|
||||||
SymbolExportKind::Text,
|
SymbolExportKind::Text,
|
||||||
)
|
)
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -601,24 +601,18 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
||||||
// strippable by the linker.
|
// strippable by the linker.
|
||||||
//
|
//
|
||||||
// Additionally weak lang items have predetermined symbol names.
|
// Additionally weak lang items have predetermined symbol names.
|
||||||
if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
|
|
||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
|
||||||
}
|
|
||||||
if let Some((name, _)) = lang_items::extract(attrs)
|
if let Some((name, _)) = lang_items::extract(attrs)
|
||||||
&& let Some(lang_item) = LangItem::from_name(name)
|
&& let Some(lang_item) = LangItem::from_name(name)
|
||||||
&& let Some(link_name) = lang_item.link_name()
|
|
||||||
{
|
{
|
||||||
|
if WEAK_LANG_ITEMS.iter().any(|&l| l == lang_item) {
|
||||||
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
||||||
|
}
|
||||||
|
if let Some(link_name) = lang_item.link_name() {
|
||||||
codegen_fn_attrs.export_name = Some(link_name);
|
codegen_fn_attrs.export_name = Some(link_name);
|
||||||
codegen_fn_attrs.link_name = Some(link_name);
|
codegen_fn_attrs.link_name = Some(link_name);
|
||||||
}
|
}
|
||||||
check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
|
|
||||||
|
|
||||||
// Internal symbols to the standard library all have no_mangle semantics in
|
|
||||||
// that they have defined symbol names present in the function name. This
|
|
||||||
// also applies to weak symbols where they all have known symbol names.
|
|
||||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
|
|
||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
|
|
||||||
}
|
}
|
||||||
|
check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
|
||||||
|
|
||||||
// Any linkage to LLVM intrinsics for now forcibly marks them all as never
|
// Any linkage to LLVM intrinsics for now forcibly marks them all as never
|
||||||
// unwinds since LLVM sometimes can't handle codegen which `invoke`s
|
// unwinds since LLVM sometimes can't handle codegen which `invoke`s
|
||||||
|
|
|
@ -174,6 +174,7 @@ impl CodegenFnAttrs {
|
||||||
/// * `#[linkage]` is present
|
/// * `#[linkage]` is present
|
||||||
pub fn contains_extern_indicator(&self) -> bool {
|
pub fn contains_extern_indicator(&self) -> bool {
|
||||||
self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
|
self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
|
||||||
|
|| self.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
|
||||||
|| self.export_name.is_some()
|
|| self.export_name.is_some()
|
||||||
|| match self.linkage {
|
|| match self.linkage {
|
||||||
// These are private, so make sure we don't try to consider
|
// These are private, so make sure we don't try to consider
|
||||||
|
|
|
@ -2203,7 +2203,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
|
|
||||||
fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) {
|
fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) {
|
||||||
match target {
|
match target {
|
||||||
Target::Fn | Target::Static => {}
|
Target::Fn | Target::Static | Target::ForeignFn | Target::ForeignStatic => {}
|
||||||
_ => {
|
_ => {
|
||||||
self.tcx
|
self.tcx
|
||||||
.dcx()
|
.dcx()
|
||||||
|
|
|
@ -184,9 +184,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
||||||
CodegenFnAttrs::EMPTY
|
CodegenFnAttrs::EMPTY
|
||||||
};
|
};
|
||||||
let is_extern = codegen_attrs.contains_extern_indicator();
|
let is_extern = codegen_attrs.contains_extern_indicator();
|
||||||
let std_internal =
|
if is_extern {
|
||||||
codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
|
|
||||||
if is_extern || std_internal {
|
|
||||||
self.reachable_symbols.insert(search_item);
|
self.reachable_symbols.insert(search_item);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -426,7 +424,6 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||||
}
|
}
|
||||||
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
|
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
|
||||||
codegen_attrs.contains_extern_indicator()
|
codegen_attrs.contains_extern_indicator()
|
||||||
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
|
|
||||||
// FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by
|
// FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by
|
||||||
// `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their
|
// `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their
|
||||||
// `SymbolExportLevel::Rust` export level but may end up being exported in dylibs.
|
// `SymbolExportLevel::Rust` export level but may end up being exported in dylibs.
|
||||||
|
|
|
@ -112,6 +112,8 @@ mod v0;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod test;
|
pub mod test;
|
||||||
|
|
||||||
|
pub use v0::mangle_internal_symbol;
|
||||||
|
|
||||||
/// This function computes the symbol name for the given `instance` and the
|
/// This function computes the symbol name for the given `instance` and the
|
||||||
/// given instantiating crate. That is, if you know that instance X is
|
/// given instantiating crate. That is, if you know that instance X is
|
||||||
/// instantiated in crate Y, this is the symbol name this instance would have.
|
/// instantiated in crate Y, this is the symbol name this instance would have.
|
||||||
|
@ -183,6 +185,39 @@ fn compute_symbol_name<'tcx>(
|
||||||
CodegenFnAttrs::EMPTY
|
CodegenFnAttrs::EMPTY
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
|
||||||
|
// Items marked as #[rustc_std_internal_symbol] need to have a fixed
|
||||||
|
// symbol name because it is used to import items from another crate
|
||||||
|
// without a direct dependency. As such it is not possible to look up
|
||||||
|
// the mangled name for the `Instance` from the crate metadata of the
|
||||||
|
// defining crate.
|
||||||
|
// Weak lang items automatically get #[rustc_std_internal_symbol]
|
||||||
|
// applied by the code computing the CodegenFnAttrs.
|
||||||
|
// We are mangling all #[rustc_std_internal_symbol] items that don't
|
||||||
|
// also have #[no_mangle] as a combination of the rustc version and the
|
||||||
|
// unmangled linkage name. This is to ensure that if we link against a
|
||||||
|
// staticlib compiled by a different rustc version, we don't get symbol
|
||||||
|
// conflicts or even UB due to a different implementation/ABI. Rust
|
||||||
|
// staticlibs currently export all symbols, including those that are
|
||||||
|
// hidden in cdylibs.
|
||||||
|
// We are using the v0 symbol mangling scheme here as we need to be
|
||||||
|
// consistent across all crates and in some contexts the legacy symbol
|
||||||
|
// mangling scheme can't be used. For example both the GCC backend and
|
||||||
|
// Rust-for-Linux don't support some of the characters used by the
|
||||||
|
// legacy symbol mangling scheme.
|
||||||
|
let name = if tcx.is_foreign_item(def_id) {
|
||||||
|
if let Some(name) = attrs.link_name { name } else { tcx.item_name(def_id) }
|
||||||
|
} else {
|
||||||
|
if let Some(name) = attrs.export_name { name } else { tcx.item_name(def_id) }
|
||||||
|
};
|
||||||
|
|
||||||
|
if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) {
|
||||||
|
return name.to_string();
|
||||||
|
} else {
|
||||||
|
return v0::mangle_internal_symbol(tcx, name.as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Foreign items by default use no mangling for their symbol name. There's a
|
// Foreign items by default use no mangling for their symbol name. There's a
|
||||||
// few exceptions to this rule though:
|
// few exceptions to this rule though:
|
||||||
//
|
//
|
||||||
|
@ -198,6 +233,8 @@ fn compute_symbol_name<'tcx>(
|
||||||
// is present we mangle everything on wasm because the demangled form will
|
// is present we mangle everything on wasm because the demangled form will
|
||||||
// show up in the `wasm-import-name` custom attribute in LLVM IR.
|
// show up in the `wasm-import-name` custom attribute in LLVM IR.
|
||||||
//
|
//
|
||||||
|
// * `#[rustc_std_internal_symbol]` mangles the symbol name in a special way
|
||||||
|
// both for exports and imports through foreign items. This is handled above.
|
||||||
// [1]: https://bugs.llvm.org/show_bug.cgi?id=44316
|
// [1]: https://bugs.llvm.org/show_bug.cgi?id=44316
|
||||||
if tcx.is_foreign_item(def_id)
|
if tcx.is_foreign_item(def_id)
|
||||||
&& (!tcx.sess.target.is_like_wasm
|
&& (!tcx.sess.target.is_like_wasm
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
use std::hash::Hasher;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
|
@ -6,6 +7,8 @@ use rustc_abi::{ExternAbi, Integer};
|
||||||
use rustc_data_structures::base_n::ToBaseN;
|
use rustc_data_structures::base_n::ToBaseN;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
|
use rustc_data_structures::stable_hasher::StableHasher;
|
||||||
|
use rustc_hashes::Hash64;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::CtorKind;
|
use rustc_hir::def::CtorKind;
|
||||||
use rustc_hir::def_id::{CrateNum, DefId};
|
use rustc_hir::def_id::{CrateNum, DefId};
|
||||||
|
@ -70,6 +73,54 @@ pub(super) fn mangle<'tcx>(
|
||||||
std::mem::take(&mut cx.out)
|
std::mem::take(&mut cx.out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mangle_internal_symbol<'tcx>(tcx: TyCtxt<'tcx>, item_name: &str) -> String {
|
||||||
|
if item_name == "rust_eh_personality" {
|
||||||
|
// rust_eh_personality must not be renamed as LLVM hard-codes the name
|
||||||
|
return "rust_eh_personality".to_owned();
|
||||||
|
} else if item_name == "__rust_no_alloc_shim_is_unstable" {
|
||||||
|
// Temporary back compat hack to give people the chance to migrate to
|
||||||
|
// include #[rustc_std_internal_symbol].
|
||||||
|
return "__rust_no_alloc_shim_is_unstable".to_owned();
|
||||||
|
}
|
||||||
|
|
||||||
|
let prefix = "_R";
|
||||||
|
let mut cx: SymbolMangler<'_> = SymbolMangler {
|
||||||
|
tcx,
|
||||||
|
start_offset: prefix.len(),
|
||||||
|
paths: FxHashMap::default(),
|
||||||
|
types: FxHashMap::default(),
|
||||||
|
consts: FxHashMap::default(),
|
||||||
|
binders: vec![],
|
||||||
|
out: String::from(prefix),
|
||||||
|
};
|
||||||
|
|
||||||
|
cx.path_append_ns(
|
||||||
|
|cx| {
|
||||||
|
cx.push("C");
|
||||||
|
cx.push_disambiguator({
|
||||||
|
let mut hasher = StableHasher::new();
|
||||||
|
// Incorporate the rustc version to ensure #[rustc_std_internal_symbol] functions
|
||||||
|
// get a different symbol name depending on the rustc version.
|
||||||
|
//
|
||||||
|
// RUSTC_FORCE_RUSTC_VERSION is ignored here as otherwise different we would get an
|
||||||
|
// abi incompatibility with the standard library.
|
||||||
|
hasher.write(tcx.sess.cfg_version.as_bytes());
|
||||||
|
|
||||||
|
let hash: Hash64 = hasher.finish();
|
||||||
|
hash.as_u64()
|
||||||
|
});
|
||||||
|
cx.push_ident("__rustc");
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
'v',
|
||||||
|
0,
|
||||||
|
item_name,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
std::mem::take(&mut cx.out)
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn mangle_typeid_for_trait_ref<'tcx>(
|
pub(super) fn mangle_typeid_for_trait_ref<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_ref: ty::ExistentialTraitRef<'tcx>,
|
trait_ref: ty::ExistentialTraitRef<'tcx>,
|
||||||
|
|
|
@ -10,25 +10,28 @@ use core::ptr::{self, NonNull};
|
||||||
|
|
||||||
unsafe extern "Rust" {
|
unsafe extern "Rust" {
|
||||||
// These are the magic symbols to call the global allocator. rustc generates
|
// These are the magic symbols to call the global allocator. rustc generates
|
||||||
// them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute
|
// them to call the global allocator if there is a `#[global_allocator]` attribute
|
||||||
// (the code expanding that attribute macro generates those functions), or to call
|
// (the code expanding that attribute macro generates those functions), or to call
|
||||||
// the default implementations in std (`__rdl_alloc` etc. in `library/std/src/alloc.rs`)
|
// the default implementations in std (`__rdl_alloc` etc. in `library/std/src/alloc.rs`)
|
||||||
// otherwise.
|
// otherwise.
|
||||||
// The rustc fork of LLVM 14 and earlier also special-cases these function names to be able to optimize them
|
|
||||||
// like `malloc`, `realloc`, and `free`, respectively.
|
|
||||||
#[rustc_allocator]
|
#[rustc_allocator]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
|
||||||
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
|
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
|
||||||
#[rustc_deallocator]
|
#[rustc_deallocator]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
|
||||||
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
|
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
|
||||||
#[rustc_reallocator]
|
#[rustc_reallocator]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
|
||||||
fn __rust_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8;
|
fn __rust_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8;
|
||||||
#[rustc_allocator_zeroed]
|
#[rustc_allocator_zeroed]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
|
||||||
fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
|
fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
|
||||||
|
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
|
||||||
static __rust_no_alloc_shim_is_unstable: u8;
|
static __rust_no_alloc_shim_is_unstable: u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,6 +360,7 @@ unsafe extern "Rust" {
|
||||||
// This is the magic symbol to call the global alloc error handler. rustc generates
|
// This is the magic symbol to call the global alloc error handler. rustc generates
|
||||||
// it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the
|
// it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the
|
||||||
// default implementations below (`__rdl_oom`) otherwise.
|
// default implementations below (`__rdl_oom`) otherwise.
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
|
||||||
fn __rust_alloc_error_handler(size: usize, align: usize) -> !;
|
fn __rust_alloc_error_handler(size: usize, align: usize) -> !;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,6 +427,7 @@ pub mod __alloc_error_handler {
|
||||||
unsafe extern "Rust" {
|
unsafe extern "Rust" {
|
||||||
// This symbol is emitted by rustc next to __rust_alloc_error_handler.
|
// This symbol is emitted by rustc next to __rust_alloc_error_handler.
|
||||||
// Its value depends on the -Zoom={panic,abort} compiler option.
|
// Its value depends on the -Zoom={panic,abort} compiler option.
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
|
||||||
static __rust_alloc_error_handler_should_panic: u8;
|
static __rust_alloc_error_handler_should_panic: u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,9 +79,11 @@ cfg_if::cfg_if! {
|
||||||
unsafe extern "C" {
|
unsafe extern "C" {
|
||||||
/// Handler in std called when a panic object is dropped outside of
|
/// Handler in std called when a panic object is dropped outside of
|
||||||
/// `catch_unwind`.
|
/// `catch_unwind`.
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
|
||||||
fn __rust_drop_panic() -> !;
|
fn __rust_drop_panic() -> !;
|
||||||
|
|
||||||
/// Handler in std called when a foreign exception is caught.
|
/// Handler in std called when a foreign exception is caught.
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
|
||||||
fn __rust_foreign_exception() -> !;
|
fn __rust_foreign_exception() -> !;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -348,6 +348,7 @@ fn default_alloc_error_hook(layout: Layout) {
|
||||||
unsafe extern "Rust" {
|
unsafe extern "Rust" {
|
||||||
// This symbol is emitted by rustc next to __rust_alloc_error_handler.
|
// This symbol is emitted by rustc next to __rust_alloc_error_handler.
|
||||||
// Its value depends on the -Zoom={panic,abort} compiler option.
|
// Its value depends on the -Zoom={panic,abort} compiler option.
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
|
||||||
static __rust_alloc_error_handler_should_panic: u8;
|
static __rust_alloc_error_handler_should_panic: u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,12 +55,14 @@ pub static EMPTY_PANIC: fn(&'static str) -> ! =
|
||||||
// hook up these functions, but it is not this day!
|
// hook up these functions, but it is not this day!
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
unsafe extern "C" {
|
unsafe extern "C" {
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
|
||||||
fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static);
|
fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "Rust" {
|
unsafe extern "Rust" {
|
||||||
/// `PanicPayload` lazily performs allocation only when needed (this avoids
|
/// `PanicPayload` lazily performs allocation only when needed (this avoids
|
||||||
/// allocations when using the "abort" panic runtime).
|
/// allocations when using the "abort" panic runtime).
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
|
||||||
fn __rust_start_panic(payload: &mut dyn PanicPayload) -> u32;
|
fn __rust_start_panic(payload: &mut dyn PanicPayload) -> u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,7 @@ extern crate rustc_index;
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
extern crate rustc_session;
|
extern crate rustc_session;
|
||||||
extern crate rustc_span;
|
extern crate rustc_span;
|
||||||
|
extern crate rustc_symbol_mangling;
|
||||||
extern crate rustc_target;
|
extern crate rustc_target;
|
||||||
// Linking `rustc_driver` pulls in the required object code as the rest of the rustc crates are
|
// Linking `rustc_driver` pulls in the required object code as the rest of the rustc crates are
|
||||||
// shipped only as rmeta files.
|
// shipped only as rmeta files.
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
//! Provides the `extern static` that this platform expects.
|
//! Provides the `extern static` that this platform expects.
|
||||||
|
|
||||||
|
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
impl<'tcx> MiriMachine<'tcx> {
|
impl<'tcx> MiriMachine<'tcx> {
|
||||||
|
@ -50,7 +52,11 @@ impl<'tcx> MiriMachine<'tcx> {
|
||||||
// "__rust_alloc_error_handler_should_panic"
|
// "__rust_alloc_error_handler_should_panic"
|
||||||
let val = ecx.tcx.sess.opts.unstable_opts.oom.should_panic();
|
let val = ecx.tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||||
let val = ImmTy::from_int(val, ecx.machine.layouts.u8);
|
let val = ImmTy::from_int(val, ecx.machine.layouts.u8);
|
||||||
Self::alloc_extern_static(ecx, "__rust_alloc_error_handler_should_panic", val)?;
|
Self::alloc_extern_static(
|
||||||
|
ecx,
|
||||||
|
&mangle_internal_symbol(*ecx.tcx, "__rust_alloc_error_handler_should_panic"),
|
||||||
|
val,
|
||||||
|
)?;
|
||||||
|
|
||||||
if ecx.target_os_is_unix() {
|
if ecx.target_os_is_unix() {
|
||||||
// "environ" is mandated by POSIX.
|
// "environ" is mandated by POSIX.
|
||||||
|
|
|
@ -12,6 +12,7 @@ use rustc_middle::mir::interpret::AllocInit;
|
||||||
use rustc_middle::ty::Ty;
|
use rustc_middle::ty::Ty;
|
||||||
use rustc_middle::{mir, ty};
|
use rustc_middle::{mir, ty};
|
||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
|
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||||
use rustc_target::callconv::{Conv, FnAbi};
|
use rustc_target::callconv::{Conv, FnAbi};
|
||||||
|
|
||||||
use self::helpers::{ToHost, ToSoft};
|
use self::helpers::{ToHost, ToSoft};
|
||||||
|
@ -51,7 +52,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||||
|
|
||||||
// Some shims forward to other MIR bodies.
|
// Some shims forward to other MIR bodies.
|
||||||
match link_name.as_str() {
|
match link_name.as_str() {
|
||||||
"__rust_alloc_error_handler" => {
|
name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc_error_handler") => {
|
||||||
// Forward to the right symbol that implements this function.
|
// Forward to the right symbol that implements this function.
|
||||||
let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else {
|
let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else {
|
||||||
// in real code, this symbol does not exist without an allocator
|
// in real code, this symbol does not exist without an allocator
|
||||||
|
@ -59,9 +60,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||||
"`__rust_alloc_error_handler` cannot be called when no alloc error handler is set"
|
"`__rust_alloc_error_handler` cannot be called when no alloc error handler is set"
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
let name = alloc_error_handler_name(handler_kind);
|
let name =
|
||||||
|
mangle_internal_symbol(*this.tcx, alloc_error_handler_name(handler_kind));
|
||||||
let handler = this
|
let handler = this
|
||||||
.lookup_exported_symbol(Symbol::intern(name))?
|
.lookup_exported_symbol(Symbol::intern(&name))?
|
||||||
.expect("missing alloc error handler symbol");
|
.expect("missing alloc error handler symbol");
|
||||||
return interp_ok(Some(handler));
|
return interp_ok(Some(handler));
|
||||||
}
|
}
|
||||||
|
@ -136,15 +138,29 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||||
// Find it if it was not cached.
|
// Find it if it was not cached.
|
||||||
let mut instance_and_crate: Option<(ty::Instance<'_>, CrateNum)> = None;
|
let mut instance_and_crate: Option<(ty::Instance<'_>, CrateNum)> = None;
|
||||||
helpers::iter_exported_symbols(tcx, |cnum, def_id| {
|
helpers::iter_exported_symbols(tcx, |cnum, def_id| {
|
||||||
|
if tcx.is_foreign_item(def_id) {
|
||||||
|
// Skip over imports of items
|
||||||
|
return interp_ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let attrs = tcx.codegen_fn_attrs(def_id);
|
let attrs = tcx.codegen_fn_attrs(def_id);
|
||||||
|
// FIXME use tcx.symbol_name(instance) instead
|
||||||
let symbol_name = if let Some(export_name) = attrs.export_name {
|
let symbol_name = if let Some(export_name) = attrs.export_name {
|
||||||
export_name
|
export_name
|
||||||
} else if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) {
|
} else if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
|
||||||
|
|| attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
|
||||||
|
{
|
||||||
tcx.item_name(def_id)
|
tcx.item_name(def_id)
|
||||||
} else {
|
} else {
|
||||||
// Skip over items without an explicitly defined symbol name.
|
// Skip over items without an explicitly defined symbol name.
|
||||||
return interp_ok(());
|
return interp_ok(());
|
||||||
};
|
};
|
||||||
|
let symbol_name =
|
||||||
|
if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
|
||||||
|
Symbol::intern(&mangle_internal_symbol(tcx, symbol_name.as_str()))
|
||||||
|
} else {
|
||||||
|
symbol_name
|
||||||
|
};
|
||||||
if symbol_name == link_name {
|
if symbol_name == link_name {
|
||||||
if let Some((original_instance, original_cnum)) = instance_and_crate {
|
if let Some((original_instance, original_cnum)) = instance_and_crate {
|
||||||
// Make sure we are consistent wrt what is 'first' and 'second'.
|
// Make sure we are consistent wrt what is 'first' and 'second'.
|
||||||
|
@ -489,7 +505,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rust allocation
|
// Rust allocation
|
||||||
"__rust_alloc" | "miri_alloc" => {
|
name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc")
|
||||||
|
|| name == "miri_alloc" =>
|
||||||
|
{
|
||||||
let default = |ecx: &mut MiriInterpCx<'tcx>| {
|
let default = |ecx: &mut MiriInterpCx<'tcx>| {
|
||||||
// Only call `check_shim` when `#[global_allocator]` isn't used. When that
|
// Only call `check_shim` when `#[global_allocator]` isn't used. When that
|
||||||
// macro is used, we act like no shim exists, so that the exported function can run.
|
// 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> {
|
||||||
ecx.check_rustc_alloc_request(size, align)?;
|
ecx.check_rustc_alloc_request(size, align)?;
|
||||||
|
|
||||||
let memory_kind = match link_name.as_str() {
|
let memory_kind = match link_name.as_str() {
|
||||||
"__rust_alloc" => MiriMemoryKind::Rust,
|
|
||||||
"miri_alloc" => MiriMemoryKind::Miri,
|
"miri_alloc" => MiriMemoryKind::Miri,
|
||||||
_ => unreachable!(),
|
_ => MiriMemoryKind::Rust,
|
||||||
};
|
};
|
||||||
|
|
||||||
let ptr = ecx.allocate_ptr(
|
let ptr = ecx.allocate_ptr(
|
||||||
|
@ -516,15 +533,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
match link_name.as_str() {
|
match link_name.as_str() {
|
||||||
"__rust_alloc" => return this.emulate_allocator(default),
|
|
||||||
"miri_alloc" => {
|
"miri_alloc" => {
|
||||||
default(this)?;
|
default(this)?;
|
||||||
return interp_ok(EmulateItemResult::NeedsReturn);
|
return interp_ok(EmulateItemResult::NeedsReturn);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => return this.emulate_allocator(default),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"__rust_alloc_zeroed" => {
|
name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc_zeroed") => {
|
||||||
return this.emulate_allocator(|this| {
|
return this.emulate_allocator(|this| {
|
||||||
// See the comment for `__rust_alloc` why `check_shim` is only called in the
|
// See the comment for `__rust_alloc` why `check_shim` is only called in the
|
||||||
// default case.
|
// default case.
|
||||||
|
@ -543,7 +559,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||||
this.write_pointer(ptr, dest)
|
this.write_pointer(ptr, dest)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
"__rust_dealloc" | "miri_dealloc" => {
|
name if name == mangle_internal_symbol(*this.tcx, "__rust_dealloc")
|
||||||
|
|| name == "miri_dealloc" =>
|
||||||
|
{
|
||||||
let default = |ecx: &mut MiriInterpCx<'tcx>| {
|
let default = |ecx: &mut MiriInterpCx<'tcx>| {
|
||||||
// See the comment for `__rust_alloc` why `check_shim` is only called in the
|
// See the comment for `__rust_alloc` why `check_shim` is only called in the
|
||||||
// default case.
|
// default case.
|
||||||
|
@ -554,9 +572,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||||
let align = ecx.read_target_usize(align)?;
|
let align = ecx.read_target_usize(align)?;
|
||||||
|
|
||||||
let memory_kind = match link_name.as_str() {
|
let memory_kind = match link_name.as_str() {
|
||||||
"__rust_dealloc" => MiriMemoryKind::Rust,
|
|
||||||
"miri_dealloc" => MiriMemoryKind::Miri,
|
"miri_dealloc" => MiriMemoryKind::Miri,
|
||||||
_ => unreachable!(),
|
_ => MiriMemoryKind::Rust,
|
||||||
};
|
};
|
||||||
|
|
||||||
// No need to check old_size/align; we anyway check that they match the allocation.
|
// 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> {
|
||||||
};
|
};
|
||||||
|
|
||||||
match link_name.as_str() {
|
match link_name.as_str() {
|
||||||
"__rust_dealloc" => {
|
|
||||||
return this.emulate_allocator(default);
|
|
||||||
}
|
|
||||||
"miri_dealloc" => {
|
"miri_dealloc" => {
|
||||||
default(this)?;
|
default(this)?;
|
||||||
return interp_ok(EmulateItemResult::NeedsReturn);
|
return interp_ok(EmulateItemResult::NeedsReturn);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => return this.emulate_allocator(default),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"__rust_realloc" => {
|
name if name == mangle_internal_symbol(*this.tcx, "__rust_realloc") => {
|
||||||
return this.emulate_allocator(|this| {
|
return this.emulate_allocator(|this| {
|
||||||
// See the comment for `__rust_alloc` why `check_shim` is only called in the
|
// See the comment for `__rust_alloc` why `check_shim` is only called in the
|
||||||
// default case.
|
// default case.
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
|
#[rustc_std_internal_symbol]
|
||||||
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
|
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
// because rustc does not support alignments that large.
|
// because rustc does not support alignments that large.
|
||||||
// https://github.com/rust-lang/miri/issues/3687
|
// https://github.com/rust-lang/miri/issues/3687
|
||||||
|
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
|
#[rustc_std_internal_symbol]
|
||||||
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
|
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
// Test non-power-of-two alignment.
|
// Test non-power-of-two alignment.
|
||||||
|
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
|
#[rustc_std_internal_symbol]
|
||||||
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
|
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
// Avoid accidental synchronization via address reuse inside `thread::spawn`.
|
// Avoid accidental synchronization via address reuse inside `thread::spawn`.
|
||||||
//@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
|
//@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
|
||||||
|
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
use std::thread::spawn;
|
use std::thread::spawn;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {}
|
||||||
unsafe impl<T> Sync for EvilSend<T> {}
|
unsafe impl<T> Sync for EvilSend<T> {}
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
|
#[rustc_std_internal_symbol]
|
||||||
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
|
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
// Avoid accidental synchronization via address reuse inside `thread::spawn`.
|
// Avoid accidental synchronization via address reuse inside `thread::spawn`.
|
||||||
//@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
|
//@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
|
||||||
|
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
use std::thread::spawn;
|
use std::thread::spawn;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {}
|
||||||
unsafe impl<T> Sync for EvilSend<T> {}
|
unsafe impl<T> Sync for EvilSend<T> {}
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
|
#[rustc_std_internal_symbol]
|
||||||
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
|
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
// Avoid accidental synchronization via address reuse inside `thread::spawn`.
|
// Avoid accidental synchronization via address reuse inside `thread::spawn`.
|
||||||
//@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
|
//@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
|
||||||
|
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
use std::thread::spawn;
|
use std::thread::spawn;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {}
|
||||||
unsafe impl<T> Sync for EvilSend<T> {}
|
unsafe impl<T> Sync for EvilSend<T> {}
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
|
#[rustc_std_internal_symbol]
|
||||||
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
|
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
|
||||||
}
|
}
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
// Avoid accidental synchronization via address reuse inside `thread::spawn`.
|
// Avoid accidental synchronization via address reuse inside `thread::spawn`.
|
||||||
//@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
|
//@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
|
||||||
|
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
use std::thread::spawn;
|
use std::thread::spawn;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {}
|
||||||
unsafe impl<T> Sync for EvilSend<T> {}
|
unsafe impl<T> Sync for EvilSend<T> {}
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
|
#[rustc_std_internal_symbol]
|
||||||
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
|
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
|
||||||
}
|
}
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
|
|
@ -40,6 +40,7 @@ fn main() {
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
fn bar() -> i32;
|
fn bar() -> i32;
|
||||||
|
#[rustc_std_internal_symbol]
|
||||||
fn baz() -> i32;
|
fn baz() -> i32;
|
||||||
fn qux() -> i32;
|
fn qux() -> i32;
|
||||||
}
|
}
|
||||||
|
@ -63,6 +64,7 @@ fn main() {
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn bar() -> i32;
|
fn bar() -> i32;
|
||||||
|
#[rustc_std_internal_symbol]
|
||||||
fn baz() -> i32;
|
fn baz() -> i32;
|
||||||
fn qux() -> i32;
|
fn qux() -> i32;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
pub fn alloc_test(data: u32) {
|
pub fn alloc_test(data: u32) {
|
||||||
// CHECK-LABEL: @alloc_test
|
// CHECK-LABEL: @alloc_test
|
||||||
// CHECK-NEXT: start:
|
// CHECK-NEXT: start:
|
||||||
// CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1
|
// CHECK-NEXT: {{.*}} load volatile i8, ptr @{{.*}}__rust_no_alloc_shim_is_unstable, align 1
|
||||||
// CHECK-NEXT: ret void
|
// CHECK-NEXT: ret void
|
||||||
let x = Box::new(data);
|
let x = Box::new(data);
|
||||||
drop(x);
|
drop(x);
|
||||||
|
|
|
@ -41,6 +41,6 @@ pub fn box_lotsa_padding() -> Box<LotsaPadding> {
|
||||||
|
|
||||||
// Hide the `allocalign` attribute in the declaration of __rust_alloc
|
// Hide the `allocalign` attribute in the declaration of __rust_alloc
|
||||||
// from the CHECK-NOT above, and also verify the attributes got set reasonably.
|
// from the CHECK-NOT above, and also verify the attributes got set reasonably.
|
||||||
// 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]+]]
|
// 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]+]]
|
||||||
|
|
||||||
// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) {{(uwtable )?}}"alloc-family"="__rust_alloc" {{.*}} }
|
// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) {{(uwtable )?}}"alloc-family"="__rust_alloc" {{.*}} }
|
||||||
|
|
|
@ -18,7 +18,7 @@ impl Drop for A {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn a(a: Box<i32>) {
|
pub fn a(a: Box<i32>) {
|
||||||
// CHECK-LABEL: define{{.*}}void @a
|
// CHECK-LABEL: define{{.*}}void @a
|
||||||
// CHECK: call void @__rust_dealloc
|
// CHECK: call void @{{.*}}__rust_dealloc
|
||||||
// CHECK-NEXT: call void @foo
|
// CHECK-NEXT: call void @foo
|
||||||
let _a = A;
|
let _a = A;
|
||||||
drop(a);
|
drop(a);
|
||||||
|
|
|
@ -47,7 +47,7 @@ pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN<NotCopy>) -> Option<NotCop
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
// CHECK-LABEL: @vec_extend_via_iter_repeat_n
|
// CHECK-LABEL: @vec_extend_via_iter_repeat_n
|
||||||
pub fn vec_extend_via_iter_repeat_n() -> Vec<u8> {
|
pub fn vec_extend_via_iter_repeat_n() -> Vec<u8> {
|
||||||
// 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)
|
// 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)
|
||||||
// CHECK: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(1234) %[[ADDR]], i8 42, i64 1234,
|
// CHECK: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(1234) %[[ADDR]], i8 42, i64 1234,
|
||||||
|
|
||||||
let n = 1234_usize;
|
let n = 1234_usize;
|
||||||
|
|
|
@ -177,6 +177,6 @@ pub fn vec_option_i32(n: usize) -> Vec<Option<i32>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that __rust_alloc_zeroed gets the right attributes for LLVM to optimize it away.
|
// Ensure that __rust_alloc_zeroed gets the right attributes for LLVM to optimize it away.
|
||||||
// CHECK: declare noalias noundef ptr @__rust_alloc_zeroed(i64 noundef, i64 allocalign noundef) unnamed_addr [[RUST_ALLOC_ZEROED_ATTRS:#[0-9]+]]
|
// CHECK: declare noalias noundef ptr @{{.*}}__rust_alloc_zeroed(i64 noundef, i64 allocalign noundef) unnamed_addr [[RUST_ALLOC_ZEROED_ATTRS:#[0-9]+]]
|
||||||
|
|
||||||
// CHECK-DAG: attributes [[RUST_ALLOC_ZEROED_ATTRS]] = { {{.*}} allockind("alloc,zeroed,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} }
|
// CHECK-DAG: attributes [[RUST_ALLOC_ZEROED_ATTRS]] = { {{.*}} allockind("alloc,zeroed,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} }
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
pub fn sum_me() -> i32 {
|
pub fn sum_me() -> i32 {
|
||||||
// CHECK-LABEL: @sum_me
|
// CHECK-LABEL: @sum_me
|
||||||
// CHECK-NEXT: {{^.*:$}}
|
// CHECK-NEXT: {{^.*:$}}
|
||||||
// CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1
|
// CHECK-NEXT: {{.*}} load volatile i8, ptr @{{.*}}__rust_no_alloc_shim_is_unstable, align 1
|
||||||
// CHECK-NEXT: ret i32 6
|
// CHECK-NEXT: ret i32 6
|
||||||
vec![1, 2, 3].iter().sum::<i32>()
|
vec![1, 2, 3].iter().sum::<i32>()
|
||||||
}
|
}
|
||||||
|
|
1
tests/run-make/symbols-all-mangled/a_lib.rs
Normal file
1
tests/run-make/symbols-all-mangled/a_lib.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub fn public_rust_function() {}
|
3
tests/run-make/symbols-all-mangled/an_executable.rs
Normal file
3
tests/run-make/symbols-all-mangled/an_executable.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
pub fn public_rust_function_from_exe() {}
|
||||||
|
|
||||||
|
fn main() {}
|
84
tests/run-make/symbols-all-mangled/rmake.rs
Normal file
84
tests/run-make/symbols-all-mangled/rmake.rs
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// Check that all symbols in cdylibs, staticlibs and bins are mangled
|
||||||
|
//@ only-elf some object file formats create multiple symbols for each function with different names
|
||||||
|
|
||||||
|
use run_make_support::object::read::{Object, ObjectSymbol};
|
||||||
|
use run_make_support::{bin_name, dynamic_lib_name, object, rfs, rustc, static_lib_name};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let staticlib_name = static_lib_name("a_lib");
|
||||||
|
let cdylib_name = dynamic_lib_name("a_lib");
|
||||||
|
let exe_name = bin_name("an_executable");
|
||||||
|
rustc().crate_type("cdylib").input("a_lib.rs").run();
|
||||||
|
rustc().crate_type("staticlib").input("a_lib.rs").run();
|
||||||
|
rustc().crate_type("bin").input("an_executable.rs").run();
|
||||||
|
|
||||||
|
symbols_check_archive(&staticlib_name);
|
||||||
|
symbols_check(&cdylib_name);
|
||||||
|
symbols_check(&exe_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn symbols_check_archive(path: &str) {
|
||||||
|
let binary_data = rfs::read(path);
|
||||||
|
let file = object::read::archive::ArchiveFile::parse(&*binary_data).unwrap();
|
||||||
|
for symbol in file.symbols().unwrap().unwrap() {
|
||||||
|
let symbol = symbol.unwrap();
|
||||||
|
let name = strip_underscore_if_apple(std::str::from_utf8(symbol.name()).unwrap());
|
||||||
|
if name.starts_with("_ZN") || name.starts_with("_R") {
|
||||||
|
continue; // Correctly mangled
|
||||||
|
}
|
||||||
|
|
||||||
|
let member_name =
|
||||||
|
std::str::from_utf8(file.member(symbol.offset()).unwrap().name()).unwrap();
|
||||||
|
if !member_name.ends_with(".rcgu.o") || member_name.contains("compiler_builtins") {
|
||||||
|
continue; // All compiler-builtins symbols must remain unmangled
|
||||||
|
}
|
||||||
|
|
||||||
|
if name == "__rust_no_alloc_shim_is_unstable" {
|
||||||
|
continue; // FIXME remove exception once we mangle this symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
if name.contains("rust_eh_personality") {
|
||||||
|
continue; // Unfortunately LLVM doesn't allow us to mangle this symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
panic!("Unmangled symbol found: {name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn symbols_check(path: &str) {
|
||||||
|
let binary_data = rfs::read(path);
|
||||||
|
let file = object::File::parse(&*binary_data).unwrap();
|
||||||
|
for symbol in file.symbols() {
|
||||||
|
if !symbol.is_definition() || !symbol.is_global() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if symbol.is_weak() {
|
||||||
|
continue; // Likely an intrinsic from compiler-builtins
|
||||||
|
}
|
||||||
|
let name = strip_underscore_if_apple(symbol.name().unwrap());
|
||||||
|
if name.starts_with("_ZN") || name.starts_with("_R") {
|
||||||
|
continue; // Correctly mangled
|
||||||
|
}
|
||||||
|
|
||||||
|
if !name.contains("rust") {
|
||||||
|
// Assume that this symbol doesn't originate from rustc. This may
|
||||||
|
// be wrong, but even if so symbol_check_archive will likely
|
||||||
|
// catch it.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if name == "__rust_no_alloc_shim_is_unstable" {
|
||||||
|
continue; // FIXME remove exception once we mangle this symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
if name.contains("rust_eh_personality") {
|
||||||
|
continue; // Unfortunately LLVM doesn't allow us to mangle this symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
panic!("Unmangled symbol found: {name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn strip_underscore_if_apple(symbol: &str) -> &str {
|
||||||
|
if cfg!(target_vendor = "apple") { symbol.strip_prefix("_").unwrap() } else { symbol }
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue