use idakit::prelude::*;
use idakit_runner_macros::kernel_test;
#[kernel_test(read_only)]
fn symbols() {
crate::common::with_canonical_db(run);
}
fn run(idb: &mut Database) {
let mut exports = 0usize;
let mut named_exports = 0usize;
let mut forwarders = 0usize;
let mut exports_in_segment = 0usize;
for export in idb.exports().take(4000) {
exports += 1;
named_exports += usize::from(export.name().is_some());
forwarders += usize::from(export.forwarder().is_some());
assert!(
export.address().is_some() || export.forwarder().is_some(),
"export #{} resolves to neither an address nor a forwarder",
export.index()
);
if let Some(ea) = export.address() {
assert!(
idb.segment_at(ea).is_some(),
"export {:?} at {ea:#x} does not resolve to any segment",
export.name()
);
exports_in_segment += 1;
}
}
println!(
"exports: {exports} total, {named_exports} named, {forwarders} forwarded, \
{exports_in_segment} resolved to a segment"
);
let mut imports = 0usize;
let mut by_name = 0usize;
let mut by_ordinal = 0usize;
let mut imports_in_segment = 0usize;
for import in idb.imports().take(8000) {
imports += 1;
by_name += usize::from(import.name().is_some());
by_ordinal += usize::from(import.ordinal().is_some());
assert!(
import.name().is_some() || import.ordinal().is_some(),
"import at {:#x} has neither a name nor an ordinal",
import.address()
);
assert!(
idb.segment_at(import.address()).is_some(),
"import {:?} at {:#x} does not resolve to any segment",
import.name(),
import.address()
);
imports_in_segment += 1;
}
println!(
"imports: {imports} total, {by_name} by name, {by_ordinal} by ordinal, \
{imports_in_segment} resolved to a segment"
);
assert!(
exports > 0 || imports > 0,
"the database has neither exports nor imports"
);
println!("symbols OK: export/import enumeration verified");
}