nullptr or None.pe: lief.PE.Binary
if (debug_info := pe.debug_info) is not None:
assert isinstance(debug_info, lief.pdb.DebugInfo)
print(f"PDB Debug handler: {debug_info}")
# Or you can load the PDB directly:
pdb = lief.pdb.load("some.pdb")
std::unique_ptr<LIEF::PE::Binary> pe;
if (const LIEF::DebugInfo* info = pe->debug_info()) {
assert(LIEF::pdb::DebugInfo::classof(info) && "Wrong DebugInfo type");
const auto& pdb = static_cast<const LIEF::pdb::DebugInfo&>(*info);
}
// Or loading directly the pdb file
std::unique_ptr<LIEF::pdb::DebugInfo> pdb = LIEF::pdb::load("some.pdb");
let pe: &lief::pe::Binary = some_pe;
if let Some(lief::DebugInfo::Pdb(pdb)) = pe.debug_info() {
// PDB debug info
}
let pdb = lief::pdb::load("some.pdb");
pdb: lief.pdb.DebugInfo
print("arg={}, guid={}".format(pdb.age, pdb.guid))
for sym in pdb.public_symbols:
print("name={}, section={}, RVA={}".format(sym.name, sym.section_name, sym.RVA))
for ty in pdb.types:
if isinstance(ty, lief.pdb.types.Class):
print(f"Class[name]={ty.name}")
for cu in pdb.compilation_units:
print(f"module={cu.module_name}")
for src in cu.sources:
print(f" - {src}")
for func in cu.functions:
print(
"name={}, section={}, RVA={}, code_size={}".format(
func.name,
func.section_name,
func.RVA,
func.code_size,
)
)
std::unique_ptr<LIEF::pdb::DebugInfo> pdb;
log(LEVEL::INFO, "age={}, guid={}", std::to_string(pdb->age()), pdb->guid());
for (const LIEF::pdb::PublicSymbol& symbol : pdb->public_symbols()) {
log(LEVEL::INFO, "name={}, section={}, RVA={}", symbol.name(),
symbol.section_name(), std::to_string(symbol.RVA()));
}
for (const LIEF::pdb::Type& ty : pdb->types()) {
if (LIEF::pdb::types::Class::classof(&ty)) {
const auto* clazz = ty.as<LIEF::pdb::types::Class>();
log(LEVEL::INFO, "Class[name]={}", clazz->name().value_or(""));
}
}
for (const LIEF::pdb::CompilationUnit& CU : pdb->compilation_units()) {
log(LEVEL::INFO, "module={}", CU.module_name());
for (const std::string& src : CU.sources()) {
log(LEVEL::INFO, " - {}", src);
}
for (const LIEF::pdb::Function& func : CU.functions()) {
log(LEVEL::INFO, "name={}, section={}, RVA={}, code size={}", func.name(),
func.section_name(), std::to_string(func.RVA()),
std::to_string(func.code_size()));
}
}
let pdb = lief::pdb::load(path).unwrap_or_else(|| {
process::exit(1);
});
println!("age={}, guid={}", pdb.age(), pdb.guid());
for symbol in pdb.public_symbols() {
println!(
"name={}, section={}, RVA={}",
symbol.name(),
symbol.section_name().unwrap_or("".to_string()),
symbol.rva()
);
}
for ty in pdb.types() {
if let lief::pdb::Type::Class(clazz) = ty {
println!("Class[name]={}", clazz.name().unwrap_or_default());
}
}
for cu in pdb.compilation_units() {
println!("module={}", cu.module_name());
for src in cu.sources() {
println!(" - {}", src);
}
for func in cu.functions() {
println!(
"name={}, section={}, RVA={}, code_size={}",
func.name(),
func.section_name(),
func.rva(),
func.code_size()
);
}
}
binary: lief.Binary
dbg = binary.load_debug_info(r"C:\Users\romain\LIEF.pdb")
std::unique_ptr<LIEF::Binary> binary;
binary->load_debug_info(R"(C:\Users\romain\LIEF.pdb)");
let bin: &mut dyn lief::generic::Binary = some_bin;
let path = PathBuf::from("C:\\Users\\romain\\LIEF.pdb");
bin.load_debug_info(&path);
binary: lief.Binary
dbg = binary.load_debug_info(r"C:\Users\romain\LIEF.pdb")
# The location (address/size) of `my_function` is defined in LIEF.pdb
for inst in binary.disassemble("my_function"):
print(inst)
std::unique_ptr<LIEF::Binary> binary;
binary->load_debug_info(R"(C:\Users\romain\LIEF.pdb)");
// The location (address/size) of `my_function` is defined in LIEF.pdb
for (const LIEF::assembly::Instruction& inst :
binary->disassemble("my_function"))
{
std::cout << inst << '\n';
}
let bin: &mut dyn lief::generic::Binary = some_bin;
let path = PathBuf::from("C:\\Users\\romain\\LIEF.pdb");
bin.load_debug_info(&path);
// The location (address/size) of `my_function` is defined in LIEF.pdb
for inst in bin.disassemble_symbol("my_function") {
println!("{inst}");
}
PDB types, functions and compilation units can be turned into C/C++ definitions using the to_decl() function:
pdb: lief.pdb.DebugInfo
opt = lief.DeclOpt()
opt.is_cpp = True
for ty in pdb.types:
print(ty.to_decl(opt))
for cu in pdb.compilation_units:
# Emit the definition of the functions of the compilation unit
print(cu.to_decl(opt))
for func in cu.functions:
print(func.to_decl(opt))
std::unique_ptr<LIEF::pdb::DebugInfo> pdb;
LIEF::DeclOpt opt;
opt.is_cpp(true);
for (const LIEF::pdb::Type& ty : pdb->types()) {
std::cout << ty.to_decl(opt) << '\n';
}
for (const LIEF::pdb::CompilationUnit& CU : pdb->compilation_units()) {
std::cout << CU.to_decl(opt) << '\n';
for (const LIEF::pdb::Function& func : CU.functions()) {
std::cout << func.to_decl(opt) << '\n';
}
}
let pdb: &lief::pdb::DebugInfo = some_pdb;
let opt = lief::DeclOpt {
is_cpp: true,
..Default::default()
};
for ty in pdb.types() {
println!("{}", ty.to_decl_with_opt(&opt));
}
for cu in pdb.compilation_units() {
println!("{}", cu.to_decl_with_opt(&opt));
for func in cu.functions() {
println!("{}", func.to_decl_with_opt(&opt));
}
}
You can find the documentation of the API for the different languages here:
Rust API: lief::pdb