Skip to content

Commit

Permalink
Mangle #[rustc_std_internal_symbol] to include the rustc version unle…
Browse files Browse the repository at this point in the history
…ss #[no_mangle] is used
  • Loading branch information
bjorn3 committed Nov 3, 2024
1 parent 386c90c commit aa00ee5
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
37 changes: 37 additions & 0 deletions compiler/rustc_symbol_mangling/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ mod v0;
pub mod errors;
pub mod test;

pub use v0::mangle_internal_symbol;

/// This function computes the symbol name for the given `instance` and the
/// 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.
Expand Down Expand Up @@ -183,6 +185,39 @@ fn compute_symbol_name<'tcx>(
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
// few exceptions to this rule though:
//
Expand All @@ -198,6 +233,8 @@ fn compute_symbol_name<'tcx>(
// is present we mangle everything on wasm because the demangled form will
// 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
if tcx.is_foreign_item(def_id)
&& (!tcx.sess.target.is_like_wasm
Expand Down
41 changes: 41 additions & 0 deletions compiler/rustc_symbol_mangling/src/v0.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::fmt::Write;
use std::hash::Hasher;
use std::iter;
use std::ops::Range;

use rustc_abi::Integer;
use rustc_data_structures::base_n::ToBaseN;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{Hash64, StableHasher};
use rustc_hir as hir;
use rustc_hir::def::CtorKind;
use rustc_hir::def_id::{CrateNum, DefId};
Expand Down Expand Up @@ -71,6 +73,45 @@ pub(super) fn mangle<'tcx>(
std::mem::take(&mut cx.out)
}

pub fn mangle_internal_symbol<'tcx>(tcx: TyCtxt<'tcx>, item_name: &str) -> String {
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>(
tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyExistentialTraitRef<'tcx>,
Expand Down

0 comments on commit aa00ee5

Please sign in to comment.