1 use alloc
::string
::String
;
4 DebugAddrBase
, DebugAddrIndex
, DebugInfoOffset
, DebugLineStrOffset
, DebugLocListsBase
,
5 DebugLocListsIndex
, DebugRngListsBase
, DebugRngListsIndex
, DebugStrOffset
, DebugStrOffsetsBase
,
6 DebugStrOffsetsIndex
, DebugTypesOffset
, DwarfFileType
, Encoding
, LocationListsOffset
,
7 RangeListsOffset
, SectionId
, UnitSectionOffset
,
11 Abbreviations
, AttributeValue
, DebugAbbrev
, DebugAddr
, DebugInfo
, DebugInfoUnitHeadersIter
,
12 DebugLine
, DebugLineStr
, DebugStr
, DebugStrOffsets
, DebugTypes
, DebugTypesUnitHeadersIter
,
13 DebuggingInformationEntry
, EntriesCursor
, EntriesRaw
, EntriesTree
, Error
,
14 IncompleteLineProgram
, LocListIter
, LocationLists
, Range
, RangeLists
, Reader
, ReaderOffset
,
15 ReaderOffsetId
, Result
, RngListIter
, Section
, UnitHeader
, UnitOffset
,
18 /// All of the commonly used DWARF sections, and other common information.
19 #[derive(Debug, Default)]
21 /// The `.debug_abbrev` section.
22 pub debug_abbrev
: DebugAbbrev
<R
>,
24 /// The `.debug_addr` section.
25 pub debug_addr
: DebugAddr
<R
>,
27 /// The `.debug_info` section.
28 pub debug_info
: DebugInfo
<R
>,
30 /// The `.debug_line` section.
31 pub debug_line
: DebugLine
<R
>,
33 /// The `.debug_line_str` section.
34 pub debug_line_str
: DebugLineStr
<R
>,
36 /// The `.debug_str` section.
37 pub debug_str
: DebugStr
<R
>,
39 /// The `.debug_str_offsets` section.
40 pub debug_str_offsets
: DebugStrOffsets
<R
>,
42 /// The `.debug_str` section for a supplementary object file.
43 pub debug_str_sup
: DebugStr
<R
>,
45 /// The `.debug_types` section.
46 pub debug_types
: DebugTypes
<R
>,
48 /// The location lists in the `.debug_loc` and `.debug_loclists` sections.
49 pub locations
: LocationLists
<R
>,
51 /// The range lists in the `.debug_ranges` and `.debug_rnglists` sections.
52 pub ranges
: RangeLists
<R
>,
54 /// The type of this file.
55 pub file_type
: DwarfFileType
,
59 /// Try to load the DWARF sections using the given loader functions.
61 /// `section` loads a DWARF section from the main object file.
62 /// `sup` loads a DWARF sections from the supplementary object file.
63 /// These functions should return an empty section if the section does not exist.
65 /// The provided callback functions may either directly return a `Reader` instance
66 /// (such as `EndianSlice`), or they may return some other type and then convert
67 /// that type into a `Reader` using `Dwarf::borrow`.
68 pub fn load
<F1
, F2
, E
>(mut section
: F1
, mut sup
: F2
) -> core
::result
::Result
<Self, E
>
70 F1
: FnMut(SectionId
) -> core
::result
::Result
<T
, E
>,
71 F2
: FnMut(SectionId
) -> core
::result
::Result
<T
, E
>,
73 // Section types are inferred.
74 let debug_loc
= Section
::load(&mut section
)?
;
75 let debug_loclists
= Section
::load(&mut section
)?
;
76 let debug_ranges
= Section
::load(&mut section
)?
;
77 let debug_rnglists
= Section
::load(&mut section
)?
;
79 debug_abbrev
: Section
::load(&mut section
)?
,
80 debug_addr
: Section
::load(&mut section
)?
,
81 debug_info
: Section
::load(&mut section
)?
,
82 debug_line
: Section
::load(&mut section
)?
,
83 debug_line_str
: Section
::load(&mut section
)?
,
84 debug_str
: Section
::load(&mut section
)?
,
85 debug_str_offsets
: Section
::load(&mut section
)?
,
86 debug_str_sup
: Section
::load(&mut sup
)?
,
87 debug_types
: Section
::load(&mut section
)?
,
88 locations
: LocationLists
::new(debug_loc
, debug_loclists
),
89 ranges
: RangeLists
::new(debug_ranges
, debug_rnglists
),
90 file_type
: DwarfFileType
::Main
,
94 /// Create a `Dwarf` structure that references the data in `self`.
96 /// This is useful when `R` implements `Reader` but `T` does not.
100 /// It can be useful to load DWARF sections into owned data structures,
101 /// such as `Vec`. However, we do not implement the `Reader` trait
102 /// for `Vec`, because it would be very inefficient, but this trait
103 /// is required for all of the methods that parse the DWARF data.
104 /// So we first load the DWARF sections into `Vec`s, and then use
105 /// `borrow` to create `Reader`s that reference the data.
108 /// # fn example() -> Result<(), gimli::Error> {
109 /// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() };
110 /// # let sup_loader = |name| { unimplemented!() };
111 /// // Read the DWARF sections into `Vec`s with whatever object loader you're using.
112 /// let owned_dwarf: gimli::Dwarf<Vec<u8>> = gimli::Dwarf::load(loader, sup_loader)?;
113 /// // Create references to the DWARF sections.
114 /// let dwarf = owned_dwarf.borrow(|section| {
115 /// gimli::EndianSlice::new(§ion, gimli::LittleEndian)
120 pub fn borrow
<'a
, F
, R
>(&'a
self, mut borrow
: F
) -> Dwarf
<R
>
122 F
: FnMut(&'a T
) -> R
,
125 debug_abbrev
: self.debug_abbrev
.borrow(&mut borrow
),
126 debug_addr
: self.debug_addr
.borrow(&mut borrow
),
127 debug_info
: self.debug_info
.borrow(&mut borrow
),
128 debug_line
: self.debug_line
.borrow(&mut borrow
),
129 debug_line_str
: self.debug_line_str
.borrow(&mut borrow
),
130 debug_str
: self.debug_str
.borrow(&mut borrow
),
131 debug_str_offsets
: self.debug_str_offsets
.borrow(&mut borrow
),
132 debug_str_sup
: self.debug_str_sup
.borrow(&mut borrow
),
133 debug_types
: self.debug_types
.borrow(&mut borrow
),
134 locations
: self.locations
.borrow(&mut borrow
),
135 ranges
: self.ranges
.borrow(&mut borrow
),
136 file_type
: self.file_type
,
141 impl<R
: Reader
> Dwarf
<R
> {
142 /// Iterate the unit headers in the `.debug_info` section.
144 /// Can be [used with
145 /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
147 pub fn units(&self) -> DebugInfoUnitHeadersIter
<R
> {
148 self.debug_info
.units()
151 /// Construct a new `Unit` from the given unit header.
153 pub fn unit(&self, header
: UnitHeader
<R
>) -> Result
<Unit
<R
>> {
154 Unit
::new(self, header
)
157 /// Iterate the type-unit headers in the `.debug_types` section.
159 /// Can be [used with
160 /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
162 pub fn type_units(&self) -> DebugTypesUnitHeadersIter
<R
> {
163 self.debug_types
.units()
166 /// Parse the abbreviations for a compilation unit.
167 // TODO: provide caching of abbreviations
169 pub fn abbreviations(&self, unit
: &UnitHeader
<R
>) -> Result
<Abbreviations
> {
170 unit
.abbreviations(&self.debug_abbrev
)
173 /// Return the string offset at the given index.
175 pub fn string_offset(
178 index
: DebugStrOffsetsIndex
<R
::Offset
>,
179 ) -> Result
<DebugStrOffset
<R
::Offset
>> {
180 self.debug_str_offsets
181 .get_str_offset(unit
.header
.format(), unit
.str_offsets_base
, index
)
184 /// Return the string at the given offset in `.debug_str`.
186 pub fn string(&self, offset
: DebugStrOffset
<R
::Offset
>) -> Result
<R
> {
187 self.debug_str
.get_str(offset
)
190 /// Return the string at the given offset in `.debug_line_str`.
192 pub fn line_string(&self, offset
: DebugLineStrOffset
<R
::Offset
>) -> Result
<R
> {
193 self.debug_line_str
.get_str(offset
)
196 /// Return an attribute value as a string slice.
198 /// If the attribute value is one of:
200 /// - an inline `DW_FORM_string` string
201 /// - a `DW_FORM_strp` reference to an offset into the `.debug_str` section
202 /// - a `DW_FORM_strp_sup` reference to an offset into a supplementary
204 /// - a `DW_FORM_line_strp` reference to an offset into the `.debug_line_str`
206 /// - a `DW_FORM_strx` index into the `.debug_str_offsets` entries for the unit
208 /// then return the attribute's string value. Returns an error if the attribute
209 /// value does not have a string form, or if a string form has an invalid value.
210 pub fn attr_string(&self, unit
: &Unit
<R
>, attr
: AttributeValue
<R
>) -> Result
<R
> {
212 AttributeValue
::String(string
) => Ok(string
),
213 AttributeValue
::DebugStrRef(offset
) => self.debug_str
.get_str(offset
),
214 AttributeValue
::DebugStrRefSup(offset
) => self.debug_str_sup
.get_str(offset
),
215 AttributeValue
::DebugLineStrRef(offset
) => self.debug_line_str
.get_str(offset
),
216 AttributeValue
::DebugStrOffsetsIndex(index
) => {
217 let offset
= self.debug_str_offsets
.get_str_offset(
218 unit
.header
.format(),
219 unit
.str_offsets_base
,
222 self.debug_str
.get_str(offset
)
224 _
=> Err(Error
::ExpectedStringAttributeValue
),
228 /// Return the address at the given index.
229 pub fn address(&self, unit
: &Unit
<R
>, index
: DebugAddrIndex
<R
::Offset
>) -> Result
<u64> {
231 .get_address(unit
.encoding().address_size
, unit
.addr_base
, index
)
234 /// Try to return an attribute value as an address.
236 /// If the attribute value is one of:
238 /// - a `DW_FORM_addr`
239 /// - a `DW_FORM_addrx` index into the `.debug_addr` entries for the unit
241 /// then return the address.
242 /// Returns `None` for other forms.
243 pub fn attr_address(&self, unit
: &Unit
<R
>, attr
: AttributeValue
<R
>) -> Result
<Option
<u64>> {
245 AttributeValue
::Addr(addr
) => Ok(Some(addr
)),
246 AttributeValue
::DebugAddrIndex(index
) => self.address(unit
, index
).map(Some
),
251 /// Return the range list offset at the given index.
252 pub fn ranges_offset(
255 index
: DebugRngListsIndex
<R
::Offset
>,
256 ) -> Result
<RangeListsOffset
<R
::Offset
>> {
258 .get_offset(unit
.encoding(), unit
.rnglists_base
, index
)
261 /// Iterate over the `RangeListEntry`s starting at the given offset.
265 offset
: RangeListsOffset
<R
::Offset
>,
266 ) -> Result
<RngListIter
<R
>> {
276 /// Try to return an attribute value as a range list offset.
278 /// If the attribute value is one of:
280 /// - a `DW_FORM_sec_offset` reference to the `.debug_ranges` or `.debug_rnglists` sections
281 /// - a `DW_FORM_rnglistx` index into the `.debug_rnglists` entries for the unit
283 /// then return the range list offset of the range list.
284 /// Returns `None` for other forms.
285 pub fn attr_ranges_offset(
288 attr
: AttributeValue
<R
>,
289 ) -> Result
<Option
<RangeListsOffset
<R
::Offset
>>> {
291 AttributeValue
::RangeListsRef(offset
) => Ok(Some(offset
)),
292 AttributeValue
::DebugRngListsIndex(index
) => self.ranges_offset(unit
, index
).map(Some
),
297 /// Try to return an attribute value as a range list entry iterator.
299 /// If the attribute value is one of:
301 /// - a `DW_FORM_sec_offset` reference to the `.debug_ranges` or `.debug_rnglists` sections
302 /// - a `DW_FORM_rnglistx` index into the `.debug_rnglists` entries for the unit
304 /// then return an iterator over the entries in the range list.
305 /// Returns `None` for other forms.
309 attr
: AttributeValue
<R
>,
310 ) -> Result
<Option
<RngListIter
<R
>>> {
311 match self.attr_ranges_offset(unit
, attr
)?
{
312 Some(offset
) => Ok(Some(self.ranges(unit
, offset
)?
)),
317 /// Return an iterator for the address ranges of a `DebuggingInformationEntry`.
319 /// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges`.
323 entry
: &DebuggingInformationEntry
<R
>,
324 ) -> Result
<RangeIter
<R
>> {
325 let mut low_pc
= None
;
326 let mut high_pc
= None
;
328 let mut attrs
= entry
.attrs();
329 while let Some(attr
) = attrs
.next()?
{
331 constants
::DW_AT_low_pc
=> {
332 if let AttributeValue
::Addr(val
) = attr
.value() {
336 constants
::DW_AT_high_pc
=> match attr
.value() {
337 AttributeValue
::Addr(val
) => high_pc
= Some(val
),
338 AttributeValue
::Udata(val
) => size
= Some(val
),
339 _
=> return Err(Error
::UnsupportedAttributeForm
),
341 constants
::DW_AT_ranges
=> {
342 if let Some(list
) = self.attr_ranges(unit
, attr
.value())?
{
343 return Ok(RangeIter(RangeIterInner
::List(list
)));
349 let range
= low_pc
.and_then(|begin
| {
350 let end
= size
.map(|size
| begin
+ size
).or(high_pc
);
351 // TODO: perhaps return an error if `end` is `None`
352 end
.map(|end
| Range { begin, end }
)
354 Ok(RangeIter(RangeIterInner
::Single(range
)))
357 /// Return an iterator for the address ranges of a `Unit`.
359 /// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges` of the
360 /// root `DebuggingInformationEntry`.
361 pub fn unit_ranges(&self, unit
: &Unit
<R
>) -> Result
<RangeIter
<R
>> {
362 let mut cursor
= unit
.header
.entries(&unit
.abbreviations
);
364 let root
= cursor
.current().ok_or(Error
::MissingUnitDie
)?
;
365 self.die_ranges(unit
, root
)
368 /// Return the location list offset at the given index.
369 pub fn locations_offset(
372 index
: DebugLocListsIndex
<R
::Offset
>,
373 ) -> Result
<LocationListsOffset
<R
::Offset
>> {
375 .get_offset(unit
.encoding(), unit
.loclists_base
, index
)
378 /// Iterate over the `LocationListEntry`s starting at the given offset.
382 offset
: LocationListsOffset
<R
::Offset
>,
383 ) -> Result
<LocListIter
<R
>> {
384 match self.file_type
{
385 DwarfFileType
::Main
=> self.locations
.locations(
392 DwarfFileType
::Dwo
=> self.locations
.locations_dwo(
402 /// Try to return an attribute value as a location list offset.
404 /// If the attribute value is one of:
406 /// - a `DW_FORM_sec_offset` reference to the `.debug_loc` or `.debug_loclists` sections
407 /// - a `DW_FORM_loclistx` index into the `.debug_loclists` entries for the unit
409 /// then return the location list offset of the location list.
410 /// Returns `None` for other forms.
411 pub fn attr_locations_offset(
414 attr
: AttributeValue
<R
>,
415 ) -> Result
<Option
<LocationListsOffset
<R
::Offset
>>> {
417 AttributeValue
::LocationListsRef(offset
) => Ok(Some(offset
)),
418 AttributeValue
::DebugLocListsIndex(index
) => {
419 self.locations_offset(unit
, index
).map(Some
)
425 /// Try to return an attribute value as a location list entry iterator.
427 /// If the attribute value is one of:
429 /// - a `DW_FORM_sec_offset` reference to the `.debug_loc` or `.debug_loclists` sections
430 /// - a `DW_FORM_loclistx` index into the `.debug_loclists` entries for the unit
432 /// then return an iterator over the entries in the location list.
433 /// Returns `None` for other forms.
434 pub fn attr_locations(
437 attr
: AttributeValue
<R
>,
438 ) -> Result
<Option
<LocListIter
<R
>>> {
439 match self.attr_locations_offset(unit
, attr
)?
{
440 Some(offset
) => Ok(Some(self.locations(unit
, offset
)?
)),
445 /// Call `Reader::lookup_offset_id` for each section, and return the first match.
447 /// The first element of the tuple is `true` for supplementary sections.
448 pub fn lookup_offset_id(&self, id
: ReaderOffsetId
) -> Option
<(bool
, SectionId
, R
::Offset
)> {
449 None
.or_else(|| self.debug_abbrev
.lookup_offset_id(id
))
450 .or_else(|| self.debug_addr
.lookup_offset_id(id
))
451 .or_else(|| self.debug_info
.lookup_offset_id(id
))
452 .or_else(|| self.debug_line
.lookup_offset_id(id
))
453 .or_else(|| self.debug_line_str
.lookup_offset_id(id
))
454 .or_else(|| self.debug_str
.lookup_offset_id(id
))
455 .or_else(|| self.debug_str_offsets
.lookup_offset_id(id
))
456 .or_else(|| self.debug_types
.lookup_offset_id(id
))
457 .or_else(|| self.locations
.lookup_offset_id(id
))
458 .or_else(|| self.ranges
.lookup_offset_id(id
))
459 .map(|(id
, offset
)| (false, id
, offset
))
462 .lookup_offset_id(id
)
463 .map(|(id
, offset
)| (true, id
, offset
))
467 /// Returns a string representation of the given error.
469 /// This uses information from the DWARF sections to provide more information in some cases.
470 pub fn format_error(&self, err
: Error
) -> String
{
471 #[allow(clippy::single_match)]
473 Error
::UnexpectedEof(id
) => match self.lookup_offset_id(id
) {
474 Some((sup
, section
, offset
)) => {
479 if sup { "(sup)" }
else { "" }
,
487 err
.description().into()
491 /// All of the commonly used information for a unit in the `.debug_info` or `.debug_types`
494 pub struct Unit
<R
, Offset
= <R
as Reader
>::Offset
>
496 R
: Reader
<Offset
= Offset
>,
497 Offset
: ReaderOffset
,
499 /// The header of the unit.
500 pub header
: UnitHeader
<R
, Offset
>,
502 /// The parsed abbreviations for the unit.
503 pub abbreviations
: Abbreviations
,
505 /// The `DW_AT_name` attribute of the unit.
508 /// The `DW_AT_comp_dir` attribute of the unit.
509 pub comp_dir
: Option
<R
>,
511 /// The `DW_AT_low_pc` attribute of the unit. Defaults to 0.
514 /// The `DW_AT_str_offsets_base` attribute of the unit. Defaults to 0.
515 pub str_offsets_base
: DebugStrOffsetsBase
<Offset
>,
517 /// The `DW_AT_addr_base` attribute of the unit. Defaults to 0.
518 pub addr_base
: DebugAddrBase
<Offset
>,
520 /// The `DW_AT_loclists_base` attribute of the unit. Defaults to 0.
521 pub loclists_base
: DebugLocListsBase
<Offset
>,
523 /// The `DW_AT_rnglists_base` attribute of the unit. Defaults to 0.
524 pub rnglists_base
: DebugRngListsBase
<Offset
>,
526 /// The line number program of the unit.
527 pub line_program
: Option
<IncompleteLineProgram
<R
, Offset
>>,
530 impl<R
: Reader
> Unit
<R
> {
531 /// Construct a new `Unit` from the given unit header.
533 pub fn new(dwarf
: &Dwarf
<R
>, header
: UnitHeader
<R
>) -> Result
<Self> {
534 let abbreviations
= header
.abbreviations(&dwarf
.debug_abbrev
)?
;
535 let mut unit
= Unit
{
540 str_offsets_base
: DebugStrOffsetsBase
::default_for_encoding_and_file(
544 // NB: Because the .debug_addr section never lives in a .dwo, we can assume its base is always 0 or provided.
545 addr_base
: DebugAddrBase(R
::Offset
::from_u8(0)),
546 loclists_base
: DebugLocListsBase
::default_for_encoding_and_file(
550 rnglists_base
: DebugRngListsBase
::default_for_encoding_and_file(
558 let mut comp_dir
= None
;
559 let mut line_program_offset
= None
;
562 let mut cursor
= unit
.header
.entries(&unit
.abbreviations
);
564 let root
= cursor
.current().ok_or(Error
::MissingUnitDie
)?
;
565 let mut attrs
= root
.attrs();
566 while let Some(attr
) = attrs
.next()?
{
568 constants
::DW_AT_name
=> {
569 name
= Some(attr
.value());
571 constants
::DW_AT_comp_dir
=> {
572 comp_dir
= Some(attr
.value());
574 constants
::DW_AT_low_pc
=> {
575 if let AttributeValue
::Addr(address
) = attr
.value() {
576 unit
.low_pc
= address
;
579 constants
::DW_AT_stmt_list
=> {
580 if let AttributeValue
::DebugLineRef(offset
) = attr
.value() {
581 line_program_offset
= Some(offset
);
584 constants
::DW_AT_str_offsets_base
=> {
585 if let AttributeValue
::DebugStrOffsetsBase(base
) = attr
.value() {
586 unit
.str_offsets_base
= base
;
589 constants
::DW_AT_addr_base
| constants
::DW_AT_GNU_addr_base
=> {
590 if let AttributeValue
::DebugAddrBase(base
) = attr
.value() {
591 unit
.addr_base
= base
;
594 constants
::DW_AT_loclists_base
=> {
595 if let AttributeValue
::DebugLocListsBase(base
) = attr
.value() {
596 unit
.loclists_base
= base
;
599 constants
::DW_AT_rnglists_base
| constants
::DW_AT_GNU_ranges_base
=> {
600 if let AttributeValue
::DebugRngListsBase(base
) = attr
.value() {
601 unit
.rnglists_base
= base
;
609 unit
.name
= match name
{
610 Some(val
) => dwarf
.attr_string(&unit
, val
).ok(),
613 unit
.comp_dir
= match comp_dir
{
614 Some(val
) => dwarf
.attr_string(&unit
, val
).ok(),
617 unit
.line_program
= match line_program_offset
{
618 Some(offset
) => Some(dwarf
.debug_line
.program(
620 unit
.header
.address_size(),
621 unit
.comp_dir
.clone(),
629 /// Return the encoding parameters for this unit.
631 pub fn encoding(&self) -> Encoding
{
632 self.header
.encoding()
635 /// Read the `DebuggingInformationEntry` at the given offset.
636 pub fn entry(&self, offset
: UnitOffset
<R
::Offset
>) -> Result
<DebuggingInformationEntry
<R
>> {
637 self.header
.entry(&self.abbreviations
, offset
)
640 /// Navigate this unit's `DebuggingInformationEntry`s.
642 pub fn entries(&self) -> EntriesCursor
<R
> {
643 self.header
.entries(&self.abbreviations
)
646 /// Navigate this unit's `DebuggingInformationEntry`s
647 /// starting at the given offset.
649 pub fn entries_at_offset(&self, offset
: UnitOffset
<R
::Offset
>) -> Result
<EntriesCursor
<R
>> {
650 self.header
.entries_at_offset(&self.abbreviations
, offset
)
653 /// Navigate this unit's `DebuggingInformationEntry`s as a tree
654 /// starting at the given offset.
656 pub fn entries_tree(&self, offset
: Option
<UnitOffset
<R
::Offset
>>) -> Result
<EntriesTree
<R
>> {
657 self.header
.entries_tree(&self.abbreviations
, offset
)
660 /// Read the raw data that defines the Debugging Information Entries.
662 pub fn entries_raw(&self, offset
: Option
<UnitOffset
<R
::Offset
>>) -> Result
<EntriesRaw
<R
>> {
663 self.header
.entries_raw(&self.abbreviations
, offset
)
666 /// Copy attributes that are subject to relocation from another unit. This is intended
667 /// to be used to copy attributes from a skeleton compilation unit to the corresponding
668 /// split compilation unit.
669 pub fn copy_relocated_attributes(&mut self, other
: &Unit
<R
>) {
670 self.low_pc
= other
.low_pc
;
671 self.addr_base
= other
.addr_base
;
672 if self.header
.version() < 5 {
673 self.rnglists_base
= other
.rnglists_base
;
678 impl<T
: ReaderOffset
> UnitSectionOffset
<T
> {
679 /// Convert an offset to be relative to the start of the given unit,
680 /// instead of relative to the start of the section.
681 /// Returns `None` if the offset is not within the unit entries.
682 pub fn to_unit_offset
<R
>(&self, unit
: &Unit
<R
>) -> Option
<UnitOffset
<T
>>
684 R
: Reader
<Offset
= T
>,
686 let (offset
, unit_offset
) = match (self, unit
.header
.offset()) {
688 UnitSectionOffset
::DebugInfoOffset(offset
),
689 UnitSectionOffset
::DebugInfoOffset(unit_offset
),
690 ) => (offset
.0, unit_offset
.0),
692 UnitSectionOffset
::DebugTypesOffset(offset
),
693 UnitSectionOffset
::DebugTypesOffset(unit_offset
),
694 ) => (offset
.0, unit_offset
.0),
697 let offset
= match offset
.checked_sub(unit_offset
) {
698 Some(offset
) => UnitOffset(offset
),
701 if !unit
.header
.is_valid_offset(offset
) {
708 impl<T
: ReaderOffset
> UnitOffset
<T
> {
709 /// Convert an offset to be relative to the start of the .debug_info section,
710 /// instead of relative to the start of the given compilation unit.
712 /// Does not check that the offset is valid.
713 pub fn to_unit_section_offset
<R
>(&self, unit
: &Unit
<R
>) -> UnitSectionOffset
<T
>
715 R
: Reader
<Offset
= T
>,
717 match unit
.header
.offset() {
718 UnitSectionOffset
::DebugInfoOffset(unit_offset
) => {
719 DebugInfoOffset(unit_offset
.0 + self.0).into()
721 UnitSectionOffset
::DebugTypesOffset(unit_offset
) => {
722 DebugTypesOffset(unit_offset
.0 + self.0).into()
728 /// An iterator for the address ranges of a `DebuggingInformationEntry`.
730 /// Returned by `Dwarf::die_ranges` and `Dwarf::unit_ranges`.
732 pub struct RangeIter
<R
: Reader
>(RangeIterInner
<R
>);
735 enum RangeIterInner
<R
: Reader
> {
736 Single(Option
<Range
>),
737 List(RngListIter
<R
>),
740 impl<R
: Reader
> Default
for RangeIter
<R
> {
741 fn default() -> Self {
742 RangeIter(RangeIterInner
::Single(None
))
746 impl<R
: Reader
> RangeIter
<R
> {
747 /// Advance the iterator to the next range.
748 pub fn next(&mut self) -> Result
<Option
<Range
>> {
750 RangeIterInner
::Single(ref mut range
) => Ok(range
.take()),
751 RangeIterInner
::List(ref mut list
) => list
.next(),
756 #[cfg(feature = "fallible-iterator")]
757 impl<R
: Reader
> fallible_iterator
::FallibleIterator
for RangeIter
<R
> {
762 fn next(&mut self) -> ::core
::result
::Result
<Option
<Self::Item
>, Self::Error
> {
763 RangeIter
::next(self)
770 use crate::read
::EndianSlice
;
771 use crate::{Endianity, LittleEndian}
;
773 /// Ensure that `Dwarf<R>` is covariant wrt R.
775 fn test_dwarf_variance() {
776 /// This only needs to compile.
777 fn _f
<'a
: 'b
, 'b
, E
: Endianity
>(x
: Dwarf
<EndianSlice
<'a
, E
>>) -> Dwarf
<EndianSlice
<'b
, E
>> {
782 /// Ensure that `Unit<R>` is covariant wrt R.
784 fn test_dwarf_unit_variance() {
785 /// This only needs to compile.
786 fn _f
<'a
: 'b
, 'b
, E
: Endianity
>(x
: Unit
<EndianSlice
<'a
, E
>>) -> Unit
<EndianSlice
<'b
, E
>> {
792 fn test_format_error() {
794 Dwarf
::load(|_
| -> Result
<_
> { Ok(vec![1, 2]) }
, |_
| Ok(vec
![1, 2])).unwrap();
795 let dwarf
= owned_dwarf
.borrow(|section
| EndianSlice
::new(§ion
, LittleEndian
));
797 match dwarf
.debug_str
.get_str(DebugStrOffset(1)) {
798 Ok(r
) => panic
!("Unexpected str {:?}", r
),
801 dwarf
.format_error(e
),
802 "Hit the end of input before it was expected at .debug_str+0x1"
806 match dwarf
.debug_str_sup
.get_str(DebugStrOffset(1)) {
807 Ok(r
) => panic
!("Unexpected str {:?}", r
),
810 dwarf
.format_error(e
),
811 "Hit the end of input before it was expected at .debug_str(sup)+0x1"
815 assert_eq
!(dwarf
.format_error(Error
::Io
), Error
::Io
.description());