diff options
| author | KyleMiles <krm504@nyu.edu> | 2023-07-25 20:01:15 -0400 |
|---|---|---|
| committer | KyleMiles <krm504@nyu.edu> | 2023-07-25 20:01:15 -0400 |
| commit | 3cf3924281802ce606757e4a707534bad6b1ccbb (patch) | |
| tree | a28ccb72f621c1d4df46b8b95b3c3e167aa6f276 /rust/examples | |
| parent | 5978a0ede2c071b547b692033f561641edc4ac37 (diff) | |
DWARF Import : Allow for duplicate type definitions; log_error when overwriting one type with another; add progress tracking; resolves #4514
Diffstat (limited to 'rust/examples')
| -rw-r--r-- | rust/examples/dwarf/dwarf_import/src/dwarfdebuginfo.rs | 25 | ||||
| -rw-r--r-- | rust/examples/dwarf/dwarf_import/src/lib.rs | 33 |
2 files changed, 49 insertions, 9 deletions
diff --git a/rust/examples/dwarf/dwarf_import/src/dwarfdebuginfo.rs b/rust/examples/dwarf/dwarf_import/src/dwarfdebuginfo.rs index 2403c879..f82174aa 100644 --- a/rust/examples/dwarf/dwarf_import/src/dwarfdebuginfo.rs +++ b/rust/examples/dwarf/dwarf_import/src/dwarfdebuginfo.rs @@ -146,10 +146,27 @@ impl DebugInfoBuilder { } pub fn add_type(&mut self, type_uid: TypeUID, name: CString, t: Ref<Type>, commit: bool) { - assert!(self - .types - .insert(type_uid, DebugType { name, t, commit }) - .is_none()); + if let Some(DebugType { + name: existing_name, + t: existing_type, + commit: _, + }) = self.types.insert( + type_uid, + DebugType { + name: name.clone(), + t: t.clone(), + commit, + }, + ) { + if existing_type != t { + error!("DWARF info contains duplicate type definition. Overwriting type `{}` (named `{:?}`) with `{}` (named `{:?}`)", + existing_type, + existing_name, + t, + name + ); + } + } } // TODO : Non-copy? diff --git a/rust/examples/dwarf/dwarf_import/src/lib.rs b/rust/examples/dwarf/dwarf_import/src/lib.rs index 0e5cfc6a..60239cb7 100644 --- a/rust/examples/dwarf/dwarf_import/src/lib.rs +++ b/rust/examples/dwarf/dwarf_import/src/lib.rs @@ -44,7 +44,8 @@ use std::ffi::CString; fn recover_names<R: Reader<Offset = usize>>( dwarf: &Dwarf<R>, debug_info_builder: &mut DebugInfoBuilder, -) { +) -> usize { + let mut total_die_count = 0; let mut iter = dwarf.units(); while let Some(header) = iter.next().unwrap() { let unit = dwarf.unit(header).unwrap(); @@ -55,9 +56,11 @@ 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; } while let Ok(Some((delta_depth, entry))) = entries.next_dfs() { + total_die_count += 1; depth += delta_depth; assert!(depth >= 0); @@ -158,18 +161,30 @@ fn recover_names<R: Reader<Offset = usize>>( } } } + + total_die_count } fn parse_unit<R: Reader<Offset = usize>>( dwarf: &Dwarf<R>, unit: &Unit<R>, debug_info_builder: &mut DebugInfoBuilder, + progress: &Box<dyn Fn(usize, usize) -> Result<(), ()>>, + total_die_count: usize, ) { let mut entries = unit.entries(); // Really all we care about as we iterate the entries in a given unit is how they modify state (our perception of the file) // 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) + let mut current_die_number = 0; while let Ok(Some((_, entry))) = entries.next_dfs() { + current_die_number += 1; + if current_die_number % 1000 == 0 + && (*progress)(current_die_number, total_die_count).is_err() + { + return; // Parsing canceled + } + match entry.tag() { constants::DW_TAG_subprogram => { parse_function_entry(dwarf, unit, entry, debug_info_builder) @@ -182,7 +197,10 @@ fn parse_unit<R: Reader<Offset = usize>>( } } -fn parse_dwarf(view: &BinaryView) -> DebugInfoBuilder { +fn parse_dwarf( + view: &BinaryView, + progress: Box<dyn Fn(usize, usize) -> Result<(), ()>>, +) -> DebugInfoBuilder { // Determine if this is a DWO // TODO : Make this more robust...some DWOs follow non-DWO conventions let dwo_file = is_dwo_dwarf(view) || is_raw_dwo_dwarf(view); @@ -208,7 +226,10 @@ fn parse_dwarf(view: &BinaryView) -> DebugInfoBuilder { // 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(); - recover_names(&dwarf, &mut debug_info_builder); + if (*progress)(0, 1).is_err() { + return debug_info_builder; // Parsing canceled + }; + let total_die_count = recover_names(&dwarf, &mut debug_info_builder); // Parse all the compilation units let mut iter = dwarf.units(); @@ -217,6 +238,8 @@ fn parse_dwarf(view: &BinaryView) -> DebugInfoBuilder { &dwarf, &dwarf.unit(header).unwrap(), &mut debug_info_builder, + &progress, + total_die_count, ); } @@ -235,10 +258,10 @@ impl CustomDebugInfoParser for DWARFParser { debug_info: &mut DebugInfo, _: &BinaryView, debug_file: &BinaryView, - _: Box<dyn Fn(usize, usize) -> Result<(), ()>>, + progress: Box<dyn Fn(usize, usize) -> Result<(), ()>>, ) -> bool { // Parse dwarf info in raw view or from a separate file - parse_dwarf(debug_file).commit_info(debug_info); + parse_dwarf(debug_file, progress).commit_info(debug_info); true } } |
