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