summaryrefslogtreecommitdiff
path: root/rust/examples
diff options
context:
space:
mode:
authorKyleMiles <krm504@nyu.edu>2023-07-25 20:01:15 -0400
committerKyleMiles <krm504@nyu.edu>2023-07-25 20:01:15 -0400
commit3cf3924281802ce606757e4a707534bad6b1ccbb (patch)
treea28ccb72f621c1d4df46b8b95b3c3e167aa6f276 /rust/examples
parent5978a0ede2c071b547b692033f561641edc4ac37 (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.rs25
-rw-r--r--rust/examples/dwarf/dwarf_import/src/lib.rs33
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
}
}