1 //! Functions for parsing DWARF `.debug_info` and `.debug_types` sections.
2 
3 use core::cell::Cell;
4 use core::ops::{Range, RangeFrom, RangeTo};
5 use core::{u16, u8};
6 
7 use crate::common::{
8     DebugAbbrevOffset, DebugAddrBase, DebugAddrIndex, DebugInfoOffset, DebugLineOffset,
9     DebugLineStrOffset, DebugLocListsBase, DebugLocListsIndex, DebugMacinfoOffset,
10     DebugMacroOffset, DebugRngListsBase, DebugRngListsIndex, DebugStrOffset, DebugStrOffsetsBase,
11     DebugStrOffsetsIndex, DebugTypeSignature, DebugTypesOffset, DwoId, Encoding, Format,
12     LocationListsOffset, RangeListsOffset, SectionId, UnitSectionOffset,
13 };
14 use crate::constants;
15 use crate::endianity::Endianity;
16 use crate::read::{
17     Abbreviation, Abbreviations, AttributeSpecification, DebugAbbrev, DebugStr, EndianSlice, Error,
18     Expression, Reader, ReaderOffset, Result, Section,
19 };
20 
21 impl<T: ReaderOffset> DebugTypesOffset<T> {
22     /// Convert an offset to be relative to the start of the given unit,
23     /// instead of relative to the start of the .debug_types section.
24     /// Returns `None` if the offset is not within the unit entries.
to_unit_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitOffset<T>> where R: Reader<Offset = T>,25     pub fn to_unit_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitOffset<T>>
26     where
27         R: Reader<Offset = T>,
28     {
29         let unit_offset = unit.offset().as_debug_types_offset()?;
30         let offset = UnitOffset(self.0.checked_sub(unit_offset.0)?);
31         if !unit.is_valid_offset(offset) {
32             return None;
33         }
34         Some(offset)
35     }
36 }
37 
38 impl<T: ReaderOffset> DebugInfoOffset<T> {
39     /// Convert an offset to be relative to the start of the given unit,
40     /// instead of relative to the start of the .debug_info section.
41     /// Returns `None` if the offset is not within this unit entries.
to_unit_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitOffset<T>> where R: Reader<Offset = T>,42     pub fn to_unit_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitOffset<T>>
43     where
44         R: Reader<Offset = T>,
45     {
46         let unit_offset = unit.offset().as_debug_info_offset()?;
47         let offset = UnitOffset(self.0.checked_sub(unit_offset.0)?);
48         if !unit.is_valid_offset(offset) {
49             return None;
50         }
51         Some(offset)
52     }
53 }
54 
55 /// An offset into the current compilation or type unit.
56 #[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
57 pub struct UnitOffset<T = usize>(pub T);
58 
59 impl<T: ReaderOffset> UnitOffset<T> {
60     /// Convert an offset to be relative to the start of the .debug_info section,
61     /// instead of relative to the start of the given unit. Returns None if the
62     /// provided unit lives in the .debug_types section.
to_debug_info_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugInfoOffset<T>> where R: Reader<Offset = T>,63     pub fn to_debug_info_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugInfoOffset<T>>
64     where
65         R: Reader<Offset = T>,
66     {
67         let unit_offset = unit.offset().as_debug_info_offset()?;
68         Some(DebugInfoOffset(unit_offset.0 + self.0))
69     }
70 
71     /// Convert an offset to be relative to the start of the .debug_types section,
72     /// instead of relative to the start of the given unit. Returns None if the
73     /// provided unit lives in the .debug_info section.
to_debug_types_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugTypesOffset<T>> where R: Reader<Offset = T>,74     pub fn to_debug_types_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugTypesOffset<T>>
75     where
76         R: Reader<Offset = T>,
77     {
78         let unit_offset = unit.offset().as_debug_types_offset()?;
79         Some(DebugTypesOffset(unit_offset.0 + self.0))
80     }
81 }
82 
83 /// The `DebugInfo` struct represents the DWARF debugging information found in
84 /// the `.debug_info` section.
85 #[derive(Debug, Default, Clone, Copy)]
86 pub struct DebugInfo<R> {
87     debug_info_section: R,
88 }
89 
90 impl<'input, Endian> DebugInfo<EndianSlice<'input, Endian>>
91 where
92     Endian: Endianity,
93 {
94     /// Construct a new `DebugInfo` instance from the data in the `.debug_info`
95     /// section.
96     ///
97     /// It is the caller's responsibility to read the `.debug_info` section and
98     /// present it as a `&[u8]` slice. That means using some ELF loader on
99     /// Linux, a Mach-O loader on OSX, etc.
100     ///
101     /// ```
102     /// use gimli::{DebugInfo, LittleEndian};
103     ///
104     /// # let buf = [0x00, 0x01, 0x02, 0x03];
105     /// # let read_debug_info_section_somehow = || &buf;
106     /// let debug_info = DebugInfo::new(read_debug_info_section_somehow(), LittleEndian);
107     /// ```
new(debug_info_section: &'input [u8], endian: Endian) -> Self108     pub fn new(debug_info_section: &'input [u8], endian: Endian) -> Self {
109         Self::from(EndianSlice::new(debug_info_section, endian))
110     }
111 }
112 
113 impl<R: Reader> DebugInfo<R> {
114     /// Iterate the units in this `.debug_info` section.
115     ///
116     /// ```
117     /// use gimli::{DebugInfo, LittleEndian};
118     ///
119     /// # let buf = [];
120     /// # let read_debug_info_section_somehow = || &buf;
121     /// let debug_info = DebugInfo::new(read_debug_info_section_somehow(), LittleEndian);
122     ///
123     /// let mut iter = debug_info.units();
124     /// while let Some(unit) = iter.next().unwrap() {
125     ///     println!("unit's length is {}", unit.unit_length());
126     /// }
127     /// ```
128     ///
129     /// Can be [used with
130     /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
units(&self) -> DebugInfoUnitHeadersIter<R>131     pub fn units(&self) -> DebugInfoUnitHeadersIter<R> {
132         DebugInfoUnitHeadersIter {
133             input: self.debug_info_section.clone(),
134             offset: DebugInfoOffset(R::Offset::from_u8(0)),
135         }
136     }
137 
138     /// Get the UnitHeader located at offset from this .debug_info section.
139     ///
140     ///
header_from_offset(&self, offset: DebugInfoOffset<R::Offset>) -> Result<UnitHeader<R>>141     pub fn header_from_offset(&self, offset: DebugInfoOffset<R::Offset>) -> Result<UnitHeader<R>> {
142         let input = &mut self.debug_info_section.clone();
143         input.skip(offset.0)?;
144         parse_unit_header(input, offset.into())
145     }
146 }
147 
148 impl<T> DebugInfo<T> {
149     /// Create a `DebugInfo` section that references the data in `self`.
150     ///
151     /// This is useful when `R` implements `Reader` but `T` does not.
152     ///
153     /// ## Example Usage
154     ///
155     /// ```rust,no_run
156     /// # let load_section = || unimplemented!();
157     /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
158     /// let owned_section: gimli::DebugInfo<Vec<u8>> = load_section();
159     /// // Create a reference to the DWARF section.
160     /// let section = owned_section.borrow(|section| {
161     ///     gimli::EndianSlice::new(&section, gimli::LittleEndian)
162     /// });
163     /// ```
borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugInfo<R> where F: FnMut(&'a T) -> R,164     pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugInfo<R>
165     where
166         F: FnMut(&'a T) -> R,
167     {
168         borrow(&self.debug_info_section).into()
169     }
170 }
171 
172 impl<R> Section<R> for DebugInfo<R> {
id() -> SectionId173     fn id() -> SectionId {
174         SectionId::DebugInfo
175     }
176 
reader(&self) -> &R177     fn reader(&self) -> &R {
178         &self.debug_info_section
179     }
180 }
181 
182 impl<R> From<R> for DebugInfo<R> {
from(debug_info_section: R) -> Self183     fn from(debug_info_section: R) -> Self {
184         DebugInfo { debug_info_section }
185     }
186 }
187 
188 /// An iterator over the units of a .debug_info section.
189 ///
190 /// See the [documentation on
191 /// `DebugInfo::units`](./struct.DebugInfo.html#method.units) for more detail.
192 #[derive(Clone, Debug)]
193 pub struct DebugInfoUnitHeadersIter<R: Reader> {
194     input: R,
195     offset: DebugInfoOffset<R::Offset>,
196 }
197 
198 impl<R: Reader> DebugInfoUnitHeadersIter<R> {
199     /// Advance the iterator to the next unit header.
next(&mut self) -> Result<Option<UnitHeader<R>>>200     pub fn next(&mut self) -> Result<Option<UnitHeader<R>>> {
201         if self.input.is_empty() {
202             Ok(None)
203         } else {
204             let len = self.input.len();
205             match parse_unit_header(&mut self.input, self.offset.into()) {
206                 Ok(header) => {
207                     self.offset.0 += len - self.input.len();
208                     Ok(Some(header))
209                 }
210                 Err(e) => {
211                     self.input.empty();
212                     Err(e)
213                 }
214             }
215         }
216     }
217 }
218 
219 #[cfg(feature = "fallible-iterator")]
220 impl<R: Reader> fallible_iterator::FallibleIterator for DebugInfoUnitHeadersIter<R> {
221     type Item = UnitHeader<R>;
222     type Error = Error;
223 
next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error>224     fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
225         DebugInfoUnitHeadersIter::next(self)
226     }
227 }
228 
229 /// Parse the unit type from the unit header.
parse_unit_type<R: Reader>(input: &mut R) -> Result<constants::DwUt>230 fn parse_unit_type<R: Reader>(input: &mut R) -> Result<constants::DwUt> {
231     let val = input.read_u8()?;
232     Ok(constants::DwUt(val))
233 }
234 
235 /// Parse the `debug_abbrev_offset` in the compilation unit header.
parse_debug_abbrev_offset<R: Reader>( input: &mut R, format: Format, ) -> Result<DebugAbbrevOffset<R::Offset>>236 fn parse_debug_abbrev_offset<R: Reader>(
237     input: &mut R,
238     format: Format,
239 ) -> Result<DebugAbbrevOffset<R::Offset>> {
240     input.read_offset(format).map(DebugAbbrevOffset)
241 }
242 
243 /// Parse the `debug_info_offset` in the arange header.
parse_debug_info_offset<R: Reader>( input: &mut R, format: Format, ) -> Result<DebugInfoOffset<R::Offset>>244 pub(crate) fn parse_debug_info_offset<R: Reader>(
245     input: &mut R,
246     format: Format,
247 ) -> Result<DebugInfoOffset<R::Offset>> {
248     input.read_offset(format).map(DebugInfoOffset)
249 }
250 
251 /// This enum specifies the type of the unit and any type
252 /// specific data carried in the header (e.g. the type
253 /// signature/type offset of a type unit).
254 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
255 pub enum UnitType<Offset>
256 where
257     Offset: ReaderOffset,
258 {
259     /// In DWARF5, a unit with type `DW_UT_compile`. In previous DWARF versions,
260     /// any unit appearing in the .debug_info section.
261     Compilation,
262     /// In DWARF5, a unit with type `DW_UT_type`. In DWARF4, any unit appearing
263     /// in the .debug_types section.
264     Type {
265         /// The unique type signature for this type unit.
266         type_signature: DebugTypeSignature,
267         /// The offset within this type unit where the type is defined.
268         type_offset: UnitOffset<Offset>,
269     },
270     /// A unit with type `DW_UT_partial`. The root DIE of this unit should be a
271     /// `DW_TAG_partial_unit`.
272     Partial,
273     /// A unit with type `DW_UT_skeleton`. The enclosed dwo_id can be used to
274     /// link this with the corresponding `SplitCompilation` unit in a dwo file.
275     /// NB: The non-standard GNU split DWARF extension to DWARF 4 will instead
276     /// be a `Compilation` unit with the dwo_id present as an attribute on the
277     /// root DIE.
278     Skeleton(DwoId),
279     /// A unit with type `DW_UT_split_compile`. The enclosed dwo_id can be used to
280     /// link this with the corresponding `Skeleton` unit in the original binary.
281     /// NB: The non-standard GNU split DWARF extension to DWARF 4 will instead
282     /// be a `Compilation` unit with the dwo_id present as an attribute on the
283     /// root DIE.
284     SplitCompilation(DwoId),
285     /// A unit with type `DW_UT_split_type`. A split type unit is identical to a
286     /// conventional type unit except for the section in which it appears.
287     SplitType {
288         /// The unique type signature for this type unit.
289         type_signature: DebugTypeSignature,
290         /// The offset within this type unit where the type is defined.
291         type_offset: UnitOffset<Offset>,
292     },
293 }
294 
295 impl<Offset> UnitType<Offset>
296 where
297     Offset: ReaderOffset,
298 {
299     // TODO: This will be used by the DWARF writing code once it
300     // supports unit types other than simple compilation units.
301     #[allow(unused)]
dw_ut(&self) -> constants::DwUt302     pub(crate) fn dw_ut(&self) -> constants::DwUt {
303         match self {
304             UnitType::Compilation => constants::DW_UT_compile,
305             UnitType::Type { .. } => constants::DW_UT_type,
306             UnitType::Partial => constants::DW_UT_partial,
307             UnitType::Skeleton(_) => constants::DW_UT_skeleton,
308             UnitType::SplitCompilation(_) => constants::DW_UT_split_compile,
309             UnitType::SplitType { .. } => constants::DW_UT_split_type,
310         }
311     }
312 }
313 
314 /// The common fields for the headers of compilation units and
315 /// type units.
316 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
317 pub struct UnitHeader<R, Offset = <R as Reader>::Offset>
318 where
319     R: Reader<Offset = Offset>,
320     Offset: ReaderOffset,
321 {
322     encoding: Encoding,
323     unit_length: Offset,
324     unit_type: UnitType<Offset>,
325     debug_abbrev_offset: DebugAbbrevOffset<Offset>,
326     unit_offset: UnitSectionOffset<Offset>,
327     entries_buf: R,
328 }
329 
330 /// Static methods.
331 impl<R, Offset> UnitHeader<R, Offset>
332 where
333     R: Reader<Offset = Offset>,
334     Offset: ReaderOffset,
335 {
336     /// Construct a new `UnitHeader`.
new( encoding: Encoding, unit_length: Offset, unit_type: UnitType<Offset>, debug_abbrev_offset: DebugAbbrevOffset<Offset>, unit_offset: UnitSectionOffset<Offset>, entries_buf: R, ) -> Self337     pub fn new(
338         encoding: Encoding,
339         unit_length: Offset,
340         unit_type: UnitType<Offset>,
341         debug_abbrev_offset: DebugAbbrevOffset<Offset>,
342         unit_offset: UnitSectionOffset<Offset>,
343         entries_buf: R,
344     ) -> Self {
345         UnitHeader {
346             encoding,
347             unit_length,
348             unit_type,
349             debug_abbrev_offset,
350             unit_offset,
351             entries_buf,
352         }
353     }
354 }
355 
356 /// Instance methods.
357 impl<R, Offset> UnitHeader<R, Offset>
358 where
359     R: Reader<Offset = Offset>,
360     Offset: ReaderOffset,
361 {
362     /// Get the offset of this unit within its section.
offset(&self) -> UnitSectionOffset<Offset>363     pub fn offset(&self) -> UnitSectionOffset<Offset> {
364         self.unit_offset
365     }
366 
367     /// Return the serialized size of the common unit header for the given
368     /// DWARF format.
size_of_header(&self) -> usize369     pub fn size_of_header(&self) -> usize {
370         let unit_length_size = self.encoding.format.initial_length_size() as usize;
371         let version_size = 2;
372         let debug_abbrev_offset_size = self.encoding.format.word_size() as usize;
373         let address_size_size = 1;
374         let unit_type_size = if self.encoding.version == 5 { 1 } else { 0 };
375         let type_specific_size = match self.unit_type {
376             UnitType::Compilation | UnitType::Partial => 0,
377             UnitType::Type { .. } | UnitType::SplitType { .. } => {
378                 let type_signature_size = 8;
379                 let type_offset_size = self.encoding.format.word_size() as usize;
380                 type_signature_size + type_offset_size
381             }
382             UnitType::Skeleton(_) | UnitType::SplitCompilation(_) => 8,
383         };
384 
385         unit_length_size
386             + version_size
387             + debug_abbrev_offset_size
388             + address_size_size
389             + unit_type_size
390             + type_specific_size
391     }
392 
393     /// Get the length of the debugging info for this compilation unit, not
394     /// including the byte length of the encoded length itself.
unit_length(&self) -> Offset395     pub fn unit_length(&self) -> Offset {
396         self.unit_length
397     }
398 
399     /// Get the length of the debugging info for this compilation unit,
400     /// including the byte length of the encoded length itself.
length_including_self(&self) -> Offset401     pub fn length_including_self(&self) -> Offset {
402         Offset::from_u8(self.format().initial_length_size()) + self.unit_length
403     }
404 
405     /// Return the encoding parameters for this unit.
encoding(&self) -> Encoding406     pub fn encoding(&self) -> Encoding {
407         self.encoding
408     }
409 
410     /// Get the DWARF version of the debugging info for this compilation unit.
version(&self) -> u16411     pub fn version(&self) -> u16 {
412         self.encoding.version
413     }
414 
415     /// Get the UnitType of this unit.
type_(&self) -> UnitType<Offset>416     pub fn type_(&self) -> UnitType<Offset> {
417         self.unit_type
418     }
419 
420     /// The offset into the `.debug_abbrev` section for this compilation unit's
421     /// debugging information entries' abbreviations.
debug_abbrev_offset(&self) -> DebugAbbrevOffset<Offset>422     pub fn debug_abbrev_offset(&self) -> DebugAbbrevOffset<Offset> {
423         self.debug_abbrev_offset
424     }
425 
426     /// The size of addresses (in bytes) in this compilation unit.
address_size(&self) -> u8427     pub fn address_size(&self) -> u8 {
428         self.encoding.address_size
429     }
430 
431     /// Whether this compilation unit is encoded in 64- or 32-bit DWARF.
format(&self) -> Format432     pub fn format(&self) -> Format {
433         self.encoding.format
434     }
435 
436     /// The serialized size of the header for this compilation unit.
header_size(&self) -> Offset437     pub fn header_size(&self) -> Offset {
438         self.length_including_self() - self.entries_buf.len()
439     }
440 
is_valid_offset(&self, offset: UnitOffset<Offset>) -> bool441     pub(crate) fn is_valid_offset(&self, offset: UnitOffset<Offset>) -> bool {
442         let size_of_header = self.header_size();
443         if offset.0 < size_of_header {
444             return false;
445         }
446 
447         let relative_to_entries_buf = offset.0 - size_of_header;
448         relative_to_entries_buf < self.entries_buf.len()
449     }
450 
451     /// Get the underlying bytes for the supplied range.
range(&self, idx: Range<UnitOffset<Offset>>) -> Result<R>452     pub fn range(&self, idx: Range<UnitOffset<Offset>>) -> Result<R> {
453         if !self.is_valid_offset(idx.start) {
454             return Err(Error::OffsetOutOfBounds);
455         }
456         if !self.is_valid_offset(idx.end) {
457             return Err(Error::OffsetOutOfBounds);
458         }
459         assert!(idx.start <= idx.end);
460         let size_of_header = self.header_size();
461         let start = idx.start.0 - size_of_header;
462         let end = idx.end.0 - size_of_header;
463         let mut input = self.entries_buf.clone();
464         input.skip(start)?;
465         input.truncate(end - start)?;
466         Ok(input)
467     }
468 
469     /// Get the underlying bytes for the supplied range.
range_from(&self, idx: RangeFrom<UnitOffset<Offset>>) -> Result<R>470     pub fn range_from(&self, idx: RangeFrom<UnitOffset<Offset>>) -> Result<R> {
471         if !self.is_valid_offset(idx.start) {
472             return Err(Error::OffsetOutOfBounds);
473         }
474         let start = idx.start.0 - self.header_size();
475         let mut input = self.entries_buf.clone();
476         input.skip(start)?;
477         Ok(input)
478     }
479 
480     /// Get the underlying bytes for the supplied range.
range_to(&self, idx: RangeTo<UnitOffset<Offset>>) -> Result<R>481     pub fn range_to(&self, idx: RangeTo<UnitOffset<Offset>>) -> Result<R> {
482         if !self.is_valid_offset(idx.end) {
483             return Err(Error::OffsetOutOfBounds);
484         }
485         let end = idx.end.0 - self.header_size();
486         let mut input = self.entries_buf.clone();
487         input.truncate(end)?;
488         Ok(input)
489     }
490 
491     /// Read the `DebuggingInformationEntry` at the given offset.
entry<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, offset: UnitOffset<Offset>, ) -> Result<DebuggingInformationEntry<'abbrev, 'me, R>>492     pub fn entry<'me, 'abbrev>(
493         &'me self,
494         abbreviations: &'abbrev Abbreviations,
495         offset: UnitOffset<Offset>,
496     ) -> Result<DebuggingInformationEntry<'abbrev, 'me, R>> {
497         let mut input = self.range_from(offset..)?;
498         let entry = DebuggingInformationEntry::parse(&mut input, self, abbreviations)?;
499         entry.ok_or(Error::NoEntryAtGivenOffset)
500     }
501 
502     /// Navigate this unit's `DebuggingInformationEntry`s.
entries<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, ) -> EntriesCursor<'abbrev, 'me, R>503     pub fn entries<'me, 'abbrev>(
504         &'me self,
505         abbreviations: &'abbrev Abbreviations,
506     ) -> EntriesCursor<'abbrev, 'me, R> {
507         EntriesCursor {
508             unit: self,
509             input: self.entries_buf.clone(),
510             abbreviations,
511             cached_current: None,
512             delta_depth: 0,
513         }
514     }
515 
516     /// Navigate this compilation unit's `DebuggingInformationEntry`s
517     /// starting at the given offset.
entries_at_offset<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, offset: UnitOffset<Offset>, ) -> Result<EntriesCursor<'abbrev, 'me, R>>518     pub fn entries_at_offset<'me, 'abbrev>(
519         &'me self,
520         abbreviations: &'abbrev Abbreviations,
521         offset: UnitOffset<Offset>,
522     ) -> Result<EntriesCursor<'abbrev, 'me, R>> {
523         let input = self.range_from(offset..)?;
524         Ok(EntriesCursor {
525             unit: self,
526             input,
527             abbreviations,
528             cached_current: None,
529             delta_depth: 0,
530         })
531     }
532 
533     /// Navigate this unit's `DebuggingInformationEntry`s as a tree
534     /// starting at the given offset.
entries_tree<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, offset: Option<UnitOffset<Offset>>, ) -> Result<EntriesTree<'abbrev, 'me, R>>535     pub fn entries_tree<'me, 'abbrev>(
536         &'me self,
537         abbreviations: &'abbrev Abbreviations,
538         offset: Option<UnitOffset<Offset>>,
539     ) -> Result<EntriesTree<'abbrev, 'me, R>> {
540         let input = match offset {
541             Some(offset) => self.range_from(offset..)?,
542             None => self.entries_buf.clone(),
543         };
544         Ok(EntriesTree::new(input, self, abbreviations))
545     }
546 
547     /// Read the raw data that defines the Debugging Information Entries.
entries_raw<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, offset: Option<UnitOffset<Offset>>, ) -> Result<EntriesRaw<'abbrev, 'me, R>>548     pub fn entries_raw<'me, 'abbrev>(
549         &'me self,
550         abbreviations: &'abbrev Abbreviations,
551         offset: Option<UnitOffset<Offset>>,
552     ) -> Result<EntriesRaw<'abbrev, 'me, R>> {
553         let input = match offset {
554             Some(offset) => self.range_from(offset..)?,
555             None => self.entries_buf.clone(),
556         };
557         Ok(EntriesRaw {
558             input,
559             unit: self,
560             abbreviations,
561             depth: 0,
562         })
563     }
564 
565     /// Parse this unit's abbreviations.
abbreviations(&self, debug_abbrev: &DebugAbbrev<R>) -> Result<Abbreviations>566     pub fn abbreviations(&self, debug_abbrev: &DebugAbbrev<R>) -> Result<Abbreviations> {
567         debug_abbrev.abbreviations(self.debug_abbrev_offset())
568     }
569 }
570 
571 /// Parse a unit header.
parse_unit_header<R, Offset>( input: &mut R, unit_offset: UnitSectionOffset<Offset>, ) -> Result<UnitHeader<R>> where R: Reader<Offset = Offset>, Offset: ReaderOffset,572 fn parse_unit_header<R, Offset>(
573     input: &mut R,
574     unit_offset: UnitSectionOffset<Offset>,
575 ) -> Result<UnitHeader<R>>
576 where
577     R: Reader<Offset = Offset>,
578     Offset: ReaderOffset,
579 {
580     let (unit_length, format) = input.read_initial_length()?;
581     let mut rest = input.split(unit_length)?;
582 
583     let version = rest.read_u16()?;
584     let abbrev_offset;
585     let address_size;
586     let unit_type;
587     // DWARF 1 was very different, and is obsolete, so isn't supported by this
588     // reader.
589     if 2 <= version && version <= 4 {
590         abbrev_offset = parse_debug_abbrev_offset(&mut rest, format)?;
591         address_size = rest.read_u8()?;
592         // Before DWARF5, all units in the .debug_info section are compilation
593         // units, and all units in the .debug_types section are type units.
594         unit_type = match unit_offset {
595             UnitSectionOffset::DebugInfoOffset(_) => constants::DW_UT_compile,
596             UnitSectionOffset::DebugTypesOffset(_) => constants::DW_UT_type,
597         };
598     } else if version == 5 {
599         unit_type = parse_unit_type(&mut rest)?;
600         address_size = rest.read_u8()?;
601         abbrev_offset = parse_debug_abbrev_offset(&mut rest, format)?;
602     } else {
603         return Err(Error::UnknownVersion(u64::from(version)));
604     }
605     let encoding = Encoding {
606         format,
607         version,
608         address_size,
609     };
610 
611     // Parse any data specific to this type of unit.
612     let unit_type = match unit_type {
613         constants::DW_UT_compile => UnitType::Compilation,
614         constants::DW_UT_type => {
615             let type_signature = parse_type_signature(&mut rest)?;
616             let type_offset = parse_type_offset(&mut rest, format)?;
617             UnitType::Type {
618                 type_signature,
619                 type_offset,
620             }
621         }
622         constants::DW_UT_partial => UnitType::Partial,
623         constants::DW_UT_skeleton => {
624             let dwo_id = parse_dwo_id(&mut rest)?;
625             UnitType::Skeleton(dwo_id)
626         }
627         constants::DW_UT_split_compile => {
628             let dwo_id = parse_dwo_id(&mut rest)?;
629             UnitType::SplitCompilation(dwo_id)
630         }
631         constants::DW_UT_split_type => {
632             let type_signature = parse_type_signature(&mut rest)?;
633             let type_offset = parse_type_offset(&mut rest, format)?;
634             UnitType::SplitType {
635                 type_signature,
636                 type_offset,
637             }
638         }
639         _ => return Err(Error::UnsupportedUnitType),
640     };
641 
642     Ok(UnitHeader::new(
643         encoding,
644         unit_length,
645         unit_type,
646         abbrev_offset,
647         unit_offset,
648         rest,
649     ))
650 }
651 
652 /// Parse a dwo_id from a header
parse_dwo_id<R: Reader>(input: &mut R) -> Result<DwoId>653 fn parse_dwo_id<R: Reader>(input: &mut R) -> Result<DwoId> {
654     Ok(DwoId(input.read_u64()?))
655 }
656 
657 /// A Debugging Information Entry (DIE).
658 ///
659 /// DIEs have a set of attributes and optionally have children DIEs as well.
660 #[derive(Clone, Debug)]
661 pub struct DebuggingInformationEntry<'abbrev, 'unit, R, Offset = <R as Reader>::Offset>
662 where
663     R: Reader<Offset = Offset>,
664     Offset: ReaderOffset,
665 {
666     offset: UnitOffset<Offset>,
667     attrs_slice: R,
668     attrs_len: Cell<Option<Offset>>,
669     abbrev: &'abbrev Abbreviation,
670     unit: &'unit UnitHeader<R, Offset>,
671 }
672 
673 impl<'abbrev, 'unit, R, Offset> DebuggingInformationEntry<'abbrev, 'unit, R, Offset>
674 where
675     R: Reader<Offset = Offset>,
676     Offset: ReaderOffset,
677 {
678     /// Construct a new `DebuggingInformationEntry`.
new( offset: UnitOffset<Offset>, attrs_slice: R, abbrev: &'abbrev Abbreviation, unit: &'unit UnitHeader<R, Offset>, ) -> Self679     pub fn new(
680         offset: UnitOffset<Offset>,
681         attrs_slice: R,
682         abbrev: &'abbrev Abbreviation,
683         unit: &'unit UnitHeader<R, Offset>,
684     ) -> Self {
685         DebuggingInformationEntry {
686             offset,
687             attrs_slice,
688             attrs_len: Cell::new(None),
689             abbrev,
690             unit,
691         }
692     }
693 
694     /// Get this entry's code.
code(&self) -> u64695     pub fn code(&self) -> u64 {
696         self.abbrev.code()
697     }
698 
699     /// Get this entry's offset.
offset(&self) -> UnitOffset<Offset>700     pub fn offset(&self) -> UnitOffset<Offset> {
701         self.offset
702     }
703 
704     /// Get this entry's `DW_TAG_whatever` tag.
705     ///
706     /// ```
707     /// # use gimli::{DebugAbbrev, DebugInfo, LittleEndian};
708     /// # let info_buf = [
709     /// #     // Comilation unit header
710     /// #
711     /// #     // 32-bit unit length = 12
712     /// #     0x0c, 0x00, 0x00, 0x00,
713     /// #     // Version 4
714     /// #     0x04, 0x00,
715     /// #     // debug_abbrev_offset
716     /// #     0x00, 0x00, 0x00, 0x00,
717     /// #     // Address size
718     /// #     0x04,
719     /// #
720     /// #     // DIEs
721     /// #
722     /// #     // Abbreviation code
723     /// #     0x01,
724     /// #     // Attribute of form DW_FORM_string = "foo\0"
725     /// #     0x66, 0x6f, 0x6f, 0x00,
726     /// # ];
727     /// # let debug_info = DebugInfo::new(&info_buf, LittleEndian);
728     /// # let abbrev_buf = [
729     /// #     // Code
730     /// #     0x01,
731     /// #     // DW_TAG_subprogram
732     /// #     0x2e,
733     /// #     // DW_CHILDREN_no
734     /// #     0x00,
735     /// #     // Begin attributes
736     /// #       // Attribute name = DW_AT_name
737     /// #       0x03,
738     /// #       // Attribute form = DW_FORM_string
739     /// #       0x08,
740     /// #     // End attributes
741     /// #     0x00,
742     /// #     0x00,
743     /// #     // Null terminator
744     /// #     0x00
745     /// # ];
746     /// # let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
747     /// # let unit = debug_info.units().next().unwrap().unwrap();
748     /// # let abbrevs = unit.abbreviations(&debug_abbrev).unwrap();
749     /// # let mut cursor = unit.entries(&abbrevs);
750     /// # let (_, entry) = cursor.next_dfs().unwrap().unwrap();
751     /// # let mut get_some_entry = || entry;
752     /// let entry = get_some_entry();
753     ///
754     /// match entry.tag() {
755     ///     gimli::DW_TAG_subprogram =>
756     ///         println!("this entry contains debug info about a function"),
757     ///     gimli::DW_TAG_inlined_subroutine =>
758     ///         println!("this entry contains debug info about a particular instance of inlining"),
759     ///     gimli::DW_TAG_variable =>
760     ///         println!("this entry contains debug info about a local variable"),
761     ///     gimli::DW_TAG_formal_parameter =>
762     ///         println!("this entry contains debug info about a function parameter"),
763     ///     otherwise =>
764     ///         println!("this entry is some other kind of data: {:?}", otherwise),
765     /// };
766     /// ```
tag(&self) -> constants::DwTag767     pub fn tag(&self) -> constants::DwTag {
768         self.abbrev.tag()
769     }
770 
771     /// Return true if this entry's type can have children, false otherwise.
has_children(&self) -> bool772     pub fn has_children(&self) -> bool {
773         self.abbrev.has_children()
774     }
775 
776     /// Iterate over this entry's set of attributes.
777     ///
778     /// ```
779     /// use gimli::{DebugAbbrev, DebugInfo, LittleEndian};
780     ///
781     /// // Read the `.debug_info` section.
782     ///
783     /// # let info_buf = [
784     /// #     // Comilation unit header
785     /// #
786     /// #     // 32-bit unit length = 12
787     /// #     0x0c, 0x00, 0x00, 0x00,
788     /// #     // Version 4
789     /// #     0x04, 0x00,
790     /// #     // debug_abbrev_offset
791     /// #     0x00, 0x00, 0x00, 0x00,
792     /// #     // Address size
793     /// #     0x04,
794     /// #
795     /// #     // DIEs
796     /// #
797     /// #     // Abbreviation code
798     /// #     0x01,
799     /// #     // Attribute of form DW_FORM_string = "foo\0"
800     /// #     0x66, 0x6f, 0x6f, 0x00,
801     /// # ];
802     /// # let read_debug_info_section_somehow = || &info_buf;
803     /// let debug_info = DebugInfo::new(read_debug_info_section_somehow(), LittleEndian);
804     ///
805     /// // Get the data about the first compilation unit out of the `.debug_info`.
806     ///
807     /// let unit = debug_info.units().next()
808     ///     .expect("Should have at least one compilation unit")
809     ///     .expect("and it should parse ok");
810     ///
811     /// // Read the `.debug_abbrev` section and parse the
812     /// // abbreviations for our compilation unit.
813     ///
814     /// # let abbrev_buf = [
815     /// #     // Code
816     /// #     0x01,
817     /// #     // DW_TAG_subprogram
818     /// #     0x2e,
819     /// #     // DW_CHILDREN_no
820     /// #     0x00,
821     /// #     // Begin attributes
822     /// #       // Attribute name = DW_AT_name
823     /// #       0x03,
824     /// #       // Attribute form = DW_FORM_string
825     /// #       0x08,
826     /// #     // End attributes
827     /// #     0x00,
828     /// #     0x00,
829     /// #     // Null terminator
830     /// #     0x00
831     /// # ];
832     /// # let read_debug_abbrev_section_somehow = || &abbrev_buf;
833     /// let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian);
834     /// let abbrevs = unit.abbreviations(&debug_abbrev).unwrap();
835     ///
836     /// // Get the first entry from that compilation unit.
837     ///
838     /// let mut cursor = unit.entries(&abbrevs);
839     /// let (_, entry) = cursor.next_dfs()
840     ///     .expect("Should parse next entry")
841     ///     .expect("Should have at least one entry");
842     ///
843     /// // Finally, print the first entry's attributes.
844     ///
845     /// let mut attrs = entry.attrs();
846     /// while let Some(attr) = attrs.next().unwrap() {
847     ///     println!("Attribute name = {:?}", attr.name());
848     ///     println!("Attribute value = {:?}", attr.value());
849     /// }
850     /// ```
851     ///
852     /// Can be [used with
853     /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
attrs<'me>(&'me self) -> AttrsIter<'abbrev, 'me, 'unit, R>854     pub fn attrs<'me>(&'me self) -> AttrsIter<'abbrev, 'me, 'unit, R> {
855         AttrsIter {
856             input: self.attrs_slice.clone(),
857             attributes: self.abbrev.attributes(),
858             entry: self,
859         }
860     }
861 
862     /// Find the first attribute in this entry which has the given name,
863     /// and return it. Returns `Ok(None)` if no attribute is found.
attr(&self, name: constants::DwAt) -> Result<Option<Attribute<R>>>864     pub fn attr(&self, name: constants::DwAt) -> Result<Option<Attribute<R>>> {
865         let mut attrs = self.attrs();
866         while let Some(attr) = attrs.next()? {
867             if attr.name() == name {
868                 return Ok(Some(attr));
869             }
870         }
871         Ok(None)
872     }
873 
874     /// Find the first attribute in this entry which has the given name,
875     /// and return its raw value. Returns `Ok(None)` if no attribute is found.
attr_value_raw(&self, name: constants::DwAt) -> Result<Option<AttributeValue<R>>>876     pub fn attr_value_raw(&self, name: constants::DwAt) -> Result<Option<AttributeValue<R>>> {
877         self.attr(name)
878             .map(|attr| attr.map(|attr| attr.raw_value()))
879     }
880 
881     /// Find the first attribute in this entry which has the given name,
882     /// and return its normalized value.  Returns `Ok(None)` if no
883     /// attribute is found.
attr_value(&self, name: constants::DwAt) -> Result<Option<AttributeValue<R>>>884     pub fn attr_value(&self, name: constants::DwAt) -> Result<Option<AttributeValue<R>>> {
885         self.attr(name).map(|attr| attr.map(|attr| attr.value()))
886     }
887 
888     /// Return the input buffer after the last attribute.
889     #[allow(clippy::inline_always)]
890     #[inline(always)]
after_attrs(&self) -> Result<R>891     fn after_attrs(&self) -> Result<R> {
892         if let Some(attrs_len) = self.attrs_len.get() {
893             let mut input = self.attrs_slice.clone();
894             input.skip(attrs_len)?;
895             Ok(input)
896         } else {
897             let mut attrs = self.attrs();
898             while let Some(_) = attrs.next()? {}
899             Ok(attrs.input)
900         }
901     }
902 
903     /// Use the `DW_AT_sibling` attribute to find the input buffer for the
904     /// next sibling. Returns `None` if the attribute is missing or invalid.
sibling(&self) -> Option<R>905     fn sibling(&self) -> Option<R> {
906         let attr = self.attr_value(constants::DW_AT_sibling);
907         if let Ok(Some(AttributeValue::UnitRef(offset))) = attr {
908             if offset.0 > self.offset.0 {
909                 if let Ok(input) = self.unit.range_from(offset..) {
910                     return Some(input);
911                 }
912             }
913         }
914         None
915     }
916 
917     /// Parse an entry. Returns `Ok(None)` for null entries.
918     #[allow(clippy::inline_always)]
919     #[inline(always)]
parse( input: &mut R, unit: &'unit UnitHeader<R>, abbreviations: &'abbrev Abbreviations, ) -> Result<Option<Self>>920     fn parse(
921         input: &mut R,
922         unit: &'unit UnitHeader<R>,
923         abbreviations: &'abbrev Abbreviations,
924     ) -> Result<Option<Self>> {
925         let offset = unit.header_size() + input.offset_from(&unit.entries_buf);
926         let code = input.read_uleb128()?;
927         if code == 0 {
928             return Ok(None);
929         };
930         let abbrev = abbreviations.get(code).ok_or(Error::UnknownAbbreviation)?;
931         Ok(Some(DebuggingInformationEntry {
932             offset: UnitOffset(offset),
933             attrs_slice: input.clone(),
934             attrs_len: Cell::new(None),
935             abbrev,
936             unit,
937         }))
938     }
939 }
940 
941 /// The value of an attribute in a `DebuggingInformationEntry`.
942 //
943 // Set the discriminant size so that all variants use the same alignment
944 // for their data.  This gives better code generation in `parse_attribute`.
945 #[repr(u64)]
946 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
947 pub enum AttributeValue<R, Offset = <R as Reader>::Offset>
948 where
949     R: Reader<Offset = Offset>,
950     Offset: ReaderOffset,
951 {
952     /// "Refers to some location in the address space of the described program."
953     Addr(u64),
954 
955     /// A slice of an arbitrary number of bytes.
956     Block(R),
957 
958     /// A one byte constant data value. How to interpret the byte depends on context.
959     ///
960     /// From section 7 of the standard: "Depending on context, it may be a
961     /// signed integer, an unsigned integer, a floating-point constant, or
962     /// anything else."
963     Data1(u8),
964 
965     /// A two byte constant data value. How to interpret the bytes depends on context.
966     ///
967     /// These bytes have been converted from `R::Endian`. This may need to be reversed
968     /// if this was not required.
969     ///
970     /// From section 7 of the standard: "Depending on context, it may be a
971     /// signed integer, an unsigned integer, a floating-point constant, or
972     /// anything else."
973     Data2(u16),
974 
975     /// A four byte constant data value. How to interpret the bytes depends on context.
976     ///
977     /// These bytes have been converted from `R::Endian`. This may need to be reversed
978     /// if this was not required.
979     ///
980     /// From section 7 of the standard: "Depending on context, it may be a
981     /// signed integer, an unsigned integer, a floating-point constant, or
982     /// anything else."
983     Data4(u32),
984 
985     /// An eight byte constant data value. How to interpret the bytes depends on context.
986     ///
987     /// These bytes have been converted from `R::Endian`. This may need to be reversed
988     /// if this was not required.
989     ///
990     /// From section 7 of the standard: "Depending on context, it may be a
991     /// signed integer, an unsigned integer, a floating-point constant, or
992     /// anything else."
993     Data8(u64),
994 
995     /// A signed integer constant.
996     Sdata(i64),
997 
998     /// An unsigned integer constant.
999     Udata(u64),
1000 
1001     /// "The information bytes contain a DWARF expression (see Section 2.5) or
1002     /// location description (see Section 2.6)."
1003     Exprloc(Expression<R>),
1004 
1005     /// A boolean that indicates presence or absence of the attribute.
1006     Flag(bool),
1007 
1008     /// An offset into another section. Which section this is an offset into
1009     /// depends on context.
1010     SecOffset(Offset),
1011 
1012     /// An offset to a set of addresses in the `.debug_addr` section.
1013     DebugAddrBase(DebugAddrBase<Offset>),
1014 
1015     /// An index into a set of addresses in the `.debug_addr` section.
1016     DebugAddrIndex(DebugAddrIndex<Offset>),
1017 
1018     /// An offset into the current compilation unit.
1019     UnitRef(UnitOffset<Offset>),
1020 
1021     /// An offset into the current `.debug_info` section, but possibly a
1022     /// different compilation unit from the current one.
1023     DebugInfoRef(DebugInfoOffset<Offset>),
1024 
1025     /// An offset into the `.debug_info` section of the supplementary object file.
1026     DebugInfoRefSup(DebugInfoOffset<Offset>),
1027 
1028     /// An offset into the `.debug_line` section.
1029     DebugLineRef(DebugLineOffset<Offset>),
1030 
1031     /// An offset into either the `.debug_loc` section or the `.debug_loclists` section.
1032     LocationListsRef(LocationListsOffset<Offset>),
1033 
1034     /// An offset to a set of offsets in the `.debug_loclists` section.
1035     DebugLocListsBase(DebugLocListsBase<Offset>),
1036 
1037     /// An index into a set of offsets in the `.debug_loclists` section.
1038     DebugLocListsIndex(DebugLocListsIndex<Offset>),
1039 
1040     /// An offset into the `.debug_macinfo` section.
1041     DebugMacinfoRef(DebugMacinfoOffset<Offset>),
1042 
1043     /// An offset into the `.debug_macro` section.
1044     DebugMacroRef(DebugMacroOffset<Offset>),
1045 
1046     /// An offset into the `.debug_ranges` section.
1047     RangeListsRef(RangeListsOffset<Offset>),
1048 
1049     /// An offset to a set of offsets in the `.debug_rnglists` section.
1050     DebugRngListsBase(DebugRngListsBase<Offset>),
1051 
1052     /// An index into a set of offsets in the `.debug_rnglists` section.
1053     DebugRngListsIndex(DebugRngListsIndex<Offset>),
1054 
1055     /// A type signature.
1056     DebugTypesRef(DebugTypeSignature),
1057 
1058     /// An offset into the `.debug_str` section.
1059     DebugStrRef(DebugStrOffset<Offset>),
1060 
1061     /// An offset into the `.debug_str` section of the supplementary object file.
1062     DebugStrRefSup(DebugStrOffset<Offset>),
1063 
1064     /// An offset to a set of entries in the `.debug_str_offsets` section.
1065     DebugStrOffsetsBase(DebugStrOffsetsBase<Offset>),
1066 
1067     /// An index into a set of entries in the `.debug_str_offsets` section.
1068     DebugStrOffsetsIndex(DebugStrOffsetsIndex<Offset>),
1069 
1070     /// An offset into the `.debug_line_str` section.
1071     DebugLineStrRef(DebugLineStrOffset<Offset>),
1072 
1073     /// A slice of bytes representing a string. Does not include a final null byte.
1074     /// Not guaranteed to be UTF-8 or anything like that.
1075     String(R),
1076 
1077     /// The value of a `DW_AT_encoding` attribute.
1078     Encoding(constants::DwAte),
1079 
1080     /// The value of a `DW_AT_decimal_sign` attribute.
1081     DecimalSign(constants::DwDs),
1082 
1083     /// The value of a `DW_AT_endianity` attribute.
1084     Endianity(constants::DwEnd),
1085 
1086     /// The value of a `DW_AT_accessibility` attribute.
1087     Accessibility(constants::DwAccess),
1088 
1089     /// The value of a `DW_AT_visibility` attribute.
1090     Visibility(constants::DwVis),
1091 
1092     /// The value of a `DW_AT_virtuality` attribute.
1093     Virtuality(constants::DwVirtuality),
1094 
1095     /// The value of a `DW_AT_language` attribute.
1096     Language(constants::DwLang),
1097 
1098     /// The value of a `DW_AT_address_class` attribute.
1099     AddressClass(constants::DwAddr),
1100 
1101     /// The value of a `DW_AT_identifier_case` attribute.
1102     IdentifierCase(constants::DwId),
1103 
1104     /// The value of a `DW_AT_calling_convention` attribute.
1105     CallingConvention(constants::DwCc),
1106 
1107     /// The value of a `DW_AT_inline` attribute.
1108     Inline(constants::DwInl),
1109 
1110     /// The value of a `DW_AT_ordering` attribute.
1111     Ordering(constants::DwOrd),
1112 
1113     /// An index into the filename entries from the line number information
1114     /// table for the compilation unit containing this value.
1115     FileIndex(u64),
1116 
1117     /// An implementation-defined identifier uniquely identifying a compilation
1118     /// unit.
1119     DwoId(DwoId),
1120 }
1121 
1122 /// An attribute in a `DebuggingInformationEntry`, consisting of a name and
1123 /// associated value.
1124 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
1125 pub struct Attribute<R: Reader> {
1126     name: constants::DwAt,
1127     value: AttributeValue<R>,
1128 }
1129 
1130 impl<R: Reader> Attribute<R> {
1131     /// Get this attribute's name.
name(&self) -> constants::DwAt1132     pub fn name(&self) -> constants::DwAt {
1133         self.name
1134     }
1135 
1136     /// Get this attribute's raw value.
raw_value(&self) -> AttributeValue<R>1137     pub fn raw_value(&self) -> AttributeValue<R> {
1138         self.value.clone()
1139     }
1140 
1141     /// Get this attribute's normalized value.
1142     ///
1143     /// Attribute values can potentially be encoded in multiple equivalent forms,
1144     /// and may have special meaning depending on the attribute name.  This method
1145     /// converts the attribute value to a normalized form based on the attribute
1146     /// name.
1147     ///
1148     /// See "Table 7.5: Attribute encodings" and "Table 7.6: Attribute form encodings".
1149     #[allow(clippy::cyclomatic_complexity)]
1150     #[allow(clippy::match_same_arms)]
value(&self) -> AttributeValue<R>1151     pub fn value(&self) -> AttributeValue<R> {
1152         // Table 7.5 shows the possible attribute classes for each name.
1153         // Table 7.6 shows the possible attribute classes for each form.
1154         // For each attribute name, we need to match on the form, and
1155         // convert it to one of the classes that is allowed for both
1156         // the name and the form.
1157         //
1158         // The individual class conversions rarely vary for each name,
1159         // so for each class conversion we define a macro that matches
1160         // on the allowed forms for that class.
1161         //
1162         // For some classes, we don't need to do any conversion, so their
1163         // macro is empty.  In the future we may want to fill them in to
1164         // provide strict checking of the forms for each class.  For now,
1165         // they simply provide a way to document the allowed classes for
1166         // each name.
1167 
1168         // DW_FORM_addr
1169         // DW_FORM_addrx
1170         // DW_FORM_addrx1
1171         // DW_FORM_addrx2
1172         // DW_FORM_addrx3
1173         // DW_FORM_addrx4
1174         macro_rules! address {
1175             () => {};
1176         }
1177         // DW_FORM_sec_offset
1178         macro_rules! addrptr {
1179             () => {
1180                 if let Some(offset) = self.offset_value() {
1181                     return AttributeValue::DebugAddrBase(DebugAddrBase(offset));
1182                 }
1183             };
1184         }
1185         // DW_FORM_block
1186         // DW_FORM_block1
1187         // DW_FORM_block2
1188         // DW_FORM_block4
1189         macro_rules! block {
1190             () => {};
1191         }
1192         // DW_FORM_sdata
1193         // DW_FORM_udata
1194         // DW_FORM_data1
1195         // DW_FORM_data2
1196         // DW_FORM_data4
1197         // DW_FORM_data8
1198         // DW_FORM_data16
1199         // DW_FORM_implicit_const
1200         macro_rules! constant {
1201             ($value:ident, $variant:ident) => {
1202                 if let Some(value) = self.$value() {
1203                     return AttributeValue::$variant(value);
1204                 }
1205             };
1206             ($value:ident, $variant:ident, $constant:ident) => {
1207                 if let Some(value) = self.$value() {
1208                     return AttributeValue::$variant(constants::$constant(value));
1209                 }
1210             };
1211         }
1212         // DW_FORM_exprloc
1213         macro_rules! exprloc {
1214             () => {
1215                 if let Some(value) = self.exprloc_value() {
1216                     return AttributeValue::Exprloc(value);
1217                 }
1218             };
1219         }
1220         // DW_FORM_flag
1221         // DW_FORM_flag_present
1222         macro_rules! flag {
1223             () => {};
1224         }
1225         // DW_FORM_sec_offset
1226         macro_rules! lineptr {
1227             () => {
1228                 if let Some(offset) = self.offset_value() {
1229                     return AttributeValue::DebugLineRef(DebugLineOffset(offset));
1230                 }
1231             };
1232         }
1233         // This also covers `loclist` in DWARF version 5.
1234         // DW_FORM_sec_offset
1235         // DW_FORM_loclistx
1236         macro_rules! loclistptr {
1237             () => {
1238                 // DebugLocListsIndex is also an allowed form in DWARF version 5.
1239                 if let Some(offset) = self.offset_value() {
1240                     return AttributeValue::LocationListsRef(LocationListsOffset(offset));
1241                 }
1242             };
1243         }
1244         // DW_FORM_sec_offset
1245         macro_rules! loclistsptr {
1246             () => {
1247                 if let Some(offset) = self.offset_value() {
1248                     return AttributeValue::DebugLocListsBase(DebugLocListsBase(offset));
1249                 }
1250             };
1251         }
1252         // DWARF version <= 4.
1253         // DW_FORM_sec_offset
1254         macro_rules! macinfoptr {
1255             () => {
1256                 if let Some(offset) = self.offset_value() {
1257                     return AttributeValue::DebugMacinfoRef(DebugMacinfoOffset(offset));
1258                 }
1259             };
1260         }
1261         // DWARF version >= 5.
1262         // DW_FORM_sec_offset
1263         macro_rules! macroptr {
1264             () => {
1265                 if let Some(offset) = self.offset_value() {
1266                     return AttributeValue::DebugMacroRef(DebugMacroOffset(offset));
1267                 }
1268             };
1269         }
1270         // DW_FORM_ref_addr
1271         // DW_FORM_ref1
1272         // DW_FORM_ref2
1273         // DW_FORM_ref4
1274         // DW_FORM_ref8
1275         // DW_FORM_ref_udata
1276         // DW_FORM_ref_sig8
1277         // DW_FORM_ref_sup4
1278         // DW_FORM_ref_sup8
1279         macro_rules! reference {
1280             () => {};
1281         }
1282         // This also covers `rnglist` in DWARF version 5.
1283         // DW_FORM_sec_offset
1284         // DW_FORM_rnglistx
1285         macro_rules! rangelistptr {
1286             () => {
1287                 // DebugRngListsIndex is also an allowed form in DWARF version 5.
1288                 if let Some(offset) = self.offset_value() {
1289                     return AttributeValue::RangeListsRef(RangeListsOffset(offset));
1290                 }
1291             };
1292         }
1293         // DW_FORM_sec_offset
1294         macro_rules! rnglistsptr {
1295             () => {
1296                 if let Some(offset) = self.offset_value() {
1297                     return AttributeValue::DebugRngListsBase(DebugRngListsBase(offset));
1298                 }
1299             };
1300         }
1301         // DW_FORM_string
1302         // DW_FORM_strp
1303         // DW_FORM_strx
1304         // DW_FORM_strx1
1305         // DW_FORM_strx2
1306         // DW_FORM_strx3
1307         // DW_FORM_strx4
1308         // DW_FORM_strp_sup
1309         // DW_FORM_line_strp
1310         macro_rules! string {
1311             () => {};
1312         }
1313         // DW_FORM_sec_offset
1314         macro_rules! stroffsetsptr {
1315             () => {
1316                 if let Some(offset) = self.offset_value() {
1317                     return AttributeValue::DebugStrOffsetsBase(DebugStrOffsetsBase(offset));
1318                 }
1319             };
1320         }
1321         // This isn't a separate form but it's useful to distinguish it from a generic udata.
1322         macro_rules! dwoid {
1323             () => {
1324                 if let Some(value) = self.udata_value() {
1325                     return AttributeValue::DwoId(DwoId(value));
1326                 }
1327             };
1328         }
1329 
1330         // Perform the allowed class conversions for each attribute name.
1331         match self.name {
1332             constants::DW_AT_sibling => {
1333                 reference!();
1334             }
1335             constants::DW_AT_location => {
1336                 exprloc!();
1337                 loclistptr!();
1338             }
1339             constants::DW_AT_name => {
1340                 string!();
1341             }
1342             constants::DW_AT_ordering => {
1343                 constant!(u8_value, Ordering, DwOrd);
1344             }
1345             constants::DW_AT_byte_size
1346             | constants::DW_AT_bit_offset
1347             | constants::DW_AT_bit_size => {
1348                 constant!(udata_value, Udata);
1349                 exprloc!();
1350                 reference!();
1351             }
1352             constants::DW_AT_stmt_list => {
1353                 lineptr!();
1354             }
1355             constants::DW_AT_low_pc => {
1356                 address!();
1357             }
1358             constants::DW_AT_high_pc => {
1359                 address!();
1360                 constant!(udata_value, Udata);
1361             }
1362             constants::DW_AT_language => {
1363                 constant!(u16_value, Language, DwLang);
1364             }
1365             constants::DW_AT_discr => {
1366                 reference!();
1367             }
1368             constants::DW_AT_discr_value => {
1369                 // constant: depends on type of DW_TAG_variant_part,
1370                 // so caller must normalize.
1371             }
1372             constants::DW_AT_visibility => {
1373                 constant!(u8_value, Visibility, DwVis);
1374             }
1375             constants::DW_AT_import => {
1376                 reference!();
1377             }
1378             constants::DW_AT_string_length => {
1379                 exprloc!();
1380                 loclistptr!();
1381                 reference!();
1382             }
1383             constants::DW_AT_common_reference => {
1384                 reference!();
1385             }
1386             constants::DW_AT_comp_dir => {
1387                 string!();
1388             }
1389             constants::DW_AT_const_value => {
1390                 // TODO: constant: sign depends on DW_AT_type.
1391                 block!();
1392                 string!();
1393             }
1394             constants::DW_AT_containing_type => {
1395                 reference!();
1396             }
1397             constants::DW_AT_default_value => {
1398                 // TODO: constant: sign depends on DW_AT_type.
1399                 reference!();
1400                 flag!();
1401             }
1402             constants::DW_AT_inline => {
1403                 constant!(u8_value, Inline, DwInl);
1404             }
1405             constants::DW_AT_is_optional => {
1406                 flag!();
1407             }
1408             constants::DW_AT_lower_bound => {
1409                 // TODO: constant: sign depends on DW_AT_type.
1410                 exprloc!();
1411                 reference!();
1412             }
1413             constants::DW_AT_producer => {
1414                 string!();
1415             }
1416             constants::DW_AT_prototyped => {
1417                 flag!();
1418             }
1419             constants::DW_AT_return_addr => {
1420                 exprloc!();
1421                 loclistptr!();
1422             }
1423             constants::DW_AT_start_scope => {
1424                 // TODO: constant
1425                 rangelistptr!();
1426             }
1427             constants::DW_AT_bit_stride => {
1428                 constant!(udata_value, Udata);
1429                 exprloc!();
1430                 reference!();
1431             }
1432             constants::DW_AT_upper_bound => {
1433                 // TODO: constant: sign depends on DW_AT_type.
1434                 exprloc!();
1435                 reference!();
1436             }
1437             constants::DW_AT_abstract_origin => {
1438                 reference!();
1439             }
1440             constants::DW_AT_accessibility => {
1441                 constant!(u8_value, Accessibility, DwAccess);
1442             }
1443             constants::DW_AT_address_class => {
1444                 constant!(udata_value, AddressClass, DwAddr);
1445             }
1446             constants::DW_AT_artificial => {
1447                 flag!();
1448             }
1449             constants::DW_AT_base_types => {
1450                 reference!();
1451             }
1452             constants::DW_AT_calling_convention => {
1453                 constant!(u8_value, CallingConvention, DwCc);
1454             }
1455             constants::DW_AT_count => {
1456                 // TODO: constant
1457                 exprloc!();
1458                 reference!();
1459             }
1460             constants::DW_AT_data_member_location => {
1461                 // Constants must be handled before loclistptr so that DW_FORM_data4/8
1462                 // are correctly interpreted for DWARF version 4+.
1463                 constant!(udata_value, Udata);
1464                 exprloc!();
1465                 loclistptr!();
1466             }
1467             constants::DW_AT_decl_column => {
1468                 constant!(udata_value, Udata);
1469             }
1470             constants::DW_AT_decl_file => {
1471                 constant!(udata_value, FileIndex);
1472             }
1473             constants::DW_AT_decl_line => {
1474                 constant!(udata_value, Udata);
1475             }
1476             constants::DW_AT_declaration => {
1477                 flag!();
1478             }
1479             constants::DW_AT_discr_list => {
1480                 block!();
1481             }
1482             constants::DW_AT_encoding => {
1483                 constant!(u8_value, Encoding, DwAte);
1484             }
1485             constants::DW_AT_external => {
1486                 flag!();
1487             }
1488             constants::DW_AT_frame_base => {
1489                 exprloc!();
1490                 loclistptr!();
1491             }
1492             constants::DW_AT_friend => {
1493                 reference!();
1494             }
1495             constants::DW_AT_identifier_case => {
1496                 constant!(u8_value, IdentifierCase, DwId);
1497             }
1498             constants::DW_AT_macro_info => {
1499                 macinfoptr!();
1500             }
1501             constants::DW_AT_namelist_item => {
1502                 reference!();
1503             }
1504             constants::DW_AT_priority => {
1505                 reference!();
1506             }
1507             constants::DW_AT_segment => {
1508                 exprloc!();
1509                 loclistptr!();
1510             }
1511             constants::DW_AT_specification => {
1512                 reference!();
1513             }
1514             constants::DW_AT_static_link => {
1515                 exprloc!();
1516                 loclistptr!();
1517             }
1518             constants::DW_AT_type => {
1519                 reference!();
1520             }
1521             constants::DW_AT_use_location => {
1522                 exprloc!();
1523                 loclistptr!();
1524             }
1525             constants::DW_AT_variable_parameter => {
1526                 flag!();
1527             }
1528             constants::DW_AT_virtuality => {
1529                 constant!(u8_value, Virtuality, DwVirtuality);
1530             }
1531             constants::DW_AT_vtable_elem_location => {
1532                 exprloc!();
1533                 loclistptr!();
1534             }
1535             constants::DW_AT_allocated => {
1536                 // TODO: constant
1537                 exprloc!();
1538                 reference!();
1539             }
1540             constants::DW_AT_associated => {
1541                 // TODO: constant
1542                 exprloc!();
1543                 reference!();
1544             }
1545             constants::DW_AT_data_location => {
1546                 exprloc!();
1547             }
1548             constants::DW_AT_byte_stride => {
1549                 constant!(udata_value, Udata);
1550                 exprloc!();
1551                 reference!();
1552             }
1553             constants::DW_AT_entry_pc => {
1554                 // TODO: constant
1555                 address!();
1556             }
1557             constants::DW_AT_use_UTF8 => {
1558                 flag!();
1559             }
1560             constants::DW_AT_extension => {
1561                 reference!();
1562             }
1563             constants::DW_AT_ranges => {
1564                 rangelistptr!();
1565             }
1566             constants::DW_AT_trampoline => {
1567                 address!();
1568                 flag!();
1569                 reference!();
1570                 string!();
1571             }
1572             constants::DW_AT_call_column => {
1573                 constant!(udata_value, Udata);
1574             }
1575             constants::DW_AT_call_file => {
1576                 constant!(udata_value, FileIndex);
1577             }
1578             constants::DW_AT_call_line => {
1579                 constant!(udata_value, Udata);
1580             }
1581             constants::DW_AT_description => {
1582                 string!();
1583             }
1584             constants::DW_AT_binary_scale => {
1585                 // TODO: constant
1586             }
1587             constants::DW_AT_decimal_scale => {
1588                 // TODO: constant
1589             }
1590             constants::DW_AT_small => {
1591                 reference!();
1592             }
1593             constants::DW_AT_decimal_sign => {
1594                 constant!(u8_value, DecimalSign, DwDs);
1595             }
1596             constants::DW_AT_digit_count => {
1597                 // TODO: constant
1598             }
1599             constants::DW_AT_picture_string => {
1600                 string!();
1601             }
1602             constants::DW_AT_mutable => {
1603                 flag!();
1604             }
1605             constants::DW_AT_threads_scaled => {
1606                 flag!();
1607             }
1608             constants::DW_AT_explicit => {
1609                 flag!();
1610             }
1611             constants::DW_AT_object_pointer => {
1612                 reference!();
1613             }
1614             constants::DW_AT_endianity => {
1615                 constant!(u8_value, Endianity, DwEnd);
1616             }
1617             constants::DW_AT_elemental => {
1618                 flag!();
1619             }
1620             constants::DW_AT_pure => {
1621                 flag!();
1622             }
1623             constants::DW_AT_recursive => {
1624                 flag!();
1625             }
1626             constants::DW_AT_signature => {
1627                 reference!();
1628             }
1629             constants::DW_AT_main_subprogram => {
1630                 flag!();
1631             }
1632             constants::DW_AT_data_bit_offset => {
1633                 // TODO: constant
1634             }
1635             constants::DW_AT_const_expr => {
1636                 flag!();
1637             }
1638             constants::DW_AT_enum_class => {
1639                 flag!();
1640             }
1641             constants::DW_AT_linkage_name => {
1642                 string!();
1643             }
1644             constants::DW_AT_string_length_bit_size => {
1645                 // TODO: constant
1646             }
1647             constants::DW_AT_string_length_byte_size => {
1648                 // TODO: constant
1649             }
1650             constants::DW_AT_rank => {
1651                 // TODO: constant
1652                 exprloc!();
1653             }
1654             constants::DW_AT_str_offsets_base => {
1655                 stroffsetsptr!();
1656             }
1657             constants::DW_AT_addr_base | constants::DW_AT_GNU_addr_base => {
1658                 addrptr!();
1659             }
1660             constants::DW_AT_rnglists_base | constants::DW_AT_GNU_ranges_base => {
1661                 rnglistsptr!();
1662             }
1663             constants::DW_AT_dwo_name => {
1664                 string!();
1665             }
1666             constants::DW_AT_reference => {
1667                 flag!();
1668             }
1669             constants::DW_AT_rvalue_reference => {
1670                 flag!();
1671             }
1672             constants::DW_AT_macros => {
1673                 macroptr!();
1674             }
1675             constants::DW_AT_call_all_calls => {
1676                 flag!();
1677             }
1678             constants::DW_AT_call_all_source_calls => {
1679                 flag!();
1680             }
1681             constants::DW_AT_call_all_tail_calls => {
1682                 flag!();
1683             }
1684             constants::DW_AT_call_return_pc => {
1685                 address!();
1686             }
1687             constants::DW_AT_call_value => {
1688                 exprloc!();
1689             }
1690             constants::DW_AT_call_origin => {
1691                 exprloc!();
1692             }
1693             constants::DW_AT_call_parameter => {
1694                 reference!();
1695             }
1696             constants::DW_AT_call_pc => {
1697                 address!();
1698             }
1699             constants::DW_AT_call_tail_call => {
1700                 flag!();
1701             }
1702             constants::DW_AT_call_target => {
1703                 exprloc!();
1704             }
1705             constants::DW_AT_call_target_clobbered => {
1706                 exprloc!();
1707             }
1708             constants::DW_AT_call_data_location => {
1709                 exprloc!();
1710             }
1711             constants::DW_AT_call_data_value => {
1712                 exprloc!();
1713             }
1714             constants::DW_AT_noreturn => {
1715                 flag!();
1716             }
1717             constants::DW_AT_alignment => {
1718                 // TODO: constant
1719             }
1720             constants::DW_AT_export_symbols => {
1721                 flag!();
1722             }
1723             constants::DW_AT_deleted => {
1724                 flag!();
1725             }
1726             constants::DW_AT_defaulted => {
1727                 // TODO: constant
1728             }
1729             constants::DW_AT_loclists_base => {
1730                 loclistsptr!();
1731             }
1732             constants::DW_AT_GNU_dwo_id => {
1733                 dwoid!();
1734             }
1735             _ => {}
1736         }
1737         self.value.clone()
1738     }
1739 
1740     /// Try to convert this attribute's value to a u8.
1741     #[inline]
u8_value(&self) -> Option<u8>1742     pub fn u8_value(&self) -> Option<u8> {
1743         self.value.u8_value()
1744     }
1745 
1746     /// Try to convert this attribute's value to a u16.
1747     #[inline]
u16_value(&self) -> Option<u16>1748     pub fn u16_value(&self) -> Option<u16> {
1749         self.value.u16_value()
1750     }
1751 
1752     /// Try to convert this attribute's value to an unsigned integer.
1753     #[inline]
udata_value(&self) -> Option<u64>1754     pub fn udata_value(&self) -> Option<u64> {
1755         self.value.udata_value()
1756     }
1757 
1758     /// Try to convert this attribute's value to a signed integer.
1759     #[inline]
sdata_value(&self) -> Option<i64>1760     pub fn sdata_value(&self) -> Option<i64> {
1761         self.value.sdata_value()
1762     }
1763 
1764     /// Try to convert this attribute's value to an offset.
1765     #[inline]
offset_value(&self) -> Option<R::Offset>1766     pub fn offset_value(&self) -> Option<R::Offset> {
1767         self.value.offset_value()
1768     }
1769 
1770     /// Try to convert this attribute's value to an expression or location buffer.
1771     ///
1772     /// Expressions and locations may be `DW_FORM_block*` or `DW_FORM_exprloc`.
1773     /// The standard doesn't mention `DW_FORM_block*` as a possible form, but
1774     /// it is encountered in practice.
1775     #[inline]
exprloc_value(&self) -> Option<Expression<R>>1776     pub fn exprloc_value(&self) -> Option<Expression<R>> {
1777         self.value.exprloc_value()
1778     }
1779 
1780     /// Try to return this attribute's value as a string slice.
1781     ///
1782     /// If this attribute's value is either an inline `DW_FORM_string` string,
1783     /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
1784     /// section, return the attribute's string value as `Some`. Other attribute
1785     /// value forms are returned as `None`.
1786     ///
1787     /// Warning: this function does not handle all possible string forms.
1788     /// Use `Dwarf::attr_string` instead.
1789     #[inline]
string_value(&self, debug_str: &DebugStr<R>) -> Option<R>1790     pub fn string_value(&self, debug_str: &DebugStr<R>) -> Option<R> {
1791         self.value.string_value(debug_str)
1792     }
1793 
1794     /// Try to return this attribute's value as a string slice.
1795     ///
1796     /// If this attribute's value is either an inline `DW_FORM_string` string,
1797     /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
1798     /// section, or a `DW_FORM_strp_sup` reference to an offset into a supplementary
1799     /// object file, return the attribute's string value as `Some`. Other attribute
1800     /// value forms are returned as `None`.
1801     ///
1802     /// Warning: this function does not handle all possible string forms.
1803     /// Use `Dwarf::attr_string` instead.
1804     #[inline]
string_value_sup( &self, debug_str: &DebugStr<R>, debug_str_sup: Option<&DebugStr<R>>, ) -> Option<R>1805     pub fn string_value_sup(
1806         &self,
1807         debug_str: &DebugStr<R>,
1808         debug_str_sup: Option<&DebugStr<R>>,
1809     ) -> Option<R> {
1810         self.value.string_value_sup(debug_str, debug_str_sup)
1811     }
1812 }
1813 
1814 impl<R, Offset> AttributeValue<R, Offset>
1815 where
1816     R: Reader<Offset = Offset>,
1817     Offset: ReaderOffset,
1818 {
1819     /// Try to convert this attribute's value to a u8.
u8_value(&self) -> Option<u8>1820     pub fn u8_value(&self) -> Option<u8> {
1821         if let Some(value) = self.udata_value() {
1822             if value <= u64::from(u8::MAX) {
1823                 return Some(value as u8);
1824             }
1825         }
1826         None
1827     }
1828 
1829     /// Try to convert this attribute's value to a u16.
u16_value(&self) -> Option<u16>1830     pub fn u16_value(&self) -> Option<u16> {
1831         if let Some(value) = self.udata_value() {
1832             if value <= u64::from(u16::MAX) {
1833                 return Some(value as u16);
1834             }
1835         }
1836         None
1837     }
1838 
1839     /// Try to convert this attribute's value to an unsigned integer.
udata_value(&self) -> Option<u64>1840     pub fn udata_value(&self) -> Option<u64> {
1841         Some(match *self {
1842             AttributeValue::Data1(data) => u64::from(data),
1843             AttributeValue::Data2(data) => u64::from(data),
1844             AttributeValue::Data4(data) => u64::from(data),
1845             AttributeValue::Data8(data) => data,
1846             AttributeValue::Udata(data) => data,
1847             AttributeValue::Sdata(data) => {
1848                 if data < 0 {
1849                     // Maybe we should emit a warning here
1850                     return None;
1851                 }
1852                 data as u64
1853             }
1854             _ => return None,
1855         })
1856     }
1857 
1858     /// Try to convert this attribute's value to a signed integer.
sdata_value(&self) -> Option<i64>1859     pub fn sdata_value(&self) -> Option<i64> {
1860         Some(match *self {
1861             AttributeValue::Data1(data) => i64::from(data as i8),
1862             AttributeValue::Data2(data) => i64::from(data as i16),
1863             AttributeValue::Data4(data) => i64::from(data as i32),
1864             AttributeValue::Data8(data) => data as i64,
1865             AttributeValue::Sdata(data) => data,
1866             AttributeValue::Udata(data) => {
1867                 if data > i64::max_value() as u64 {
1868                     // Maybe we should emit a warning here
1869                     return None;
1870                 }
1871                 data as i64
1872             }
1873             _ => return None,
1874         })
1875     }
1876 
1877     /// Try to convert this attribute's value to an offset.
offset_value(&self) -> Option<R::Offset>1878     pub fn offset_value(&self) -> Option<R::Offset> {
1879         // While offsets will be DW_FORM_data4/8 in DWARF version 2/3,
1880         // these have already been converted to `SecOffset.
1881         if let AttributeValue::SecOffset(offset) = *self {
1882             Some(offset)
1883         } else {
1884             None
1885         }
1886     }
1887 
1888     /// Try to convert this attribute's value to an expression or location buffer.
1889     ///
1890     /// Expressions and locations may be `DW_FORM_block*` or `DW_FORM_exprloc`.
1891     /// The standard doesn't mention `DW_FORM_block*` as a possible form, but
1892     /// it is encountered in practice.
exprloc_value(&self) -> Option<Expression<R>>1893     pub fn exprloc_value(&self) -> Option<Expression<R>> {
1894         Some(match *self {
1895             AttributeValue::Block(ref data) => Expression(data.clone()),
1896             AttributeValue::Exprloc(ref data) => data.clone(),
1897             _ => return None,
1898         })
1899     }
1900 
1901     /// Try to return this attribute's value as a string slice.
1902     ///
1903     /// If this attribute's value is either an inline `DW_FORM_string` string,
1904     /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
1905     /// section, return the attribute's string value as `Some`. Other attribute
1906     /// value forms are returned as `None`.
1907     ///
1908     /// Warning: this function does not handle all possible string forms.
1909     /// Use `Dwarf::attr_string` instead.
string_value(&self, debug_str: &DebugStr<R>) -> Option<R>1910     pub fn string_value(&self, debug_str: &DebugStr<R>) -> Option<R> {
1911         match *self {
1912             AttributeValue::String(ref string) => Some(string.clone()),
1913             AttributeValue::DebugStrRef(offset) => debug_str.get_str(offset).ok(),
1914             _ => None,
1915         }
1916     }
1917 
1918     /// Try to return this attribute's value as a string slice.
1919     ///
1920     /// If this attribute's value is either an inline `DW_FORM_string` string,
1921     /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
1922     /// section, or a `DW_FORM_strp_sup` reference to an offset into a supplementary
1923     /// object file, return the attribute's string value as `Some`. Other attribute
1924     /// value forms are returned as `None`.
1925     ///
1926     /// Warning: this function does not handle all possible string forms.
1927     /// Use `Dwarf::attr_string` instead.
string_value_sup( &self, debug_str: &DebugStr<R>, debug_str_sup: Option<&DebugStr<R>>, ) -> Option<R>1928     pub fn string_value_sup(
1929         &self,
1930         debug_str: &DebugStr<R>,
1931         debug_str_sup: Option<&DebugStr<R>>,
1932     ) -> Option<R> {
1933         match *self {
1934             AttributeValue::String(ref string) => Some(string.clone()),
1935             AttributeValue::DebugStrRef(offset) => debug_str.get_str(offset).ok(),
1936             AttributeValue::DebugStrRefSup(offset) => {
1937                 debug_str_sup.and_then(|s| s.get_str(offset).ok())
1938             }
1939             _ => None,
1940         }
1941     }
1942 }
1943 
length_u8_value<R: Reader>(input: &mut R) -> Result<R>1944 fn length_u8_value<R: Reader>(input: &mut R) -> Result<R> {
1945     let len = input.read_u8().map(R::Offset::from_u8)?;
1946     input.split(len)
1947 }
1948 
length_u16_value<R: Reader>(input: &mut R) -> Result<R>1949 fn length_u16_value<R: Reader>(input: &mut R) -> Result<R> {
1950     let len = input.read_u16().map(R::Offset::from_u16)?;
1951     input.split(len)
1952 }
1953 
length_u32_value<R: Reader>(input: &mut R) -> Result<R>1954 fn length_u32_value<R: Reader>(input: &mut R) -> Result<R> {
1955     let len = input.read_u32().map(R::Offset::from_u32)?;
1956     input.split(len)
1957 }
1958 
length_uleb128_value<R: Reader>(input: &mut R) -> Result<R>1959 fn length_uleb128_value<R: Reader>(input: &mut R) -> Result<R> {
1960     let len = input.read_uleb128().and_then(R::Offset::from_u64)?;
1961     input.split(len)
1962 }
1963 
1964 // Return true if the given `name` can be a section offset in DWARF version 2/3.
1965 // This is required to correctly handle relocations.
allow_section_offset(name: constants::DwAt, version: u16) -> bool1966 fn allow_section_offset(name: constants::DwAt, version: u16) -> bool {
1967     match name {
1968         constants::DW_AT_location
1969         | constants::DW_AT_stmt_list
1970         | constants::DW_AT_string_length
1971         | constants::DW_AT_return_addr
1972         | constants::DW_AT_start_scope
1973         | constants::DW_AT_frame_base
1974         | constants::DW_AT_macro_info
1975         | constants::DW_AT_macros
1976         | constants::DW_AT_segment
1977         | constants::DW_AT_static_link
1978         | constants::DW_AT_use_location
1979         | constants::DW_AT_vtable_elem_location
1980         | constants::DW_AT_ranges => true,
1981         constants::DW_AT_data_member_location => version == 2 || version == 3,
1982         _ => false,
1983     }
1984 }
1985 
parse_attribute<'unit, R: Reader>( input: &mut R, encoding: Encoding, spec: AttributeSpecification, ) -> Result<Attribute<R>>1986 pub(crate) fn parse_attribute<'unit, R: Reader>(
1987     input: &mut R,
1988     encoding: Encoding,
1989     spec: AttributeSpecification,
1990 ) -> Result<Attribute<R>> {
1991     let mut form = spec.form();
1992     loop {
1993         let value = match form {
1994             constants::DW_FORM_indirect => {
1995                 let dynamic_form = input.read_uleb128_u16()?;
1996                 form = constants::DwForm(dynamic_form);
1997                 continue;
1998             }
1999             constants::DW_FORM_addr => {
2000                 let addr = input.read_address(encoding.address_size)?;
2001                 AttributeValue::Addr(addr)
2002             }
2003             constants::DW_FORM_block1 => {
2004                 let block = length_u8_value(input)?;
2005                 AttributeValue::Block(block)
2006             }
2007             constants::DW_FORM_block2 => {
2008                 let block = length_u16_value(input)?;
2009                 AttributeValue::Block(block)
2010             }
2011             constants::DW_FORM_block4 => {
2012                 let block = length_u32_value(input)?;
2013                 AttributeValue::Block(block)
2014             }
2015             constants::DW_FORM_block => {
2016                 let block = length_uleb128_value(input)?;
2017                 AttributeValue::Block(block)
2018             }
2019             constants::DW_FORM_data1 => {
2020                 let data = input.read_u8()?;
2021                 AttributeValue::Data1(data)
2022             }
2023             constants::DW_FORM_data2 => {
2024                 let data = input.read_u16()?;
2025                 AttributeValue::Data2(data)
2026             }
2027             constants::DW_FORM_data4 => {
2028                 // DWARF version 2/3 may use DW_FORM_data4/8 for section offsets.
2029                 // Ensure we handle relocations here.
2030                 if encoding.format == Format::Dwarf32
2031                     && allow_section_offset(spec.name(), encoding.version)
2032                 {
2033                     let offset = input.read_offset(Format::Dwarf32)?;
2034                     AttributeValue::SecOffset(offset)
2035                 } else {
2036                     let data = input.read_u32()?;
2037                     AttributeValue::Data4(data)
2038                 }
2039             }
2040             constants::DW_FORM_data8 => {
2041                 // DWARF version 2/3 may use DW_FORM_data4/8 for section offsets.
2042                 // Ensure we handle relocations here.
2043                 if encoding.format == Format::Dwarf64
2044                     && allow_section_offset(spec.name(), encoding.version)
2045                 {
2046                     let offset = input.read_offset(Format::Dwarf64)?;
2047                     AttributeValue::SecOffset(offset)
2048                 } else {
2049                     let data = input.read_u64()?;
2050                     AttributeValue::Data8(data)
2051                 }
2052             }
2053             constants::DW_FORM_data16 => {
2054                 let block = input.split(R::Offset::from_u8(16))?;
2055                 AttributeValue::Block(block)
2056             }
2057             constants::DW_FORM_udata => {
2058                 let data = input.read_uleb128()?;
2059                 AttributeValue::Udata(data)
2060             }
2061             constants::DW_FORM_sdata => {
2062                 let data = input.read_sleb128()?;
2063                 AttributeValue::Sdata(data)
2064             }
2065             constants::DW_FORM_exprloc => {
2066                 let block = length_uleb128_value(input)?;
2067                 AttributeValue::Exprloc(Expression(block))
2068             }
2069             constants::DW_FORM_flag => {
2070                 let present = input.read_u8()?;
2071                 AttributeValue::Flag(present != 0)
2072             }
2073             constants::DW_FORM_flag_present => {
2074                 // FlagPresent is this weird compile time always true thing that
2075                 // isn't actually present in the serialized DIEs, only in the abbreviation.
2076                 AttributeValue::Flag(true)
2077             }
2078             constants::DW_FORM_sec_offset => {
2079                 let offset = input.read_offset(encoding.format)?;
2080                 AttributeValue::SecOffset(offset)
2081             }
2082             constants::DW_FORM_ref1 => {
2083                 let reference = input.read_u8().map(R::Offset::from_u8)?;
2084                 AttributeValue::UnitRef(UnitOffset(reference))
2085             }
2086             constants::DW_FORM_ref2 => {
2087                 let reference = input.read_u16().map(R::Offset::from_u16)?;
2088                 AttributeValue::UnitRef(UnitOffset(reference))
2089             }
2090             constants::DW_FORM_ref4 => {
2091                 let reference = input.read_u32().map(R::Offset::from_u32)?;
2092                 AttributeValue::UnitRef(UnitOffset(reference))
2093             }
2094             constants::DW_FORM_ref8 => {
2095                 let reference = input.read_u64().and_then(R::Offset::from_u64)?;
2096                 AttributeValue::UnitRef(UnitOffset(reference))
2097             }
2098             constants::DW_FORM_ref_udata => {
2099                 let reference = input.read_uleb128().and_then(R::Offset::from_u64)?;
2100                 AttributeValue::UnitRef(UnitOffset(reference))
2101             }
2102             constants::DW_FORM_ref_addr => {
2103                 // This is an offset, but DWARF version 2 specifies that DW_FORM_ref_addr
2104                 // has the same size as an address on the target system.  This was changed
2105                 // in DWARF version 3.
2106                 let offset = if encoding.version == 2 {
2107                     input.read_sized_offset(encoding.address_size)?
2108                 } else {
2109                     input.read_offset(encoding.format)?
2110                 };
2111                 AttributeValue::DebugInfoRef(DebugInfoOffset(offset))
2112             }
2113             constants::DW_FORM_ref_sig8 => {
2114                 let signature = input.read_u64()?;
2115                 AttributeValue::DebugTypesRef(DebugTypeSignature(signature))
2116             }
2117             constants::DW_FORM_ref_sup4 => {
2118                 let offset = input.read_u32().map(R::Offset::from_u32)?;
2119                 AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
2120             }
2121             constants::DW_FORM_ref_sup8 => {
2122                 let offset = input.read_u64().and_then(R::Offset::from_u64)?;
2123                 AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
2124             }
2125             constants::DW_FORM_GNU_ref_alt => {
2126                 let offset = input.read_offset(encoding.format)?;
2127                 AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
2128             }
2129             constants::DW_FORM_string => {
2130                 let string = input.read_null_terminated_slice()?;
2131                 AttributeValue::String(string)
2132             }
2133             constants::DW_FORM_strp => {
2134                 let offset = input.read_offset(encoding.format)?;
2135                 AttributeValue::DebugStrRef(DebugStrOffset(offset))
2136             }
2137             constants::DW_FORM_strp_sup | constants::DW_FORM_GNU_strp_alt => {
2138                 let offset = input.read_offset(encoding.format)?;
2139                 AttributeValue::DebugStrRefSup(DebugStrOffset(offset))
2140             }
2141             constants::DW_FORM_line_strp => {
2142                 let offset = input.read_offset(encoding.format)?;
2143                 AttributeValue::DebugLineStrRef(DebugLineStrOffset(offset))
2144             }
2145             constants::DW_FORM_implicit_const => {
2146                 let data = spec
2147                     .implicit_const_value()
2148                     .ok_or(Error::InvalidImplicitConst)?;
2149                 AttributeValue::Sdata(data)
2150             }
2151             constants::DW_FORM_strx | constants::DW_FORM_GNU_str_index => {
2152                 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2153                 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2154             }
2155             constants::DW_FORM_strx1 => {
2156                 let index = input.read_u8().map(R::Offset::from_u8)?;
2157                 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2158             }
2159             constants::DW_FORM_strx2 => {
2160                 let index = input.read_u16().map(R::Offset::from_u16)?;
2161                 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2162             }
2163             constants::DW_FORM_strx3 => {
2164                 let index = input.read_uint(3).and_then(R::Offset::from_u64)?;
2165                 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2166             }
2167             constants::DW_FORM_strx4 => {
2168                 let index = input.read_u32().map(R::Offset::from_u32)?;
2169                 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2170             }
2171             constants::DW_FORM_addrx | constants::DW_FORM_GNU_addr_index => {
2172                 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2173                 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2174             }
2175             constants::DW_FORM_addrx1 => {
2176                 let index = input.read_u8().map(R::Offset::from_u8)?;
2177                 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2178             }
2179             constants::DW_FORM_addrx2 => {
2180                 let index = input.read_u16().map(R::Offset::from_u16)?;
2181                 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2182             }
2183             constants::DW_FORM_addrx3 => {
2184                 let index = input.read_uint(3).and_then(R::Offset::from_u64)?;
2185                 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2186             }
2187             constants::DW_FORM_addrx4 => {
2188                 let index = input.read_u32().map(R::Offset::from_u32)?;
2189                 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2190             }
2191             constants::DW_FORM_loclistx => {
2192                 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2193                 AttributeValue::DebugLocListsIndex(DebugLocListsIndex(index))
2194             }
2195             constants::DW_FORM_rnglistx => {
2196                 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2197                 AttributeValue::DebugRngListsIndex(DebugRngListsIndex(index))
2198             }
2199             _ => {
2200                 return Err(Error::UnknownForm);
2201             }
2202         };
2203         let attr = Attribute {
2204             name: spec.name(),
2205             value,
2206         };
2207         return Ok(attr);
2208     }
2209 }
2210 
2211 /// An iterator over a particular entry's attributes.
2212 ///
2213 /// See [the documentation for
2214 /// `DebuggingInformationEntry::attrs()`](./struct.DebuggingInformationEntry.html#method.attrs)
2215 /// for details.
2216 ///
2217 /// Can be [used with
2218 /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
2219 #[derive(Clone, Copy, Debug)]
2220 pub struct AttrsIter<'abbrev, 'entry, 'unit, R: Reader> {
2221     input: R,
2222     attributes: &'abbrev [AttributeSpecification],
2223     entry: &'entry DebuggingInformationEntry<'abbrev, 'unit, R>,
2224 }
2225 
2226 impl<'abbrev, 'entry, 'unit, R: Reader> AttrsIter<'abbrev, 'entry, 'unit, R> {
2227     /// Advance the iterator and return the next attribute.
2228     ///
2229     /// Returns `None` when iteration is finished. If an error
2230     /// occurs while parsing the next attribute, then this error
2231     /// is returned, and all subsequent calls return `None`.
2232     #[allow(clippy::inline_always)]
2233     #[inline(always)]
next(&mut self) -> Result<Option<Attribute<R>>>2234     pub fn next(&mut self) -> Result<Option<Attribute<R>>> {
2235         if self.attributes.is_empty() {
2236             // Now that we have parsed all of the attributes, we know where
2237             // either (1) this entry's children start, if the abbreviation says
2238             // this entry has children; or (2) where this entry's siblings
2239             // begin.
2240             if let Some(end) = self.entry.attrs_len.get() {
2241                 debug_assert_eq!(end, self.input.offset_from(&self.entry.attrs_slice));
2242             } else {
2243                 self.entry
2244                     .attrs_len
2245                     .set(Some(self.input.offset_from(&self.entry.attrs_slice)));
2246             }
2247 
2248             return Ok(None);
2249         }
2250 
2251         let spec = self.attributes[0];
2252         let rest_spec = &self.attributes[1..];
2253         match parse_attribute(&mut self.input, self.entry.unit.encoding(), spec) {
2254             Ok(attr) => {
2255                 self.attributes = rest_spec;
2256                 Ok(Some(attr))
2257             }
2258             Err(e) => {
2259                 self.input.empty();
2260                 Err(e)
2261             }
2262         }
2263     }
2264 }
2265 
2266 #[cfg(feature = "fallible-iterator")]
2267 impl<'abbrev, 'entry, 'unit, R: Reader> fallible_iterator::FallibleIterator
2268     for AttrsIter<'abbrev, 'entry, 'unit, R>
2269 {
2270     type Item = Attribute<R>;
2271     type Error = Error;
2272 
next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error>2273     fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
2274         AttrsIter::next(self)
2275     }
2276 }
2277 
2278 /// A raw reader of the data that defines the Debugging Information Entries.
2279 ///
2280 /// `EntriesRaw` provides primitives to read the components of Debugging Information
2281 /// Entries (DIEs). A DIE consists of an abbreviation code (read with `read_abbreviation`)
2282 /// followed by a number of attributes (read with `read_attribute`).
2283 /// The user must provide the control flow to read these correctly.
2284 /// In particular, all attributes must always be read before reading another
2285 /// abbreviation code.
2286 ///
2287 /// `EntriesRaw` lacks some features of `EntriesCursor`, such as the ability to skip
2288 /// to the next sibling DIE. However, this also allows it to optimize better, since it
2289 /// does not need to perform the extra bookkeeping required to support these features,
2290 /// and thus it is suitable for cases where performance is important.
2291 ///
2292 /// ## Example Usage
2293 /// ```rust,no_run
2294 /// # fn example() -> Result<(), gimli::Error> {
2295 /// # let debug_info = gimli::DebugInfo::new(&[], gimli::LittleEndian);
2296 /// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
2297 /// let unit = get_some_unit();
2298 /// # let debug_abbrev = gimli::DebugAbbrev::new(&[], gimli::LittleEndian);
2299 /// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
2300 /// let abbrevs = get_abbrevs_for_unit(&unit);
2301 ///
2302 /// let mut entries = unit.entries_raw(&abbrevs, None)?;
2303 /// while !entries.is_empty() {
2304 ///     let abbrev = if let Some(abbrev) = entries.read_abbreviation()? {
2305 ///         abbrev
2306 ///     } else {
2307 ///         // Null entry with no attributes.
2308 ///         continue
2309 ///     };
2310 ///     match abbrev.tag() {
2311 ///         gimli::DW_TAG_subprogram => {
2312 ///             // Loop over attributes for DIEs we care about.
2313 ///             for spec in abbrev.attributes() {
2314 ///                 let attr = entries.read_attribute(*spec)?;
2315 ///                 match attr.name() {
2316 ///                     // Handle attributes.
2317 ///                     _ => {}
2318 ///                 }
2319 ///             }
2320 ///         }
2321 ///         _ => {
2322 ///             // Skip attributes for DIEs we don't care about.
2323 ///             for spec in abbrev.attributes() {
2324 ///                 entries.read_attribute(*spec)?;
2325 ///             }
2326 ///         }
2327 ///     }
2328 /// }
2329 /// # unreachable!()
2330 /// # }
2331 /// ```
2332 #[derive(Clone, Debug)]
2333 pub struct EntriesRaw<'abbrev, 'unit, R>
2334 where
2335     R: Reader,
2336 {
2337     input: R,
2338     unit: &'unit UnitHeader<R>,
2339     abbreviations: &'abbrev Abbreviations,
2340     depth: isize,
2341 }
2342 
2343 impl<'abbrev, 'unit, R: Reader> EntriesRaw<'abbrev, 'unit, R> {
2344     /// Return true if there is no more input.
2345     #[inline]
is_empty(&self) -> bool2346     pub fn is_empty(&self) -> bool {
2347         self.input.is_empty()
2348     }
2349 
2350     /// Return the unit offset at which the reader will read next.
2351     ///
2352     /// If you want the offset of the next entry, then this must be called prior to reading
2353     /// the next entry.
next_offset(&self) -> UnitOffset<R::Offset>2354     pub fn next_offset(&self) -> UnitOffset<R::Offset> {
2355         UnitOffset(self.unit.header_size() + self.input.offset_from(&self.unit.entries_buf))
2356     }
2357 
2358     /// Return the depth of the next entry.
2359     ///
2360     /// This depth is updated when `read_abbreviation` is called, and is updated
2361     /// based on null entries and the `has_children` field in the abbreviation.
2362     #[inline]
next_depth(&self) -> isize2363     pub fn next_depth(&self) -> isize {
2364         self.depth
2365     }
2366 
2367     /// Read an abbreviation code and lookup the corresponding `Abbreviation`.
2368     ///
2369     /// Returns `Ok(None)` for null entries.
2370     #[inline]
read_abbreviation(&mut self) -> Result<Option<&'abbrev Abbreviation>>2371     pub fn read_abbreviation(&mut self) -> Result<Option<&'abbrev Abbreviation>> {
2372         let code = self.input.read_uleb128()?;
2373         if code == 0 {
2374             self.depth -= 1;
2375             return Ok(None);
2376         };
2377         let abbrev = self
2378             .abbreviations
2379             .get(code)
2380             .ok_or(Error::UnknownAbbreviation)?;
2381         if abbrev.has_children() {
2382             self.depth += 1;
2383         }
2384         Ok(Some(abbrev))
2385     }
2386 
2387     /// Read an attribute.
2388     #[inline]
read_attribute(&mut self, spec: AttributeSpecification) -> Result<Attribute<R>>2389     pub fn read_attribute(&mut self, spec: AttributeSpecification) -> Result<Attribute<R>> {
2390         parse_attribute(&mut self.input, self.unit.encoding(), spec)
2391     }
2392 }
2393 
2394 /// A cursor into the Debugging Information Entries tree for a compilation unit.
2395 ///
2396 /// The `EntriesCursor` can traverse the DIE tree in DFS order using `next_dfs()`,
2397 /// or skip to the next sibling of the entry the cursor is currently pointing to
2398 /// using `next_sibling()`.
2399 ///
2400 /// It is also possible to traverse the DIE tree at a lower abstraction level
2401 /// using `next_entry()`. This method does not skip over null entries, or provide
2402 /// any indication of the current tree depth. In this case, you must use `current()`
2403 /// to obtain the current entry, and `current().has_children()` to determine if
2404 /// the entry following the current entry will be a sibling or child. `current()`
2405 /// will return `None` if the current entry is a null entry, which signifies the
2406 /// end of the current tree depth.
2407 #[derive(Clone, Debug)]
2408 pub struct EntriesCursor<'abbrev, 'unit, R>
2409 where
2410     R: Reader,
2411 {
2412     input: R,
2413     unit: &'unit UnitHeader<R>,
2414     abbreviations: &'abbrev Abbreviations,
2415     cached_current: Option<DebuggingInformationEntry<'abbrev, 'unit, R>>,
2416     delta_depth: isize,
2417 }
2418 
2419 impl<'abbrev, 'unit, R: Reader> EntriesCursor<'abbrev, 'unit, R> {
2420     /// Get a reference to the entry that the cursor is currently pointing to.
2421     ///
2422     /// If the cursor is not pointing at an entry, or if the current entry is a
2423     /// null entry, then `None` is returned.
2424     #[inline]
current(&self) -> Option<&DebuggingInformationEntry<'abbrev, 'unit, R>>2425     pub fn current(&self) -> Option<&DebuggingInformationEntry<'abbrev, 'unit, R>> {
2426         self.cached_current.as_ref()
2427     }
2428 
2429     /// Move the cursor to the next DIE in the tree.
2430     ///
2431     /// Returns `Some` if there is a next entry, even if this entry is null.
2432     /// If there is no next entry, then `None` is returned.
next_entry(&mut self) -> Result<Option<()>>2433     pub fn next_entry(&mut self) -> Result<Option<()>> {
2434         if let Some(ref current) = self.cached_current {
2435             self.input = current.after_attrs()?;
2436         }
2437 
2438         if self.input.is_empty() {
2439             self.cached_current = None;
2440             self.delta_depth = 0;
2441             return Ok(None);
2442         }
2443 
2444         match DebuggingInformationEntry::parse(&mut self.input, self.unit, self.abbreviations) {
2445             Ok(Some(entry)) => {
2446                 self.delta_depth = entry.has_children() as isize;
2447                 self.cached_current = Some(entry);
2448                 Ok(Some(()))
2449             }
2450             Ok(None) => {
2451                 self.delta_depth = -1;
2452                 self.cached_current = None;
2453                 Ok(Some(()))
2454             }
2455             Err(e) => {
2456                 self.input.empty();
2457                 self.delta_depth = 0;
2458                 self.cached_current = None;
2459                 Err(e)
2460             }
2461         }
2462     }
2463 
2464     /// Move the cursor to the next DIE in the tree in DFS order.
2465     ///
2466     /// Upon successful movement of the cursor, return the delta traversal
2467     /// depth and the entry:
2468     ///
2469     ///   * If we moved down into the previous current entry's children, we get
2470     ///     `Some((1, entry))`.
2471     ///
2472     ///   * If we moved to the previous current entry's sibling, we get
2473     ///     `Some((0, entry))`.
2474     ///
2475     ///   * If the previous entry does not have any siblings and we move up to
2476     ///     its parent's next sibling, then we get `Some((-1, entry))`. Note that
2477     ///     if the parent doesn't have a next sibling, then it could go up to the
2478     ///     parent's parent's next sibling and return `Some((-2, entry))`, etc.
2479     ///
2480     /// If there is no next entry, then `None` is returned.
2481     ///
2482     /// Here is an example that finds the first entry in a compilation unit that
2483     /// does not have any children.
2484     ///
2485     /// ```
2486     /// # use gimli::{DebugAbbrev, DebugInfo, LittleEndian};
2487     /// # let info_buf = [
2488     /// #     // Comilation unit header
2489     /// #
2490     /// #     // 32-bit unit length = 25
2491     /// #     0x19, 0x00, 0x00, 0x00,
2492     /// #     // Version 4
2493     /// #     0x04, 0x00,
2494     /// #     // debug_abbrev_offset
2495     /// #     0x00, 0x00, 0x00, 0x00,
2496     /// #     // Address size
2497     /// #     0x04,
2498     /// #
2499     /// #     // DIEs
2500     /// #
2501     /// #     // Abbreviation code
2502     /// #     0x01,
2503     /// #     // Attribute of form DW_FORM_string = "foo\0"
2504     /// #     0x66, 0x6f, 0x6f, 0x00,
2505     /// #
2506     /// #       // Children
2507     /// #
2508     /// #       // Abbreviation code
2509     /// #       0x01,
2510     /// #       // Attribute of form DW_FORM_string = "foo\0"
2511     /// #       0x66, 0x6f, 0x6f, 0x00,
2512     /// #
2513     /// #         // Children
2514     /// #
2515     /// #         // Abbreviation code
2516     /// #         0x01,
2517     /// #         // Attribute of form DW_FORM_string = "foo\0"
2518     /// #         0x66, 0x6f, 0x6f, 0x00,
2519     /// #
2520     /// #           // Children
2521     /// #
2522     /// #           // End of children
2523     /// #           0x00,
2524     /// #
2525     /// #         // End of children
2526     /// #         0x00,
2527     /// #
2528     /// #       // End of children
2529     /// #       0x00,
2530     /// # ];
2531     /// # let debug_info = DebugInfo::new(&info_buf, LittleEndian);
2532     /// #
2533     /// # let abbrev_buf = [
2534     /// #     // Code
2535     /// #     0x01,
2536     /// #     // DW_TAG_subprogram
2537     /// #     0x2e,
2538     /// #     // DW_CHILDREN_yes
2539     /// #     0x01,
2540     /// #     // Begin attributes
2541     /// #       // Attribute name = DW_AT_name
2542     /// #       0x03,
2543     /// #       // Attribute form = DW_FORM_string
2544     /// #       0x08,
2545     /// #     // End attributes
2546     /// #     0x00,
2547     /// #     0x00,
2548     /// #     // Null terminator
2549     /// #     0x00
2550     /// # ];
2551     /// # let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
2552     /// #
2553     /// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
2554     ///
2555     /// let unit = get_some_unit();
2556     /// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
2557     /// let abbrevs = get_abbrevs_for_unit(&unit);
2558     ///
2559     /// let mut first_entry_with_no_children = None;
2560     /// let mut cursor = unit.entries(&abbrevs);
2561     ///
2562     /// // Move the cursor to the root.
2563     /// assert!(cursor.next_dfs().unwrap().is_some());
2564     ///
2565     /// // Traverse the DIE tree in depth-first search order.
2566     /// let mut depth = 0;
2567     /// while let Some((delta_depth, current)) = cursor.next_dfs().expect("Should parse next dfs") {
2568     ///     // Update depth value, and break out of the loop when we
2569     ///     // return to the original starting position.
2570     ///     depth += delta_depth;
2571     ///     if depth <= 0 {
2572     ///         break;
2573     ///     }
2574     ///
2575     ///     first_entry_with_no_children = Some(current.clone());
2576     /// }
2577     ///
2578     /// println!("The first entry with no children is {:?}",
2579     ///          first_entry_with_no_children.unwrap());
2580     /// ```
2581     #[allow(clippy::type_complexity)]
next_dfs( &mut self, ) -> Result<Option<(isize, &DebuggingInformationEntry<'abbrev, 'unit, R>)>>2582     pub fn next_dfs(
2583         &mut self,
2584     ) -> Result<Option<(isize, &DebuggingInformationEntry<'abbrev, 'unit, R>)>> {
2585         let mut delta_depth = self.delta_depth;
2586         loop {
2587             // The next entry should be the one we want.
2588             if self.next_entry()?.is_some() {
2589                 if let Some(ref entry) = self.cached_current {
2590                     return Ok(Some((delta_depth, entry)));
2591                 }
2592 
2593                 // next_entry() read a null entry.
2594                 delta_depth += self.delta_depth;
2595             } else {
2596                 return Ok(None);
2597             }
2598         }
2599     }
2600 
2601     /// Move the cursor to the next sibling DIE of the current one.
2602     ///
2603     /// Returns `Ok(Some(entry))` when the cursor has been moved to
2604     /// the next sibling, `Ok(None)` when there is no next sibling.
2605     ///
2606     /// The depth of the cursor is never changed if this method returns `Ok`.
2607     /// Once `Ok(None)` is returned, this method will continue to return
2608     /// `Ok(None)` until either `next_entry` or `next_dfs` is called.
2609     ///
2610     /// Here is an example that iterates over all of the direct children of the
2611     /// root entry:
2612     ///
2613     /// ```
2614     /// # use gimli::{DebugAbbrev, DebugInfo, LittleEndian};
2615     /// # let info_buf = [
2616     /// #     // Comilation unit header
2617     /// #
2618     /// #     // 32-bit unit length = 25
2619     /// #     0x19, 0x00, 0x00, 0x00,
2620     /// #     // Version 4
2621     /// #     0x04, 0x00,
2622     /// #     // debug_abbrev_offset
2623     /// #     0x00, 0x00, 0x00, 0x00,
2624     /// #     // Address size
2625     /// #     0x04,
2626     /// #
2627     /// #     // DIEs
2628     /// #
2629     /// #     // Abbreviation code
2630     /// #     0x01,
2631     /// #     // Attribute of form DW_FORM_string = "foo\0"
2632     /// #     0x66, 0x6f, 0x6f, 0x00,
2633     /// #
2634     /// #       // Children
2635     /// #
2636     /// #       // Abbreviation code
2637     /// #       0x01,
2638     /// #       // Attribute of form DW_FORM_string = "foo\0"
2639     /// #       0x66, 0x6f, 0x6f, 0x00,
2640     /// #
2641     /// #         // Children
2642     /// #
2643     /// #         // Abbreviation code
2644     /// #         0x01,
2645     /// #         // Attribute of form DW_FORM_string = "foo\0"
2646     /// #         0x66, 0x6f, 0x6f, 0x00,
2647     /// #
2648     /// #           // Children
2649     /// #
2650     /// #           // End of children
2651     /// #           0x00,
2652     /// #
2653     /// #         // End of children
2654     /// #         0x00,
2655     /// #
2656     /// #       // End of children
2657     /// #       0x00,
2658     /// # ];
2659     /// # let debug_info = DebugInfo::new(&info_buf, LittleEndian);
2660     /// #
2661     /// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
2662     ///
2663     /// # let abbrev_buf = [
2664     /// #     // Code
2665     /// #     0x01,
2666     /// #     // DW_TAG_subprogram
2667     /// #     0x2e,
2668     /// #     // DW_CHILDREN_yes
2669     /// #     0x01,
2670     /// #     // Begin attributes
2671     /// #       // Attribute name = DW_AT_name
2672     /// #       0x03,
2673     /// #       // Attribute form = DW_FORM_string
2674     /// #       0x08,
2675     /// #     // End attributes
2676     /// #     0x00,
2677     /// #     0x00,
2678     /// #     // Null terminator
2679     /// #     0x00
2680     /// # ];
2681     /// # let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
2682     /// #
2683     /// let unit = get_some_unit();
2684     /// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
2685     /// let abbrevs = get_abbrevs_for_unit(&unit);
2686     ///
2687     /// let mut cursor = unit.entries(&abbrevs);
2688     ///
2689     /// // Move the cursor to the root.
2690     /// assert!(cursor.next_dfs().unwrap().is_some());
2691     ///
2692     /// // Move the cursor to the root's first child.
2693     /// assert!(cursor.next_dfs().unwrap().is_some());
2694     ///
2695     /// // Iterate the root's children.
2696     /// loop {
2697     ///     {
2698     ///         let current = cursor.current().expect("Should be at an entry");
2699     ///         println!("{:?} is a child of the root", current);
2700     ///     }
2701     ///
2702     ///     if cursor.next_sibling().expect("Should parse next sibling").is_none() {
2703     ///         break;
2704     ///     }
2705     /// }
2706     /// ```
next_sibling( &mut self, ) -> Result<Option<&DebuggingInformationEntry<'abbrev, 'unit, R>>>2707     pub fn next_sibling(
2708         &mut self,
2709     ) -> Result<Option<&DebuggingInformationEntry<'abbrev, 'unit, R>>> {
2710         if self.current().is_none() {
2711             // We're already at the null for the end of the sibling list.
2712             return Ok(None);
2713         }
2714 
2715         // Loop until we find an entry at the current level.
2716         let mut depth = 0;
2717         loop {
2718             // Use is_some() and unwrap() to keep borrow checker happy.
2719             if self.current().is_some() && self.current().unwrap().has_children() {
2720                 if let Some(sibling_input) = self.current().unwrap().sibling() {
2721                     // Fast path: this entry has a DW_AT_sibling
2722                     // attribute pointing to its sibling, so jump
2723                     // to it (which keeps us at the same depth).
2724                     self.input = sibling_input;
2725                     self.cached_current = None;
2726                 } else {
2727                     // This entry has children, so the next entry is
2728                     // down one level.
2729                     depth += 1;
2730                 }
2731             }
2732 
2733             if self.next_entry()?.is_none() {
2734                 // End of input.
2735                 return Ok(None);
2736             }
2737 
2738             if depth == 0 {
2739                 // Found an entry at the current level.
2740                 return Ok(self.current());
2741             }
2742 
2743             if self.current().is_none() {
2744                 // A null entry means the end of a child list, so we're
2745                 // back up a level.
2746                 depth -= 1;
2747             }
2748         }
2749     }
2750 }
2751 
2752 /// The state information for a tree view of the Debugging Information Entries.
2753 ///
2754 /// The `EntriesTree` can be used to recursively iterate through the DIE
2755 /// tree, following the parent/child relationships. The `EntriesTree` contains
2756 /// shared state for all nodes in the tree, avoiding any duplicate parsing of
2757 /// entries during the traversal.
2758 ///
2759 /// ## Example Usage
2760 /// ```rust,no_run
2761 /// # fn example() -> Result<(), gimli::Error> {
2762 /// # let debug_info = gimli::DebugInfo::new(&[], gimli::LittleEndian);
2763 /// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
2764 /// let unit = get_some_unit();
2765 /// # let debug_abbrev = gimli::DebugAbbrev::new(&[], gimli::LittleEndian);
2766 /// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
2767 /// let abbrevs = get_abbrevs_for_unit(&unit);
2768 ///
2769 /// let mut tree = unit.entries_tree(&abbrevs, None)?;
2770 /// let root = tree.root()?;
2771 /// process_tree(root)?;
2772 /// # unreachable!()
2773 /// # }
2774 ///
2775 /// fn process_tree<R>(mut node: gimli::EntriesTreeNode<R>) -> gimli::Result<()>
2776 ///     where R: gimli::Reader
2777 /// {
2778 ///     {
2779 ///         // Examine the entry attributes.
2780 ///         let mut attrs = node.entry().attrs();
2781 ///         while let Some(attr) = attrs.next()? {
2782 ///         }
2783 ///     }
2784 ///     let mut children = node.children();
2785 ///     while let Some(child) = children.next()? {
2786 ///         // Recursively process a child.
2787 ///         process_tree(child);
2788 ///     }
2789 ///     Ok(())
2790 /// }
2791 /// ```
2792 #[derive(Clone, Debug)]
2793 pub struct EntriesTree<'abbrev, 'unit, R>
2794 where
2795     R: Reader,
2796 {
2797     root: R,
2798     unit: &'unit UnitHeader<R>,
2799     abbreviations: &'abbrev Abbreviations,
2800     input: R,
2801     entry: Option<DebuggingInformationEntry<'abbrev, 'unit, R>>,
2802     depth: isize,
2803 }
2804 
2805 impl<'abbrev, 'unit, R: Reader> EntriesTree<'abbrev, 'unit, R> {
new(root: R, unit: &'unit UnitHeader<R>, abbreviations: &'abbrev Abbreviations) -> Self2806     fn new(root: R, unit: &'unit UnitHeader<R>, abbreviations: &'abbrev Abbreviations) -> Self {
2807         let input = root.clone();
2808         EntriesTree {
2809             root,
2810             unit,
2811             abbreviations,
2812             input,
2813             entry: None,
2814             depth: 0,
2815         }
2816     }
2817 
2818     /// Returns the root node of the tree.
root<'me>(&'me mut self) -> Result<EntriesTreeNode<'abbrev, 'unit, 'me, R>>2819     pub fn root<'me>(&'me mut self) -> Result<EntriesTreeNode<'abbrev, 'unit, 'me, R>> {
2820         self.input = self.root.clone();
2821         self.entry =
2822             DebuggingInformationEntry::parse(&mut self.input, self.unit, self.abbreviations)?;
2823         if self.entry.is_none() {
2824             return Err(Error::UnexpectedNull);
2825         }
2826         self.depth = 0;
2827         Ok(EntriesTreeNode::new(self, 1))
2828     }
2829 
2830     /// Move the cursor to the next entry at the specified depth.
2831     ///
2832     /// Requires `depth <= self.depth + 1`.
2833     ///
2834     /// Returns `true` if successful.
next(&mut self, depth: isize) -> Result<bool>2835     fn next(&mut self, depth: isize) -> Result<bool> {
2836         if self.depth < depth {
2837             debug_assert_eq!(self.depth + 1, depth);
2838 
2839             match self.entry {
2840                 Some(ref entry) => {
2841                     if !entry.has_children() {
2842                         return Ok(false);
2843                     }
2844                     self.depth += 1;
2845                     self.input = entry.after_attrs()?;
2846                 }
2847                 None => return Ok(false),
2848             }
2849 
2850             if self.input.is_empty() {
2851                 self.entry = None;
2852                 return Ok(false);
2853             }
2854 
2855             return match DebuggingInformationEntry::parse(
2856                 &mut self.input,
2857                 self.unit,
2858                 self.abbreviations,
2859             ) {
2860                 Ok(entry) => {
2861                     self.entry = entry;
2862                     Ok(self.entry.is_some())
2863                 }
2864                 Err(e) => {
2865                     self.input.empty();
2866                     self.entry = None;
2867                     Err(e)
2868                 }
2869             };
2870         }
2871 
2872         loop {
2873             match self.entry {
2874                 Some(ref entry) => {
2875                     if entry.has_children() {
2876                         if let Some(sibling_input) = entry.sibling() {
2877                             // Fast path: this entry has a DW_AT_sibling
2878                             // attribute pointing to its sibling, so jump
2879                             // to it (which keeps us at the same depth).
2880                             self.input = sibling_input;
2881                         } else {
2882                             // This entry has children, so the next entry is
2883                             // down one level.
2884                             self.depth += 1;
2885                             self.input = entry.after_attrs()?;
2886                         }
2887                     } else {
2888                         // This entry has no children, so next entry is at same depth.
2889                         self.input = entry.after_attrs()?;
2890                     }
2891                 }
2892                 None => {
2893                     // This entry is a null, so next entry is up one level.
2894                     self.depth -= 1;
2895                 }
2896             }
2897 
2898             if self.input.is_empty() {
2899                 self.entry = None;
2900                 return Ok(false);
2901             }
2902 
2903             match DebuggingInformationEntry::parse(&mut self.input, self.unit, self.abbreviations) {
2904                 Ok(entry) => {
2905                     self.entry = entry;
2906                     if self.depth == depth {
2907                         return Ok(self.entry.is_some());
2908                     }
2909                 }
2910                 Err(e) => {
2911                     self.input.empty();
2912                     self.entry = None;
2913                     return Err(e);
2914                 }
2915             }
2916         }
2917     }
2918 }
2919 
2920 /// A node in the Debugging Information Entry tree.
2921 ///
2922 /// The root node of a tree can be obtained
2923 /// via [`EntriesTree::root`](./struct.EntriesTree.html#method.root).
2924 #[derive(Debug)]
2925 pub struct EntriesTreeNode<'abbrev, 'unit, 'tree, R: Reader> {
2926     tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
2927     depth: isize,
2928 }
2929 
2930 impl<'abbrev, 'unit, 'tree, R: Reader> EntriesTreeNode<'abbrev, 'unit, 'tree, R> {
new( tree: &'tree mut EntriesTree<'abbrev, 'unit, R>, depth: isize, ) -> EntriesTreeNode<'abbrev, 'unit, 'tree, R>2931     fn new(
2932         tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
2933         depth: isize,
2934     ) -> EntriesTreeNode<'abbrev, 'unit, 'tree, R> {
2935         debug_assert!(tree.entry.is_some());
2936         EntriesTreeNode { tree, depth }
2937     }
2938 
2939     /// Returns the current entry in the tree.
entry(&self) -> &DebuggingInformationEntry<'abbrev, 'unit, R>2940     pub fn entry(&self) -> &DebuggingInformationEntry<'abbrev, 'unit, R> {
2941         // We never create a node without an entry.
2942         self.tree.entry.as_ref().unwrap()
2943     }
2944 
2945     /// Create an iterator for the children of the current entry.
2946     ///
2947     /// The current entry can no longer be accessed after creating the
2948     /// iterator.
children(self) -> EntriesTreeIter<'abbrev, 'unit, 'tree, R>2949     pub fn children(self) -> EntriesTreeIter<'abbrev, 'unit, 'tree, R> {
2950         EntriesTreeIter::new(self.tree, self.depth)
2951     }
2952 }
2953 
2954 /// An iterator that allows traversal of the children of an
2955 /// `EntriesTreeNode`.
2956 ///
2957 /// The items returned by this iterator are also `EntriesTreeNode`s,
2958 /// which allow recursive traversal of grandchildren, etc.
2959 #[derive(Debug)]
2960 pub struct EntriesTreeIter<'abbrev, 'unit, 'tree, R: Reader> {
2961     tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
2962     depth: isize,
2963     empty: bool,
2964 }
2965 
2966 impl<'abbrev, 'unit, 'tree, R: Reader> EntriesTreeIter<'abbrev, 'unit, 'tree, R> {
new( tree: &'tree mut EntriesTree<'abbrev, 'unit, R>, depth: isize, ) -> EntriesTreeIter<'abbrev, 'unit, 'tree, R>2967     fn new(
2968         tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
2969         depth: isize,
2970     ) -> EntriesTreeIter<'abbrev, 'unit, 'tree, R> {
2971         EntriesTreeIter {
2972             tree,
2973             depth,
2974             empty: false,
2975         }
2976     }
2977 
2978     /// Returns an `EntriesTreeNode` for the next child entry.
2979     ///
2980     /// Returns `None` if there are no more children.
next<'me>(&'me mut self) -> Result<Option<EntriesTreeNode<'abbrev, 'unit, 'me, R>>>2981     pub fn next<'me>(&'me mut self) -> Result<Option<EntriesTreeNode<'abbrev, 'unit, 'me, R>>> {
2982         if self.empty {
2983             Ok(None)
2984         } else if self.tree.next(self.depth)? {
2985             Ok(Some(EntriesTreeNode::new(self.tree, self.depth + 1)))
2986         } else {
2987             self.empty = true;
2988             Ok(None)
2989         }
2990     }
2991 }
2992 
2993 /// Parse a type unit header's unique type signature. Callers should handle
2994 /// unique-ness checking.
parse_type_signature<R: Reader>(input: &mut R) -> Result<DebugTypeSignature>2995 fn parse_type_signature<R: Reader>(input: &mut R) -> Result<DebugTypeSignature> {
2996     input.read_u64().map(DebugTypeSignature)
2997 }
2998 
2999 /// Parse a type unit header's type offset.
parse_type_offset<R: Reader>(input: &mut R, format: Format) -> Result<UnitOffset<R::Offset>>3000 fn parse_type_offset<R: Reader>(input: &mut R, format: Format) -> Result<UnitOffset<R::Offset>> {
3001     input.read_offset(format).map(UnitOffset)
3002 }
3003 
3004 /// The `DebugTypes` struct represents the DWARF type information
3005 /// found in the `.debug_types` section.
3006 #[derive(Debug, Default, Clone, Copy)]
3007 pub struct DebugTypes<R> {
3008     debug_types_section: R,
3009 }
3010 
3011 impl<'input, Endian> DebugTypes<EndianSlice<'input, Endian>>
3012 where
3013     Endian: Endianity,
3014 {
3015     /// Construct a new `DebugTypes` instance from the data in the `.debug_types`
3016     /// section.
3017     ///
3018     /// It is the caller's responsibility to read the `.debug_types` section and
3019     /// present it as a `&[u8]` slice. That means using some ELF loader on
3020     /// Linux, a Mach-O loader on OSX, etc.
3021     ///
3022     /// ```
3023     /// use gimli::{DebugTypes, LittleEndian};
3024     ///
3025     /// # let buf = [0x00, 0x01, 0x02, 0x03];
3026     /// # let read_debug_types_section_somehow = || &buf;
3027     /// let debug_types = DebugTypes::new(read_debug_types_section_somehow(), LittleEndian);
3028     /// ```
new(debug_types_section: &'input [u8], endian: Endian) -> Self3029     pub fn new(debug_types_section: &'input [u8], endian: Endian) -> Self {
3030         Self::from(EndianSlice::new(debug_types_section, endian))
3031     }
3032 }
3033 
3034 impl<T> DebugTypes<T> {
3035     /// Create a `DebugTypes` section that references the data in `self`.
3036     ///
3037     /// This is useful when `R` implements `Reader` but `T` does not.
3038     ///
3039     /// ## Example Usage
3040     ///
3041     /// ```rust,no_run
3042     /// # let load_section = || unimplemented!();
3043     /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
3044     /// let owned_section: gimli::DebugTypes<Vec<u8>> = load_section();
3045     /// // Create a reference to the DWARF section.
3046     /// let section = owned_section.borrow(|section| {
3047     ///     gimli::EndianSlice::new(&section, gimli::LittleEndian)
3048     /// });
3049     /// ```
borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugTypes<R> where F: FnMut(&'a T) -> R,3050     pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugTypes<R>
3051     where
3052         F: FnMut(&'a T) -> R,
3053     {
3054         borrow(&self.debug_types_section).into()
3055     }
3056 }
3057 
3058 impl<R> Section<R> for DebugTypes<R> {
id() -> SectionId3059     fn id() -> SectionId {
3060         SectionId::DebugTypes
3061     }
3062 
reader(&self) -> &R3063     fn reader(&self) -> &R {
3064         &self.debug_types_section
3065     }
3066 }
3067 
3068 impl<R> From<R> for DebugTypes<R> {
from(debug_types_section: R) -> Self3069     fn from(debug_types_section: R) -> Self {
3070         DebugTypes {
3071             debug_types_section,
3072         }
3073     }
3074 }
3075 
3076 impl<R: Reader> DebugTypes<R> {
3077     /// Iterate the type-units in this `.debug_types` section.
3078     ///
3079     /// ```
3080     /// use gimli::{DebugTypes, LittleEndian};
3081     ///
3082     /// # let buf = [];
3083     /// # let read_debug_types_section_somehow = || &buf;
3084     /// let debug_types = DebugTypes::new(read_debug_types_section_somehow(), LittleEndian);
3085     ///
3086     /// let mut iter = debug_types.units();
3087     /// while let Some(unit) = iter.next().unwrap() {
3088     ///     println!("unit's length is {}", unit.unit_length());
3089     /// }
3090     /// ```
3091     ///
3092     /// Can be [used with
3093     /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
units(&self) -> DebugTypesUnitHeadersIter<R>3094     pub fn units(&self) -> DebugTypesUnitHeadersIter<R> {
3095         DebugTypesUnitHeadersIter {
3096             input: self.debug_types_section.clone(),
3097             offset: DebugTypesOffset(R::Offset::from_u8(0)),
3098         }
3099     }
3100 }
3101 
3102 /// An iterator over the type-units of this `.debug_types` section.
3103 ///
3104 /// See the [documentation on
3105 /// `DebugTypes::units`](./struct.DebugTypes.html#method.units) for
3106 /// more detail.
3107 #[derive(Clone, Debug)]
3108 pub struct DebugTypesUnitHeadersIter<R: Reader> {
3109     input: R,
3110     offset: DebugTypesOffset<R::Offset>,
3111 }
3112 
3113 impl<R: Reader> DebugTypesUnitHeadersIter<R> {
3114     /// Advance the iterator to the next type unit header.
next(&mut self) -> Result<Option<UnitHeader<R>>>3115     pub fn next(&mut self) -> Result<Option<UnitHeader<R>>> {
3116         if self.input.is_empty() {
3117             Ok(None)
3118         } else {
3119             let len = self.input.len();
3120             match parse_unit_header(&mut self.input, self.offset.into()) {
3121                 Ok(header) => {
3122                     self.offset.0 += len - self.input.len();
3123                     Ok(Some(header))
3124                 }
3125                 Err(e) => {
3126                     self.input.empty();
3127                     Err(e)
3128                 }
3129             }
3130         }
3131     }
3132 }
3133 
3134 #[cfg(feature = "fallible-iterator")]
3135 impl<R: Reader> fallible_iterator::FallibleIterator for DebugTypesUnitHeadersIter<R> {
3136     type Item = UnitHeader<R>;
3137     type Error = Error;
3138 
next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error>3139     fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
3140         DebugTypesUnitHeadersIter::next(self)
3141     }
3142 }
3143 
3144 #[cfg(test)]
3145 // Tests require leb128::write.
3146 #[cfg(feature = "write")]
3147 mod tests {
3148     use super::*;
3149     use crate::constants;
3150     use crate::constants::*;
3151     use crate::endianity::{Endianity, LittleEndian};
3152     use crate::leb128;
3153     use crate::read::abbrev::tests::AbbrevSectionMethods;
3154     use crate::read::{
3155         Abbreviation, AttributeSpecification, DebugAbbrev, EndianSlice, Error, Result,
3156     };
3157     use crate::test_util::GimliSectionMethods;
3158     use alloc::vec::Vec;
3159     use core::cell::Cell;
3160     use test_assembler::{Endian, Label, LabelMaker, Section};
3161 
3162     // Mixin methods for `Section` to help define binary test data.
3163 
3164     trait UnitSectionMethods {
unit<'input, E>(self, unit: &mut UnitHeader<EndianSlice<'input, E>>) -> Self where E: Endianity3165         fn unit<'input, E>(self, unit: &mut UnitHeader<EndianSlice<'input, E>>) -> Self
3166         where
3167             E: Endianity;
die<F>(self, code: u64, attr: F) -> Self where F: Fn(Section) -> Section3168         fn die<F>(self, code: u64, attr: F) -> Self
3169         where
3170             F: Fn(Section) -> Section;
die_null(self) -> Self3171         fn die_null(self) -> Self;
attr_string(self, s: &str) -> Self3172         fn attr_string(self, s: &str) -> Self;
attr_ref1(self, o: u8) -> Self3173         fn attr_ref1(self, o: u8) -> Self;
offset(self, offset: usize, format: Format) -> Self3174         fn offset(self, offset: usize, format: Format) -> Self;
3175     }
3176 
3177     impl UnitSectionMethods for Section {
unit<'input, E>(self, unit: &mut UnitHeader<EndianSlice<'input, E>>) -> Self where E: Endianity,3178         fn unit<'input, E>(self, unit: &mut UnitHeader<EndianSlice<'input, E>>) -> Self
3179         where
3180             E: Endianity,
3181         {
3182             let size = self.size();
3183             let length = Label::new();
3184             let start = Label::new();
3185             let end = Label::new();
3186 
3187             let section = match unit.format() {
3188                 Format::Dwarf32 => self.L32(&length),
3189                 Format::Dwarf64 => self.L32(0xffff_ffff).L64(&length),
3190             };
3191 
3192             let section = match unit.version() {
3193                 2 | 3 | 4 => section
3194                     .mark(&start)
3195                     .L16(unit.version())
3196                     .offset(unit.debug_abbrev_offset.0, unit.format())
3197                     .D8(unit.address_size()),
3198                 5 => section
3199                     .mark(&start)
3200                     .L16(unit.version())
3201                     .D8(unit.type_().dw_ut().0)
3202                     .D8(unit.address_size())
3203                     .offset(unit.debug_abbrev_offset.0, unit.format()),
3204                 _ => unreachable!(),
3205             };
3206 
3207             let section = match unit.type_() {
3208                 UnitType::Compilation | UnitType::Partial => {
3209                     unit.unit_offset = DebugInfoOffset(size as usize).into();
3210                     section
3211                 }
3212                 UnitType::Type {
3213                     type_signature,
3214                     type_offset,
3215                 }
3216                 | UnitType::SplitType {
3217                     type_signature,
3218                     type_offset,
3219                 } => {
3220                     if unit.version() == 5 {
3221                         unit.unit_offset = DebugInfoOffset(size as usize).into();
3222                     } else {
3223                         unit.unit_offset = DebugTypesOffset(size as usize).into();
3224                     }
3225                     section
3226                         .L64(type_signature.0)
3227                         .offset(type_offset.0, unit.format())
3228                 }
3229                 UnitType::Skeleton(dwo_id) | UnitType::SplitCompilation(dwo_id) => {
3230                     unit.unit_offset = DebugInfoOffset(size as usize).into();
3231                     section.L64(dwo_id.0)
3232                 }
3233             };
3234 
3235             let section = section.append_bytes(unit.entries_buf.into()).mark(&end);
3236 
3237             unit.unit_length = (&end - &start) as usize;
3238             length.set_const(unit.unit_length as u64);
3239 
3240             section
3241         }
3242 
die<F>(self, code: u64, attr: F) -> Self where F: Fn(Section) -> Section,3243         fn die<F>(self, code: u64, attr: F) -> Self
3244         where
3245             F: Fn(Section) -> Section,
3246         {
3247             let section = self.uleb(code);
3248             attr(section)
3249         }
3250 
die_null(self) -> Self3251         fn die_null(self) -> Self {
3252             self.D8(0)
3253         }
3254 
attr_string(self, attr: &str) -> Self3255         fn attr_string(self, attr: &str) -> Self {
3256             self.append_bytes(attr.as_bytes()).D8(0)
3257         }
3258 
attr_ref1(self, attr: u8) -> Self3259         fn attr_ref1(self, attr: u8) -> Self {
3260             self.D8(attr)
3261         }
3262 
offset(self, offset: usize, format: Format) -> Self3263         fn offset(self, offset: usize, format: Format) -> Self {
3264             match format {
3265                 Format::Dwarf32 => self.L32(offset as u32),
3266                 Format::Dwarf64 => self.L64(offset as u64),
3267             }
3268         }
3269     }
3270 
3271     /// Ensure that `UnitHeader<R>` is covariant wrt R.
3272     #[test]
test_unit_header_variance()3273     fn test_unit_header_variance() {
3274         /// This only needs to compile.
3275         fn _f<'a: 'b, 'b, E: Endianity>(
3276             x: UnitHeader<EndianSlice<'a, E>>,
3277         ) -> UnitHeader<EndianSlice<'b, E>> {
3278             x
3279         }
3280     }
3281 
3282     #[test]
test_parse_debug_abbrev_offset_32()3283     fn test_parse_debug_abbrev_offset_32() {
3284         let section = Section::with_endian(Endian::Little).L32(0x0403_0201);
3285         let buf = section.get_contents().unwrap();
3286         let buf = &mut EndianSlice::new(&buf, LittleEndian);
3287 
3288         match parse_debug_abbrev_offset(buf, Format::Dwarf32) {
3289             Ok(val) => assert_eq!(val, DebugAbbrevOffset(0x0403_0201)),
3290             otherwise => panic!("Unexpected result: {:?}", otherwise),
3291         };
3292     }
3293 
3294     #[test]
test_parse_debug_abbrev_offset_32_incomplete()3295     fn test_parse_debug_abbrev_offset_32_incomplete() {
3296         let buf = [0x01, 0x02];
3297         let buf = &mut EndianSlice::new(&buf, LittleEndian);
3298 
3299         match parse_debug_abbrev_offset(buf, Format::Dwarf32) {
3300             Err(Error::UnexpectedEof(_)) => assert!(true),
3301             otherwise => panic!("Unexpected result: {:?}", otherwise),
3302         };
3303     }
3304 
3305     #[test]
3306     #[cfg(target_pointer_width = "64")]
test_parse_debug_abbrev_offset_64()3307     fn test_parse_debug_abbrev_offset_64() {
3308         let section = Section::with_endian(Endian::Little).L64(0x0807_0605_0403_0201);
3309         let buf = section.get_contents().unwrap();
3310         let buf = &mut EndianSlice::new(&buf, LittleEndian);
3311 
3312         match parse_debug_abbrev_offset(buf, Format::Dwarf64) {
3313             Ok(val) => assert_eq!(val, DebugAbbrevOffset(0x0807_0605_0403_0201)),
3314             otherwise => panic!("Unexpected result: {:?}", otherwise),
3315         };
3316     }
3317 
3318     #[test]
test_parse_debug_abbrev_offset_64_incomplete()3319     fn test_parse_debug_abbrev_offset_64_incomplete() {
3320         let buf = [0x01, 0x02];
3321         let buf = &mut EndianSlice::new(&buf, LittleEndian);
3322 
3323         match parse_debug_abbrev_offset(buf, Format::Dwarf64) {
3324             Err(Error::UnexpectedEof(_)) => assert!(true),
3325             otherwise => panic!("Unexpected result: {:?}", otherwise),
3326         };
3327     }
3328 
3329     #[test]
test_parse_debug_info_offset_32()3330     fn test_parse_debug_info_offset_32() {
3331         let section = Section::with_endian(Endian::Little).L32(0x0403_0201);
3332         let buf = section.get_contents().unwrap();
3333         let buf = &mut EndianSlice::new(&buf, LittleEndian);
3334 
3335         match parse_debug_info_offset(buf, Format::Dwarf32) {
3336             Ok(val) => assert_eq!(val, DebugInfoOffset(0x0403_0201)),
3337             otherwise => panic!("Unexpected result: {:?}", otherwise),
3338         };
3339     }
3340 
3341     #[test]
test_parse_debug_info_offset_32_incomplete()3342     fn test_parse_debug_info_offset_32_incomplete() {
3343         let buf = [0x01, 0x02];
3344         let buf = &mut EndianSlice::new(&buf, LittleEndian);
3345 
3346         match parse_debug_info_offset(buf, Format::Dwarf32) {
3347             Err(Error::UnexpectedEof(_)) => assert!(true),
3348             otherwise => panic!("Unexpected result: {:?}", otherwise),
3349         };
3350     }
3351 
3352     #[test]
3353     #[cfg(target_pointer_width = "64")]
test_parse_debug_info_offset_64()3354     fn test_parse_debug_info_offset_64() {
3355         let section = Section::with_endian(Endian::Little).L64(0x0807_0605_0403_0201);
3356         let buf = section.get_contents().unwrap();
3357         let buf = &mut EndianSlice::new(&buf, LittleEndian);
3358 
3359         match parse_debug_info_offset(buf, Format::Dwarf64) {
3360             Ok(val) => assert_eq!(val, DebugInfoOffset(0x0807_0605_0403_0201)),
3361             otherwise => panic!("Unexpected result: {:?}", otherwise),
3362         };
3363     }
3364 
3365     #[test]
test_parse_debug_info_offset_64_incomplete()3366     fn test_parse_debug_info_offset_64_incomplete() {
3367         let buf = [0x01, 0x02];
3368         let buf = &mut EndianSlice::new(&buf, LittleEndian);
3369 
3370         match parse_debug_info_offset(buf, Format::Dwarf64) {
3371             Err(Error::UnexpectedEof(_)) => assert!(true),
3372             otherwise => panic!("Unexpected result: {:?}", otherwise),
3373         };
3374     }
3375 
3376     #[test]
3377     #[cfg(target_pointer_width = "64")]
test_units()3378     fn test_units() {
3379         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3380         let mut unit64 = UnitHeader {
3381             encoding: Encoding {
3382                 format: Format::Dwarf64,
3383                 version: 4,
3384                 address_size: 8,
3385             },
3386             unit_length: 0,
3387             unit_type: UnitType::Compilation,
3388             debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3389             unit_offset: DebugInfoOffset(0).into(),
3390             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3391         };
3392         let mut unit32 = UnitHeader {
3393             encoding: Encoding {
3394                 format: Format::Dwarf32,
3395                 version: 4,
3396                 address_size: 4,
3397             },
3398             unit_length: 0,
3399             unit_type: UnitType::Compilation,
3400             debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3401             unit_offset: DebugInfoOffset(0).into(),
3402             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3403         };
3404         let section = Section::with_endian(Endian::Little)
3405             .unit(&mut unit64)
3406             .unit(&mut unit32);
3407         let buf = section.get_contents().unwrap();
3408 
3409         let debug_info = DebugInfo::new(&buf, LittleEndian);
3410         let mut units = debug_info.units();
3411 
3412         assert_eq!(units.next(), Ok(Some(unit64)));
3413         assert_eq!(units.next(), Ok(Some(unit32)));
3414         assert_eq!(units.next(), Ok(None));
3415     }
3416 
3417     #[test]
test_unit_version_unknown_version()3418     fn test_unit_version_unknown_version() {
3419         let buf = [0x02, 0x00, 0x00, 0x00, 0xab, 0xcd];
3420         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3421 
3422         match parse_unit_header(rest, DebugInfoOffset(0).into()) {
3423             Err(Error::UnknownVersion(0xcdab)) => assert!(true),
3424             otherwise => panic!("Unexpected result: {:?}", otherwise),
3425         };
3426 
3427         let buf = [0x02, 0x00, 0x00, 0x00, 0x1, 0x0];
3428         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3429 
3430         match parse_unit_header(rest, DebugInfoOffset(0).into()) {
3431             Err(Error::UnknownVersion(1)) => assert!(true),
3432             otherwise => panic!("Unexpected result: {:?}", otherwise),
3433         };
3434     }
3435 
3436     #[test]
test_unit_version_incomplete()3437     fn test_unit_version_incomplete() {
3438         let buf = [0x01, 0x00, 0x00, 0x00, 0x04];
3439         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3440 
3441         match parse_unit_header(rest, DebugInfoOffset(0).into()) {
3442             Err(Error::UnexpectedEof(_)) => assert!(true),
3443             otherwise => panic!("Unexpected result: {:?}", otherwise),
3444         };
3445     }
3446 
3447     #[test]
test_parse_unit_header_32_ok()3448     fn test_parse_unit_header_32_ok() {
3449         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3450         let encoding = Encoding {
3451             format: Format::Dwarf32,
3452             version: 4,
3453             address_size: 4,
3454         };
3455         let mut expected_unit = UnitHeader {
3456             encoding,
3457             unit_length: 0,
3458             unit_type: UnitType::Compilation,
3459             debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3460             unit_offset: DebugInfoOffset(0).into(),
3461             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3462         };
3463         let section = Section::with_endian(Endian::Little)
3464             .unit(&mut expected_unit)
3465             .append_bytes(expected_rest);
3466         let buf = section.get_contents().unwrap();
3467         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3468 
3469         assert_eq!(
3470             parse_unit_header(rest, DebugInfoOffset(0).into()),
3471             Ok(expected_unit)
3472         );
3473         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3474     }
3475 
3476     #[test]
3477     #[cfg(target_pointer_width = "64")]
test_parse_unit_header_64_ok()3478     fn test_parse_unit_header_64_ok() {
3479         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3480         let encoding = Encoding {
3481             format: Format::Dwarf64,
3482             version: 4,
3483             address_size: 8,
3484         };
3485         let mut expected_unit = UnitHeader {
3486             encoding,
3487             unit_length: 0,
3488             unit_type: UnitType::Compilation,
3489             debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3490             unit_offset: DebugInfoOffset(0).into(),
3491             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3492         };
3493         let section = Section::with_endian(Endian::Little)
3494             .unit(&mut expected_unit)
3495             .append_bytes(expected_rest);
3496         let buf = section.get_contents().unwrap();
3497         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3498 
3499         assert_eq!(
3500             parse_unit_header(rest, DebugInfoOffset(0).into()),
3501             Ok(expected_unit)
3502         );
3503         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3504     }
3505 
3506     #[test]
test_parse_v5_unit_header_32_ok()3507     fn test_parse_v5_unit_header_32_ok() {
3508         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3509         let encoding = Encoding {
3510             format: Format::Dwarf32,
3511             version: 5,
3512             address_size: 4,
3513         };
3514         let mut expected_unit = UnitHeader {
3515             encoding,
3516             unit_length: 0,
3517             unit_type: UnitType::Compilation,
3518             debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3519             unit_offset: DebugInfoOffset(0).into(),
3520             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3521         };
3522         let section = Section::with_endian(Endian::Little)
3523             .unit(&mut expected_unit)
3524             .append_bytes(expected_rest);
3525         let buf = section.get_contents().unwrap();
3526         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3527 
3528         assert_eq!(
3529             parse_unit_header(rest, DebugInfoOffset(0).into()),
3530             Ok(expected_unit)
3531         );
3532         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3533     }
3534 
3535     #[test]
3536     #[cfg(target_pointer_width = "64")]
test_parse_v5_unit_header_64_ok()3537     fn test_parse_v5_unit_header_64_ok() {
3538         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3539         let encoding = Encoding {
3540             format: Format::Dwarf64,
3541             version: 5,
3542             address_size: 8,
3543         };
3544         let mut expected_unit = UnitHeader {
3545             encoding,
3546             unit_length: 0,
3547             unit_type: UnitType::Compilation,
3548             debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3549             unit_offset: DebugInfoOffset(0).into(),
3550             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3551         };
3552         let section = Section::with_endian(Endian::Little)
3553             .unit(&mut expected_unit)
3554             .append_bytes(expected_rest);
3555         let buf = section.get_contents().unwrap();
3556         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3557 
3558         assert_eq!(
3559             parse_unit_header(rest, DebugInfoOffset(0).into()),
3560             Ok(expected_unit)
3561         );
3562         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3563     }
3564 
3565     #[test]
test_parse_v5_partial_unit_header_32_ok()3566     fn test_parse_v5_partial_unit_header_32_ok() {
3567         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3568         let encoding = Encoding {
3569             format: Format::Dwarf32,
3570             version: 5,
3571             address_size: 4,
3572         };
3573         let mut expected_unit = UnitHeader {
3574             encoding,
3575             unit_length: 0,
3576             unit_type: UnitType::Partial,
3577             debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3578             unit_offset: DebugInfoOffset(0).into(),
3579             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3580         };
3581         let section = Section::with_endian(Endian::Little)
3582             .unit(&mut expected_unit)
3583             .append_bytes(expected_rest);
3584         let buf = section.get_contents().unwrap();
3585         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3586 
3587         assert_eq!(
3588             parse_unit_header(rest, DebugInfoOffset(0).into()),
3589             Ok(expected_unit)
3590         );
3591         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3592     }
3593 
3594     #[test]
3595     #[cfg(target_pointer_width = "64")]
test_parse_v5_partial_unit_header_64_ok()3596     fn test_parse_v5_partial_unit_header_64_ok() {
3597         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3598         let encoding = Encoding {
3599             format: Format::Dwarf64,
3600             version: 5,
3601             address_size: 8,
3602         };
3603         let mut expected_unit = UnitHeader {
3604             encoding,
3605             unit_length: 0,
3606             unit_type: UnitType::Partial,
3607             debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3608             unit_offset: DebugInfoOffset(0).into(),
3609             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3610         };
3611         let section = Section::with_endian(Endian::Little)
3612             .unit(&mut expected_unit)
3613             .append_bytes(expected_rest);
3614         let buf = section.get_contents().unwrap();
3615         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3616 
3617         assert_eq!(
3618             parse_unit_header(rest, DebugInfoOffset(0).into()),
3619             Ok(expected_unit)
3620         );
3621         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3622     }
3623 
3624     #[test]
test_parse_v5_skeleton_unit_header_32_ok()3625     fn test_parse_v5_skeleton_unit_header_32_ok() {
3626         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3627         let encoding = Encoding {
3628             format: Format::Dwarf32,
3629             version: 5,
3630             address_size: 4,
3631         };
3632         let mut expected_unit = UnitHeader {
3633             encoding,
3634             unit_length: 0,
3635             unit_type: UnitType::Skeleton(DwoId(0x0706_5040_0302_1000)),
3636             debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3637             unit_offset: DebugInfoOffset(0).into(),
3638             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3639         };
3640         let section = Section::with_endian(Endian::Little)
3641             .unit(&mut expected_unit)
3642             .append_bytes(expected_rest);
3643         let buf = section.get_contents().unwrap();
3644         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3645 
3646         assert_eq!(
3647             parse_unit_header(rest, DebugInfoOffset(0).into()),
3648             Ok(expected_unit)
3649         );
3650         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3651     }
3652 
3653     #[test]
3654     #[cfg(target_pointer_width = "64")]
test_parse_v5_skeleton_unit_header_64_ok()3655     fn test_parse_v5_skeleton_unit_header_64_ok() {
3656         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3657         let encoding = Encoding {
3658             format: Format::Dwarf64,
3659             version: 5,
3660             address_size: 8,
3661         };
3662         let mut expected_unit = UnitHeader {
3663             encoding,
3664             unit_length: 0,
3665             unit_type: UnitType::Skeleton(DwoId(0x0706_5040_0302_1000)),
3666             debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3667             unit_offset: DebugInfoOffset(0).into(),
3668             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3669         };
3670         let section = Section::with_endian(Endian::Little)
3671             .unit(&mut expected_unit)
3672             .append_bytes(expected_rest);
3673         let buf = section.get_contents().unwrap();
3674         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3675 
3676         assert_eq!(
3677             parse_unit_header(rest, DebugInfoOffset(0).into()),
3678             Ok(expected_unit)
3679         );
3680         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3681     }
3682 
3683     #[test]
test_parse_v5_split_compilation_unit_header_32_ok()3684     fn test_parse_v5_split_compilation_unit_header_32_ok() {
3685         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3686         let encoding = Encoding {
3687             format: Format::Dwarf32,
3688             version: 5,
3689             address_size: 4,
3690         };
3691         let mut expected_unit = UnitHeader {
3692             encoding,
3693             unit_length: 0,
3694             unit_type: UnitType::SplitCompilation(DwoId(0x0706_5040_0302_1000)),
3695             debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3696             unit_offset: DebugInfoOffset(0).into(),
3697             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3698         };
3699         let section = Section::with_endian(Endian::Little)
3700             .unit(&mut expected_unit)
3701             .append_bytes(expected_rest);
3702         let buf = section.get_contents().unwrap();
3703         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3704 
3705         assert_eq!(
3706             parse_unit_header(rest, DebugInfoOffset(0).into()),
3707             Ok(expected_unit)
3708         );
3709         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3710     }
3711 
3712     #[test]
3713     #[cfg(target_pointer_width = "64")]
test_parse_v5_split_compilation_unit_header_64_ok()3714     fn test_parse_v5_split_compilation_unit_header_64_ok() {
3715         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3716         let encoding = Encoding {
3717             format: Format::Dwarf64,
3718             version: 5,
3719             address_size: 8,
3720         };
3721         let mut expected_unit = UnitHeader {
3722             encoding,
3723             unit_length: 0,
3724             unit_type: UnitType::SplitCompilation(DwoId(0x0706_5040_0302_1000)),
3725             debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3726             unit_offset: DebugInfoOffset(0).into(),
3727             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3728         };
3729         let section = Section::with_endian(Endian::Little)
3730             .unit(&mut expected_unit)
3731             .append_bytes(expected_rest);
3732         let buf = section.get_contents().unwrap();
3733         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3734 
3735         assert_eq!(
3736             parse_unit_header(rest, DebugInfoOffset(0).into()),
3737             Ok(expected_unit)
3738         );
3739         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3740     }
3741 
3742     #[test]
test_parse_type_offset_32_ok()3743     fn test_parse_type_offset_32_ok() {
3744         let buf = [0x12, 0x34, 0x56, 0x78, 0x00];
3745         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3746 
3747         match parse_type_offset(rest, Format::Dwarf32) {
3748             Ok(offset) => {
3749                 assert_eq!(rest.len(), 1);
3750                 assert_eq!(UnitOffset(0x7856_3412), offset);
3751             }
3752             otherwise => panic!("Unexpected result: {:?}", otherwise),
3753         }
3754     }
3755 
3756     #[test]
3757     #[cfg(target_pointer_width = "64")]
test_parse_type_offset_64_ok()3758     fn test_parse_type_offset_64_ok() {
3759         let buf = [0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xff, 0x00];
3760         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3761 
3762         match parse_type_offset(rest, Format::Dwarf64) {
3763             Ok(offset) => {
3764                 assert_eq!(rest.len(), 1);
3765                 assert_eq!(UnitOffset(0xffde_bc9a_7856_3412), offset);
3766             }
3767             otherwise => panic!("Unexpected result: {:?}", otherwise),
3768         }
3769     }
3770 
3771     #[test]
test_parse_type_offset_incomplete()3772     fn test_parse_type_offset_incomplete() {
3773         // Need at least 4 bytes.
3774         let buf = [0xff, 0xff, 0xff];
3775         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3776 
3777         match parse_type_offset(rest, Format::Dwarf32) {
3778             Err(Error::UnexpectedEof(_)) => assert!(true),
3779             otherwise => panic!("Unexpected result: {:?}", otherwise),
3780         };
3781     }
3782 
3783     #[test]
test_parse_type_unit_header_32_ok()3784     fn test_parse_type_unit_header_32_ok() {
3785         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3786         let encoding = Encoding {
3787             format: Format::Dwarf32,
3788             version: 4,
3789             address_size: 8,
3790         };
3791         let mut expected_unit = UnitHeader {
3792             encoding,
3793             unit_length: 0,
3794             unit_type: UnitType::Type {
3795                 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3796                 type_offset: UnitOffset(0x7856_3412),
3797             },
3798             debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3799             unit_offset: DebugTypesOffset(0).into(),
3800             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3801         };
3802         let section = Section::with_endian(Endian::Little)
3803             .unit(&mut expected_unit)
3804             .append_bytes(expected_rest);
3805         let buf = section.get_contents().unwrap();
3806         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3807 
3808         assert_eq!(
3809             parse_unit_header(rest, DebugTypesOffset(0).into()),
3810             Ok(expected_unit)
3811         );
3812         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3813     }
3814 
3815     #[test]
3816     #[cfg(target_pointer_width = "64")]
test_parse_type_unit_header_64_ok()3817     fn test_parse_type_unit_header_64_ok() {
3818         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3819         let encoding = Encoding {
3820             format: Format::Dwarf64,
3821             version: 4,
3822             address_size: 8,
3823         };
3824         let mut expected_unit = UnitHeader {
3825             encoding,
3826             unit_length: 0,
3827             unit_type: UnitType::Type {
3828                 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3829                 type_offset: UnitOffset(0x7856_3412_7856_3412),
3830             },
3831             debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3832             unit_offset: DebugTypesOffset(0).into(),
3833             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3834         };
3835         let section = Section::with_endian(Endian::Little)
3836             .unit(&mut expected_unit)
3837             .append_bytes(expected_rest);
3838         let buf = section.get_contents().unwrap();
3839         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3840 
3841         assert_eq!(
3842             parse_unit_header(rest, DebugTypesOffset(0).into()),
3843             Ok(expected_unit)
3844         );
3845         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3846     }
3847 
3848     #[test]
test_parse_v5_type_unit_header_32_ok()3849     fn test_parse_v5_type_unit_header_32_ok() {
3850         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3851         let encoding = Encoding {
3852             format: Format::Dwarf32,
3853             version: 5,
3854             address_size: 8,
3855         };
3856         let mut expected_unit = UnitHeader {
3857             encoding,
3858             unit_length: 0,
3859             unit_type: UnitType::Type {
3860                 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3861                 type_offset: UnitOffset(0x7856_3412),
3862             },
3863             debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3864             unit_offset: DebugInfoOffset(0).into(),
3865             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3866         };
3867         let section = Section::with_endian(Endian::Little)
3868             .unit(&mut expected_unit)
3869             .append_bytes(expected_rest);
3870         let buf = section.get_contents().unwrap();
3871         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3872 
3873         assert_eq!(
3874             parse_unit_header(rest, DebugInfoOffset(0).into()),
3875             Ok(expected_unit)
3876         );
3877         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3878     }
3879 
3880     #[test]
3881     #[cfg(target_pointer_width = "64")]
test_parse_v5_type_unit_header_64_ok()3882     fn test_parse_v5_type_unit_header_64_ok() {
3883         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3884         let encoding = Encoding {
3885             format: Format::Dwarf64,
3886             version: 5,
3887             address_size: 8,
3888         };
3889         let mut expected_unit = UnitHeader {
3890             encoding,
3891             unit_length: 0,
3892             unit_type: UnitType::Type {
3893                 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3894                 type_offset: UnitOffset(0x7856_3412_7856_3412),
3895             },
3896             debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3897             unit_offset: DebugInfoOffset(0).into(),
3898             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3899         };
3900         let section = Section::with_endian(Endian::Little)
3901             .unit(&mut expected_unit)
3902             .append_bytes(expected_rest);
3903         let buf = section.get_contents().unwrap();
3904         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3905 
3906         assert_eq!(
3907             parse_unit_header(rest, DebugInfoOffset(0).into()),
3908             Ok(expected_unit)
3909         );
3910         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3911     }
3912 
3913     #[test]
test_parse_v5_split_type_unit_header_32_ok()3914     fn test_parse_v5_split_type_unit_header_32_ok() {
3915         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3916         let encoding = Encoding {
3917             format: Format::Dwarf32,
3918             version: 5,
3919             address_size: 8,
3920         };
3921         let mut expected_unit = UnitHeader {
3922             encoding,
3923             unit_length: 0,
3924             unit_type: UnitType::SplitType {
3925                 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3926                 type_offset: UnitOffset(0x7856_3412),
3927             },
3928             debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3929             unit_offset: DebugInfoOffset(0).into(),
3930             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3931         };
3932         let section = Section::with_endian(Endian::Little)
3933             .unit(&mut expected_unit)
3934             .append_bytes(expected_rest);
3935         let buf = section.get_contents().unwrap();
3936         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3937 
3938         assert_eq!(
3939             parse_unit_header(rest, DebugInfoOffset(0).into()),
3940             Ok(expected_unit)
3941         );
3942         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3943     }
3944 
3945     #[test]
3946     #[cfg(target_pointer_width = "64")]
test_parse_v5_split_type_unit_header_64_ok()3947     fn test_parse_v5_split_type_unit_header_64_ok() {
3948         let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3949         let encoding = Encoding {
3950             format: Format::Dwarf64,
3951             version: 5,
3952             address_size: 8,
3953         };
3954         let mut expected_unit = UnitHeader {
3955             encoding,
3956             unit_length: 0,
3957             unit_type: UnitType::SplitType {
3958                 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3959                 type_offset: UnitOffset(0x7856_3412_7856_3412),
3960             },
3961             debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3962             unit_offset: DebugInfoOffset(0).into(),
3963             entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3964         };
3965         let section = Section::with_endian(Endian::Little)
3966             .unit(&mut expected_unit)
3967             .append_bytes(expected_rest);
3968         let buf = section.get_contents().unwrap();
3969         let rest = &mut EndianSlice::new(&buf, LittleEndian);
3970 
3971         assert_eq!(
3972             parse_unit_header(rest, DebugInfoOffset(0).into()),
3973             Ok(expected_unit)
3974         );
3975         assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3976     }
3977 
section_contents<F>(f: F) -> Vec<u8> where F: Fn(Section) -> Section,3978     fn section_contents<F>(f: F) -> Vec<u8>
3979     where
3980         F: Fn(Section) -> Section,
3981     {
3982         f(Section::with_endian(Endian::Little))
3983             .get_contents()
3984             .unwrap()
3985     }
3986 
3987     #[test]
test_attribute_value()3988     fn test_attribute_value() {
3989         let mut unit = test_parse_attribute_unit_default();
3990         let endian = unit.entries_buf.endian();
3991 
3992         let block_data = &[1, 2, 3, 4];
3993         let buf = section_contents(|s| s.uleb(block_data.len() as u64).append_bytes(block_data));
3994         let block = EndianSlice::new(&buf, endian);
3995 
3996         let buf = section_contents(|s| s.L32(0x0102_0304));
3997         let data4 = EndianSlice::new(&buf, endian);
3998 
3999         let buf = section_contents(|s| s.L64(0x0102_0304_0506_0708));
4000         let data8 = EndianSlice::new(&buf, endian);
4001 
4002         let tests = [
4003             (
4004                 Format::Dwarf32,
4005                 2,
4006                 constants::DW_AT_data_member_location,
4007                 constants::DW_FORM_block,
4008                 block,
4009                 AttributeValue::Block(EndianSlice::new(block_data, endian)),
4010                 AttributeValue::Exprloc(Expression(EndianSlice::new(block_data, endian))),
4011             ),
4012             (
4013                 Format::Dwarf32,
4014                 2,
4015                 constants::DW_AT_data_member_location,
4016                 constants::DW_FORM_data4,
4017                 data4,
4018                 AttributeValue::SecOffset(0x0102_0304),
4019                 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304)),
4020             ),
4021             (
4022                 Format::Dwarf64,
4023                 2,
4024                 constants::DW_AT_data_member_location,
4025                 constants::DW_FORM_data4,
4026                 data4,
4027                 AttributeValue::Data4(0x0102_0304),
4028                 AttributeValue::Udata(0x0102_0304),
4029             ),
4030             (
4031                 Format::Dwarf32,
4032                 4,
4033                 constants::DW_AT_data_member_location,
4034                 constants::DW_FORM_data4,
4035                 data4,
4036                 AttributeValue::Data4(0x0102_0304),
4037                 AttributeValue::Udata(0x0102_0304),
4038             ),
4039             (
4040                 Format::Dwarf32,
4041                 2,
4042                 constants::DW_AT_data_member_location,
4043                 constants::DW_FORM_data8,
4044                 data8,
4045                 AttributeValue::Data8(0x0102_0304_0506_0708),
4046                 AttributeValue::Udata(0x0102_0304_0506_0708),
4047             ),
4048             #[cfg(target_pointer_width = "64")]
4049             (
4050                 Format::Dwarf64,
4051                 2,
4052                 constants::DW_AT_data_member_location,
4053                 constants::DW_FORM_data8,
4054                 data8,
4055                 AttributeValue::SecOffset(0x0102_0304_0506_0708),
4056                 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304_0506_0708)),
4057             ),
4058             (
4059                 Format::Dwarf64,
4060                 4,
4061                 constants::DW_AT_data_member_location,
4062                 constants::DW_FORM_data8,
4063                 data8,
4064                 AttributeValue::Data8(0x0102_0304_0506_0708),
4065                 AttributeValue::Udata(0x0102_0304_0506_0708),
4066             ),
4067             (
4068                 Format::Dwarf32,
4069                 4,
4070                 constants::DW_AT_location,
4071                 constants::DW_FORM_data4,
4072                 data4,
4073                 AttributeValue::SecOffset(0x0102_0304),
4074                 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304)),
4075             ),
4076             #[cfg(target_pointer_width = "64")]
4077             (
4078                 Format::Dwarf64,
4079                 4,
4080                 constants::DW_AT_location,
4081                 constants::DW_FORM_data8,
4082                 data8,
4083                 AttributeValue::SecOffset(0x0102_0304_0506_0708),
4084                 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304_0506_0708)),
4085             ),
4086             (
4087                 Format::Dwarf32,
4088                 4,
4089                 constants::DW_AT_str_offsets_base,
4090                 constants::DW_FORM_sec_offset,
4091                 data4,
4092                 AttributeValue::SecOffset(0x0102_0304),
4093                 AttributeValue::DebugStrOffsetsBase(DebugStrOffsetsBase(0x0102_0304)),
4094             ),
4095             (
4096                 Format::Dwarf32,
4097                 4,
4098                 constants::DW_AT_stmt_list,
4099                 constants::DW_FORM_sec_offset,
4100                 data4,
4101                 AttributeValue::SecOffset(0x0102_0304),
4102                 AttributeValue::DebugLineRef(DebugLineOffset(0x0102_0304)),
4103             ),
4104             (
4105                 Format::Dwarf32,
4106                 4,
4107                 constants::DW_AT_addr_base,
4108                 constants::DW_FORM_sec_offset,
4109                 data4,
4110                 AttributeValue::SecOffset(0x0102_0304),
4111                 AttributeValue::DebugAddrBase(DebugAddrBase(0x0102_0304)),
4112             ),
4113             (
4114                 Format::Dwarf32,
4115                 4,
4116                 constants::DW_AT_rnglists_base,
4117                 constants::DW_FORM_sec_offset,
4118                 data4,
4119                 AttributeValue::SecOffset(0x0102_0304),
4120                 AttributeValue::DebugRngListsBase(DebugRngListsBase(0x0102_0304)),
4121             ),
4122             (
4123                 Format::Dwarf32,
4124                 4,
4125                 constants::DW_AT_loclists_base,
4126                 constants::DW_FORM_sec_offset,
4127                 data4,
4128                 AttributeValue::SecOffset(0x0102_0304),
4129                 AttributeValue::DebugLocListsBase(DebugLocListsBase(0x0102_0304)),
4130             ),
4131         ];
4132 
4133         for test in tests.iter() {
4134             let (format, version, name, form, mut input, expect_raw, expect_value) = *test;
4135             unit.encoding.format = format;
4136             unit.encoding.version = version;
4137             let spec = AttributeSpecification::new(name, form, None);
4138             let attribute =
4139                 parse_attribute(&mut input, unit.encoding(), spec).expect("Should parse attribute");
4140             assert_eq!(attribute.raw_value(), expect_raw);
4141             assert_eq!(attribute.value(), expect_value);
4142         }
4143     }
4144 
4145     #[test]
test_attribute_udata_sdata_value()4146     fn test_attribute_udata_sdata_value() {
4147         #[allow(clippy::type_complexity)]
4148         let tests: &[(
4149             AttributeValue<EndianSlice<LittleEndian>>,
4150             Option<u64>,
4151             Option<i64>,
4152         )] = &[
4153             (AttributeValue::Data1(1), Some(1), Some(1)),
4154             (
4155                 AttributeValue::Data1(core::u8::MAX),
4156                 Some(u64::from(std::u8::MAX)),
4157                 Some(-1),
4158             ),
4159             (AttributeValue::Data2(1), Some(1), Some(1)),
4160             (
4161                 AttributeValue::Data2(core::u16::MAX),
4162                 Some(u64::from(std::u16::MAX)),
4163                 Some(-1),
4164             ),
4165             (AttributeValue::Data4(1), Some(1), Some(1)),
4166             (
4167                 AttributeValue::Data4(core::u32::MAX),
4168                 Some(u64::from(std::u32::MAX)),
4169                 Some(-1),
4170             ),
4171             (AttributeValue::Data8(1), Some(1), Some(1)),
4172             (
4173                 AttributeValue::Data8(core::u64::MAX),
4174                 Some(core::u64::MAX),
4175                 Some(-1),
4176             ),
4177             (AttributeValue::Sdata(1), Some(1), Some(1)),
4178             (AttributeValue::Sdata(-1), None, Some(-1)),
4179             (AttributeValue::Udata(1), Some(1), Some(1)),
4180             (AttributeValue::Udata(1u64 << 63), Some(1u64 << 63), None),
4181         ];
4182         for test in tests.iter() {
4183             let (value, expect_udata, expect_sdata) = *test;
4184             let attribute = Attribute {
4185                 name: DW_AT_data_member_location,
4186                 value,
4187             };
4188             assert_eq!(attribute.udata_value(), expect_udata);
4189             assert_eq!(attribute.sdata_value(), expect_sdata);
4190         }
4191     }
4192 
test_parse_attribute_unit<Endian>( address_size: u8, format: Format, endian: Endian, ) -> UnitHeader<EndianSlice<'static, Endian>> where Endian: Endianity,4193     fn test_parse_attribute_unit<Endian>(
4194         address_size: u8,
4195         format: Format,
4196         endian: Endian,
4197     ) -> UnitHeader<EndianSlice<'static, Endian>>
4198     where
4199         Endian: Endianity,
4200     {
4201         let encoding = Encoding {
4202             format,
4203             version: 4,
4204             address_size,
4205         };
4206         UnitHeader::new(
4207             encoding,
4208             7,
4209             UnitType::Compilation,
4210             DebugAbbrevOffset(0x0807_0605),
4211             DebugInfoOffset(0).into(),
4212             EndianSlice::new(&[], endian),
4213         )
4214     }
4215 
test_parse_attribute_unit_default() -> UnitHeader<EndianSlice<'static, LittleEndian>>4216     fn test_parse_attribute_unit_default() -> UnitHeader<EndianSlice<'static, LittleEndian>> {
4217         test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian)
4218     }
4219 
test_parse_attribute<'input, Endian>( buf: &'input [u8], len: usize, unit: &UnitHeader<EndianSlice<'input, Endian>>, form: constants::DwForm, value: AttributeValue<EndianSlice<'input, Endian>>, ) where Endian: Endianity,4220     fn test_parse_attribute<'input, Endian>(
4221         buf: &'input [u8],
4222         len: usize,
4223         unit: &UnitHeader<EndianSlice<'input, Endian>>,
4224         form: constants::DwForm,
4225         value: AttributeValue<EndianSlice<'input, Endian>>,
4226     ) where
4227         Endian: Endianity,
4228     {
4229         let spec = AttributeSpecification::new(constants::DW_AT_low_pc, form, None);
4230 
4231         let expect = Attribute {
4232             name: constants::DW_AT_low_pc,
4233             value,
4234         };
4235 
4236         let rest = &mut EndianSlice::new(buf, Endian::default());
4237         match parse_attribute(rest, unit.encoding(), spec) {
4238             Ok(attr) => {
4239                 assert_eq!(attr, expect);
4240                 assert_eq!(*rest, EndianSlice::new(&buf[len..], Endian::default()));
4241             }
4242             otherwise => {
4243                 assert!(false, "Unexpected parse result = {:#?}", otherwise);
4244             }
4245         };
4246     }
4247 
4248     #[test]
test_parse_attribute_addr()4249     fn test_parse_attribute_addr() {
4250         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
4251         let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4252         let form = constants::DW_FORM_addr;
4253         let value = AttributeValue::Addr(0x0403_0201);
4254         test_parse_attribute(&buf, 4, &unit, form, value);
4255     }
4256 
4257     #[test]
test_parse_attribute_addr8()4258     fn test_parse_attribute_addr8() {
4259         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
4260         let unit = test_parse_attribute_unit(8, Format::Dwarf32, LittleEndian);
4261         let form = constants::DW_FORM_addr;
4262         let value = AttributeValue::Addr(0x0807_0605_0403_0201);
4263         test_parse_attribute(&buf, 8, &unit, form, value);
4264     }
4265 
4266     #[test]
test_parse_attribute_block1()4267     fn test_parse_attribute_block1() {
4268         // Length of data (3), three bytes of data, two bytes of left over input.
4269         let buf = [0x03, 0x09, 0x09, 0x09, 0x00, 0x00];
4270         let unit = test_parse_attribute_unit_default();
4271         let form = constants::DW_FORM_block1;
4272         let value = AttributeValue::Block(EndianSlice::new(&buf[1..4], LittleEndian));
4273         test_parse_attribute(&buf, 4, &unit, form, value);
4274     }
4275 
4276     #[test]
test_parse_attribute_block2()4277     fn test_parse_attribute_block2() {
4278         // Two byte length of data (2), two bytes of data, two bytes of left over input.
4279         let buf = [0x02, 0x00, 0x09, 0x09, 0x00, 0x00];
4280         let unit = test_parse_attribute_unit_default();
4281         let form = constants::DW_FORM_block2;
4282         let value = AttributeValue::Block(EndianSlice::new(&buf[2..4], LittleEndian));
4283         test_parse_attribute(&buf, 4, &unit, form, value);
4284     }
4285 
4286     #[test]
test_parse_attribute_block4()4287     fn test_parse_attribute_block4() {
4288         // Four byte length of data (2), two bytes of data, no left over input.
4289         let buf = [0x02, 0x00, 0x00, 0x00, 0x99, 0x99];
4290         let unit = test_parse_attribute_unit_default();
4291         let form = constants::DW_FORM_block4;
4292         let value = AttributeValue::Block(EndianSlice::new(&buf[4..], LittleEndian));
4293         test_parse_attribute(&buf, 6, &unit, form, value);
4294     }
4295 
4296     #[test]
test_parse_attribute_block()4297     fn test_parse_attribute_block() {
4298         // LEB length of data (2, one byte), two bytes of data, no left over input.
4299         let buf = [0x02, 0x99, 0x99];
4300         let unit = test_parse_attribute_unit_default();
4301         let form = constants::DW_FORM_block;
4302         let value = AttributeValue::Block(EndianSlice::new(&buf[1..], LittleEndian));
4303         test_parse_attribute(&buf, 3, &unit, form, value);
4304     }
4305 
4306     #[test]
test_parse_attribute_data1()4307     fn test_parse_attribute_data1() {
4308         let buf = [0x03];
4309         let unit = test_parse_attribute_unit_default();
4310         let form = constants::DW_FORM_data1;
4311         let value = AttributeValue::Data1(0x03);
4312         test_parse_attribute(&buf, 1, &unit, form, value);
4313     }
4314 
4315     #[test]
test_parse_attribute_data2()4316     fn test_parse_attribute_data2() {
4317         let buf = [0x02, 0x01, 0x0];
4318         let unit = test_parse_attribute_unit_default();
4319         let form = constants::DW_FORM_data2;
4320         let value = AttributeValue::Data2(0x0102);
4321         test_parse_attribute(&buf, 2, &unit, form, value);
4322     }
4323 
4324     #[test]
test_parse_attribute_data4()4325     fn test_parse_attribute_data4() {
4326         let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4327         let unit = test_parse_attribute_unit_default();
4328         let form = constants::DW_FORM_data4;
4329         let value = AttributeValue::Data4(0x0403_0201);
4330         test_parse_attribute(&buf, 4, &unit, form, value);
4331     }
4332 
4333     #[test]
test_parse_attribute_data8()4334     fn test_parse_attribute_data8() {
4335         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4336         let unit = test_parse_attribute_unit_default();
4337         let form = constants::DW_FORM_data8;
4338         let value = AttributeValue::Data8(0x0807_0605_0403_0201);
4339         test_parse_attribute(&buf, 8, &unit, form, value);
4340     }
4341 
4342     #[test]
test_parse_attribute_udata()4343     fn test_parse_attribute_udata() {
4344         let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4345 
4346         let bytes_written = {
4347             let mut writable = &mut buf[..];
4348             leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4349         };
4350 
4351         let unit = test_parse_attribute_unit_default();
4352         let form = constants::DW_FORM_udata;
4353         let value = AttributeValue::Udata(4097);
4354         test_parse_attribute(&buf, bytes_written, &unit, form, value);
4355     }
4356 
4357     #[test]
test_parse_attribute_sdata()4358     fn test_parse_attribute_sdata() {
4359         let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4360 
4361         let bytes_written = {
4362             let mut writable = &mut buf[..];
4363             leb128::write::signed(&mut writable, -4097).expect("should write ok")
4364         };
4365 
4366         let unit = test_parse_attribute_unit_default();
4367         let form = constants::DW_FORM_sdata;
4368         let value = AttributeValue::Sdata(-4097);
4369         test_parse_attribute(&buf, bytes_written, &unit, form, value);
4370     }
4371 
4372     #[test]
test_parse_attribute_exprloc()4373     fn test_parse_attribute_exprloc() {
4374         // LEB length of data (2, one byte), two bytes of data, one byte left over input.
4375         let buf = [0x02, 0x99, 0x99, 0x11];
4376         let unit = test_parse_attribute_unit_default();
4377         let form = constants::DW_FORM_exprloc;
4378         let value = AttributeValue::Exprloc(Expression(EndianSlice::new(&buf[1..3], LittleEndian)));
4379         test_parse_attribute(&buf, 3, &unit, form, value);
4380     }
4381 
4382     #[test]
test_parse_attribute_flag_true()4383     fn test_parse_attribute_flag_true() {
4384         let buf = [0x42];
4385         let unit = test_parse_attribute_unit_default();
4386         let form = constants::DW_FORM_flag;
4387         let value = AttributeValue::Flag(true);
4388         test_parse_attribute(&buf, 1, &unit, form, value);
4389     }
4390 
4391     #[test]
test_parse_attribute_flag_false()4392     fn test_parse_attribute_flag_false() {
4393         let buf = [0x00];
4394         let unit = test_parse_attribute_unit_default();
4395         let form = constants::DW_FORM_flag;
4396         let value = AttributeValue::Flag(false);
4397         test_parse_attribute(&buf, 1, &unit, form, value);
4398     }
4399 
4400     #[test]
test_parse_attribute_flag_present()4401     fn test_parse_attribute_flag_present() {
4402         let buf = [0x01, 0x02, 0x03, 0x04];
4403         let unit = test_parse_attribute_unit_default();
4404         let form = constants::DW_FORM_flag_present;
4405         let value = AttributeValue::Flag(true);
4406         // DW_FORM_flag_present does not consume any bytes of the input stream.
4407         test_parse_attribute(&buf, 0, &unit, form, value);
4408     }
4409 
4410     #[test]
test_parse_attribute_sec_offset_32()4411     fn test_parse_attribute_sec_offset_32() {
4412         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10];
4413         let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4414         let form = constants::DW_FORM_sec_offset;
4415         let value = AttributeValue::SecOffset(0x0403_0201);
4416         test_parse_attribute(&buf, 4, &unit, form, value);
4417     }
4418 
4419     #[test]
4420     #[cfg(target_pointer_width = "64")]
test_parse_attribute_sec_offset_64()4421     fn test_parse_attribute_sec_offset_64() {
4422         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10];
4423         let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4424         let form = constants::DW_FORM_sec_offset;
4425         let value = AttributeValue::SecOffset(0x0807_0605_0403_0201);
4426         test_parse_attribute(&buf, 8, &unit, form, value);
4427     }
4428 
4429     #[test]
test_parse_attribute_ref1()4430     fn test_parse_attribute_ref1() {
4431         let buf = [0x03];
4432         let unit = test_parse_attribute_unit_default();
4433         let form = constants::DW_FORM_ref1;
4434         let value = AttributeValue::UnitRef(UnitOffset(3));
4435         test_parse_attribute(&buf, 1, &unit, form, value);
4436     }
4437 
4438     #[test]
test_parse_attribute_ref2()4439     fn test_parse_attribute_ref2() {
4440         let buf = [0x02, 0x01, 0x0];
4441         let unit = test_parse_attribute_unit_default();
4442         let form = constants::DW_FORM_ref2;
4443         let value = AttributeValue::UnitRef(UnitOffset(258));
4444         test_parse_attribute(&buf, 2, &unit, form, value);
4445     }
4446 
4447     #[test]
test_parse_attribute_ref4()4448     fn test_parse_attribute_ref4() {
4449         let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4450         let unit = test_parse_attribute_unit_default();
4451         let form = constants::DW_FORM_ref4;
4452         let value = AttributeValue::UnitRef(UnitOffset(0x0403_0201));
4453         test_parse_attribute(&buf, 4, &unit, form, value);
4454     }
4455 
4456     #[test]
4457     #[cfg(target_pointer_width = "64")]
test_parse_attribute_ref8()4458     fn test_parse_attribute_ref8() {
4459         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4460         let unit = test_parse_attribute_unit_default();
4461         let form = constants::DW_FORM_ref8;
4462         let value = AttributeValue::UnitRef(UnitOffset(0x0807_0605_0403_0201));
4463         test_parse_attribute(&buf, 8, &unit, form, value);
4464     }
4465 
4466     #[test]
test_parse_attribute_ref_sup4()4467     fn test_parse_attribute_ref_sup4() {
4468         let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4469         let unit = test_parse_attribute_unit_default();
4470         let form = constants::DW_FORM_ref_sup4;
4471         let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0403_0201));
4472         test_parse_attribute(&buf, 4, &unit, form, value);
4473     }
4474 
4475     #[test]
4476     #[cfg(target_pointer_width = "64")]
test_parse_attribute_ref_sup8()4477     fn test_parse_attribute_ref_sup8() {
4478         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4479         let unit = test_parse_attribute_unit_default();
4480         let form = constants::DW_FORM_ref_sup8;
4481         let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0807_0605_0403_0201));
4482         test_parse_attribute(&buf, 8, &unit, form, value);
4483     }
4484 
4485     #[test]
test_parse_attribute_refudata()4486     fn test_parse_attribute_refudata() {
4487         let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4488 
4489         let bytes_written = {
4490             let mut writable = &mut buf[..];
4491             leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4492         };
4493 
4494         let unit = test_parse_attribute_unit_default();
4495         let form = constants::DW_FORM_ref_udata;
4496         let value = AttributeValue::UnitRef(UnitOffset(4097));
4497         test_parse_attribute(&buf, bytes_written, &unit, form, value);
4498     }
4499 
4500     #[test]
test_parse_attribute_refaddr_32()4501     fn test_parse_attribute_refaddr_32() {
4502         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4503         let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4504         let form = constants::DW_FORM_ref_addr;
4505         let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0403_0201));
4506         test_parse_attribute(&buf, 4, &unit, form, value);
4507     }
4508 
4509     #[test]
4510     #[cfg(target_pointer_width = "64")]
test_parse_attribute_refaddr_64()4511     fn test_parse_attribute_refaddr_64() {
4512         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4513         let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4514         let form = constants::DW_FORM_ref_addr;
4515         let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0807_0605_0403_0201));
4516         test_parse_attribute(&buf, 8, &unit, form, value);
4517     }
4518 
4519     #[test]
test_parse_attribute_refaddr_version2()4520     fn test_parse_attribute_refaddr_version2() {
4521         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4522         let mut unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4523         unit.encoding.version = 2;
4524         let form = constants::DW_FORM_ref_addr;
4525         let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0403_0201));
4526         test_parse_attribute(&buf, 4, &unit, form, value);
4527     }
4528 
4529     #[test]
4530     #[cfg(target_pointer_width = "64")]
test_parse_attribute_refaddr8_version2()4531     fn test_parse_attribute_refaddr8_version2() {
4532         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4533         let mut unit = test_parse_attribute_unit(8, Format::Dwarf32, LittleEndian);
4534         unit.encoding.version = 2;
4535         let form = constants::DW_FORM_ref_addr;
4536         let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0807_0605_0403_0201));
4537         test_parse_attribute(&buf, 8, &unit, form, value);
4538     }
4539 
4540     #[test]
test_parse_attribute_gnu_ref_alt_32()4541     fn test_parse_attribute_gnu_ref_alt_32() {
4542         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4543         let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4544         let form = constants::DW_FORM_GNU_ref_alt;
4545         let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0403_0201));
4546         test_parse_attribute(&buf, 4, &unit, form, value);
4547     }
4548 
4549     #[test]
4550     #[cfg(target_pointer_width = "64")]
test_parse_attribute_gnu_ref_alt_64()4551     fn test_parse_attribute_gnu_ref_alt_64() {
4552         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4553         let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4554         let form = constants::DW_FORM_GNU_ref_alt;
4555         let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0807_0605_0403_0201));
4556         test_parse_attribute(&buf, 8, &unit, form, value);
4557     }
4558 
4559     #[test]
test_parse_attribute_refsig8()4560     fn test_parse_attribute_refsig8() {
4561         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4562         let unit = test_parse_attribute_unit_default();
4563         let form = constants::DW_FORM_ref_sig8;
4564         let value = AttributeValue::DebugTypesRef(DebugTypeSignature(0x0807_0605_0403_0201));
4565         test_parse_attribute(&buf, 8, &unit, form, value);
4566     }
4567 
4568     #[test]
test_parse_attribute_string()4569     fn test_parse_attribute_string() {
4570         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x0, 0x99, 0x99];
4571         let unit = test_parse_attribute_unit_default();
4572         let form = constants::DW_FORM_string;
4573         let value = AttributeValue::String(EndianSlice::new(&buf[..5], LittleEndian));
4574         test_parse_attribute(&buf, 6, &unit, form, value);
4575     }
4576 
4577     #[test]
test_parse_attribute_strp_32()4578     fn test_parse_attribute_strp_32() {
4579         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4580         let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4581         let form = constants::DW_FORM_strp;
4582         let value = AttributeValue::DebugStrRef(DebugStrOffset(0x0403_0201));
4583         test_parse_attribute(&buf, 4, &unit, form, value);
4584     }
4585 
4586     #[test]
4587     #[cfg(target_pointer_width = "64")]
test_parse_attribute_strp_64()4588     fn test_parse_attribute_strp_64() {
4589         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4590         let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4591         let form = constants::DW_FORM_strp;
4592         let value = AttributeValue::DebugStrRef(DebugStrOffset(0x0807_0605_0403_0201));
4593         test_parse_attribute(&buf, 8, &unit, form, value);
4594     }
4595 
4596     #[test]
test_parse_attribute_strp_sup_32()4597     fn test_parse_attribute_strp_sup_32() {
4598         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4599         let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4600         let form = constants::DW_FORM_strp_sup;
4601         let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0403_0201));
4602         test_parse_attribute(&buf, 4, &unit, form, value);
4603     }
4604 
4605     #[test]
4606     #[cfg(target_pointer_width = "64")]
test_parse_attribute_strp_sup_64()4607     fn test_parse_attribute_strp_sup_64() {
4608         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4609         let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4610         let form = constants::DW_FORM_strp_sup;
4611         let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0807_0605_0403_0201));
4612         test_parse_attribute(&buf, 8, &unit, form, value);
4613     }
4614 
4615     #[test]
test_parse_attribute_gnu_strp_alt_32()4616     fn test_parse_attribute_gnu_strp_alt_32() {
4617         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4618         let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4619         let form = constants::DW_FORM_GNU_strp_alt;
4620         let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0403_0201));
4621         test_parse_attribute(&buf, 4, &unit, form, value);
4622     }
4623 
4624     #[test]
4625     #[cfg(target_pointer_width = "64")]
test_parse_attribute_gnu_strp_alt_64()4626     fn test_parse_attribute_gnu_strp_alt_64() {
4627         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4628         let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4629         let form = constants::DW_FORM_GNU_strp_alt;
4630         let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0807_0605_0403_0201));
4631         test_parse_attribute(&buf, 8, &unit, form, value);
4632     }
4633 
4634     #[test]
test_parse_attribute_strx()4635     fn test_parse_attribute_strx() {
4636         let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4637 
4638         let bytes_written = {
4639             let mut writable = &mut buf[..];
4640             leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4641         };
4642 
4643         let unit = test_parse_attribute_unit_default();
4644         let form = constants::DW_FORM_strx;
4645         let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(4097));
4646         test_parse_attribute(&buf, bytes_written, &unit, form, value);
4647     }
4648 
4649     #[test]
test_parse_attribute_strx1()4650     fn test_parse_attribute_strx1() {
4651         let buf = [0x01, 0x99, 0x99];
4652         let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4653         let form = constants::DW_FORM_strx1;
4654         let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x01));
4655         test_parse_attribute(&buf, 1, &unit, form, value);
4656     }
4657 
4658     #[test]
test_parse_attribute_strx2()4659     fn test_parse_attribute_strx2() {
4660         let buf = [0x01, 0x02, 0x99, 0x99];
4661         let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4662         let form = constants::DW_FORM_strx2;
4663         let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x0201));
4664         test_parse_attribute(&buf, 2, &unit, form, value);
4665     }
4666 
4667     #[test]
test_parse_attribute_strx3()4668     fn test_parse_attribute_strx3() {
4669         let buf = [0x01, 0x02, 0x03, 0x99, 0x99];
4670         let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4671         let form = constants::DW_FORM_strx3;
4672         let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x03_0201));
4673         test_parse_attribute(&buf, 3, &unit, form, value);
4674     }
4675 
4676     #[test]
test_parse_attribute_strx4()4677     fn test_parse_attribute_strx4() {
4678         let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4679         let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4680         let form = constants::DW_FORM_strx4;
4681         let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x0403_0201));
4682         test_parse_attribute(&buf, 4, &unit, form, value);
4683     }
4684 
4685     #[test]
test_parse_attribute_addrx()4686     fn test_parse_attribute_addrx() {
4687         let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4688 
4689         let bytes_written = {
4690             let mut writable = &mut buf[..];
4691             leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4692         };
4693 
4694         let unit = test_parse_attribute_unit_default();
4695         let form = constants::DW_FORM_addrx;
4696         let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(4097));
4697         test_parse_attribute(&buf, bytes_written, &unit, form, value);
4698     }
4699 
4700     #[test]
test_parse_attribute_addrx1()4701     fn test_parse_attribute_addrx1() {
4702         let buf = [0x01, 0x99, 0x99];
4703         let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4704         let form = constants::DW_FORM_addrx1;
4705         let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x01));
4706         test_parse_attribute(&buf, 1, &unit, form, value);
4707     }
4708 
4709     #[test]
test_parse_attribute_addrx2()4710     fn test_parse_attribute_addrx2() {
4711         let buf = [0x01, 0x02, 0x99, 0x99];
4712         let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4713         let form = constants::DW_FORM_addrx2;
4714         let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x0201));
4715         test_parse_attribute(&buf, 2, &unit, form, value);
4716     }
4717 
4718     #[test]
test_parse_attribute_addrx3()4719     fn test_parse_attribute_addrx3() {
4720         let buf = [0x01, 0x02, 0x03, 0x99, 0x99];
4721         let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4722         let form = constants::DW_FORM_addrx3;
4723         let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x03_0201));
4724         test_parse_attribute(&buf, 3, &unit, form, value);
4725     }
4726 
4727     #[test]
test_parse_attribute_addrx4()4728     fn test_parse_attribute_addrx4() {
4729         let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4730         let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4731         let form = constants::DW_FORM_addrx4;
4732         let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x0403_0201));
4733         test_parse_attribute(&buf, 4, &unit, form, value);
4734     }
4735 
4736     #[test]
test_parse_attribute_loclistx()4737     fn test_parse_attribute_loclistx() {
4738         let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4739 
4740         let bytes_written = {
4741             let mut writable = &mut buf[..];
4742             leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4743         };
4744 
4745         let unit = test_parse_attribute_unit_default();
4746         let form = constants::DW_FORM_loclistx;
4747         let value = AttributeValue::DebugLocListsIndex(DebugLocListsIndex(4097));
4748         test_parse_attribute(&buf, bytes_written, &unit, form, value);
4749     }
4750 
4751     #[test]
test_parse_attribute_rnglistx()4752     fn test_parse_attribute_rnglistx() {
4753         let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4754 
4755         let bytes_written = {
4756             let mut writable = &mut buf[..];
4757             leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4758         };
4759 
4760         let unit = test_parse_attribute_unit_default();
4761         let form = constants::DW_FORM_rnglistx;
4762         let value = AttributeValue::DebugRngListsIndex(DebugRngListsIndex(4097));
4763         test_parse_attribute(&buf, bytes_written, &unit, form, value);
4764     }
4765 
4766     #[test]
test_parse_attribute_indirect()4767     fn test_parse_attribute_indirect() {
4768         let mut buf = [0; 100];
4769 
4770         let bytes_written = {
4771             let mut writable = &mut buf[..];
4772             leb128::write::unsigned(&mut writable, constants::DW_FORM_udata.0.into())
4773                 .expect("should write udata")
4774                 + leb128::write::unsigned(&mut writable, 9_999_999).expect("should write value")
4775         };
4776 
4777         let unit = test_parse_attribute_unit_default();
4778         let form = constants::DW_FORM_indirect;
4779         let value = AttributeValue::Udata(9_999_999);
4780         test_parse_attribute(&buf, bytes_written, &unit, form, value);
4781     }
4782 
4783     #[test]
test_parse_attribute_indirect_implicit_const()4784     fn test_parse_attribute_indirect_implicit_const() {
4785         let encoding = Encoding {
4786             format: Format::Dwarf32,
4787             version: 4,
4788             address_size: 4,
4789         };
4790         let mut buf = [0; 100];
4791         let mut writable = &mut buf[..];
4792         leb128::write::unsigned(&mut writable, constants::DW_FORM_implicit_const.0.into())
4793             .expect("should write implicit_const");
4794 
4795         let input = &mut EndianSlice::new(&buf, LittleEndian);
4796         let spec =
4797             AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_indirect, None);
4798         assert_eq!(
4799             parse_attribute(input, encoding, spec),
4800             Err(Error::InvalidImplicitConst)
4801         );
4802     }
4803 
4804     #[test]
test_attrs_iter()4805     fn test_attrs_iter() {
4806         let encoding = Encoding {
4807             format: Format::Dwarf32,
4808             version: 4,
4809             address_size: 4,
4810         };
4811         let unit = UnitHeader::new(
4812             encoding,
4813             7,
4814             UnitType::Compilation,
4815             DebugAbbrevOffset(0x0807_0605),
4816             DebugInfoOffset(0).into(),
4817             EndianSlice::new(&[], LittleEndian),
4818         );
4819 
4820         let abbrev = Abbreviation::new(
4821             42,
4822             constants::DW_TAG_subprogram,
4823             constants::DW_CHILDREN_yes,
4824             vec![
4825                 AttributeSpecification::new(constants::DW_AT_name, constants::DW_FORM_string, None),
4826                 AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_addr, None),
4827                 AttributeSpecification::new(
4828                     constants::DW_AT_high_pc,
4829                     constants::DW_FORM_addr,
4830                     None,
4831                 ),
4832             ]
4833             .into(),
4834         );
4835 
4836         // "foo", 42, 1337, 4 dangling bytes of 0xaa where children would be
4837         let buf = [
4838             0x66, 0x6f, 0x6f, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x39, 0x05, 0x00, 0x00, 0xaa, 0xaa,
4839             0xaa, 0xaa,
4840         ];
4841 
4842         let entry = DebuggingInformationEntry {
4843             offset: UnitOffset(0),
4844             attrs_slice: EndianSlice::new(&buf, LittleEndian),
4845             attrs_len: Cell::new(None),
4846             abbrev: &abbrev,
4847             unit: &unit,
4848         };
4849 
4850         let mut attrs = AttrsIter {
4851             input: EndianSlice::new(&buf, LittleEndian),
4852             attributes: abbrev.attributes(),
4853             entry: &entry,
4854         };
4855 
4856         match attrs.next() {
4857             Ok(Some(attr)) => {
4858                 assert_eq!(
4859                     attr,
4860                     Attribute {
4861                         name: constants::DW_AT_name,
4862                         value: AttributeValue::String(EndianSlice::new(b"foo", LittleEndian)),
4863                     }
4864                 );
4865             }
4866             otherwise => {
4867                 assert!(false, "Unexpected parse result = {:#?}", otherwise);
4868             }
4869         }
4870 
4871         assert!(entry.attrs_len.get().is_none());
4872 
4873         match attrs.next() {
4874             Ok(Some(attr)) => {
4875                 assert_eq!(
4876                     attr,
4877                     Attribute {
4878                         name: constants::DW_AT_low_pc,
4879                         value: AttributeValue::Addr(0x2a),
4880                     }
4881                 );
4882             }
4883             otherwise => {
4884                 assert!(false, "Unexpected parse result = {:#?}", otherwise);
4885             }
4886         }
4887 
4888         assert!(entry.attrs_len.get().is_none());
4889 
4890         match attrs.next() {
4891             Ok(Some(attr)) => {
4892                 assert_eq!(
4893                     attr,
4894                     Attribute {
4895                         name: constants::DW_AT_high_pc,
4896                         value: AttributeValue::Addr(0x539),
4897                     }
4898                 );
4899             }
4900             otherwise => {
4901                 assert!(false, "Unexpected parse result = {:#?}", otherwise);
4902             }
4903         }
4904 
4905         assert!(entry.attrs_len.get().is_none());
4906 
4907         assert!(attrs.next().expect("should parse next").is_none());
4908         assert!(entry.attrs_len.get().is_some());
4909         assert_eq!(
4910             entry.attrs_len.get().expect("should have entry.attrs_len"),
4911             buf.len() - 4
4912         )
4913     }
4914 
4915     #[test]
test_attrs_iter_incomplete()4916     fn test_attrs_iter_incomplete() {
4917         let encoding = Encoding {
4918             format: Format::Dwarf32,
4919             version: 4,
4920             address_size: 4,
4921         };
4922         let unit = UnitHeader::new(
4923             encoding,
4924             7,
4925             UnitType::Compilation,
4926             DebugAbbrevOffset(0x0807_0605),
4927             DebugInfoOffset(0).into(),
4928             EndianSlice::new(&[], LittleEndian),
4929         );
4930 
4931         let abbrev = Abbreviation::new(
4932             42,
4933             constants::DW_TAG_subprogram,
4934             constants::DW_CHILDREN_yes,
4935             vec![
4936                 AttributeSpecification::new(constants::DW_AT_name, constants::DW_FORM_string, None),
4937                 AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_addr, None),
4938                 AttributeSpecification::new(
4939                     constants::DW_AT_high_pc,
4940                     constants::DW_FORM_addr,
4941                     None,
4942                 ),
4943             ]
4944             .into(),
4945         );
4946 
4947         // "foo"
4948         let buf = [0x66, 0x6f, 0x6f, 0x00];
4949 
4950         let entry = DebuggingInformationEntry {
4951             offset: UnitOffset(0),
4952             attrs_slice: EndianSlice::new(&buf, LittleEndian),
4953             attrs_len: Cell::new(None),
4954             abbrev: &abbrev,
4955             unit: &unit,
4956         };
4957 
4958         let mut attrs = AttrsIter {
4959             input: EndianSlice::new(&buf, LittleEndian),
4960             attributes: abbrev.attributes(),
4961             entry: &entry,
4962         };
4963 
4964         match attrs.next() {
4965             Ok(Some(attr)) => {
4966                 assert_eq!(
4967                     attr,
4968                     Attribute {
4969                         name: constants::DW_AT_name,
4970                         value: AttributeValue::String(EndianSlice::new(b"foo", LittleEndian)),
4971                     }
4972                 );
4973             }
4974             otherwise => {
4975                 assert!(false, "Unexpected parse result = {:#?}", otherwise);
4976             }
4977         }
4978 
4979         assert!(entry.attrs_len.get().is_none());
4980 
4981         // Return error for incomplete attribute.
4982         assert!(attrs.next().is_err());
4983         assert!(entry.attrs_len.get().is_none());
4984 
4985         // Return error for all subsequent calls.
4986         assert!(attrs.next().is_err());
4987         assert!(attrs.next().is_err());
4988         assert!(attrs.next().is_err());
4989         assert!(attrs.next().is_err());
4990         assert!(entry.attrs_len.get().is_none());
4991     }
4992 
assert_entry_name<Endian>(entry: &DebuggingInformationEntry<EndianSlice<Endian>>, name: &str) where Endian: Endianity,4993     fn assert_entry_name<Endian>(entry: &DebuggingInformationEntry<EndianSlice<Endian>>, name: &str)
4994     where
4995         Endian: Endianity,
4996     {
4997         let value = entry
4998             .attr_value(constants::DW_AT_name)
4999             .expect("Should have parsed the name attribute")
5000             .expect("Should have found the name attribute");
5001 
5002         assert_eq!(
5003             value,
5004             AttributeValue::String(EndianSlice::new(name.as_bytes(), Endian::default()))
5005         );
5006     }
5007 
assert_current_name<Endian>(cursor: &EntriesCursor<EndianSlice<Endian>>, name: &str) where Endian: Endianity,5008     fn assert_current_name<Endian>(cursor: &EntriesCursor<EndianSlice<Endian>>, name: &str)
5009     where
5010         Endian: Endianity,
5011     {
5012         let entry = cursor.current().expect("Should have an entry result");
5013         assert_entry_name(entry, name);
5014     }
5015 
assert_next_entry<Endian>(cursor: &mut EntriesCursor<EndianSlice<Endian>>, name: &str) where Endian: Endianity,5016     fn assert_next_entry<Endian>(cursor: &mut EntriesCursor<EndianSlice<Endian>>, name: &str)
5017     where
5018         Endian: Endianity,
5019     {
5020         cursor
5021             .next_entry()
5022             .expect("Should parse next entry")
5023             .expect("Should have an entry");
5024         assert_current_name(cursor, name);
5025     }
5026 
assert_next_entry_null<Endian>(cursor: &mut EntriesCursor<EndianSlice<Endian>>) where Endian: Endianity,5027     fn assert_next_entry_null<Endian>(cursor: &mut EntriesCursor<EndianSlice<Endian>>)
5028     where
5029         Endian: Endianity,
5030     {
5031         cursor
5032             .next_entry()
5033             .expect("Should parse next entry")
5034             .expect("Should have an entry");
5035         assert!(cursor.current().is_none());
5036     }
5037 
assert_next_dfs<Endian>( cursor: &mut EntriesCursor<EndianSlice<Endian>>, name: &str, depth: isize, ) where Endian: Endianity,5038     fn assert_next_dfs<Endian>(
5039         cursor: &mut EntriesCursor<EndianSlice<Endian>>,
5040         name: &str,
5041         depth: isize,
5042     ) where
5043         Endian: Endianity,
5044     {
5045         {
5046             let (val, entry) = cursor
5047                 .next_dfs()
5048                 .expect("Should parse next dfs")
5049                 .expect("Should not be done with traversal");
5050             assert_eq!(val, depth);
5051             assert_entry_name(entry, name);
5052         }
5053         assert_current_name(cursor, name);
5054     }
5055 
assert_next_sibling<Endian>(cursor: &mut EntriesCursor<EndianSlice<Endian>>, name: &str) where Endian: Endianity,5056     fn assert_next_sibling<Endian>(cursor: &mut EntriesCursor<EndianSlice<Endian>>, name: &str)
5057     where
5058         Endian: Endianity,
5059     {
5060         {
5061             let entry = cursor
5062                 .next_sibling()
5063                 .expect("Should parse next sibling")
5064                 .expect("Should not be done with traversal");
5065             assert_entry_name(entry, name);
5066         }
5067         assert_current_name(cursor, name);
5068     }
5069 
assert_valid_sibling_ptr<Endian>(cursor: &EntriesCursor<EndianSlice<Endian>>) where Endian: Endianity,5070     fn assert_valid_sibling_ptr<Endian>(cursor: &EntriesCursor<EndianSlice<Endian>>)
5071     where
5072         Endian: Endianity,
5073     {
5074         let sibling_ptr = cursor
5075             .current()
5076             .expect("Should have current entry")
5077             .attr_value(constants::DW_AT_sibling);
5078         match sibling_ptr {
5079             Ok(Some(AttributeValue::UnitRef(offset))) => {
5080                 cursor
5081                     .unit
5082                     .range_from(offset..)
5083                     .expect("Sibling offset should be valid");
5084             }
5085             _ => panic!("Invalid sibling pointer {:?}", sibling_ptr),
5086         }
5087     }
5088 
entries_cursor_tests_abbrev_buf() -> Vec<u8>5089     fn entries_cursor_tests_abbrev_buf() -> Vec<u8> {
5090         #[rustfmt::skip]
5091         let section = Section::with_endian(Endian::Little)
5092             .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5093                 .abbrev_attr(DW_AT_name, DW_FORM_string)
5094                 .abbrev_attr_null()
5095             .abbrev_null();
5096         section.get_contents().unwrap()
5097     }
5098 
entries_cursor_tests_debug_info_buf() -> Vec<u8>5099     fn entries_cursor_tests_debug_info_buf() -> Vec<u8> {
5100         #[rustfmt::skip]
5101         let section = Section::with_endian(Endian::Little)
5102             .die(1, |s| s.attr_string("001"))
5103                 .die(1, |s| s.attr_string("002"))
5104                     .die(1, |s| s.attr_string("003"))
5105                         .die_null()
5106                     .die_null()
5107                 .die(1, |s| s.attr_string("004"))
5108                     .die(1, |s| s.attr_string("005"))
5109                         .die_null()
5110                     .die(1, |s| s.attr_string("006"))
5111                         .die_null()
5112                     .die_null()
5113                 .die(1, |s| s.attr_string("007"))
5114                     .die(1, |s| s.attr_string("008"))
5115                         .die(1, |s| s.attr_string("009"))
5116                             .die_null()
5117                         .die_null()
5118                     .die_null()
5119                 .die(1, |s| s.attr_string("010"))
5120                     .die_null()
5121                 .die_null();
5122         let entries_buf = section.get_contents().unwrap();
5123 
5124         let encoding = Encoding {
5125             format: Format::Dwarf32,
5126             version: 4,
5127             address_size: 4,
5128         };
5129         let mut unit = UnitHeader {
5130             encoding,
5131             unit_length: 0,
5132             unit_type: UnitType::Compilation,
5133             debug_abbrev_offset: DebugAbbrevOffset(0),
5134             unit_offset: DebugInfoOffset(0).into(),
5135             entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
5136         };
5137         let section = Section::with_endian(Endian::Little).unit(&mut unit);
5138         section.get_contents().unwrap()
5139     }
5140 
5141     #[test]
test_cursor_next_entry_incomplete()5142     fn test_cursor_next_entry_incomplete() {
5143         #[rustfmt::skip]
5144         let section = Section::with_endian(Endian::Little)
5145             .die(1, |s| s.attr_string("001"))
5146                 .die(1, |s| s.attr_string("002"))
5147                     .die(1, |s| s);
5148         let entries_buf = section.get_contents().unwrap();
5149 
5150         let encoding = Encoding {
5151             format: Format::Dwarf32,
5152             version: 4,
5153             address_size: 4,
5154         };
5155         let mut unit = UnitHeader {
5156             encoding,
5157             unit_length: 0,
5158             unit_type: UnitType::Compilation,
5159             debug_abbrev_offset: DebugAbbrevOffset(0),
5160             unit_offset: DebugInfoOffset(0).into(),
5161             entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
5162         };
5163         let section = Section::with_endian(Endian::Little).unit(&mut unit);
5164         let info_buf = &section.get_contents().unwrap();
5165         let debug_info = DebugInfo::new(info_buf, LittleEndian);
5166 
5167         let unit = debug_info
5168             .units()
5169             .next()
5170             .expect("should have a unit result")
5171             .expect("and it should be ok");
5172 
5173         let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5174         let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5175 
5176         let abbrevs = unit
5177             .abbreviations(&debug_abbrev)
5178             .expect("Should parse abbreviations");
5179 
5180         let mut cursor = unit.entries(&abbrevs);
5181 
5182         assert_next_entry(&mut cursor, "001");
5183         assert_next_entry(&mut cursor, "002");
5184 
5185         {
5186             // Entry code is present, but none of the attributes.
5187             cursor
5188                 .next_entry()
5189                 .expect("Should parse next entry")
5190                 .expect("Should have an entry");
5191             let entry = cursor.current().expect("Should have an entry result");
5192             assert!(entry.attrs().next().is_err());
5193         }
5194 
5195         assert!(cursor.next_entry().is_err());
5196         assert!(cursor.next_entry().is_err());
5197     }
5198 
5199     #[test]
test_cursor_next_entry()5200     fn test_cursor_next_entry() {
5201         let info_buf = &entries_cursor_tests_debug_info_buf();
5202         let debug_info = DebugInfo::new(info_buf, LittleEndian);
5203 
5204         let unit = debug_info
5205             .units()
5206             .next()
5207             .expect("should have a unit result")
5208             .expect("and it should be ok");
5209 
5210         let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5211         let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5212 
5213         let abbrevs = unit
5214             .abbreviations(&debug_abbrev)
5215             .expect("Should parse abbreviations");
5216 
5217         let mut cursor = unit.entries(&abbrevs);
5218 
5219         assert_next_entry(&mut cursor, "001");
5220         assert_next_entry(&mut cursor, "002");
5221         assert_next_entry(&mut cursor, "003");
5222         assert_next_entry_null(&mut cursor);
5223         assert_next_entry_null(&mut cursor);
5224         assert_next_entry(&mut cursor, "004");
5225         assert_next_entry(&mut cursor, "005");
5226         assert_next_entry_null(&mut cursor);
5227         assert_next_entry(&mut cursor, "006");
5228         assert_next_entry_null(&mut cursor);
5229         assert_next_entry_null(&mut cursor);
5230         assert_next_entry(&mut cursor, "007");
5231         assert_next_entry(&mut cursor, "008");
5232         assert_next_entry(&mut cursor, "009");
5233         assert_next_entry_null(&mut cursor);
5234         assert_next_entry_null(&mut cursor);
5235         assert_next_entry_null(&mut cursor);
5236         assert_next_entry(&mut cursor, "010");
5237         assert_next_entry_null(&mut cursor);
5238         assert_next_entry_null(&mut cursor);
5239 
5240         assert!(cursor
5241             .next_entry()
5242             .expect("Should parse next entry")
5243             .is_none());
5244         assert!(cursor.current().is_none());
5245     }
5246 
5247     #[test]
test_cursor_next_dfs()5248     fn test_cursor_next_dfs() {
5249         let info_buf = &entries_cursor_tests_debug_info_buf();
5250         let debug_info = DebugInfo::new(info_buf, LittleEndian);
5251 
5252         let unit = debug_info
5253             .units()
5254             .next()
5255             .expect("should have a unit result")
5256             .expect("and it should be ok");
5257 
5258         let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5259         let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5260 
5261         let abbrevs = unit
5262             .abbreviations(&debug_abbrev)
5263             .expect("Should parse abbreviations");
5264 
5265         let mut cursor = unit.entries(&abbrevs);
5266 
5267         assert_next_dfs(&mut cursor, "001", 0);
5268         assert_next_dfs(&mut cursor, "002", 1);
5269         assert_next_dfs(&mut cursor, "003", 1);
5270         assert_next_dfs(&mut cursor, "004", -1);
5271         assert_next_dfs(&mut cursor, "005", 1);
5272         assert_next_dfs(&mut cursor, "006", 0);
5273         assert_next_dfs(&mut cursor, "007", -1);
5274         assert_next_dfs(&mut cursor, "008", 1);
5275         assert_next_dfs(&mut cursor, "009", 1);
5276         assert_next_dfs(&mut cursor, "010", -2);
5277 
5278         assert!(cursor.next_dfs().expect("Should parse next dfs").is_none());
5279         assert!(cursor.current().is_none());
5280     }
5281 
5282     #[test]
test_cursor_next_sibling_no_sibling_ptr()5283     fn test_cursor_next_sibling_no_sibling_ptr() {
5284         let info_buf = &entries_cursor_tests_debug_info_buf();
5285         let debug_info = DebugInfo::new(info_buf, LittleEndian);
5286 
5287         let unit = debug_info
5288             .units()
5289             .next()
5290             .expect("should have a unit result")
5291             .expect("and it should be ok");
5292 
5293         let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5294         let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5295 
5296         let abbrevs = unit
5297             .abbreviations(&debug_abbrev)
5298             .expect("Should parse abbreviations");
5299 
5300         let mut cursor = unit.entries(&abbrevs);
5301 
5302         assert_next_dfs(&mut cursor, "001", 0);
5303 
5304         // Down to the first child of the root entry.
5305 
5306         assert_next_dfs(&mut cursor, "002", 1);
5307 
5308         // Now iterate all children of the root via `next_sibling`.
5309 
5310         assert_next_sibling(&mut cursor, "004");
5311         assert_next_sibling(&mut cursor, "007");
5312         assert_next_sibling(&mut cursor, "010");
5313 
5314         // There should be no more siblings.
5315 
5316         assert!(cursor
5317             .next_sibling()
5318             .expect("Should parse next sibling")
5319             .is_none());
5320         assert!(cursor.current().is_none());
5321     }
5322 
5323     #[test]
test_cursor_next_sibling_continuation()5324     fn test_cursor_next_sibling_continuation() {
5325         let info_buf = &entries_cursor_tests_debug_info_buf();
5326         let debug_info = DebugInfo::new(info_buf, LittleEndian);
5327 
5328         let unit = debug_info
5329             .units()
5330             .next()
5331             .expect("should have a unit result")
5332             .expect("and it should be ok");
5333 
5334         let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5335         let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5336 
5337         let abbrevs = unit
5338             .abbreviations(&debug_abbrev)
5339             .expect("Should parse abbreviations");
5340 
5341         let mut cursor = unit.entries(&abbrevs);
5342 
5343         assert_next_dfs(&mut cursor, "001", 0);
5344 
5345         // Down to the first child of the root entry.
5346 
5347         assert_next_dfs(&mut cursor, "002", 1);
5348 
5349         // Get the next sibling, then iterate its children
5350 
5351         assert_next_sibling(&mut cursor, "004");
5352         assert_next_dfs(&mut cursor, "005", 1);
5353         assert_next_sibling(&mut cursor, "006");
5354         assert!(cursor
5355             .next_sibling()
5356             .expect("Should parse next sibling")
5357             .is_none());
5358         assert!(cursor
5359             .next_sibling()
5360             .expect("Should parse next sibling")
5361             .is_none());
5362         assert!(cursor
5363             .next_sibling()
5364             .expect("Should parse next sibling")
5365             .is_none());
5366         assert!(cursor
5367             .next_sibling()
5368             .expect("Should parse next sibling")
5369             .is_none());
5370 
5371         // And we should be able to continue with the children of the root entry.
5372 
5373         assert_next_dfs(&mut cursor, "007", -1);
5374         assert_next_sibling(&mut cursor, "010");
5375 
5376         // There should be no more siblings.
5377 
5378         assert!(cursor
5379             .next_sibling()
5380             .expect("Should parse next sibling")
5381             .is_none());
5382         assert!(cursor.current().is_none());
5383     }
5384 
entries_cursor_sibling_abbrev_buf() -> Vec<u8>5385     fn entries_cursor_sibling_abbrev_buf() -> Vec<u8> {
5386         #[rustfmt::skip]
5387         let section = Section::with_endian(Endian::Little)
5388             .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5389                 .abbrev_attr(DW_AT_name, DW_FORM_string)
5390                 .abbrev_attr(DW_AT_sibling, DW_FORM_ref1)
5391                 .abbrev_attr_null()
5392             .abbrev(2, DW_TAG_subprogram, DW_CHILDREN_yes)
5393                 .abbrev_attr(DW_AT_name, DW_FORM_string)
5394                 .abbrev_attr_null()
5395                 .abbrev_null();
5396         section.get_contents().unwrap()
5397     }
5398 
entries_cursor_sibling_entries_buf(header_size: usize) -> Vec<u8>5399     fn entries_cursor_sibling_entries_buf(header_size: usize) -> Vec<u8> {
5400         let start = Label::new();
5401         let sibling004_ref = Label::new();
5402         let sibling004 = Label::new();
5403         let sibling009_ref = Label::new();
5404         let sibling009 = Label::new();
5405 
5406         #[rustfmt::skip]
5407         let section = Section::with_endian(Endian::Little)
5408             .mark(&start)
5409             .die(2, |s| s.attr_string("001"))
5410                 // Valid sibling attribute.
5411                 .die(1, |s| s.attr_string("002").D8(&sibling004_ref))
5412                     // Invalid code to ensure the sibling attribute was used.
5413                     .die(10, |s| s.attr_string("003"))
5414                         .die_null()
5415                     .die_null()
5416                 .mark(&sibling004)
5417                 // Invalid sibling attribute.
5418                 .die(1, |s| s.attr_string("004").attr_ref1(255))
5419                     .die(2, |s| s.attr_string("005"))
5420                         .die_null()
5421                     .die_null()
5422                 // Sibling attribute in child only.
5423                 .die(2, |s| s.attr_string("006"))
5424                     // Valid sibling attribute.
5425                     .die(1, |s| s.attr_string("007").D8(&sibling009_ref))
5426                         // Invalid code to ensure the sibling attribute was used.
5427                         .die(10, |s| s.attr_string("008"))
5428                             .die_null()
5429                         .die_null()
5430                     .mark(&sibling009)
5431                     .die(2, |s| s.attr_string("009"))
5432                         .die_null()
5433                     .die_null()
5434                 // No sibling attribute.
5435                 .die(2, |s| s.attr_string("010"))
5436                     .die(2, |s| s.attr_string("011"))
5437                         .die_null()
5438                     .die_null()
5439                 .die_null();
5440 
5441         let offset = header_size as u64 + (&sibling004 - &start) as u64;
5442         sibling004_ref.set_const(offset);
5443 
5444         let offset = header_size as u64 + (&sibling009 - &start) as u64;
5445         sibling009_ref.set_const(offset);
5446 
5447         section.get_contents().unwrap()
5448     }
5449 
test_cursor_next_sibling_with_ptr(cursor: &mut EntriesCursor<EndianSlice<LittleEndian>>)5450     fn test_cursor_next_sibling_with_ptr(cursor: &mut EntriesCursor<EndianSlice<LittleEndian>>) {
5451         assert_next_dfs(cursor, "001", 0);
5452 
5453         // Down to the first child of the root.
5454 
5455         assert_next_dfs(cursor, "002", 1);
5456 
5457         // Now iterate all children of the root via `next_sibling`.
5458 
5459         assert_valid_sibling_ptr(&cursor);
5460         assert_next_sibling(cursor, "004");
5461         assert_next_sibling(cursor, "006");
5462         assert_next_sibling(cursor, "010");
5463 
5464         // There should be no more siblings.
5465 
5466         assert!(cursor
5467             .next_sibling()
5468             .expect("Should parse next sibling")
5469             .is_none());
5470         assert!(cursor.current().is_none());
5471     }
5472 
5473     #[test]
test_debug_info_next_sibling_with_ptr()5474     fn test_debug_info_next_sibling_with_ptr() {
5475         let encoding = Encoding {
5476             format: Format::Dwarf32,
5477             version: 4,
5478             address_size: 4,
5479         };
5480 
5481         let mut unit = UnitHeader {
5482             encoding,
5483             unit_length: 0,
5484             unit_type: UnitType::Compilation,
5485             debug_abbrev_offset: DebugAbbrevOffset(0),
5486             unit_offset: DebugInfoOffset(0).into(),
5487             entries_buf: EndianSlice::new(&[], LittleEndian),
5488         };
5489         let header_size = unit.size_of_header();
5490         let entries_buf = entries_cursor_sibling_entries_buf(header_size);
5491         unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian);
5492         let section = Section::with_endian(Endian::Little).unit(&mut unit);
5493         let info_buf = section.get_contents().unwrap();
5494         let debug_info = DebugInfo::new(&info_buf, LittleEndian);
5495 
5496         let unit = debug_info
5497             .units()
5498             .next()
5499             .expect("should have a unit result")
5500             .expect("and it should be ok");
5501 
5502         let abbrev_buf = entries_cursor_sibling_abbrev_buf();
5503         let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
5504 
5505         let abbrevs = unit
5506             .abbreviations(&debug_abbrev)
5507             .expect("Should parse abbreviations");
5508 
5509         let mut cursor = unit.entries(&abbrevs);
5510         test_cursor_next_sibling_with_ptr(&mut cursor);
5511     }
5512 
5513     #[test]
test_debug_types_next_sibling_with_ptr()5514     fn test_debug_types_next_sibling_with_ptr() {
5515         let encoding = Encoding {
5516             format: Format::Dwarf32,
5517             version: 4,
5518             address_size: 4,
5519         };
5520         let mut unit = UnitHeader {
5521             encoding,
5522             unit_length: 0,
5523             unit_type: UnitType::Type {
5524                 type_signature: DebugTypeSignature(0),
5525                 type_offset: UnitOffset(0),
5526             },
5527             debug_abbrev_offset: DebugAbbrevOffset(0),
5528             unit_offset: DebugTypesOffset(0).into(),
5529             entries_buf: EndianSlice::new(&[], LittleEndian),
5530         };
5531         let header_size = unit.size_of_header();
5532         let entries_buf = entries_cursor_sibling_entries_buf(header_size);
5533         unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian);
5534         let section = Section::with_endian(Endian::Little).unit(&mut unit);
5535         let info_buf = section.get_contents().unwrap();
5536         let debug_types = DebugTypes::new(&info_buf, LittleEndian);
5537 
5538         let unit = debug_types
5539             .units()
5540             .next()
5541             .expect("should have a unit result")
5542             .expect("and it should be ok");
5543 
5544         let abbrev_buf = entries_cursor_sibling_abbrev_buf();
5545         let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
5546 
5547         let abbrevs = unit
5548             .abbreviations(&debug_abbrev)
5549             .expect("Should parse abbreviations");
5550 
5551         let mut cursor = unit.entries(&abbrevs);
5552         test_cursor_next_sibling_with_ptr(&mut cursor);
5553     }
5554 
5555     #[test]
test_entries_at_offset()5556     fn test_entries_at_offset() {
5557         let info_buf = &entries_cursor_tests_debug_info_buf();
5558         let debug_info = DebugInfo::new(info_buf, LittleEndian);
5559 
5560         let unit = debug_info
5561             .units()
5562             .next()
5563             .expect("should have a unit result")
5564             .expect("and it should be ok");
5565 
5566         let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5567         let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5568 
5569         let abbrevs = unit
5570             .abbreviations(&debug_abbrev)
5571             .expect("Should parse abbreviations");
5572 
5573         let mut cursor = unit
5574             .entries_at_offset(&abbrevs, UnitOffset(unit.header_size()))
5575             .unwrap();
5576         assert_next_entry(&mut cursor, "001");
5577 
5578         let cursor = unit.entries_at_offset(&abbrevs, UnitOffset(0));
5579         match cursor {
5580             Err(Error::OffsetOutOfBounds) => {}
5581             otherwise => {
5582                 assert!(false, "Unexpected parse result = {:#?}", otherwise);
5583             }
5584         }
5585     }
5586 
entries_tree_tests_debug_abbrevs_buf() -> Vec<u8>5587     fn entries_tree_tests_debug_abbrevs_buf() -> Vec<u8> {
5588         #[rustfmt::skip]
5589         let section = Section::with_endian(Endian::Little)
5590             .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5591                 .abbrev_attr(DW_AT_name, DW_FORM_string)
5592                 .abbrev_attr_null()
5593             .abbrev(2, DW_TAG_subprogram, DW_CHILDREN_no)
5594                 .abbrev_attr(DW_AT_name, DW_FORM_string)
5595                 .abbrev_attr_null()
5596             .abbrev_null()
5597             .get_contents()
5598             .unwrap();
5599         section
5600     }
5601 
entries_tree_tests_debug_info_buf(header_size: usize) -> (Vec<u8>, UnitOffset)5602     fn entries_tree_tests_debug_info_buf(header_size: usize) -> (Vec<u8>, UnitOffset) {
5603         let start = Label::new();
5604         let entry2 = Label::new();
5605         #[rustfmt::skip]
5606         let section = Section::with_endian(Endian::Little)
5607             .mark(&start)
5608             .die(1, |s| s.attr_string("root"))
5609                 .die(1, |s| s.attr_string("1"))
5610                     .die(1, |s| s.attr_string("1a"))
5611                         .die_null()
5612                     .die(2, |s| s.attr_string("1b"))
5613                     .die_null()
5614                 .mark(&entry2)
5615                 .die(1, |s| s.attr_string("2"))
5616                     .die(1, |s| s.attr_string("2a"))
5617                         .die(1, |s| s.attr_string("2a1"))
5618                             .die_null()
5619                         .die_null()
5620                     .die(1, |s| s.attr_string("2b"))
5621                         .die(2, |s| s.attr_string("2b1"))
5622                         .die_null()
5623                     .die_null()
5624                 .die(1, |s| s.attr_string("3"))
5625                     .die(1, |s| s.attr_string("3a"))
5626                         .die(2, |s| s.attr_string("3a1"))
5627                         .die(2, |s| s.attr_string("3a2"))
5628                         .die_null()
5629                     .die(2, |s| s.attr_string("3b"))
5630                     .die_null()
5631                 .die(2, |s| s.attr_string("final"))
5632                 .die_null()
5633             .get_contents()
5634             .unwrap();
5635         let entry2 = UnitOffset(header_size + (&entry2 - &start) as usize);
5636         (section, entry2)
5637     }
5638 
5639     #[test]
test_entries_tree()5640     fn test_entries_tree() {
5641         fn assert_entry<'input, 'abbrev, 'unit, 'tree, Endian>(
5642             node: Result<
5643                 Option<EntriesTreeNode<'abbrev, 'unit, 'tree, EndianSlice<'input, Endian>>>,
5644             >,
5645             name: &str,
5646         ) -> EntriesTreeIter<'abbrev, 'unit, 'tree, EndianSlice<'input, Endian>>
5647         where
5648             Endian: Endianity,
5649         {
5650             let node = node
5651                 .expect("Should parse entry")
5652                 .expect("Should have entry");
5653             assert_entry_name(node.entry(), name);
5654             node.children()
5655         }
5656 
5657         fn assert_null<E: Endianity>(node: Result<Option<EntriesTreeNode<EndianSlice<E>>>>) {
5658             match node {
5659                 Ok(None) => {}
5660                 otherwise => {
5661                     assert!(false, "Unexpected parse result = {:#?}", otherwise);
5662                 }
5663             }
5664         }
5665 
5666         let abbrevs_buf = entries_tree_tests_debug_abbrevs_buf();
5667         let debug_abbrev = DebugAbbrev::new(&abbrevs_buf, LittleEndian);
5668 
5669         let encoding = Encoding {
5670             format: Format::Dwarf32,
5671             version: 4,
5672             address_size: 4,
5673         };
5674         let mut unit = UnitHeader {
5675             encoding,
5676             unit_length: 0,
5677             unit_type: UnitType::Compilation,
5678             debug_abbrev_offset: DebugAbbrevOffset(0),
5679             unit_offset: DebugInfoOffset(0).into(),
5680             entries_buf: EndianSlice::new(&[], LittleEndian),
5681         };
5682         let header_size = unit.size_of_header();
5683         let (entries_buf, entry2) = entries_tree_tests_debug_info_buf(header_size);
5684         unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian);
5685         let info_buf = Section::with_endian(Endian::Little)
5686             .unit(&mut unit)
5687             .get_contents()
5688             .unwrap();
5689         let debug_info = DebugInfo::new(&info_buf, LittleEndian);
5690 
5691         let unit = debug_info
5692             .units()
5693             .next()
5694             .expect("Should parse unit")
5695             .expect("and it should be some");
5696         let abbrevs = unit
5697             .abbreviations(&debug_abbrev)
5698             .expect("Should parse abbreviations");
5699         let mut tree = unit
5700             .entries_tree(&abbrevs, None)
5701             .expect("Should have entries tree");
5702 
5703         // Test we can restart iteration of the tree.
5704         {
5705             let mut iter = assert_entry(tree.root().map(Some), "root");
5706             assert_entry(iter.next(), "1");
5707         }
5708         {
5709             let mut iter = assert_entry(tree.root().map(Some), "root");
5710             assert_entry(iter.next(), "1");
5711         }
5712 
5713         let mut iter = assert_entry(tree.root().map(Some), "root");
5714         {
5715             // Test iteration with children.
5716             let mut iter = assert_entry(iter.next(), "1");
5717             {
5718                 // Test iteration with children flag, but no children.
5719                 let mut iter = assert_entry(iter.next(), "1a");
5720                 assert_null(iter.next());
5721                 assert_null(iter.next());
5722             }
5723             {
5724                 // Test iteration without children flag.
5725                 let mut iter = assert_entry(iter.next(), "1b");
5726                 assert_null(iter.next());
5727                 assert_null(iter.next());
5728             }
5729             assert_null(iter.next());
5730             assert_null(iter.next());
5731         }
5732         {
5733             // Test skipping over children.
5734             let mut iter = assert_entry(iter.next(), "2");
5735             assert_entry(iter.next(), "2a");
5736             assert_entry(iter.next(), "2b");
5737             assert_null(iter.next());
5738         }
5739         {
5740             // Test skipping after partial iteration.
5741             let mut iter = assert_entry(iter.next(), "3");
5742             {
5743                 let mut iter = assert_entry(iter.next(), "3a");
5744                 assert_entry(iter.next(), "3a1");
5745                 // Parent iter should be able to skip over "3a2".
5746             }
5747             assert_entry(iter.next(), "3b");
5748             assert_null(iter.next());
5749         }
5750         assert_entry(iter.next(), "final");
5751         assert_null(iter.next());
5752 
5753         // Test starting at an offset.
5754         let mut tree = unit
5755             .entries_tree(&abbrevs, Some(entry2))
5756             .expect("Should have entries tree");
5757         let mut iter = assert_entry(tree.root().map(Some), "2");
5758         assert_entry(iter.next(), "2a");
5759         assert_entry(iter.next(), "2b");
5760         assert_null(iter.next());
5761     }
5762 
5763     #[test]
test_entries_raw()5764     fn test_entries_raw() {
5765         fn assert_abbrev<'input, 'abbrev, 'unit, Endian>(
5766             entries: &mut EntriesRaw<'abbrev, 'unit, EndianSlice<'input, Endian>>,
5767             tag: DwTag,
5768         ) -> &'abbrev Abbreviation
5769         where
5770             Endian: Endianity,
5771         {
5772             let abbrev = entries
5773                 .read_abbreviation()
5774                 .expect("Should parse abbrev")
5775                 .expect("Should have abbrev");
5776             assert_eq!(abbrev.tag(), tag);
5777             abbrev
5778         }
5779 
5780         fn assert_null<'input, 'abbrev, 'unit, Endian>(
5781             entries: &mut EntriesRaw<'abbrev, 'unit, EndianSlice<'input, Endian>>,
5782         ) where
5783             Endian: Endianity,
5784         {
5785             match entries.read_abbreviation() {
5786                 Ok(None) => {}
5787                 otherwise => {
5788                     assert!(false, "Unexpected parse result = {:#?}", otherwise);
5789                 }
5790             }
5791         }
5792 
5793         fn assert_attr<'input, 'abbrev, 'unit, Endian>(
5794             entries: &mut EntriesRaw<'abbrev, 'unit, EndianSlice<'input, Endian>>,
5795             spec: Option<AttributeSpecification>,
5796             name: DwAt,
5797             value: &str,
5798         ) where
5799             Endian: Endianity,
5800         {
5801             let spec = spec.expect("Should have attribute specification");
5802             let attr = entries
5803                 .read_attribute(spec)
5804                 .expect("Should parse attribute");
5805             assert_eq!(attr.name(), name);
5806             assert_eq!(
5807                 attr.value(),
5808                 AttributeValue::String(EndianSlice::new(value.as_bytes(), Endian::default()))
5809             );
5810         }
5811 
5812         #[rustfmt::skip]
5813         let section = Section::with_endian(Endian::Little)
5814             .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5815                 .abbrev_attr(DW_AT_name, DW_FORM_string)
5816                 .abbrev_attr(DW_AT_linkage_name, DW_FORM_string)
5817                 .abbrev_attr_null()
5818             .abbrev(2, DW_TAG_variable, DW_CHILDREN_no)
5819                 .abbrev_attr(DW_AT_name, DW_FORM_string)
5820                 .abbrev_attr_null()
5821             .abbrev_null();
5822         let abbrevs_buf = section.get_contents().unwrap();
5823         let debug_abbrev = DebugAbbrev::new(&abbrevs_buf, LittleEndian);
5824 
5825         #[rustfmt::skip]
5826         let section = Section::with_endian(Endian::Little)
5827             .die(1, |s| s.attr_string("f1").attr_string("l1"))
5828                 .die(2, |s| s.attr_string("v1"))
5829                 .die(2, |s| s.attr_string("v2"))
5830                 .die(1, |s| s.attr_string("f2").attr_string("l2"))
5831                     .die_null()
5832                 .die_null();
5833         let entries_buf = section.get_contents().unwrap();
5834 
5835         let encoding = Encoding {
5836             format: Format::Dwarf32,
5837             version: 4,
5838             address_size: 4,
5839         };
5840         let mut unit = UnitHeader {
5841             encoding,
5842             unit_length: 0,
5843             unit_type: UnitType::Compilation,
5844             debug_abbrev_offset: DebugAbbrevOffset(0),
5845             unit_offset: DebugInfoOffset(0).into(),
5846             entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
5847         };
5848         let section = Section::with_endian(Endian::Little).unit(&mut unit);
5849         let info_buf = section.get_contents().unwrap();
5850         let debug_info = DebugInfo::new(&info_buf, LittleEndian);
5851 
5852         let unit = debug_info
5853             .units()
5854             .next()
5855             .expect("should have a unit result")
5856             .expect("and it should be ok");
5857 
5858         let abbrevs = unit
5859             .abbreviations(&debug_abbrev)
5860             .expect("Should parse abbreviations");
5861 
5862         let mut entries = unit
5863             .entries_raw(&abbrevs, None)
5864             .expect("Should have entries");
5865 
5866         assert_eq!(entries.next_depth(), 0);
5867         let abbrev = assert_abbrev(&mut entries, DW_TAG_subprogram);
5868         let mut attrs = abbrev.attributes().iter().copied();
5869         assert_attr(&mut entries, attrs.next(), DW_AT_name, "f1");
5870         assert_attr(&mut entries, attrs.next(), DW_AT_linkage_name, "l1");
5871         assert!(attrs.next().is_none());
5872 
5873         assert_eq!(entries.next_depth(), 1);
5874         let abbrev = assert_abbrev(&mut entries, DW_TAG_variable);
5875         let mut attrs = abbrev.attributes().iter().copied();
5876         assert_attr(&mut entries, attrs.next(), DW_AT_name, "v1");
5877         assert!(attrs.next().is_none());
5878 
5879         assert_eq!(entries.next_depth(), 1);
5880         let abbrev = assert_abbrev(&mut entries, DW_TAG_variable);
5881         let mut attrs = abbrev.attributes().iter().copied();
5882         assert_attr(&mut entries, attrs.next(), DW_AT_name, "v2");
5883         assert!(attrs.next().is_none());
5884 
5885         assert_eq!(entries.next_depth(), 1);
5886         let abbrev = assert_abbrev(&mut entries, DW_TAG_subprogram);
5887         let mut attrs = abbrev.attributes().iter().copied();
5888         assert_attr(&mut entries, attrs.next(), DW_AT_name, "f2");
5889         assert_attr(&mut entries, attrs.next(), DW_AT_linkage_name, "l2");
5890         assert!(attrs.next().is_none());
5891 
5892         assert_eq!(entries.next_depth(), 2);
5893         assert_null(&mut entries);
5894 
5895         assert_eq!(entries.next_depth(), 1);
5896         assert_null(&mut entries);
5897 
5898         assert_eq!(entries.next_depth(), 0);
5899         assert!(entries.is_empty());
5900     }
5901 
5902     #[test]
test_debug_info_offset()5903     fn test_debug_info_offset() {
5904         let padding = &[0; 10];
5905         let entries = &[0; 20];
5906         let encoding = Encoding {
5907             format: Format::Dwarf32,
5908             version: 4,
5909             address_size: 4,
5910         };
5911         let mut unit = UnitHeader {
5912             encoding,
5913             unit_length: 0,
5914             unit_type: UnitType::Compilation,
5915             debug_abbrev_offset: DebugAbbrevOffset(0),
5916             unit_offset: DebugInfoOffset(0).into(),
5917             entries_buf: EndianSlice::new(entries, LittleEndian),
5918         };
5919         Section::with_endian(Endian::Little)
5920             .append_bytes(padding)
5921             .unit(&mut unit);
5922         let offset = padding.len();
5923         let header_length = unit.size_of_header();
5924         let length = unit.length_including_self();
5925         assert_eq!(DebugInfoOffset(0).to_unit_offset(&unit), None);
5926         assert_eq!(DebugInfoOffset(offset - 1).to_unit_offset(&unit), None);
5927         assert_eq!(DebugInfoOffset(offset).to_unit_offset(&unit), None);
5928         assert_eq!(
5929             DebugInfoOffset(offset + header_length - 1).to_unit_offset(&unit),
5930             None
5931         );
5932         assert_eq!(
5933             DebugInfoOffset(offset + header_length).to_unit_offset(&unit),
5934             Some(UnitOffset(header_length))
5935         );
5936         assert_eq!(
5937             DebugInfoOffset(offset + length - 1).to_unit_offset(&unit),
5938             Some(UnitOffset(length - 1))
5939         );
5940         assert_eq!(DebugInfoOffset(offset + length).to_unit_offset(&unit), None);
5941         assert_eq!(
5942             UnitOffset(header_length).to_debug_info_offset(&unit),
5943             Some(DebugInfoOffset(offset + header_length))
5944         );
5945         assert_eq!(
5946             UnitOffset(length - 1).to_debug_info_offset(&unit),
5947             Some(DebugInfoOffset(offset + length - 1))
5948         );
5949     }
5950 
5951     #[test]
test_debug_types_offset()5952     fn test_debug_types_offset() {
5953         let padding = &[0; 10];
5954         let entries = &[0; 20];
5955         let encoding = Encoding {
5956             format: Format::Dwarf32,
5957             version: 4,
5958             address_size: 4,
5959         };
5960         let mut unit = UnitHeader {
5961             encoding,
5962             unit_length: 0,
5963             unit_type: UnitType::Type {
5964                 type_signature: DebugTypeSignature(0),
5965                 type_offset: UnitOffset(0),
5966             },
5967             debug_abbrev_offset: DebugAbbrevOffset(0),
5968             unit_offset: DebugTypesOffset(0).into(),
5969             entries_buf: EndianSlice::new(entries, LittleEndian),
5970         };
5971         Section::with_endian(Endian::Little)
5972             .append_bytes(padding)
5973             .unit(&mut unit);
5974         let offset = padding.len();
5975         let header_length = unit.size_of_header();
5976         let length = unit.length_including_self();
5977         assert_eq!(DebugTypesOffset(0).to_unit_offset(&unit), None);
5978         assert_eq!(DebugTypesOffset(offset - 1).to_unit_offset(&unit), None);
5979         assert_eq!(DebugTypesOffset(offset).to_unit_offset(&unit), None);
5980         assert_eq!(
5981             DebugTypesOffset(offset + header_length - 1).to_unit_offset(&unit),
5982             None
5983         );
5984         assert_eq!(
5985             DebugTypesOffset(offset + header_length).to_unit_offset(&unit),
5986             Some(UnitOffset(header_length))
5987         );
5988         assert_eq!(
5989             DebugTypesOffset(offset + length - 1).to_unit_offset(&unit),
5990             Some(UnitOffset(length - 1))
5991         );
5992         assert_eq!(
5993             DebugTypesOffset(offset + length).to_unit_offset(&unit),
5994             None
5995         );
5996         assert_eq!(
5997             UnitOffset(header_length).to_debug_types_offset(&unit),
5998             Some(DebugTypesOffset(offset + header_length))
5999         );
6000         assert_eq!(
6001             UnitOffset(length - 1).to_debug_types_offset(&unit),
6002             Some(DebugTypesOffset(offset + length - 1))
6003         );
6004     }
6005 
6006     #[test]
test_length_including_self()6007     fn test_length_including_self() {
6008         let encoding = Encoding {
6009             format: Format::Dwarf32,
6010             version: 4,
6011             address_size: 4,
6012         };
6013         let mut unit = UnitHeader {
6014             encoding,
6015             unit_length: 0,
6016             unit_type: UnitType::Compilation,
6017             debug_abbrev_offset: DebugAbbrevOffset(0),
6018             unit_offset: DebugInfoOffset(0).into(),
6019             entries_buf: EndianSlice::new(&[], LittleEndian),
6020         };
6021         unit.encoding.format = Format::Dwarf32;
6022         assert_eq!(unit.length_including_self(), 4);
6023         unit.encoding.format = Format::Dwarf64;
6024         assert_eq!(unit.length_including_self(), 12);
6025         unit.unit_length = 10;
6026         assert_eq!(unit.length_including_self(), 22);
6027     }
6028 
6029     #[test]
test_parse_type_unit_abbrevs()6030     fn test_parse_type_unit_abbrevs() {
6031         let types_buf = [
6032             // Type unit header
6033             0x25, 0x00, 0x00, 0x00, // 32-bit unit length = 37
6034             0x04, 0x00, // Version 4
6035             0x00, 0x00, 0x00, 0x00, // debug_abbrev_offset
6036             0x04, // Address size
6037             0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Type signature
6038             0x01, 0x02, 0x03, 0x04, // Type offset
6039             // DIEs
6040             // Abbreviation code
6041             0x01, // Attribute of form DW_FORM_string = "foo\0"
6042             0x66, 0x6f, 0x6f, 0x00, // Children
6043             // Abbreviation code
6044             0x01, // Attribute of form DW_FORM_string = "foo\0"
6045             0x66, 0x6f, 0x6f, 0x00, // Children
6046             // Abbreviation code
6047             0x01, // Attribute of form DW_FORM_string = "foo\0"
6048             0x66, 0x6f, 0x6f, 0x00, // Children
6049             0x00, // End of children
6050             0x00, // End of children
6051             0x00, // End of children
6052         ];
6053         let debug_types = DebugTypes::new(&types_buf, LittleEndian);
6054 
6055         let abbrev_buf = [
6056             // Code
6057             0x01, // DW_TAG_subprogram
6058             0x2e, // DW_CHILDREN_yes
6059             0x01, // Begin attributes
6060             0x03, // Attribute name = DW_AT_name
6061             0x08, // Attribute form = DW_FORM_string
6062             0x00, 0x00, // End attributes
6063             0x00, // Null terminator
6064         ];
6065 
6066         let get_some_type_unit = || debug_types.units().next().unwrap().unwrap();
6067 
6068         let unit = get_some_type_unit();
6069 
6070         let read_debug_abbrev_section_somehow = || &abbrev_buf;
6071         let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian);
6072         let _abbrevs_for_unit = unit.abbreviations(&debug_abbrev).unwrap();
6073     }
6074 }
6075