| 1 | use crate::common::{DebugInfoOffset, SectionId}; |
| 2 | use crate::endianity::Endianity; |
| 3 | use crate::read::lookup::{DebugLookup, LookupEntryIter, PubStuffEntry, PubStuffParser}; |
| 4 | use crate::read::{EndianSlice, Reader, Result, Section, UnitOffset}; |
| 5 | |
| 6 | /// A single parsed pubtype. |
| 7 | #[derive (Debug, Clone)] |
| 8 | pub struct PubTypesEntry<R: Reader> { |
| 9 | unit_header_offset: DebugInfoOffset<R::Offset>, |
| 10 | die_offset: UnitOffset<R::Offset>, |
| 11 | name: R, |
| 12 | } |
| 13 | |
| 14 | impl<R: Reader> PubTypesEntry<R> { |
| 15 | /// Returns the name of the type this entry refers to. |
| 16 | pub fn name(&self) -> &R { |
| 17 | &self.name |
| 18 | } |
| 19 | |
| 20 | /// Returns the offset into the .debug_info section for the header of the compilation unit |
| 21 | /// which contains the type with this name. |
| 22 | pub fn unit_header_offset(&self) -> DebugInfoOffset<R::Offset> { |
| 23 | self.unit_header_offset |
| 24 | } |
| 25 | |
| 26 | /// Returns the offset into the compilation unit for the debugging information entry which |
| 27 | /// the type with this name. |
| 28 | pub fn die_offset(&self) -> UnitOffset<R::Offset> { |
| 29 | self.die_offset |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | impl<R: Reader> PubStuffEntry<R> for PubTypesEntry<R> { |
| 34 | fn new( |
| 35 | die_offset: UnitOffset<R::Offset>, |
| 36 | name: R, |
| 37 | unit_header_offset: DebugInfoOffset<R::Offset>, |
| 38 | ) -> Self { |
| 39 | PubTypesEntry { |
| 40 | unit_header_offset, |
| 41 | die_offset, |
| 42 | name, |
| 43 | } |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | /// The `DebugPubTypes` struct represents the DWARF public types information |
| 48 | /// found in the `.debug_info` section. |
| 49 | #[derive (Debug, Clone)] |
| 50 | pub struct DebugPubTypes<R: Reader>(DebugLookup<R, PubStuffParser<R, PubTypesEntry<R>>>); |
| 51 | |
| 52 | impl<'input, Endian> DebugPubTypes<EndianSlice<'input, Endian>> |
| 53 | where |
| 54 | Endian: Endianity, |
| 55 | { |
| 56 | /// Construct a new `DebugPubTypes` instance from the data in the `.debug_pubtypes` |
| 57 | /// section. |
| 58 | /// |
| 59 | /// It is the caller's responsibility to read the `.debug_pubtypes` section and |
| 60 | /// present it as a `&[u8]` slice. That means using some ELF loader on |
| 61 | /// Linux, a Mach-O loader on macOS, etc. |
| 62 | /// |
| 63 | /// ``` |
| 64 | /// use gimli::{DebugPubTypes, LittleEndian}; |
| 65 | /// |
| 66 | /// # let buf = []; |
| 67 | /// # let read_debug_pubtypes_somehow = || &buf; |
| 68 | /// let debug_pubtypes = |
| 69 | /// DebugPubTypes::new(read_debug_pubtypes_somehow(), LittleEndian); |
| 70 | /// ``` |
| 71 | pub fn new(debug_pubtypes_section: &'input [u8], endian: Endian) -> Self { |
| 72 | Self::from(EndianSlice::new(slice:debug_pubtypes_section, endian)) |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | impl<R: Reader> DebugPubTypes<R> { |
| 77 | /// Iterate the pubtypes in the `.debug_pubtypes` section. |
| 78 | /// |
| 79 | /// ``` |
| 80 | /// use gimli::{DebugPubTypes, EndianSlice, LittleEndian}; |
| 81 | /// |
| 82 | /// # let buf = []; |
| 83 | /// # let read_debug_pubtypes_section_somehow = || &buf; |
| 84 | /// let debug_pubtypes = |
| 85 | /// DebugPubTypes::new(read_debug_pubtypes_section_somehow(), LittleEndian); |
| 86 | /// |
| 87 | /// let mut iter = debug_pubtypes.items(); |
| 88 | /// while let Some(pubtype) = iter.next().unwrap() { |
| 89 | /// println!("pubtype {} found!" , pubtype.name().to_string_lossy()); |
| 90 | /// } |
| 91 | /// ``` |
| 92 | pub fn items(&self) -> PubTypesEntryIter<R> { |
| 93 | PubTypesEntryIter(self.0.items()) |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | impl<R: Reader> Section<R> for DebugPubTypes<R> { |
| 98 | fn id() -> SectionId { |
| 99 | SectionId::DebugPubTypes |
| 100 | } |
| 101 | |
| 102 | fn reader(&self) -> &R { |
| 103 | self.0.reader() |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | impl<R: Reader> From<R> for DebugPubTypes<R> { |
| 108 | fn from(debug_pubtypes_section: R) -> Self { |
| 109 | DebugPubTypes(DebugLookup::from(debug_pubtypes_section)) |
| 110 | } |
| 111 | } |
| 112 | |
| 113 | /// An iterator over the pubtypes from a `.debug_pubtypes` section. |
| 114 | /// |
| 115 | /// Can be [used with |
| 116 | /// `FallibleIterator`](./index.html#using-with-fallibleiterator). |
| 117 | #[derive (Debug, Clone)] |
| 118 | pub struct PubTypesEntryIter<R: Reader>(LookupEntryIter<R, PubStuffParser<R, PubTypesEntry<R>>>); |
| 119 | |
| 120 | impl<R: Reader> PubTypesEntryIter<R> { |
| 121 | /// Advance the iterator and return the next pubtype. |
| 122 | /// |
| 123 | /// Returns the newly parsed pubtype as `Ok(Some(pubtype))`. Returns |
| 124 | /// `Ok(None)` when iteration is complete and all pubtypes have already been |
| 125 | /// parsed and yielded. If an error occurs while parsing the next pubtype, |
| 126 | /// then this error is returned as `Err(e)`, and all subsequent calls return |
| 127 | /// `Ok(None)`. |
| 128 | pub fn next(&mut self) -> Result<Option<PubTypesEntry<R>>> { |
| 129 | self.0.next() |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | #[cfg (feature = "fallible-iterator" )] |
| 134 | impl<R: Reader> fallible_iterator::FallibleIterator for PubTypesEntryIter<R> { |
| 135 | type Item = PubTypesEntry<R>; |
| 136 | type Error = crate::read::Error; |
| 137 | |
| 138 | fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> { |
| 139 | self.0.next() |
| 140 | } |
| 141 | } |
| 142 | |