about summary refs log tree commit diff
diff options
context:
space:
mode:
authorusamoi <usamoi@outlook.com>2025-07-05 02:07:29 +0800
committerusamoi <usamoi@outlook.com>2025-07-09 22:40:11 +0800
commitbf6d29d55847614e677e6c5d6060d2dc0b1ad47b (patch)
treea68e156fb4f45bd85d71eb16ef0307229f470036
parent556d20a834126d2d0ac20743b9792b8474d6d03c (diff)
downloadrust-bf6d29d55847614e677e6c5d6060d2dc0b1ad47b.tar.gz
rust-bf6d29d55847614e677e6c5d6060d2dc0b1ad47b.zip
use `--dynamic-list` for exporting executable symbols
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs41
-rw-r--r--tests/ui/linking/export-executable-symbols.rs30
2 files changed, 55 insertions, 16 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 1896f63bd2d..e0a3ad55be0 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -800,9 +800,7 @@ impl<'a> Linker for GccLinker<'a> {
             return;
         }
 
-        let is_windows = self.sess.target.is_like_windows;
-        let path = tmpdir.join(if is_windows { "list.def" } else { "list" });
-
+        let path = tmpdir.join(if self.sess.target.is_like_windows { "list.def" } else { "list" });
         debug!("EXPORTED SYMBOLS:");
 
         if self.sess.target.is_like_darwin {
@@ -817,7 +815,8 @@ impl<'a> Linker for GccLinker<'a> {
             if let Err(error) = res {
                 self.sess.dcx().emit_fatal(errors::LibDefWriteFailure { error });
             }
-        } else if is_windows {
+            self.link_arg("-exported_symbols_list").link_arg(path);
+        } else if self.sess.target.is_like_windows {
             let res: io::Result<()> = try {
                 let mut f = File::create_buffered(&path)?;
 
@@ -835,6 +834,21 @@ impl<'a> Linker for GccLinker<'a> {
             if let Err(error) = res {
                 self.sess.dcx().emit_fatal(errors::LibDefWriteFailure { error });
             }
+            self.link_arg(path);
+        } else if crate_type == CrateType::Executable && !self.sess.target.is_like_solaris {
+            let res: io::Result<()> = try {
+                let mut f = File::create_buffered(&path)?;
+                writeln!(f, "{{")?;
+                for (sym, _) in symbols {
+                    debug!(sym);
+                    writeln!(f, "  {sym};")?;
+                }
+                writeln!(f, "}};")?;
+            };
+            if let Err(error) = res {
+                self.sess.dcx().emit_fatal(errors::VersionScriptWriteFailure { error });
+            }
+            self.link_arg("--dynamic-list").link_arg(path);
         } else {
             // Write an LD version script
             let res: io::Result<()> = try {
@@ -852,18 +866,13 @@ impl<'a> Linker for GccLinker<'a> {
             if let Err(error) = res {
                 self.sess.dcx().emit_fatal(errors::VersionScriptWriteFailure { error });
             }
-        }
-
-        if self.sess.target.is_like_darwin {
-            self.link_arg("-exported_symbols_list").link_arg(path);
-        } else if self.sess.target.is_like_solaris {
-            self.link_arg("-M").link_arg(path);
-        } else if is_windows {
-            self.link_arg(path);
-        } else {
-            let mut arg = OsString::from("--version-script=");
-            arg.push(path);
-            self.link_arg(arg).link_arg("--no-undefined-version");
+            if self.sess.target.is_like_solaris {
+                self.link_arg("-M").link_arg(path);
+            } else {
+                let mut arg = OsString::from("--version-script=");
+                arg.push(path);
+                self.link_arg(arg).link_arg("--no-undefined-version");
+            }
         }
     }
 
diff --git a/tests/ui/linking/export-executable-symbols.rs b/tests/ui/linking/export-executable-symbols.rs
new file mode 100644
index 00000000000..aea5527b6a1
--- /dev/null
+++ b/tests/ui/linking/export-executable-symbols.rs
@@ -0,0 +1,30 @@
+//@ run-pass
+//@ only-linux
+//@ only-gnu
+//@ compile-flags: -Zexport-executable-symbols
+//@ edition: 2024
+
+// Regression test for <https://github.com/rust-lang/rust/issues/101610>.
+
+#![feature(rustc_private)]
+
+extern crate libc;
+
+#[unsafe(no_mangle)]
+fn hack() -> u64 {
+    998244353
+}
+
+fn main() {
+    unsafe {
+        let handle = libc::dlopen(std::ptr::null(), libc::RTLD_NOW);
+        let ptr = libc::dlsym(handle, c"hack".as_ptr());
+        let ptr: Option<unsafe fn() -> u64> = std::mem::transmute(ptr);
+        if let Some(f) = ptr {
+            assert!(f() == 998244353);
+            println!("symbol `hack` is found successfully");
+        } else {
+            panic!("symbol `hack` is not found");
+        }
+    }
+}