Coverage Report

Created: 2026-03-14 06:47

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