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