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