1use crate::common::{
27 DebugInfoOffset, DebugNamesOffset, DebugStrOffset, DebugTypeSignature, Format, SectionId,
28};
29use crate::constants;
30use crate::endianity::Endianity;
31use crate::read::{
32 DebugStr, EndianSlice, Error, Reader, ReaderOffset, Result, Section, UnitOffset,
33};
34use alloc::vec::Vec;
35
36#[derive(Debug, Default, Clone, Copy)]
44pub struct DebugNames<R> {
45 section: R,
46}
47
48impl<'input, Endian> DebugNames<EndianSlice<'input, Endian>>
49where
50 Endian: Endianity,
51{
52 pub fn new(debug_names_section: &'input [u8], endian: Endian) -> Self {
68 Self::from(EndianSlice::new(debug_names_section, endian))
69 }
70}
71
72impl<T> DebugNames<T> {
73 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugNames<R>
79 where
80 F: FnMut(&'a T) -> R,
81 {
82 borrow(&self.section).into()
83 }
84}
85
86impl<R: Reader> DebugNames<R> {
87 pub fn headers(&self) -> NameIndexHeaderIter<R> {
89 NameIndexHeaderIter {
90 input: self.section.clone(),
91 end_offset: self.section.len(),
92 }
93 }
94}
95
96impl<R> Section<R> for DebugNames<R> {
97 fn id() -> SectionId {
98 SectionId::DebugNames
99 }
100
101 fn reader(&self) -> &R {
102 &self.section
103 }
104}
105
106impl<R> From<R> for DebugNames<R> {
107 fn from(debug_names_section: R) -> Self {
108 DebugNames {
109 section: debug_names_section,
110 }
111 }
112}
113
114#[derive(Debug, Clone)]
116pub struct NameIndexHeaderIter<R: Reader> {
117 input: R,
118 end_offset: R::Offset,
119}
120
121impl<R: Reader> NameIndexHeaderIter<R> {
122 pub fn next(&mut self) -> Result<Option<NameIndexHeader<R>>> {
126 if self.input.is_empty() {
127 return Ok(None);
128 }
129
130 let offset = DebugNamesOffset(self.end_offset - self.input.len());
131 let result = NameIndexHeader::parse(&mut self.input, offset).map(Some);
132 if result.is_err() {
133 self.input.empty();
134 }
135 result
136 }
137}
138
139impl<R: Reader> Iterator for NameIndexHeaderIter<R> {
140 type Item = Result<NameIndexHeader<R>>;
141
142 fn next(&mut self) -> Option<Self::Item> {
143 NameIndexHeaderIter::next(self).transpose()
144 }
145}
146
147#[derive(Debug, Clone)]
149pub struct NameIndexHeader<R: Reader> {
150 offset: DebugNamesOffset<R::Offset>,
152 length: R::Offset,
154 format: Format,
156 version: u16,
158 compile_unit_count: u32,
160 local_type_unit_count: u32,
162 foreign_type_unit_count: u32,
164 bucket_count: u32,
166 name_count: u32,
168 abbrev_table_size: u32,
170 augmentation_string: Option<R>,
172 content: R,
174}
175
176impl<R: Reader> NameIndexHeader<R> {
177 pub fn index(self) -> Result<NameIndex<R>> {
179 NameIndex::new(self)
180 }
181
182 #[inline]
184 pub fn offset(&self) -> DebugNamesOffset<R::Offset> {
185 self.offset
186 }
187
188 #[inline]
190 pub fn length(&self) -> R::Offset {
191 self.length
192 }
193
194 #[inline]
196 pub fn format(&self) -> Format {
197 self.format
198 }
199
200 #[inline]
202 pub fn version(&self) -> u16 {
203 self.version
204 }
205
206 #[inline]
208 pub fn compile_unit_count(&self) -> u32 {
209 self.compile_unit_count
210 }
211
212 #[inline]
214 pub fn local_type_unit_count(&self) -> u32 {
215 self.local_type_unit_count
216 }
217
218 #[inline]
220 pub fn foreign_type_unit_count(&self) -> u32 {
221 self.foreign_type_unit_count
222 }
223
224 #[inline]
226 pub fn bucket_count(&self) -> u32 {
227 self.bucket_count
228 }
229
230 #[inline]
232 pub fn name_count(&self) -> u32 {
233 self.name_count
234 }
235
236 #[inline]
238 pub fn abbrev_table_size(&self) -> u32 {
239 self.abbrev_table_size
240 }
241
242 #[inline]
244 pub fn augmentation_string(&self) -> Option<&R> {
245 self.augmentation_string.as_ref()
246 }
247
248 fn parse(input: &mut R, offset: DebugNamesOffset<R::Offset>) -> Result<Self> {
249 let (length, format) = input.read_initial_length()?;
250 let mut input = input.split(length)?;
251
252 let version = input.read_u16()?;
253
254 if version != 5 {
255 return Err(Error::UnknownVersion(version as u64));
256 }
257
258 input.skip(R::Offset::from_u8(2))?; let compile_unit_count = input.read_u32()?;
260 let local_type_unit_count = input.read_u32()?;
261 let foreign_type_unit_count = input.read_u32()?;
262 let bucket_count = input.read_u32()?;
263 let name_count = input.read_u32()?;
264 let abbrev_table_size = input.read_u32()?;
265 let augmentation_string_size = input.read_u32()?;
266 let augmentation_string = if augmentation_string_size > 0 {
267 let val = input.split(R::Offset::from_u32(augmentation_string_size))?;
268 input.skip(R::Offset::from_u32(
269 (4 - (augmentation_string_size & 3)) & 3,
270 ))?;
271 Some(val)
272 } else {
273 None
274 };
275
276 Ok(NameIndexHeader {
277 offset,
278 length,
279 format,
280 version,
281 compile_unit_count,
282 local_type_unit_count,
283 foreign_type_unit_count,
284 bucket_count,
285 name_count,
286 abbrev_table_size,
287 augmentation_string,
288 content: input,
289 })
290 }
291}
292
293#[derive(Debug, Clone, Copy, PartialEq, Eq)]
302pub struct NameTableIndex(pub u32);
303
304#[derive(Debug, Clone, Copy, PartialEq, Eq)]
309pub enum NameTypeUnit<T> {
310 Local(DebugInfoOffset<T>),
312 Foreign(DebugTypeSignature),
314}
315
316#[derive(Debug)]
321pub struct NameIndex<R: Reader> {
322 format: Format,
323 compile_unit_count: u32,
324 local_type_unit_count: u32,
325 foreign_type_unit_count: u32,
326 bucket_count: u32,
327 name_count: u32,
328
329 compile_unit_list: R,
331 local_type_unit_list: R,
332 foreign_type_unit_list: R,
333 bucket_data: R,
334 hash_table_data: R,
335 name_table_data: R,
336 entry_offset_data: R,
337 entry_pool: R,
338
339 abbreviations: NameAbbreviations,
340}
341
342impl<R: Reader> NameIndex<R> {
343 pub fn new(header: NameIndexHeader<R>) -> Result<Self> {
345 let mut reader = header.content;
346
347 let offset_size = header.format.word_size() as u64;
349
350 let cu_list_size = header.compile_unit_count as u64 * offset_size;
351 let local_tu_size = header.local_type_unit_count as u64 * offset_size;
352 let foreign_tu_size = header.foreign_type_unit_count as u64 * 8; let buckets_size = header.bucket_count as u64 * 4;
354 let hash_table_size = if header.bucket_count == 0 {
355 0
356 } else {
357 header.name_count as u64 * 4
358 };
359 let name_table_size = header.name_count as u64 * offset_size;
360 let abbrev_size = header.abbrev_table_size as u64;
361
362 let compile_unit_list = reader.split(R::Offset::from_u64(cu_list_size)?)?;
364 let local_type_unit_list = reader.split(R::Offset::from_u64(local_tu_size)?)?;
365 let foreign_type_unit_list = reader.split(R::Offset::from_u64(foreign_tu_size)?)?;
366 let bucket_data = reader.split(R::Offset::from_u64(buckets_size)?)?;
367 let hash_table_data = reader.split(R::Offset::from_u64(hash_table_size)?)?;
368 let name_table_data = reader.split(R::Offset::from_u64(name_table_size)?)?;
369 let entry_offset_data = reader.split(R::Offset::from_u64(name_table_size)?)?;
370 let abbreviation_table = reader.split(R::Offset::from_u64(abbrev_size)?)?;
371
372 let abbreviations = NameAbbreviations::parse(abbreviation_table)?;
373
374 let entry_pool = reader;
376
377 Ok(NameIndex {
378 format: header.format,
379 compile_unit_count: header.compile_unit_count,
380 local_type_unit_count: header.local_type_unit_count,
381 foreign_type_unit_count: header.foreign_type_unit_count,
382 bucket_count: header.bucket_count,
383 name_count: header.name_count,
384 compile_unit_list,
385 local_type_unit_list,
386 foreign_type_unit_list,
387 bucket_data,
388 hash_table_data,
389 name_table_data,
390 entry_offset_data,
391 entry_pool,
392 abbreviations,
393 })
394 }
395
396 pub fn compile_unit_count(&self) -> u32 {
398 self.compile_unit_count
399 }
400
401 pub fn compile_unit(&self, index: u32) -> Result<DebugInfoOffset<R::Offset>> {
407 let mut reader = self.compile_unit_list.clone();
408 reader.skip(R::Offset::from_u64(
409 u64::from(index) * u64::from(self.format.word_size()),
410 )?)?;
411 reader.read_offset(self.format).map(DebugInfoOffset)
412 }
413
414 pub fn default_compile_unit(&self) -> Result<Option<DebugInfoOffset<R::Offset>>> {
419 if self.compile_unit_count == 1 {
420 self.compile_unit(0).map(Some)
421 } else {
422 Ok(None)
423 }
424 }
425
426 pub fn local_type_unit_count(&self) -> u32 {
428 self.local_type_unit_count
429 }
430
431 pub fn local_type_unit(&self, index: u32) -> Result<DebugInfoOffset<R::Offset>> {
437 let mut reader = self.local_type_unit_list.clone();
438 reader.skip(R::Offset::from_u64(
439 u64::from(index) * u64::from(self.format.word_size()),
440 )?)?;
441 reader.read_offset(self.format).map(DebugInfoOffset)
442 }
443
444 pub fn foreign_type_unit_count(&self) -> u32 {
446 self.foreign_type_unit_count
447 }
448
449 pub fn foreign_type_unit(&self, index: u32) -> Result<DebugTypeSignature> {
455 let mut reader = self.foreign_type_unit_list.clone();
456 reader.skip(R::Offset::from_u64(u64::from(index) * 8)?)?;
457 reader.read_u64().map(DebugTypeSignature)
458 }
459
460 pub fn type_unit_count(&self) -> u32 {
462 self.local_type_unit_count + self.foreign_type_unit_count
463 }
464
465 pub fn type_unit(&self, index: u32) -> Result<NameTypeUnit<R::Offset>> {
472 if let Some(foreign_index) = index.checked_sub(self.local_type_unit_count) {
473 self.foreign_type_unit(foreign_index)
474 .map(NameTypeUnit::Foreign)
475 } else {
476 self.local_type_unit(index).map(NameTypeUnit::Local)
477 }
478 }
479
480 pub fn has_hash_table(&self) -> bool {
482 self.bucket_count != 0
483 }
484
485 pub fn bucket_count(&self) -> u32 {
487 self.bucket_count
488 }
489
490 pub fn find_by_bucket(&self, bucket_index: u32) -> Result<Option<NameBucketIter<R>>> {
500 NameBucketIter::new(self, bucket_index)
501 }
502
503 pub fn find_by_hash(&self, hash_value: u32) -> Result<NameHashIter<R>> {
509 NameHashIter::new(self, hash_value)
510 }
511
512 pub fn name_count(&self) -> u32 {
516 self.name_count
517 }
518
519 pub fn names(&self) -> NameTableIter {
521 NameTableIter::new(self)
522 }
523
524 pub fn name_string_offset(&self, index: NameTableIndex) -> Result<DebugStrOffset<R::Offset>> {
528 let mut reader = self.name_table_data.clone();
529 reader.skip(R::Offset::from_u64(
530 u64::from(index.0) * u64::from(self.format.word_size()),
531 )?)?;
532 reader.read_offset(self.format).map(DebugStrOffset)
533 }
534
535 pub fn name_string(&self, index: NameTableIndex, debug_str: &DebugStr<R>) -> Result<R> {
539 let offset = self.name_string_offset(index)?;
540 debug_str.get_str(offset)
541 }
542
543 pub fn name_entries(&self, index: NameTableIndex) -> Result<NameEntryIter<'_, R>> {
550 NameEntryIter::new(self, index)
551 }
552
553 pub fn name_entry(&self, offset: NameEntryOffset<R::Offset>) -> Result<NameEntry<R>> {
557 let mut entries = self.entry_pool.clone();
558 entries.skip(offset.0)?;
559 NameEntry::parse(&mut entries, offset, &self.abbreviations)?
560 .ok_or(Error::NoEntryAtGivenOffset(offset.0.into_u64()))
561 }
562
563 pub fn abbreviations(&self) -> &NameAbbreviations {
565 &self.abbreviations
566 }
567}
568
569#[derive(Debug)]
571pub struct NameTableIter {
572 name_table_index: NameTableIndex,
573 name_count: u32,
574}
575
576impl NameTableIter {
577 fn new<R: Reader>(name_index: &NameIndex<R>) -> Self {
578 NameTableIter {
579 name_table_index: NameTableIndex(0),
580 name_count: name_index.name_count,
581 }
582 }
583}
584
585impl Iterator for NameTableIter {
586 type Item = NameTableIndex;
587
588 fn next(&mut self) -> Option<Self::Item> {
589 let name_table_index = self.name_table_index;
590 if name_table_index.0 >= self.name_count {
591 return None;
592 }
593 self.name_table_index.0 += 1;
594 Some(name_table_index)
595 }
596}
597
598#[derive(Debug)]
600pub struct NameBucketIter<R: Reader> {
601 reader: R,
602 name_table_index: NameTableIndex,
603 name_count: u32,
604 bucket_index: u32,
605 bucket_count: u32,
606}
607
608impl<R: Reader> NameBucketIter<R> {
609 fn new(name_index: &NameIndex<R>, bucket_index: u32) -> Result<Option<Self>> {
610 let mut bucket_reader = name_index.bucket_data.clone();
611 bucket_reader.skip(R::Offset::from_u64(u64::from(bucket_index) * 4)?)?;
612 let start = bucket_reader.read_u32()?;
613 if start == 0 {
614 return Ok(None);
615 }
616 let name_table_index = NameTableIndex(start - 1);
617
618 let mut reader = name_index.hash_table_data.clone();
619 reader.skip(R::Offset::from_u64(u64::from(name_table_index.0) * 4)?)?;
620
621 Ok(Some(NameBucketIter {
622 reader,
623 name_table_index,
624 name_count: name_index.name_count,
625 bucket_index,
626 bucket_count: name_index.bucket_count,
627 }))
628 }
629
630 pub fn next(&mut self) -> Result<Option<(NameTableIndex, u32)>> {
632 let name_table_index = self.name_table_index;
633 if name_table_index.0 >= self.name_count {
634 return Ok(None);
635 }
636 let hash = self.reader.read_u32()?;
637 self.name_table_index.0 += 1;
638 if hash % self.bucket_count != self.bucket_index {
639 return Ok(None);
640 }
641 Ok(Some((name_table_index, hash)))
642 }
643}
644
645#[cfg(feature = "fallible-iterator")]
646impl<R: Reader> fallible_iterator::FallibleIterator for NameBucketIter<R> {
647 type Item = (NameTableIndex, u32);
648 type Error = Error;
649
650 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
651 NameBucketIter::next(self)
652 }
653}
654
655impl<R: Reader> Iterator for NameBucketIter<R> {
656 type Item = Result<(NameTableIndex, u32)>;
657
658 fn next(&mut self) -> Option<Self::Item> {
659 NameBucketIter::next(self).transpose()
660 }
661}
662
663#[derive(Debug)]
666pub struct NameHashIter<R: Reader> {
667 bucket_iter: Option<NameBucketIter<R>>,
668 hash: u32,
669}
670
671impl<R: Reader> NameHashIter<R> {
672 fn new(name_index: &NameIndex<R>, hash: u32) -> Result<Self> {
673 let bucket_index = if name_index.bucket_count == 0 {
674 0
675 } else {
676 hash % name_index.bucket_count
677 };
678 let bucket_iter = NameBucketIter::new(name_index, bucket_index)?;
679
680 Ok(NameHashIter { bucket_iter, hash })
681 }
682
683 pub fn next(&mut self) -> Result<Option<NameTableIndex>> {
685 let Some(bucket_iter) = &mut self.bucket_iter else {
686 return Ok(None);
687 };
688 while let Some((name_table_index, hash)) = bucket_iter.next()? {
689 if hash == self.hash {
690 return Ok(Some(name_table_index));
691 }
692 }
693 Ok(None)
694 }
695}
696
697#[cfg(feature = "fallible-iterator")]
698impl<R: Reader> fallible_iterator::FallibleIterator for NameHashIter<R> {
699 type Item = NameTableIndex;
700 type Error = Error;
701
702 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
703 NameHashIter::next(self)
704 }
705}
706
707impl<R: Reader> Iterator for NameHashIter<R> {
708 type Item = Result<NameTableIndex>;
709
710 fn next(&mut self) -> Option<Self::Item> {
711 NameHashIter::next(self).transpose()
712 }
713}
714
715#[derive(Debug)]
720pub struct NameEntryIter<'a, R: Reader> {
721 entries: R,
722 end_offset: R::Offset,
723 abbreviations: &'a NameAbbreviations,
724}
725
726impl<'a, R: Reader> NameEntryIter<'a, R> {
727 fn new(name_index: &'a NameIndex<R>, index: NameTableIndex) -> Result<Self> {
728 let mut offsets = name_index.entry_offset_data.clone();
729 offsets.skip(R::Offset::from_u64(
730 u64::from(index.0) * u64::from(name_index.format.word_size()),
731 )?)?;
732 let offset = offsets
733 .read_offset(name_index.format)
734 .map(NameEntryOffset)?;
735
736 let mut entries = name_index.entry_pool.clone();
737 let end_offset = entries.len();
738 entries.skip(offset.0)?;
739 Ok(NameEntryIter {
740 entries,
741 end_offset,
742 abbreviations: &name_index.abbreviations,
743 })
744 }
745
746 pub fn next(&mut self) -> Result<Option<NameEntry<R>>> {
748 if self.entries.is_empty() {
749 return Ok(None);
750 }
751
752 let offset = NameEntryOffset(self.end_offset - self.entries.len());
753 match NameEntry::parse(&mut self.entries, offset, self.abbreviations) {
754 Ok(Some(entry)) => Ok(Some(entry)),
755 Ok(None) => {
756 self.entries.empty();
758 Ok(None)
759 }
760 Err(e) => {
761 self.entries.empty();
763 Err(e)
764 }
765 }
766 }
767}
768
769#[cfg(feature = "fallible-iterator")]
770impl<'a, R: Reader> fallible_iterator::FallibleIterator for NameEntryIter<'a, R> {
771 type Item = NameEntry<R>;
772 type Error = Error;
773
774 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
775 NameEntryIter::next(self)
776 }
777}
778
779impl<'a, R: Reader> Iterator for NameEntryIter<'a, R> {
780 type Item = Result<NameEntry<R>>;
781
782 fn next(&mut self) -> Option<Self::Item> {
783 NameEntryIter::next(self).transpose()
784 }
785}
786
787#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
789pub struct NameEntryOffset<T = usize>(pub T);
790
791#[derive(Debug, Clone, PartialEq, Eq)]
793pub struct NameEntry<R: Reader> {
794 pub offset: NameEntryOffset<R::Offset>,
796
797 pub abbrev_code: u64,
799
800 pub tag: constants::DwTag,
802
803 pub attrs: Vec<NameAttribute<R>>,
805}
806
807impl<R: Reader> NameEntry<R> {
808 pub fn compile_unit(&self, names: &NameIndex<R>) -> Result<Option<DebugInfoOffset<R::Offset>>> {
817 for attr in &self.attrs {
818 if attr.name == constants::DW_IDX_compile_unit {
819 return attr.compile_unit(names).map(Some);
820 }
821 }
822 Ok(None)
823 }
824
825 pub fn type_unit(&self, names: &NameIndex<R>) -> Result<Option<NameTypeUnit<R::Offset>>> {
827 for attr in &self.attrs {
828 if attr.name == constants::DW_IDX_type_unit {
829 return attr.type_unit(names).map(Some);
830 }
831 }
832 Ok(None)
833 }
834
835 pub fn die_offset(&self) -> Result<Option<UnitOffset<R::Offset>>> {
839 for attr in &self.attrs {
840 if attr.name == constants::DW_IDX_die_offset {
841 return attr.die_offset().map(Some);
842 }
843 }
844 Ok(None)
845 }
846
847 pub fn parent(&self) -> Result<Option<Option<NameEntryOffset<R::Offset>>>> {
854 for attr in &self.attrs {
855 if attr.name == constants::DW_IDX_parent {
856 return attr.parent().map(Some);
857 }
858 }
859 Ok(None)
860 }
861
862 pub fn type_hash(&self) -> Result<Option<u64>> {
864 for attr in &self.attrs {
865 if attr.name == constants::DW_IDX_type_hash {
866 return attr.type_hash().map(Some);
867 }
868 }
869 Ok(None)
870 }
871
872 fn parse(
874 entry_reader: &mut R,
875 offset: NameEntryOffset<R::Offset>,
876 abbreviations: &NameAbbreviations,
877 ) -> Result<Option<NameEntry<R>>> {
878 let abbrev_code = entry_reader.read_uleb128()?;
879 if abbrev_code == 0 {
880 return Ok(None);
881 }
882 let Some(abbrev) = abbreviations.get(abbrev_code) else {
883 return Err(Error::InvalidAbbreviationCode(abbrev_code));
884 };
885 let tag = abbrev.tag();
886 let specs = abbrev.attributes();
887 let mut attrs = Vec::with_capacity(specs.len());
888 for spec in specs {
889 let name = spec.name();
890 let form = spec.form();
891 let value = read_debug_names_form_value(entry_reader, form)?;
892 attrs.push(NameAttribute { name, form, value });
893 }
894
895 Ok(Some(NameEntry {
896 offset,
897 abbrev_code,
898 tag,
899 attrs,
900 }))
901 }
902}
903
904#[derive(Debug, Clone, Copy, PartialEq, Eq)]
906pub struct NameAttribute<R: Reader> {
907 name: constants::DwIdx,
908 form: constants::DwForm,
909 value: NameAttributeValue<R>,
910}
911
912impl<R: Reader> NameAttribute<R> {
913 pub fn name(&self) -> constants::DwIdx {
915 self.name
916 }
917
918 pub fn form(&self) -> constants::DwForm {
920 self.form
921 }
922
923 pub fn value(&self) -> &NameAttributeValue<R> {
927 &self.value
928 }
929
930 pub fn compile_unit(&self, names: &NameIndex<R>) -> Result<DebugInfoOffset<R::Offset>> {
932 match self.value {
933 NameAttributeValue::Unsigned(val) => {
934 let index =
935 u32::try_from(val).map_err(|_| Error::InvalidNameAttributeIndex(val))?;
936 names.compile_unit(index)
937 }
938 _ => Err(Error::UnsupportedAttributeForm(self.form)),
939 }
940 }
941
942 pub fn type_unit(&self, names: &NameIndex<R>) -> Result<NameTypeUnit<R::Offset>> {
944 match self.value {
945 NameAttributeValue::Unsigned(val) => {
946 let index =
947 u32::try_from(val).map_err(|_| Error::InvalidNameAttributeIndex(val))?;
948 names.type_unit(index)
949 }
950 _ => Err(Error::UnsupportedAttributeForm(self.form)),
951 }
952 }
953
954 pub fn die_offset(&self) -> Result<UnitOffset<R::Offset>> {
956 match self.value {
957 NameAttributeValue::Offset(val) => Ok(UnitOffset(val)),
958 _ => Err(Error::UnsupportedAttributeForm(self.form)),
959 }
960 }
961
962 pub fn parent(&self) -> Result<Option<NameEntryOffset<R::Offset>>> {
967 match self.value {
968 NameAttributeValue::Offset(val) => Ok(Some(NameEntryOffset(val))),
969 NameAttributeValue::Flag(true) => Ok(None),
970 _ => Err(Error::UnsupportedAttributeForm(self.form)),
971 }
972 }
973
974 pub fn type_hash(&self) -> Result<u64> {
976 match self.value {
977 NameAttributeValue::Unsigned(val) => Ok(val),
978 _ => Err(Error::UnsupportedAttributeForm(self.form)),
979 }
980 }
981}
982
983#[derive(Debug, Clone, Copy, PartialEq, Eq)]
985pub enum NameAttributeValue<R: Reader> {
986 Unsigned(u64),
991 Offset(R::Offset),
996 Flag(bool),
1001}
1002
1003fn read_debug_names_form_value<R: Reader>(
1008 input: &mut R,
1009 form: constants::DwForm,
1010) -> Result<NameAttributeValue<R>> {
1011 Ok(match form {
1012 constants::DW_FORM_flag => {
1013 let present = input.read_u8()?;
1014 NameAttributeValue::Flag(present != 0)
1015 }
1016 constants::DW_FORM_flag_present => NameAttributeValue::Flag(true),
1017 constants::DW_FORM_data1 => {
1018 let data = input.read_u8()?;
1019 NameAttributeValue::Unsigned(u64::from(data))
1020 }
1021 constants::DW_FORM_data2 => {
1022 let data = input.read_u16()?;
1023 NameAttributeValue::Unsigned(u64::from(data))
1024 }
1025 constants::DW_FORM_data4 => {
1026 let data = input.read_u32()?;
1027 NameAttributeValue::Unsigned(u64::from(data))
1028 }
1029 constants::DW_FORM_data8 => {
1030 let data = input.read_u64()?;
1031 NameAttributeValue::Unsigned(data)
1032 }
1033 constants::DW_FORM_udata => {
1034 let data = input.read_uleb128()?;
1035 NameAttributeValue::Unsigned(data)
1036 }
1037 constants::DW_FORM_ref1 => {
1038 let reference = input.read_u8().map(R::Offset::from_u8)?;
1039 NameAttributeValue::Offset(reference)
1040 }
1041 constants::DW_FORM_ref2 => {
1042 let reference = input.read_u16().map(R::Offset::from_u16)?;
1043 NameAttributeValue::Offset(reference)
1044 }
1045 constants::DW_FORM_ref4 => {
1046 let reference = input.read_u32().map(R::Offset::from_u32)?;
1047 NameAttributeValue::Offset(reference)
1048 }
1049 constants::DW_FORM_ref8 => {
1050 let reference = input.read_u64().and_then(R::Offset::from_u64)?;
1051 NameAttributeValue::Offset(reference)
1052 }
1053 constants::DW_FORM_ref_udata => {
1054 let reference = input.read_uleb128().and_then(R::Offset::from_u64)?;
1055 NameAttributeValue::Offset(reference)
1056 }
1057 form => return Err(Error::UnknownForm(form)),
1058 })
1059}
1060
1061#[derive(Debug, Default, Clone)]
1063pub struct NameAbbreviations {
1064 abbreviations: Vec<NameAbbreviation>,
1066}
1067
1068impl NameAbbreviations {
1069 pub fn get(&self, code: u64) -> Option<&NameAbbreviation> {
1071 self.abbreviations.iter().find(|abbrev| abbrev.code == code)
1072 }
1073
1074 pub fn abbreviations(&self) -> &[NameAbbreviation] {
1076 &self.abbreviations
1077 }
1078
1079 fn parse<R: Reader>(mut reader: R) -> Result<NameAbbreviations> {
1081 let mut abbreviations = Vec::new();
1082
1083 while !reader.is_empty() {
1085 let code = reader.read_uleb128()?;
1086 if code == 0 {
1087 break; }
1089
1090 let tag = reader.read_uleb128_u16()?;
1091 if tag == 0 {
1092 return Err(Error::AbbreviationTagZero);
1093 }
1094 let tag = constants::DwTag(tag);
1095
1096 let mut attributes = Vec::new();
1097 loop {
1098 let name = reader.read_uleb128_u16()?;
1099 let form = reader.read_uleb128_u16()?;
1100 match (name, form) {
1101 (0, 0) => break,
1102 (0, _) => return Err(Error::AttributeNameZero),
1103 (_, 0) => return Err(Error::AttributeFormZero),
1104 (_, _) => {}
1105 }
1106 attributes.push(NameAbbreviationAttribute {
1107 name: constants::DwIdx(name),
1108 form: constants::DwForm(form),
1109 });
1110 }
1111
1112 abbreviations.push(NameAbbreviation {
1113 code,
1114 tag,
1115 attributes,
1116 });
1117 }
1118
1119 Ok(NameAbbreviations { abbreviations })
1120 }
1121}
1122
1123#[derive(Debug, Clone)]
1125pub struct NameAbbreviation {
1126 code: u64,
1128 tag: constants::DwTag,
1130 attributes: Vec<NameAbbreviationAttribute>,
1132}
1133
1134impl NameAbbreviation {
1135 pub fn code(&self) -> u64 {
1137 self.code
1138 }
1139
1140 pub fn tag(&self) -> constants::DwTag {
1142 self.tag
1143 }
1144
1145 pub fn attributes(&self) -> &[NameAbbreviationAttribute] {
1147 &self.attributes
1148 }
1149}
1150
1151#[derive(Debug, Clone)]
1153pub struct NameAbbreviationAttribute {
1154 name: constants::DwIdx,
1156 form: constants::DwForm,
1158}
1159
1160impl NameAbbreviationAttribute {
1161 pub fn name(&self) -> constants::DwIdx {
1163 self.name
1164 }
1165
1166 pub fn form(&self) -> constants::DwForm {
1168 self.form
1169 }
1170}
1171
1172#[cfg(test)]
1173mod tests {
1174 use super::*;
1175 use crate::constants::*;
1176 use crate::endianity::LittleEndian;
1177 use crate::test_util::GimliSectionMethods;
1178 use test_assembler::{Endian, Label, LabelMaker, Section};
1179
1180 pub trait DebugNamesSectionMethods {
1182 fn debug_names_header(
1183 self,
1184 header: &mut NameIndexHeader<EndianSlice<'_, LittleEndian>>,
1185 ) -> Self;
1186 fn debug_names_abbrev(self, code: u64, tag: DwTag, idx_attrs: &[(DwIdx, DwForm)]) -> Self;
1187 fn debug_names_abbrev_null(self) -> Self;
1188 fn debug_names_entry_null(self) -> Self;
1189 fn offset(self, offset: usize, format: Format) -> Self;
1190 fn offset_label(self, offset: &Label, format: Format) -> Self;
1191 }
1192
1193 impl DebugNamesSectionMethods for Section {
1194 fn debug_names_header(
1195 self,
1196 header: &mut NameIndexHeader<EndianSlice<'_, LittleEndian>>,
1197 ) -> Self {
1198 let length = Label::new();
1199 let start = Label::new();
1200 let end = Label::new();
1201
1202 let section = match header.format {
1203 Format::Dwarf32 => self.D32(&length),
1204 Format::Dwarf64 => self.D32(0xffffffff).D64(&length),
1205 };
1206 let section = section
1207 .mark(&start)
1208 .D16(header.version)
1209 .D16(0) .D32(header.compile_unit_count)
1211 .D32(header.local_type_unit_count)
1212 .D32(header.foreign_type_unit_count)
1213 .D32(header.bucket_count)
1214 .D32(header.name_count)
1215 .D32(header.abbrev_table_size);
1216 let section = if let Some(augmentation_string) = header.augmentation_string {
1217 section
1218 .D32(augmentation_string.len() as u32)
1219 .append_bytes(augmentation_string.slice())
1220 .append_repeated(0, (4 - (augmentation_string.len() & 3)) & 3)
1221 } else {
1222 section.D32(0)
1223 };
1224 let section = section.append_bytes(header.content.slice()).mark(&end);
1225 header.length = (&end - &start) as usize;
1226 length.set_const(header.length as u64);
1227 section
1228 }
1229
1230 fn debug_names_abbrev(self, code: u64, tag: DwTag, idx_attrs: &[(DwIdx, DwForm)]) -> Self {
1231 let mut section = self.uleb(code).uleb(tag.0.into());
1232 for &(idx, form) in idx_attrs {
1233 section = section.uleb(idx.0.into()).uleb(form.0.into());
1234 }
1235 section.D8(0).D8(0) }
1237
1238 fn debug_names_abbrev_null(self) -> Self {
1239 self.D8(0)
1240 }
1241
1242 fn offset(self, offset: usize, format: Format) -> Self {
1243 match format {
1244 Format::Dwarf32 => self.D32(offset as u32),
1245 Format::Dwarf64 => self.D64(offset as u64),
1246 }
1247 }
1248
1249 fn offset_label(self, offset: &Label, format: Format) -> Self {
1250 match format {
1251 Format::Dwarf32 => self.D32(offset),
1252 Format::Dwarf64 => self.D64(offset),
1253 }
1254 }
1255
1256 fn debug_names_entry_null(self) -> Self {
1257 self.D8(0)
1258 }
1259 }
1260
1261 #[test]
1262 fn test_debug_names() {
1263 for format in [Format::Dwarf32, Format::Dwarf64] {
1264 let offset_form = match format {
1265 Format::Dwarf32 => DW_FORM_ref4,
1266 Format::Dwarf64 => DW_FORM_ref8,
1267 };
1268 let abbrev_start = Label::new();
1269 let abbrev_end = Label::new();
1270 let entries_1 = Label::new();
1271 let entries_2 = Label::new();
1272 let entries_3 = Label::new();
1273 let entries_4 = Label::new();
1274 let entries_2_offset = Label::new();
1275 let entries_3_offset = Label::new();
1276 let entries_4_offset = Label::new();
1277
1278 let debug_str = Section::new()
1279 .append_repeated(0, 0xd9)
1280 .append_bytes(b"char\0")
1281 .append_bytes(b"__ARRAY_SIZE_TYPE__\0")
1282 .append_bytes(b"main\0")
1283 .append_bytes(b"int\0")
1284 .get_contents()
1285 .unwrap();
1286 let debug_str = DebugStr::new(&debug_str, LittleEndian);
1287
1288 let section = Section::with_endian(Endian::Little)
1289 .offset(0x101, format)
1291 .offset(0x201, format)
1293 .offset(0x202, format)
1294 .D64(0x1234_5678) .D32(1) .D32(0) .D32(2) .D32(3) .D32(0x0b88_8030) .D32(0x7c9a_7f6a) .D32(0x0cef_4cfb) .D32(0x7c95_2063) .offset(0xf7, format) .offset(0xf2, format) .offset(0xde, format) .offset(0xd9, format) .offset(0x00, format)
1313 .offset_label(&entries_2_offset, format)
1314 .offset_label(&entries_3_offset, format)
1315 .offset_label(&entries_4_offset, format)
1316 .mark(&abbrev_start)
1317 .debug_names_abbrev(
1318 1,
1319 DW_TAG_base_type,
1320 &[
1321 (DW_IDX_type_unit, DW_FORM_udata),
1322 (DW_IDX_die_offset, offset_form),
1323 (DW_IDX_parent, DW_FORM_flag_present),
1324 ],
1325 )
1326 .debug_names_abbrev(2, DW_TAG_subprogram, &[(DW_IDX_die_offset, offset_form)])
1327 .debug_names_abbrev(
1328 3,
1329 DW_TAG_subprogram,
1330 &[
1331 (DW_IDX_compile_unit, DW_FORM_data1),
1332 (DW_IDX_die_offset, offset_form),
1333 (DW_IDX_parent, offset_form),
1334 ],
1335 )
1336 .debug_names_abbrev_null()
1337 .mark(&abbrev_end)
1338 .mark(&entries_1)
1340 .uleb(1)
1342 .uleb(0)
1343 .offset(0x10, format)
1344 .uleb(1)
1346 .uleb(2)
1347 .offset(0x20, format)
1348 .uleb(1)
1350 .uleb(4)
1351 .offset(0x30, format)
1352 .debug_names_entry_null()
1353 .mark(&entries_2)
1355 .uleb(2)
1357 .offset(0x40, format)
1358 .uleb(3)
1360 .D8(0)
1361 .offset(0x50, format)
1362 .offset((&entries_2 - &entries_1) as usize, format)
1363 .debug_names_entry_null()
1364 .mark(&entries_3)
1366 .uleb(4) .debug_names_entry_null()
1368 .mark(&entries_4)
1370 .debug_names_entry_null();
1371 let abbrev_table_size = (&abbrev_end - &abbrev_start) as u32;
1372 entries_2_offset.set_const((&entries_2 - &entries_1) as u64);
1373 entries_3_offset.set_const((&entries_3 - &entries_1) as u64);
1374 entries_4_offset.set_const((&entries_4 - &entries_1) as u64);
1375 let content = section.get_contents().unwrap();
1376
1377 let mut header = NameIndexHeader {
1378 offset: DebugNamesOffset(0),
1379 length: 0,
1380 format,
1381 version: 5,
1382 compile_unit_count: 1,
1383 local_type_unit_count: 2,
1384 foreign_type_unit_count: 1,
1385 bucket_count: 4,
1386 name_count: 4,
1387 abbrev_table_size,
1388 augmentation_string: Some(EndianSlice::new(b"LLVM0700", LittleEndian)),
1389 content: EndianSlice::new(&content, LittleEndian),
1390 };
1391
1392 let buf = Section::with_endian(Endian::Little)
1393 .debug_names_header(&mut header)
1394 .get_contents()
1395 .unwrap();
1396
1397 let debug_names = DebugNames::new(&buf, LittleEndian);
1398 let mut headers = debug_names.headers();
1399 let header = headers.next().unwrap().unwrap();
1400 assert_eq!(header.offset(), DebugNamesOffset(0));
1401 assert_eq!(header.version(), 5);
1402 assert_eq!(header.format(), format);
1403 assert_eq!(header.compile_unit_count(), 1);
1404 assert_eq!(header.local_type_unit_count(), 2);
1405 assert_eq!(header.foreign_type_unit_count(), 1);
1406 assert_eq!(header.bucket_count(), 4);
1407 assert_eq!(header.name_count(), 4);
1408 assert_eq!(header.abbrev_table_size(), abbrev_table_size);
1409 assert_eq!(header.augmentation_string().unwrap().slice(), b"LLVM0700");
1410
1411 let name_index = header.index().unwrap();
1412
1413 assert_eq!(name_index.compile_unit_count(), 1);
1414 assert_eq!(name_index.compile_unit(0), Ok(DebugInfoOffset(0x101)));
1415 assert!(name_index.compile_unit(1).is_err());
1416 assert_eq!(
1417 name_index.default_compile_unit(),
1418 Ok(Some(DebugInfoOffset(0x101)))
1419 );
1420
1421 assert_eq!(name_index.local_type_unit_count(), 2);
1422 assert_eq!(name_index.local_type_unit(0), Ok(DebugInfoOffset(0x201)));
1423 assert_eq!(name_index.local_type_unit(1), Ok(DebugInfoOffset(0x202)));
1424 assert!(name_index.local_type_unit(2).is_err());
1425
1426 assert_eq!(name_index.foreign_type_unit_count(), 1);
1427 assert_eq!(
1428 name_index.foreign_type_unit(0),
1429 Ok(DebugTypeSignature(0x1234_5678))
1430 );
1431 assert!(name_index.foreign_type_unit(1).is_err());
1432
1433 assert_eq!(name_index.type_unit_count(), 3);
1434 assert_eq!(
1435 name_index.type_unit(0),
1436 Ok(NameTypeUnit::Local(DebugInfoOffset(0x201)))
1437 );
1438 assert_eq!(
1439 name_index.type_unit(1),
1440 Ok(NameTypeUnit::Local(DebugInfoOffset(0x202)))
1441 );
1442 assert_eq!(
1443 name_index.type_unit(2),
1444 Ok(NameTypeUnit::Foreign(DebugTypeSignature(0x1234_5678)))
1445 );
1446 assert!(name_index.type_unit(3).is_err());
1447
1448 assert!(name_index.has_hash_table());
1449 assert_eq!(name_index.bucket_count(), 4);
1450
1451 let mut names = name_index.find_by_bucket(0).unwrap().unwrap();
1453 assert_eq!(names.next(), Ok(Some((NameTableIndex(0), 0x0b88_8030))));
1454 assert_eq!(names.next(), Ok(None));
1455
1456 assert!(matches!(name_index.find_by_bucket(1), Ok(None)));
1458
1459 let mut names = name_index.find_by_bucket(3).unwrap().unwrap();
1461 assert_eq!(names.next(), Ok(Some((NameTableIndex(2), 0x0cef_4cfb))));
1462 assert_eq!(names.next(), Ok(Some((NameTableIndex(3), 0x7c95_2063))));
1463 assert_eq!(names.next(), Ok(None));
1464
1465 assert!(name_index.find_by_bucket(4).is_err());
1467
1468 for (i, hash) in [0x0b88_8030, 0x7c9a_7f6a, 0x0cef_4cfb, 0x7c95_2063]
1470 .into_iter()
1471 .enumerate()
1472 {
1473 let mut names = name_index.find_by_hash(hash).unwrap();
1474 assert_eq!(names.next(), Ok(Some(NameTableIndex(i as u32))));
1475 assert_eq!(names.next(), Ok(None));
1476 }
1477
1478 let mut names = name_index.find_by_hash(0x0b88_8031).unwrap();
1480 assert!(matches!(names.next(), Ok(None)));
1481
1482 let mut names = name_index.find_by_hash(0x0b88_8034).unwrap();
1484 assert!(matches!(names.next(), Ok(None)));
1485
1486 assert_eq!(name_index.name_count(), 4);
1487 let mut names = name_index.names();
1488
1489 let name = names.next().unwrap();
1491 assert_eq!(
1492 name_index.name_string_offset(name),
1493 Ok(DebugStrOffset(0xf7))
1494 );
1495 assert_eq!(
1496 name_index.name_string(name, &debug_str).unwrap().slice(),
1497 b"int"
1498 );
1499
1500 let mut entries = name_index.name_entries(name).unwrap();
1501 let entry = entries.next().unwrap().unwrap();
1502 assert_eq!(entry, name_index.name_entry(entry.offset).unwrap());
1503 assert_eq!(entry.tag, DW_TAG_base_type);
1504 assert_eq!(entry.compile_unit(&name_index), Ok(None));
1505 assert_eq!(
1506 entry.type_unit(&name_index),
1507 Ok(Some(NameTypeUnit::Local(DebugInfoOffset(0x201))))
1508 );
1509 assert_eq!(entry.die_offset(), Ok(Some(UnitOffset(0x10))));
1510 assert_eq!(entry.parent(), Ok(Some(None)));
1511 assert_eq!(entry.type_hash(), Ok(None));
1512
1513 let entry = entries.next().unwrap().unwrap();
1514 assert_eq!(entry, name_index.name_entry(entry.offset).unwrap());
1515 assert_eq!(entry.tag, DW_TAG_base_type);
1516 assert_eq!(entry.compile_unit(&name_index), Ok(None));
1517 assert_eq!(
1518 entry.type_unit(&name_index),
1519 Ok(Some(NameTypeUnit::Foreign(DebugTypeSignature(0x1234_5678))))
1520 );
1521 assert_eq!(entry.die_offset(), Ok(Some(UnitOffset(0x20))));
1522 assert_eq!(entry.parent(), Ok(Some(None)));
1523 assert_eq!(entry.type_hash(), Ok(None));
1524
1525 let entry = entries.next().unwrap().unwrap();
1526 assert_eq!(entry, name_index.name_entry(entry.offset).unwrap());
1527 assert_eq!(entry.tag, DW_TAG_base_type);
1528 assert_eq!(entry.compile_unit(&name_index), Ok(None));
1529 assert!(entry.type_unit(&name_index).is_err());
1530 assert_eq!(entry.die_offset(), Ok(Some(UnitOffset(0x30))));
1531 assert_eq!(entry.parent(), Ok(Some(None)));
1532 assert_eq!(entry.type_hash(), Ok(None));
1533
1534 assert!(matches!(entries.next(), Ok(None)));
1535
1536 let name = names.next().unwrap();
1538 assert_eq!(
1539 name_index.name_string_offset(name),
1540 Ok(DebugStrOffset(0xf2))
1541 );
1542 assert_eq!(
1543 name_index.name_string(name, &debug_str).unwrap().slice(),
1544 b"main"
1545 );
1546
1547 let mut entries = name_index.name_entries(name).unwrap();
1548 let entry = entries.next().unwrap().unwrap();
1549 assert_eq!(entry, name_index.name_entry(entry.offset).unwrap());
1550 assert_eq!(entry.tag, DW_TAG_subprogram);
1551 assert_eq!(entry.compile_unit(&name_index), Ok(None));
1552 assert_eq!(entry.type_unit(&name_index), Ok(None));
1553 assert_eq!(entry.die_offset(), Ok(Some(UnitOffset(0x40))));
1554 assert_eq!(entry.parent(), Ok(None));
1555
1556 let entry = entries.next().unwrap().unwrap();
1557 assert_eq!(entry, name_index.name_entry(entry.offset).unwrap());
1558 assert_eq!(entry.tag, DW_TAG_subprogram);
1559 assert_eq!(
1560 entry.compile_unit(&name_index),
1561 Ok(Some(DebugInfoOffset(0x101)))
1562 );
1563 assert_eq!(entry.type_unit(&name_index), Ok(None));
1564 assert_eq!(entry.die_offset(), Ok(Some(UnitOffset(0x50))));
1565 assert_eq!(
1566 entry.parent(),
1567 Ok(Some(Some(NameEntryOffset(
1568 (&entries_2 - &entries_1) as usize
1569 ))))
1570 );
1571
1572 assert!(matches!(entries.next(), Ok(None)));
1573
1574 let name = names.next().unwrap();
1576 assert_eq!(
1577 name_index.name_string_offset(name),
1578 Ok(DebugStrOffset(0xde))
1579 );
1580 assert_eq!(
1581 name_index.name_string(name, &debug_str).unwrap().slice(),
1582 b"__ARRAY_SIZE_TYPE__"
1583 );
1584
1585 let mut entries = name_index.name_entries(name).unwrap();
1586 assert!(matches!(
1587 entries.next(),
1588 Err(Error::InvalidAbbreviationCode(4))
1589 ));
1590 assert!(matches!(entries.next(), Ok(None)));
1591
1592 let name = names.next().unwrap();
1594 assert_eq!(
1595 name_index.name_string_offset(name),
1596 Ok(DebugStrOffset(0xd9))
1597 );
1598 assert_eq!(
1599 name_index.name_string(name, &debug_str).unwrap().slice(),
1600 b"char"
1601 );
1602
1603 let mut entries = name_index.name_entries(name).unwrap();
1604 assert!(matches!(entries.next(), Ok(None)));
1605
1606 assert_eq!(names.next(), None);
1607
1608 assert!(matches!(headers.next(), Ok(None)));
1609 }
1610 }
1611
1612 #[test]
1617 fn test_debug_names_no_hash_table() {
1618 for format in [Format::Dwarf32, Format::Dwarf64] {
1619 let word_size = usize::from(format.word_size());
1620 let abbrev_start = Label::new();
1621 let abbrev_end = Label::new();
1622
1623 let debug_str = Section::new()
1624 .append_bytes(b"main\0")
1625 .get_contents()
1626 .unwrap();
1627 let debug_str = DebugStr::new(&debug_str, LittleEndian);
1628
1629 let content = Section::with_endian(Endian::Little)
1630 .offset(0x101, format)
1632 .offset(0x102, format)
1633 .offset(0x201, format)
1635 .D64(0x1234_5678) .offset(0x0, format) .offset(0x00, format)
1641 .mark(&abbrev_start)
1642 .debug_names_abbrev(
1643 1,
1644 DW_TAG_subprogram,
1645 &[
1646 (DW_IDX_die_offset, DW_FORM_ref4),
1647 (DW_IDX_parent, DW_FORM_flag_present),
1648 ],
1649 )
1650 .debug_names_abbrev_null()
1651 .mark(&abbrev_end)
1652 .uleb(0x01)
1654 .offset(0x3c, format)
1655 .debug_names_entry_null()
1656 .get_contents()
1657 .unwrap();
1658
1659 let mut header = NameIndexHeader {
1660 offset: DebugNamesOffset(0),
1661 length: 0,
1662 format,
1663 version: 5,
1664 compile_unit_count: 2,
1665 local_type_unit_count: 1,
1666 foreign_type_unit_count: 1,
1667 bucket_count: 0,
1668 name_count: 1,
1669 abbrev_table_size: (&abbrev_end - &abbrev_start) as u32,
1670 augmentation_string: None,
1671 content: EndianSlice::new(&content, LittleEndian),
1672 };
1673
1674 let buf = Section::with_endian(Endian::Little)
1675 .debug_names_header(&mut header)
1676 .get_contents()
1677 .unwrap();
1678
1679 let debug_names = DebugNames::new(&buf, LittleEndian);
1680 let mut headers = debug_names.headers();
1681 let header = headers.next().unwrap().unwrap();
1682 assert_eq!(header.offset(), DebugNamesOffset(0));
1683 assert_eq!(header.length(), 51 + 6 * word_size);
1684 assert_eq!(header.version(), 5);
1685 assert_eq!(header.format(), format);
1686 assert_eq!(header.compile_unit_count(), 2);
1687 assert_eq!(header.local_type_unit_count(), 1);
1688 assert_eq!(header.foreign_type_unit_count(), 1);
1689 assert_eq!(header.bucket_count(), 0);
1690 assert_eq!(header.name_count(), 1);
1691 assert_eq!(header.abbrev_table_size(), 9);
1692 assert!(header.augmentation_string().is_none());
1693
1694 let name_index = header.index().unwrap();
1695
1696 assert_eq!(name_index.compile_unit_count(), 2);
1697 assert_eq!(name_index.compile_unit(0), Ok(DebugInfoOffset(0x101)));
1698 assert_eq!(name_index.compile_unit(1), Ok(DebugInfoOffset(0x102)));
1699 assert_eq!(name_index.default_compile_unit(), Ok(None));
1700
1701 assert_eq!(name_index.local_type_unit_count(), 1);
1702 assert_eq!(name_index.local_type_unit(0), Ok(DebugInfoOffset(0x201)));
1703
1704 assert_eq!(name_index.foreign_type_unit_count(), 1);
1705 assert_eq!(
1706 name_index.foreign_type_unit(0),
1707 Ok(DebugTypeSignature(0x1234_5678))
1708 );
1709
1710 assert_eq!(name_index.type_unit_count(), 2);
1711 assert_eq!(
1712 name_index.type_unit(0),
1713 Ok(NameTypeUnit::Local(DebugInfoOffset(0x201)))
1714 );
1715 assert_eq!(
1716 name_index.type_unit(1),
1717 Ok(NameTypeUnit::Foreign(DebugTypeSignature(0x1234_5678)))
1718 );
1719
1720 assert!(!name_index.has_hash_table());
1722 assert_eq!(name_index.bucket_count(), 0);
1723 assert!(name_index.find_by_bucket(0).is_err());
1724 assert!(name_index.find_by_hash(0).is_err());
1725
1726 assert_eq!(name_index.name_count(), 1);
1728 let mut names = name_index.names();
1729
1730 let name = names.next().unwrap();
1731 assert_eq!(name_index.name_string_offset(name), Ok(DebugStrOffset(0x0)));
1732 assert_eq!(
1733 name_index.name_string(name, &debug_str).unwrap().slice(),
1734 b"main"
1735 );
1736 let mut entries = name_index.name_entries(name).unwrap();
1737 let entry = entries.next().unwrap().unwrap();
1738 assert_eq!(entry, name_index.name_entry(entry.offset).unwrap());
1739
1740 assert!(headers.next().unwrap().is_none());
1741 }
1742 }
1743
1744 #[test]
1745 fn test_debug_names_invalid_version() {
1746 for format in [Format::Dwarf32, Format::Dwarf64] {
1747 let mut header = NameIndexHeader {
1748 offset: DebugNamesOffset(0),
1749 length: 0,
1750 format,
1751 version: 4,
1752 compile_unit_count: 0,
1753 local_type_unit_count: 0,
1754 foreign_type_unit_count: 0,
1755 bucket_count: 0,
1756 name_count: 0,
1757 abbrev_table_size: 0,
1758 augmentation_string: None,
1759 content: EndianSlice::new(&[], LittleEndian),
1760 };
1761
1762 let buf = Section::with_endian(Endian::Little)
1763 .debug_names_header(&mut header)
1764 .get_contents()
1765 .unwrap();
1766
1767 let debug_names = DebugNames::new(&buf, LittleEndian);
1768 let mut headers = debug_names.headers();
1769 let result = headers.next();
1770 assert_eq!(result.unwrap_err(), Error::UnknownVersion(4));
1771 assert!(headers.next().unwrap().is_none());
1772 }
1773 }
1774
1775 #[test]
1776 fn test_debug_names_truncated() {
1777 for format in [Format::Dwarf32, Format::Dwarf64] {
1778 let mut header = NameIndexHeader {
1779 offset: DebugNamesOffset(0),
1780 length: 0,
1781 format,
1782 version: 5,
1783 compile_unit_count: 0,
1784 local_type_unit_count: 0,
1785 foreign_type_unit_count: 0,
1786 bucket_count: 0,
1787 name_count: 0,
1788 abbrev_table_size: 0,
1789 augmentation_string: None,
1790 content: EndianSlice::new(&[], LittleEndian),
1791 };
1792
1793 let buf = Section::with_endian(Endian::Little)
1794 .debug_names_header(&mut header)
1795 .get_contents()
1796 .unwrap();
1797
1798 let debug_names = DebugNames::new(&buf[..buf.len() - 1], LittleEndian);
1799 let mut headers = debug_names.headers();
1800 assert!(headers.next().is_err());
1801 assert!(headers.next().unwrap().is_none());
1802 }
1803 }
1804
1805 #[test]
1806 fn test_debug_names_abbrev_table_empty() {
1807 let reader = EndianSlice::new(&[], LittleEndian);
1808 let abbrevs = NameAbbreviations::parse(reader).unwrap();
1809 assert!(abbrevs.abbreviations.is_empty());
1810
1811 let reader = EndianSlice::new(&[0], LittleEndian);
1812 let abbrevs = NameAbbreviations::parse(reader).unwrap();
1813 assert!(abbrevs.abbreviations.is_empty());
1814 }
1815
1816 #[test]
1817 fn test_debug_names_abbrev_table_invalid() {
1818 let input = Section::with_endian(Endian::Little)
1819 .uleb(1) .uleb(0) .uleb(2) .uleb(3) .D8(0) .D8(0) .D8(0) .get_contents()
1827 .unwrap();
1828 let reader = EndianSlice::new(&input, LittleEndian);
1829 assert!(matches!(
1830 NameAbbreviations::parse(reader),
1831 Err(Error::AbbreviationTagZero)
1832 ));
1833
1834 let input = Section::with_endian(Endian::Little)
1835 .uleb(1) .uleb(2) .uleb(0) .uleb(3) .D8(0) .D8(0) .D8(0) .get_contents()
1843 .unwrap();
1844 let reader = EndianSlice::new(&input, LittleEndian);
1845 assert!(matches!(
1846 NameAbbreviations::parse(reader),
1847 Err(Error::AttributeNameZero)
1848 ));
1849
1850 let input = Section::with_endian(Endian::Little)
1851 .uleb(1) .uleb(2) .uleb(3) .uleb(0) .D8(0) .D8(0) .D8(0) .get_contents()
1859 .unwrap();
1860 let reader = EndianSlice::new(&input, LittleEndian);
1861 assert!(matches!(
1862 NameAbbreviations::parse(reader),
1863 Err(Error::AttributeFormZero)
1864 ));
1865 }
1866
1867 #[test]
1868 fn test_debug_names_augmentation() {
1869 let augmentation = b"LLVM0700";
1870 let content = [0x12, 0x23];
1871 for i in 1..augmentation.len() {
1872 let augmentation_string = &augmentation[..i];
1873 let mut header = NameIndexHeader {
1874 offset: DebugNamesOffset(0),
1875 length: 0,
1876 format: Format::Dwarf32,
1877 version: 5,
1878 compile_unit_count: 0,
1879 local_type_unit_count: 0,
1880 foreign_type_unit_count: 0,
1881 bucket_count: 0,
1882 name_count: 0,
1883 abbrev_table_size: 0,
1884 augmentation_string: Some(EndianSlice::new(augmentation_string, LittleEndian)),
1885 content: EndianSlice::new(&content, LittleEndian),
1886 };
1887
1888 let buf = Section::with_endian(Endian::Little)
1889 .debug_names_header(&mut header)
1890 .get_contents()
1891 .unwrap();
1892
1893 let debug_names = DebugNames::new(&buf, LittleEndian);
1894 let mut headers = debug_names.headers();
1895 let header = headers.next().unwrap().unwrap();
1896 assert_eq!(
1897 header.augmentation_string().unwrap().slice(),
1898 augmentation_string
1899 );
1900 assert_eq!(header.content.slice(), content);
1901 }
1902 }
1903}