gimli/read/
abbrev.rs

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