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