1use core::error;
135use core::fmt::{self, Debug};
136use core::result;
137#[cfg(feature = "std")]
138use std::io;
139
140use crate::common::{Register, SectionId};
141use crate::constants;
142
143mod util;
144pub use util::*;
145
146mod addr;
147pub use self::addr::*;
148
149mod cfi;
150pub use self::cfi::*;
151
152#[cfg(feature = "read")]
153mod dwarf;
154#[cfg(feature = "read")]
155pub use self::dwarf::*;
156
157mod endian_slice;
158pub use self::endian_slice::*;
159
160#[cfg(feature = "endian-reader")]
161mod endian_reader;
162#[cfg(feature = "endian-reader")]
163pub use self::endian_reader::*;
164
165mod reader;
166pub use self::reader::*;
167
168mod relocate;
169pub use self::relocate::*;
170
171#[cfg(feature = "read")]
172mod abbrev;
173#[cfg(feature = "read")]
174pub use self::abbrev::*;
175
176mod aranges;
177pub use self::aranges::*;
178
179mod index;
180pub use self::index::*;
181
182#[cfg(feature = "read")]
183mod line;
184#[cfg(feature = "read")]
185pub use self::line::*;
186
187mod lists;
188
189mod loclists;
190pub use self::loclists::*;
191
192#[cfg(feature = "read")]
193mod lookup;
194
195#[cfg(feature = "read")]
196mod macros;
197#[cfg(feature = "read")]
198pub use self::macros::*;
199
200#[cfg(feature = "read")]
201mod names;
202#[cfg(feature = "read")]
203pub use self::names::*;
204
205mod op;
206pub use self::op::*;
207
208#[cfg(feature = "read")]
209mod pubnames;
210#[cfg(feature = "read")]
211pub use self::pubnames::*;
212
213#[cfg(feature = "read")]
214mod pubtypes;
215#[cfg(feature = "read")]
216pub use self::pubtypes::*;
217
218mod rnglists;
219pub use self::rnglists::*;
220
221mod str;
222pub use self::str::*;
223
224#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
226pub struct UnitOffset<T = usize>(pub T);
227
228#[cfg(feature = "read")]
229mod unit;
230#[cfg(feature = "read")]
231pub use self::unit::*;
232
233mod value;
234pub use self::value::*;
235
236#[derive(Debug, Clone, Copy, PartialEq, Eq)]
238pub struct StoreOnHeap;
239
240#[derive(Debug, Clone, Copy, PartialEq, Eq)]
242#[non_exhaustive]
243pub enum Error {
244 Io,
246 PcRelativePointerButSectionBaseIsUndefined,
248 TextRelativePointerButTextBaseIsUndefined,
250 DataRelativePointerButDataBaseIsUndefined,
252 FuncRelativePointerInBadContext,
255 CannotParseOmitPointerEncoding,
257 BadUnsignedLeb128,
259 BadSignedLeb128,
261 AbbreviationTagZero,
264 AttributeNameZero,
267 AttributeFormZero,
270 InvalidAbbreviationChildren(constants::DwChildren),
273 UnknownForm(constants::DwForm),
275 DuplicateAbbreviationCode(u64),
277 UnknownReservedLength(u32),
279 UnknownVersion(u64),
281 InvalidAbbreviationCode(u64),
283 UnexpectedEof(ReaderOffsetId),
285 UnknownLocListsEntry(constants::DwLle),
287 UnknownRangeListsEntry(constants::DwRle),
289 UnsupportedAddressSize(u8),
291 UnsupportedOffsetSize(u8),
293 MinimumInstructionLengthZero,
295 MaximumOperationsPerInstructionZero,
297 LineRangeZero,
299 OpcodeBaseZero,
301 BadUtf8,
303 NotCieId(u64),
305 NotCiePointer(u64),
307 BadBranchTarget(u64),
309 InvalidPushObjectAddress,
311 NotEnoughStackItems,
313 TooManyIterations,
315 InvalidExpression(constants::DwOp),
318 UnsupportedEvaluation,
320 InvalidPiece,
323 InvalidExpressionTerminator(u64),
326 DivisionByZero,
328 TypeMismatch,
330 IntegralTypeRequired,
333 UnsupportedTypeOperation,
335 InvalidShiftExpression,
337 InvalidDerefSize(u8),
339 UnknownCallFrameInstruction(constants::DwCfa),
341 InvalidCfiSetLoc(u64),
343 AddressOverflow,
348 CfiInstructionInInvalidContext,
351 PopWithEmptyStack,
354 NoUnwindInfoForAddress,
356 UnsupportedOffset,
358 UnknownPointerEncoding(constants::DwEhPe),
360 NoEntryAtGivenOffset(u64),
362 OffsetOutOfBounds(u64),
364 UnknownAugmentation,
366 UnsupportedPointerEncoding(constants::DwEhPe),
368 UnsupportedIndirectPointer,
370 UnsupportedRegister(u64),
372 TooManyRegisterRules,
374 StackFull,
377 UnknownUnitType(constants::DwUt),
379 UnsupportedSegmentSize(u8),
381 MissingUnitDie,
383 MissingSplitUnit,
385 UnsupportedAttributeForm(constants::DwForm),
387 MissingFileEntryFormatPath,
389 ExpectedStringAttributeValue,
391 InvalidImplicitConst,
393 UnsupportedIndexSectionCount(u32),
395 InvalidIndexSlotCount(u32),
397 InvalidIndexRow(u32),
399 UnknownIndexSection(constants::DwSect),
401 UnknownIndexSectionV2(constants::DwSectV2),
403 InvalidMacinfoType(constants::DwMacinfo),
405 InvalidMacroType(constants::DwMacro),
407 UnsupportedOpcodeOperandsTable,
409 InvalidNameAttributeIndex(u64),
411}
412
413impl fmt::Display for Error {
414 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> ::core::result::Result<(), fmt::Error> {
415 match *self {
416 Error::Io => write!(f, "I/O error"),
417 Error::PcRelativePointerButSectionBaseIsUndefined => {
418 write!(f, "undefined section base for DW_EH_PE_pcrel pointer")
419 }
420 Error::TextRelativePointerButTextBaseIsUndefined => {
421 write!(f, "undefined text base for DW_EH_PE_textrel pointer")
422 }
423 Error::DataRelativePointerButDataBaseIsUndefined => {
424 write!(f, "undefined data base for DW_EH_PE_datarel pointer")
425 }
426 Error::FuncRelativePointerInBadContext => {
427 write!(f, "invalid context for DW_EH_PE_funcrel pointer")
428 }
429 Error::CannotParseOmitPointerEncoding => {
430 write!(f, "invalid encoding for required pointer: DW_EH_PE_omit")
431 }
432 Error::BadUnsignedLeb128 => write!(f, "unsigned LEB128 overflow"),
433 Error::BadSignedLeb128 => write!(f, "signed LEB128 overflow"),
434 Error::AbbreviationTagZero => {
435 write!(f, "invalid abbreviation tag: zero")
436 }
437 Error::AttributeNameZero => {
438 write!(f, "invalid attribute name: zero")
439 }
440 Error::AttributeFormZero => {
441 write!(f, "invalid attribute form: zero")
442 }
443 Error::InvalidAbbreviationChildren(val) => {
444 write!(f, "invalid abbreviation children: 0x{:x}", val.0)
445 }
446 Error::UnknownForm(val) => write!(f, "unknown attribute form: 0x{:x}", val.0),
447 Error::DuplicateAbbreviationCode(val) => {
448 write!(f, "duplicate abbreviation code: {val}")
449 }
450 Error::UnknownReservedLength(val) => write!(f, "unknown reserved length: 0x{val:x}"),
451 Error::UnknownVersion(version) => write!(f, "unknown DWARF version: {version}"),
452 Error::InvalidAbbreviationCode(val) => {
453 write!(f, "invalid abbreviation code: {val}")
454 }
455 Error::UnexpectedEof(_) => write!(f, "unexpected end of input"),
456 Error::UnknownLocListsEntry(val) => {
457 write!(f, "unknown location lists entry: 0x{:x}", val.0)
458 }
459 Error::UnknownRangeListsEntry(val) => {
460 write!(f, "unknown range lists entry: 0x{:x}", val.0)
461 }
462 Error::UnsupportedAddressSize(val) => {
463 write!(f, "unsupported address size: {val}")
464 }
465 Error::UnsupportedOffsetSize(val) => {
466 write!(f, "unsupported offset size: {val}")
467 }
468 Error::MinimumInstructionLengthZero => {
469 write!(f, "invalid minimum line instruction length: zero")
470 }
471 Error::MaximumOperationsPerInstructionZero => {
472 write!(f, "invalid maximum operations per line instruction: zero")
473 }
474 Error::LineRangeZero => write!(f, "invalid line range: zero"),
475 Error::OpcodeBaseZero => write!(f, "invalid line opcode base: zero"),
476 Error::BadUtf8 => write!(f, "invalid UTF-8"),
477 Error::NotCieId(val) => write!(f, "invalid CIE at offset 0x{val:x}: missing CIE ID"),
478 Error::NotCiePointer(val) => {
479 write!(f, "invalid FDE at offset 0x{val:x}: missing CIE pointer")
480 }
481 Error::BadBranchTarget(_) => write!(f, "invalid expression branch target"),
482 Error::InvalidPushObjectAddress => {
483 write!(f, "undefined object address for DW_OP_push_object_address")
484 }
485 Error::NotEnoughStackItems => {
486 write!(f, "expression stack underflow")
487 }
488 Error::TooManyIterations => {
489 write!(f, "exceeded maximum expression iterations")
490 }
491 Error::InvalidExpression(val) => write!(f, "unknown expression opcode: 0x{:x}", val.0),
492 Error::UnsupportedEvaluation => {
493 write!(f, "unsupported evaluation operation")
494 }
495 Error::InvalidPiece => {
496 write!(f, "invalid expression: piece followed by non-piece")
497 }
498 Error::InvalidExpressionTerminator(_) => {
499 write!(f, "invalid expression terminator")
500 }
501 Error::DivisionByZero => {
502 write!(f, "division by zero")
503 }
504 Error::TypeMismatch => write!(f, "invalid operand type: mismatch"),
505 Error::IntegralTypeRequired => {
506 write!(f, "invalid operand type: integral required")
507 }
508 Error::UnsupportedTypeOperation => {
509 write!(f, "unsupported operand type")
510 }
511 Error::InvalidShiftExpression => {
512 write!(f, "invalid shift amount")
513 }
514 Error::InvalidDerefSize(val) => {
515 write!(f, "invalid deref size: {val}")
516 }
517 Error::UnknownCallFrameInstruction(val) => {
518 write!(f, "unknown call frame instruction: 0x{:x}", val.0)
519 }
520 Error::InvalidCfiSetLoc(val) => {
521 write!(f, "invalid DW_CFA_set_loc: address 0x{val:x} goes backward")
522 }
523 Error::AddressOverflow => write!(f, "address overflow"),
524 Error::CfiInstructionInInvalidContext => {
525 write!(f, "invalid context for call frame instruction")
526 }
527 Error::PopWithEmptyStack => {
528 write!(f, "invalid DW_CFA_restore_state: empty stack")
529 }
530 Error::NoUnwindInfoForAddress => {
531 write!(f, "no unwind info for address")
532 }
533 Error::UnsupportedOffset => {
534 write!(f, "offset overflow")
535 }
536 Error::UnknownPointerEncoding(val) => {
537 write!(f, "unknown pointer encoding: 0x{:x}", val.0)
538 }
539 Error::NoEntryAtGivenOffset(val) => write!(f, "no entry at offset: 0x{val:x}"),
540 Error::OffsetOutOfBounds(val) => write!(f, "invalid offset: 0x{val:x}"),
541 Error::UnknownAugmentation => write!(f, "unknown CFI augmentation"),
542 Error::UnsupportedPointerEncoding(val) => {
543 write!(f, "unsupported pointer encoding: 0x{:x}", val.0)
544 }
545 Error::UnsupportedIndirectPointer => {
546 write!(f, "unsupported indirect pointer")
547 }
548 Error::UnsupportedRegister(val) => {
549 write!(f, "unsupported register: 0x{val:x}")
550 }
551 Error::TooManyRegisterRules => {
552 write!(f, "too many CFI register rules")
553 }
554 Error::StackFull => {
555 write!(f, "CFI stack overflow")
556 }
557 Error::UnknownUnitType(val) => {
558 write!(f, "unknown unit type: 0x{:x}", val.0)
559 }
560 Error::UnsupportedSegmentSize(val) => write!(f, "unsupported segment size: {val}"),
561 Error::MissingUnitDie => {
562 write!(f, "missing unit DIE")
563 }
564 Error::MissingSplitUnit => {
565 write!(f, "missing split compilation unit")
566 }
567 Error::UnsupportedAttributeForm(val) => {
568 write!(f, "unsupported attribute form: 0x{:x}", val.0)
569 }
570 Error::MissingFileEntryFormatPath => {
571 write!(f, "missing file entry format path")
572 }
573 Error::ExpectedStringAttributeValue => {
574 write!(f, "invalid attribute form for string")
575 }
576 Error::InvalidImplicitConst => {
577 write!(f, "invalid indirect attribute form: DW_FORM_implicit_const")
578 }
579 Error::UnsupportedIndexSectionCount(val) => {
580 write!(f, "unsupported DWP section count: {val}")
581 }
582 Error::InvalidIndexSlotCount(val) => write!(f, "invalid DWP slot count: 0x{:x}", val),
583 Error::InvalidIndexRow(val) => write!(f, "invalid DWP row index: 0x{:x}", val),
584 Error::UnknownIndexSection(val) => write!(f, "unknown DWP section type: 0x{:x}", val.0),
585 Error::UnknownIndexSectionV2(val) => {
586 write!(f, "unknown DWP v2 section type: 0x{:x}", val.0)
587 }
588 Error::InvalidMacinfoType(val) => write!(f, "unknown macinfo type: 0x{:x}", val.0),
589 Error::InvalidMacroType(val) => write!(f, "unknown macro type: 0x{:x}", val.0),
590 Error::UnsupportedOpcodeOperandsTable => {
591 write!(f, "unsupported macro opcode operands table")
592 }
593 Error::InvalidNameAttributeIndex(val) => {
594 write!(f, "invalid index in name attribute: 0x{val:x}")
595 }
596 }
597 }
598}
599
600impl error::Error for Error {}
601
602#[cfg(feature = "std")]
603impl From<io::Error> for Error {
604 fn from(_: io::Error) -> Self {
605 Error::Io
606 }
607}
608
609pub type Result<T> = result::Result<T, Error>;
611
612pub trait Section<R>: From<R> {
625 fn id() -> SectionId;
627
628 fn section_name() -> &'static str {
630 Self::id().name()
631 }
632
633 fn dwo_section_name() -> Option<&'static str> {
636 Self::id().dwo_name()
637 }
638
639 fn xcoff_section_name() -> Option<&'static str> {
642 Self::id().xcoff_name()
643 }
644
645 fn load<F, E>(f: F) -> core::result::Result<Self, E>
647 where
648 F: FnOnce(SectionId) -> core::result::Result<R, E>,
649 {
650 f(Self::id()).map(From::from)
651 }
652
653 fn reader(&self) -> &R
655 where
656 R: Reader;
657
658 fn dwp_range(&self, offset: u32, size: u32) -> Result<Self>
661 where
662 R: Reader,
663 {
664 let mut data = self.reader().clone();
665 data.skip(R::Offset::from_u32(offset))?;
666 data.truncate(R::Offset::from_u32(size))?;
667 Ok(data.into())
668 }
669
670 fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(SectionId, R::Offset)>
672 where
673 R: Reader,
674 {
675 self.reader()
676 .lookup_offset_id(id)
677 .map(|offset| (Self::id(), offset))
678 }
679}
680
681impl Register {
682 pub(crate) fn from_u64(x: u64) -> Result<Register> {
683 let y = x as u16;
684 if u64::from(y) == x {
685 Ok(Register(y))
686 } else {
687 Err(Error::UnsupportedRegister(x))
688 }
689 }
690}
691
692#[cfg(test)]
693mod tests {
694 use super::*;
695 use crate::common::Format;
696 use crate::endianity::LittleEndian;
697 use test_assembler::{Endian, Section};
698
699 #[test]
700 fn test_parse_initial_length_32_ok() {
701 let section = Section::with_endian(Endian::Little).L32(0x7856_3412);
702 let buf = section.get_contents().unwrap();
703
704 let input = &mut EndianSlice::new(&buf, LittleEndian);
705 match input.read_initial_length() {
706 Ok((length, format)) => {
707 assert_eq!(input.len(), 0);
708 assert_eq!(format, Format::Dwarf32);
709 assert_eq!(0x7856_3412, length);
710 }
711 otherwise => panic!("Unexpected result: {:?}", otherwise),
712 }
713 }
714
715 #[test]
716 fn test_parse_initial_length_64_ok() {
717 let section = Section::with_endian(Endian::Little)
718 .L32(0xffff_ffff)
720 .L64(0xffde_bc9a_7856_3412);
722 let buf = section.get_contents().unwrap();
723 let input = &mut EndianSlice::new(&buf, LittleEndian);
724
725 #[cfg(target_pointer_width = "64")]
726 match input.read_initial_length() {
727 Ok((length, format)) => {
728 assert_eq!(input.len(), 0);
729 assert_eq!(format, Format::Dwarf64);
730 assert_eq!(0xffde_bc9a_7856_3412, length);
731 }
732 otherwise => panic!("Unexpected result: {:?}", otherwise),
733 }
734
735 #[cfg(target_pointer_width = "32")]
736 match input.read_initial_length() {
737 Err(Error::UnsupportedOffset) => {}
738 otherwise => panic!("Unexpected result: {:?}", otherwise),
739 };
740 }
741
742 #[test]
743 fn test_parse_initial_length_unknown_reserved_value() {
744 let section = Section::with_endian(Endian::Little).L32(0xffff_fffe);
745 let buf = section.get_contents().unwrap();
746
747 let input = &mut EndianSlice::new(&buf, LittleEndian);
748 match input.read_initial_length() {
749 Err(Error::UnknownReservedLength(0xffff_fffe)) => {}
750 otherwise => panic!("Unexpected result: {:?}", otherwise),
751 };
752 }
753
754 #[test]
755 fn test_parse_initial_length_incomplete() {
756 let buf = [0xff, 0xff, 0xff]; let input = &mut EndianSlice::new(&buf, LittleEndian);
759 match input.read_initial_length() {
760 Err(Error::UnexpectedEof(_)) => {}
761 otherwise => panic!("Unexpected result: {:?}", otherwise),
762 };
763 }
764
765 #[test]
766 fn test_parse_initial_length_64_incomplete() {
767 let section = Section::with_endian(Endian::Little)
768 .L32(0xffff_ffff)
770 .L32(0x7856_3412);
772 let buf = section.get_contents().unwrap();
773
774 let input = &mut EndianSlice::new(&buf, LittleEndian);
775 match input.read_initial_length() {
776 Err(Error::UnexpectedEof(_)) => {}
777 otherwise => panic!("Unexpected result: {:?}", otherwise),
778 };
779 }
780
781 #[test]
782 fn test_parse_offset_32() {
783 let section = Section::with_endian(Endian::Little).L32(0x0123_4567);
784 let buf = section.get_contents().unwrap();
785
786 let input = &mut EndianSlice::new(&buf, LittleEndian);
787 match input.read_offset(Format::Dwarf32) {
788 Ok(val) => {
789 assert_eq!(input.len(), 0);
790 assert_eq!(val, 0x0123_4567);
791 }
792 otherwise => panic!("Unexpected result: {:?}", otherwise),
793 };
794 }
795
796 #[test]
797 fn test_parse_offset_64_small() {
798 let section = Section::with_endian(Endian::Little).L64(0x0123_4567);
799 let buf = section.get_contents().unwrap();
800
801 let input = &mut EndianSlice::new(&buf, LittleEndian);
802 match input.read_offset(Format::Dwarf64) {
803 Ok(val) => {
804 assert_eq!(input.len(), 0);
805 assert_eq!(val, 0x0123_4567);
806 }
807 otherwise => panic!("Unexpected result: {:?}", otherwise),
808 };
809 }
810
811 #[test]
812 #[cfg(target_pointer_width = "64")]
813 fn test_parse_offset_64_large() {
814 let section = Section::with_endian(Endian::Little).L64(0x0123_4567_89ab_cdef);
815 let buf = section.get_contents().unwrap();
816
817 let input = &mut EndianSlice::new(&buf, LittleEndian);
818 match input.read_offset(Format::Dwarf64) {
819 Ok(val) => {
820 assert_eq!(input.len(), 0);
821 assert_eq!(val, 0x0123_4567_89ab_cdef);
822 }
823 otherwise => panic!("Unexpected result: {:?}", otherwise),
824 };
825 }
826
827 #[test]
828 #[cfg(target_pointer_width = "32")]
829 fn test_parse_offset_64_large() {
830 let section = Section::with_endian(Endian::Little).L64(0x0123_4567_89ab_cdef);
831 let buf = section.get_contents().unwrap();
832
833 let input = &mut EndianSlice::new(&buf, LittleEndian);
834 match input.read_offset(Format::Dwarf64) {
835 Err(Error::UnsupportedOffset) => {}
836 otherwise => panic!("Unexpected result: {:?}", otherwise),
837 };
838 }
839}