1 use core
::marker
::PhantomData
;
3 use crate::common
::{DebugInfoOffset, Format}
;
4 use crate::read
::{parse_debug_info_offset, Error, Reader, ReaderOffset, Result, UnitOffset}
;
6 // The various "Accelerated Access" sections (DWARF standard v4 Section 6.1) all have
7 // similar structures. They consist of a header with metadata and an offset into the
8 // .debug_info section for the entire compilation unit, and a series
9 // of following entries that list addresses (for .debug_aranges) or names
10 // (for .debug_pubnames and .debug_pubtypes) that are covered.
12 // Because these three tables all have similar structures, we abstract out some of
13 // the parsing mechanics.
15 pub trait LookupParser
<R
: Reader
> {
16 /// The type of the produced header.
18 /// The type of the produced entry.
21 /// Parse a header from `input`. Returns a tuple of `input` sliced to contain just the entries
22 /// corresponding to this header (without the header itself), and the parsed representation of
23 /// the header itself.
24 fn parse_header(input
: &mut R
) -> Result
<(R
, Self::Header
)>;
26 /// Parse a single entry from `input`. Returns either a parsed representation of the entry
27 /// or None if `input` is exhausted.
28 fn parse_entry(input
: &mut R
, header
: &Self::Header
) -> Result
<Option
<Self::Entry
>>;
31 #[derive(Clone, Debug)]
32 pub struct DebugLookup
<R
, Parser
>
35 Parser
: LookupParser
<R
>,
38 phantom
: PhantomData
<Parser
>,
41 impl<R
, Parser
> From
<R
> for DebugLookup
<R
, Parser
>
44 Parser
: LookupParser
<R
>,
46 fn from(input_buffer
: R
) -> Self {
54 impl<R
, Parser
> DebugLookup
<R
, Parser
>
57 Parser
: LookupParser
<R
>,
59 pub fn items(&self) -> LookupEntryIter
<R
, Parser
> {
62 remaining_input
: self.input_buffer
.clone(),
66 pub fn reader(&self) -> &R
{
71 #[derive(Clone, Debug)]
72 pub struct LookupEntryIter
<R
, Parser
>
75 Parser
: LookupParser
<R
>,
77 current_set
: Option
<(R
, Parser
::Header
)>, // Only none at the very beginning and end.
81 impl<R
, Parser
> LookupEntryIter
<R
, Parser
>
84 Parser
: LookupParser
<R
>,
86 /// Advance the iterator and return the next entry.
88 /// Returns the newly parsed entry as `Ok(Some(Parser::Entry))`. Returns
89 /// `Ok(None)` when iteration is complete and all entries have already been
90 /// parsed and yielded. If an error occurs while parsing the next entry,
91 /// then this error is returned as `Err(e)`, and all subsequent calls return
94 /// Can be [used with `FallibleIterator`](./index.html#using-with-fallibleiterator).
95 pub fn next(&mut self) -> Result
<Option
<Parser
::Entry
>> {
97 if let Some((ref mut input
, ref header
)) = self.current_set
{
98 if !input
.is_empty() {
99 match Parser
::parse_entry(input
, header
) {
100 Ok(Some(entry
)) => return Ok(Some(entry
)),
104 self.remaining_input
.empty();
110 if self.remaining_input
.is_empty() {
111 self.current_set
= None
;
114 match Parser
::parse_header(&mut self.remaining_input
) {
116 self.current_set
= Some(set
);
119 self.current_set
= None
;
120 self.remaining_input
.empty();
128 #[derive(Debug, Clone, PartialEq, Eq)]
129 pub struct PubStuffHeader
<T
= usize> {
133 unit_offset
: DebugInfoOffset
<T
>,
137 pub trait PubStuffEntry
<R
: Reader
> {
139 die_offset
: UnitOffset
<R
::Offset
>,
141 unit_header_offset
: DebugInfoOffset
<R
::Offset
>,
145 #[derive(Clone, Debug)]
146 pub struct PubStuffParser
<R
, Entry
>
149 Entry
: PubStuffEntry
<R
>,
151 // This struct is never instantiated.
152 phantom
: PhantomData
<(R
, Entry
)>,
155 impl<R
, Entry
> LookupParser
<R
> for PubStuffParser
<R
, Entry
>
158 Entry
: PubStuffEntry
<R
>,
160 type Header
= PubStuffHeader
<R
::Offset
>;
163 /// Parse an pubthings set header. Returns a tuple of the
164 /// pubthings to be parsed for this set, and the newly created PubThingHeader struct.
165 fn parse_header(input
: &mut R
) -> Result
<(R
, Self::Header
)> {
166 let (length
, format
) = input
.read_initial_length()?
;
167 let mut rest
= input
.split(length
)?
;
169 let version
= rest
.read_u16()?
;
171 return Err(Error
::UnknownVersion(u64::from(version
)));
174 let unit_offset
= parse_debug_info_offset(&mut rest
, format
)?
;
175 let unit_length
= rest
.read_length(format
)?
;
177 let header
= PubStuffHeader
{
187 /// Parse a single pubthing. Return `None` for the null pubthing, `Some` for an actual pubthing.
188 fn parse_entry(input
: &mut R
, header
: &Self::Header
) -> Result
<Option
<Self::Entry
>> {
189 let offset
= input
.read_offset(header
.format
)?
;
190 if offset
.into_u64() == 0 {
194 let name
= input
.read_null_terminated_slice()?
;
195 Ok(Some(Self::Entry
::new(