Skip to content

Commit

Permalink
refactor extern-fn-reachable to make sure symbols are exported
Browse files Browse the repository at this point in the history
  • Loading branch information
lolbinarycat committed Aug 6, 2024
1 parent 158f1ea commit 8663bbe
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 15 deletions.
34 changes: 22 additions & 12 deletions src/tools/run-make-support/src/symbols.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::path::Path;

use object::{self, Object, ObjectSymbol, SymbolIterator};
use object::{self, Object, Symbol, ObjectSymbol, SymbolIterator};

/// Iterate through the symbols in an object file.
///
Expand Down Expand Up @@ -43,28 +43,38 @@ pub fn any_symbol_contains(path: impl AsRef<Path>, substrings: &[&str]) -> bool
})
}

/// Check if an object file contains *all* of the given symbols.
/// Get a list of symbols that are in `symbol_names` but not the final binary.
///
/// The symbols must also match `pred`.
///
/// The symbol names must match exactly.
///
/// Panics if `path` is not a valid object file readable by the current user.
pub fn contains_exact_symbols(path: impl AsRef<Path>, symbol_names: &[&str]) -> bool {
pub fn missing_exact_symbols<'a>(path: impl AsRef<Path>, symbol_names: &[&'a str], pred: impl Fn(&Symbol<'_, '_>) -> bool) -> Vec<&'a str> {
let mut found = vec![false; symbol_names.len()];
with_symbol_iter(path, |syms| {
for sym in syms {
for sym in syms.filter(&pred) {
for (i, symbol_name) in symbol_names.iter().enumerate() {
found[i] |= sym.name_bytes().unwrap() == symbol_name.as_bytes();
}
}
});
let result = found.iter().all(|x| *x);
if !result {
eprintln!("does not contain symbol(s): ");
for i in 0..found.len() {
if !found[i] {
eprintln!("* {}", symbol_names[i]);
}
return found.iter().enumerate()
.filter_map(|(i, found)| if !*found {
Some(symbol_names[i])
} else {
None
}).collect();
}

/// Assert that the symbol file contains all of the listed symbols and they all match the given predicate
pub fn assert_contains_exact_symbols(path: impl AsRef<Path>, symbol_names: &[&str], pred: impl Fn(&Symbol<'_, '_>) -> bool) {
let missing = missing_exact_symbols(path.as_ref(), symbol_names, pred);
if missing.len() > 0 {
eprintln!("{} does not contain symbol(s): ", path.as_ref().display());
for sn in missing {
eprintln!("* {}", sn);
}
panic!("missing symbols");
}
result
}
10 changes: 7 additions & 3 deletions tests/run-make/extern-fn-reachable/rmake.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
//@ ignore-cross-compile
use run_make_support::rustc;
use run_make_support::symbols::contains_exact_symbols;

use run_make_support::symbols::assert_contains_exact_symbols;
use run_make_support::object::ObjectSymbol;
fn main() {
rustc().input("dylib.rs").output("dylib.so").prefer_dynamic().run();
assert!(contains_exact_symbols("dylib.so", &["fun1", "fun2", "fun3", "fun4", "fun5"]));
assert_contains_exact_symbols(
"dylib.so",
&["fun1", "fun2", "fun3", "fun4", "fun5"],
|sym| dbg!(dbg!(sym).is_global()) && !dbg!(sym.is_undefined()),
);
}

0 comments on commit 8663bbe

Please sign in to comment.