Skip to main content

gimli/read/
dwarf.rs

1use alloc::string::String;
2use alloc::sync::Arc;
3
4use crate::common::{
5    DebugAddrBase, DebugAddrIndex, DebugInfoOffset, DebugLineStrOffset, DebugLocListsBase,
6    DebugLocListsIndex, DebugMacinfoOffset, DebugRngListsBase, DebugRngListsIndex, DebugStrOffset,
7    DebugStrOffsetsBase, DebugStrOffsetsIndex, DebugTypeSignature, DwarfFileType, DwoId, Encoding,
8    LocationListsOffset, RangeListsOffset, RawRangeListsOffset, SectionId,
9};
10use crate::read::{
11    Abbreviations, AbbreviationsCache, AbbreviationsCacheStrategy, AttributeValue, DebugAbbrev,
12    DebugAddr, DebugAranges, DebugCuIndex, DebugInfo, DebugInfoUnitHeadersIter, DebugLine,
13    DebugLineStr, DebugLoc, DebugLocLists, DebugMacinfo, DebugMacro, DebugNames, DebugRanges,
14    DebugRngLists, DebugStr, DebugStrOffsets, DebugTuIndex, DebugTypes, DebugTypesUnitHeadersIter,
15    DebuggingInformationEntry, EntriesCursor, EntriesRaw, EntriesTree, Error,
16    IncompleteLineProgram, IndexSectionId, LocListIter, LocationLists, MacroIter, Range,
17    RangeLists, RawLocListIter, RawRngListIter, Reader, ReaderOffset, ReaderOffsetId, Result,
18    RngListIter, Section, UnitHeader, UnitIndex, UnitIndexSectionIterator, UnitOffset, UnitType,
19};
20use crate::{DebugMacroOffset, constants};
21
22/// All of the commonly used DWARF sections.
23///
24/// This is useful for storing sections when `T` does not implement `Reader`.
25/// It can be used to create a `Dwarf` that references the data in `self`.
26/// If `T` does implement `Reader`, then use `Dwarf` directly.
27///
28/// ## Example Usage
29///
30/// It can be useful to load DWARF sections into owned data structures,
31/// such as `Vec`. However, we do not implement the `Reader` trait
32/// for `Vec`, because it would be very inefficient, but this trait
33/// is required for all of the methods that parse the DWARF data.
34/// So we first load the DWARF sections into `Vec`s, and then use
35/// `borrow` to create `Reader`s that reference the data.
36///
37/// ```rust,no_run
38/// # fn example() -> Result<(), gimli::Error> {
39/// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() };
40/// // Read the DWARF sections into `Vec`s with whatever object loader you're using.
41/// let dwarf_sections: gimli::DwarfSections<Vec<u8>> = gimli::DwarfSections::load(loader)?;
42/// // Create references to the DWARF sections.
43/// let dwarf: gimli::Dwarf<_> = dwarf_sections.borrow(|section| {
44///     gimli::EndianSlice::new(&section, gimli::LittleEndian)
45/// });
46/// # unreachable!()
47/// # }
48/// ```
49#[derive(Debug, Default)]
50pub struct DwarfSections<T> {
51    /// The `.debug_abbrev` section.
52    pub debug_abbrev: DebugAbbrev<T>,
53    /// The `.debug_addr` section.
54    pub debug_addr: DebugAddr<T>,
55    /// The `.debug_aranges` section.
56    pub debug_aranges: DebugAranges<T>,
57    /// The `.debug_info` section.
58    pub debug_info: DebugInfo<T>,
59    /// The `.debug_line` section.
60    pub debug_line: DebugLine<T>,
61    /// The `.debug_line_str` section.
62    pub debug_line_str: DebugLineStr<T>,
63    /// The `.debug_macinfo` section.
64    pub debug_macinfo: DebugMacinfo<T>,
65    /// The `.debug_macro` section.
66    pub debug_macro: DebugMacro<T>,
67    /// The `.debug_names` section.
68    pub debug_names: DebugNames<T>,
69    /// The `.debug_str` section.
70    pub debug_str: DebugStr<T>,
71    /// The `.debug_str_offsets` section.
72    pub debug_str_offsets: DebugStrOffsets<T>,
73    /// The `.debug_types` section.
74    pub debug_types: DebugTypes<T>,
75    /// The `.debug_loc` section.
76    pub debug_loc: DebugLoc<T>,
77    /// The `.debug_loclists` section.
78    pub debug_loclists: DebugLocLists<T>,
79    /// The `.debug_ranges` section.
80    pub debug_ranges: DebugRanges<T>,
81    /// The `.debug_rnglists` section.
82    pub debug_rnglists: DebugRngLists<T>,
83}
84
85impl<T> DwarfSections<T> {
86    /// Try to load the DWARF sections using the given loader function.
87    ///
88    /// `section` loads a DWARF section from the object file.
89    /// It should return an empty section if the section does not exist.
90    pub fn load<F, E>(mut section: F) -> core::result::Result<Self, E>
91    where
92        F: FnMut(SectionId) -> core::result::Result<T, E>,
93    {
94        Ok(DwarfSections {
95            // Section types are inferred.
96            debug_abbrev: Section::load(&mut section)?,
97            debug_addr: Section::load(&mut section)?,
98            debug_aranges: Section::load(&mut section)?,
99            debug_info: Section::load(&mut section)?,
100            debug_line: Section::load(&mut section)?,
101            debug_line_str: Section::load(&mut section)?,
102            debug_macinfo: Section::load(&mut section)?,
103            debug_macro: Section::load(&mut section)?,
104            debug_names: Section::load(&mut section)?,
105            debug_str: Section::load(&mut section)?,
106            debug_str_offsets: Section::load(&mut section)?,
107            debug_types: Section::load(&mut section)?,
108            debug_loc: Section::load(&mut section)?,
109            debug_loclists: Section::load(&mut section)?,
110            debug_ranges: Section::load(&mut section)?,
111            debug_rnglists: Section::load(&mut section)?,
112        })
113    }
114
115    /// Create a `Dwarf` structure that references the data in `self`.
116    pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> Dwarf<R>
117    where
118        F: FnMut(&'a T) -> R,
119    {
120        Dwarf::from_sections(DwarfSections {
121            debug_abbrev: self.debug_abbrev.borrow(&mut borrow),
122            debug_addr: self.debug_addr.borrow(&mut borrow),
123            debug_aranges: self.debug_aranges.borrow(&mut borrow),
124            debug_info: self.debug_info.borrow(&mut borrow),
125            debug_line: self.debug_line.borrow(&mut borrow),
126            debug_line_str: self.debug_line_str.borrow(&mut borrow),
127            debug_macinfo: self.debug_macinfo.borrow(&mut borrow),
128            debug_macro: self.debug_macro.borrow(&mut borrow),
129            debug_names: self.debug_names.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_types: self.debug_types.borrow(&mut borrow),
133            debug_loc: self.debug_loc.borrow(&mut borrow),
134            debug_loclists: self.debug_loclists.borrow(&mut borrow),
135            debug_ranges: self.debug_ranges.borrow(&mut borrow),
136            debug_rnglists: self.debug_rnglists.borrow(&mut borrow),
137        })
138    }
139
140    /// Create a `Dwarf` structure that references the data in `self` and `sup`.
141    ///
142    /// This is like `borrow`, but also includes the supplementary object file.
143    /// This is useful when `R` implements `Reader` but `T` does not.
144    ///
145    /// ## Example Usage
146    ///
147    /// ```rust,no_run
148    /// # fn example() -> Result<(), gimli::Error> {
149    /// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() };
150    /// # let sup_loader = |name| -> Result<_, gimli::Error> { unimplemented!() };
151    /// // Read the DWARF sections into `Vec`s with whatever object loader you're using.
152    /// let dwarf_sections: gimli::DwarfSections<Vec<u8>> = gimli::DwarfSections::load(loader)?;
153    /// let dwarf_sup_sections: gimli::DwarfSections<Vec<u8>> = gimli::DwarfSections::load(sup_loader)?;
154    /// // Create references to the DWARF sections.
155    /// let dwarf = dwarf_sections.borrow_with_sup(Some(&dwarf_sup_sections), |section| {
156    ///     gimli::EndianSlice::new(&section, gimli::LittleEndian)
157    /// });
158    /// # unreachable!()
159    /// # }
160    /// ```
161    pub fn borrow_with_sup<'a, F, R>(&'a self, sup: Option<&'a Self>, mut borrow: F) -> Dwarf<R>
162    where
163        F: FnMut(&'a T) -> R,
164    {
165        let mut dwarf = self.borrow(&mut borrow);
166        if let Some(sup) = sup {
167            dwarf.set_sup(sup.borrow(&mut borrow));
168        }
169        dwarf
170    }
171}
172
173/// All of the commonly used DWARF sections, and other common information.
174#[derive(Debug, Default)]
175pub struct Dwarf<R> {
176    /// The `.debug_abbrev` section.
177    pub debug_abbrev: DebugAbbrev<R>,
178
179    /// The `.debug_addr` section.
180    pub debug_addr: DebugAddr<R>,
181
182    /// The `.debug_aranges` section.
183    pub debug_aranges: DebugAranges<R>,
184
185    /// The `.debug_info` section.
186    pub debug_info: DebugInfo<R>,
187
188    /// The `.debug_line` section.
189    pub debug_line: DebugLine<R>,
190
191    /// The `.debug_line_str` section.
192    pub debug_line_str: DebugLineStr<R>,
193
194    /// The `.debug_macinfo` section.
195    pub debug_macinfo: DebugMacinfo<R>,
196
197    /// The `.debug_macro` section.
198    pub debug_macro: DebugMacro<R>,
199
200    /// The `.debug_names` section.
201    pub debug_names: DebugNames<R>,
202
203    /// The `.debug_str` section.
204    pub debug_str: DebugStr<R>,
205
206    /// The `.debug_str_offsets` section.
207    pub debug_str_offsets: DebugStrOffsets<R>,
208
209    /// The `.debug_types` section.
210    pub debug_types: DebugTypes<R>,
211
212    /// The location lists in the `.debug_loc` and `.debug_loclists` sections.
213    pub locations: LocationLists<R>,
214
215    /// The range lists in the `.debug_ranges` and `.debug_rnglists` sections.
216    pub ranges: RangeLists<R>,
217
218    /// The type of this file.
219    pub file_type: DwarfFileType,
220
221    /// The DWARF sections for a supplementary object file.
222    pub sup: Option<Arc<Dwarf<R>>>,
223
224    /// A cache of previously parsed abbreviations for units in this file.
225    pub abbreviations_cache: AbbreviationsCache,
226}
227
228impl<T> Dwarf<T> {
229    /// Try to load the DWARF sections using the given loader function.
230    ///
231    /// `section` loads a DWARF section from the object file.
232    /// It should return an empty section if the section does not exist.
233    ///
234    /// After loading, the user should set the `file_type` field and
235    /// call `load_sup` if required.
236    pub fn load<F, E>(section: F) -> core::result::Result<Self, E>
237    where
238        F: FnMut(SectionId) -> core::result::Result<T, E>,
239    {
240        let sections = DwarfSections::load(section)?;
241        Ok(Self::from_sections(sections))
242    }
243
244    /// Load the DWARF sections from the supplementary object file.
245    ///
246    /// `section` operates the same as for `load`.
247    ///
248    /// Sets `self.sup`, replacing any previous value.
249    pub fn load_sup<F, E>(&mut self, section: F) -> core::result::Result<(), E>
250    where
251        F: FnMut(SectionId) -> core::result::Result<T, E>,
252    {
253        self.set_sup(Self::load(section)?);
254        Ok(())
255    }
256
257    /// Create a `Dwarf` structure from the given sections.
258    ///
259    /// The caller should set the `file_type` and `sup` fields if required.
260    fn from_sections(sections: DwarfSections<T>) -> Self {
261        Dwarf {
262            debug_abbrev: sections.debug_abbrev,
263            debug_addr: sections.debug_addr,
264            debug_aranges: sections.debug_aranges,
265            debug_info: sections.debug_info,
266            debug_line: sections.debug_line,
267            debug_line_str: sections.debug_line_str,
268            debug_macinfo: sections.debug_macinfo,
269            debug_macro: sections.debug_macro,
270            debug_names: sections.debug_names,
271            debug_str: sections.debug_str,
272            debug_str_offsets: sections.debug_str_offsets,
273            debug_types: sections.debug_types,
274            locations: LocationLists::new(sections.debug_loc, sections.debug_loclists),
275            ranges: RangeLists::new(sections.debug_ranges, sections.debug_rnglists),
276            file_type: DwarfFileType::Main,
277            sup: None,
278            abbreviations_cache: AbbreviationsCache::new(),
279        }
280    }
281
282    /// Create a `Dwarf` structure that references the data in `self`.
283    ///
284    /// This is useful when `R` implements `Reader` but `T` does not.
285    ///
286    /// ## Example Usage
287    ///
288    /// It can be useful to load DWARF sections into owned data structures,
289    /// such as `Vec`. However, we do not implement the `Reader` trait
290    /// for `Vec`, because it would be very inefficient, but this trait
291    /// is required for all of the methods that parse the DWARF data.
292    /// So we first load the DWARF sections into `Vec`s, and then use
293    /// `borrow` to create `Reader`s that reference the data.
294    ///
295    /// ```rust,no_run
296    /// # fn example() -> Result<(), gimli::Error> {
297    /// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() };
298    /// # let sup_loader = |name| -> Result<_, gimli::Error> { unimplemented!() };
299    /// // Read the DWARF sections into `Vec`s with whatever object loader you're using.
300    /// let mut owned_dwarf: gimli::Dwarf<Vec<u8>> = gimli::Dwarf::load(loader)?;
301    /// owned_dwarf.load_sup(sup_loader)?;
302    /// // Create references to the DWARF sections.
303    /// let dwarf = owned_dwarf.borrow(|section| {
304    ///     gimli::EndianSlice::new(&section, gimli::LittleEndian)
305    /// });
306    /// # unreachable!()
307    /// # }
308    /// ```
309    #[deprecated(note = "use `DwarfSections::borrow` instead")]
310    pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> Dwarf<R>
311    where
312        F: FnMut(&'a T) -> R,
313    {
314        Dwarf {
315            debug_abbrev: self.debug_abbrev.borrow(&mut borrow),
316            debug_addr: self.debug_addr.borrow(&mut borrow),
317            debug_aranges: self.debug_aranges.borrow(&mut borrow),
318            debug_info: self.debug_info.borrow(&mut borrow),
319            debug_line: self.debug_line.borrow(&mut borrow),
320            debug_line_str: self.debug_line_str.borrow(&mut borrow),
321            debug_macinfo: self.debug_macinfo.borrow(&mut borrow),
322            debug_macro: self.debug_macro.borrow(&mut borrow),
323            debug_names: self.debug_names.borrow(&mut borrow),
324            debug_str: self.debug_str.borrow(&mut borrow),
325            debug_str_offsets: self.debug_str_offsets.borrow(&mut borrow),
326            debug_types: self.debug_types.borrow(&mut borrow),
327            locations: self.locations.borrow(&mut borrow),
328            ranges: self.ranges.borrow(&mut borrow),
329            file_type: self.file_type,
330            sup: self.sup().map(|sup| Arc::new(sup.borrow(borrow))),
331            abbreviations_cache: AbbreviationsCache::new(),
332        }
333    }
334
335    /// Store the DWARF sections for the supplementary object file.
336    pub fn set_sup(&mut self, sup: Dwarf<T>) {
337        self.sup = Some(Arc::new(sup));
338    }
339
340    /// Return a reference to the DWARF sections for the supplementary object file.
341    pub fn sup(&self) -> Option<&Dwarf<T>> {
342        self.sup.as_ref().map(Arc::as_ref)
343    }
344}
345
346impl<R: Reader> Dwarf<R> {
347    /// Parse abbreviations and store them in the cache.
348    ///
349    /// This will iterate over the units in `self.debug_info` to determine the
350    /// abbreviations offsets.
351    ///
352    /// Errors during parsing abbreviations are also stored in the cache.
353    /// Errors during iterating over the units are ignored.
354    pub fn populate_abbreviations_cache(&mut self, strategy: AbbreviationsCacheStrategy) {
355        self.abbreviations_cache
356            .populate(strategy, &self.debug_abbrev, self.debug_info.units());
357    }
358
359    /// Iterate the unit headers in the `.debug_info` section.
360    #[inline]
361    pub fn units(&self) -> DebugInfoUnitHeadersIter<R> {
362        self.debug_info.units()
363    }
364
365    /// Parse the unit header at the given offset in the `.debug_info` section.
366    #[inline]
367    pub fn unit_header(&self, offset: DebugInfoOffset<R::Offset>) -> Result<UnitHeader<R>> {
368        self.debug_info.header_from_offset(offset)
369    }
370
371    /// Construct a new `Unit` from the given unit header.
372    #[inline]
373    pub fn unit(&self, header: UnitHeader<R>) -> Result<Unit<R>> {
374        Unit::new(self, header)
375    }
376
377    /// Iterate the type-unit headers in the `.debug_types` section.
378    #[inline]
379    pub fn type_units(&self) -> DebugTypesUnitHeadersIter<R> {
380        self.debug_types.units()
381    }
382
383    /// Parse the abbreviations for a compilation unit.
384    #[inline]
385    pub fn abbreviations(&self, unit: &UnitHeader<R>) -> Result<Arc<Abbreviations>> {
386        self.abbreviations_cache
387            .get(&self.debug_abbrev, unit.debug_abbrev_offset())
388    }
389
390    /// Return the string offset at the given index.
391    #[inline]
392    pub fn string_offset(
393        &self,
394        unit: &Unit<R>,
395        index: DebugStrOffsetsIndex<R::Offset>,
396    ) -> Result<DebugStrOffset<R::Offset>> {
397        self.debug_str_offsets
398            .get_str_offset(unit.header.format(), unit.str_offsets_base, index)
399    }
400
401    /// Return the string at the given offset in `.debug_str`.
402    #[inline]
403    pub fn string(&self, offset: DebugStrOffset<R::Offset>) -> Result<R> {
404        self.debug_str.get_str(offset)
405    }
406
407    /// Return the string at the given offset in `.debug_line_str`.
408    #[inline]
409    pub fn line_string(&self, offset: DebugLineStrOffset<R::Offset>) -> Result<R> {
410        self.debug_line_str.get_str(offset)
411    }
412
413    /// Return the string at the given offset in the `.debug_str`
414    /// in the supplementary object file.
415    #[inline]
416    pub fn sup_string(&self, offset: DebugStrOffset<R::Offset>) -> Result<R> {
417        if let Some(sup) = self.sup() {
418            sup.debug_str.get_str(offset)
419        } else {
420            Err(Error::ExpectedStringAttributeValue)
421        }
422    }
423
424    /// Return an attribute value as a string slice.
425    ///
426    /// If the attribute value is one of:
427    ///
428    /// - an inline `DW_FORM_string` string
429    /// - a `DW_FORM_strp` reference to an offset into the `.debug_str` section
430    /// - a `DW_FORM_strp_sup` reference to an offset into a supplementary
431    ///   object file
432    /// - a `DW_FORM_line_strp` reference to an offset into the `.debug_line_str`
433    ///   section
434    /// - a `DW_FORM_strx` index into the `.debug_str_offsets` entries for the unit
435    ///
436    /// then return the attribute's string value. Returns an error if the attribute
437    /// value does not have a string form, or if a string form has an invalid value.
438    pub fn attr_string(&self, unit: &Unit<R>, attr: AttributeValue<R>) -> Result<R> {
439        match attr {
440            AttributeValue::String(string) => Ok(string),
441            AttributeValue::DebugStrRef(offset) => self.string(offset),
442            AttributeValue::DebugStrRefSup(offset) => self.sup_string(offset),
443            AttributeValue::DebugLineStrRef(offset) => self.line_string(offset),
444            AttributeValue::DebugStrOffsetsIndex(index) => {
445                let offset = self.string_offset(unit, index)?;
446                self.string(offset)
447            }
448            _ => Err(Error::ExpectedStringAttributeValue),
449        }
450    }
451
452    /// Return an attribute value as a string slice.
453    ///
454    /// This only handles forms that are usable without an associated unit.
455    ///
456    /// If the attribute value is one of:
457    ///
458    /// - an inline `DW_FORM_string` string
459    /// - a `DW_FORM_strp` reference to an offset into the `.debug_str` section
460    /// - a `DW_FORM_strp_sup` reference to an offset into a supplementary
461    ///   object file
462    /// - a `DW_FORM_line_strp` reference to an offset into the `.debug_line_str`
463    ///   section
464    ///
465    /// then return the attribute's string value. Returns an error if the attribute
466    /// value does not have a string form, or if a string form has an invalid value.
467    pub fn attr_line_string(&self, attr: AttributeValue<R>) -> Result<R> {
468        match attr {
469            AttributeValue::String(string) => Ok(string),
470            AttributeValue::DebugStrRef(offset) => self.string(offset),
471            AttributeValue::DebugStrRefSup(offset) => self.sup_string(offset),
472            AttributeValue::DebugLineStrRef(offset) => self.line_string(offset),
473            _ => Err(Error::ExpectedStringAttributeValue),
474        }
475    }
476
477    /// Return the address at the given index.
478    pub fn address(&self, unit: &Unit<R>, index: DebugAddrIndex<R::Offset>) -> Result<u64> {
479        self.debug_addr
480            .get_address(unit.encoding().address_size, unit.addr_base, index)
481    }
482
483    /// Try to return an attribute value as an address.
484    ///
485    /// If the attribute value is one of:
486    ///
487    /// - a `DW_FORM_addr`
488    /// - a `DW_FORM_addrx` index into the `.debug_addr` entries for the unit
489    ///
490    /// then return the address.
491    /// Returns `None` for other forms.
492    pub fn attr_address(&self, unit: &Unit<R>, attr: AttributeValue<R>) -> Result<Option<u64>> {
493        match attr {
494            AttributeValue::Addr(addr) => Ok(Some(addr)),
495            AttributeValue::DebugAddrIndex(index) => self.address(unit, index).map(Some),
496            _ => Ok(None),
497        }
498    }
499
500    /// Return the range list offset for the given raw offset.
501    ///
502    /// This handles adding `DW_AT_GNU_ranges_base` if required.
503    pub fn ranges_offset_from_raw(
504        &self,
505        unit: &Unit<R>,
506        offset: RawRangeListsOffset<R::Offset>,
507    ) -> RangeListsOffset<R::Offset> {
508        if self.file_type == DwarfFileType::Dwo && unit.header.version() < 5 {
509            RangeListsOffset(offset.0.wrapping_add(unit.rnglists_base.0))
510        } else {
511            RangeListsOffset(offset.0)
512        }
513    }
514
515    /// Return the range list offset at the given index.
516    pub fn ranges_offset(
517        &self,
518        unit: &Unit<R>,
519        index: DebugRngListsIndex<R::Offset>,
520    ) -> Result<RangeListsOffset<R::Offset>> {
521        self.ranges
522            .get_offset(unit.encoding(), unit.rnglists_base, index)
523    }
524
525    /// Iterate over the `RangeListEntry`s starting at the given offset.
526    pub fn ranges(
527        &self,
528        unit: &Unit<R>,
529        offset: RangeListsOffset<R::Offset>,
530    ) -> Result<RngListIter<R>> {
531        self.ranges.ranges(
532            offset,
533            unit.encoding(),
534            unit.low_pc,
535            &self.debug_addr,
536            unit.addr_base,
537        )
538    }
539
540    /// Iterate over the `RawRngListEntry`ies starting at the given offset.
541    pub fn raw_ranges(
542        &self,
543        unit: &Unit<R>,
544        offset: RangeListsOffset<R::Offset>,
545    ) -> Result<RawRngListIter<R>> {
546        self.ranges.raw_ranges(offset, unit.encoding())
547    }
548
549    /// Try to return an attribute value as a range list offset.
550    ///
551    /// If the attribute value is one of:
552    ///
553    /// - a `DW_FORM_sec_offset` reference to the `.debug_ranges` or `.debug_rnglists` sections
554    /// - a `DW_FORM_rnglistx` index into the `.debug_rnglists` entries for the unit
555    ///
556    /// then return the range list offset of the range list.
557    /// Returns `None` for other forms.
558    pub fn attr_ranges_offset(
559        &self,
560        unit: &Unit<R>,
561        attr: AttributeValue<R>,
562    ) -> Result<Option<RangeListsOffset<R::Offset>>> {
563        match attr {
564            AttributeValue::RangeListsRef(offset) => {
565                Ok(Some(self.ranges_offset_from_raw(unit, offset)))
566            }
567            AttributeValue::DebugRngListsIndex(index) => self.ranges_offset(unit, index).map(Some),
568            _ => Ok(None),
569        }
570    }
571
572    /// Try to return an attribute value as a range list entry iterator.
573    ///
574    /// If the attribute value is one of:
575    ///
576    /// - a `DW_FORM_sec_offset` reference to the `.debug_ranges` or `.debug_rnglists` sections
577    /// - a `DW_FORM_rnglistx` index into the `.debug_rnglists` entries for the unit
578    ///
579    /// then return an iterator over the entries in the range list.
580    /// Returns `None` for other forms.
581    pub fn attr_ranges(
582        &self,
583        unit: &Unit<R>,
584        attr: AttributeValue<R>,
585    ) -> Result<Option<RngListIter<R>>> {
586        match self.attr_ranges_offset(unit, attr)? {
587            Some(offset) => Ok(Some(self.ranges(unit, offset)?)),
588            None => Ok(None),
589        }
590    }
591
592    /// Return an iterator for the address ranges of a `DebuggingInformationEntry`.
593    ///
594    /// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges`.
595    pub fn die_ranges(
596        &self,
597        unit: &Unit<R>,
598        entry: &DebuggingInformationEntry<R>,
599    ) -> Result<RangeIter<R>> {
600        let mut low_pc = None;
601        let mut high_pc = None;
602        let mut size = None;
603        for attr in entry.attrs() {
604            match attr.name() {
605                constants::DW_AT_low_pc => {
606                    low_pc = Some(
607                        self.attr_address(unit, attr.value())?
608                            .ok_or(Error::UnsupportedAttributeForm(attr.form()))?,
609                    );
610                }
611                constants::DW_AT_high_pc => match attr.value() {
612                    AttributeValue::Udata(val) => size = Some(val),
613                    value => {
614                        high_pc = Some(
615                            self.attr_address(unit, value)?
616                                .ok_or(Error::UnsupportedAttributeForm(attr.form()))?,
617                        );
618                    }
619                },
620                constants::DW_AT_ranges => {
621                    if let Some(list) = self.attr_ranges(unit, attr.value())? {
622                        return Ok(RangeIter(RangeIterInner::List(list)));
623                    }
624                }
625                _ => {}
626            }
627        }
628        let range = low_pc.and_then(|begin| {
629            let end = size.map(|size| begin + size).or(high_pc);
630            // TODO: perhaps return an error if `end` is `None`
631            end.map(|end| Range { begin, end })
632        });
633        Ok(RangeIter(RangeIterInner::Single(range)))
634    }
635
636    /// Return an iterator for the address ranges of a `Unit`.
637    ///
638    /// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges` of the
639    /// root `DebuggingInformationEntry`.
640    pub fn unit_ranges(&self, unit: &Unit<R>) -> Result<RangeIter<R>> {
641        let mut cursor = unit.header.entries(&unit.abbreviations);
642        cursor.next_dfs()?;
643        let root = cursor.current().ok_or(Error::MissingUnitDie)?;
644        self.die_ranges(unit, root)
645    }
646
647    /// Return the location list offset at the given index.
648    pub fn locations_offset(
649        &self,
650        unit: &Unit<R>,
651        index: DebugLocListsIndex<R::Offset>,
652    ) -> Result<LocationListsOffset<R::Offset>> {
653        self.locations
654            .get_offset(unit.encoding(), unit.loclists_base, index)
655    }
656
657    /// Iterate over the `LocationListEntry`s starting at the given offset.
658    pub fn locations(
659        &self,
660        unit: &Unit<R>,
661        offset: LocationListsOffset<R::Offset>,
662    ) -> Result<LocListIter<R>> {
663        match self.file_type {
664            DwarfFileType::Main => self.locations.locations(
665                offset,
666                unit.encoding(),
667                unit.low_pc,
668                &self.debug_addr,
669                unit.addr_base,
670            ),
671            DwarfFileType::Dwo => self.locations.locations_dwo(
672                offset,
673                unit.encoding(),
674                unit.low_pc,
675                &self.debug_addr,
676                unit.addr_base,
677            ),
678        }
679    }
680
681    /// Iterate over the raw `LocationListEntry`s starting at the given offset.
682    pub fn raw_locations(
683        &self,
684        unit: &Unit<R>,
685        offset: LocationListsOffset<R::Offset>,
686    ) -> Result<RawLocListIter<R>> {
687        match self.file_type {
688            DwarfFileType::Main => self.locations.raw_locations(offset, unit.encoding()),
689            DwarfFileType::Dwo => self.locations.raw_locations_dwo(offset, unit.encoding()),
690        }
691    }
692
693    /// Try to return an attribute value as a location list offset.
694    ///
695    /// If the attribute value is one of:
696    ///
697    /// - a `DW_FORM_sec_offset` reference to the `.debug_loc` or `.debug_loclists` sections
698    /// - a `DW_FORM_loclistx` index into the `.debug_loclists` entries for the unit
699    ///
700    /// then return the location list offset of the location list.
701    /// Returns `None` for other forms.
702    pub fn attr_locations_offset(
703        &self,
704        unit: &Unit<R>,
705        attr: AttributeValue<R>,
706    ) -> Result<Option<LocationListsOffset<R::Offset>>> {
707        match attr {
708            AttributeValue::LocationListsRef(offset) => Ok(Some(offset)),
709            AttributeValue::DebugLocListsIndex(index) => {
710                self.locations_offset(unit, index).map(Some)
711            }
712            _ => Ok(None),
713        }
714    }
715
716    /// Try to return an attribute value as a location list entry iterator.
717    ///
718    /// If the attribute value is one of:
719    ///
720    /// - a `DW_FORM_sec_offset` reference to the `.debug_loc` or `.debug_loclists` sections
721    /// - a `DW_FORM_loclistx` index into the `.debug_loclists` entries for the unit
722    ///
723    /// then return an iterator over the entries in the location list.
724    /// Returns `None` for other forms.
725    pub fn attr_locations(
726        &self,
727        unit: &Unit<R>,
728        attr: AttributeValue<R>,
729    ) -> Result<Option<LocListIter<R>>> {
730        match self.attr_locations_offset(unit, attr)? {
731            Some(offset) => Ok(Some(self.locations(unit, offset)?)),
732            None => Ok(None),
733        }
734    }
735
736    /// Call `Reader::lookup_offset_id` for each section, and return the first match.
737    ///
738    /// The first element of the tuple is `true` for supplementary sections.
739    pub fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(bool, SectionId, R::Offset)> {
740        None.or_else(|| self.debug_abbrev.lookup_offset_id(id))
741            .or_else(|| self.debug_addr.lookup_offset_id(id))
742            .or_else(|| self.debug_aranges.lookup_offset_id(id))
743            .or_else(|| self.debug_info.lookup_offset_id(id))
744            .or_else(|| self.debug_line.lookup_offset_id(id))
745            .or_else(|| self.debug_line_str.lookup_offset_id(id))
746            .or_else(|| self.debug_str.lookup_offset_id(id))
747            .or_else(|| self.debug_str_offsets.lookup_offset_id(id))
748            .or_else(|| self.debug_types.lookup_offset_id(id))
749            .or_else(|| self.locations.lookup_offset_id(id))
750            .or_else(|| self.ranges.lookup_offset_id(id))
751            .map(|(id, offset)| (false, id, offset))
752            .or_else(|| {
753                self.sup()
754                    .and_then(|sup| sup.lookup_offset_id(id))
755                    .map(|(_, id, offset)| (true, id, offset))
756            })
757    }
758
759    /// Returns a string representation of the given error.
760    ///
761    /// This uses information from the DWARF sections to provide more information in some cases.
762    pub fn format_error(&self, err: Error) -> String {
763        #[allow(clippy::single_match)]
764        match err {
765            Error::UnexpectedEof(id) => match self.lookup_offset_id(id) {
766                Some((sup, section, offset)) => {
767                    return format!(
768                        "{} at {}{}+0x{:x}",
769                        err,
770                        section.name(),
771                        if sup { "(sup)" } else { "" },
772                        offset.into_u64(),
773                    );
774                }
775                None => {}
776            },
777            _ => {}
778        }
779        format!("{}", err)
780    }
781
782    /// Return a fallible iterator over the macro information from `.debug_macinfo` for the given offset.
783    pub fn macinfo(&self, offset: DebugMacinfoOffset<R::Offset>) -> Result<MacroIter<R>> {
784        self.debug_macinfo.get_macinfo(offset)
785    }
786
787    /// Return a fallible iterator over the macro information from `.debug_macro` for the given offset.
788    pub fn macros(&self, offset: DebugMacroOffset<R::Offset>) -> Result<MacroIter<R>> {
789        self.debug_macro.get_macros(offset)
790    }
791}
792
793impl<R: Clone> Dwarf<R> {
794    /// Assuming `self` was loaded from a .dwo, take the appropriate
795    /// sections from `parent` (which contains the skeleton unit for this
796    /// dwo) such as `.debug_addr` and merge them into this `Dwarf`.
797    pub fn make_dwo(&mut self, parent: &Dwarf<R>) {
798        self.file_type = DwarfFileType::Dwo;
799        // These sections are always taken from the parent file and not the dwo.
800        self.debug_addr = parent.debug_addr.clone();
801        // .debug_rnglists comes from the DWO, .debug_ranges comes from the
802        // parent file.
803        self.ranges
804            .set_debug_ranges(parent.ranges.debug_ranges().clone());
805        self.sup.clone_from(&parent.sup);
806    }
807}
808
809/// The sections from a `.dwp` file.
810///
811/// This is useful for storing sections when `T` does not implement `Reader`.
812/// It can be used to create a `DwarfPackage` that references the data in `self`.
813/// If `T` does implement `Reader`, then use `DwarfPackage` directly.
814///
815/// ## Example Usage
816///
817/// It can be useful to load DWARF sections into owned data structures,
818/// such as `Vec`. However, we do not implement the `Reader` trait
819/// for `Vec`, because it would be very inefficient, but this trait
820/// is required for all of the methods that parse the DWARF data.
821/// So we first load the DWARF sections into `Vec`s, and then use
822/// `borrow` to create `Reader`s that reference the data.
823///
824/// ```rust,no_run
825/// # fn example() -> Result<(), gimli::Error> {
826/// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() };
827/// // Read the DWARF sections into `Vec`s with whatever object loader you're using.
828/// let dwp_sections: gimli::DwarfPackageSections<Vec<u8>> = gimli::DwarfPackageSections::load(loader)?;
829/// // Create references to the DWARF sections.
830/// let dwp: gimli::DwarfPackage<_> = dwp_sections.borrow(
831///     |section| gimli::EndianSlice::new(&section, gimli::LittleEndian),
832///     gimli::EndianSlice::new(&[], gimli::LittleEndian),
833/// )?;
834/// # unreachable!()
835/// # }
836/// ```
837#[derive(Debug, Default)]
838pub struct DwarfPackageSections<T> {
839    /// The `.debug_cu_index` section.
840    pub cu_index: DebugCuIndex<T>,
841    /// The `.debug_tu_index` section.
842    pub tu_index: DebugTuIndex<T>,
843    /// The `.debug_abbrev.dwo` section.
844    pub debug_abbrev: DebugAbbrev<T>,
845    /// The `.debug_info.dwo` section.
846    pub debug_info: DebugInfo<T>,
847    /// The `.debug_line.dwo` section.
848    pub debug_line: DebugLine<T>,
849    /// The `.debug_macinfo.dwo` section.
850    ///
851    /// Only present when using GNU split-dwarf extension to DWARF 4.
852    pub debug_macinfo: DebugMacinfo<T>,
853    /// The `.debug_macro.dwo` section.
854    pub debug_macro: DebugMacro<T>,
855    /// The `.debug_str.dwo` section.
856    pub debug_str: DebugStr<T>,
857    /// The `.debug_str_offsets.dwo` section.
858    pub debug_str_offsets: DebugStrOffsets<T>,
859    /// The `.debug_loc.dwo` section.
860    ///
861    /// Only present when using GNU split-dwarf extension to DWARF 4.
862    pub debug_loc: DebugLoc<T>,
863    /// The `.debug_loclists.dwo` section.
864    pub debug_loclists: DebugLocLists<T>,
865    /// The `.debug_rnglists.dwo` section.
866    pub debug_rnglists: DebugRngLists<T>,
867    /// The `.debug_types.dwo` section.
868    ///
869    /// Only present when using GNU split-dwarf extension to DWARF 4.
870    pub debug_types: DebugTypes<T>,
871}
872
873impl<T> DwarfPackageSections<T> {
874    /// Try to load the `.dwp` sections using the given loader function.
875    ///
876    /// `section` loads a DWARF section from the object file.
877    /// It should return an empty section if the section does not exist.
878    pub fn load<F, E>(mut section: F) -> core::result::Result<Self, E>
879    where
880        F: FnMut(SectionId) -> core::result::Result<T, E>,
881        E: From<Error>,
882    {
883        Ok(DwarfPackageSections {
884            // Section types are inferred.
885            cu_index: Section::load(&mut section)?,
886            tu_index: Section::load(&mut section)?,
887            debug_abbrev: Section::load(&mut section)?,
888            debug_info: Section::load(&mut section)?,
889            debug_line: Section::load(&mut section)?,
890            debug_macinfo: Section::load(&mut section)?,
891            debug_macro: Section::load(&mut section)?,
892            debug_str: Section::load(&mut section)?,
893            debug_str_offsets: Section::load(&mut section)?,
894            debug_loc: Section::load(&mut section)?,
895            debug_loclists: Section::load(&mut section)?,
896            debug_rnglists: Section::load(&mut section)?,
897            debug_types: Section::load(&mut section)?,
898        })
899    }
900
901    /// Create a `DwarfPackage` structure that references the data in `self`.
902    pub fn borrow<'a, F, R>(&'a self, mut borrow: F, empty: R) -> Result<DwarfPackage<R>>
903    where
904        F: FnMut(&'a T) -> R,
905        R: Reader,
906    {
907        DwarfPackage::from_sections(
908            DwarfPackageSections {
909                cu_index: self.cu_index.borrow(&mut borrow),
910                tu_index: self.tu_index.borrow(&mut borrow),
911                debug_abbrev: self.debug_abbrev.borrow(&mut borrow),
912                debug_info: self.debug_info.borrow(&mut borrow),
913                debug_line: self.debug_line.borrow(&mut borrow),
914                debug_macinfo: self.debug_macinfo.borrow(&mut borrow),
915                debug_macro: self.debug_macro.borrow(&mut borrow),
916                debug_str: self.debug_str.borrow(&mut borrow),
917                debug_str_offsets: self.debug_str_offsets.borrow(&mut borrow),
918                debug_loc: self.debug_loc.borrow(&mut borrow),
919                debug_loclists: self.debug_loclists.borrow(&mut borrow),
920                debug_rnglists: self.debug_rnglists.borrow(&mut borrow),
921                debug_types: self.debug_types.borrow(&mut borrow),
922            },
923            empty,
924        )
925    }
926}
927
928/// The sections from a `.dwp` file, with parsed indices.
929#[derive(Debug)]
930pub struct DwarfPackage<R: Reader> {
931    /// The compilation unit index in the `.debug_cu_index` section.
932    pub cu_index: UnitIndex<R>,
933
934    /// The type unit index in the `.debug_tu_index` section.
935    pub tu_index: UnitIndex<R>,
936
937    /// The `.debug_abbrev.dwo` section.
938    pub debug_abbrev: DebugAbbrev<R>,
939
940    /// The `.debug_info.dwo` section.
941    pub debug_info: DebugInfo<R>,
942
943    /// The `.debug_line.dwo` section.
944    pub debug_line: DebugLine<R>,
945
946    /// The `.debug_macinfo.dwo` section.
947    pub debug_macinfo: DebugMacinfo<R>,
948
949    /// The `.debug_macro.dwo` section.
950    pub debug_macro: DebugMacro<R>,
951
952    /// The `.debug_str.dwo` section.
953    pub debug_str: DebugStr<R>,
954
955    /// The `.debug_str_offsets.dwo` section.
956    pub debug_str_offsets: DebugStrOffsets<R>,
957
958    /// The `.debug_loc.dwo` section.
959    ///
960    /// Only present when using GNU split-dwarf extension to DWARF 4.
961    pub debug_loc: DebugLoc<R>,
962
963    /// The `.debug_loclists.dwo` section.
964    pub debug_loclists: DebugLocLists<R>,
965
966    /// The `.debug_rnglists.dwo` section.
967    pub debug_rnglists: DebugRngLists<R>,
968
969    /// The `.debug_types.dwo` section.
970    ///
971    /// Only present when using GNU split-dwarf extension to DWARF 4.
972    pub debug_types: DebugTypes<R>,
973
974    /// An empty section.
975    ///
976    /// Used when creating `Dwarf<R>`.
977    pub empty: R,
978}
979
980impl<R: Reader> DwarfPackage<R> {
981    /// Try to load the `.dwp` sections using the given loader function.
982    ///
983    /// `section` loads a DWARF section from the object file.
984    /// It should return an empty section if the section does not exist.
985    pub fn load<F, E>(section: F, empty: R) -> core::result::Result<Self, E>
986    where
987        F: FnMut(SectionId) -> core::result::Result<R, E>,
988        E: From<Error>,
989    {
990        let sections = DwarfPackageSections::load(section)?;
991        Ok(Self::from_sections(sections, empty)?)
992    }
993
994    /// Create a `DwarfPackage` structure from the given sections.
995    fn from_sections(sections: DwarfPackageSections<R>, empty: R) -> Result<Self> {
996        Ok(DwarfPackage {
997            cu_index: sections.cu_index.index()?,
998            tu_index: sections.tu_index.index()?,
999            debug_abbrev: sections.debug_abbrev,
1000            debug_info: sections.debug_info,
1001            debug_line: sections.debug_line,
1002            debug_macinfo: sections.debug_macinfo,
1003            debug_macro: sections.debug_macro,
1004            debug_str: sections.debug_str,
1005            debug_str_offsets: sections.debug_str_offsets,
1006            debug_loc: sections.debug_loc,
1007            debug_loclists: sections.debug_loclists,
1008            debug_rnglists: sections.debug_rnglists,
1009            debug_types: sections.debug_types,
1010            empty,
1011        })
1012    }
1013
1014    /// Find the compilation unit with the given DWO identifier and return its section
1015    /// contributions.
1016    ///
1017    /// ## Example Usage
1018    ///
1019    /// ```rust,no_run
1020    /// # fn example<R: gimli::Reader>(
1021    /// #        dwarf: &gimli::Dwarf<R>,
1022    /// #        dwp: &gimli::DwarfPackage<R>,
1023    /// #        dwo_id: gimli::DwoId,
1024    /// # ) -> Result<(), gimli::Error> {
1025    /// if let Some(dwo) = dwp.find_cu(dwo_id, dwarf)? {
1026    ///    let dwo_header = dwo.units().next()?.expect("DWO should have one unit");
1027    ///    let dwo_unit = dwo.unit(dwo_header)?;
1028    ///    // Do something with `dwo_unit`.
1029    /// }
1030    /// # unreachable!()
1031    /// # }
1032    pub fn find_cu(&self, id: DwoId, parent: &Dwarf<R>) -> Result<Option<Dwarf<R>>> {
1033        let row = match self.cu_index.find(id.0) {
1034            Some(row) => row,
1035            None => return Ok(None),
1036        };
1037        self.cu_sections(row, parent).map(Some)
1038    }
1039
1040    /// Find the type unit with the given type signature and return its section
1041    /// contributions.
1042    pub fn find_tu(
1043        &self,
1044        signature: DebugTypeSignature,
1045        parent: &Dwarf<R>,
1046    ) -> Result<Option<Dwarf<R>>> {
1047        let row = match self.tu_index.find(signature.0) {
1048            Some(row) => row,
1049            None => return Ok(None),
1050        };
1051        self.tu_sections(row, parent).map(Some)
1052    }
1053
1054    /// Return the section contributions of the compilation unit at the given index.
1055    ///
1056    /// The index must be in the range `1..cu_index.unit_count`.
1057    ///
1058    /// This function should only be needed by low level parsers.
1059    pub fn cu_sections(&self, index: u32, parent: &Dwarf<R>) -> Result<Dwarf<R>> {
1060        self.sections(self.cu_index.sections(index)?, parent)
1061    }
1062
1063    /// Return the section contributions of the compilation unit at the given index.
1064    ///
1065    /// The index must be in the range `1..tu_index.unit_count`.
1066    ///
1067    /// This function should only be needed by low level parsers.
1068    pub fn tu_sections(&self, index: u32, parent: &Dwarf<R>) -> Result<Dwarf<R>> {
1069        self.sections(self.tu_index.sections(index)?, parent)
1070    }
1071
1072    /// Return the section contributions of a unit.
1073    ///
1074    /// This function should only be needed by low level parsers.
1075    pub fn sections(
1076        &self,
1077        sections: UnitIndexSectionIterator<'_, R>,
1078        parent: &Dwarf<R>,
1079    ) -> Result<Dwarf<R>> {
1080        let mut abbrev_offset = 0;
1081        let mut abbrev_size = 0;
1082        let mut info_offset = 0;
1083        let mut info_size = 0;
1084        let mut line_offset = 0;
1085        let mut line_size = 0;
1086        let mut loc_offset = 0;
1087        let mut loc_size = 0;
1088        let mut loclists_offset = 0;
1089        let mut loclists_size = 0;
1090        let mut macinfo_offset = 0;
1091        let mut macinfo_size = 0;
1092        let mut macro_offset = 0;
1093        let mut macro_size = 0;
1094        let mut str_offsets_offset = 0;
1095        let mut str_offsets_size = 0;
1096        let mut rnglists_offset = 0;
1097        let mut rnglists_size = 0;
1098        let mut types_offset = 0;
1099        let mut types_size = 0;
1100        for section in sections {
1101            match section.section {
1102                IndexSectionId::DebugAbbrev => {
1103                    abbrev_offset = section.offset;
1104                    abbrev_size = section.size;
1105                }
1106                IndexSectionId::DebugInfo => {
1107                    info_offset = section.offset;
1108                    info_size = section.size;
1109                }
1110                IndexSectionId::DebugLine => {
1111                    line_offset = section.offset;
1112                    line_size = section.size;
1113                }
1114                IndexSectionId::DebugLoc => {
1115                    loc_offset = section.offset;
1116                    loc_size = section.size;
1117                }
1118                IndexSectionId::DebugLocLists => {
1119                    loclists_offset = section.offset;
1120                    loclists_size = section.size;
1121                }
1122                IndexSectionId::DebugMacinfo => {
1123                    macinfo_offset = section.offset;
1124                    macinfo_size = section.size;
1125                }
1126                IndexSectionId::DebugMacro => {
1127                    macro_offset = section.offset;
1128                    macro_size = section.size;
1129                }
1130                IndexSectionId::DebugStrOffsets => {
1131                    str_offsets_offset = section.offset;
1132                    str_offsets_size = section.size;
1133                }
1134                IndexSectionId::DebugRngLists => {
1135                    rnglists_offset = section.offset;
1136                    rnglists_size = section.size;
1137                }
1138                IndexSectionId::DebugTypes => {
1139                    types_offset = section.offset;
1140                    types_size = section.size;
1141                }
1142            }
1143        }
1144
1145        let debug_abbrev = self.debug_abbrev.dwp_range(abbrev_offset, abbrev_size)?;
1146        let debug_info = self.debug_info.dwp_range(info_offset, info_size)?;
1147        let debug_line = self.debug_line.dwp_range(line_offset, line_size)?;
1148        let debug_loc = self.debug_loc.dwp_range(loc_offset, loc_size)?;
1149        let debug_loclists = self
1150            .debug_loclists
1151            .dwp_range(loclists_offset, loclists_size)?;
1152        let debug_macinfo = self.debug_macinfo.dwp_range(macinfo_offset, macinfo_size)?;
1153        let debug_macro = self.debug_macro.dwp_range(macro_offset, macro_size)?;
1154        let debug_str_offsets = self
1155            .debug_str_offsets
1156            .dwp_range(str_offsets_offset, str_offsets_size)?;
1157        let debug_rnglists = self
1158            .debug_rnglists
1159            .dwp_range(rnglists_offset, rnglists_size)?;
1160        let debug_types = self.debug_types.dwp_range(types_offset, types_size)?;
1161
1162        let debug_str = self.debug_str.clone();
1163
1164        let debug_addr = parent.debug_addr.clone();
1165        let debug_ranges = parent.ranges.debug_ranges().clone();
1166
1167        let debug_aranges = self.empty.clone().into();
1168        let debug_line_str = self.empty.clone().into();
1169        let debug_names = self.empty.clone().into();
1170
1171        Ok(Dwarf {
1172            debug_abbrev,
1173            debug_addr,
1174            debug_aranges,
1175            debug_info,
1176            debug_line,
1177            debug_line_str,
1178            debug_macinfo,
1179            debug_macro,
1180            debug_names,
1181            debug_str,
1182            debug_str_offsets,
1183            debug_types,
1184            locations: LocationLists::new(debug_loc, debug_loclists),
1185            ranges: RangeLists::new(debug_ranges, debug_rnglists),
1186            file_type: DwarfFileType::Dwo,
1187            sup: parent.sup.clone(),
1188            abbreviations_cache: AbbreviationsCache::new(),
1189        })
1190    }
1191}
1192
1193/// All of the commonly used information for a unit in the `.debug_info` or `.debug_types`
1194/// sections.
1195#[derive(Debug)]
1196pub struct Unit<R, Offset = <R as Reader>::Offset>
1197where
1198    R: Reader<Offset = Offset>,
1199    Offset: ReaderOffset,
1200{
1201    /// The header of the unit.
1202    pub header: UnitHeader<R, Offset>,
1203
1204    /// The parsed abbreviations for the unit.
1205    pub abbreviations: Arc<Abbreviations>,
1206
1207    /// The `DW_AT_name` attribute of the unit.
1208    pub name: Option<R>,
1209
1210    /// The `DW_AT_comp_dir` attribute of the unit.
1211    pub comp_dir: Option<R>,
1212
1213    /// The `DW_AT_low_pc` attribute of the unit. Defaults to 0.
1214    pub low_pc: u64,
1215
1216    /// The `DW_AT_str_offsets_base` attribute of the unit. Defaults to 0.
1217    pub str_offsets_base: DebugStrOffsetsBase<Offset>,
1218
1219    /// The `DW_AT_addr_base` attribute of the unit. Defaults to 0.
1220    pub addr_base: DebugAddrBase<Offset>,
1221
1222    /// The `DW_AT_loclists_base` attribute of the unit. Defaults to 0.
1223    pub loclists_base: DebugLocListsBase<Offset>,
1224
1225    /// The `DW_AT_rnglists_base` attribute of the unit. Defaults to 0.
1226    pub rnglists_base: DebugRngListsBase<Offset>,
1227
1228    /// The line number program of the unit.
1229    pub line_program: Option<IncompleteLineProgram<R, Offset>>,
1230
1231    /// The DWO ID of a skeleton unit or split compilation unit.
1232    pub dwo_id: Option<DwoId>,
1233}
1234
1235impl<R: Reader> core::ops::Deref for Unit<R> {
1236    type Target = UnitHeader<R>;
1237
1238    fn deref(&self) -> &Self::Target {
1239        &self.header
1240    }
1241}
1242
1243impl<R: Reader> Unit<R> {
1244    /// Construct a new `Unit` from the given unit header.
1245    #[inline]
1246    pub fn new(dwarf: &Dwarf<R>, header: UnitHeader<R>) -> Result<Self> {
1247        let abbreviations = dwarf.abbreviations(&header)?;
1248        Self::new_with_abbreviations(dwarf, header, abbreviations)
1249    }
1250
1251    /// Construct a new `Unit` from the given unit header and abbreviations.
1252    ///
1253    /// The abbreviations for this call can be obtained using `dwarf.abbreviations(&header)`.
1254    /// The caller may implement caching to reuse the `Abbreviations` across units with the
1255    /// same `header.debug_abbrev_offset()` value.
1256    #[inline]
1257    pub fn new_with_abbreviations(
1258        dwarf: &Dwarf<R>,
1259        header: UnitHeader<R>,
1260        abbreviations: Arc<Abbreviations>,
1261    ) -> Result<Self> {
1262        let mut unit = Unit {
1263            abbreviations,
1264            name: None,
1265            comp_dir: None,
1266            low_pc: 0,
1267            str_offsets_base: DebugStrOffsetsBase::default_for_encoding_and_file(
1268                header.encoding(),
1269                dwarf.file_type,
1270            ),
1271            // NB: Because the .debug_addr section never lives in a .dwo, we can assume its base is always 0 or provided.
1272            addr_base: DebugAddrBase(R::Offset::from_u8(0)),
1273            loclists_base: DebugLocListsBase::default_for_encoding_and_file(
1274                header.encoding(),
1275                dwarf.file_type,
1276            ),
1277            rnglists_base: DebugRngListsBase::default_for_encoding_and_file(
1278                header.encoding(),
1279                dwarf.file_type,
1280            ),
1281            line_program: None,
1282            dwo_id: match header.type_() {
1283                UnitType::Skeleton(dwo_id) | UnitType::SplitCompilation(dwo_id) => Some(dwo_id),
1284                _ => None,
1285            },
1286            header,
1287        };
1288        let mut name = None;
1289        let mut comp_dir = None;
1290        let mut line_program_offset = None;
1291        let mut low_pc_attr = None;
1292
1293        {
1294            let mut cursor = unit.header.entries(&unit.abbreviations);
1295            cursor.next_dfs()?;
1296            let root = cursor.current().ok_or(Error::MissingUnitDie)?;
1297            for attr in root.attrs() {
1298                match attr.name() {
1299                    constants::DW_AT_name => {
1300                        name = Some(attr.value());
1301                    }
1302                    constants::DW_AT_comp_dir => {
1303                        comp_dir = Some(attr.value());
1304                    }
1305                    constants::DW_AT_low_pc => {
1306                        low_pc_attr = Some(attr.value());
1307                    }
1308                    constants::DW_AT_stmt_list => {
1309                        if let AttributeValue::DebugLineRef(offset) = attr.value() {
1310                            line_program_offset = Some(offset);
1311                        }
1312                    }
1313                    constants::DW_AT_str_offsets_base => {
1314                        if let AttributeValue::DebugStrOffsetsBase(base) = attr.value() {
1315                            unit.str_offsets_base = base;
1316                        }
1317                    }
1318                    constants::DW_AT_addr_base | constants::DW_AT_GNU_addr_base => {
1319                        if let AttributeValue::DebugAddrBase(base) = attr.value() {
1320                            unit.addr_base = base;
1321                        }
1322                    }
1323                    constants::DW_AT_loclists_base => {
1324                        if let AttributeValue::DebugLocListsBase(base) = attr.value() {
1325                            unit.loclists_base = base;
1326                        }
1327                    }
1328                    constants::DW_AT_rnglists_base | constants::DW_AT_GNU_ranges_base => {
1329                        if let AttributeValue::DebugRngListsBase(base) = attr.value() {
1330                            unit.rnglists_base = base;
1331                        }
1332                    }
1333                    constants::DW_AT_GNU_dwo_id => {
1334                        if unit.dwo_id.is_none()
1335                            && let AttributeValue::DwoId(dwo_id) = attr.value()
1336                        {
1337                            unit.dwo_id = Some(dwo_id);
1338                        }
1339                    }
1340                    _ => {}
1341                }
1342            }
1343        }
1344
1345        unit.name = match name {
1346            Some(val) => dwarf.attr_string(&unit, val).ok(),
1347            None => None,
1348        };
1349        unit.comp_dir = match comp_dir {
1350            Some(val) => dwarf.attr_string(&unit, val).ok(),
1351            None => None,
1352        };
1353        unit.line_program = match line_program_offset {
1354            Some(offset) => Some(dwarf.debug_line.program(
1355                offset,
1356                unit.header.address_size(),
1357                unit.comp_dir.clone(),
1358                unit.name.clone(),
1359            )?),
1360            None => None,
1361        };
1362        if let Some(low_pc_attr) = low_pc_attr
1363            && let Some(addr) = dwarf.attr_address(&unit, low_pc_attr)?
1364        {
1365            unit.low_pc = addr;
1366        }
1367        Ok(unit)
1368    }
1369
1370    /// Return a reference to this unit and its associated `Dwarf`.
1371    pub fn unit_ref<'a>(&'a self, dwarf: &'a Dwarf<R>) -> UnitRef<'a, R> {
1372        UnitRef::new(dwarf, self)
1373    }
1374
1375    /// Return the encoding parameters for this unit.
1376    #[inline]
1377    pub fn encoding(&self) -> Encoding {
1378        self.header.encoding()
1379    }
1380
1381    /// Read the `DebuggingInformationEntry` at the given offset.
1382    pub fn entry(&self, offset: UnitOffset<R::Offset>) -> Result<DebuggingInformationEntry<R>> {
1383        self.header.entry(&self.abbreviations, offset)
1384    }
1385
1386    /// Navigate this unit's `DebuggingInformationEntry`s.
1387    #[inline]
1388    pub fn entries(&self) -> EntriesCursor<'_, R> {
1389        self.header.entries(&self.abbreviations)
1390    }
1391
1392    /// Navigate this unit's `DebuggingInformationEntry`s
1393    /// starting at the given offset.
1394    #[inline]
1395    pub fn entries_at_offset(&self, offset: UnitOffset<R::Offset>) -> Result<EntriesCursor<'_, R>> {
1396        self.header.entries_at_offset(&self.abbreviations, offset)
1397    }
1398
1399    /// Navigate this unit's `DebuggingInformationEntry`s as a tree
1400    /// starting at the given offset.
1401    #[inline]
1402    pub fn entries_tree(
1403        &self,
1404        offset: Option<UnitOffset<R::Offset>>,
1405    ) -> Result<EntriesTree<'_, R>> {
1406        self.header.entries_tree(&self.abbreviations, offset)
1407    }
1408
1409    /// Read the raw data that defines the Debugging Information Entries.
1410    #[inline]
1411    pub fn entries_raw(&self, offset: Option<UnitOffset<R::Offset>>) -> Result<EntriesRaw<'_, R>> {
1412        self.header.entries_raw(&self.abbreviations, offset)
1413    }
1414
1415    /// Copy attributes that are subject to relocation from another unit. This is intended
1416    /// to be used to copy attributes from a skeleton compilation unit to the corresponding
1417    /// split compilation unit.
1418    pub fn copy_relocated_attributes(&mut self, other: &Unit<R>) {
1419        self.low_pc = other.low_pc;
1420        self.addr_base = other.addr_base;
1421        if self.header.version() < 5 {
1422            self.rnglists_base = other.rnglists_base;
1423        }
1424    }
1425
1426    /// Find the dwo name (if any) for this unit, automatically handling the differences
1427    /// between the standardized DWARF 5 split DWARF format and the pre-DWARF 5 GNU
1428    /// extension.
1429    ///
1430    /// The returned value is relative to this unit's `comp_dir`.
1431    pub fn dwo_name(&self) -> Result<Option<AttributeValue<R>>> {
1432        let mut entries = self.entries();
1433        entries.next_entry()?;
1434        let entry = entries.current().ok_or(Error::MissingUnitDie)?;
1435        if self.header.version() < 5 {
1436            Ok(entry.attr_value(constants::DW_AT_GNU_dwo_name))
1437        } else {
1438            Ok(entry.attr_value(constants::DW_AT_dwo_name))
1439        }
1440    }
1441}
1442
1443/// A reference to a `Unit` and its associated `Dwarf`.
1444///
1445/// These often need to be passed around together, so this struct makes that easier.
1446///
1447/// It implements `Deref` to `&'a Unit`, so you can use it as if it were a `Unit`.
1448/// It also implements methods that correspond to methods on `Dwarf` that take a `Unit`.
1449#[derive(Debug)]
1450pub struct UnitRef<'a, R: Reader> {
1451    /// The `Dwarf` that contains the unit.
1452    pub dwarf: &'a Dwarf<R>,
1453
1454    /// The `Unit` being referenced.
1455    pub unit: &'a Unit<R>,
1456}
1457
1458impl<'a, R: Reader> Clone for UnitRef<'a, R> {
1459    fn clone(&self) -> Self {
1460        *self
1461    }
1462}
1463
1464impl<'a, R: Reader> Copy for UnitRef<'a, R> {}
1465
1466impl<'a, R: Reader> core::ops::Deref for UnitRef<'a, R> {
1467    type Target = &'a Unit<R>;
1468
1469    fn deref(&self) -> &Self::Target {
1470        &self.unit
1471    }
1472}
1473
1474impl<'a, R: Reader> UnitRef<'a, R> {
1475    /// Construct a new `UnitRef` from a `Dwarf` and a `Unit`.
1476    pub fn new(dwarf: &'a Dwarf<R>, unit: &'a Unit<R>) -> Self {
1477        UnitRef { dwarf, unit }
1478    }
1479
1480    /// Return the string offset at the given index.
1481    #[inline]
1482    pub fn string_offset(
1483        &self,
1484        index: DebugStrOffsetsIndex<R::Offset>,
1485    ) -> Result<DebugStrOffset<R::Offset>> {
1486        self.dwarf.string_offset(self.unit, index)
1487    }
1488
1489    /// Return the string at the given offset in `.debug_str`.
1490    #[inline]
1491    pub fn string(&self, offset: DebugStrOffset<R::Offset>) -> Result<R> {
1492        self.dwarf.string(offset)
1493    }
1494
1495    /// Return the string at the given offset in `.debug_line_str`.
1496    #[inline]
1497    pub fn line_string(&self, offset: DebugLineStrOffset<R::Offset>) -> Result<R> {
1498        self.dwarf.line_string(offset)
1499    }
1500
1501    /// Return the string at the given offset in the `.debug_str`
1502    /// in the supplementary object file.
1503    #[inline]
1504    pub fn sup_string(&self, offset: DebugStrOffset<R::Offset>) -> Result<R> {
1505        self.dwarf.sup_string(offset)
1506    }
1507
1508    /// Return an attribute value as a string slice.
1509    ///
1510    /// See [`Dwarf::attr_string`] for more information.
1511    pub fn attr_string(&self, attr: AttributeValue<R>) -> Result<R> {
1512        self.dwarf.attr_string(self.unit, attr)
1513    }
1514
1515    /// Return the address at the given index.
1516    pub fn address(&self, index: DebugAddrIndex<R::Offset>) -> Result<u64> {
1517        self.dwarf.address(self.unit, index)
1518    }
1519
1520    /// Try to return an attribute value as an address.
1521    ///
1522    /// See [`Dwarf::attr_address`] for more information.
1523    pub fn attr_address(&self, attr: AttributeValue<R>) -> Result<Option<u64>> {
1524        self.dwarf.attr_address(self.unit, attr)
1525    }
1526
1527    /// Return the range list offset for the given raw offset.
1528    ///
1529    /// This handles adding `DW_AT_GNU_ranges_base` if required.
1530    pub fn ranges_offset_from_raw(
1531        &self,
1532        offset: RawRangeListsOffset<R::Offset>,
1533    ) -> RangeListsOffset<R::Offset> {
1534        self.dwarf.ranges_offset_from_raw(self.unit, offset)
1535    }
1536
1537    /// Return the range list offset at the given index.
1538    pub fn ranges_offset(
1539        &self,
1540        index: DebugRngListsIndex<R::Offset>,
1541    ) -> Result<RangeListsOffset<R::Offset>> {
1542        self.dwarf.ranges_offset(self.unit, index)
1543    }
1544
1545    /// Iterate over the `RangeListEntry`s starting at the given offset.
1546    pub fn ranges(&self, offset: RangeListsOffset<R::Offset>) -> Result<RngListIter<R>> {
1547        self.dwarf.ranges(self.unit, offset)
1548    }
1549
1550    /// Iterate over the `RawRngListEntry`ies starting at the given offset.
1551    pub fn raw_ranges(&self, offset: RangeListsOffset<R::Offset>) -> Result<RawRngListIter<R>> {
1552        self.dwarf.raw_ranges(self.unit, offset)
1553    }
1554
1555    /// Try to return an attribute value as a range list offset.
1556    ///
1557    /// See [`Dwarf::attr_ranges_offset`] for more information.
1558    pub fn attr_ranges_offset(
1559        &self,
1560        attr: AttributeValue<R>,
1561    ) -> Result<Option<RangeListsOffset<R::Offset>>> {
1562        self.dwarf.attr_ranges_offset(self.unit, attr)
1563    }
1564
1565    /// Try to return an attribute value as a range list entry iterator.
1566    ///
1567    /// See [`Dwarf::attr_ranges`] for more information.
1568    pub fn attr_ranges(&self, attr: AttributeValue<R>) -> Result<Option<RngListIter<R>>> {
1569        self.dwarf.attr_ranges(self.unit, attr)
1570    }
1571
1572    /// Return an iterator for the address ranges of a `DebuggingInformationEntry`.
1573    ///
1574    /// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges`.
1575    pub fn die_ranges(&self, entry: &DebuggingInformationEntry<R>) -> Result<RangeIter<R>> {
1576        self.dwarf.die_ranges(self.unit, entry)
1577    }
1578
1579    /// Return an iterator for the address ranges of the `Unit`.
1580    ///
1581    /// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges` of the
1582    /// root `DebuggingInformationEntry`.
1583    pub fn unit_ranges(&self) -> Result<RangeIter<R>> {
1584        self.dwarf.unit_ranges(self.unit)
1585    }
1586
1587    /// Return the location list offset at the given index.
1588    pub fn locations_offset(
1589        &self,
1590        index: DebugLocListsIndex<R::Offset>,
1591    ) -> Result<LocationListsOffset<R::Offset>> {
1592        self.dwarf.locations_offset(self.unit, index)
1593    }
1594
1595    /// Iterate over the `LocationListEntry`s starting at the given offset.
1596    pub fn locations(&self, offset: LocationListsOffset<R::Offset>) -> Result<LocListIter<R>> {
1597        self.dwarf.locations(self.unit, offset)
1598    }
1599
1600    /// Iterate over the raw `LocationListEntry`s starting at the given offset.
1601    pub fn raw_locations(
1602        &self,
1603        offset: LocationListsOffset<R::Offset>,
1604    ) -> Result<RawLocListIter<R>> {
1605        self.dwarf.raw_locations(self.unit, offset)
1606    }
1607
1608    /// Try to return an attribute value as a location list offset.
1609    ///
1610    /// See [`Dwarf::attr_locations_offset`] for more information.
1611    pub fn attr_locations_offset(
1612        &self,
1613        attr: AttributeValue<R>,
1614    ) -> Result<Option<LocationListsOffset<R::Offset>>> {
1615        self.dwarf.attr_locations_offset(self.unit, attr)
1616    }
1617
1618    /// Try to return an attribute value as a location list entry iterator.
1619    ///
1620    /// See [`Dwarf::attr_locations`] for more information.
1621    pub fn attr_locations(&self, attr: AttributeValue<R>) -> Result<Option<LocListIter<R>>> {
1622        self.dwarf.attr_locations(self.unit, attr)
1623    }
1624
1625    /// Try to return an iterator for the list of macros at the given `.debug_macinfo` offset.
1626    pub fn macinfo(&self, offset: DebugMacinfoOffset<R::Offset>) -> Result<MacroIter<R>> {
1627        self.dwarf.macinfo(offset)
1628    }
1629
1630    /// Try to return an iterator for the list of macros at the given `.debug_macro` offset.
1631    pub fn macros(&self, offset: DebugMacroOffset<R::Offset>) -> Result<MacroIter<R>> {
1632        self.dwarf.macros(offset)
1633    }
1634}
1635
1636/// An iterator for the address ranges of a `DebuggingInformationEntry`.
1637///
1638/// Returned by `Dwarf::die_ranges` and `Dwarf::unit_ranges`.
1639#[derive(Debug)]
1640pub struct RangeIter<R: Reader>(RangeIterInner<R>);
1641
1642#[derive(Debug)]
1643enum RangeIterInner<R: Reader> {
1644    Single(Option<Range>),
1645    List(RngListIter<R>),
1646}
1647
1648impl<R: Reader> Default for RangeIter<R> {
1649    fn default() -> Self {
1650        RangeIter(RangeIterInner::Single(None))
1651    }
1652}
1653
1654impl<R: Reader> RangeIter<R> {
1655    /// Advance the iterator to the next range.
1656    pub fn next(&mut self) -> Result<Option<Range>> {
1657        match self.0 {
1658            RangeIterInner::Single(ref mut range) => Ok(range.take()),
1659            RangeIterInner::List(ref mut list) => list.next(),
1660        }
1661    }
1662}
1663
1664#[cfg(feature = "fallible-iterator")]
1665impl<R: Reader> fallible_iterator::FallibleIterator for RangeIter<R> {
1666    type Item = Range;
1667    type Error = Error;
1668
1669    #[inline]
1670    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
1671        RangeIter::next(self)
1672    }
1673}
1674
1675impl<R: Reader> Iterator for RangeIter<R> {
1676    type Item = Result<Range>;
1677
1678    #[inline]
1679    fn next(&mut self) -> Option<Self::Item> {
1680        RangeIter::next(self).transpose()
1681    }
1682}
1683
1684#[cfg(test)]
1685mod tests {
1686    use super::*;
1687    use crate::read::EndianSlice;
1688    use crate::{Endianity, LittleEndian};
1689
1690    /// Ensure that `Dwarf<R>` is covariant wrt R.
1691    #[test]
1692    fn test_dwarf_variance() {
1693        /// This only needs to compile.
1694        fn _f<'a: 'b, 'b, E: Endianity>(x: Dwarf<EndianSlice<'a, E>>) -> Dwarf<EndianSlice<'b, E>> {
1695            x
1696        }
1697    }
1698
1699    /// Ensure that `Unit<R>` is covariant wrt R.
1700    #[test]
1701    fn test_dwarf_unit_variance() {
1702        /// This only needs to compile.
1703        fn _f<'a: 'b, 'b, E: Endianity>(x: Unit<EndianSlice<'a, E>>) -> Unit<EndianSlice<'b, E>> {
1704            x
1705        }
1706    }
1707
1708    #[test]
1709    fn test_send() {
1710        fn assert_is_send<T: Send>() {}
1711        assert_is_send::<Dwarf<EndianSlice<'_, LittleEndian>>>();
1712        assert_is_send::<Unit<EndianSlice<'_, LittleEndian>>>();
1713    }
1714
1715    #[test]
1716    fn test_format_error() {
1717        let dwarf_sections = DwarfSections::load(|_| -> Result<_> { Ok(vec![1, 2]) }).unwrap();
1718        let sup_sections = DwarfSections::load(|_| -> Result<_> { Ok(vec![1, 2]) }).unwrap();
1719        let dwarf = dwarf_sections.borrow_with_sup(Some(&sup_sections), |section| {
1720            EndianSlice::new(section, LittleEndian)
1721        });
1722
1723        match dwarf.debug_str.get_str(DebugStrOffset(1)) {
1724            Ok(r) => panic!("Unexpected str {:?}", r),
1725            Err(e) => {
1726                assert_eq!(
1727                    dwarf.format_error(e),
1728                    "unexpected end of input at .debug_str+0x1"
1729                );
1730            }
1731        }
1732        match dwarf.sup().unwrap().debug_str.get_str(DebugStrOffset(1)) {
1733            Ok(r) => panic!("Unexpected str {:?}", r),
1734            Err(e) => {
1735                assert_eq!(
1736                    dwarf.format_error(e),
1737                    "unexpected end of input at .debug_str(sup)+0x1"
1738                );
1739            }
1740        }
1741        assert_eq!(dwarf.format_error(Error::Io), format!("{}", Error::Io));
1742    }
1743}