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