summaryrefslogtreecommitdiff
path: root/plugins/dwarf
diff options
context:
space:
mode:
authorJosh Ferrell <josh@vector35.com>2025-10-12 15:58:05 -0400
committerJosh Ferrell <josh@vector35.com>2025-10-12 15:58:05 -0400
commit49558b88ed5dacaac0bdf1946291bc37a4a88cb9 (patch)
tree8a91157664f21f98566c456dbb3f850970ac52dd /plugins/dwarf
parent573b03c844090b53fb49b2156deae7540c8c3059 (diff)
Replace calls to unwrap() in dwarf_import
Diffstat (limited to 'plugins/dwarf')
-rw-r--r--plugins/dwarf/dwarf_import/build.rs7
-rw-r--r--plugins/dwarf/dwarf_import/src/die_handlers.rs228
-rw-r--r--plugins/dwarf/dwarf_import/src/dwarfdebuginfo.rs120
-rw-r--r--plugins/dwarf/dwarf_import/src/functions.rs32
-rw-r--r--plugins/dwarf/dwarf_import/src/helpers.rs80
-rw-r--r--plugins/dwarf/dwarf_import/src/lib.rs54
-rw-r--r--plugins/dwarf/dwarf_import/src/types.rs87
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,
)