diff --git a/src/read/abbrev.rs b/src/read/abbrev.rs index 7b244d75..1cb4f561 100644 --- a/src/read/abbrev.rs +++ b/src/read/abbrev.rs @@ -267,8 +267,9 @@ impl Abbreviations { let mut abbrevs = Abbreviations::empty(); while let Some(abbrev) = Abbreviation::parse(input)? { + let code = abbrev.code; if abbrevs.insert(abbrev).is_err() { - return Err(Error::DuplicateAbbreviationCode); + return Err(Error::DuplicateAbbreviationCode(code)); } } @@ -348,7 +349,7 @@ impl Abbreviation { if val == constants::DW_CHILDREN_no || val == constants::DW_CHILDREN_yes { Ok(val) } else { - Err(Error::BadHasChildren) + Err(Error::InvalidAbbreviationChildren(val)) } } @@ -894,7 +895,7 @@ pub(crate) mod tests { let buf = &mut EndianSlice::new(&buf, LittleEndian); match Abbreviations::parse(buf) { - Err(Error::DuplicateAbbreviationCode) => {} + Err(Error::DuplicateAbbreviationCode(1)) => {} otherwise => panic!("Unexpected result: {:?}", otherwise), }; } @@ -927,7 +928,7 @@ pub(crate) mod tests { let val = Abbreviation::parse_has_children(rest).expect("Should parse children"); assert_eq!(val, constants::DW_CHILDREN_yes); match Abbreviation::parse_has_children(rest) { - Err(Error::BadHasChildren) => {} + Err(Error::InvalidAbbreviationChildren(constants::DwChildren(2))) => {} otherwise => panic!("Unexpected result: {:?}", otherwise), }; } diff --git a/src/read/addr.rs b/src/read/addr.rs index f79336cc..a330227c 100644 --- a/src/read/addr.rs +++ b/src/read/addr.rs @@ -156,7 +156,7 @@ where let address_size = rest.read_address_size()?; let segment_size = rest.read_u8()?; if segment_size != 0 { - return Err(Error::UnsupportedSegmentSize); + return Err(Error::UnsupportedSegmentSize(segment_size)); } // unit_length + version + address_size + segment_size diff --git a/src/read/aranges.rs b/src/read/aranges.rs index 406948e2..3b731a9e 100644 --- a/src/read/aranges.rs +++ b/src/read/aranges.rs @@ -170,7 +170,7 @@ where let address_size = rest.read_address_size()?; let segment_size = rest.read_u8()?; if segment_size != 0 { - return Err(Error::UnsupportedSegmentSize); + return Err(Error::UnsupportedSegmentSize(segment_size)); } // unit_length + version + offset + address_size + segment_size diff --git a/src/read/cfi.rs b/src/read/cfi.rs index c7dc99ec..71bbc482 100644 --- a/src/read/cfi.rs +++ b/src/read/cfi.rs @@ -161,7 +161,7 @@ impl EhFrameHdr { fde_count = 0 } else { if fde_count_enc != fde_count_enc.format() { - return Err(Error::UnsupportedPointerEncoding); + return Err(Error::UnsupportedPointerEncoding(fde_count_enc)); } fde_count = parse_encoded_value(fde_count_enc, ¶meters, &mut reader)?; } @@ -256,13 +256,10 @@ impl<'a, 'bases, R: Reader> EhHdrTableIter<'a, 'bases, R> { pub fn nth(&mut self, n: usize) -> Result> { use core::convert::TryFrom; let size = match self.hdr.table_enc.format() { - constants::DW_EH_PE_uleb128 | constants::DW_EH_PE_sleb128 => { - return Err(Error::VariableLengthSearchTable); - } constants::DW_EH_PE_sdata2 | constants::DW_EH_PE_udata2 => 2, constants::DW_EH_PE_sdata4 | constants::DW_EH_PE_udata4 => 4, constants::DW_EH_PE_sdata8 | constants::DW_EH_PE_udata8 => 8, - _ => return Err(Error::UnknownPointerEncoding(self.hdr.table_enc)), + _ => return Err(Error::UnsupportedPointerEncoding(self.hdr.table_enc)), }; let row_size = size * 2; @@ -343,13 +340,10 @@ impl<'a, R: Reader + 'a> EhHdrTable<'a, R> { /// To be sure, you **must** call `contains` on the FDE. pub fn lookup(&self, address: u64, bases: &BaseAddresses) -> Result { let size = match self.hdr.table_enc.format() { - constants::DW_EH_PE_uleb128 | constants::DW_EH_PE_sleb128 => { - return Err(Error::VariableLengthSearchTable); - } constants::DW_EH_PE_sdata2 | constants::DW_EH_PE_udata2 => 2, constants::DW_EH_PE_sdata4 | constants::DW_EH_PE_udata4 => 4, constants::DW_EH_PE_sdata8 | constants::DW_EH_PE_udata8 => 8, - _ => return Err(Error::UnknownPointerEncoding(self.hdr.table_enc)), + _ => return Err(Error::UnsupportedPointerEncoding(self.hdr.table_enc)), }; let row_size = size * 2; @@ -656,7 +650,7 @@ pub trait UnwindSection: Clone + Debug + _UnwindSectionPrivate { let offset = UnwindOffset::into(offset); let input = &mut self.section().clone(); input.skip(offset)?; - CommonInformationEntry::parse(self, bases, input) + CommonInformationEntry::parse(self, bases, input, offset) } /// Parse the `PartialFrameDescriptionEntry` at the given offset. @@ -668,7 +662,7 @@ pub trait UnwindSection: Clone + Debug + _UnwindSectionPrivate { let offset = UnwindOffset::into(offset); let input = &mut self.section().clone(); input.skip(offset)?; - PartialFrameDescriptionEntry::parse_partial(self, bases, input) + PartialFrameDescriptionEntry::parse_partial(self, bases, input, offset) } /// Parse the `FrameDescriptionEntry` at the given offset. @@ -1337,12 +1331,13 @@ impl CommonInformationEntry { section: &Section, bases: &BaseAddresses, input: &mut R, + offset: R::Offset, ) -> Result> { let Some(prefix) = parse_cfi_entry_prefix(section, input)? else { - return Err(Error::NoEntryAtGivenOffset); + return Err(Error::NoEntryAtGivenOffset(offset.into_u64())); }; if !Section::is_cie(prefix.format, prefix.cie_id_or_offset) { - return Err(Error::NotCieId); + return Err(Error::NotCieId(offset.into_u64())); } CommonInformationEntry::from_prefix(section, bases, prefix) } @@ -1369,7 +1364,7 @@ impl CommonInformationEntry { let address_size = rest.read_address_size()?; let segment_size = rest.read_u8()?; if segment_size != 0 { - return Err(Error::UnsupportedSegmentSize); + return Err(Error::UnsupportedSegmentSize(segment_size)); } address_size } else { @@ -1564,12 +1559,13 @@ where section: &Section, bases: &'bases BaseAddresses, input: &mut R, + offset: R::Offset, ) -> Result> { let Some(prefix) = parse_cfi_entry_prefix(section, input)? else { - return Err(Error::NoEntryAtGivenOffset); + return Err(Error::NoEntryAtGivenOffset(offset.into_u64())); }; if Section::is_cie(prefix.format, prefix.cie_id_or_offset) { - return Err(Error::NotCiePointer); + return Err(Error::NotCiePointer(offset.into_u64())); } Self::from_prefix(section, bases, prefix) } @@ -1582,7 +1578,7 @@ where let cie_offset = R::Offset::from_u64(prefix.cie_id_or_offset)?; let Some(cie_offset) = section.resolve_cie_offset(prefix.cie_offset_base, cie_offset) else { - return Err(Error::OffsetOutOfBounds); + return Err(Error::OffsetOutOfBounds(cie_offset.into_u64())); }; let fde = PartialFrameDescriptionEntry { @@ -2371,7 +2367,7 @@ where // address for the next row. SetLoc { address } => { if address < self.ctx.start_address() { - return Err(Error::InvalidAddressRange); + return Err(Error::InvalidCfiSetLoc(address)); } self.next_start_address = address; @@ -3650,7 +3646,7 @@ impl Pointer { pub fn direct(self) -> Result { match self { Pointer::Direct(p) => Ok(p), - Pointer::Indirect(_) => Err(Error::UnsupportedPointerEncoding), + Pointer::Indirect(_) => Err(Error::UnsupportedIndirectPointer), } } @@ -3717,7 +3713,7 @@ fn parse_encoded_pointer( return Err(Error::FuncRelativePointerInBadContext); } } - constants::DW_EH_PE_aligned => return Err(Error::UnsupportedPointerEncoding), + constants::DW_EH_PE_aligned => return Err(Error::UnsupportedPointerEncoding(encoding)), _ => unreachable!(), }; @@ -3826,7 +3822,7 @@ mod tests { let bases = Default::default(); match parse_cfi_entry(§ion, &bases, input) { Ok(Some(CieOrFde::Fde(partial))) => partial.parse(get_cie), - Ok(_) => Err(Error::NoEntryAtGivenOffset), + Ok(_) => Err(Error::NoEntryAtGivenOffset(0)), Err(e) => Err(e), } } @@ -4030,7 +4026,7 @@ mod tests { debug_frame.set_address_size(address_size); let input = &mut EndianSlice::new(§ion, E::default()); let bases = Default::default(); - let result = CommonInformationEntry::parse(&debug_frame, &bases, input); + let result = CommonInformationEntry::parse(&debug_frame, &bases, input, 0); let result = result.map(|cie| (*input, cie)).map_eof(§ion); assert_eq!(result, expected); } @@ -4084,7 +4080,7 @@ mod tests { .B32(4) // Not the CIE Id. .B32(0xbad1_bad2); - assert_parse_cie(kind, section, 8, Err(Error::NotCieId)); + assert_parse_cie(kind, section, 8, Err(Error::NotCieId(0))); } #[test] @@ -4225,7 +4221,8 @@ mod tests { CommonInformationEntry::parse( &debug_frame, &bases, - &mut EndianSlice::new(&contents, LittleEndian) + &mut EndianSlice::new(&contents, LittleEndian), + 0, ) .map_eof(&contents), Err(Error::UnexpectedEof(ReaderOffsetId(4))) @@ -5404,7 +5401,7 @@ mod tests { ctx.row_mut().start_address = 999; let expected = ctx.clone(); let instructions = [( - Err(Error::InvalidAddressRange), + Err(Error::InvalidCfiSetLoc(42)), CallFrameInstruction::SetLoc { address: 42 }, )]; assert_eval(ctx, expected, cie, None, instructions); @@ -6500,7 +6497,9 @@ mod tests { let table = table.unwrap(); assert_eq!( table.lookup(0, &bases), - Err(Error::VariableLengthSearchTable) + Err(Error::UnsupportedPointerEncoding( + constants::DW_EH_PE_uleb128 + )) ); } @@ -6517,7 +6516,12 @@ mod tests { let bases = BaseAddresses::default(); let result = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8); assert!(result.is_err()); - assert_eq!(result.unwrap_err(), Error::UnsupportedPointerEncoding); + assert_eq!( + result.unwrap_err(), + Error::UnsupportedPointerEncoding( + constants::DW_EH_PE_indirect | constants::DW_EH_PE_udata4 + ) + ); } #[test] @@ -6544,7 +6548,7 @@ mod tests { let table = table.unwrap(); assert_eq!( table.lookup(0, &bases), - Err(Error::UnsupportedPointerEncoding) + Err(Error::UnsupportedIndirectPointer) ); } @@ -6737,7 +6741,7 @@ mod tests { assert_eq!( eh_frame.cie_from_offset(&bases, EhFrameOffset(0)), - Err(Error::NoEntryAtGivenOffset) + Err(Error::NoEntryAtGivenOffset(0)) ); } @@ -6759,7 +6763,7 @@ mod tests { assert_eq!( debug_frame.cie_from_offset(&bases, DebugFrameOffset(0)), - Err(Error::NoEntryAtGivenOffset) + Err(Error::NoEntryAtGivenOffset(0)) ); } @@ -6809,7 +6813,7 @@ mod tests { let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; assert_eq!( resolve_cie_offset(&buf, buf.len() + 4 + 2), - Err(Error::OffsetOutOfBounds) + Err(Error::OffsetOutOfBounds(buf.len() as u64 + 4 + 2)) ); } @@ -6818,7 +6822,7 @@ mod tests { let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; assert_eq!( resolve_cie_offset(&buf, usize::MAX), - Err(Error::OffsetOutOfBounds) + Err(Error::OffsetOutOfBounds(u32::MAX as u64)) ); } @@ -6899,7 +6903,7 @@ mod tests { let section = Section::with_endian(kind.endian()) .cie(kind, None, &mut cie) .mark(&end_of_cie) - .fde(kind, 99_999_999_999_999, &mut fde); + .fde(kind, 99_999_999, &mut fde); section.start().set_const(0); let section = section.get_contents().unwrap(); @@ -6911,7 +6915,7 @@ mod tests { &mut section.range_from(end_of_cie.value().unwrap() as usize..), UnwindSection::cie_from_offset, ); - assert_eq!(result, Err(Error::OffsetOutOfBounds)); + assert_eq!(result, Err(Error::OffsetOutOfBounds(99_999_999))); } #[test] @@ -7933,7 +7937,7 @@ mod tests { }; assert_eq!( parse_encoded_pointer(encoding, ¶meters, &mut rest), - Err(Error::UnsupportedPointerEncoding) + Err(Error::UnsupportedPointerEncoding(encoding)) ); } diff --git a/src/read/dwarf.rs b/src/read/dwarf.rs index 657a198c..3f6d4ef5 100644 --- a/src/read/dwarf.rs +++ b/src/read/dwarf.rs @@ -605,15 +605,15 @@ impl Dwarf { constants::DW_AT_low_pc => { low_pc = Some( self.attr_address(unit, attr.value())? - .ok_or(Error::UnsupportedAttributeForm)?, + .ok_or(Error::UnsupportedAttributeForm(attr.form()))?, ); } constants::DW_AT_high_pc => match attr.value() { AttributeValue::Udata(val) => size = Some(val), - attr => { + value => { high_pc = Some( - self.attr_address(unit, attr)? - .ok_or(Error::UnsupportedAttributeForm)?, + self.attr_address(unit, value)? + .ok_or(Error::UnsupportedAttributeForm(attr.form()))?, ); } }, @@ -776,7 +776,7 @@ impl Dwarf { }, _ => {} } - err.description().into() + format!("{}", err) } /// Return a fallible iterator over the macro information from `.debug_macinfo` for the given offset. @@ -1725,7 +1725,7 @@ mod tests { Err(e) => { assert_eq!( dwarf.format_error(e), - "Hit the end of input before it was expected at .debug_str+0x1" + "unexpected end of input at .debug_str+0x1" ); } } @@ -1734,10 +1734,10 @@ mod tests { Err(e) => { assert_eq!( dwarf.format_error(e), - "Hit the end of input before it was expected at .debug_str(sup)+0x1" + "unexpected end of input at .debug_str(sup)+0x1" ); } } - assert_eq!(dwarf.format_error(Error::Io), Error::Io.description()); + assert_eq!(dwarf.format_error(Error::Io), format!("{}", Error::Io)); } } diff --git a/src/read/index.rs b/src/read/index.rs index bd8e74bf..02daa1f4 100644 --- a/src/read/index.rs +++ b/src/read/index.rs @@ -167,7 +167,7 @@ impl UnitIndex { let unit_count = input.read_u32()?; let slot_count = input.read_u32()?; if slot_count != 0 && (slot_count & (slot_count - 1) != 0 || slot_count <= unit_count) { - return Err(Error::InvalidIndexSlotCount); + return Err(Error::InvalidIndexSlotCount(slot_count)); } let hash_ids = input.split(R::Offset::from_u64(u64::from(slot_count) * 8)?)?; @@ -175,7 +175,7 @@ impl UnitIndex { let mut sections = [IndexSectionId::DebugAbbrev; SECTION_COUNT_MAX as usize]; if section_count > SECTION_COUNT_MAX.into() { - return Err(Error::InvalidIndexSectionCount); + return Err(Error::UnsupportedIndexSectionCount(section_count)); } for i in 0..section_count { let section = input.read_u32()?; @@ -256,22 +256,16 @@ impl UnitIndex { } /// Return the section offsets and sizes for the given row index. - pub fn sections(&self, mut row: u32) -> Result> { - if row == 0 { - return Err(Error::InvalidIndexRow); - } - row -= 1; - if row >= self.unit_count { - return Err(Error::InvalidIndexRow); + pub fn sections(&self, row: u32) -> Result> { + if row == 0 || row > self.unit_count { + return Err(Error::InvalidIndexRow(row)); } + let row_offset = + R::Offset::from_u64(u64::from(row - 1) * u64::from(self.section_count) * 4)?; let mut offsets = self.offsets.clone(); - offsets.skip(R::Offset::from_u64( - u64::from(row) * u64::from(self.section_count) * 4, - )?)?; + offsets.skip(row_offset)?; let mut sizes = self.sizes.clone(); - sizes.skip(R::Offset::from_u64( - u64::from(row) * u64::from(self.section_count) * 4, - )?)?; + sizes.skip(row_offset)?; Ok(UnitIndexSectionIterator { sections: self.sections[..self.section_count as usize].iter(), offsets, diff --git a/src/read/line.rs b/src/read/line.rs index b0763994..33c6bbdc 100644 --- a/src/read/line.rs +++ b/src/read/line.rs @@ -1246,7 +1246,7 @@ where address_size = rest.read_address_size()?; let segment_selector_size = rest.read_u8()?; if segment_selector_size != 0 { - return Err(Error::UnsupportedSegmentSize); + return Err(Error::UnsupportedSegmentSize(segment_selector_size)); } } diff --git a/src/read/lists.rs b/src/read/lists.rs index bb41901d..8be694d6 100644 --- a/src/read/lists.rs +++ b/src/read/lists.rs @@ -52,7 +52,7 @@ fn parse_header(input: &mut R) -> Result { let address_size = input.read_address_size()?; let segment_selector_size = input.read_u8()?; if segment_selector_size != 0 { - return Err(Error::UnsupportedSegmentSize); + return Err(Error::UnsupportedSegmentSize(segment_selector_size)); } let offset_entry_count = input.read_u32()?; diff --git a/src/read/mod.rs b/src/read/mod.rs index fb22ff52..321c9109 100644 --- a/src/read/mod.rs +++ b/src/read/mod.rs @@ -269,31 +269,19 @@ pub enum Error { AttributeFormZero, /// The abbreviation's has-children byte was not one of /// `DW_CHILDREN_{yes,no}`. - BadHasChildren, - /// The specified length is impossible. - BadLength, + InvalidAbbreviationChildren(constants::DwChildren), /// Found an unknown `DW_FORM_*` type. UnknownForm(constants::DwForm), - /// Expected a zero, found something else. - ExpectedZero, /// Found an abbreviation code that has already been used. - DuplicateAbbreviationCode, - /// Found a duplicate arange. - DuplicateArange, + DuplicateAbbreviationCode(u64), /// Found an unknown reserved length value. - UnknownReservedLength, + UnknownReservedLength(u32), /// Found an unknown DWARF version. UnknownVersion(u64), - /// Found a record with an unknown abbreviation code. - UnknownAbbreviation(u64), + /// Found an entry with an invalid abbreviation code. + InvalidAbbreviationCode(u64), /// Hit the end of input before it was expected. UnexpectedEof(ReaderOffsetId), - /// Read a null entry before it was expected. - UnexpectedNull, - /// Found an unknown standard opcode. - UnknownStandardOpcode(constants::DwLns), - /// Found an unknown extended opcode. - UnknownExtendedOpcode(constants::DwLne), /// Found an unknown location-lists format. UnknownLocListsEntry(constants::DwLle), /// Found an unknown range-lists format. @@ -302,8 +290,6 @@ pub enum Error { UnsupportedAddressSize(u8), /// The specified offset size is not supported. UnsupportedOffsetSize(u8), - /// The specified field size is not supported. - UnsupportedFieldSize(u8), /// The minimum instruction length must not be zero. MinimumInstructionLengthZero, /// The maximum operations per instruction must not be zero. @@ -315,9 +301,9 @@ pub enum Error { /// Found an invalid UTF-8 string. BadUtf8, /// Expected to find the CIE ID, but found something else. - NotCieId, + NotCieId(u64), /// Expected to find a pointer to a CIE, but found the CIE ID instead. - NotCiePointer, + NotCiePointer(u64), /// Invalid branch target for a DW_OP_bra or DW_OP_skip. BadBranchTarget(u64), /// DW_OP_push_object_address used but no address passed in. @@ -352,8 +338,8 @@ pub enum Error { InvalidDerefSize(u8), /// An unknown DW_CFA_* instruction. UnknownCallFrameInstruction(constants::DwCfa), - /// The end of an address range was before the beginning. - InvalidAddressRange, + /// A `DW_CFA_set_loc` instruction moved the address backward. + InvalidCfiSetLoc(u64), /// An address calculation overflowed. /// /// This is returned in cases where the address is expected to be @@ -372,13 +358,15 @@ pub enum Error { /// The given pointer encoding is either unknown or invalid. UnknownPointerEncoding(constants::DwEhPe), /// Did not find an entry at the given offset. - NoEntryAtGivenOffset, + NoEntryAtGivenOffset(u64), /// The given offset is out of bounds. - OffsetOutOfBounds, + OffsetOutOfBounds(u64), /// Found an unknown CFI augmentation. UnknownAugmentation, /// We do not support the given pointer encoding yet. - UnsupportedPointerEncoding, + UnsupportedPointerEncoding(constants::DwEhPe), + /// We do not support dereferencing indirect pointers. + UnsupportedIndirectPointer, /// Registers larger than `u16` are not supported. UnsupportedRegister(u64), /// The CFI program defined more register rules than we have storage for. @@ -386,33 +374,28 @@ pub enum Error { /// Attempted to push onto the CFI or evaluation stack, but it was already /// at full capacity. StackFull, - /// The `.eh_frame_hdr` binary search table claims to be variable-length encoded, - /// which makes binary search impossible. - VariableLengthSearchTable, /// The `DW_UT_*` value for this unit is not supported yet. - UnsupportedUnitType, - /// Ranges using AddressIndex are not supported yet. - UnsupportedAddressIndex, + UnknownUnitType(constants::DwUt), /// Nonzero segment selector sizes aren't supported yet. - UnsupportedSegmentSize, + UnsupportedSegmentSize(u8), /// A compilation unit or type unit is missing its top level DIE. MissingUnitDie, /// A split DWARF section does not contain the split compilation unit. MissingSplitUnit, /// A DIE attribute used an unsupported form. - UnsupportedAttributeForm, + UnsupportedAttributeForm(constants::DwForm), /// Missing DW_LNCT_path in file entry format. MissingFileEntryFormatPath, /// Expected an attribute value to be a string form. ExpectedStringAttributeValue, - /// `DW_FORM_implicit_const` used in an invalid context. + /// An attribute with an indirect form cannot use `DW_FORM_implicit_const`. InvalidImplicitConst, /// Invalid section count in `.dwp` index. - InvalidIndexSectionCount, + UnsupportedIndexSectionCount(u32), /// Invalid slot count in `.dwp` index. - InvalidIndexSlotCount, - /// Invalid hash row in `.dwp` index. - InvalidIndexRow, + InvalidIndexSlotCount(u32), + /// Invalid row index in `.dwp` index. + InvalidIndexRow(u32), /// Unknown section type in `.dwp` index. UnknownIndexSection(constants::DwSect), /// Unknown section type in version 2 `.dwp` index. @@ -428,167 +411,187 @@ pub enum Error { } impl fmt::Display for Error { - #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> ::core::result::Result<(), fmt::Error> { - write!(f, "{}", self.description()) - } -} - -impl Error { - /// A short description of the error. - pub fn description(&self) -> &str { match *self { - Error::Io => "An I/O error occurred while reading.", + Error::Io => write!(f, "I/O error"), Error::PcRelativePointerButSectionBaseIsUndefined => { - "Found a PC relative pointer, but the section base is undefined." + write!(f, "undefined section base for DW_EH_PE_pcrel pointer") } Error::TextRelativePointerButTextBaseIsUndefined => { - "Found a `.text` relative pointer, but the `.text` base is undefined." + write!(f, "undefined text base for DW_EH_PE_textrel pointer") } Error::DataRelativePointerButDataBaseIsUndefined => { - "Found a data relative pointer, but the data base is undefined." + write!(f, "undefined data base for DW_EH_PE_datarel pointer") } Error::FuncRelativePointerInBadContext => { - "Found a function relative pointer in a context that does not have a function base." + write!(f, "invalid context for DW_EH_PE_funcrel pointer") } Error::CannotParseOmitPointerEncoding => { - "Cannot parse a pointer with a `DW_EH_PE_omit` encoding." + write!(f, "invalid encoding for required pointer: DW_EH_PE_omit") } - Error::BadUnsignedLeb128 => "An error parsing an unsigned LEB128 value", - Error::BadSignedLeb128 => "An error parsing a signed LEB128 value", + Error::BadUnsignedLeb128 => write!(f, "unsigned LEB128 overflow"), + Error::BadSignedLeb128 => write!(f, "signed LEB128 overflow"), Error::AbbreviationTagZero => { - "An abbreviation declared that its tag is zero, - but zero is reserved for null records" + write!(f, "invalid abbreviation tag: zero") } Error::AttributeNameZero => { - "An attribute specification declared that its name is zero, - but zero is reserved for null records" + write!(f, "invalid attribute name: zero") } Error::AttributeFormZero => { - "An attribute specification declared that its form is zero, - but zero is reserved for null records" - } - Error::BadHasChildren => { - "The abbreviation's has-children byte was not one of - `DW_CHILDREN_{yes,no}`" - } - Error::BadLength => "The specified length is impossible", - Error::UnknownForm(_) => "Found an unknown `DW_FORM_*` type", - Error::ExpectedZero => "Expected a zero, found something else", - Error::DuplicateAbbreviationCode => { - "Found an abbreviation code that has already been used" - } - Error::DuplicateArange => "Found a duplicate arange", - Error::UnknownReservedLength => "Found an unknown reserved length value", - Error::UnknownVersion(_) => "Found an unknown DWARF version", - Error::UnknownAbbreviation(_) => "Found a record with an unknown abbreviation code", - Error::UnexpectedEof(_) => "Hit the end of input before it was expected", - Error::UnexpectedNull => "Read a null entry before it was expected.", - Error::UnknownStandardOpcode(_) => "Found an unknown standard opcode", - Error::UnknownExtendedOpcode(_) => "Found an unknown extended opcode", - Error::UnknownLocListsEntry(_) => "Found an unknown location lists entry", - Error::UnknownRangeListsEntry(_) => "Found an unknown range lists entry", - Error::UnsupportedAddressSize(_) => "The specified address size is not supported", - Error::UnsupportedOffsetSize(_) => "The specified offset size is not supported", - Error::UnsupportedFieldSize(_) => "The specified field size is not supported", + write!(f, "invalid attribute form: zero") + } + Error::InvalidAbbreviationChildren(val) => { + write!(f, "invalid abbreviation children: 0x{:x}", val.0) + } + Error::UnknownForm(val) => write!(f, "unknown attribute form: 0x{:x}", val.0), + Error::DuplicateAbbreviationCode(val) => { + write!(f, "duplicate abbreviation code: {val}") + } + Error::UnknownReservedLength(val) => write!(f, "unknown reserved length: 0x{val:x}"), + Error::UnknownVersion(version) => write!(f, "unknown DWARF version: {version}"), + Error::InvalidAbbreviationCode(val) => { + write!(f, "invalid abbreviation code: {val}") + } + Error::UnexpectedEof(_) => write!(f, "unexpected end of input"), + Error::UnknownLocListsEntry(val) => { + write!(f, "unknown location lists entry: 0x{:x}", val.0) + } + Error::UnknownRangeListsEntry(val) => { + write!(f, "unknown range lists entry: 0x{:x}", val.0) + } + Error::UnsupportedAddressSize(val) => { + write!(f, "unsupported address size: {val}") + } + Error::UnsupportedOffsetSize(val) => { + write!(f, "unsupported offset size: {val}") + } Error::MinimumInstructionLengthZero => { - "The minimum instruction length must not be zero." + write!(f, "invalid minimum line instruction length: zero") } Error::MaximumOperationsPerInstructionZero => { - "The maximum operations per instruction must not be zero." - } - Error::LineRangeZero => "The line range must not be zero.", - Error::OpcodeBaseZero => "The opcode base must not be zero.", - Error::BadUtf8 => "Found an invalid UTF-8 string.", - Error::NotCieId => "Expected to find the CIE ID, but found something else.", - Error::NotCiePointer => "Expected to find a CIE pointer, but found the CIE ID instead.", - Error::BadBranchTarget(_) => "Invalid branch target in DWARF expression", + write!(f, "invalid maximum operations per line instruction: zero") + } + Error::LineRangeZero => write!(f, "invalid line range: zero"), + Error::OpcodeBaseZero => write!(f, "invalid line opcode base: zero"), + Error::BadUtf8 => write!(f, "invalid UTF-8"), + Error::NotCieId(val) => write!(f, "invalid CIE at offset 0x{val:x}: missing CIE ID"), + Error::NotCiePointer(val) => { + write!(f, "invalid FDE at offset 0x{val:x}: missing CIE pointer") + } + Error::BadBranchTarget(_) => write!(f, "invalid expression branch target"), Error::InvalidPushObjectAddress => { - "DW_OP_push_object_address used but no object address given" + write!(f, "undefined object address for DW_OP_push_object_address") + } + Error::NotEnoughStackItems => { + write!(f, "expression stack underflow") + } + Error::TooManyIterations => { + write!(f, "exceeded maximum expression iterations") + } + Error::InvalidExpression(val) => write!(f, "unknown expression opcode: 0x{:x}", val.0), + Error::UnsupportedEvaluation => { + write!(f, "unsupported evaluation operation") } - Error::NotEnoughStackItems => "Not enough items on stack when evaluating expression", - Error::TooManyIterations => "Too many iterations to evaluate DWARF expression", - Error::InvalidExpression(_) => "Invalid opcode in DWARF expression", - Error::UnsupportedEvaluation => "Unsupported operation when evaluating expression", Error::InvalidPiece => { - "DWARF expression has piece followed by non-piece expression at end" + write!(f, "invalid expression: piece followed by non-piece") + } + Error::InvalidExpressionTerminator(_) => { + write!(f, "invalid expression terminator") + } + Error::DivisionByZero => { + write!(f, "division by zero") + } + Error::TypeMismatch => write!(f, "invalid operand type: mismatch"), + Error::IntegralTypeRequired => { + write!(f, "invalid operand type: integral required") } - Error::InvalidExpressionTerminator(_) => "Expected DW_OP_piece or DW_OP_bit_piece", - Error::DivisionByZero => "Division or modulus by zero when evaluating expression", - Error::TypeMismatch => "Type mismatch when evaluating expression", - Error::IntegralTypeRequired => "Integral type expected when evaluating expression", Error::UnsupportedTypeOperation => { - "An expression operation used types that are not supported" + write!(f, "unsupported operand type") } Error::InvalidShiftExpression => { - "The shift value in an expression must be a non-negative integer." + write!(f, "invalid shift amount") } - Error::InvalidDerefSize(_) => { - "The size of a deref expression must not be larger than the size of an address." + Error::InvalidDerefSize(val) => { + write!(f, "invalid deref size: {val}") } - Error::UnknownCallFrameInstruction(_) => "An unknown DW_CFA_* instruction", - Error::InvalidAddressRange => { - "The end of an address range must not be before the beginning." + Error::UnknownCallFrameInstruction(val) => { + write!(f, "unknown call frame instruction: 0x{:x}", val.0) } - Error::AddressOverflow => "An address calculation overflowed.", + Error::InvalidCfiSetLoc(val) => { + write!(f, "invalid DW_CFA_set_loc: address 0x{val:x} goes backward") + } + Error::AddressOverflow => write!(f, "address overflow"), Error::CfiInstructionInInvalidContext => { - "Encountered a call frame instruction in a context in which it is not valid." + write!(f, "invalid context for call frame instruction") } Error::PopWithEmptyStack => { - "When evaluating call frame instructions, found a `DW_CFA_restore_state` stack pop \ - instruction, but the stack was empty, and had nothing to pop." + write!(f, "invalid DW_CFA_restore_state: empty stack") + } + Error::NoUnwindInfoForAddress => { + write!(f, "no unwind info for address") } - Error::NoUnwindInfoForAddress => "Do not have unwind info for the given address.", Error::UnsupportedOffset => { - "An offset value was larger than the maximum supported value." + write!(f, "offset overflow") + } + Error::UnknownPointerEncoding(val) => { + write!(f, "unknown pointer encoding: 0x{:x}", val.0) } - Error::UnknownPointerEncoding(_) => { - "The given pointer encoding is either unknown or invalid." + Error::NoEntryAtGivenOffset(val) => write!(f, "no entry at offset: 0x{val:x}"), + Error::OffsetOutOfBounds(val) => write!(f, "invalid offset: 0x{val:x}"), + Error::UnknownAugmentation => write!(f, "unknown CFI augmentation"), + Error::UnsupportedPointerEncoding(val) => { + write!(f, "unsupported pointer encoding: 0x{:x}", val.0) } - Error::NoEntryAtGivenOffset => "Did not find an entry at the given offset.", - Error::OffsetOutOfBounds => "The given offset is out of bounds.", - Error::UnknownAugmentation => "Found an unknown CFI augmentation.", - Error::UnsupportedPointerEncoding => { - "We do not support the given pointer encoding yet." + Error::UnsupportedIndirectPointer => { + write!(f, "unsupported indirect pointer") + } + Error::UnsupportedRegister(val) => { + write!(f, "unsupported register: 0x{val:x}") } - Error::UnsupportedRegister(_) => "Registers larger than `u16` are not supported.", Error::TooManyRegisterRules => { - "The CFI program defined more register rules than we have storage for." + write!(f, "too many CFI register rules") } Error::StackFull => { - "Attempted to push onto the CFI stack, but it was already at full capacity." + write!(f, "CFI stack overflow") } - Error::VariableLengthSearchTable => { - "The `.eh_frame_hdr` binary search table claims to be variable-length encoded, \ - which makes binary search impossible." + Error::UnknownUnitType(val) => { + write!(f, "unknown unit type: 0x{:x}", val.0) } - Error::UnsupportedUnitType => "The `DW_UT_*` value for this unit is not supported yet", - Error::UnsupportedAddressIndex => "Ranges involving AddressIndex are not supported yet", - Error::UnsupportedSegmentSize => "Nonzero segment size not supported yet", + Error::UnsupportedSegmentSize(val) => write!(f, "unsupported segment size: {val}"), Error::MissingUnitDie => { - "A compilation unit or type unit is missing its top level DIE." + write!(f, "missing unit DIE") } Error::MissingSplitUnit => { - "A split DWARF section does not contain the split compilation unit." + write!(f, "missing split compilation unit") + } + Error::UnsupportedAttributeForm(val) => { + write!(f, "unsupported attribute form: 0x{:x}", val.0) + } + Error::MissingFileEntryFormatPath => { + write!(f, "missing file entry format path") } - Error::UnsupportedAttributeForm => "A DIE attribute used an unsupported form.", - Error::MissingFileEntryFormatPath => "Missing DW_LNCT_path in file entry format.", Error::ExpectedStringAttributeValue => { - "Expected an attribute value to be a string form." - } - Error::InvalidImplicitConst => "DW_FORM_implicit_const used in an invalid context.", - Error::InvalidIndexSectionCount => "Invalid section count in `.dwp` index.", - Error::InvalidIndexSlotCount => "Invalid slot count in `.dwp` index.", - Error::InvalidIndexRow => "Invalid hash row in `.dwp` index.", - Error::UnknownIndexSection(_) => "Unknown section type in `.dwp` index.", - Error::UnknownIndexSectionV2(_) => "Unknown section type in version 2 `.dwp` index.", - Error::InvalidMacinfoType(_) => "Invalid macinfo type in `.debug_macinfo`.", - Error::InvalidMacroType(_) => "Invalid macro type in `.debug_macro`.", + write!(f, "invalid attribute form for string") + } + Error::InvalidImplicitConst => { + write!(f, "invalid indirect attribute form: DW_FORM_implicit_const") + } + Error::UnsupportedIndexSectionCount(val) => { + write!(f, "unsupported DWP section count: {val}") + } + Error::InvalidIndexSlotCount(val) => write!(f, "invalid DWP slot count: 0x{:x}", val), + Error::InvalidIndexRow(val) => write!(f, "invalid DWP row index: 0x{:x}", val), + Error::UnknownIndexSection(val) => write!(f, "unknown DWP section type: 0x{:x}", val.0), + Error::UnknownIndexSectionV2(val) => { + write!(f, "unknown DWP v2 section type: 0x{:x}", val.0) + } + Error::InvalidMacinfoType(val) => write!(f, "unknown macinfo type: 0x{:x}", val.0), + Error::InvalidMacroType(val) => write!(f, "unknown macro type: 0x{:x}", val.0), Error::UnsupportedOpcodeOperandsTable => { - "The optional `opcode_operands_table` in `.debug_macro` is currently not supported." + write!(f, "unsupported macro opcode operands table") } - Error::InvalidNameAttributeIndex(_) => { - "Invalid index in a `.debug_names` attribute value." + Error::InvalidNameAttributeIndex(val) => { + write!(f, "invalid index in name attribute: 0x{val:x}") } } } @@ -743,7 +746,7 @@ mod tests { let input = &mut EndianSlice::new(&buf, LittleEndian); match input.read_initial_length() { - Err(Error::UnknownReservedLength) => {} + Err(Error::UnknownReservedLength(0xffff_fffe)) => {} otherwise => panic!("Unexpected result: {:?}", otherwise), }; } diff --git a/src/read/names.rs b/src/read/names.rs index 6699edeb..c464bebd 100644 --- a/src/read/names.rs +++ b/src/read/names.rs @@ -556,7 +556,8 @@ impl NameIndex { pub fn name_entry(&self, offset: NameEntryOffset) -> Result> { let mut entries = self.entry_pool.clone(); entries.skip(offset.0)?; - NameEntry::parse(&mut entries, offset, &self.abbreviations)?.ok_or(Error::UnexpectedNull) + NameEntry::parse(&mut entries, offset, &self.abbreviations)? + .ok_or(Error::NoEntryAtGivenOffset(offset.0.into_u64())) } /// Get the abbreviation table for name entries in this name index. @@ -879,7 +880,7 @@ impl NameEntry { return Ok(None); } let Some(abbrev) = abbreviations.get(abbrev_code) else { - return Err(Error::UnknownAbbreviation(abbrev_code)); + return Err(Error::InvalidAbbreviationCode(abbrev_code)); }; let tag = abbrev.tag(); let specs = abbrev.attributes(); @@ -934,7 +935,7 @@ impl NameAttribute { u32::try_from(val).map_err(|_| Error::InvalidNameAttributeIndex(val))?; names.compile_unit(index) } - _ => Err(Error::UnsupportedAttributeForm), + _ => Err(Error::UnsupportedAttributeForm(self.form)), } } @@ -946,7 +947,7 @@ impl NameAttribute { u32::try_from(val).map_err(|_| Error::InvalidNameAttributeIndex(val))?; names.type_unit(index) } - _ => Err(Error::UnsupportedAttributeForm), + _ => Err(Error::UnsupportedAttributeForm(self.form)), } } @@ -954,7 +955,7 @@ impl NameAttribute { pub fn die_offset(&self) -> Result> { match self.value { NameAttributeValue::Offset(val) => Ok(UnitOffset(val)), - _ => Err(Error::UnsupportedAttributeForm), + _ => Err(Error::UnsupportedAttributeForm(self.form)), } } @@ -966,7 +967,7 @@ impl NameAttribute { match self.value { NameAttributeValue::Offset(val) => Ok(Some(NameEntryOffset(val))), NameAttributeValue::Flag(true) => Ok(None), - _ => Err(Error::UnsupportedAttributeForm), + _ => Err(Error::UnsupportedAttributeForm(self.form)), } } @@ -974,7 +975,7 @@ impl NameAttribute { pub fn type_hash(&self) -> Result { match self.value { NameAttributeValue::Unsigned(val) => Ok(val), - _ => Err(Error::UnsupportedAttributeForm), + _ => Err(Error::UnsupportedAttributeForm(self.form)), } } } @@ -1582,7 +1583,10 @@ mod tests { ); let mut entries = name_index.name_entries(name).unwrap(); - assert!(matches!(entries.next(), Err(Error::UnknownAbbreviation(4)))); + assert!(matches!( + entries.next(), + Err(Error::InvalidAbbreviationCode(4)) + )); assert!(matches!(entries.next(), Ok(None))); // No entries diff --git a/src/read/reader.rs b/src/read/reader.rs index c4ba4396..492cf5ef 100644 --- a/src/read/reader.rs +++ b/src/read/reader.rs @@ -525,7 +525,7 @@ pub trait Reader: Debug + Clone { let val = self.read_u64().and_then(Self::Offset::from_u64)?; Ok((val, Format::Dwarf64)) } else { - Err(Error::UnknownReservedLength) + Err(Error::UnknownReservedLength(val)) } } diff --git a/src/read/unit.rs b/src/read/unit.rs index c0b98da6..7a4649ed 100644 --- a/src/read/unit.rs +++ b/src/read/unit.rs @@ -537,10 +537,10 @@ where /// Get the underlying bytes for the supplied range. pub fn range(&self, idx: Range>) -> Result { if !self.is_in_bounds(idx.start) { - return Err(Error::OffsetOutOfBounds); + return Err(Error::OffsetOutOfBounds(idx.start.0.into_u64())); } if !self.is_in_bounds(idx.end) { - return Err(Error::OffsetOutOfBounds); + return Err(Error::OffsetOutOfBounds(idx.end.0.into_u64())); } assert!(idx.start <= idx.end); let size_of_header = self.header_size(); @@ -555,7 +555,7 @@ where /// Get the underlying bytes for the supplied range. pub fn range_from(&self, idx: RangeFrom>) -> Result { if !self.is_in_bounds(idx.start) { - return Err(Error::OffsetOutOfBounds); + return Err(Error::OffsetOutOfBounds(idx.start.0.into_u64())); } let start = idx.start.0 - self.header_size(); let mut input = self.entries_buf.clone(); @@ -566,7 +566,7 @@ where /// Get the underlying bytes for the supplied range. pub fn range_to(&self, idx: RangeTo>) -> Result { if !self.is_in_bounds(idx.end) { - return Err(Error::OffsetOutOfBounds); + return Err(Error::OffsetOutOfBounds(idx.end.0.into_u64())); } let end = idx.end.0 - self.header_size(); let mut input = self.entries_buf.clone(); @@ -588,7 +588,7 @@ where let mut input = self.entries_raw(abbreviations, Some(offset))?; input.read_entry(&mut entry)?; if entry.is_null() { - Err(Error::NoEntryAtGivenOffset) + Err(Error::NoEntryAtGivenOffset(offset.0.into_u64())) } else { Ok(entry) } @@ -739,7 +739,7 @@ where type_offset, } } - _ => return Err(Error::UnsupportedUnitType), + _ => return Err(Error::UnknownUnitType(unit_type)), }; Ok(UnitHeader::new( @@ -2403,7 +2403,7 @@ impl<'abbrev, R: Reader> EntriesRaw<'abbrev, R> { let abbrev = self .abbreviations .get(code) - .ok_or(Error::UnknownAbbreviation(code))?; + .ok_or(Error::InvalidAbbreviationCode(code))?; if abbrev.has_children() { self.depth += 1; } @@ -2861,7 +2861,7 @@ impl<'abbrev, R: Reader> EntriesTree<'abbrev, R> { self.input.input = self.root.clone(); self.input.depth = 0; if !self.input.read_entry(&mut self.entry)? { - return Err(Error::UnexpectedNull); + return Err(Error::NoEntryAtGivenOffset(self.entry.offset.0.into_u64())); } Ok(EntriesTreeNode::new(self, 1)) } @@ -5236,7 +5236,7 @@ mod tests { let cursor = unit.entries_at_offset(&abbrevs, UnitOffset(0)); match cursor { - Err(Error::OffsetOutOfBounds) => {} + Err(Error::OffsetOutOfBounds(0)) => {} otherwise => { panic!("Unexpected parse result = {:#?}", otherwise); } diff --git a/src/write/unit.rs b/src/write/unit.rs index 7d133801..31ee5548 100644 --- a/src/write/unit.rs +++ b/src/write/unit.rs @@ -1600,7 +1600,7 @@ pub(crate) mod convert { use crate::common::{ DwoId, LineEncoding, LocationListsOffset, RangeListsOffset, UnitSectionOffset, }; - use crate::read::{self, Reader}; + use crate::read::{self, Reader, ReaderOffset}; use crate::write::{ self, ConvertError, ConvertLineProgram, ConvertResult, Dwarf, LocationList, RangeList, }; @@ -3068,7 +3068,7 @@ pub(crate) mod convert { let mut read_entry = read::DebuggingInformationEntry::null(); if !read_entries.read_entry(&mut read_entry)? { // Null entry. - return Err(read::Error::NoEntryAtGivenOffset.into()); + return Err(read::Error::NoEntryAtGivenOffset(offset.0.into_u64()).into()); }; let mut entry = ConvertUnitEntry {