diff options
| author | KyleMiles <krm504@nyu.edu> | 2023-08-25 14:08:25 -0400 |
|---|---|---|
| committer | KyleMiles <krm504@nyu.edu> | 2023-09-29 12:02:59 -0400 |
| commit | 20e79d4e43a8734cdc5c4f9ca5b204a2c44aca8e (patch) | |
| tree | 067c27dd7c35158ef2d9f8fa4073e81574088406 /rust/examples/dwarf/dwarf_import/src/lib.rs | |
| parent | a452691f145583f092893dff6ecab14375d0613f (diff) | |
DWARF Import : Misc code cleanup, improvements, and enabling by default changes
This includes:
Gracefully handle missing DIE references
Partially revert 7849cda
Misc DWARFv5 Fixes
Speed Improvements
Fix crash on unexpected EOF
Partially revert 0d5fe9ec8963a26361b8bf1af17e029afc87f952 and Correctly initialize DWARF Import plugin
Diffstat (limited to 'rust/examples/dwarf/dwarf_import/src/lib.rs')
| -rw-r--r-- | rust/examples/dwarf/dwarf_import/src/lib.rs | 144 |
1 files changed, 72 insertions, 72 deletions
diff --git a/rust/examples/dwarf/dwarf_import/src/lib.rs b/rust/examples/dwarf/dwarf_import/src/lib.rs index 6ec2e5ad..7aab3775 100644 --- a/rust/examples/dwarf/dwarf_import/src/lib.rs +++ b/rust/examples/dwarf/dwarf_import/src/lib.rs @@ -18,7 +18,7 @@ mod functions; mod helpers; mod types; -use crate::dwarfdebuginfo::DebugInfoBuilder; +use crate::dwarfdebuginfo::{DebugInfoBuilder, DebugInfoBuilderContext}; use crate::functions::parse_function_entry; use crate::helpers::{get_attr_die, get_name, get_uid, DieReference}; use crate::types::parse_data_variable; @@ -27,7 +27,6 @@ use binaryninja::{ binaryview::{BinaryView, BinaryViewExt}, debuginfo::{CustomDebugInfoParser, DebugInfo, DebugInfoParser}, logger, - settings::Settings, templatesimplifier::simplify_str_to_str, }; use dwarfreader::{ @@ -36,18 +35,16 @@ use dwarfreader::{ use gimli::{constants, DebuggingInformationEntry, Dwarf, DwarfFileType, Reader, SectionId, Unit}; -use log::LevelFilter; +use log::{warn, LevelFilter}; use std::ffi::CString; fn recover_names<R: Reader<Offset = usize>>( - dwarf: &Dwarf<R>, - debug_info_builder: &mut DebugInfoBuilder, + debug_info_builder_context: &mut DebugInfoBuilderContext<R>, progress: &dyn Fn(usize, usize) -> Result<(), ()>, -) -> usize { - let mut total_die_count = 0; - let mut iter = dwarf.units(); +) { + let mut iter = debug_info_builder_context.dwarf().units(); while let Ok(Some(header)) = iter.next() { - let unit = dwarf.unit(header).unwrap(); + let unit = debug_info_builder_context.dwarf().unit(header).unwrap(); let mut namespace_qualifiers: Vec<(isize, CString)> = vec![]; let mut entries = unit.entries(); let mut depth = 0; @@ -55,14 +52,14 @@ fn recover_names<R: Reader<Offset = usize>>( // The first entry in the unit is the header for the unit if let Ok(Some((delta_depth, _))) = entries.next_dfs() { depth += delta_depth; - total_die_count += 1; + debug_info_builder_context.total_die_count += 1; } while let Ok(Some((delta_depth, entry))) = entries.next_dfs() { - total_die_count += 1; + debug_info_builder_context.total_die_count += 1; - if (*progress)(0, total_die_count).is_err() { - return 0; // Parsing canceled + if (*progress)(0, debug_info_builder_context.total_die_count).is_err() { + return; // Parsing canceled }; depth += delta_depth; @@ -74,34 +71,37 @@ fn recover_names<R: Reader<Offset = usize>>( match entry.tag() { constants::DW_TAG_namespace => { fn resolve_namespace_name<R: Reader<Offset = usize>>( - dwarf: &Dwarf<R>, unit: &Unit<R>, entry: &DebuggingInformationEntry<R>, + debug_info_builder_context: &DebugInfoBuilderContext<R>, namespace_qualifiers: &mut Vec<(isize, CString)>, depth: isize, ) { - if let Some(namespace_qualifier) = get_name(dwarf, unit, entry) { - namespace_qualifiers.push((depth, namespace_qualifier)); - } else if let Some(die_reference) = - get_attr_die(dwarf, unit, entry, constants::DW_AT_extension) + if let Some(namespace_qualifier) = + get_name(unit, entry, debug_info_builder_context) { + namespace_qualifiers.push((depth, namespace_qualifier)); + } else if let Some(die_reference) = get_attr_die( + unit, + entry, + debug_info_builder_context, + constants::DW_AT_extension, + ) { match die_reference { - DieReference::Offset(entry_offset) => resolve_namespace_name( - dwarf, - unit, - &unit.entry(entry_offset).unwrap(), - namespace_qualifiers, - depth, - ), DieReference::UnitAndOffset((entry_unit, entry_offset)) => { resolve_namespace_name( - dwarf, - &entry_unit, + entry_unit, &entry_unit.entry(entry_offset).unwrap(), + debug_info_builder_context, namespace_qualifiers, depth, ) } + DieReference::Err => { + warn!( + "Failed to fetch DIE. Debug information may be incomplete." + ); + } } } else { namespace_qualifiers @@ -109,12 +109,18 @@ fn recover_names<R: Reader<Offset = usize>>( } } - resolve_namespace_name(dwarf, &unit, entry, &mut namespace_qualifiers, depth); + resolve_namespace_name( + &unit, + entry, + debug_info_builder_context, + &mut namespace_qualifiers, + depth, + ); } constants::DW_TAG_class_type | constants::DW_TAG_structure_type | constants::DW_TAG_union_type => { - if let Some(name) = get_name(dwarf, &unit, entry) { + if let Some(name) = get_name(&unit, entry, debug_info_builder_context) { namespace_qualifiers.push((depth, name)) } else { namespace_qualifiers.push(( @@ -128,7 +134,7 @@ fn recover_names<R: Reader<Offset = usize>>( .unwrap(), )) } - debug_info_builder.set_name( + debug_info_builder_context.set_name( get_uid(&unit, entry), CString::new( simplify_str_to_str( @@ -146,8 +152,8 @@ fn recover_names<R: Reader<Offset = usize>>( constants::DW_TAG_typedef | constants::DW_TAG_subprogram | constants::DW_TAG_enumeration_type => { - if let Some(name) = get_name(dwarf, &unit, entry) { - debug_info_builder.set_name( + if let Some(name) = get_name(&unit, entry, debug_info_builder_context) { + debug_info_builder_context.set_name( get_uid(&unit, entry), CString::new( simplify_str_to_str( @@ -167,24 +173,21 @@ fn recover_names<R: Reader<Offset = usize>>( } } _ => { - if let Some(name) = get_name(dwarf, &unit, entry) { - debug_info_builder.set_name(get_uid(&unit, entry), name); + if let Some(name) = get_name(&unit, entry, debug_info_builder_context) { + debug_info_builder_context.set_name(get_uid(&unit, entry), name); } } } } } - - total_die_count } fn parse_unit<R: Reader<Offset = usize>>( - dwarf: &Dwarf<R>, unit: &Unit<R>, + debug_info_builder_context: &DebugInfoBuilderContext<R>, debug_info_builder: &mut DebugInfoBuilder, progress: &dyn Fn(usize, usize) -> Result<(), ()>, current_die_number: &mut usize, - total_die_count: usize, ) { let mut entries = unit.entries(); @@ -192,16 +195,21 @@ fn parse_unit<R: Reader<Offset = usize>>( // There's a lot of junk we don't care about in DWARF info, so we choose a couple DIEs and mutate state (add functions (which adds the types it uses) and keep track of what namespace we're in) while let Ok(Some((_, entry))) = entries.next_dfs() { *current_die_number += 1; - if (*progress)(*current_die_number, total_die_count).is_err() { + if (*progress)( + *current_die_number, + debug_info_builder_context.total_die_count, + ) + .is_err() + { return; // Parsing canceled } match entry.tag() { constants::DW_TAG_subprogram => { - parse_function_entry(dwarf, unit, entry, debug_info_builder) + parse_function_entry(unit, entry, debug_info_builder_context, debug_info_builder) } constants::DW_TAG_variable => { - parse_data_variable(dwarf, unit, entry, debug_info_builder) + parse_data_variable(unit, entry, debug_info_builder_context, debug_info_builder) } _ => (), } @@ -237,29 +245,25 @@ fn parse_dwarf( // Since DWARF is stored as a tree with arbitrary implicit edges among leaves, // it is not possible to correctly track namespaces while you're parsing "in order" without backtracking, // so we just do it up front - let mut debug_info_builder = DebugInfoBuilder::new(view); - if (*progress)(0, 1).is_err() { - return debug_info_builder; // Parsing canceled - }; - let total_die_count = recover_names(&dwarf, &mut debug_info_builder, &progress); - if total_die_count == 0 { - return debug_info_builder; - } + let mut debug_info_builder = DebugInfoBuilder::new(); + if let Some(mut debug_info_builder_context) = DebugInfoBuilderContext::new(view, dwarf) { + recover_names(&mut debug_info_builder_context, &progress); + if debug_info_builder_context.total_die_count == 0 { + return debug_info_builder; + } - // Parse all the compilation units - let mut iter = dwarf.units(); - let mut current_die_number = 0; - while let Ok(Some(header)) = iter.next() { - parse_unit( - &dwarf, - &dwarf.unit(header).unwrap(), - &mut debug_info_builder, - &progress, - &mut current_die_number, - total_die_count, - ); + // Parse all the compilation units + let mut current_die_number = 0; + for unit in debug_info_builder_context.units() { + parse_unit( + unit, + &debug_info_builder_context, + &mut debug_info_builder, + &progress, + &mut current_die_number, + ); + } } - debug_info_builder } @@ -267,24 +271,20 @@ struct DWARFParser; impl CustomDebugInfoParser for DWARFParser { fn is_valid(&self, view: &BinaryView) -> bool { - Settings::new("").get_bool("corePlugins.dwarfImport", None, None) - && dwarfreader::is_valid(view) + dwarfreader::is_valid(view) } fn parse_info( &self, debug_info: &mut DebugInfo, - _: &BinaryView, + bv: &BinaryView, debug_file: &BinaryView, progress: Box<dyn Fn(usize, usize) -> Result<(), ()>>, ) -> bool { - if Settings::new("").get_bool("corePlugins.dwarfImport", None, None) { - // Parse dwarf info in raw view or from a separate file - parse_dwarf(debug_file, progress).commit_info(debug_info); - true - } else { - false - } + parse_dwarf(debug_file, progress) + .post_process(bv, debug_info) + .commit_info(debug_info); + true } } |
