extern crate pdb;
use pdb::FallibleIterator;
use std::collections::HashMap;
fn setup<F>(func: F) where F: FnOnce(&pdb::SymbolTable, bool) -> () {
let (file, is_fixture) = if let Ok(filename) = std::env::var("PDB_FILE") {
(std::fs::File::open(filename).expect("opening file"), false)
} else {
(std::fs::File::open("fixtures/self/foo.pdb").expect("opening file"), true)
};
let mut pdb = pdb::PDB::open(file).expect("opening pdb");
let symbol_table = pdb.global_symbols().expect("global symbols");
func(&symbol_table, is_fixture);
}
#[test]
fn count_symbols() {
setup(|global_symbols,is_fixture| {
let mut map: HashMap<u16, usize> = HashMap::new();
let mut iter = global_symbols.iter();
while let Some(sym) = iter.next().expect("next symbol") {
let kind = sym.raw_kind();
let mut entry = map.entry(kind).or_insert(0);
if *entry == 0 && is_fixture {
println!("#[test]");
println!("fn kind_{:04x}() {{", sym.raw_kind());
println!(" let buf = &{:?};", sym.raw_bytes());
println!(" let (symbol, data, name) = parse(buf).expect(\"parse\");");
println!(" assert_eq!(symbol.raw_kind(), 0x{:04x});", sym.raw_kind());
println!(" assert_eq!(data, SymbolData::{:?});", sym.parse().expect("parse"));
println!(" assert_eq!(name, {:?});", sym.name().expect("name"));
println!("}}");
println!("");
}
*entry += 1;
}
println!("symbol counts by kind:");
for (kind, count) in &map {
println!(" - kind: 0x{:04x}, count: {}", kind, count);
}
assert!(*map.get(&0x1107).expect("0x1107") >= 500);
assert!(*map.get(&0x1108).expect("0x1108") >= 400);
assert!(*map.get(&0x110c).expect("0x110c") >= 90);
assert!(*map.get(&0x110d).expect("0x110d") >= 120);
assert!(*map.get(&0x110e).expect("0x110e") >= 3000);
assert!(*map.get(&0x110e).expect("0x110e") >= 3000);
assert!(*map.get(&0x1125).expect("0x1125") >= 2000);
assert!(*map.get(&0x1127).expect("0x1127") >= 500);
})
}
#[test]
fn find_symbols() {
setup(|global_symbols,is_fixture| {
if !is_fixture {
return
}
let mut map: HashMap<&[u8], Option<pdb::SymbolData>> = HashMap::new();
map.insert("main".as_bytes(), None);
map.insert("memcpy".as_bytes(), None);
map.insert("HeapAlloc".as_bytes(), None);
map.insert("?static_f_public@Baz@@SAXXZ".as_bytes(), None);
let mut iter = global_symbols.iter();
while let Some(sym) = iter.next().expect("next symbol") {
let name = sym.name().expect("symbol name");
let data = sym.parse().expect("symbol parsing");
match map.entry(name.as_bytes()) {
std::collections::hash_map::Entry::Occupied(mut e) => {
e.insert(Some(data));
}
_ => {}
}
}
for (key, value) in map {
match value {
Some(data) => {
println!("found {} => {:?}", String::from_utf8_lossy(key), data);
}
None => {
println!("couldn't find {}", String::from_utf8_lossy(key));
assert!(false);
}
}
}
})
}