From 98b9d0232fce1a0fbac328a2b31393e9c77712ec Mon Sep 17 00:00:00 2001
From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date: Sat, 2 Dec 2023 13:48:06 +0000
Subject: [PATCH 1/9] Allow #[rustc_std_internal_symbol] on foreign items

---
 compiler/rustc_passes/src/check_attr.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index ece5a53aaa9c4..fb3df5b43acf1 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -2203,7 +2203,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
 
     fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) {
         match target {
-            Target::Fn | Target::Static => {}
+            Target::Fn | Target::Static | Target::ForeignFn | Target::ForeignStatic => {}
             _ => {
                 self.tcx
                     .dcx()

From 60b785fc8d2ca002189c7c4956f46e3ebe66fb63 Mon Sep 17 00:00:00 2001
From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date: Sat, 2 Dec 2023 13:50:44 +0000
Subject: [PATCH 2/9] Mark #[rustc_std_internal_symbol] as extern indicator

It currently implies #[no_mangle] which is alread an extern indicator,
but this will change in a future commit.
---
 compiler/rustc_middle/src/middle/codegen_fn_attrs.rs | 1 +
 compiler/rustc_passes/src/reachable.rs               | 5 +----
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index a94ead161c379..0cc72a261a5a3 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -174,6 +174,7 @@ impl CodegenFnAttrs {
     /// * `#[linkage]` is present
     pub fn contains_extern_indicator(&self) -> bool {
         self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
+            || self.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
             || self.export_name.is_some()
             || match self.linkage {
                 // These are private, so make sure we don't try to consider
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 599a08bac20de..b9e413a20c1aa 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -184,9 +184,7 @@ impl<'tcx> ReachableContext<'tcx> {
                 CodegenFnAttrs::EMPTY
             };
             let is_extern = codegen_attrs.contains_extern_indicator();
-            let std_internal =
-                codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
-            if is_extern || std_internal {
+            if is_extern {
                 self.reachable_symbols.insert(search_item);
             }
         } else {
@@ -426,7 +424,6 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     }
     let codegen_attrs = tcx.codegen_fn_attrs(def_id);
     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
         // `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.

From 42de015549ad6e60d6f0e603daf0948259a2840d Mon Sep 17 00:00:00 2001
From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date: Sat, 2 Dec 2023 13:52:47 +0000
Subject: [PATCH 3/9] Mark imports of #[rustc_std_internal_symbol] items with
 this attribute

This ensures that they will be correctly mangled in a future commit.
---
 library/alloc/src/alloc.rs      | 11 ++++++++---
 library/panic_unwind/src/lib.rs |  2 ++
 library/std/src/alloc.rs        |  1 +
 library/std/src/panicking.rs    |  2 ++
 4 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 2f752f6eb3940..1e03a191276ca 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -10,25 +10,28 @@ use core::ptr::{self, NonNull};
 
 unsafe extern "Rust" {
     // 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 default implementations in std (`__rdl_alloc` etc. in `library/std/src/alloc.rs`)
     // 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_nounwind]
+    #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
     fn __rust_alloc(size: usize, align: usize) -> *mut u8;
     #[rustc_deallocator]
     #[rustc_nounwind]
+    #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
     fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
     #[rustc_reallocator]
     #[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;
     #[rustc_allocator_zeroed]
     #[rustc_nounwind]
+    #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
     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;
 }
 
@@ -357,6 +360,7 @@ unsafe extern "Rust" {
     // 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
     // default implementations below (`__rdl_oom`) otherwise.
+    #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
     fn __rust_alloc_error_handler(size: usize, align: usize) -> !;
 }
 
@@ -423,6 +427,7 @@ pub mod __alloc_error_handler {
         unsafe extern "Rust" {
             // This symbol is emitted by rustc next to __rust_alloc_error_handler.
             // 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;
         }
 
diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs
index a284633ea2fc7..e5c1d6bdb3b06 100644
--- a/library/panic_unwind/src/lib.rs
+++ b/library/panic_unwind/src/lib.rs
@@ -79,9 +79,11 @@ cfg_if::cfg_if! {
 unsafe extern "C" {
     /// Handler in std called when a panic object is dropped outside of
     /// `catch_unwind`.
+    #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
     fn __rust_drop_panic() -> !;
 
     /// Handler in std called when a foreign exception is caught.
+    #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
     fn __rust_foreign_exception() -> !;
 }
 
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index 99d105a2454a5..5d2a304b41c5a 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -348,6 +348,7 @@ fn default_alloc_error_hook(layout: Layout) {
     unsafe extern "Rust" {
         // This symbol is emitted by rustc next to __rust_alloc_error_handler.
         // 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;
     }
 
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index b47b41d4bc5b7..b35549c92ada7 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -55,12 +55,14 @@ pub static EMPTY_PANIC: fn(&'static str) -> ! =
 // hook up these functions, but it is not this day!
 #[allow(improper_ctypes)]
 unsafe extern "C" {
+    #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
     fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static);
 }
 
 unsafe extern "Rust" {
     /// `PanicPayload` lazily performs allocation only when needed (this avoids
     /// allocations when using the "abort" panic runtime).
+    #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)]
     fn __rust_start_panic(payload: &mut dyn PanicPayload) -> u32;
 }
 

From c0639ef8e4b4bf9feadb8bea49d4fe23ce9e8017 Mon Sep 17 00:00:00 2001
From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date: Sat, 2 Dec 2023 14:08:49 +0000
Subject: [PATCH 4/9] Mangle #[rustc_std_internal_symbol] to include the rustc
 version unless #[no_mangle] is used

---
 compiler/rustc_symbol_mangling/src/lib.rs | 37 ++++++++++++++++++++
 compiler/rustc_symbol_mangling/src/v0.rs  | 42 +++++++++++++++++++++++
 2 files changed, 79 insertions(+)

diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index c4558b5ce8be3..c9b15151a2cb2 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -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.
@@ -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:
     //
@@ -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
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index bc3923e4b4d67..dbaeae5e9513e 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -1,4 +1,5 @@
 use std::fmt::Write;
+use std::hash::Hasher;
 use std::iter;
 use std::ops::Range;
 
@@ -6,6 +7,8 @@ use rustc_abi::{ExternAbi, 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::StableHasher;
+use rustc_hashes::Hash64;
 use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{CrateNum, DefId};
@@ -70,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::ExistentialTraitRef<'tcx>,

From b754ef727ca87050a8d758fc44f524cfb4310eff Mon Sep 17 00:00:00 2001
From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date: Sat, 2 Dec 2023 14:17:33 +0000
Subject: [PATCH 5/9] Remove implicit #[no_mangle] for
 #[rustc_std_internal_symbol]

---
 .../rustc_codegen_cranelift/src/allocator.rs  | 30 ++++++++++++++-----
 compiler/rustc_codegen_cranelift/src/lib.rs   |  1 +
 compiler/rustc_codegen_gcc/src/allocator.rs   | 13 ++++----
 compiler/rustc_codegen_gcc/src/lib.rs         |  1 +
 compiler/rustc_codegen_llvm/src/allocator.rs  | 17 ++++++-----
 compiler/rustc_codegen_llvm/src/context.rs    |  3 +-
 compiler/rustc_codegen_llvm/src/intrinsic.rs  |  6 +++-
 .../src/back/symbol_export.rs                 | 16 ++++++----
 compiler/rustc_codegen_ssa/src/base.rs        | 16 ++++++++--
 .../rustc_codegen_ssa/src/codegen_attrs.rs    | 20 +++++--------
 compiler/rustc_symbol_mangling/src/v0.rs      |  9 ++++++
 tests/codegen/alloc-optimisation.rs           |  2 +-
 tests/codegen/box-uninit-bytes.rs             |  2 +-
 tests/codegen/dealloc-no-unwind.rs            |  2 +-
 tests/codegen/iter-repeat-n-trivial-drop.rs   |  2 +-
 tests/codegen/vec-calloc.rs                   |  2 +-
 tests/codegen/vec-optimizes-away.rs           |  2 +-
 17 files changed, 95 insertions(+), 49 deletions(-)

diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs
index 5e33b9d606fa5..9cff8a84db3d9 100644
--- a/compiler/rustc_codegen_cranelift/src/allocator.rs
+++ b/compiler/rustc_codegen_cranelift/src/allocator.rs
@@ -7,6 +7,7 @@ use rustc_ast::expand::allocator::{
 };
 use rustc_codegen_ssa::base::allocator_kind_for_codegen;
 use rustc_session::config::OomStrategy;
+use rustc_symbol_mangling::mangle_internal_symbol;
 
 use crate::prelude::*;
 
@@ -14,6 +15,7 @@ use crate::prelude::*;
 pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool {
     let Some(kind) = allocator_kind_for_codegen(tcx) else { return false };
     codegen_inner(
+        tcx,
         module,
         kind,
         tcx.alloc_error_handler_kind(()).unwrap(),
@@ -23,6 +25,7 @@ pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool {
 }
 
 fn codegen_inner(
+    tcx: TyCtxt<'_>,
     module: &mut dyn Module,
     kind: AllocatorKind,
     alloc_error_handler_kind: AllocatorKind,
@@ -62,8 +65,8 @@ fn codegen_inner(
             crate::common::create_wrapper_function(
                 module,
                 sig,
-                &global_fn_name(method.name),
-                &default_fn_name(method.name),
+                &mangle_internal_symbol(tcx, &global_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(
         module,
         sig,
-        "__rust_alloc_error_handler",
-        &alloc_error_handler_name(alloc_error_handler_kind),
+        &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
+        &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();
     data.set_align(1);
     let val = oom_strategy.should_panic();
     data.define(Box::new([val]));
     module.define_data(data_id, &data).unwrap();
 
-    let data_id =
-        module.declare_data(NO_ALLOC_SHIM_IS_UNSTABLE, Linkage::Export, false, false).unwrap();
+    let data_id = module
+        .declare_data(
+            &mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE),
+            Linkage::Export,
+            false,
+            false,
+        )
+        .unwrap();
     let mut data = DataDescription::new();
     data.set_align(1);
     data.define(Box::new([0]));
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 06939beb37423..ab3386a9b4ccf 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -26,6 +26,7 @@ extern crate rustc_index;
 extern crate rustc_metadata;
 extern crate rustc_session;
 extern crate rustc_span;
+extern crate rustc_symbol_mangling;
 extern crate rustc_target;
 #[macro_use]
 extern crate tracing;
diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs
index 416f3231a13c4..f4ebd42ee2dc0 100644
--- a/compiler/rustc_codegen_gcc/src/allocator.rs
+++ b/compiler/rustc_codegen_gcc/src/allocator.rs
@@ -8,6 +8,7 @@ use rustc_ast::expand::allocator::{
 use rustc_middle::bug;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::OomStrategy;
+use rustc_symbol_mangling::mangle_internal_symbol;
 
 use crate::GccContext;
 #[cfg(feature = "master")]
@@ -53,8 +54,8 @@ pub(crate) unsafe fn codegen(
                     panic!("invalid allocator output")
                 }
             };
-            let from_name = global_fn_name(method.name);
-            let to_name = default_fn_name(method.name);
+            let from_name = mangle_internal_symbol(tcx, &global_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);
         }
@@ -64,13 +65,13 @@ pub(crate) unsafe fn codegen(
     create_wrapper_function(
         tcx,
         context,
-        "__rust_alloc_error_handler",
-        alloc_error_handler_name(alloc_error_handler_kind),
+        &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
+        &mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)),
         &[usize, usize],
         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);
     #[cfg(feature = "master")]
     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);
     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);
     #[cfg(feature = "master")]
     global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index d478b2af46c28..bfa23174a19d9 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -52,6 +52,7 @@ extern crate rustc_metadata;
 extern crate rustc_middle;
 extern crate rustc_session;
 extern crate rustc_span;
+extern crate rustc_symbol_mangling;
 extern crate rustc_target;
 
 // This prevents duplicating functions and statics that are already part of the host rustc process.
diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs
index e614115f64b9f..4a78e69497994 100644
--- a/compiler/rustc_codegen_llvm/src/allocator.rs
+++ b/compiler/rustc_codegen_llvm/src/allocator.rs
@@ -7,6 +7,7 @@ use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _;
 use rustc_middle::bug;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{DebugInfo, OomStrategy};
+use rustc_symbol_mangling::mangle_internal_symbol;
 
 use crate::builder::SBuilder;
 use crate::declare::declare_simple_fn;
@@ -53,8 +54,8 @@ pub(crate) unsafe fn codegen(
                 }
             };
 
-            let from_name = global_fn_name(method.name);
-            let to_name = default_fn_name(method.name);
+            let from_name = mangle_internal_symbol(tcx, &global_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);
         }
@@ -64,8 +65,8 @@ pub(crate) unsafe fn codegen(
     create_wrapper_function(
         tcx,
         &cx,
-        "__rust_alloc_error_handler",
-        alloc_error_handler_name(alloc_error_handler_kind),
+        &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
+        &mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)),
         &[usize, usize], // size, align
         None,
         true,
@@ -73,15 +74,15 @@ pub(crate) unsafe fn codegen(
 
     unsafe {
         // __rust_alloc_error_handler_should_panic
-        let name = OomStrategy::SYMBOL;
-        let ll_g = cx.declare_global(name, i8);
+        let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL);
+        let ll_g = cx.declare_global(&name, i8);
         llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
         let val = tcx.sess.opts.unstable_opts.oom.should_panic();
         let llval = llvm::LLVMConstInt(i8, val as u64, False);
         llvm::set_initializer(ll_g, llval);
 
-        let name = NO_ALLOC_SHIM_IS_UNSTABLE;
-        let ll_g = cx.declare_global(name, i8);
+        let name = mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE);
+        let ll_g = cx.declare_global(&name, i8);
         llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
         let llval = llvm::LLVMConstInt(i8, 0, False);
         llvm::set_initializer(ll_g, llval);
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 9f8ec0ea526af..926445c780b53 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -27,6 +27,7 @@ use rustc_session::config::{
 };
 use rustc_span::source_map::Spanned;
 use rustc_span::{DUMMY_SP, Span};
+use rustc_symbol_mangling::mangle_internal_symbol;
 use rustc_target::spec::{HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel};
 use smallvec::SmallVec;
 
@@ -1199,7 +1200,7 @@ impl<'ll> CodegenCx<'ll, '_> {
             Some(def_id) => self.get_static(def_id),
             _ => {
                 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));
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 660fc7ec4c404..67135fcc3080d 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -14,6 +14,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf};
 use rustc_middle::ty::{self, GenericArgsRef, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_span::{Span, Symbol, sym};
+use rustc_symbol_mangling::mangle_internal_symbol;
 use rustc_target::callconv::{FnAbi, PassMode};
 use rustc_target::spec::{HasTargetSpec, PanicStrategy};
 use tracing::debug;
@@ -812,7 +813,10 @@ fn codegen_msvc_try<'ll>(
         let type_name = bx.const_bytes(b"rust_panic\0");
         let type_info =
             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);
         if bx.cx.tcx.sess.target.supports_comdat() {
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 459f4329d6e92..5c9e72ae0f19b 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -1,6 +1,6 @@
 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_hir::def::DefKind;
 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::util::Providers;
 use rustc_session::config::{CrateType, OomStrategy};
+use rustc_symbol_mangling::mangle_internal_symbol;
 use rustc_target::callconv::Conv;
 use rustc_target::spec::{SanitizerSet, TlsModel};
 use tracing::debug;
@@ -219,8 +220,11 @@ fn exported_symbols_provider_local(
     if allocator_kind_for_codegen(tcx).is_some() {
         for symbol_name in ALLOCATOR_METHODS
             .iter()
-            .map(|method| format!("__rust_{}", method.name))
-            .chain(["__rust_alloc_error_handler".to_string(), OomStrategy::SYMBOL.to_string()])
+            .map(|method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str()))
+            .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));
 
@@ -234,8 +238,10 @@ fn exported_symbols_provider_local(
             ));
         }
 
-        let exported_symbol =
-            ExportedSymbol::NoDefId(SymbolName::new(tcx, NO_ALLOC_SHIM_IS_UNSTABLE));
+        let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(
+            tcx,
+            &mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE),
+        ));
         symbols.push((
             exported_symbol,
             SymbolExportInfo {
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index e9c886d28edf6..396febcc63702 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -28,6 +28,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_session::Session;
 use rustc_session::config::{self, CrateType, EntryFnType, OutputType};
 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::traits::{ObligationCause, ObligationCtxt};
 use tracing::{debug, info};
@@ -989,7 +990,12 @@ impl CrateInfo {
                 .for_each(|(_, linked_symbols)| {
                     let mut symbols = missing_weak_lang_items
                         .iter()
-                        .map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text))
+                        .map(|item| {
+                            (
+                                format!("{prefix}{}", mangle_internal_symbol(tcx, item.as_str())),
+                                SymbolExportKind::Text,
+                            )
+                        })
                         .collect::<Vec<_>>();
                     symbols.sort_unstable_by(|a, b| a.0.cmp(&b.0));
                     linked_symbols.extend(symbols);
@@ -1002,7 +1008,13 @@ impl CrateInfo {
                         // errors.
                         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,
                             )
                         }));
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 998a4ff727e85..d5972b5c9e649 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -601,25 +601,19 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
     // strippable by the linker.
     //
     // 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)
         && let Some(lang_item) = LangItem::from_name(name)
-        && let Some(link_name) = lang_item.link_name()
     {
-        codegen_fn_attrs.export_name = Some(link_name);
-        codegen_fn_attrs.link_name = Some(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.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;
-    }
-
     // Any linkage to LLVM intrinsics for now forcibly marks them all as never
     // unwinds since LLVM sometimes can't handle codegen which `invoke`s
     // intrinsic functions.
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index dbaeae5e9513e..d824a23279b1b 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -74,6 +74,15 @@ pub(super) fn mangle<'tcx>(
 }
 
 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,
diff --git a/tests/codegen/alloc-optimisation.rs b/tests/codegen/alloc-optimisation.rs
index 8abeecf8550be..19f14647c1d7d 100644
--- a/tests/codegen/alloc-optimisation.rs
+++ b/tests/codegen/alloc-optimisation.rs
@@ -5,7 +5,7 @@
 pub fn alloc_test(data: u32) {
     // CHECK-LABEL: @alloc_test
     // 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
     let x = Box::new(data);
     drop(x);
diff --git a/tests/codegen/box-uninit-bytes.rs b/tests/codegen/box-uninit-bytes.rs
index 3b83ef3e250c4..0cc011485951c 100644
--- a/tests/codegen/box-uninit-bytes.rs
+++ b/tests/codegen/box-uninit-bytes.rs
@@ -41,6 +41,6 @@ pub fn box_lotsa_padding() -> Box<LotsaPadding> {
 
 // Hide the `allocalign` attribute in the declaration of __rust_alloc
 // 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" {{.*}} }
diff --git a/tests/codegen/dealloc-no-unwind.rs b/tests/codegen/dealloc-no-unwind.rs
index c560d7a993209..68597817d6f34 100644
--- a/tests/codegen/dealloc-no-unwind.rs
+++ b/tests/codegen/dealloc-no-unwind.rs
@@ -18,7 +18,7 @@ impl Drop for A {
 #[no_mangle]
 pub fn a(a: Box<i32>) {
     // CHECK-LABEL: define{{.*}}void @a
-    // CHECK: call void @__rust_dealloc
+    // CHECK: call void @{{.*}}__rust_dealloc
     // CHECK-NEXT: call void @foo
     let _a = A;
     drop(a);
diff --git a/tests/codegen/iter-repeat-n-trivial-drop.rs b/tests/codegen/iter-repeat-n-trivial-drop.rs
index 4dab499a8a5cb..3bb942d11d534 100644
--- a/tests/codegen/iter-repeat-n-trivial-drop.rs
+++ b/tests/codegen/iter-repeat-n-trivial-drop.rs
@@ -47,7 +47,7 @@ pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN<NotCopy>) -> Option<NotCop
 #[no_mangle]
 // CHECK-LABEL: @vec_extend_via_iter_repeat_n
 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,
 
     let n = 1234_usize;
diff --git a/tests/codegen/vec-calloc.rs b/tests/codegen/vec-calloc.rs
index 2e2769ce1301a..d1c320ead012e 100644
--- a/tests/codegen/vec-calloc.rs
+++ b/tests/codegen/vec-calloc.rs
@@ -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.
-// 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" {{.*}} }
diff --git a/tests/codegen/vec-optimizes-away.rs b/tests/codegen/vec-optimizes-away.rs
index 39d5c1614c82a..f6ed2898bdaaa 100644
--- a/tests/codegen/vec-optimizes-away.rs
+++ b/tests/codegen/vec-optimizes-away.rs
@@ -5,7 +5,7 @@
 pub fn sum_me() -> i32 {
     // CHECK-LABEL: @sum_me
     // 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
     vec![1, 2, 3].iter().sum::<i32>()
 }

From 0b0ccd403bf39e0c5d82a1d2b34f5af5ce3b5f4f Mon Sep 17 00:00:00 2001
From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date: Sun, 30 Jun 2024 20:27:00 +0000
Subject: [PATCH 6/9] Fix miri

---
 src/tools/miri/src/lib.rs                     |  1 +
 src/tools/miri/src/shims/extern_static.rs     |  8 ++-
 src/tools/miri/src/shims/foreign_items.rs     | 50 ++++++++++++-------
 src/tools/miri/tests/fail/alloc/too_large.rs  |  3 ++
 .../fail/alloc/unsupported_big_alignment.rs   |  3 ++
 .../unsupported_non_power_two_alignment.rs    |  4 ++
 .../fail/data_race/dealloc_read_race1.rs      |  3 ++
 .../fail/data_race/dealloc_read_race2.rs      |  3 ++
 .../fail/data_race/dealloc_write_race1.rs     |  3 ++
 .../fail/data_race/dealloc_write_race2.rs     |  3 ++
 .../pass/function_calls/exported_symbol.rs    |  2 +
 11 files changed, 64 insertions(+), 19 deletions(-)

diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 0bf5ae87f3836..03f76cfa6524c 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -71,6 +71,7 @@ extern crate rustc_index;
 extern crate rustc_middle;
 extern crate rustc_session;
 extern crate rustc_span;
+extern crate rustc_symbol_mangling;
 extern crate rustc_target;
 // Linking `rustc_driver` pulls in the required  object code as the rest of the rustc crates are
 // shipped only as rmeta files.
diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs
index 20dd3c8db2a3e..2feed5a835228 100644
--- a/src/tools/miri/src/shims/extern_static.rs
+++ b/src/tools/miri/src/shims/extern_static.rs
@@ -1,5 +1,7 @@
 //! Provides the `extern static` that this platform expects.
 
+use rustc_symbol_mangling::mangle_internal_symbol;
+
 use crate::*;
 
 impl<'tcx> MiriMachine<'tcx> {
@@ -50,7 +52,11 @@ impl<'tcx> MiriMachine<'tcx> {
         // "__rust_alloc_error_handler_should_panic"
         let val = ecx.tcx.sess.opts.unstable_opts.oom.should_panic();
         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() {
             // "environ" is mandated by POSIX.
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 505c079143a4c..03c6081e992c5 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -12,6 +12,7 @@ use rustc_middle::mir::interpret::AllocInit;
 use rustc_middle::ty::Ty;
 use rustc_middle::{mir, ty};
 use rustc_span::Symbol;
+use rustc_symbol_mangling::mangle_internal_symbol;
 use rustc_target::callconv::{Conv, FnAbi};
 
 use self::helpers::{ToHost, ToSoft};
@@ -51,7 +52,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
         // Some shims forward to other MIR bodies.
         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.
                 let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else {
                     // 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"
                     );
                 };
-                let name = alloc_error_handler_name(handler_kind);
+                let name =
+                    mangle_internal_symbol(*this.tcx, alloc_error_handler_name(handler_kind));
                 let handler = this
-                    .lookup_exported_symbol(Symbol::intern(name))?
+                    .lookup_exported_symbol(Symbol::intern(&name))?
                     .expect("missing alloc error handler symbol");
                 return interp_ok(Some(handler));
             }
@@ -136,15 +138,29 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 // Find it if it was not cached.
                 let mut instance_and_crate: Option<(ty::Instance<'_>, CrateNum)> = None;
                 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);
+                    // FIXME use tcx.symbol_name(instance) instead
                     let symbol_name = if let Some(export_name) = attrs.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)
                     } else {
                         // Skip over items without an explicitly defined symbol name.
                         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 let Some((original_instance, original_cnum)) = instance_and_crate {
                             // Make sure we are consistent wrt what is 'first' and 'second'.
@@ -489,7 +505,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
 
             // 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>| {
                     // 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.
@@ -500,9 +518,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     ecx.check_rustc_alloc_request(size, align)?;
 
                     let memory_kind = match link_name.as_str() {
-                        "__rust_alloc" => MiriMemoryKind::Rust,
                         "miri_alloc" => MiriMemoryKind::Miri,
-                        _ => unreachable!(),
+                        _ => MiriMemoryKind::Rust,
                     };
 
                     let ptr = ecx.allocate_ptr(
@@ -516,15 +533,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 };
 
                 match link_name.as_str() {
-                    "__rust_alloc" => return this.emulate_allocator(default),
                     "miri_alloc" => {
                         default(this)?;
                         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| {
                     // See the comment for `__rust_alloc` why `check_shim` is only called in the
                     // default case.
@@ -543,7 +559,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     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>| {
                     // See the comment for `__rust_alloc` why `check_shim` is only called in the
                     // default case.
@@ -554,9 +572,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     let align = ecx.read_target_usize(align)?;
 
                     let memory_kind = match link_name.as_str() {
-                        "__rust_dealloc" => MiriMemoryKind::Rust,
                         "miri_dealloc" => MiriMemoryKind::Miri,
-                        _ => unreachable!(),
+                        _ => MiriMemoryKind::Rust,
                     };
 
                     // 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() {
-                    "__rust_dealloc" => {
-                        return this.emulate_allocator(default);
-                    }
                     "miri_dealloc" => {
                         default(this)?;
                         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| {
                     // See the comment for `__rust_alloc` why `check_shim` is only called in the
                     // default case.
diff --git a/src/tools/miri/tests/fail/alloc/too_large.rs b/src/tools/miri/tests/fail/alloc/too_large.rs
index 4e28d2401d79f..c53318855aba0 100644
--- a/src/tools/miri/tests/fail/alloc/too_large.rs
+++ b/src/tools/miri/tests/fail/alloc/too_large.rs
@@ -1,4 +1,7 @@
+#![feature(rustc_attrs)]
+
 extern "Rust" {
+    #[rustc_std_internal_symbol]
     fn __rust_alloc(size: usize, align: usize) -> *mut u8;
 }
 
diff --git a/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs b/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs
index 08d84c461bfaa..34c6a6ce55012 100644
--- a/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs
+++ b/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs
@@ -2,7 +2,10 @@
 // because rustc does not support alignments that large.
 // https://github.com/rust-lang/miri/issues/3687
 
+#![feature(rustc_attrs)]
+
 extern "Rust" {
+    #[rustc_std_internal_symbol]
     fn __rust_alloc(size: usize, align: usize) -> *mut u8;
 }
 
diff --git a/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs b/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs
index a4ab8094bf4e1..ce8861937f873 100644
--- a/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs
+++ b/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs
@@ -1,5 +1,9 @@
 // Test non-power-of-two alignment.
+
+#![feature(rustc_attrs)]
+
 extern "Rust" {
+    #[rustc_std_internal_symbol]
     fn __rust_alloc(size: usize, align: usize) -> *mut u8;
 }
 
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs
index f174909e9d56b..d0a2848205410 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs
@@ -3,6 +3,8 @@
 // Avoid accidental synchronization via address reuse inside `thread::spawn`.
 //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
 
+#![feature(rustc_attrs)]
+
 use std::thread::spawn;
 
 #[derive(Copy, Clone)]
@@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {}
 unsafe impl<T> Sync for EvilSend<T> {}
 
 extern "Rust" {
+    #[rustc_std_internal_symbol]
     fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
 }
 
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs
index 1edfbf5e61c0d..f56c44cabc234 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs
@@ -3,6 +3,8 @@
 // Avoid accidental synchronization via address reuse inside `thread::spawn`.
 //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
 
+#![feature(rustc_attrs)]
+
 use std::thread::spawn;
 
 #[derive(Copy, Clone)]
@@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {}
 unsafe impl<T> Sync for EvilSend<T> {}
 
 extern "Rust" {
+    #[rustc_std_internal_symbol]
     fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
 }
 
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs
index 7605f1911db77..a16ea25e11ce8 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs
@@ -3,6 +3,8 @@
 // Avoid accidental synchronization via address reuse inside `thread::spawn`.
 //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
 
+#![feature(rustc_attrs)]
+
 use std::thread::spawn;
 
 #[derive(Copy, Clone)]
@@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {}
 unsafe impl<T> Sync for EvilSend<T> {}
 
 extern "Rust" {
+    #[rustc_std_internal_symbol]
     fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
 }
 pub fn main() {
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs
index 4f3819bd636b2..f3855e33c98d9 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs
@@ -3,6 +3,8 @@
 // Avoid accidental synchronization via address reuse inside `thread::spawn`.
 //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0
 
+#![feature(rustc_attrs)]
+
 use std::thread::spawn;
 
 #[derive(Copy, Clone)]
@@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {}
 unsafe impl<T> Sync for EvilSend<T> {}
 
 extern "Rust" {
+    #[rustc_std_internal_symbol]
     fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
 }
 pub fn main() {
diff --git a/src/tools/miri/tests/pass/function_calls/exported_symbol.rs b/src/tools/miri/tests/pass/function_calls/exported_symbol.rs
index 27aee9c883588..d804f3642b1d2 100644
--- a/src/tools/miri/tests/pass/function_calls/exported_symbol.rs
+++ b/src/tools/miri/tests/pass/function_calls/exported_symbol.rs
@@ -40,6 +40,7 @@ fn main() {
 
         extern "Rust" {
             fn bar() -> i32;
+            #[rustc_std_internal_symbol]
             fn baz() -> i32;
             fn qux() -> i32;
         }
@@ -63,6 +64,7 @@ fn main() {
 
             extern "C" {
                 fn bar() -> i32;
+                #[rustc_std_internal_symbol]
                 fn baz() -> i32;
                 fn qux() -> i32;
             }

From 83c0398856762562e3398c565fe2010c1d13e0aa Mon Sep 17 00:00:00 2001
From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date: Thu, 6 Feb 2025 18:16:45 +0000
Subject: [PATCH 7/9] Add test that all symbols we expect to be mangled are
 actually mangled

---
 tests/run-make/symbols-all-mangled/a_lib.rs   |  1 +
 .../symbols-all-mangled/an_executable.rs      |  3 +
 tests/run-make/symbols-all-mangled/rmake.rs   | 84 +++++++++++++++++++
 3 files changed, 88 insertions(+)
 create mode 100644 tests/run-make/symbols-all-mangled/a_lib.rs
 create mode 100644 tests/run-make/symbols-all-mangled/an_executable.rs
 create mode 100644 tests/run-make/symbols-all-mangled/rmake.rs

diff --git a/tests/run-make/symbols-all-mangled/a_lib.rs b/tests/run-make/symbols-all-mangled/a_lib.rs
new file mode 100644
index 0000000000000..716dd3263c5b7
--- /dev/null
+++ b/tests/run-make/symbols-all-mangled/a_lib.rs
@@ -0,0 +1 @@
+pub fn public_rust_function() {}
diff --git a/tests/run-make/symbols-all-mangled/an_executable.rs b/tests/run-make/symbols-all-mangled/an_executable.rs
new file mode 100644
index 0000000000000..db8df13b9a753
--- /dev/null
+++ b/tests/run-make/symbols-all-mangled/an_executable.rs
@@ -0,0 +1,3 @@
+pub fn public_rust_function_from_exe() {}
+
+fn main() {}
diff --git a/tests/run-make/symbols-all-mangled/rmake.rs b/tests/run-make/symbols-all-mangled/rmake.rs
new file mode 100644
index 0000000000000..a4c656722a7ac
--- /dev/null
+++ b/tests/run-make/symbols-all-mangled/rmake.rs
@@ -0,0 +1,84 @@
+// Check that all symbols in cdylibs, staticlibs and bins are mangled
+
+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 == "__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
+        }
+
+        if ["_start", "__dso_handle", "_init", "_fini", "__TMC_END__"].contains(&name) {
+            continue; // Part of the libc crt object
+        }
+
+        if name == "main" {
+            continue; // The main symbol has to be unmangled for the crt object to find it
+        }
+
+        panic!("Unmangled symbol found: {name}");
+    }
+}
+
+fn strip_underscore_if_apple(symbol: &str) -> &str {
+    if cfg!(target_vendor = "apple") { symbol.strip_prefix("_").unwrap() } else { symbol }
+}

From 3866d1c30c0ca1a92dfb106d0b0f51250f951be9 Mon Sep 17 00:00:00 2001
From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date: Wed, 26 Feb 2025 14:05:24 +0000
Subject: [PATCH 8/9] Ignore symbols that don't contain rust as substring for
 executables

For staticlib we still keep checking symbols that don't contain rust as
substring.
---
 tests/run-make/symbols-all-mangled/rmake.rs | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/tests/run-make/symbols-all-mangled/rmake.rs b/tests/run-make/symbols-all-mangled/rmake.rs
index a4c656722a7ac..244f68e511b31 100644
--- a/tests/run-make/symbols-all-mangled/rmake.rs
+++ b/tests/run-make/symbols-all-mangled/rmake.rs
@@ -59,6 +59,13 @@ fn symbols_check(path: &str) {
             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
         }
@@ -67,14 +74,6 @@ fn symbols_check(path: &str) {
             continue; // Unfortunately LLVM doesn't allow us to mangle this symbol
         }
 
-        if ["_start", "__dso_handle", "_init", "_fini", "__TMC_END__"].contains(&name) {
-            continue; // Part of the libc crt object
-        }
-
-        if name == "main" {
-            continue; // The main symbol has to be unmangled for the crt object to find it
-        }
-
         panic!("Unmangled symbol found: {name}");
     }
 }

From bebc5026b109bf5522185ae8bd1c3f0cbabe6acd Mon Sep 17 00:00:00 2001
From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date: Thu, 6 Mar 2025 13:13:55 +0000
Subject: [PATCH 9/9] Only run symbols-all-mangled test on ELF targets

---
 tests/run-make/symbols-all-mangled/rmake.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/run-make/symbols-all-mangled/rmake.rs b/tests/run-make/symbols-all-mangled/rmake.rs
index 244f68e511b31..81f2678e55cd0 100644
--- a/tests/run-make/symbols-all-mangled/rmake.rs
+++ b/tests/run-make/symbols-all-mangled/rmake.rs
@@ -1,4 +1,5 @@
 // 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};