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