2025-02-06 18:16:45 +00:00
|
|
|
// Check that all symbols in cdylibs, staticlibs and bins are mangled
|
2025-03-06 13:13:55 +00:00
|
|
|
//@ only-elf some object file formats create multiple symbols for each function with different names
|
2025-02-06 18:16:45 +00:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-18 11:11:51 -04:00
|
|
|
if name.contains(".llvm.") {
|
|
|
|
|
// Starting in LLVM 21 we get various implementation-detail functions which
|
|
|
|
|
// contain .llvm. that are not a problem.
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
panic!("Unmangled symbol found in {path}: {name}");
|
2025-02-06 18:16:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-26 14:05:24 +00:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-06 18:16:45 +00:00
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-18 11:11:51 -04:00
|
|
|
if name.contains(".llvm.") {
|
|
|
|
|
// Starting in LLVM 21 we get various implementation-detail functions which
|
|
|
|
|
// contain .llvm. that are not a problem.
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
panic!("Unmangled symbol found in {path}: {name}");
|
2025-02-06 18:16:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn strip_underscore_if_apple(symbol: &str) -> &str {
|
|
|
|
|
if cfg!(target_vendor = "apple") { symbol.strip_prefix("_").unwrap() } else { symbol }
|
|
|
|
|
}
|