Coverage Report

Created: 2025-02-25 06:39

/rust/registry/src/index.crates.io-6f17d22bba15001f/gimli-0.31.1/src/read/abbrev.rs
Line
Count
Source (jump to first uncovered line)
1
//! Functions for parsing DWARF debugging abbreviations.
2
3
use alloc::collections::btree_map;
4
use alloc::sync::Arc;
5
use alloc::vec::Vec;
6
use core::convert::TryFrom;
7
use core::fmt::{self, Debug};
8
use core::iter::FromIterator;
9
use core::ops::Deref;
10
11
use crate::common::{DebugAbbrevOffset, Encoding, SectionId};
12
use crate::constants;
13
use crate::endianity::Endianity;
14
use crate::read::{
15
    DebugInfoUnitHeadersIter, EndianSlice, Error, Reader, ReaderOffset, Result, Section, UnitHeader,
16
};
17
18
/// The `DebugAbbrev` struct represents the abbreviations describing
19
/// `DebuggingInformationEntry`s' attribute names and forms found in the
20
/// `.debug_abbrev` section.
21
#[derive(Debug, Default, Clone, Copy)]
22
pub struct DebugAbbrev<R> {
23
    debug_abbrev_section: R,
24
}
25
26
impl<'input, Endian> DebugAbbrev<EndianSlice<'input, Endian>>
27
where
28
    Endian: Endianity,
29
{
30
    /// Construct a new `DebugAbbrev` instance from the data in the `.debug_abbrev`
31
    /// section.
32
    ///
33
    /// It is the caller's responsibility to read the `.debug_abbrev` section and
34
    /// present it as a `&[u8]` slice. That means using some ELF loader on
35
    /// Linux, a Mach-O loader on macOS, etc.
36
    ///
37
    /// ```
38
    /// use gimli::{DebugAbbrev, LittleEndian};
39
    ///
40
    /// # let buf = [0x00, 0x01, 0x02, 0x03];
41
    /// # let read_debug_abbrev_section_somehow = || &buf;
42
    /// let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian);
43
    /// ```
44
0
    pub fn new(debug_abbrev_section: &'input [u8], endian: Endian) -> Self {
45
0
        Self::from(EndianSlice::new(debug_abbrev_section, endian))
46
0
    }
47
}
48
49
impl<R: Reader> DebugAbbrev<R> {
50
    /// Parse the abbreviations at the given `offset` within this
51
    /// `.debug_abbrev` section.
52
    ///
53
    /// The `offset` should generally be retrieved from a unit header.
54
0
    pub fn abbreviations(
55
0
        &self,
56
0
        debug_abbrev_offset: DebugAbbrevOffset<R::Offset>,
57
0
    ) -> Result<Abbreviations> {
58
0
        let input = &mut self.debug_abbrev_section.clone();
59
0
        input.skip(debug_abbrev_offset.0)?;
60
0
        Abbreviations::parse(input)
61
0
    }
Unexecuted instantiation: <gimli::read::abbrev::DebugAbbrev<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::abbreviations
Unexecuted instantiation: <gimli::read::abbrev::DebugAbbrev<_>>::abbreviations
62
}
63
64
impl<T> DebugAbbrev<T> {
65
    /// Create a `DebugAbbrev` section that references the data in `self`.
66
    ///
67
    /// This is useful when `R` implements `Reader` but `T` does not.
68
    ///
69
    /// Used by `DwarfSections::borrow`.
70
0
    pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAbbrev<R>
71
0
    where
72
0
        F: FnMut(&'a T) -> R,
73
0
    {
74
0
        borrow(&self.debug_abbrev_section).into()
75
0
    }
76
}
77
78
impl<R> Section<R> for DebugAbbrev<R> {
79
0
    fn id() -> SectionId {
80
0
        SectionId::DebugAbbrev
81
0
    }
Unexecuted instantiation: <gimli::read::abbrev::DebugAbbrev<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::abbrev::DebugAbbrev<_> as gimli::read::Section<_>>::id
82
83
0
    fn reader(&self) -> &R {
84
0
        &self.debug_abbrev_section
85
0
    }
Unexecuted instantiation: <gimli::read::abbrev::DebugAbbrev<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::abbrev::DebugAbbrev<_> as gimli::read::Section<_>>::reader
86
}
87
88
impl<R> From<R> for DebugAbbrev<R> {
89
0
    fn from(debug_abbrev_section: R) -> Self {
90
0
        DebugAbbrev {
91
0
            debug_abbrev_section,
92
0
        }
93
0
    }
Unexecuted instantiation: <gimli::read::abbrev::DebugAbbrev<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::abbrev::DebugAbbrev<_> as core::convert::From<_>>::from
94
}
95
96
/// The strategy to use for caching abbreviations.
97
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
98
#[non_exhaustive]
99
pub enum AbbreviationsCacheStrategy {
100
    /// Cache abbreviations that are used more than once.
101
    ///
102
    /// This is useful if the units in the `.debug_info` section will be parsed only once.
103
    Duplicates,
104
    /// Cache all abbreviations.
105
    ///
106
    /// This is useful if the units in the `.debug_info` section will be parsed more than once.
107
    All,
108
}
109
110
/// A cache of previously parsed `Abbreviations`.
111
#[derive(Debug, Default)]
112
pub struct AbbreviationsCache {
113
    abbreviations: btree_map::BTreeMap<u64, Result<Arc<Abbreviations>>>,
114
}
115
116
impl AbbreviationsCache {
117
    /// Create an empty abbreviations cache.
118
0
    pub fn new() -> Self {
119
0
        Self::default()
120
0
    }
121
122
    /// Parse abbreviations and store them in the cache.
123
    ///
124
    /// This will iterate over the given units to determine the abbreviations
125
    /// offsets. Any existing cache entries are discarded.
126
    ///
127
    /// Errors during parsing abbreviations are also stored in the cache.
128
    /// Errors during iterating over the units are ignored.
129
0
    pub fn populate<R: Reader>(
130
0
        &mut self,
131
0
        strategy: AbbreviationsCacheStrategy,
132
0
        debug_abbrev: &DebugAbbrev<R>,
133
0
        mut units: DebugInfoUnitHeadersIter<R>,
134
0
    ) {
135
0
        let mut offsets = Vec::new();
136
0
        match strategy {
137
            AbbreviationsCacheStrategy::Duplicates => {
138
0
                while let Ok(Some(unit)) = units.next() {
139
0
                    offsets.push(unit.debug_abbrev_offset());
140
0
                }
141
0
                offsets.sort_unstable_by_key(|offset| offset.0);
142
0
                let mut prev_offset = R::Offset::from_u8(0);
143
0
                let mut count = 0;
144
0
                offsets.retain(|offset| {
145
0
                    if count == 0 || prev_offset != offset.0 {
146
0
                        prev_offset = offset.0;
147
0
                        count = 1;
148
0
                    } else {
149
0
                        count += 1;
150
0
                    }
151
0
                    count == 2
152
0
                });
153
0
            }
154
            AbbreviationsCacheStrategy::All => {
155
0
                while let Ok(Some(unit)) = units.next() {
156
0
                    offsets.push(unit.debug_abbrev_offset());
157
0
                }
158
0
                offsets.sort_unstable_by_key(|offset| offset.0);
159
0
                offsets.dedup();
160
0
            }
161
        }
162
0
        self.abbreviations = offsets
163
0
            .into_iter()
164
0
            .map(|offset| {
165
0
                (
166
0
                    offset.0.into_u64(),
167
0
                    debug_abbrev.abbreviations(offset).map(Arc::new),
168
0
                )
169
0
            })
170
0
            .collect();
171
0
    }
172
173
    /// Set an entry in the abbreviations cache.
174
    ///
175
    /// This is only required if you want to manually populate the cache.
176
0
    pub fn set<R: Reader>(
177
0
        &mut self,
178
0
        offset: DebugAbbrevOffset<R::Offset>,
179
0
        abbreviations: Arc<Abbreviations>,
180
0
    ) {
181
0
        self.abbreviations
182
0
            .insert(offset.0.into_u64(), Ok(abbreviations));
183
0
    }
184
185
    /// Parse the abbreviations at the given offset.
186
    ///
187
    /// This uses the cache if possible, but does not update it.
188
0
    pub fn get<R: Reader>(
189
0
        &self,
190
0
        debug_abbrev: &DebugAbbrev<R>,
191
0
        offset: DebugAbbrevOffset<R::Offset>,
192
0
    ) -> Result<Arc<Abbreviations>> {
193
0
        match self.abbreviations.get(&offset.0.into_u64()) {
194
0
            Some(entry) => entry.clone(),
195
0
            None => debug_abbrev.abbreviations(offset).map(Arc::new),
196
        }
197
0
    }
Unexecuted instantiation: <gimli::read::abbrev::AbbreviationsCache>::get::<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>
Unexecuted instantiation: <gimli::read::abbrev::AbbreviationsCache>::get::<_>
198
}
199
200
/// A set of type abbreviations.
201
///
202
/// Construct an `Abbreviations` instance with the
203
/// [`abbreviations()`](struct.UnitHeader.html#method.abbreviations)
204
/// method.
205
#[derive(Debug, Default, Clone)]
206
pub struct Abbreviations {
207
    vec: Vec<Abbreviation>,
208
    map: btree_map::BTreeMap<u64, Abbreviation>,
209
}
210
211
impl Abbreviations {
212
    /// Construct a new, empty set of abbreviations.
213
0
    fn empty() -> Abbreviations {
214
0
        Abbreviations {
215
0
            vec: Vec::new(),
216
0
            map: btree_map::BTreeMap::new(),
217
0
        }
218
0
    }
219
220
    /// Insert an abbreviation into the set.
221
    ///
222
    /// Returns `Ok` if it is the first abbreviation in the set with its code,
223
    /// `Err` if the code is a duplicate and there already exists an
224
    /// abbreviation in the set with the given abbreviation's code.
225
0
    fn insert(&mut self, abbrev: Abbreviation) -> ::core::result::Result<(), ()> {
226
0
        let code_usize = abbrev.code as usize;
227
0
        if code_usize as u64 == abbrev.code {
228
            // Optimize for sequential abbreviation codes by storing them
229
            // in a Vec, as long as the map doesn't already contain them.
230
            // A potential further optimization would be to allow some
231
            // holes in the Vec, but there's no need for that yet.
232
0
            if code_usize - 1 < self.vec.len() {
233
0
                return Err(());
234
0
            } else if code_usize - 1 == self.vec.len() {
235
0
                if !self.map.is_empty() && self.map.contains_key(&abbrev.code) {
236
0
                    return Err(());
237
                } else {
238
0
                    self.vec.push(abbrev);
239
0
                    return Ok(());
240
                }
241
0
            }
242
0
        }
243
0
        match self.map.entry(abbrev.code) {
244
0
            btree_map::Entry::Occupied(_) => Err(()),
245
0
            btree_map::Entry::Vacant(entry) => {
246
0
                entry.insert(abbrev);
247
0
                Ok(())
248
            }
249
        }
250
0
    }
251
252
    /// Get the abbreviation associated with the given code.
253
    #[inline]
254
0
    pub fn get(&self, code: u64) -> Option<&Abbreviation> {
255
0
        if let Ok(code) = usize::try_from(code) {
256
0
            let index = code.checked_sub(1)?;
257
0
            if index < self.vec.len() {
258
0
                return Some(&self.vec[index]);
259
0
            }
260
0
        }
261
262
0
        self.map.get(&code)
263
0
    }
Unexecuted instantiation: <gimli::read::abbrev::Abbreviations>::get
Unexecuted instantiation: <gimli::read::abbrev::Abbreviations>::get
264
265
    /// Parse a series of abbreviations, terminated by a null abbreviation.
266
0
    fn parse<R: Reader>(input: &mut R) -> Result<Abbreviations> {
267
0
        let mut abbrevs = Abbreviations::empty();
268
269
0
        while let Some(abbrev) = Abbreviation::parse(input)? {
270
0
            if abbrevs.insert(abbrev).is_err() {
271
0
                return Err(Error::DuplicateAbbreviationCode);
272
0
            }
273
        }
274
275
0
        Ok(abbrevs)
276
0
    }
Unexecuted instantiation: <gimli::read::abbrev::Abbreviations>::parse::<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>
Unexecuted instantiation: <gimli::read::abbrev::Abbreviations>::parse::<_>
277
}
278
279
/// An abbreviation describes the shape of a `DebuggingInformationEntry`'s type:
280
/// its code, tag type, whether it has children, and its set of attributes.
281
#[derive(Debug, Clone, PartialEq, Eq)]
282
pub struct Abbreviation {
283
    code: u64,
284
    tag: constants::DwTag,
285
    has_children: constants::DwChildren,
286
    attributes: Attributes,
287
}
288
289
impl Abbreviation {
290
    /// Construct a new `Abbreviation`.
291
    ///
292
    /// ### Panics
293
    ///
294
    /// Panics if `code` is `0`.
295
0
    pub(crate) fn new(
296
0
        code: u64,
297
0
        tag: constants::DwTag,
298
0
        has_children: constants::DwChildren,
299
0
        attributes: Attributes,
300
0
    ) -> Abbreviation {
301
0
        assert_ne!(code, 0);
302
0
        Abbreviation {
303
0
            code,
304
0
            tag,
305
0
            has_children,
306
0
            attributes,
307
0
        }
308
0
    }
309
310
    /// Get this abbreviation's code.
311
    #[inline]
312
0
    pub fn code(&self) -> u64 {
313
0
        self.code
314
0
    }
315
316
    /// Get this abbreviation's tag.
317
    #[inline]
318
0
    pub fn tag(&self) -> constants::DwTag {
319
0
        self.tag
320
0
    }
Unexecuted instantiation: <gimli::read::abbrev::Abbreviation>::tag
Unexecuted instantiation: <gimli::read::abbrev::Abbreviation>::tag
321
322
    /// Return true if this abbreviation's type has children, false otherwise.
323
    #[inline]
324
0
    pub fn has_children(&self) -> bool {
325
0
        self.has_children == constants::DW_CHILDREN_yes
326
0
    }
Unexecuted instantiation: <gimli::read::abbrev::Abbreviation>::has_children
Unexecuted instantiation: <gimli::read::abbrev::Abbreviation>::has_children
327
328
    /// Get this abbreviation's attributes.
329
    #[inline]
330
0
    pub fn attributes(&self) -> &[AttributeSpecification] {
331
0
        &self.attributes[..]
332
0
    }
Unexecuted instantiation: <gimli::read::abbrev::Abbreviation>::attributes
Unexecuted instantiation: <gimli::read::abbrev::Abbreviation>::attributes
333
334
    /// Parse an abbreviation's tag.
335
0
    fn parse_tag<R: Reader>(input: &mut R) -> Result<constants::DwTag> {
336
0
        let val = input.read_uleb128_u16()?;
337
0
        if val == 0 {
338
0
            Err(Error::AbbreviationTagZero)
339
        } else {
340
0
            Ok(constants::DwTag(val))
341
        }
342
0
    }
Unexecuted instantiation: <gimli::read::abbrev::Abbreviation>::parse_tag::<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>
Unexecuted instantiation: <gimli::read::abbrev::Abbreviation>::parse_tag::<_>
343
344
    /// Parse an abbreviation's "does the type have children?" byte.
345
0
    fn parse_has_children<R: Reader>(input: &mut R) -> Result<constants::DwChildren> {
346
0
        let val = input.read_u8()?;
347
0
        let val = constants::DwChildren(val);
348
0
        if val == constants::DW_CHILDREN_no || val == constants::DW_CHILDREN_yes {
349
0
            Ok(val)
350
        } else {
351
0
            Err(Error::BadHasChildren)
352
        }
353
0
    }
Unexecuted instantiation: <gimli::read::abbrev::Abbreviation>::parse_has_children::<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>
Unexecuted instantiation: <gimli::read::abbrev::Abbreviation>::parse_has_children::<_>
354
355
    /// Parse a series of attribute specifications, terminated by a null attribute
356
    /// specification.
357
0
    fn parse_attributes<R: Reader>(input: &mut R) -> Result<Attributes> {
358
0
        let mut attrs = Attributes::new();
359
360
0
        while let Some(attr) = AttributeSpecification::parse(input)? {
361
0
            attrs.push(attr);
362
0
        }
363
364
0
        Ok(attrs)
365
0
    }
Unexecuted instantiation: <gimli::read::abbrev::Abbreviation>::parse_attributes::<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>
Unexecuted instantiation: <gimli::read::abbrev::Abbreviation>::parse_attributes::<_>
366
367
    /// Parse an abbreviation. Return `None` for the null abbreviation, `Some`
368
    /// for an actual abbreviation.
369
0
    fn parse<R: Reader>(input: &mut R) -> Result<Option<Abbreviation>> {
370
0
        let code = input.read_uleb128()?;
371
0
        if code == 0 {
372
0
            return Ok(None);
373
0
        }
374
375
0
        let tag = Self::parse_tag(input)?;
376
0
        let has_children = Self::parse_has_children(input)?;
377
0
        let attributes = Self::parse_attributes(input)?;
378
0
        let abbrev = Abbreviation::new(code, tag, has_children, attributes);
379
0
        Ok(Some(abbrev))
380
0
    }
Unexecuted instantiation: <gimli::read::abbrev::Abbreviation>::parse::<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>
Unexecuted instantiation: <gimli::read::abbrev::Abbreviation>::parse::<_>
381
}
382
383
/// A list of attributes found in an `Abbreviation`
384
#[derive(Clone)]
385
pub(crate) enum Attributes {
386
    Inline {
387
        buf: [AttributeSpecification; MAX_ATTRIBUTES_INLINE],
388
        len: usize,
389
    },
390
    Heap(Vec<AttributeSpecification>),
391
}
392
393
// Length of 5 based on benchmark results for both x86-64 and i686.
394
const MAX_ATTRIBUTES_INLINE: usize = 5;
395
396
impl Attributes {
397
    /// Returns a new empty list of attributes
398
0
    fn new() -> Attributes {
399
0
        let default =
400
0
            AttributeSpecification::new(constants::DW_AT_null, constants::DW_FORM_null, None);
401
0
        Attributes::Inline {
402
0
            buf: [default; 5],
403
0
            len: 0,
404
0
        }
405
0
    }
406
407
    /// Pushes a new value onto this list of attributes.
408
0
    fn push(&mut self, attr: AttributeSpecification) {
409
0
        match self {
410
0
            Attributes::Heap(list) => list.push(attr),
411
            Attributes::Inline {
412
0
                buf,
413
0
                len: MAX_ATTRIBUTES_INLINE,
414
0
            } => {
415
0
                let mut list = buf.to_vec();
416
0
                list.push(attr);
417
0
                *self = Attributes::Heap(list);
418
0
            }
419
0
            Attributes::Inline { buf, len } => {
420
0
                buf[*len] = attr;
421
0
                *len += 1;
422
0
            }
423
        }
424
0
    }
425
}
426
427
impl Debug for Attributes {
428
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
429
0
        (**self).fmt(f)
430
0
    }
431
}
432
433
impl PartialEq for Attributes {
434
0
    fn eq(&self, other: &Attributes) -> bool {
435
0
        **self == **other
436
0
    }
437
}
438
439
impl Eq for Attributes {}
440
441
impl Deref for Attributes {
442
    type Target = [AttributeSpecification];
443
0
    fn deref(&self) -> &[AttributeSpecification] {
444
0
        match self {
445
0
            Attributes::Inline { buf, len } => &buf[..*len],
446
0
            Attributes::Heap(list) => list,
447
        }
448
0
    }
449
}
450
451
impl FromIterator<AttributeSpecification> for Attributes {
452
0
    fn from_iter<I>(iter: I) -> Attributes
453
0
    where
454
0
        I: IntoIterator<Item = AttributeSpecification>,
455
0
    {
456
0
        let mut list = Attributes::new();
457
0
        for item in iter {
458
0
            list.push(item);
459
0
        }
460
0
        list
461
0
    }
462
}
463
464
impl From<Vec<AttributeSpecification>> for Attributes {
465
0
    fn from(list: Vec<AttributeSpecification>) -> Attributes {
466
0
        Attributes::Heap(list)
467
0
    }
468
}
469
470
/// The description of an attribute in an abbreviated type. It is a pair of name
471
/// and form.
472
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
473
pub struct AttributeSpecification {
474
    name: constants::DwAt,
475
    form: constants::DwForm,
476
    implicit_const_value: i64,
477
}
478
479
impl AttributeSpecification {
480
    /// Construct a new `AttributeSpecification` from the given name and form
481
    /// and implicit const value.
482
    #[inline]
483
0
    pub fn new(
484
0
        name: constants::DwAt,
485
0
        form: constants::DwForm,
486
0
        implicit_const_value: Option<i64>,
487
0
    ) -> AttributeSpecification {
488
0
        debug_assert!(
489
0
            (form == constants::DW_FORM_implicit_const && implicit_const_value.is_some())
490
0
                || (form != constants::DW_FORM_implicit_const && implicit_const_value.is_none())
491
        );
492
0
        AttributeSpecification {
493
0
            name,
494
0
            form,
495
0
            implicit_const_value: implicit_const_value.unwrap_or(0),
496
0
        }
497
0
    }
Unexecuted instantiation: <gimli::read::abbrev::AttributeSpecification>::new
Unexecuted instantiation: <gimli::read::abbrev::AttributeSpecification>::new
498
499
    /// Get the attribute's name.
500
    #[inline]
501
0
    pub fn name(&self) -> constants::DwAt {
502
0
        self.name
503
0
    }
Unexecuted instantiation: <gimli::read::abbrev::AttributeSpecification>::name
Unexecuted instantiation: <gimli::read::abbrev::AttributeSpecification>::name
504
505
    /// Get the attribute's form.
506
    #[inline]
507
0
    pub fn form(&self) -> constants::DwForm {
508
0
        self.form
509
0
    }
Unexecuted instantiation: <gimli::read::abbrev::AttributeSpecification>::form
Unexecuted instantiation: <gimli::read::abbrev::AttributeSpecification>::form
510
511
    /// Get the attribute's implicit const value.
512
    #[inline]
513
0
    pub fn implicit_const_value(&self) -> Option<i64> {
514
0
        if self.form == constants::DW_FORM_implicit_const {
515
0
            Some(self.implicit_const_value)
516
        } else {
517
0
            None
518
        }
519
0
    }
Unexecuted instantiation: <gimli::read::abbrev::AttributeSpecification>::implicit_const_value
Unexecuted instantiation: <gimli::read::abbrev::AttributeSpecification>::implicit_const_value
520
521
    /// Return the size of the attribute, in bytes.
522
    ///
523
    /// Note that because some attributes are variably sized, the size cannot
524
    /// always be known without parsing, in which case we return `None`.
525
0
    pub fn size<R: Reader>(&self, header: &UnitHeader<R>) -> Option<usize> {
526
0
        get_attribute_size(self.form, header.encoding()).map(usize::from)
527
0
    }
528
529
    /// Parse an attribute's form.
530
0
    fn parse_form<R: Reader>(input: &mut R) -> Result<constants::DwForm> {
531
0
        let val = input.read_uleb128_u16()?;
532
0
        if val == 0 {
533
0
            Err(Error::AttributeFormZero)
534
        } else {
535
0
            Ok(constants::DwForm(val))
536
        }
537
0
    }
Unexecuted instantiation: <gimli::read::abbrev::AttributeSpecification>::parse_form::<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>
Unexecuted instantiation: <gimli::read::abbrev::AttributeSpecification>::parse_form::<_>
538
539
    /// Parse an attribute specification. Returns `None` for the null attribute
540
    /// specification, `Some` for an actual attribute specification.
541
0
    fn parse<R: Reader>(input: &mut R) -> Result<Option<AttributeSpecification>> {
542
0
        let name = input.read_uleb128_u16()?;
543
0
        if name == 0 {
544
            // Parse the null attribute specification.
545
0
            let form = input.read_uleb128_u16()?;
546
0
            return if form == 0 {
547
0
                Ok(None)
548
            } else {
549
0
                Err(Error::ExpectedZero)
550
            };
551
0
        }
552
0
553
0
        let name = constants::DwAt(name);
554
0
        let form = Self::parse_form(input)?;
555
0
        let implicit_const_value = if form == constants::DW_FORM_implicit_const {
556
0
            Some(input.read_sleb128()?)
557
        } else {
558
0
            None
559
        };
560
0
        let spec = AttributeSpecification::new(name, form, implicit_const_value);
561
0
        Ok(Some(spec))
562
0
    }
Unexecuted instantiation: <gimli::read::abbrev::AttributeSpecification>::parse::<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>
Unexecuted instantiation: <gimli::read::abbrev::AttributeSpecification>::parse::<_>
563
}
564
565
#[inline]
566
0
pub(crate) fn get_attribute_size(form: constants::DwForm, encoding: Encoding) -> Option<u8> {
567
0
    match form {
568
0
        constants::DW_FORM_addr => Some(encoding.address_size),
569
570
0
        constants::DW_FORM_implicit_const | constants::DW_FORM_flag_present => Some(0),
571
572
        constants::DW_FORM_data1
573
        | constants::DW_FORM_flag
574
        | constants::DW_FORM_strx1
575
        | constants::DW_FORM_ref1
576
0
        | constants::DW_FORM_addrx1 => Some(1),
577
578
        constants::DW_FORM_data2
579
        | constants::DW_FORM_ref2
580
        | constants::DW_FORM_addrx2
581
0
        | constants::DW_FORM_strx2 => Some(2),
582
583
0
        constants::DW_FORM_addrx3 | constants::DW_FORM_strx3 => Some(3),
584
585
        constants::DW_FORM_data4
586
        | constants::DW_FORM_ref_sup4
587
        | constants::DW_FORM_ref4
588
        | constants::DW_FORM_strx4
589
0
        | constants::DW_FORM_addrx4 => Some(4),
590
591
        constants::DW_FORM_data8
592
        | constants::DW_FORM_ref8
593
        | constants::DW_FORM_ref_sig8
594
0
        | constants::DW_FORM_ref_sup8 => Some(8),
595
596
0
        constants::DW_FORM_data16 => Some(16),
597
598
        constants::DW_FORM_sec_offset
599
        | constants::DW_FORM_GNU_ref_alt
600
        | constants::DW_FORM_strp
601
        | constants::DW_FORM_strp_sup
602
        | constants::DW_FORM_GNU_strp_alt
603
0
        | constants::DW_FORM_line_strp => Some(encoding.format.word_size()),
604
605
        constants::DW_FORM_ref_addr => {
606
            // This is an offset, but DWARF version 2 specifies that DW_FORM_ref_addr
607
            // has the same size as an address on the target system.  This was changed
608
            // in DWARF version 3.
609
0
            Some(if encoding.version == 2 {
610
0
                encoding.address_size
611
            } else {
612
0
                encoding.format.word_size()
613
            })
614
        }
615
616
        // Variably sized forms.
617
        constants::DW_FORM_block
618
        | constants::DW_FORM_block1
619
        | constants::DW_FORM_block2
620
        | constants::DW_FORM_block4
621
        | constants::DW_FORM_exprloc
622
        | constants::DW_FORM_ref_udata
623
        | constants::DW_FORM_string
624
        | constants::DW_FORM_sdata
625
        | constants::DW_FORM_udata
626
0
        | constants::DW_FORM_indirect => None,
627
628
        // We don't know the size of unknown forms.
629
0
        _ => None,
630
    }
631
0
}
Unexecuted instantiation: gimli::read::abbrev::get_attribute_size
Unexecuted instantiation: gimli::read::abbrev::get_attribute_size
632
633
#[cfg(test)]
634
pub(crate) mod tests {
635
    use super::*;
636
    use crate::constants;
637
    use crate::endianity::LittleEndian;
638
    use crate::read::{EndianSlice, Error};
639
    use crate::test_util::GimliSectionMethods;
640
    #[cfg(target_pointer_width = "32")]
641
    use core::u32;
642
    use test_assembler::Section;
643
644
    pub trait AbbrevSectionMethods {
645
        fn abbrev(self, code: u64, tag: constants::DwTag, children: constants::DwChildren) -> Self;
646
        fn abbrev_null(self) -> Self;
647
        fn abbrev_attr(self, name: constants::DwAt, form: constants::DwForm) -> Self;
648
        fn abbrev_attr_implicit_const(self, name: constants::DwAt, value: i64) -> Self;
649
        fn abbrev_attr_null(self) -> Self;
650
    }
651
652
    impl AbbrevSectionMethods for Section {
653
        fn abbrev(self, code: u64, tag: constants::DwTag, children: constants::DwChildren) -> Self {
654
            self.uleb(code).uleb(tag.0.into()).D8(children.0)
655
        }
656
657
        fn abbrev_null(self) -> Self {
658
            self.D8(0)
659
        }
660
661
        fn abbrev_attr(self, name: constants::DwAt, form: constants::DwForm) -> Self {
662
            self.uleb(name.0.into()).uleb(form.0.into())
663
        }
664
665
        fn abbrev_attr_implicit_const(self, name: constants::DwAt, value: i64) -> Self {
666
            self.uleb(name.0.into())
667
                .uleb(constants::DW_FORM_implicit_const.0.into())
668
                .sleb(value)
669
        }
670
671
        fn abbrev_attr_null(self) -> Self {
672
            self.D8(0).D8(0)
673
        }
674
    }
675
676
    #[test]
677
    fn test_debug_abbrev_ok() {
678
        let extra_start = [1, 2, 3, 4];
679
        let expected_rest = [5, 6, 7, 8];
680
        #[rustfmt::skip]
681
        let buf = Section::new()
682
            .append_bytes(&extra_start)
683
            .abbrev(2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
684
                .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
685
                .abbrev_attr_null()
686
            .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
687
                .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
688
                .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
689
                .abbrev_attr_null()
690
            .abbrev_null()
691
            .append_bytes(&expected_rest)
692
            .get_contents()
693
            .unwrap();
694
695
        let abbrev1 = Abbreviation::new(
696
            1,
697
            constants::DW_TAG_compile_unit,
698
            constants::DW_CHILDREN_yes,
699
            vec![
700
                AttributeSpecification::new(
701
                    constants::DW_AT_producer,
702
                    constants::DW_FORM_strp,
703
                    None,
704
                ),
705
                AttributeSpecification::new(
706
                    constants::DW_AT_language,
707
                    constants::DW_FORM_data2,
708
                    None,
709
                ),
710
            ]
711
            .into(),
712
        );
713
714
        let abbrev2 = Abbreviation::new(
715
            2,
716
            constants::DW_TAG_subprogram,
717
            constants::DW_CHILDREN_no,
718
            vec![AttributeSpecification::new(
719
                constants::DW_AT_name,
720
                constants::DW_FORM_string,
721
                None,
722
            )]
723
            .into(),
724
        );
725
726
        let debug_abbrev = DebugAbbrev::new(&buf, LittleEndian);
727
        let debug_abbrev_offset = DebugAbbrevOffset(extra_start.len());
728
        let abbrevs = debug_abbrev
729
            .abbreviations(debug_abbrev_offset)
730
            .expect("Should parse abbreviations");
731
        assert_eq!(abbrevs.get(1), Some(&abbrev1));
732
        assert_eq!(abbrevs.get(2), Some(&abbrev2));
733
    }
734
735
    #[test]
736
    fn test_abbreviations_insert() {
737
        fn abbrev(code: u16) -> Abbreviation {
738
            Abbreviation::new(
739
                code.into(),
740
                constants::DwTag(code),
741
                constants::DW_CHILDREN_no,
742
                vec![].into(),
743
            )
744
        }
745
746
        fn assert_abbrev(abbrevs: &Abbreviations, code: u16) {
747
            let abbrev = abbrevs.get(code.into()).unwrap();
748
            assert_eq!(abbrev.tag(), constants::DwTag(code));
749
        }
750
751
        // Sequential insert.
752
        let mut abbrevs = Abbreviations::empty();
753
        abbrevs.insert(abbrev(1)).unwrap();
754
        abbrevs.insert(abbrev(2)).unwrap();
755
        assert_eq!(abbrevs.vec.len(), 2);
756
        assert!(abbrevs.map.is_empty());
757
        assert_abbrev(&abbrevs, 1);
758
        assert_abbrev(&abbrevs, 2);
759
760
        // Out of order insert.
761
        let mut abbrevs = Abbreviations::empty();
762
        abbrevs.insert(abbrev(2)).unwrap();
763
        abbrevs.insert(abbrev(3)).unwrap();
764
        assert!(abbrevs.vec.is_empty());
765
        assert_abbrev(&abbrevs, 2);
766
        assert_abbrev(&abbrevs, 3);
767
768
        // Mixed order insert.
769
        let mut abbrevs = Abbreviations::empty();
770
        abbrevs.insert(abbrev(1)).unwrap();
771
        abbrevs.insert(abbrev(3)).unwrap();
772
        abbrevs.insert(abbrev(2)).unwrap();
773
        assert_eq!(abbrevs.vec.len(), 2);
774
        assert_abbrev(&abbrevs, 1);
775
        assert_abbrev(&abbrevs, 2);
776
        assert_abbrev(&abbrevs, 3);
777
778
        // Duplicate code in vec.
779
        let mut abbrevs = Abbreviations::empty();
780
        abbrevs.insert(abbrev(1)).unwrap();
781
        abbrevs.insert(abbrev(2)).unwrap();
782
        assert_eq!(abbrevs.insert(abbrev(1)), Err(()));
783
        assert_eq!(abbrevs.insert(abbrev(2)), Err(()));
784
785
        // Duplicate code in map when adding to map.
786
        let mut abbrevs = Abbreviations::empty();
787
        abbrevs.insert(abbrev(2)).unwrap();
788
        assert_eq!(abbrevs.insert(abbrev(2)), Err(()));
789
790
        // Duplicate code in map when adding to vec.
791
        let mut abbrevs = Abbreviations::empty();
792
        abbrevs.insert(abbrev(2)).unwrap();
793
        abbrevs.insert(abbrev(1)).unwrap();
794
        assert_eq!(abbrevs.insert(abbrev(2)), Err(()));
795
796
        // 32-bit usize conversions.
797
        let mut abbrevs = Abbreviations::empty();
798
        abbrevs.insert(abbrev(2)).unwrap();
799
    }
800
801
    #[test]
802
    #[cfg(target_pointer_width = "32")]
803
    fn test_abbreviations_insert_32() {
804
        fn abbrev(code: u64) -> Abbreviation {
805
            Abbreviation::new(
806
                code,
807
                constants::DwTag(code as u16),
808
                constants::DW_CHILDREN_no,
809
                vec![].into(),
810
            )
811
        }
812
813
        fn assert_abbrev(abbrevs: &Abbreviations, code: u64) {
814
            let abbrev = abbrevs.get(code).unwrap();
815
            assert_eq!(abbrev.tag(), constants::DwTag(code as u16));
816
        }
817
818
        let mut abbrevs = Abbreviations::empty();
819
        abbrevs.insert(abbrev(1)).unwrap();
820
821
        let wrap_code = (u32::MAX as u64 + 1) + 1;
822
        // `get` should not treat the wrapped code as `1`.
823
        assert_eq!(abbrevs.get(wrap_code), None);
824
        // `insert` should not treat the wrapped code as `1`.
825
        abbrevs.insert(abbrev(wrap_code)).unwrap();
826
        assert_abbrev(&abbrevs, 1);
827
        assert_abbrev(&abbrevs, wrap_code);
828
    }
829
830
    #[test]
831
    fn test_parse_abbreviations_ok() {
832
        let expected_rest = [1, 2, 3, 4];
833
        #[rustfmt::skip]
834
        let buf = Section::new()
835
            .abbrev(2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
836
                .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
837
                .abbrev_attr_null()
838
            .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
839
                .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
840
                .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
841
                .abbrev_attr_null()
842
            .abbrev_null()
843
            .append_bytes(&expected_rest)
844
            .get_contents()
845
            .unwrap();
846
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
847
848
        let abbrev1 = Abbreviation::new(
849
            1,
850
            constants::DW_TAG_compile_unit,
851
            constants::DW_CHILDREN_yes,
852
            vec![
853
                AttributeSpecification::new(
854
                    constants::DW_AT_producer,
855
                    constants::DW_FORM_strp,
856
                    None,
857
                ),
858
                AttributeSpecification::new(
859
                    constants::DW_AT_language,
860
                    constants::DW_FORM_data2,
861
                    None,
862
                ),
863
            ]
864
            .into(),
865
        );
866
867
        let abbrev2 = Abbreviation::new(
868
            2,
869
            constants::DW_TAG_subprogram,
870
            constants::DW_CHILDREN_no,
871
            vec![AttributeSpecification::new(
872
                constants::DW_AT_name,
873
                constants::DW_FORM_string,
874
                None,
875
            )]
876
            .into(),
877
        );
878
879
        let abbrevs = Abbreviations::parse(rest).expect("Should parse abbreviations");
880
        assert_eq!(abbrevs.get(1), Some(&abbrev1));
881
        assert_eq!(abbrevs.get(2), Some(&abbrev2));
882
        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
883
    }
884
885
    #[test]
886
    fn test_parse_abbreviations_duplicate() {
887
        let expected_rest = [1, 2, 3, 4];
888
        #[rustfmt::skip]
889
        let buf = Section::new()
890
            .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
891
                .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
892
                .abbrev_attr_null()
893
            .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
894
                .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
895
                .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
896
                .abbrev_attr_null()
897
            .abbrev_null()
898
            .append_bytes(&expected_rest)
899
            .get_contents()
900
            .unwrap();
901
        let buf = &mut EndianSlice::new(&buf, LittleEndian);
902
903
        match Abbreviations::parse(buf) {
904
            Err(Error::DuplicateAbbreviationCode) => {}
905
            otherwise => panic!("Unexpected result: {:?}", otherwise),
906
        };
907
    }
908
909
    #[test]
910
    fn test_parse_abbreviation_tag_ok() {
911
        let buf = [0x01, 0x02];
912
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
913
        let tag = Abbreviation::parse_tag(rest).expect("Should parse tag");
914
        assert_eq!(tag, constants::DW_TAG_array_type);
915
        assert_eq!(*rest, EndianSlice::new(&buf[1..], LittleEndian));
916
    }
917
918
    #[test]
919
    fn test_parse_abbreviation_tag_zero() {
920
        let buf = [0x00];
921
        let buf = &mut EndianSlice::new(&buf, LittleEndian);
922
        match Abbreviation::parse_tag(buf) {
923
            Err(Error::AbbreviationTagZero) => {}
924
            otherwise => panic!("Unexpected result: {:?}", otherwise),
925
        };
926
    }
927
928
    #[test]
929
    fn test_parse_abbreviation_has_children() {
930
        let buf = [0x00, 0x01, 0x02];
931
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
932
        let val = Abbreviation::parse_has_children(rest).expect("Should parse children");
933
        assert_eq!(val, constants::DW_CHILDREN_no);
934
        let val = Abbreviation::parse_has_children(rest).expect("Should parse children");
935
        assert_eq!(val, constants::DW_CHILDREN_yes);
936
        match Abbreviation::parse_has_children(rest) {
937
            Err(Error::BadHasChildren) => {}
938
            otherwise => panic!("Unexpected result: {:?}", otherwise),
939
        };
940
    }
941
942
    #[test]
943
    fn test_parse_abbreviation_ok() {
944
        let expected_rest = [0x01, 0x02, 0x03, 0x04];
945
        let buf = Section::new()
946
            .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
947
            .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
948
            .abbrev_attr_null()
949
            .append_bytes(&expected_rest)
950
            .get_contents()
951
            .unwrap();
952
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
953
954
        let expect = Some(Abbreviation::new(
955
            1,
956
            constants::DW_TAG_subprogram,
957
            constants::DW_CHILDREN_no,
958
            vec![AttributeSpecification::new(
959
                constants::DW_AT_name,
960
                constants::DW_FORM_string,
961
                None,
962
            )]
963
            .into(),
964
        ));
965
966
        let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation");
967
        assert_eq!(abbrev, expect);
968
        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
969
    }
970
971
    #[test]
972
    fn test_parse_abbreviation_implicit_const_ok() {
973
        let expected_rest = [0x01, 0x02, 0x03, 0x04];
974
        let buf = Section::new()
975
            .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
976
            .abbrev_attr_implicit_const(constants::DW_AT_name, -42)
977
            .abbrev_attr_null()
978
            .append_bytes(&expected_rest)
979
            .get_contents()
980
            .unwrap();
981
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
982
983
        let expect = Some(Abbreviation::new(
984
            1,
985
            constants::DW_TAG_subprogram,
986
            constants::DW_CHILDREN_no,
987
            vec![AttributeSpecification::new(
988
                constants::DW_AT_name,
989
                constants::DW_FORM_implicit_const,
990
                Some(-42),
991
            )]
992
            .into(),
993
        ));
994
995
        let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation");
996
        assert_eq!(abbrev, expect);
997
        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
998
    }
999
1000
    #[test]
1001
    fn test_parse_abbreviation_implicit_const_no_const() {
1002
        let buf = Section::new()
1003
            .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
1004
            .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_implicit_const)
1005
            .get_contents()
1006
            .unwrap();
1007
        let buf = &mut EndianSlice::new(&buf, LittleEndian);
1008
1009
        match Abbreviation::parse(buf) {
1010
            Err(Error::UnexpectedEof(_)) => {}
1011
            otherwise => panic!("Unexpected result: {:?}", otherwise),
1012
        }
1013
    }
1014
1015
    #[test]
1016
    fn test_parse_null_abbreviation_ok() {
1017
        let expected_rest = [0x01, 0x02, 0x03, 0x04];
1018
        let buf = Section::new()
1019
            .abbrev_null()
1020
            .append_bytes(&expected_rest)
1021
            .get_contents()
1022
            .unwrap();
1023
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
1024
1025
        let abbrev = Abbreviation::parse(rest).expect("Should parse null abbreviation");
1026
        assert!(abbrev.is_none());
1027
        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
1028
    }
1029
1030
    #[test]
1031
    fn test_parse_attribute_form_ok() {
1032
        let buf = [0x01, 0x02];
1033
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
1034
        let tag = AttributeSpecification::parse_form(rest).expect("Should parse form");
1035
        assert_eq!(tag, constants::DW_FORM_addr);
1036
        assert_eq!(*rest, EndianSlice::new(&buf[1..], LittleEndian));
1037
    }
1038
1039
    #[test]
1040
    fn test_parse_attribute_form_zero() {
1041
        let buf = [0x00];
1042
        let buf = &mut EndianSlice::new(&buf, LittleEndian);
1043
        match AttributeSpecification::parse_form(buf) {
1044
            Err(Error::AttributeFormZero) => {}
1045
            otherwise => panic!("Unexpected result: {:?}", otherwise),
1046
        };
1047
    }
1048
1049
    #[test]
1050
    fn test_parse_null_attribute_specification_ok() {
1051
        let buf = [0x00, 0x00, 0x01];
1052
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
1053
        let attr =
1054
            AttributeSpecification::parse(rest).expect("Should parse null attribute specification");
1055
        assert!(attr.is_none());
1056
        assert_eq!(*rest, EndianSlice::new(&buf[2..], LittleEndian));
1057
    }
1058
1059
    #[test]
1060
    fn test_parse_attribute_specifications_name_zero() {
1061
        let buf = [0x00, 0x01, 0x00, 0x00];
1062
        let buf = &mut EndianSlice::new(&buf, LittleEndian);
1063
        match AttributeSpecification::parse(buf) {
1064
            Err(Error::ExpectedZero) => {}
1065
            otherwise => panic!("Unexpected result: {:?}", otherwise),
1066
        };
1067
    }
1068
1069
    #[test]
1070
    fn test_parse_attribute_specifications_form_zero() {
1071
        let buf = [0x01, 0x00, 0x00, 0x00];
1072
        let buf = &mut EndianSlice::new(&buf, LittleEndian);
1073
        match AttributeSpecification::parse(buf) {
1074
            Err(Error::AttributeFormZero) => {}
1075
            otherwise => panic!("Unexpected result: {:?}", otherwise),
1076
        };
1077
    }
1078
1079
    #[test]
1080
    fn test_get_abbrev_zero() {
1081
        let mut abbrevs = Abbreviations::empty();
1082
        abbrevs
1083
            .insert(Abbreviation::new(
1084
                1,
1085
                constants::DwTag(1),
1086
                constants::DW_CHILDREN_no,
1087
                vec![].into(),
1088
            ))
1089
            .unwrap();
1090
        assert!(abbrevs.get(0).is_none());
1091
    }
1092
}