From e6e90c9a26021bda4bffe22f0df69a412942763f Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Mon, 4 Mar 2024 13:39:19 +1000 Subject: [PATCH] read: add DwarfPackageSections::borrow Also replace Dwarf::borrow with DwarfSections::borrow for consistency. --- crates/examples/src/bin/simple.rs | 3 +- crates/examples/src/bin/simple_line.rs | 2 +- src/read/abbrev.rs | 12 +- src/read/addr.rs | 12 +- src/read/aranges.rs | 12 +- src/read/dwarf.rs | 358 +++++++++++++++++++++---- src/read/index.rs | 28 ++ src/read/line.rs | 12 +- src/read/loclists.rs | 40 ++- src/read/mod.rs | 4 + src/read/rnglists.rs | 40 ++- src/read/str.rs | 36 +-- src/read/unit.rs | 24 +- 13 files changed, 409 insertions(+), 174 deletions(-) diff --git a/crates/examples/src/bin/simple.rs b/crates/examples/src/bin/simple.rs index 8f3beffb..cd88d2cc 100644 --- a/crates/examples/src/bin/simple.rs +++ b/crates/examples/src/bin/simple.rs @@ -29,7 +29,7 @@ fn dump_file(object: &object::File, endian: gimli::RunTimeEndian) -> Result<(), }; // Load all of the sections. - let dwarf_cow = gimli::Dwarf::load(&load_section)?; + let dwarf_cow = gimli::DwarfSections::load(&load_section)?; // Borrow a `Cow<[u8]>` to create an `EndianSlice`. let borrow_section: &dyn for<'a> Fn( @@ -38,6 +38,7 @@ fn dump_file(object: &object::File, endian: gimli::RunTimeEndian) -> Result<(), &|section| gimli::EndianSlice::new(section, endian); // Create `EndianSlice`s for all of the sections. + // Alternatively, we could have used `Dwarf::load` with an owned type such as `EndianRcSlice`. let dwarf = dwarf_cow.borrow(&borrow_section); // Iterate over the compilation units. diff --git a/crates/examples/src/bin/simple_line.rs b/crates/examples/src/bin/simple_line.rs index 5312f9cf..ec4ca964 100644 --- a/crates/examples/src/bin/simple_line.rs +++ b/crates/examples/src/bin/simple_line.rs @@ -29,7 +29,7 @@ fn dump_file(object: &object::File, endian: gimli::RunTimeEndian) -> Result<(), }; // Load all of the sections. - let dwarf_cow = gimli::Dwarf::load(&load_section)?; + let dwarf_cow = gimli::DwarfSections::load(&load_section)?; // Borrow a `Cow<[u8]>` to create an `EndianSlice`. let borrow_section: &dyn for<'a> Fn( diff --git a/src/read/abbrev.rs b/src/read/abbrev.rs index 9477323e..b9931b2e 100644 --- a/src/read/abbrev.rs +++ b/src/read/abbrev.rs @@ -66,17 +66,7 @@ impl DebugAbbrev { /// /// This is useful when `R` implements `Reader` but `T` does not. /// - /// ## Example Usage - /// - /// ```rust,no_run - /// # let load_section = || unimplemented!(); - /// // Read the DWARF section into a `Vec` with whatever object loader you're using. - /// let owned_section: gimli::DebugAbbrev> = load_section(); - /// // Create a reference to the DWARF section. - /// let section = owned_section.borrow(|section| { - /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) - /// }); - /// ``` + /// Used by `DwarfSections::borrow`. pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAbbrev where F: FnMut(&'a T) -> R, diff --git a/src/read/addr.rs b/src/read/addr.rs index 4ac304cb..fc2fbabd 100644 --- a/src/read/addr.rs +++ b/src/read/addr.rs @@ -45,17 +45,7 @@ impl DebugAddr { /// /// This is useful when `R` implements `Reader` but `T` does not. /// - /// ## Example Usage - /// - /// ```rust,no_run - /// # let load_section = || unimplemented!(); - /// // Read the DWARF section into a `Vec` with whatever object loader you're using. - /// let owned_section: gimli::DebugAddr> = load_section(); - /// // Create a reference to the DWARF section. - /// let section = owned_section.borrow(|section| { - /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) - /// }); - /// ``` + /// Used by `DwarfSections::borrow`. pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAddr where F: FnMut(&'a T) -> R, diff --git a/src/read/aranges.rs b/src/read/aranges.rs index cffd5021..12bcec7e 100644 --- a/src/read/aranges.rs +++ b/src/read/aranges.rs @@ -59,17 +59,7 @@ impl DebugAranges { /// /// This is useful when `R` implements `Reader` but `T` does not. /// - /// ## Example Usage - /// - /// ```rust,no_run - /// # let load_section = || unimplemented!(); - /// // Read the DWARF section into a `Vec` with whatever object loader you're using. - /// let owned_section: gimli::DebugAranges> = load_section(); - /// // Create a reference to the DWARF section. - /// let section = owned_section.borrow(|section| { - /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) - /// }); - /// ``` + /// Used by `DwarfSections::borrow`. pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAranges where F: FnMut(&'a T) -> R, diff --git a/src/read/dwarf.rs b/src/read/dwarf.rs index b0d1a77e..b87eaaf4 100644 --- a/src/read/dwarf.rs +++ b/src/read/dwarf.rs @@ -11,13 +11,150 @@ use crate::constants; use crate::read::{ Abbreviations, AbbreviationsCache, AbbreviationsCacheStrategy, AttributeValue, DebugAbbrev, DebugAddr, DebugAranges, DebugCuIndex, DebugInfo, DebugInfoUnitHeadersIter, DebugLine, - DebugLineStr, DebugLoc, DebugLocLists, DebugRngLists, DebugStr, DebugStrOffsets, DebugTuIndex, - DebugTypes, DebugTypesUnitHeadersIter, DebuggingInformationEntry, EntriesCursor, EntriesRaw, - EntriesTree, Error, IncompleteLineProgram, LocListIter, LocationLists, Range, RangeLists, - RawLocListIter, RawRngListIter, Reader, ReaderOffset, ReaderOffsetId, Result, RngListIter, - Section, UnitHeader, UnitIndex, UnitIndexSectionIterator, UnitOffset, UnitType, + DebugLineStr, DebugLoc, DebugLocLists, DebugRanges, DebugRngLists, DebugStr, DebugStrOffsets, + DebugTuIndex, DebugTypes, DebugTypesUnitHeadersIter, DebuggingInformationEntry, EntriesCursor, + EntriesRaw, EntriesTree, Error, IncompleteLineProgram, LocListIter, LocationLists, Range, + RangeLists, RawLocListIter, RawRngListIter, Reader, ReaderOffset, ReaderOffsetId, Result, + RngListIter, Section, UnitHeader, UnitIndex, UnitIndexSectionIterator, UnitOffset, UnitType, }; +/// All of the commonly used DWARF sections. +/// +/// This is useful for storing sections when `T` does not implement `Reader`. +/// It can be used to create a `Dwarf` that references the data in `self`. +/// If `T` does implement `Reader`, then use `Dwarf` directly. +/// +/// ## Example Usage +/// +/// It can be useful to load DWARF sections into owned data structures, +/// such as `Vec`. However, we do not implement the `Reader` trait +/// for `Vec`, because it would be very inefficient, but this trait +/// is required for all of the methods that parse the DWARF data. +/// So we first load the DWARF sections into `Vec`s, and then use +/// `borrow` to create `Reader`s that reference the data. +/// +/// ```rust,no_run +/// # fn example() -> Result<(), gimli::Error> { +/// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() }; +/// // Read the DWARF sections into `Vec`s with whatever object loader you're using. +/// let dwarf_sections: gimli::DwarfSections> = gimli::DwarfSections::load(loader)?; +/// // Create references to the DWARF sections. +/// let dwarf: gimli::Dwarf<_> = dwarf_sections.borrow(|section| { +/// gimli::EndianSlice::new(§ion, gimli::LittleEndian) +/// }); +/// # unreachable!() +/// # } +/// ``` +#[derive(Debug)] +pub struct DwarfSections { + /// The `.debug_abbrev` section. + pub debug_abbrev: DebugAbbrev, + /// The `.debug_addr` section. + pub debug_addr: DebugAddr, + /// The `.debug_aranges` section. + pub debug_aranges: DebugAranges, + /// The `.debug_info` section. + pub debug_info: DebugInfo, + /// The `.debug_line` section. + pub debug_line: DebugLine, + /// The `.debug_line_str` section. + pub debug_line_str: DebugLineStr, + /// The `.debug_str` section. + pub debug_str: DebugStr, + /// The `.debug_str_offsets` section. + pub debug_str_offsets: DebugStrOffsets, + /// The `.debug_types` section. + pub debug_types: DebugTypes, + /// The `.debug_loc` section. + pub debug_loc: DebugLoc, + /// The `.debug_loclists` section. + pub debug_loclists: DebugLocLists, + /// The `.debug_ranges` section. + pub debug_ranges: DebugRanges, + /// The `.debug_rnglists` section. + pub debug_rnglists: DebugRngLists, +} + +impl DwarfSections { + /// Try to load the DWARF sections using the given loader function. + /// + /// `section` loads a DWARF section from the object file. + /// It should return an empty section if the section does not exist. + pub fn load(mut section: F) -> core::result::Result + where + F: FnMut(SectionId) -> core::result::Result, + { + Ok(DwarfSections { + // Section types are inferred. + debug_abbrev: Section::load(&mut section)?, + debug_addr: Section::load(&mut section)?, + debug_aranges: Section::load(&mut section)?, + debug_info: Section::load(&mut section)?, + debug_line: Section::load(&mut section)?, + debug_line_str: Section::load(&mut section)?, + debug_str: Section::load(&mut section)?, + debug_str_offsets: Section::load(&mut section)?, + debug_types: Section::load(&mut section)?, + debug_loc: Section::load(&mut section)?, + debug_loclists: Section::load(&mut section)?, + debug_ranges: Section::load(&mut section)?, + debug_rnglists: Section::load(&mut section)?, + }) + } + + /// Create a `Dwarf` structure that references the data in `self`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> Dwarf + where + F: FnMut(&'a T) -> R, + { + Dwarf::from_sections(DwarfSections { + debug_abbrev: self.debug_abbrev.borrow(&mut borrow), + debug_addr: self.debug_addr.borrow(&mut borrow), + debug_aranges: self.debug_aranges.borrow(&mut borrow), + debug_info: self.debug_info.borrow(&mut borrow), + debug_line: self.debug_line.borrow(&mut borrow), + debug_line_str: self.debug_line_str.borrow(&mut borrow), + debug_str: self.debug_str.borrow(&mut borrow), + debug_str_offsets: self.debug_str_offsets.borrow(&mut borrow), + debug_types: self.debug_types.borrow(&mut borrow), + debug_loc: self.debug_loc.borrow(&mut borrow), + debug_loclists: self.debug_loclists.borrow(&mut borrow), + debug_ranges: self.debug_ranges.borrow(&mut borrow), + debug_rnglists: self.debug_rnglists.borrow(&mut borrow), + }) + } + + /// Create a `Dwarf` structure that references the data in `self` and `sup`. + /// + /// This is like `borrow`, but also includes the supplementary object file. + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// ## Example Usage + /// + /// ```rust,no_run + /// # fn example() -> Result<(), gimli::Error> { + /// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() }; + /// # let sup_loader = |name| -> Result<_, gimli::Error> { unimplemented!() }; + /// // Read the DWARF sections into `Vec`s with whatever object loader you're using. + /// let dwarf_sections: gimli::DwarfSections> = gimli::DwarfSections::load(loader)?; + /// let dwarf_sup_sections: gimli::DwarfSections> = gimli::DwarfSections::load(sup_loader)?; + /// // Create references to the DWARF sections. + /// let dwarf = dwarf_sections.borrow_with_sup(&dwarf_sup_sections, |section| { + /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) + /// }); + /// # unreachable!() + /// # } + /// ``` + pub fn borrow_with_sup<'a, F, R>(&'a self, sup: &'a Self, mut borrow: F) -> Dwarf + where + F: FnMut(&'a T) -> R, + { + let mut dwarf = self.borrow(&mut borrow); + dwarf.set_sup(sup.borrow(&mut borrow)); + dwarf + } +} + /// All of the commonly used DWARF sections, and other common information. #[derive(Debug, Default)] pub struct Dwarf { @@ -70,37 +207,14 @@ impl Dwarf { /// `section` loads a DWARF section from the object file. /// It should return an empty section if the section does not exist. /// - /// `section` may either directly return a `Reader` instance (such as - /// `EndianSlice`), or it may return some other type and then convert - /// that type into a `Reader` using `Dwarf::borrow`. - /// /// After loading, the user should set the `file_type` field and /// call `load_sup` if required. - pub fn load(mut section: F) -> core::result::Result + pub fn load(section: F) -> core::result::Result where F: FnMut(SectionId) -> core::result::Result, { - // Section types are inferred. - let debug_loc = Section::load(&mut section)?; - let debug_loclists = Section::load(&mut section)?; - let debug_ranges = Section::load(&mut section)?; - let debug_rnglists = Section::load(&mut section)?; - Ok(Dwarf { - debug_abbrev: Section::load(&mut section)?, - debug_addr: Section::load(&mut section)?, - debug_aranges: Section::load(&mut section)?, - debug_info: Section::load(&mut section)?, - debug_line: Section::load(&mut section)?, - debug_line_str: Section::load(&mut section)?, - debug_str: Section::load(&mut section)?, - debug_str_offsets: Section::load(&mut section)?, - debug_types: Section::load(&mut section)?, - locations: LocationLists::new(debug_loc, debug_loclists), - ranges: RangeLists::new(debug_ranges, debug_rnglists), - file_type: DwarfFileType::Main, - sup: None, - abbreviations_cache: AbbreviationsCache::new(), - }) + let sections = DwarfSections::load(section)?; + Ok(Self::from_sections(sections)) } /// Load the DWARF sections from the supplementary object file. @@ -112,10 +226,32 @@ impl Dwarf { where F: FnMut(SectionId) -> core::result::Result, { - self.sup = Some(Arc::new(Self::load(section)?)); + self.set_sup(Self::load(section)?); Ok(()) } + /// Create a `Dwarf` structure from the given sections. + /// + /// The caller should set the `file_type` and `sup` fields if required. + fn from_sections(sections: DwarfSections) -> Self { + Dwarf { + debug_abbrev: sections.debug_abbrev, + debug_addr: sections.debug_addr, + debug_aranges: sections.debug_aranges, + debug_info: sections.debug_info, + debug_line: sections.debug_line, + debug_line_str: sections.debug_line_str, + debug_str: sections.debug_str, + debug_str_offsets: sections.debug_str_offsets, + debug_types: sections.debug_types, + locations: LocationLists::new(sections.debug_loc, sections.debug_loclists), + ranges: RangeLists::new(sections.debug_ranges, sections.debug_rnglists), + file_type: DwarfFileType::Main, + sup: None, + abbreviations_cache: AbbreviationsCache::new(), + } + } + /// Create a `Dwarf` structure that references the data in `self`. /// /// This is useful when `R` implements `Reader` but `T` does not. @@ -143,6 +279,7 @@ impl Dwarf { /// # unreachable!() /// # } /// ``` + #[deprecated(note = "use `DwarfSections::borrow` instead")] pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> Dwarf where F: FnMut(&'a T) -> R, @@ -165,7 +302,12 @@ impl Dwarf { } } - /// Return a reference to the DWARF sections for supplementary object file. + /// Store the DWARF sections for the supplementary object file. + pub fn set_sup(&mut self, sup: Dwarf) { + self.sup = Some(Arc::new(sup)); + } + + /// Return a reference to the DWARF sections for the supplementary object file. pub fn sup(&self) -> Option<&Dwarf> { self.sup.as_ref().map(Arc::as_ref) } @@ -600,6 +742,115 @@ impl Dwarf { } /// The sections from a `.dwp` file. +/// +/// This is useful for storing sections when `T` does not implement `Reader`. +/// It can be used to create a `DwarfPackage` that references the data in `self`. +/// If `T` does implement `Reader`, then use `DwarfPackage` directly. +/// +/// ## Example Usage +/// +/// It can be useful to load DWARF sections into owned data structures, +/// such as `Vec`. However, we do not implement the `Reader` trait +/// for `Vec`, because it would be very inefficient, but this trait +/// is required for all of the methods that parse the DWARF data. +/// So we first load the DWARF sections into `Vec`s, and then use +/// `borrow` to create `Reader`s that reference the data. +/// +/// ```rust,no_run +/// # fn example() -> Result<(), gimli::Error> { +/// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() }; +/// // Read the DWARF sections into `Vec`s with whatever object loader you're using. +/// let dwp_sections: gimli::DwarfPackageSections> = gimli::DwarfPackageSections::load(loader)?; +/// // Create references to the DWARF sections. +/// let dwp: gimli::DwarfPackage<_> = dwp_sections.borrow( +/// |section| gimli::EndianSlice::new(§ion, gimli::LittleEndian), +/// gimli::EndianSlice::new(&[], gimli::LittleEndian), +/// )?; +/// # unreachable!() +/// # } +/// ``` +#[derive(Debug)] +pub struct DwarfPackageSections { + /// The `.debug_cu_index` section. + pub cu_index: DebugCuIndex, + /// The `.debug_tu_index` section. + pub tu_index: DebugTuIndex, + /// The `.debug_abbrev.dwo` section. + pub debug_abbrev: DebugAbbrev, + /// The `.debug_info.dwo` section. + pub debug_info: DebugInfo, + /// The `.debug_line.dwo` section. + pub debug_line: DebugLine, + /// The `.debug_str.dwo` section. + pub debug_str: DebugStr, + /// The `.debug_str_offsets.dwo` section. + pub debug_str_offsets: DebugStrOffsets, + /// The `.debug_loc.dwo` section. + /// + /// Only present when using GNU split-dwarf extension to DWARF 4. + pub debug_loc: DebugLoc, + /// The `.debug_loclists.dwo` section. + pub debug_loclists: DebugLocLists, + /// The `.debug_rnglists.dwo` section. + pub debug_rnglists: DebugRngLists, + /// The `.debug_types.dwo` section. + /// + /// Only present when using GNU split-dwarf extension to DWARF 4. + pub debug_types: DebugTypes, +} + +impl DwarfPackageSections { + /// Try to load the `.dwp` sections using the given loader function. + /// + /// `section` loads a DWARF section from the object file. + /// It should return an empty section if the section does not exist. + pub fn load(mut section: F) -> core::result::Result + where + F: FnMut(SectionId) -> core::result::Result, + E: From, + { + Ok(DwarfPackageSections { + // Section types are inferred. + cu_index: Section::load(&mut section)?, + tu_index: Section::load(&mut section)?, + debug_abbrev: Section::load(&mut section)?, + debug_info: Section::load(&mut section)?, + debug_line: Section::load(&mut section)?, + debug_str: Section::load(&mut section)?, + debug_str_offsets: Section::load(&mut section)?, + debug_loc: Section::load(&mut section)?, + debug_loclists: Section::load(&mut section)?, + debug_rnglists: Section::load(&mut section)?, + debug_types: Section::load(&mut section)?, + }) + } + + /// Create a `DwarfPackage` structure that references the data in `self`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F, empty: R) -> Result> + where + F: FnMut(&'a T) -> R, + R: Reader, + { + DwarfPackage::from_sections( + DwarfPackageSections { + cu_index: self.cu_index.borrow(&mut borrow), + tu_index: self.tu_index.borrow(&mut borrow), + debug_abbrev: self.debug_abbrev.borrow(&mut borrow), + debug_info: self.debug_info.borrow(&mut borrow), + debug_line: self.debug_line.borrow(&mut borrow), + debug_str: self.debug_str.borrow(&mut borrow), + debug_str_offsets: self.debug_str_offsets.borrow(&mut borrow), + debug_loc: self.debug_loc.borrow(&mut borrow), + debug_loclists: self.debug_loclists.borrow(&mut borrow), + debug_rnglists: self.debug_rnglists.borrow(&mut borrow), + debug_types: self.debug_types.borrow(&mut borrow), + }, + empty, + ) + } +} + +/// The sections from a `.dwp` file, with parsed indices. #[derive(Debug)] pub struct DwarfPackage { /// The compilation unit index in the `.debug_cu_index` section. @@ -650,24 +901,29 @@ impl DwarfPackage { /// /// `section` loads a DWARF section from the object file. /// It should return an empty section if the section does not exist. - pub fn load(mut section: F, empty: R) -> core::result::Result + pub fn load(section: F, empty: R) -> core::result::Result where F: FnMut(SectionId) -> core::result::Result, E: From, { + let sections = DwarfPackageSections::load(section)?; + Ok(Self::from_sections(sections, empty)?) + } + + /// Create a `DwarfPackage` structure from the given sections. + fn from_sections(sections: DwarfPackageSections, empty: R) -> Result { Ok(DwarfPackage { - cu_index: DebugCuIndex::load(&mut section)?.index()?, - tu_index: DebugTuIndex::load(&mut section)?.index()?, - // Section types are inferred. - debug_abbrev: Section::load(&mut section)?, - debug_info: Section::load(&mut section)?, - debug_line: Section::load(&mut section)?, - debug_str: Section::load(&mut section)?, - debug_str_offsets: Section::load(&mut section)?, - debug_loc: Section::load(&mut section)?, - debug_loclists: Section::load(&mut section)?, - debug_rnglists: Section::load(&mut section)?, - debug_types: Section::load(&mut section)?, + cu_index: sections.cu_index.index()?, + tu_index: sections.tu_index.index()?, + debug_abbrev: sections.debug_abbrev, + debug_info: sections.debug_info, + debug_line: sections.debug_line, + debug_str: sections.debug_str, + debug_str_offsets: sections.debug_str_offsets, + debug_loc: sections.debug_loc, + debug_loclists: sections.debug_loclists, + debug_rnglists: sections.debug_rnglists, + debug_types: sections.debug_types, empty, }) } @@ -1178,11 +1434,11 @@ mod tests { #[test] fn test_format_error() { - let mut owned_dwarf = Dwarf::load(|_| -> Result<_> { Ok(vec![1, 2]) }).unwrap(); - owned_dwarf - .load_sup(|_| -> Result<_> { Ok(vec![1, 2]) }) - .unwrap(); - let dwarf = owned_dwarf.borrow(|section| EndianSlice::new(section, LittleEndian)); + let dwarf_sections = DwarfSections::load(|_| -> Result<_> { Ok(vec![1, 2]) }).unwrap(); + let sup_sections = DwarfSections::load(|_| -> Result<_> { Ok(vec![1, 2]) }).unwrap(); + let dwarf = dwarf_sections.borrow_with_sup(&sup_sections, |section| { + EndianSlice::new(section, LittleEndian) + }); match dwarf.debug_str.get_str(DebugStrOffset(1)) { Ok(r) => panic!("Unexpected str {:?}", r), diff --git a/src/read/index.rs b/src/read/index.rs index 129eb2fb..a2098882 100644 --- a/src/read/index.rs +++ b/src/read/index.rs @@ -24,6 +24,20 @@ where } } +impl DebugCuIndex { + /// Create a `DebugCuIndex` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfPackageSections::borrow`. + pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugCuIndex + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + impl Section for DebugCuIndex { fn id() -> SectionId { SectionId::DebugCuIndex @@ -66,6 +80,20 @@ where } } +impl DebugTuIndex { + /// Create a `DebugTuIndex` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfPackageSections::borrow`. + pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugTuIndex + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + impl Section for DebugTuIndex { fn id() -> SectionId { SectionId::DebugTuIndex diff --git a/src/read/line.rs b/src/read/line.rs index 67bb6e2a..d7ad4841 100644 --- a/src/read/line.rs +++ b/src/read/line.rs @@ -86,17 +86,7 @@ impl DebugLine { /// /// This is useful when `R` implements `Reader` but `T` does not. /// - /// ## Example Usage - /// - /// ```rust,no_run - /// # let load_section = || unimplemented!(); - /// // Read the DWARF section into a `Vec` with whatever object loader you're using. - /// let owned_section: gimli::DebugLine> = load_section(); - /// // Create a reference to the DWARF section. - /// let section = owned_section.borrow(|section| { - /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) - /// }); - /// ``` + /// Used by `DwarfSections::borrow`. pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugLine where F: FnMut(&'a T) -> R, diff --git a/src/read/loclists.rs b/src/read/loclists.rs index ac3c8604..469cf71e 100644 --- a/src/read/loclists.rs +++ b/src/read/loclists.rs @@ -38,6 +38,20 @@ where } } +impl DebugLoc { + /// Create a `DebugLoc` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugLoc + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + impl Section for DebugLoc { fn id() -> SectionId { SectionId::DebugLoc @@ -84,6 +98,20 @@ where } } +impl DebugLocLists { + /// Create a `DebugLocLists` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugLocLists + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + impl Section for DebugLocLists { fn id() -> SectionId { SectionId::DebugLocLists @@ -146,17 +174,7 @@ impl LocationLists { /// /// This is useful when `R` implements `Reader` but `T` does not. /// - /// ## Example Usage - /// - /// ```rust,no_run - /// # let load_section = || unimplemented!(); - /// // Read the DWARF section into a `Vec` with whatever object loader you're using. - /// let owned_section: gimli::LocationLists> = load_section(); - /// // Create a reference to the DWARF section. - /// let section = owned_section.borrow(|section| { - /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) - /// }); - /// ``` + /// Used by `Dwarf::borrow`. pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> LocationLists where F: FnMut(&'a T) -> R, diff --git a/src/read/mod.rs b/src/read/mod.rs index 5d8f594e..61ad9615 100644 --- a/src/read/mod.rs +++ b/src/read/mod.rs @@ -67,6 +67,10 @@ //! sections. It has methods that simplify access to debugging data that spans //! multiple sections. Use of this type is optional, but recommended. //! +//! * The [`DwarfPackage`](./struct.Dwarf.html) type contains the DWARF +//! package (DWP) sections. It has methods to find a DWARF object (DWO) +//! within the package. +//! //! * Each section gets its own type. Consider these types the entry points to //! the library: //! diff --git a/src/read/rnglists.rs b/src/read/rnglists.rs index 03a42171..72671838 100644 --- a/src/read/rnglists.rs +++ b/src/read/rnglists.rs @@ -38,6 +38,20 @@ where } } +impl DebugRanges { + /// Create a `DebugRanges` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugRanges + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + impl Section for DebugRanges { fn id() -> SectionId { SectionId::DebugRanges @@ -85,6 +99,20 @@ where } } +impl DebugRngLists { + /// Create a `DebugRngLists` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugRngLists + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + impl Section for DebugRngLists { fn id() -> SectionId { SectionId::DebugRngLists @@ -165,17 +193,7 @@ impl RangeLists { /// /// This is useful when `R` implements `Reader` but `T` does not. /// - /// ## Example Usage - /// - /// ```rust,no_run - /// # let load_section = || unimplemented!(); - /// // Read the DWARF section into a `Vec` with whatever object loader you're using. - /// let owned_section: gimli::RangeLists> = load_section(); - /// // Create a reference to the DWARF section. - /// let section = owned_section.borrow(|section| { - /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) - /// }); - /// ``` + /// Used by `Dwarf::borrow`. pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> RangeLists where F: FnMut(&'a T) -> R, diff --git a/src/read/str.rs b/src/read/str.rs index 94e832d0..df7ab1cc 100644 --- a/src/read/str.rs +++ b/src/read/str.rs @@ -61,17 +61,7 @@ impl DebugStr { /// /// This is useful when `R` implements `Reader` but `T` does not. /// - /// ## Example Usage - /// - /// ```rust,no_run - /// # let load_section = || unimplemented!(); - /// // Read the DWARF section into a `Vec` with whatever object loader you're using. - /// let owned_section: gimli::DebugStr> = load_section(); - /// // Create a reference to the DWARF section. - /// let section = owned_section.borrow(|section| { - /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) - /// }); - /// ``` + /// Used by `DwarfSections::borrow`. pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugStr where F: FnMut(&'a T) -> R, @@ -139,17 +129,7 @@ impl DebugStrOffsets { /// /// This is useful when `R` implements `Reader` but `T` does not. /// - /// ## Example Usage - /// - /// ```rust,no_run - /// # let load_section = || unimplemented!(); - /// // Read the DWARF section into a `Vec` with whatever object loader you're using. - /// let owned_section: gimli::DebugStrOffsets> = load_section(); - /// // Create a reference to the DWARF section. - /// let section = owned_section.borrow(|section| { - /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) - /// }); - /// ``` + /// Used by `DwarfSections::borrow`. pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugStrOffsets where F: FnMut(&'a T) -> R, @@ -242,17 +222,7 @@ impl DebugLineStr { /// /// This is useful when `R` implements `Reader` but `T` does not. /// - /// ## Example Usage - /// - /// ```rust,no_run - /// # let load_section = || unimplemented!(); - /// // Read the DWARF section into a `Vec` with whatever object loader you're using. - /// let owned_section: gimli::DebugLineStr> = load_section(); - /// // Create a reference to the DWARF section. - /// let section = owned_section.borrow(|section| { - /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) - /// }); - /// ``` + /// Used by `DwarfSections::borrow`. pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugLineStr where F: FnMut(&'a T) -> R, diff --git a/src/read/unit.rs b/src/read/unit.rs index f4be8b5a..de368a58 100644 --- a/src/read/unit.rs +++ b/src/read/unit.rs @@ -147,17 +147,7 @@ impl DebugInfo { /// /// This is useful when `R` implements `Reader` but `T` does not. /// - /// ## Example Usage - /// - /// ```rust,no_run - /// # let load_section = || unimplemented!(); - /// // Read the DWARF section into a `Vec` with whatever object loader you're using. - /// let owned_section: gimli::DebugInfo> = load_section(); - /// // Create a reference to the DWARF section. - /// let section = owned_section.borrow(|section| { - /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) - /// }); - /// ``` + /// Used by `DwarfSections::borrow`. pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugInfo where F: FnMut(&'a T) -> R, @@ -3099,17 +3089,7 @@ impl DebugTypes { /// /// This is useful when `R` implements `Reader` but `T` does not. /// - /// ## Example Usage - /// - /// ```rust,no_run - /// # let load_section = || unimplemented!(); - /// // Read the DWARF section into a `Vec` with whatever object loader you're using. - /// let owned_section: gimli::DebugTypes> = load_section(); - /// // Create a reference to the DWARF section. - /// let section = owned_section.borrow(|section| { - /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) - /// }); - /// ``` + /// Used by `DwarfSections::borrow`. pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugTypes where F: FnMut(&'a T) -> R,