diff options
| author | Josh Ferrell <josh@vector35.com> | 2025-10-12 15:58:05 -0400 |
|---|---|---|
| committer | Josh Ferrell <josh@vector35.com> | 2025-10-12 15:58:05 -0400 |
| commit | 49558b88ed5dacaac0bdf1946291bc37a4a88cb9 (patch) | |
| tree | 8a91157664f21f98566c456dbb3f850970ac52dd /plugins/dwarf | |
| parent | 573b03c844090b53fb49b2156deae7540c8c3059 (diff) | |
Replace calls to unwrap() in dwarf_import
Diffstat (limited to 'plugins/dwarf')
| -rw-r--r-- | plugins/dwarf/dwarf_import/build.rs | 7 | ||||
| -rw-r--r-- | plugins/dwarf/dwarf_import/src/die_handlers.rs | 228 | ||||
| -rw-r--r-- | plugins/dwarf/dwarf_import/src/dwarfdebuginfo.rs | 120 | ||||
| -rw-r--r-- | plugins/dwarf/dwarf_import/src/functions.rs | 32 | ||||
| -rw-r--r-- | plugins/dwarf/dwarf_import/src/helpers.rs | 80 | ||||
| -rw-r--r-- | plugins/dwarf/dwarf_import/src/lib.rs | 54 | ||||
| -rw-r--r-- | plugins/dwarf/dwarf_import/src/types.rs | 87 |
7 files changed, 424 insertions, 184 deletions
diff --git a/plugins/dwarf/dwarf_import/build.rs b/plugins/dwarf/dwarf_import/build.rs index 9006f16a..8cbaf2b1 100644 --- a/plugins/dwarf/dwarf_import/build.rs +++ b/plugins/dwarf/dwarf_import/build.rs @@ -3,7 +3,12 @@ fn main() { .expect("DEP_BINARYNINJACORE_PATH not specified"); println!("cargo::rustc-link-lib=dylib=binaryninjacore"); - println!("cargo::rustc-link-search={}", link_path.to_str().unwrap()); + println!( + "cargo::rustc-link-search={}", + link_path + .to_str() + .expect("Failed to convert link path to string") + ); #[cfg(target_os = "linux")] { diff --git a/plugins/dwarf/dwarf_import/src/die_handlers.rs b/plugins/dwarf/dwarf_import/src/die_handlers.rs index f71fdabc..da9f1b7d 100644 --- a/plugins/dwarf/dwarf_import/src/die_handlers.rs +++ b/plugins/dwarf/dwarf_import/src/die_handlers.rs @@ -106,8 +106,23 @@ pub(crate) fn handle_enum<R: ReaderType>( let mut enumeration_builder = EnumerationBuilder::new(); - let mut tree = unit.entries_tree(Some(entry.offset())).unwrap(); - let mut children = tree.root().unwrap().children(); + let mut tree = match unit.entries_tree(Some(entry.offset())) { + Ok(x) => x, + Err(e) => { + log::error!("Failed to get enum entry tree: {}", e); + return None; + } + }; + + let tree_root = match tree.root() { + Ok(x) => x, + Err(e) => { + log::error!("Failed to get enum entry tree root: {}", e); + return None; + } + }; + + let mut children = tree_root.children(); while let Ok(Some(child)) = children.next() { if child.entry().tag() == constants::DW_TAG_enumerator { let name = debug_info_builder_context.get_name(dwarf, unit, child.entry())?; @@ -183,49 +198,32 @@ pub(crate) fn handle_pointer<R: ReaderType>( // ?DW_AT_data_location // * = Optional - if let Some(pointer_size) = get_size_as_usize(entry) { - if let Some(entry_type_offset) = entry_type { - let parent_type = debug_info_builder - .get_type(entry_type_offset) - .unwrap() - .get_type(); - Some(Type::pointer_of_width( - parent_type.as_ref(), - pointer_size, - false, - false, - Some(reference_type), - )) - } else { - Some(Type::pointer_of_width( - Type::void().as_ref(), - pointer_size, - false, - false, - Some(reference_type), - )) - } - } else if let Some(entry_type_offset) = entry_type { - let parent_type = debug_info_builder + let pointer_size = match get_size_as_usize(entry) { + Some(x) => x, + None => debug_info_builder_context.default_address_size(), + }; + + let target_type = match entry_type { + Some(entry_type_offset) => debug_info_builder .get_type(entry_type_offset) - .unwrap() - .get_type(); - Some(Type::pointer_of_width( - parent_type.as_ref(), - debug_info_builder_context.default_address_size(), - false, - false, - Some(reference_type), - )) - } else { - Some(Type::pointer_of_width( - Type::void().as_ref(), - debug_info_builder_context.default_address_size(), - false, - false, - Some(reference_type), - )) - } + .or_else(|| { + log::error!( + "Failed to get pointer target type at entry offset {}", + entry_type_offset + ); + None + })? + .get_type(), + None => Type::void(), + }; + + Some(Type::pointer_of_width( + target_type.as_ref(), + pointer_size, + false, + false, + Some(reference_type), + )) } pub(crate) fn handle_array<R: ReaderType>( @@ -246,35 +244,51 @@ pub(crate) fn handle_array<R: ReaderType>( // * = Optional // For multidimensional arrays, DW_TAG_subrange_type or DW_TAG_enumeration_type - if let Some(entry_type_offset) = entry_type { - let parent_type = debug_info_builder - .get_type(entry_type_offset) - .unwrap() - .get_type(); - - let mut tree = unit.entries_tree(Some(entry.offset())).unwrap(); - let mut children = tree.root().unwrap().children(); + let entry_type_offset = entry_type?; + let parent_type = debug_info_builder + .get_type(entry_type_offset) + .or_else(|| { + log::error!( + "Failed to get array member type at entry offset {}", + entry_type_offset + ); + None + })? + .get_type(); - // TODO : This is currently applying the size in reverse order - let mut result_type: Option<Ref<Type>> = None; - while let Ok(Some(child)) = children.next() { - if let Some(inner_type) = result_type { - result_type = Some(Type::array( - inner_type.as_ref(), - get_subrange_size(child.entry()), - )); - } else { - result_type = Some(Type::array( - parent_type.as_ref(), - get_subrange_size(child.entry()), - )); - } + let mut tree = match unit.entries_tree(Some(entry.offset())) { + Ok(x) => x, + Err(e) => { + log::error!("Failed to get array entry tree: {}", e); + return None; } + }; + let tree_root = match tree.root() { + Ok(x) => x, + Err(e) => { + log::error!("Failed to get array entry tree root: {}", e); + return None; + } + }; + let mut children = tree_root.children(); - result_type.map_or(Some(Type::array(parent_type.as_ref(), 0)), Some) - } else { - None + // TODO : This is currently applying the size in reverse order + let mut result_type: Option<Ref<Type>> = None; + while let Ok(Some(child)) = children.next() { + if let Some(inner_type) = result_type { + result_type = Some(Type::array( + inner_type.as_ref(), + get_subrange_size(child.entry()), + )); + } else { + result_type = Some(Type::array( + parent_type.as_ref(), + get_subrange_size(child.entry()), + )); + } } + + result_type.map_or(Some(Type::array(parent_type.as_ref(), 0)), Some) } pub(crate) fn handle_function<R: ReaderType>( @@ -327,8 +341,23 @@ pub(crate) fn handle_function<R: ReaderType>( let mut variable_arguments = false; // Get all the children and populate - let mut tree = unit.entries_tree(Some(entry.offset())).unwrap(); - let mut children = tree.root().unwrap().children(); + let mut tree = match unit.entries_tree(Some(entry.offset())) { + Ok(x) => x, + Err(e) => { + log::error!("Failed to get function entry tree: {}", e); + return None; + } + }; + + let tree_root = match tree.root() { + Ok(x) => x, + Err(e) => { + log::error!("Failed to get function entry tree root: {}", e); + return None; + } + }; + + let mut children = tree_root.children(); while let Ok(Some(child)) = children.next() { if child.entry().tag() == constants::DW_TAG_formal_parameter { if let (Some(child_uid), Some(name)) = { @@ -343,7 +372,16 @@ pub(crate) fn handle_function<R: ReaderType>( debug_info_builder_context.get_name(dwarf, unit, child.entry()), ) } { - let child_type = debug_info_builder.get_type(child_uid).unwrap().get_type(); + let child_type = debug_info_builder + .get_type(child_uid) + .or_else(|| { + log::error!( + "Failed to get function parameter type with uid {}", + child_uid + ); + None + })? + .get_type(); parameters.push(FunctionParameter::new(child_type, name, None)); } } else if child.entry().tag() == constants::DW_TAG_unspecified_parameters { @@ -373,15 +411,22 @@ pub(crate) fn handle_const( // ?DW_AT_sibling // ?DW_AT_type - if let Some(entry_type_offset) = entry_type { - let parent_type = debug_info_builder + let target_type_builder = match entry_type { + Some(entry_type_offset) => debug_info_builder .get_type(entry_type_offset) - .unwrap() - .get_type(); - Some((*parent_type).to_builder().set_const(true).finalize()) - } else { - Some(TypeBuilder::void().set_const(true).finalize()) - } + .or_else(|| { + log::error!( + "Failed to get const type with entry offset {}", + entry_type_offset + ); + None + })? + .get_type() + .to_builder(), + None => TypeBuilder::void(), + }; + + Some(target_type_builder.set_const(true).finalize()) } pub(crate) fn handle_volatile( @@ -396,13 +441,20 @@ pub(crate) fn handle_volatile( // ?DW_AT_sibling // ?DW_AT_type - if let Some(entry_type_offset) = entry_type { - let parent_type = debug_info_builder + let target_type_builder = match entry_type { + Some(entry_type_offset) => debug_info_builder .get_type(entry_type_offset) - .unwrap() - .get_type(); - Some((*parent_type).to_builder().set_volatile(true).finalize()) - } else { - Some(TypeBuilder::void().set_volatile(true).finalize()) - } + .or_else(|| { + log::error!( + "Failed to get volatile type with entry offset {}", + entry_type_offset + ); + None + })? + .get_type() + .to_builder(), + None => TypeBuilder::void(), + }; + + Some(target_type_builder.set_volatile(true).finalize()) } diff --git a/plugins/dwarf/dwarf_import/src/dwarfdebuginfo.rs b/plugins/dwarf/dwarf_import/src/dwarfdebuginfo.rs index 2dff2b35..0dc6b7fb 100644 --- a/plugins/dwarf/dwarf_import/src/dwarfdebuginfo.rs +++ b/plugins/dwarf/dwarf_import/src/dwarfdebuginfo.rs @@ -189,7 +189,18 @@ impl<R: ReaderType> DebugInfoBuilderContext<R> { .get(&get_uid( dwarf, entry_unit, - &entry_unit.entry(entry_offset).unwrap(), + match &entry_unit.entry(entry_offset) { + Ok(x) => x, + Err(e) => { + log::error!( + "Failed to get entry {:?} in unit {:?}: {}", + entry_offset, + entry_unit.header.offset(), + e + ); + return None; + } + }, )) .cloned(), DieReference::Err => None, @@ -252,11 +263,15 @@ impl DebugInfoBuilder { // update the function // if the full name exists, update the stored index for the full name if let Some(idx) = self.raw_function_name_indices.get(ident) { - let function = self.functions.get_mut(*idx).unwrap(); + let function = self.functions.get_mut(*idx).or_else(|| { + log::error!("Failed to get function with index {}", idx); + None + })?; - if function.full_name.is_some() && function.full_name != full_name { - self.full_function_name_indices - .remove(function.full_name.as_ref().unwrap()); + if function.full_name != full_name { + if let Some(existing_full_name) = &function.full_name { + self.full_function_name_indices.remove(existing_full_name); + } } function.update( @@ -268,9 +283,9 @@ impl DebugInfoBuilder { frame_base, ); - if function.full_name.is_some() { + if let Some(existing_full_name) = &function.full_name { self.full_function_name_indices - .insert(function.full_name.clone().unwrap(), *idx); + .insert(existing_full_name.clone(), *idx); } return Some(*idx); @@ -281,11 +296,15 @@ impl DebugInfoBuilder { // update the function // if the raw name exists, update the stored index for the raw name if let Some(idx) = self.full_function_name_indices.get(ident) { - let function = self.functions.get_mut(*idx).unwrap(); + let function = self.functions.get_mut(*idx).or_else(|| { + log::error!("Failed to get function with index {}", idx); + None + })?; - if function.raw_name.is_some() && function.raw_name != raw_name { - self.raw_function_name_indices - .remove(function.raw_name.as_ref().unwrap()); + if function.raw_name != raw_name { + if let Some(existing_raw_name) = &function.raw_name { + self.raw_function_name_indices.remove(existing_raw_name); + } } function.update( @@ -297,9 +316,9 @@ impl DebugInfoBuilder { frame_base, ); - if function.raw_name.is_some() { + if let Some(existing_raw_name) = &function.raw_name { self.raw_function_name_indices - .insert(function.raw_name.clone().unwrap(), *idx); + .insert(existing_raw_name.clone(), *idx); } return Some(*idx); @@ -412,10 +431,11 @@ impl DebugInfoBuilder { }; // Either get the known type or use a 0 confidence void type so we at least get the name applied - let ty = match type_uid { - Some(uid) => Conf::new(self.get_type(uid).unwrap().ty.clone(), 128), - None => Conf::new(Type::void(), 0), - }; + let ty = type_uid + .and_then(|uid| self.get_type(uid)) + .map(|t| Conf::new(t.ty.clone(), 128)) + .unwrap_or_else(|| Conf::new(Type::void(), 0)); + let function = &mut self.functions[function_index]; // TODO: If we can't find a known offset can we try to guess somehow? @@ -503,11 +523,32 @@ impl DebugInfoBuilder { if let Some((_existing_name, existing_type_uid)) = self.data_variables.insert(address, (name, type_uid)) { - let existing_type = self.get_type(existing_type_uid).unwrap().ty.as_ref(); - let new_type = self.get_type(type_uid).unwrap().ty.as_ref(); + let existing_type = match self.get_type(existing_type_uid) { + Some(x) => x.ty.as_ref(), + None => { + log::error!( + "Failed to find existing type with uid {} for data variable at {:#x}", + existing_type_uid, + address + ); + return; + } + }; + + let new_type = match self.get_type(type_uid) { + Some(x) => x.ty.as_ref(), + None => { + log::error!( + "Failed to find new type with uid {} for data variable at {:#x}", + type_uid, + address + ); + return; + } + }; if existing_type_uid != type_uid || existing_type != new_type { - warn!("DWARF info contains duplicate data variable definition. Overwriting data variable at 0x{:08x} (`{}`) with `{}`", + warn!("DWARF info contains duplicate data variable definition. Overwriting data variable at {:#08x} (`{}`) with `{}`", address, existing_type, new_type @@ -575,9 +616,16 @@ impl DebugInfoBuilder { // TODO : Consume data? fn commit_data_variables(&self, debug_info: &mut DebugInfo) { for (&address, (name, type_uid)) in &self.data_variables { + let data_var_type = match self.get_type(*type_uid) { + Some(x) => &x.ty, + None => { + log::error!("Failed to find type for data variable at {:#x}", address); + continue; + } + }; assert!(debug_info.add_data_variable( address, - &self.get_type(*type_uid).unwrap().ty, + data_var_type, name.as_deref(), &[] // TODO : Components )); @@ -585,24 +633,26 @@ impl DebugInfoBuilder { } fn get_function_type(&self, function: &FunctionInfoBuilder) -> Ref<Type> { - let return_type = match function.return_type { - Some(return_type_id) => { - Conf::new(self.get_type(return_type_id).unwrap().ty.clone(), 128) - } - _ => Conf::new(Type::void(), 0), - }; + let return_type = function + .return_type + .and_then(|return_type_id| self.get_type(return_type_id)) + .map(|t| Conf::new(t.ty.clone(), 128)) + .unwrap_or_else(|| Conf::new(Type::void(), 0)); let parameters: Vec<FunctionParameter> = function .parameters .iter() - .filter_map(|parameter| match parameter { - Some((name, 0)) => Some(FunctionParameter::new(Type::void(), name.clone(), None)), - Some((name, uid)) => Some(FunctionParameter::new( - self.get_type(*uid).unwrap().ty.clone(), - name.clone(), - None, - )), - _ => None, + .filter_map(|parameter| { + parameter.as_ref().map(|(name, uid)| { + let ty = match uid { + 0 => Type::void(), + uid => self + .get_type(*uid) + .map(|t| t.ty.clone()) + .unwrap_or_else(Type::void), + }; + FunctionParameter::new(ty, name.clone(), None) + }) }) .collect(); diff --git a/plugins/dwarf/dwarf_import/src/functions.rs b/plugins/dwarf/dwarf_import/src/functions.rs index 5f7b0e42..532b88a2 100644 --- a/plugins/dwarf/dwarf_import/src/functions.rs +++ b/plugins/dwarf/dwarf_import/src/functions.rs @@ -42,13 +42,25 @@ fn get_parameters<R: ReaderType>( } // We make a new tree from the current entry to iterate over its children - let mut sub_die_tree = unit.entries_tree(Some(entry.offset())).unwrap(); - let root = sub_die_tree.root().unwrap(); + let mut sub_die_tree = match unit.entries_tree(Some(entry.offset())) { + Ok(x) => x, + Err(e) => { + log::error!("Failed to get function parameter entry tree: {}", e); + return (vec![], false); + } + }; + let root = match sub_die_tree.root() { + Ok(x) => x, + Err(e) => { + log::error!("Failed to get function parameter entry tree root: {}", e); + return (vec![], false); + } + }; let mut variable_arguments = false; let mut result = vec![]; let mut children = root.children(); - while let Some(child) = children.next().unwrap() { + while let Ok(Some(child)) = children.next() { match child.entry().tag() { constants::DW_TAG_formal_parameter => { //TODO: if the param type is a typedef to an anonymous struct (typedef struct {...} foo) then this is reoslved to an anonymous struct instead of foo @@ -118,7 +130,8 @@ pub(crate) fn parse_function_entry<R: ReaderType>( }); static ABI_REGEX_MEM: OnceLock<Regex> = OnceLock::new(); - let abi_regex = ABI_REGEX_MEM.get_or_init(|| Regex::new(r"\[abi:v\d+\]").unwrap()); + let abi_regex = ABI_REGEX_MEM + .get_or_init(|| Regex::new(r"\[abi:v\d+\]").expect("Failed to generate ABI regex")); if let Ok(sym) = cpp_demangle::Symbol::new(possibly_mangled_name) { if let Ok(demangled) = sym.demangle(demangle_options) { let cleaned = abi_regex.replace_all(&demangled, ""); @@ -187,8 +200,15 @@ pub(crate) fn parse_lexical_block<R: ReaderType>( } } } else if let Ok(Some(low_pc_value)) = entry.attr_value(constants::DW_AT_low_pc) { + let unit_base = match unit.header.offset().as_debug_info_offset() { + Some(x) => x.0, + None => { + log::warn!("Unable to get unit offset in debug info: {:?}. This may be an indicator of parsing issues.", unit.header.offset()); + 0 + } + }; + let Ok(Some(low_pc)) = dwarf.attr_address(unit, low_pc_value.clone()) else { - let unit_base: usize = unit.header.offset().as_debug_info_offset().unwrap().0; error!( "Failed to read lexical block low_pc for entry {:#x}, please report this bug.", unit_base + entry.offset().0 @@ -197,7 +217,6 @@ pub(crate) fn parse_lexical_block<R: ReaderType>( }; let Ok(Some(high_pc_value)) = entry.attr_value(constants::DW_AT_high_pc) else { - let unit_base: usize = unit.header.offset().as_debug_info_offset().unwrap().0; error!("Failed to read lexical block high_pc attribute for entry {:#x}, please report this bug.", unit_base + entry.offset().0); return None; }; @@ -207,7 +226,6 @@ pub(crate) fn parse_lexical_block<R: ReaderType>( .and_then(|x| Some(low_pc + x)) .or_else(|| dwarf.attr_address(unit, high_pc_value).unwrap_or(None)) else { - let unit_base: usize = unit.header.offset().as_debug_info_offset().unwrap().0; error!( "Failed to read lexical block high_pc for entry {:#x}, please report this bug.", unit_base + entry.offset().0 diff --git a/plugins/dwarf/dwarf_import/src/helpers.rs b/plugins/dwarf/dwarf_import/src/helpers.rs index 0ab9ab95..35580ad3 100644 --- a/plugins/dwarf/dwarf_import/src/helpers.rs +++ b/plugins/dwarf/dwarf_import/src/helpers.rs @@ -110,11 +110,14 @@ pub(crate) fn get_attr_die<'a, R: ReaderType>( Ok(Some(DebugInfoRefSup(offset))) => { for source_unit in debug_info_builder_context.sup_units() { if let Some(new_offset) = offset.to_unit_offset(&source_unit.header) { - return Some(DieReference::UnitAndOffset(( - dwarf.sup().unwrap(), - source_unit, - new_offset, - ))); + let sup: &Dwarf<R> = match dwarf.sup() { + Some(x) => x, + None => { + log::error!("Trying to get offset in supplmentary dwarf info, but none is present"); + return None; + } + }; + return Some(DieReference::UnitAndOffset((sup, source_unit, new_offset))); } } warn!("Failed to fetch DIE. Supplementary debug information may be incomplete."); @@ -185,11 +188,18 @@ pub(crate) fn get_name<R: ReaderType>( ) -> Option<String> { match resolve_specification(dwarf, unit, entry, debug_info_builder_context) { DieReference::UnitAndOffset((dwarf, entry_unit, entry_offset)) => { - if let Ok(Some(attr_val)) = entry_unit - .entry(entry_offset) - .unwrap() - .attr_value(constants::DW_AT_name) - { + let resolved_entry = match entry_unit.entry(entry_offset) { + Ok(x) => x, + Err(_) => { + log::error!( + "Failed to get entry in unit at {:?} at offset {:#x} (get_name)", + entry_unit.header.offset(), + entry_offset.0 + ); + return None; + } + }; + if let Ok(Some(attr_val)) = resolved_entry.attr_value(constants::DW_AT_name) { if let Ok(attr_string) = dwarf.attr_string(entry_unit, attr_val.clone()) { if let Ok(attr_string) = attr_string.to_string() { return Some(attr_string.to_string()); @@ -225,11 +235,19 @@ pub(crate) fn get_raw_name<R: ReaderType>( ) -> Option<String> { match resolve_specification(dwarf, unit, entry, debug_info_builder_context) { DieReference::UnitAndOffset((dwarf, entry_unit, entry_offset)) => { - if let Ok(Some(attr_val)) = entry_unit - .entry(entry_offset) - .unwrap() - .attr_value(constants::DW_AT_linkage_name) - { + let resolved_entry = match entry_unit.entry(entry_offset) { + Ok(x) => x, + Err(_) => { + log::error!( + "Failed to get entry in unit at {:?} at offset {:#x} (get_raw_name)", + entry_unit.header.offset(), + entry_offset.0 + ); + return None; + } + }; + + if let Ok(Some(attr_val)) = resolved_entry.attr_value(constants::DW_AT_linkage_name) { if let Ok(attr_string) = dwarf.attr_string(entry_unit, attr_val.clone()) { if let Ok(attr_string) = attr_string.to_string() { return Some(attr_string.to_string()); @@ -379,22 +397,26 @@ pub(crate) fn get_build_id(view: &BinaryView) -> Result<String, String> { return Err("Build id section must be at least 12 bytes".to_string()); } - let name_len: u32; - let desc_len: u32; - let note_type: u32; - match raw_view.default_endianness() { - Endianness::LittleEndian => { - name_len = u32::from_le_bytes(build_id_bytes[0..4].try_into().unwrap()); - desc_len = u32::from_le_bytes(build_id_bytes[4..8].try_into().unwrap()); - note_type = u32::from_le_bytes(build_id_bytes[8..12].try_into().unwrap()); - } - Endianness::BigEndian => { - name_len = u32::from_be_bytes(build_id_bytes[0..4].try_into().unwrap()); - desc_len = u32::from_be_bytes(build_id_bytes[4..8].try_into().unwrap()); - note_type = u32::from_be_bytes(build_id_bytes[8..12].try_into().unwrap()); - } + let conversion_func = match raw_view.default_endianness() { + Endianness::LittleEndian => u32::from_le_bytes, + Endianness::BigEndian => u32::from_be_bytes, }; + let name_len = build_id_bytes[0..4] + .try_into() + .map_err(|e| format!("Failed to get name length: {}", e)) + .map(|byte_val| conversion_func(byte_val))?; + + let desc_len = build_id_bytes[4..8] + .try_into() + .map_err(|e| format!("Failed to get desc length: {}", e)) + .map(|byte_val| conversion_func(byte_val))?; + + let note_type = build_id_bytes[8..12] + .try_into() + .map_err(|e| format!("Failed to get note type: {}", e)) + .map(|byte_val| conversion_func(byte_val))?; + if note_type != 3 { return Err(format!("Build id section has wrong type: {}", note_type)); } diff --git a/plugins/dwarf/dwarf_import/src/lib.rs b/plugins/dwarf/dwarf_import/src/lib.rs index 6e6613a0..ebe3c301 100644 --- a/plugins/dwarf/dwarf_import/src/lib.rs +++ b/plugins/dwarf/dwarf_import/src/lib.rs @@ -121,8 +121,20 @@ fn recover_names_internal<R: ReaderType>( let mut iter = dwarf.units(); let mut current_byte_offset: usize = 0; while let Ok(Some(header)) = iter.next() { - let unit_offset = header.offset().as_debug_info_offset().unwrap().0; - let unit = dwarf.unit(header).unwrap(); + let unit_offset = header.offset().as_debug_info_offset().map_or_else( + || { + log::warn!("Failed to get debug info offset for {:?}", header.offset()); + 0 + }, + |x| x.0, + ); + let unit = match dwarf.unit(header) { + Ok(x) => x, + Err(e) => { + log::error!("Failed to get unit at {:#x}: {}", unit_offset, e); + continue; + } + }; let mut namespace_qualifiers: Vec<(isize, String)> = vec![]; let mut entries = unit.entries(); let mut depth = 0; @@ -178,10 +190,17 @@ fn recover_names_internal<R: ReaderType>( ) { match die_reference { DieReference::UnitAndOffset((dwarf, entry_unit, entry_offset)) => { + let resolved_entry = match entry_unit.entry(entry_offset) { + Ok(x) => x, + Err(e) => { + log::error!("Failed to resolve entry in unit {:?} at offset {:#x} (resolve_namespace_name): {}", entry_unit, entry_offset.0, e); + return; + } + }; resolve_namespace_name( dwarf, entry_unit, - &entry_unit.entry(entry_offset).unwrap(), + &resolved_entry, debug_info_builder_context, namespace_qualifiers, depth, @@ -525,7 +544,13 @@ fn parse_range_data_offsets( let eh_frame_section_reader = |section_id: SectionId| -> _ { create_section_reader(section_id, bv, eh_frame_endian, dwo_file) }; - let mut eh_frame = gimli::EhFrame::load(eh_frame_section_reader).unwrap(); + let mut eh_frame = match gimli::EhFrame::load(eh_frame_section_reader) { + Ok(x) => x, + Err(e) => { + log::error!("Failed to load EH frame: {}", e); + return None; + } + }; if let Some(view_arch) = bv.default_arch() { if view_arch.name().as_str() == "aarch64" { eh_frame.set_vendor(gimli::Vendor::AArch64); @@ -543,7 +568,13 @@ fn parse_range_data_offsets( let debug_frame_section_reader = |section_id: SectionId| -> _ { create_section_reader(section_id, bv, debug_frame_endian, dwo_file) }; - let mut debug_frame = gimli::DebugFrame::load(debug_frame_section_reader).unwrap(); + let mut debug_frame = match gimli::DebugFrame::load(debug_frame_section_reader) { + Ok(x) => x, + Err(e) => { + log::error!("Failed to load debug frame: {}", e); + return None; + } + }; if let Some(view_arch) = bv.default_arch() { if view_arch.name().as_str() == "aarch64" { debug_frame.set_vendor(gimli::Vendor::AArch64); @@ -649,8 +680,17 @@ fn parse_dwarf( let mut current_die_number = 0; for unit in debug_info_builder_context.sup_units() { + let sup = match dwarf.sup() { + Some(x) => x, + None => { + log::error!( + "Supplemental units found but no supplementary DWARF info available" + ); + break; + } + }; parse_unit( - dwarf.sup().unwrap(), + sup, unit, &debug_info_builder_context, &mut debug_info_builder, @@ -717,7 +757,7 @@ impl CustomDebugInfoParser for DWARFParser { .and_then(|build_id| { load_debug_info_for_build_id(&build_id, bv) .0 - .map(|x| x.raw_view().unwrap()) + .map(|x| x.raw_view().expect("Failed to get raw view")) }); let result = match parse_dwarf( diff --git a/plugins/dwarf/dwarf_import/src/types.rs b/plugins/dwarf/dwarf_import/src/types.rs index 78992510..822c0668 100644 --- a/plugins/dwarf/dwarf_import/src/types.rs +++ b/plugins/dwarf/dwarf_import/src/types.rs @@ -175,8 +175,21 @@ fn do_structure_parse<R: ReaderType>( // Get all the children and base classes to populate let mut base_structures = Vec::new(); - let mut tree = unit.entries_tree(Some(entry.offset())).unwrap(); - let mut children = tree.root().unwrap().children(); + let mut tree = match unit.entries_tree(Some(entry.offset())) { + Ok(x) => x, + Err(e) => { + log::error!("Failed to get structure entry tree: {}", e); + return None; + } + }; + let tree_root = match tree.root() { + Ok(x) => x, + Err(e) => { + log::error!("Failed to get structure entry tree root: {}", e); + return None; + } + }; + let mut children = tree_root.children(); while let Ok(Some(child)) = children.next() { match child.entry().tag() { constants::DW_TAG_member => { @@ -315,13 +328,27 @@ pub(crate) fn get_type<R: ReaderType>( ) { // This needs to recurse first (before the early return below) to ensure all sub-types have been parsed match die_reference { - DieReference::UnitAndOffset((dwarf, entry_unit, entry_offset)) => get_type( - dwarf, - entry_unit, - &entry_unit.entry(entry_offset).unwrap(), - debug_info_builder_context, - debug_info_builder, - ), + DieReference::UnitAndOffset((dwarf, entry_unit, entry_offset)) => { + let resolved_entry = match entry_unit.entry(entry_offset) { + Ok(x) => x, + Err(e) => { + log::error!( + "Failed to resolve entry in unit {:?} at offset {:#x}: {}", + entry_unit, + entry_offset.0, + e + ); + return None; + } + }; + get_type( + dwarf, + entry_unit, + &resolved_entry, + debug_info_builder_context, + debug_info_builder, + ) + } DieReference::Err => { warn!("Failed to fetch DIE when getting type through DW_AT_type. Debug information may be incomplete."); None @@ -336,13 +363,27 @@ pub(crate) fn get_type<R: ReaderType>( ) { // This needs to recurse first (before the early return below) to ensure all sub-types have been parsed match die_reference { - DieReference::UnitAndOffset((dwarf, entry_unit, entry_offset)) => get_type( - dwarf, - entry_unit, - &entry_unit.entry(entry_offset).unwrap(), - debug_info_builder_context, - debug_info_builder, - ), + DieReference::UnitAndOffset((dwarf, entry_unit, entry_offset)) => { + let resolved_entry = match entry_unit.entry(entry_offset) { + Ok(x) => x, + Err(e) => { + log::error!( + "Failed to resolve entry in unit {:?} at offset {:#x}: {}", + entry_unit, + entry_offset.0, + e + ); + return None; + } + }; + get_type( + dwarf, + entry_unit, + &resolved_entry, + debug_info_builder_context, + debug_info_builder, + ) + } DieReference::Err => { warn!("Failed to fetch DIE when getting type through DW_AT_abstract_origin. Debug information may be incomplete."); None @@ -355,10 +396,22 @@ pub(crate) fn get_type<R: ReaderType>( if entry_unit.header.offset() != unit.header.offset() && entry_offset != entry.offset() => { + let resolved_entry = match entry_unit.entry(entry_offset) { + Ok(x) => x, + Err(e) => { + log::error!( + "Failed to resolve entry in unit {:?} at offset {:#x}: {}", + entry_unit, + entry_offset.0, + e + ); + return None; + } + }; get_type( dwarf, entry_unit, - &entry_unit.entry(entry_offset).unwrap(), + &resolved_entry, debug_info_builder_context, debug_info_builder, ) |
