Coverage Report

Created: 2026-02-26 07:03

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