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