Rollup merge of #143446 - usamoi:export-executable-symbols, r=bjorn3,oli-obk
use `--dynamic-list` for exporting executable symbols closes rust-lang/rust#101610 cc rust-lang/rust#84161 https://sourceware.org/binutils/docs-2.39/ld/VERSION.html: > --dynamic-list=dynamic-list-file Specify the name of a dynamic list file to the linker. This is typically used when creating shared libraries to specify a list of global symbols whose references shouldn’t be bound to the definition within the shared library, or creating dynamically linked executables to specify a list of symbols which should be added to the symbol table in the executable. This option is only meaningful on ELF platforms which support shared libraries. `ld.lld --help`: > --dynamic-list=<file>: Similar to --export-dynamic-symbol-list. When creating a shared object, this additionally implies -Bsymbolic but does not set DF_SYMBOLIC > --export-dynamic-symbol-list=file: Read a list of dynamic symbol patterns. Apply --export-dynamic-symbol on each pattern > --export-dynamic-symbol=glob: (executable) Put matched symbols in the dynamic symbol table. (shared object) References to matched non-local STV_DEFAULT symbols shouldn't be bound to definitions within the shared object. Does not imply -Bsymbolic. > --export-dynamic: Put symbols in the dynamic symbol table Use `--dynamic-list` because it's older than `--export-dynamic-symbol-list` (binutils 2.35) try-job: dist-i586-gnu-i586-i686-musl
This commit is contained in:
@@ -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,20 +866,15 @@ 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 {
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn subsystem(&mut self, subsystem: &str) {
|
||||
self.link_args(&["--subsystem", subsystem]);
|
||||
|
||||
30
tests/ui/linking/export-executable-symbols.rs
Normal file
30
tests/ui/linking/export-executable-symbols.rs
Normal file
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user