Use object in run-make/symbols-visibility

This commit is contained in:
Chris Denton 2024-08-03 14:56:16 +00:00
parent ad0a2b7180
commit c2523c9543
No known key found for this signature in database
GPG Key ID: 713472F2F45627DE

View File

@ -4,12 +4,8 @@
// are exported, and that generics are only shown if explicitely requested. // are exported, and that generics are only shown if explicitely requested.
// See https://github.com/rust-lang/rust/issues/37530 // See https://github.com/rust-lang/rust/issues/37530
//@ ignore-windows-msvc use run_make_support::object::read::Object;
use run_make_support::{bin_name, dynamic_lib_name, is_msvc, object, regex, rfs, rustc};
//FIXME(Oneirical): This currently uses llvm-nm for symbol detection. However,
// the custom Rust-based solution of #128314 may prove to be an interesting alternative.
use run_make_support::{bin_name, dynamic_lib_name, is_darwin, is_windows, llvm_nm, regex, rustc};
fn main() { fn main() {
let cdylib_name = dynamic_lib_name("a_cdylib"); let cdylib_name = dynamic_lib_name("a_cdylib");
@ -64,16 +60,15 @@ fn main() {
); );
// FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032 // FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032
// if is_windows() { if is_msvc() {
// // Check that an executable does not export any dynamic symbols // Check that an executable does not export any dynamic symbols
// symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib") symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), false);
//, false); symbols_check(
// symbols_check( &exe_name,
// &exe_name, SymbolCheckType::StrSymbol("public_rust_function_from_exe"),
// SymbolCheckType::StrSymbol("public_rust_function_from_exe"), false,
// false, );
// ); }
// }
// Check the combined case, where we generate a cdylib and an rlib in the same // Check the combined case, where we generate a cdylib and an rlib in the same
// compilation session: // compilation session:
@ -131,44 +126,37 @@ fn main() {
); );
// FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032 // FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032
// if is_windows() { if is_msvc() {
// // Check that an executable does not export any dynamic symbols // Check that an executable does not export any dynamic symbols
// symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib") symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), false);
//, false); symbols_check(
// symbols_check( &exe_name,
// &exe_name, SymbolCheckType::StrSymbol("public_rust_function_from_exe"),
// SymbolCheckType::StrSymbol("public_rust_function_from_exe"), false,
// false, );
// ); }
// }
} }
#[track_caller] #[track_caller]
fn symbols_check(path: &str, symbol_check_type: SymbolCheckType, exists_once: bool) { fn symbols_check(path: &str, symbol_check_type: SymbolCheckType, exists_once: bool) {
let mut nm = llvm_nm(); let binary_data = rfs::read(path);
if is_windows() { let file = object::File::parse(&*binary_data).unwrap();
nm.arg("--extern-only"); let mut found: u64 = 0;
} else if is_darwin() { for export in file.exports().unwrap() {
nm.arg("--extern-only").arg("--defined-only"); let name = std::str::from_utf8(export.name()).unwrap();
} else { if has_symbol(name, symbol_check_type) {
nm.arg("--dynamic"); found += 1;
}
} }
let out = nm.input(path).run().stdout_utf8(); assert_eq!(found, exists_once as u64);
assert_eq!(
out.lines()
.filter(|&line| !line.contains("__imp_") && has_symbol(line, symbol_check_type))
.count()
== 1,
exists_once
);
} }
fn has_symbol(line: &str, symbol_check_type: SymbolCheckType) -> bool { fn has_symbol(name: &str, symbol_check_type: SymbolCheckType) -> bool {
if let SymbolCheckType::StrSymbol(expected) = symbol_check_type { if let SymbolCheckType::StrSymbol(expected) = symbol_check_type {
line.contains(expected) !name.contains("__imp_") && name.contains(expected)
} else { } else {
let regex = regex::Regex::new(r#"_ZN.*h.*E\|_R[a-zA-Z0-9_]+"#).unwrap(); let regex = regex::Regex::new(r#"_ZN.*h.*E\|_R[a-zA-Z0-9_]+"#).unwrap();
regex.is_match(line) regex.is_match(name)
} }
} }