@@ 1,4 1,5 @@
use crate::types;
+use anyhow::Result;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::hash::Hash;
@@ 100,7 101,7 @@ where
pub fn entry_int_attr<R>(
entry: &gimli::DebuggingInformationEntry<R>,
attr: gimli::DwAt,
-) -> gimli::Result<Option<u64>>
+) -> Result<Option<u64>>
where
R: gimli::Reader,
{
@@ 116,11 117,11 @@ where
gimli::AttributeValue::Data8(n) => n,
gimli::AttributeValue::Sdata(n) => n as u64,
gimli::AttributeValue::Udata(n) => n,
- av => panic!("unexpected attribute value for {}: {:?}", attr, av),
+ av => anyhow::bail!("unexpected attribute value for {}: {:?}", attr, av),
}))
}
-pub fn entry_byte_size<R>(entry: &gimli::DebuggingInformationEntry<R>) -> gimli::Result<Option<u64>>
+pub fn entry_byte_size<R>(entry: &gimli::DebuggingInformationEntry<R>) -> Result<Option<u64>>
where
R: gimli::Reader,
{
@@ 129,7 130,7 @@ where
pub fn entry_encoding<R>(
entry: &gimli::DebuggingInformationEntry<R>,
-) -> gimli::Result<Option<crate::types::Encoding>>
+) -> Result<Option<crate::types::Encoding>>
where
R: gimli::Reader,
{
@@ 140,7 141,7 @@ where
Ok(Some(match encoding_attr {
gimli::AttributeValue::Encoding(encoding) => crate::types::Encoding::try_from(encoding)
.map_err(|()| gimli::Error::Io /* TODO */)?,
- av => panic!("unexpected attribute value for DW_AT_encoding: {:?}", av),
+ av => anyhow::bail!("unexpected attribute value for DW_AT_encoding: {:?}", av),
}))
}
@@ 161,7 162,7 @@ pub fn entry_type<R>(
cache: &mut types::Cache<R>,
unit: &gimli::Unit<R>,
entry: &gimli::DebuggingInformationEntry<R>,
-) -> gimli::Result<Option<types::InstancePtr<R>>>
+) -> Result<Option<types::InstancePtr<R>>>
where
R: gimli::Reader,
{
@@ 189,7 190,7 @@ impl<'a, R> Sources<'a, R>
where
R: gimli::Reader + Eq + Hash,
{
- pub fn parse(dwarf: &'a gimli::Dwarf<R>) -> gimli::Result<Sources<'a, R>> {
+ pub fn parse(dwarf: &'a gimli::Dwarf<R>) -> Result<Sources<'a, R>> {
let mut subprograms = HashMap::new();
let mut type_cache = types::Cache::new(dwarf);
@@ 1,3 1,5 @@
+use anyhow::Context;
+use anyhow::Result;
use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::hash_map;
@@ 7,6 9,23 @@ use std::fmt;
use std::rc::Rc;
use std::rc::Weak;
+fn r<R>(val: &R) -> String
+where
+ R: gimli::Reader,
+{
+ val.to_string_lossy().unwrap().to_string()
+}
+
+fn or<R>(val: &Option<R>) -> String
+where
+ R: gimli::Reader,
+{
+ match val {
+ Some(val) => r(val),
+ None => String::new(),
+ }
+}
+
/// Description of how base types are encoded.
///
/// Enumeration version of `DW_AT_encoding` (see section 7.8).
@@ 306,10 325,12 @@ where
fn resolve_base_definition(
&mut self,
entry: &gimli::DebuggingInformationEntry<R>,
- ) -> gimli::Result<Definition<R>> {
+ ) -> Result<Definition<R>> {
Ok(Definition::Base {
- byte_size: crate::dwarf::entry_byte_size(entry)?.unwrap(),
- encoding: crate::dwarf::entry_encoding(entry)?.unwrap(),
+ byte_size: crate::dwarf::entry_byte_size(entry)?
+ .context("expected base type to have a byte size")?,
+ encoding: crate::dwarf::entry_encoding(entry)?
+ .context("expected base type to have an encoding")?,
})
}
@@ 317,12 338,16 @@ where
&mut self,
unit: &gimli::Unit<R>,
entry: &gimli::DebuggingInformationEntry<R>,
- ) -> gimli::Result<Definition<R>> {
- let byte_size = crate::dwarf::entry_byte_size(entry)?.unwrap();
+ ) -> Result<Definition<R>> {
+ let byte_size =
+ crate::dwarf::entry_byte_size(entry)?.context("expected enum to have a byte size")?;
let encoding = match crate::dwarf::entry_encoding(entry)? {
None => match crate::dwarf::entry_type(self, unit, entry)? {
None => {
- assert_eq!(byte_size, 1);
+ anyhow::ensure!(
+ byte_size == 1,
+ "expected type with a byte size greater than one to have an encoding",
+ );
Encoding::Unsigned
}
Some(type_) => match &type_
@@ 334,7 359,9 @@ where
.definition
{
Definition::Base { encoding, .. } => *encoding,
- unexpected => panic!("unexpected underlying type for enum: {:?}", unexpected),
+ unexpected => {
+ anyhow::bail!("unexpected underlying type for enum: {:?}", unexpected)
+ }
},
},
Some(encoding) => encoding,
@@ 346,8 373,10 @@ where
if child.tag() != gimli::DW_TAG_enumerator {
continue;
}
- let name = crate::dwarf::entry_name(self.dwarf, unit, child)?.unwrap();
- let value = crate::dwarf::entry_int_attr(child, gimli::DW_AT_const_value)?.unwrap();
+ let name = crate::dwarf::entry_name(self.dwarf, unit, child)?
+ .context("expected enum variant to have a name")?;
+ let value = crate::dwarf::entry_int_attr(child, gimli::DW_AT_const_value)?
+ .with_context(|| format!("expected enum variant {:?} to have a value", r(&name)))?;
enumerators.push(Enumerator { name, value });
}
@@ 362,7 391,7 @@ where
&mut self,
unit: &gimli::Unit<R>,
entry: &gimli::DebuggingInformationEntry<R>,
- ) -> gimli::Result<Definition<R>> {
+ ) -> Result<Definition<R>> {
let mut members = Vec::new();
let mut children = crate::dwarf::entry_children(unit, entry)?;
while let Some(child) = children.next()? {
@@ 370,9 399,16 @@ where
continue;
}
let name = crate::dwarf::entry_name(self.dwarf, unit, child)?;
- let location =
- crate::dwarf::entry_int_attr(child, gimli::DW_AT_data_member_location)?.unwrap();
- let type_ = crate::dwarf::entry_type(self, unit, child)?.unwrap();
+ let location = crate::dwarf::entry_int_attr(child, gimli::DW_AT_data_member_location)?
+ .with_context(|| {
+ format!(
+ "expected DW_AT_data_member_location on structure member {:?}",
+ or(&name),
+ )
+ })?;
+ let type_ = crate::dwarf::entry_type(self, unit, child)?.with_context(|| {
+ format!("expected structure member {:?} to have a type", or(&name))
+ })?;
members.push(Member {
name,
location,
@@ 386,7 422,7 @@ where
&mut self,
unit: &gimli::Unit<R>,
entry: &gimli::DebuggingInformationEntry<R>,
- ) -> gimli::Result<Definition<R>> {
+ ) -> Result<Definition<R>> {
let return_type = crate::dwarf::entry_type(self, unit, entry)?;
let mut parameters = Vec::new();
let mut children = crate::dwarf::entry_children(unit, entry)?;
@@ 394,7 430,8 @@ where
if child.tag() != gimli::DW_TAG_formal_parameter {
continue;
}
- let type_ = crate::dwarf::entry_type(self, unit, child)?.unwrap();
+ let type_ = crate::dwarf::entry_type(self, unit, child)?
+ .context("expected subroutine parameter to have a type")?;
parameters.push(type_);
}
Ok(Definition::Subroutine {
@@ 407,7 444,7 @@ where
&mut self,
unit: &gimli::Unit<R>,
entry: &gimli::DebuggingInformationEntry<R>,
- ) -> gimli::Result<Definition<R>> {
+ ) -> Result<Definition<R>> {
let mut members = Vec::new();
let mut children = crate::dwarf::entry_children(unit, entry)?;
while let Some(child) = children.next()? {
@@ 415,7 452,9 @@ where
continue;
}
let name = crate::dwarf::entry_name(self.dwarf, unit, child)?;
- let type_ = crate::dwarf::entry_type(self, unit, child)?.unwrap();
+ let type_ = crate::dwarf::entry_type(self, unit, child)?.with_context(|| {
+ format!("expected union variant {:?} to have a type", or(&name))
+ })?;
members.push(Member {
name,
location: 0,
@@ 429,8 468,11 @@ where
&mut self,
unit: &gimli::Unit<R>,
entry: &gimli::DebuggingInformationEntry<R>,
- ) -> gimli::Result<TypePtr<R>> {
- let entry_offset = entry.offset().to_debug_info_offset(&unit.header).unwrap();
+ ) -> Result<TypePtr<R>> {
+ let entry_offset = entry
+ .offset()
+ .to_debug_info_offset(&unit.header)
+ .context("unit offset couldn't be converted to a .debug_info offset")?;
// Allocate the definition and store it in the map in case the type is
// recursive.
@@ 448,13 490,21 @@ where
let name = crate::dwarf::entry_name(self.dwarf, unit, entry)?;
let definition = match entry.tag() {
- gimli::DW_TAG_base_type => self.resolve_base_definition(entry)?,
- gimli::DW_TAG_enumeration_type => self.resolve_enumeration_definition(unit, entry)?,
- gimli::DW_TAG_structure_type | gimli::DW_TAG_class_type => {
- self.resolve_structure_definition(unit, entry)?
- }
- gimli::DW_TAG_subroutine_type => self.resolve_subroutine_definition(unit, entry)?,
- gimli::DW_TAG_union_type => self.resolve_union_definition(unit, entry)?,
+ gimli::DW_TAG_base_type => self
+ .resolve_base_definition(entry)
+ .with_context(|| format!("failed to parse base type {:?}", or(&name)))?,
+ gimli::DW_TAG_enumeration_type => self
+ .resolve_enumeration_definition(unit, entry)
+ .with_context(|| format!("failed to parse enum {:?}", or(&name)))?,
+ gimli::DW_TAG_structure_type | gimli::DW_TAG_class_type => self
+ .resolve_structure_definition(unit, entry)
+ .with_context(|| format!("failed to parse structure {:?}", or(&name)))?,
+ gimli::DW_TAG_subroutine_type => self
+ .resolve_subroutine_definition(unit, entry)
+ .with_context(|| format!("failed to parse subroutine {:?}", or(&name)))?,
+ gimli::DW_TAG_union_type => self
+ .resolve_union_definition(unit, entry)
+ .with_context(|| format!("failed to union base type {:?}", or(&name)))?,
_ => unreachable!(),
};
@@ 467,8 517,10 @@ where
&mut self,
unit: &gimli::Unit<R>,
mut entry_offset: gimli::UnitOffset<R::Offset>,
- ) -> gimli::Result<InstancePtr<R>> {
- let absolute_offset = entry_offset.to_debug_info_offset(&unit.header).unwrap();
+ ) -> Result<InstancePtr<R>> {
+ let absolute_offset = entry_offset
+ .to_debug_info_offset(&unit.header)
+ .context("unit offset couldn't be converted to a .debug_info offset")?;
if let Some(instance) = self.instances.get(&absolute_offset) {
return Ok(Rc::clone(instance));
}
@@ 494,13 546,13 @@ where
gimli::DW_TAG_restrict_type => modifiers.push(Modifier::Restrict),
gimli::DW_TAG_volatile_type => modifiers.push(Modifier::Volatile),
gimli::DW_TAG_typedef => {}
- tag => panic!("unexpected tag: {}", tag),
+ tag => anyhow::bail!("unexpected tag for type: {}", tag),
}
if let Some(next_attr) = entry.attr_value(gimli::DW_AT_type)? {
entry_offset = match next_attr {
gimli::AttributeValue::UnitRef(offset) => offset,
- av => panic!("unexpected attribute value: {:?}", av),
+ av => anyhow::bail!("unexpected attribute value for type: {:?}", av),
};
continue;
}