about summary refs log tree commit diff
diff options
context:
space:
mode:
authorusamoi <usamoi@outlook.com>2025-04-13 23:18:39 +0800
committerusamoi <usamoi@outlook.com>2025-04-25 01:41:25 +0800
commitb1a38313cb0dee9a7c5573ae37ad48b0a347cb7c (patch)
treead9109c49a5d15cd4885accb5d778e13499b65b3
parent65fa0ab9246da73183b848a0c29b033779fe6f6c (diff)
downloadrust-b1a38313cb0dee9a7c5573ae37ad48b0a347cb7c.tar.gz
rust-b1a38313cb0dee9a7c5573ae37ad48b0a347cb7c.zip
set subsections_via_symbols for ld64 helper sections
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs6
-rw-r--r--tests/ui/linking/cdylib-no-mangle.rs20
-rw-r--r--tests/ui/linking/executable-no-mangle-strip.rs27
3 files changed, 53 insertions, 0 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 8de68925cab..f0c47ac41e8 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2015,6 +2015,12 @@ fn add_linked_symbol_object(
         file.set_mangling(object::write::Mangling::None);
     }
 
+    if file.format() == object::BinaryFormat::MachO {
+        // Divide up the sections into sub-sections via symbols for dead code stripping.
+        // Without this flag, unused `#[no_mangle]` or `#[used]` cannot be discard on MachO targets.
+        file.set_subsections_via_symbols();
+    }
+
     // ld64 requires a relocation to load undefined symbols, see below.
     // Not strictly needed if linking with lld, but might as well do it there too.
     let ld64_section_helper = if file.format() == object::BinaryFormat::MachO {
diff --git a/tests/ui/linking/cdylib-no-mangle.rs b/tests/ui/linking/cdylib-no-mangle.rs
new file mode 100644
index 00000000000..f442c3f584d
--- /dev/null
+++ b/tests/ui/linking/cdylib-no-mangle.rs
@@ -0,0 +1,20 @@
+//@ only-apple
+//@ build-fail
+//@ dont-check-compiler-stderr
+//@ dont-check-compiler-stdout
+
+// Regression test for <https://github.com/rust-lang/rust/issues/139744>.
+// Functions in the dynamic library marked with no_mangle should not be GC-ed.
+
+#![crate_type = "cdylib"]
+
+unsafe extern "C" {
+    unsafe static THIS_SYMBOL_SHOULD_BE_UNDEFINED: usize;
+}
+
+#[unsafe(no_mangle)]
+pub unsafe fn function_marked_with_no_mangle() {
+    println!("FUNCTION_MARKED_WITH_NO_MANGLE = {}", unsafe { THIS_SYMBOL_SHOULD_BE_UNDEFINED });
+}
+
+//~? ERROR linking
diff --git a/tests/ui/linking/executable-no-mangle-strip.rs b/tests/ui/linking/executable-no-mangle-strip.rs
new file mode 100644
index 00000000000..cc283dc53ee
--- /dev/null
+++ b/tests/ui/linking/executable-no-mangle-strip.rs
@@ -0,0 +1,27 @@
+//@ run-pass
+//@ ignore-windows-gnu: only statics marked with used can be GC-ed on windows-gnu
+
+// Regression test for <https://github.com/rust-lang/rust/issues/139744>.
+// Functions in the binary marked with no_mangle should be GC-ed if they
+// are not indirectly referenced by main.
+
+#![feature(used_with_arg)]
+
+#[cfg_attr(windows, link(name = "this_lib_does_not_exist", kind = "raw-dylib"))]
+unsafe extern "C" {
+    unsafe static THIS_SYMBOL_SHOULD_BE_UNDEFINED: usize;
+}
+
+#[unsafe(no_mangle)]
+pub unsafe fn function_marked_with_no_mangle() {
+    println!("FUNCTION_MARKED_WITH_NO_MANGLE = {}", unsafe { THIS_SYMBOL_SHOULD_BE_UNDEFINED });
+}
+
+#[used(compiler)]
+pub static FUNCTION_MARKED_WITH_USED: unsafe fn() = || {
+    println!("FUNCTION_MARKED_WITH_USED = {}", unsafe { THIS_SYMBOL_SHOULD_BE_UNDEFINED });
+};
+
+fn main() {
+    println!("MAIN");
+}