Skip to main content

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            let code = abbrev.code;
271            if abbrevs.insert(abbrev).is_err() {
272                return Err(Error::DuplicateAbbreviationCode(code));
273            }
274        }
275
276        Ok(abbrevs)
277    }
278}
279
280/// An abbreviation describes the shape of a `DebuggingInformationEntry`'s type:
281/// its code, tag type, whether it has children, and its set of attributes.
282#[derive(Debug, Clone, PartialEq, Eq)]
283pub struct Abbreviation {
284    code: u64,
285    tag: constants::DwTag,
286    has_children: constants::DwChildren,
287    attributes: Attributes,
288}
289
290impl Abbreviation {
291    /// Construct a new `Abbreviation`.
292    ///
293    /// ### Panics
294    ///
295    /// Panics if `code` is `0`.
296    pub(crate) fn new(
297        code: u64,
298        tag: constants::DwTag,
299        has_children: constants::DwChildren,
300        attributes: Attributes,
301    ) -> Abbreviation {
302        assert_ne!(code, 0);
303        Abbreviation {
304            code,
305            tag,
306            has_children,
307            attributes,
308        }
309    }
310
311    /// Get this abbreviation's code.
312    #[inline]
313    pub fn code(&self) -> u64 {
314        self.code
315    }
316
317    /// Get this abbreviation's tag.
318    #[inline]
319    pub fn tag(&self) -> constants::DwTag {
320        self.tag
321    }
322
323    /// Return true if this abbreviation's type has children, false otherwise.
324    #[inline]
325    pub fn has_children(&self) -> bool {
326        self.has_children == constants::DW_CHILDREN_yes
327    }
328
329    /// Get this abbreviation's attributes.
330    #[inline]
331    pub fn attributes(&self) -> &[AttributeSpecification] {
332        &self.attributes[..]
333    }
334
335    /// Parse an abbreviation's tag.
336    fn parse_tag<R: Reader>(input: &mut R) -> Result<constants::DwTag> {
337        let val = input.read_uleb128_u16()?;
338        if val == 0 {
339            Err(Error::AbbreviationTagZero)
340        } else {
341            Ok(constants::DwTag(val))
342        }
343    }
344
345    /// Parse an abbreviation's "does the type have children?" byte.
346    fn parse_has_children<R: Reader>(input: &mut R) -> Result<constants::DwChildren> {
347        let val = input.read_u8()?;
348        let val = constants::DwChildren(val);
349        if val == constants::DW_CHILDREN_no || val == constants::DW_CHILDREN_yes {
350            Ok(val)
351        } else {
352            Err(Error::InvalidAbbreviationChildren(val))
353        }
354    }
355
356    /// Parse a series of attribute specifications, terminated by a null attribute
357    /// specification.
358    fn parse_attributes<R: Reader>(input: &mut R) -> Result<Attributes> {
359        let mut attrs = Attributes::new();
360
361        while let Some(attr) = AttributeSpecification::parse(input)? {
362            attrs.push(attr);
363        }
364
365        Ok(attrs)
366    }
367
368    /// Parse an abbreviation. Return `None` for the null abbreviation, `Some`
369    /// for an actual abbreviation.
370    fn parse<R: Reader>(input: &mut R) -> Result<Option<Abbreviation>> {
371        if input.is_empty() {
372            // Try to recover from missing null terminator.
373            // If the input was actually truncated, then we'll return an error later
374            // when trying to find the missing abbreviation.
375            return Ok(None);
376        }
377        let code = input.read_uleb128()?;
378        if code == 0 {
379            return Ok(None);
380        }
381
382        let tag = Self::parse_tag(input)?;
383        let has_children = Self::parse_has_children(input)?;
384        let attributes = Self::parse_attributes(input)?;
385        let abbrev = Abbreviation::new(code, tag, has_children, attributes);
386        Ok(Some(abbrev))
387    }
388}
389
390/// A list of attributes found in an `Abbreviation`
391#[derive(Clone)]
392pub(crate) enum Attributes {
393    Inline {
394        buf: [AttributeSpecification; MAX_ATTRIBUTES_INLINE],
395        len: usize,
396    },
397    Heap(Vec<AttributeSpecification>),
398}
399
400// Length of 5 based on benchmark results for both x86-64 and i686.
401const MAX_ATTRIBUTES_INLINE: usize = 5;
402
403impl Attributes {
404    /// Returns a new empty list of attributes
405    fn new() -> Attributes {
406        let default =
407            AttributeSpecification::new(constants::DW_AT_null, constants::DW_FORM_null, None);
408        Attributes::Inline {
409            buf: [default; 5],
410            len: 0,
411        }
412    }
413
414    /// Pushes a new value onto this list of attributes.
415    fn push(&mut self, attr: AttributeSpecification) {
416        match self {
417            Attributes::Heap(list) => list.push(attr),
418            Attributes::Inline {
419                buf,
420                len: MAX_ATTRIBUTES_INLINE,
421            } => {
422                let mut list = buf.to_vec();
423                list.push(attr);
424                *self = Attributes::Heap(list);
425            }
426            Attributes::Inline { buf, len } => {
427                buf[*len] = attr;
428                *len += 1;
429            }
430        }
431    }
432}
433
434impl Debug for Attributes {
435    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
436        (**self).fmt(f)
437    }
438}
439
440impl PartialEq for Attributes {
441    fn eq(&self, other: &Attributes) -> bool {
442        **self == **other
443    }
444}
445
446impl Eq for Attributes {}
447
448impl Deref for Attributes {
449    type Target = [AttributeSpecification];
450    fn deref(&self) -> &[AttributeSpecification] {
451        match self {
452            Attributes::Inline { buf, len } => &buf[..*len],
453            Attributes::Heap(list) => list,
454        }
455    }
456}
457
458impl FromIterator<AttributeSpecification> for Attributes {
459    fn from_iter<I>(iter: I) -> Attributes
460    where
461        I: IntoIterator<Item = AttributeSpecification>,
462    {
463        let mut list = Attributes::new();
464        for item in iter {
465            list.push(item);
466        }
467        list
468    }
469}
470
471impl From<Vec<AttributeSpecification>> for Attributes {
472    fn from(list: Vec<AttributeSpecification>) -> Attributes {
473        Attributes::Heap(list)
474    }
475}
476
477/// The description of an attribute in an abbreviated type. It is a pair of name
478/// and form.
479#[derive(Debug, Clone, Copy, PartialEq, Eq)]
480pub struct AttributeSpecification {
481    name: constants::DwAt,
482    form: constants::DwForm,
483    implicit_const_value: i64,
484}
485
486impl AttributeSpecification {
487    /// Construct a new `AttributeSpecification` from the given name and form
488    /// and implicit const value.
489    #[inline]
490    pub fn new(
491        name: constants::DwAt,
492        form: constants::DwForm,
493        implicit_const_value: Option<i64>,
494    ) -> AttributeSpecification {
495        debug_assert!(
496            (form == constants::DW_FORM_implicit_const && implicit_const_value.is_some())
497                || (form != constants::DW_FORM_implicit_const && implicit_const_value.is_none())
498        );
499        AttributeSpecification {
500            name,
501            form,
502            implicit_const_value: implicit_const_value.unwrap_or(0),
503        }
504    }
505
506    /// Get the attribute's name.
507    #[inline]
508    pub fn name(&self) -> constants::DwAt {
509        self.name
510    }
511
512    /// Get the attribute's form.
513    #[inline]
514    pub fn form(&self) -> constants::DwForm {
515        self.form
516    }
517
518    /// Get the attribute's implicit const value.
519    #[inline]
520    pub fn implicit_const_value(&self) -> Option<i64> {
521        if self.form == constants::DW_FORM_implicit_const {
522            Some(self.implicit_const_value)
523        } else {
524            None
525        }
526    }
527
528    /// Return the size of the attribute, in bytes.
529    ///
530    /// Note that because some attributes are variably sized, the size cannot
531    /// always be known without parsing, in which case we return `None`.
532    pub fn size<R: Reader>(&self, header: &UnitHeader<R>) -> Option<usize> {
533        get_attribute_size(self.form, header.encoding()).map(usize::from)
534    }
535
536    /// Parse an attribute specification. Returns `None` for the null attribute
537    /// specification, `Some` for an actual attribute specification.
538    fn parse<R: Reader>(input: &mut R) -> Result<Option<AttributeSpecification>> {
539        let name = input.read_uleb128_u16()?;
540        let form = input.read_uleb128_u16()?;
541        match (name, form) {
542            (0, 0) => return Ok(None),
543            (0, _) => return Err(Error::AttributeNameZero),
544            (_, 0) => return Err(Error::AttributeFormZero),
545            (_, _) => {}
546        }
547        let name = constants::DwAt(name);
548        let form = constants::DwForm(form);
549        let implicit_const_value = if form == constants::DW_FORM_implicit_const {
550            Some(input.read_sleb128()?)
551        } else {
552            None
553        };
554        let spec = AttributeSpecification::new(name, form, implicit_const_value);
555        Ok(Some(spec))
556    }
557}
558
559#[inline]
560pub(crate) fn get_attribute_size(form: constants::DwForm, encoding: Encoding) -> Option<u8> {
561    match form {
562        constants::DW_FORM_addr => Some(encoding.address_size),
563
564        constants::DW_FORM_implicit_const | constants::DW_FORM_flag_present => Some(0),
565
566        constants::DW_FORM_data1
567        | constants::DW_FORM_flag
568        | constants::DW_FORM_strx1
569        | constants::DW_FORM_ref1
570        | constants::DW_FORM_addrx1 => Some(1),
571
572        constants::DW_FORM_data2
573        | constants::DW_FORM_ref2
574        | constants::DW_FORM_addrx2
575        | constants::DW_FORM_strx2 => Some(2),
576
577        constants::DW_FORM_addrx3 | constants::DW_FORM_strx3 => Some(3),
578
579        constants::DW_FORM_data4
580        | constants::DW_FORM_ref_sup4
581        | constants::DW_FORM_ref4
582        | constants::DW_FORM_strx4
583        | constants::DW_FORM_addrx4 => Some(4),
584
585        constants::DW_FORM_data8
586        | constants::DW_FORM_ref8
587        | constants::DW_FORM_ref_sig8
588        | constants::DW_FORM_ref_sup8 => Some(8),
589
590        constants::DW_FORM_data16 => Some(16),
591
592        constants::DW_FORM_sec_offset
593        | constants::DW_FORM_GNU_ref_alt
594        | constants::DW_FORM_strp
595        | constants::DW_FORM_strp_sup
596        | constants::DW_FORM_GNU_strp_alt
597        | constants::DW_FORM_line_strp => Some(encoding.format.word_size()),
598
599        constants::DW_FORM_ref_addr => {
600            // This is an offset, but DWARF version 2 specifies that DW_FORM_ref_addr
601            // has the same size as an address on the target system.  This was changed
602            // in DWARF version 3.
603            Some(if encoding.version == 2 {
604                encoding.address_size
605            } else {
606                encoding.format.word_size()
607            })
608        }
609
610        // Variably sized forms.
611        constants::DW_FORM_block
612        | constants::DW_FORM_block1
613        | constants::DW_FORM_block2
614        | constants::DW_FORM_block4
615        | constants::DW_FORM_exprloc
616        | constants::DW_FORM_ref_udata
617        | constants::DW_FORM_string
618        | constants::DW_FORM_sdata
619        | constants::DW_FORM_udata
620        | constants::DW_FORM_indirect => None,
621
622        // We don't know the size of unknown forms.
623        _ => None,
624    }
625}
626
627#[cfg(test)]
628pub(crate) mod tests {
629    use super::*;
630    use crate::constants;
631    use crate::endianity::LittleEndian;
632    use crate::read::{EndianSlice, Error};
633    use crate::test_util::GimliSectionMethods;
634    #[cfg(target_pointer_width = "32")]
635    use core::u32;
636    use test_assembler::Section;
637
638    pub trait AbbrevSectionMethods {
639        fn abbrev(self, code: u64, tag: constants::DwTag, children: constants::DwChildren) -> Self;
640        fn abbrev_null(self) -> Self;
641        fn abbrev_attr(self, name: constants::DwAt, form: constants::DwForm) -> Self;
642        fn abbrev_attr_implicit_const(self, name: constants::DwAt, value: i64) -> Self;
643        fn abbrev_attr_null(self) -> Self;
644    }
645
646    impl AbbrevSectionMethods for Section {
647        fn abbrev(self, code: u64, tag: constants::DwTag, children: constants::DwChildren) -> Self {
648            self.uleb(code).uleb(tag.0.into()).D8(children.0)
649        }
650
651        fn abbrev_null(self) -> Self {
652            self.D8(0)
653        }
654
655        fn abbrev_attr(self, name: constants::DwAt, form: constants::DwForm) -> Self {
656            self.uleb(name.0.into()).uleb(form.0.into())
657        }
658
659        fn abbrev_attr_implicit_const(self, name: constants::DwAt, value: i64) -> Self {
660            self.uleb(name.0.into())
661                .uleb(constants::DW_FORM_implicit_const.0.into())
662                .sleb(value)
663        }
664
665        fn abbrev_attr_null(self) -> Self {
666            self.D8(0).D8(0)
667        }
668    }
669
670    #[test]
671    fn test_debug_abbrev_ok() {
672        let extra_start = [1, 2, 3, 4];
673        let expected_rest = [5, 6, 7, 8];
674        #[rustfmt::skip]
675        let buf = Section::new()
676            .append_bytes(&extra_start)
677            .abbrev(2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
678                .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
679                .abbrev_attr_null()
680            .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
681                .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
682                .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
683                .abbrev_attr_null()
684            .abbrev_null()
685            .append_bytes(&expected_rest)
686            .get_contents()
687            .unwrap();
688
689        let abbrev1 = Abbreviation::new(
690            1,
691            constants::DW_TAG_compile_unit,
692            constants::DW_CHILDREN_yes,
693            vec![
694                AttributeSpecification::new(
695                    constants::DW_AT_producer,
696                    constants::DW_FORM_strp,
697                    None,
698                ),
699                AttributeSpecification::new(
700                    constants::DW_AT_language,
701                    constants::DW_FORM_data2,
702                    None,
703                ),
704            ]
705            .into(),
706        );
707
708        let abbrev2 = Abbreviation::new(
709            2,
710            constants::DW_TAG_subprogram,
711            constants::DW_CHILDREN_no,
712            vec![AttributeSpecification::new(
713                constants::DW_AT_name,
714                constants::DW_FORM_string,
715                None,
716            )]
717            .into(),
718        );
719
720        let debug_abbrev = DebugAbbrev::new(&buf, LittleEndian);
721        let debug_abbrev_offset = DebugAbbrevOffset(extra_start.len());
722        let abbrevs = debug_abbrev
723            .abbreviations(debug_abbrev_offset)
724            .expect("Should parse abbreviations");
725        assert_eq!(abbrevs.get(1), Some(&abbrev1));
726        assert_eq!(abbrevs.get(2), Some(&abbrev2));
727    }
728
729    #[test]
730    fn test_abbreviations_insert() {
731        fn abbrev(code: u16) -> Abbreviation {
732            Abbreviation::new(
733                code.into(),
734                constants::DwTag(code),
735                constants::DW_CHILDREN_no,
736                vec![].into(),
737            )
738        }
739
740        fn assert_abbrev(abbrevs: &Abbreviations, code: u16) {
741            let abbrev = abbrevs.get(code.into()).unwrap();
742            assert_eq!(abbrev.tag(), constants::DwTag(code));
743        }
744
745        // Sequential insert.
746        let mut abbrevs = Abbreviations::empty();
747        abbrevs.insert(abbrev(1)).unwrap();
748        abbrevs.insert(abbrev(2)).unwrap();
749        assert_eq!(abbrevs.vec.len(), 2);
750        assert!(abbrevs.map.is_empty());
751        assert_abbrev(&abbrevs, 1);
752        assert_abbrev(&abbrevs, 2);
753
754        // Out of order insert.
755        let mut abbrevs = Abbreviations::empty();
756        abbrevs.insert(abbrev(2)).unwrap();
757        abbrevs.insert(abbrev(3)).unwrap();
758        assert!(abbrevs.vec.is_empty());
759        assert_abbrev(&abbrevs, 2);
760        assert_abbrev(&abbrevs, 3);
761
762        // Mixed order insert.
763        let mut abbrevs = Abbreviations::empty();
764        abbrevs.insert(abbrev(1)).unwrap();
765        abbrevs.insert(abbrev(3)).unwrap();
766        abbrevs.insert(abbrev(2)).unwrap();
767        assert_eq!(abbrevs.vec.len(), 2);
768        assert_abbrev(&abbrevs, 1);
769        assert_abbrev(&abbrevs, 2);
770        assert_abbrev(&abbrevs, 3);
771
772        // Duplicate code in vec.
773        let mut abbrevs = Abbreviations::empty();
774        abbrevs.insert(abbrev(1)).unwrap();
775        abbrevs.insert(abbrev(2)).unwrap();
776        assert_eq!(abbrevs.insert(abbrev(1)), Err(()));
777        assert_eq!(abbrevs.insert(abbrev(2)), Err(()));
778
779        // Duplicate code in map when adding to map.
780        let mut abbrevs = Abbreviations::empty();
781        abbrevs.insert(abbrev(2)).unwrap();
782        assert_eq!(abbrevs.insert(abbrev(2)), Err(()));
783
784        // Duplicate code in map when adding to vec.
785        let mut abbrevs = Abbreviations::empty();
786        abbrevs.insert(abbrev(2)).unwrap();
787        abbrevs.insert(abbrev(1)).unwrap();
788        assert_eq!(abbrevs.insert(abbrev(2)), Err(()));
789
790        // 32-bit usize conversions.
791        let mut abbrevs = Abbreviations::empty();
792        abbrevs.insert(abbrev(2)).unwrap();
793    }
794
795    #[test]
796    #[cfg(target_pointer_width = "32")]
797    fn test_abbreviations_insert_32() {
798        fn abbrev(code: u64) -> Abbreviation {
799            Abbreviation::new(
800                code,
801                constants::DwTag(code as u16),
802                constants::DW_CHILDREN_no,
803                vec![].into(),
804            )
805        }
806
807        fn assert_abbrev(abbrevs: &Abbreviations, code: u64) {
808            let abbrev = abbrevs.get(code).unwrap();
809            assert_eq!(abbrev.tag(), constants::DwTag(code as u16));
810        }
811
812        let mut abbrevs = Abbreviations::empty();
813        abbrevs.insert(abbrev(1)).unwrap();
814
815        let wrap_code = (u32::MAX as u64 + 1) + 1;
816        // `get` should not treat the wrapped code as `1`.
817        assert_eq!(abbrevs.get(wrap_code), None);
818        // `insert` should not treat the wrapped code as `1`.
819        abbrevs.insert(abbrev(wrap_code)).unwrap();
820        assert_abbrev(&abbrevs, 1);
821        assert_abbrev(&abbrevs, wrap_code);
822    }
823
824    #[test]
825    fn test_parse_abbreviations_ok() {
826        let expected_rest = [1, 2, 3, 4];
827        #[rustfmt::skip]
828        let buf = Section::new()
829            .abbrev(2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
830                .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
831                .abbrev_attr_null()
832            .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
833                .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
834                .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
835                .abbrev_attr_null()
836            .abbrev_null()
837            .append_bytes(&expected_rest)
838            .get_contents()
839            .unwrap();
840        let rest = &mut EndianSlice::new(&buf, LittleEndian);
841
842        let abbrev1 = Abbreviation::new(
843            1,
844            constants::DW_TAG_compile_unit,
845            constants::DW_CHILDREN_yes,
846            vec![
847                AttributeSpecification::new(
848                    constants::DW_AT_producer,
849                    constants::DW_FORM_strp,
850                    None,
851                ),
852                AttributeSpecification::new(
853                    constants::DW_AT_language,
854                    constants::DW_FORM_data2,
855                    None,
856                ),
857            ]
858            .into(),
859        );
860
861        let abbrev2 = Abbreviation::new(
862            2,
863            constants::DW_TAG_subprogram,
864            constants::DW_CHILDREN_no,
865            vec![AttributeSpecification::new(
866                constants::DW_AT_name,
867                constants::DW_FORM_string,
868                None,
869            )]
870            .into(),
871        );
872
873        let abbrevs = Abbreviations::parse(rest).expect("Should parse abbreviations");
874        assert_eq!(abbrevs.get(1), Some(&abbrev1));
875        assert_eq!(abbrevs.get(2), Some(&abbrev2));
876        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
877    }
878
879    #[test]
880    fn test_parse_abbreviations_duplicate() {
881        let expected_rest = [1, 2, 3, 4];
882        #[rustfmt::skip]
883        let buf = Section::new()
884            .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
885                .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
886                .abbrev_attr_null()
887            .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
888                .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
889                .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
890                .abbrev_attr_null()
891            .abbrev_null()
892            .append_bytes(&expected_rest)
893            .get_contents()
894            .unwrap();
895        let buf = &mut EndianSlice::new(&buf, LittleEndian);
896
897        match Abbreviations::parse(buf) {
898            Err(Error::DuplicateAbbreviationCode(1)) => {}
899            otherwise => panic!("Unexpected result: {:?}", otherwise),
900        };
901    }
902
903    #[test]
904    fn test_parse_abbreviation_tag_ok() {
905        let buf = [0x01, 0x02];
906        let rest = &mut EndianSlice::new(&buf, LittleEndian);
907        let tag = Abbreviation::parse_tag(rest).expect("Should parse tag");
908        assert_eq!(tag, constants::DW_TAG_array_type);
909        assert_eq!(*rest, EndianSlice::new(&buf[1..], LittleEndian));
910    }
911
912    #[test]
913    fn test_parse_abbreviation_tag_zero() {
914        let buf = [0x00];
915        let buf = &mut EndianSlice::new(&buf, LittleEndian);
916        match Abbreviation::parse_tag(buf) {
917            Err(Error::AbbreviationTagZero) => {}
918            otherwise => panic!("Unexpected result: {:?}", otherwise),
919        };
920    }
921
922    #[test]
923    fn test_parse_abbreviation_has_children() {
924        let buf = [0x00, 0x01, 0x02];
925        let rest = &mut EndianSlice::new(&buf, LittleEndian);
926        let val = Abbreviation::parse_has_children(rest).expect("Should parse children");
927        assert_eq!(val, constants::DW_CHILDREN_no);
928        let val = Abbreviation::parse_has_children(rest).expect("Should parse children");
929        assert_eq!(val, constants::DW_CHILDREN_yes);
930        match Abbreviation::parse_has_children(rest) {
931            Err(Error::InvalidAbbreviationChildren(constants::DwChildren(2))) => {}
932            otherwise => panic!("Unexpected result: {:?}", otherwise),
933        };
934    }
935
936    #[test]
937    fn test_parse_abbreviation_ok() {
938        let expected_rest = [0x01, 0x02, 0x03, 0x04];
939        let buf = Section::new()
940            .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
941            .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
942            .abbrev_attr_null()
943            .append_bytes(&expected_rest)
944            .get_contents()
945            .unwrap();
946        let rest = &mut EndianSlice::new(&buf, LittleEndian);
947
948        let expect = Some(Abbreviation::new(
949            1,
950            constants::DW_TAG_subprogram,
951            constants::DW_CHILDREN_no,
952            vec![AttributeSpecification::new(
953                constants::DW_AT_name,
954                constants::DW_FORM_string,
955                None,
956            )]
957            .into(),
958        ));
959
960        let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation");
961        assert_eq!(abbrev, expect);
962        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
963    }
964
965    #[test]
966    fn test_parse_abbreviation_implicit_const_ok() {
967        let expected_rest = [0x01, 0x02, 0x03, 0x04];
968        let buf = Section::new()
969            .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
970            .abbrev_attr_implicit_const(constants::DW_AT_name, -42)
971            .abbrev_attr_null()
972            .append_bytes(&expected_rest)
973            .get_contents()
974            .unwrap();
975        let rest = &mut EndianSlice::new(&buf, LittleEndian);
976
977        let expect = Some(Abbreviation::new(
978            1,
979            constants::DW_TAG_subprogram,
980            constants::DW_CHILDREN_no,
981            vec![AttributeSpecification::new(
982                constants::DW_AT_name,
983                constants::DW_FORM_implicit_const,
984                Some(-42),
985            )]
986            .into(),
987        ));
988
989        let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation");
990        assert_eq!(abbrev, expect);
991        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
992    }
993
994    #[test]
995    fn test_parse_abbreviation_implicit_const_no_const() {
996        let buf = Section::new()
997            .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
998            .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_implicit_const)
999            .get_contents()
1000            .unwrap();
1001        let buf = &mut EndianSlice::new(&buf, LittleEndian);
1002
1003        match Abbreviation::parse(buf) {
1004            Err(Error::UnexpectedEof(_)) => {}
1005            otherwise => panic!("Unexpected result: {:?}", otherwise),
1006        }
1007    }
1008
1009    #[test]
1010    fn test_parse_null_abbreviation_ok() {
1011        let expected_rest = [0x01, 0x02, 0x03, 0x04];
1012        let buf = Section::new()
1013            .abbrev_null()
1014            .append_bytes(&expected_rest)
1015            .get_contents()
1016            .unwrap();
1017        let rest = &mut EndianSlice::new(&buf, LittleEndian);
1018
1019        let abbrev = Abbreviation::parse(rest).expect("Should parse null abbreviation");
1020        assert!(abbrev.is_none());
1021        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
1022    }
1023
1024    #[test]
1025    fn test_parse_null_attribute_specification_ok() {
1026        let buf = [0x00, 0x00, 0x01];
1027        let rest = &mut EndianSlice::new(&buf, LittleEndian);
1028        let attr =
1029            AttributeSpecification::parse(rest).expect("Should parse null attribute specification");
1030        assert!(attr.is_none());
1031        assert_eq!(*rest, EndianSlice::new(&buf[2..], LittleEndian));
1032    }
1033
1034    #[test]
1035    fn test_parse_attribute_specifications_name_zero() {
1036        let buf = [0x00, 0x01, 0x00, 0x00];
1037        let buf = &mut EndianSlice::new(&buf, LittleEndian);
1038        match AttributeSpecification::parse(buf) {
1039            Err(Error::AttributeNameZero) => {}
1040            otherwise => panic!("Unexpected result: {:?}", otherwise),
1041        };
1042    }
1043
1044    #[test]
1045    fn test_parse_attribute_specifications_form_zero() {
1046        let buf = [0x01, 0x00, 0x00, 0x00];
1047        let buf = &mut EndianSlice::new(&buf, LittleEndian);
1048        match AttributeSpecification::parse(buf) {
1049            Err(Error::AttributeFormZero) => {}
1050            otherwise => panic!("Unexpected result: {:?}", otherwise),
1051        };
1052    }
1053
1054    #[test]
1055    fn test_get_abbrev_zero() {
1056        let mut abbrevs = Abbreviations::empty();
1057        abbrevs
1058            .insert(Abbreviation::new(
1059                1,
1060                constants::DwTag(1),
1061                constants::DW_CHILDREN_no,
1062                vec![].into(),
1063            ))
1064            .unwrap();
1065        assert!(abbrevs.get(0).is_none());
1066    }
1067}