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