1use std::path::Path;
23use object::{self, Object, ObjectSymbol, SymbolIterator};
45/// Given an [`object::File`], find the exported dynamic symbol names via
6/// [`object::Object::exports`]. This does not distinguish between which section the symbols appear
7/// in.
8#[track_caller]
9pub fn exported_dynamic_symbol_names<'file>(file: &'file object::File<'file>) -> Vec<&'file str> {
10file.exports()
11 .unwrap()
12 .into_iter()
13 .filter_map(|sym| std::str::from_utf8(sym.name()).ok())
14 .collect()
15}
1617/// Iterate through the symbols in an object file. See [`object::Object::symbols`].
18///
19/// Panics if `path` is not a valid object file readable by the current user or if `path` cannot be
20/// parsed as a recognized object file.
21#[track_caller]
22pub fn with_symbol_iter<P, F, R>(path: P, func: F) -> R
23where
24P: AsRef<Path>,
25 F: FnOnce(&mut SymbolIterator<'_, '_>) -> R,
26{
27let path = path.as_ref();
28let blob = crate::fs::read(path);
29let f = object::File::parse(&*blob)
30 .unwrap_or_else(|e| panic!("failed to parse `{}`: {e}", path.display()));
31let mut iter = f.symbols();
32func(&mut iter)
33}
3435/// Check an object file's symbols for substrings.
36///
37/// Returns `true` if any of the symbols found in the object file at `path` contain a substring
38/// listed in `substrings`.
39///
40/// Panics if `path` is not a valid object file readable by the current user or if `path` cannot be
41/// parsed as a recognized object file.
42#[track_caller]
43pub fn any_symbol_contains(path: impl AsRef<Path>, substrings: &[&str]) -> bool {
44with_symbol_iter(path, |syms| {
45for sym in syms {
46for substring in substrings {
47if sym
48 .name_bytes()
49 .unwrap()
50 .windows(substring.len())
51 .any(|x| x == substring.as_bytes())
52 {
53eprintln!("{:?} contains {}", sym, substring);
54return true;
55 }
56 }
57 }
58false
59})
60}