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 | |