Skip to main content

gimli/read/
names.rs

1//! Functions for parsing DWARF 5 `.debug_names` sections.
2//!
3//! The `.debug_names` section provides an accelerated access table for debugging
4//! information entries (DIEs) organized by name. This section is defined in
5//! DWARF 5 Section 6.1.1 and enables efficient lookup of symbols without
6//! scanning the entire `.debug_info` section.
7//!
8//! # DWARF 5 Name Index
9//!
10//! A name index in the `.debug_names` section contains:
11//! - **Header**: Format, version, and table counts
12//! - **CU/TU Lists**: Lists of compilation and type units
13//! - **Hash Table**: Bucket-based hash table for name lookup
14//! - **Name Table**: String and entry offsets for each name
15//! - **Abbreviation Table**: Describes entry structure and attributes
16//! - **Entry Pool**: Series of entries with abbreviation codes and attributes
17//!
18//! Per DWARF 5 Section 6.1.1.3, a `.debug_names` section can contain multiple
19//! name indexes. There are two strategies:
20//! - **Per-module index**: Single index covering all compilation units (most common)
21//! - **Per-CU indexes**: Separate indexes for individual compilation units
22//!
23//! The choice depends on the compiler/linker. When looking up names, all indexes
24//! must be searched since a name could appear in any index.
25//!
26use 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/// The `DebugNames` struct represents the DWARF 5 name index information
37/// found in the `.debug_names` section.
38///
39/// The `.debug_names` section provides an index for efficiently finding
40/// debugging information entries (DIEs) by name. It contains hash tables
41/// that map names to DIE offsets, allowing debuggers to quickly locate
42/// functions, variables, types, and other named entities.
43#[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    /// Construct a new `DebugNames` instance from the data in the `.debug_names`
53    /// section.
54    ///
55    /// It is the caller's responsibility to read the `.debug_names` section and
56    /// present it as a `&[u8]` slice. That means using some ELF loader on
57    /// Linux, a Mach-O loader on macOS, etc.
58    ///
59    /// ```
60    /// use gimli::{DebugNames, LittleEndian};
61    ///
62    /// # let buf = [0x00, 0x01, 0x02, 0x03];
63    /// # let read_debug_names_section_somehow = || &buf;
64    /// let debug_names =
65    ///     DebugNames::new(read_debug_names_section_somehow(), LittleEndian);
66    /// ```
67    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    /// Create a `DebugNames` section that references the data in `self`.
74    ///
75    /// This is useful when `R` implements `Reader` but `T` does not.
76    ///
77    /// Used by `DwarfSections::borrow`.
78    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    /// Iterate over all name indexes in the `.debug_names` section.
88    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/// An iterator over the name index headers in the `.debug_names` section.
115#[derive(Debug, Clone)]
116pub struct NameIndexHeaderIter<R: Reader> {
117    input: R,
118    end_offset: R::Offset,
119}
120
121impl<R: Reader> NameIndexHeaderIter<R> {
122    /// Advance the iterator and return the next name index header.
123    ///
124    /// Returns `Ok(None)` when iteration is complete.
125    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/// The header of a name index in the `.debug_names` section.
148#[derive(Debug, Clone)]
149pub struct NameIndexHeader<R: Reader> {
150    /// The section offset of the header.
151    offset: DebugNamesOffset<R::Offset>,
152    /// The length of this name index.
153    length: R::Offset,
154    /// The format of the unit.
155    format: Format,
156    /// Version of the name index format (should be 5 for DWARF 5).
157    version: u16,
158    /// Number of compilation units in the CU list.
159    compile_unit_count: u32,
160    /// Number of type units in the local TU list.
161    local_type_unit_count: u32,
162    /// Number of type units in the foreign TU list.
163    foreign_type_unit_count: u32,
164    /// Number of buckets in the hash table.
165    bucket_count: u32,
166    /// Number of unique name entries.
167    name_count: u32,
168    /// Size of the abbreviations table in bytes.
169    abbrev_table_size: u32,
170    /// The augmentation string.
171    augmentation_string: Option<R>,
172    /// The remaining unparsed contents of the index.
173    content: R,
174}
175
176impl<R: Reader> NameIndexHeader<R> {
177    /// Convert the header into a `NameIndex`.
178    pub fn index(self) -> Result<NameIndex<R>> {
179        NameIndex::new(self)
180    }
181
182    /// Return the section offset of this name index.
183    #[inline]
184    pub fn offset(&self) -> DebugNamesOffset<R::Offset> {
185        self.offset
186    }
187
188    /// Return the index length.
189    #[inline]
190    pub fn length(&self) -> R::Offset {
191        self.length
192    }
193
194    /// Return the format (DWARF32 or DWARF64).
195    #[inline]
196    pub fn format(&self) -> Format {
197        self.format
198    }
199
200    /// Return the version of this name index.
201    #[inline]
202    pub fn version(&self) -> u16 {
203        self.version
204    }
205
206    /// Return the number of compilation units in this index.
207    #[inline]
208    pub fn compile_unit_count(&self) -> u32 {
209        self.compile_unit_count
210    }
211
212    /// Return the number of local type units in this index.
213    #[inline]
214    pub fn local_type_unit_count(&self) -> u32 {
215        self.local_type_unit_count
216    }
217
218    /// Return the number of foreign type units in this index.
219    #[inline]
220    pub fn foreign_type_unit_count(&self) -> u32 {
221        self.foreign_type_unit_count
222    }
223
224    /// Return the number of buckets in the hash table.
225    #[inline]
226    pub fn bucket_count(&self) -> u32 {
227        self.bucket_count
228    }
229
230    /// Return the number of unique name entries.
231    #[inline]
232    pub fn name_count(&self) -> u32 {
233        self.name_count
234    }
235
236    /// Return the size of the abbreviations table in bytes.
237    #[inline]
238    pub fn abbrev_table_size(&self) -> u32 {
239        self.abbrev_table_size
240    }
241
242    /// Return the augmentation string.
243    #[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))?; // Padding
259        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/// An index into the name table of a `NameIndex`.
294///
295/// This is used as an index into the list of string offsets, the list of entry
296/// offsets, and the list of hashes.
297///
298/// Note that while the DWARF standard specifies that indexes in the DWARF data
299/// start at 1, we use a zero based index here. Functions that read an index from
300/// the data will automatically adjust the index to start at 0.
301#[derive(Debug, Clone, Copy, PartialEq, Eq)]
302pub struct NameTableIndex(pub u32);
303
304/// A reference to a type unit.
305///
306/// This is the result of looking up a type unit index obtained from a `DW_IDX_type_unit`
307/// attribute.
308#[derive(Debug, Clone, Copy, PartialEq, Eq)]
309pub enum NameTypeUnit<T> {
310    /// The offset of a local type unit in the `.debug_info` section.
311    Local(DebugInfoOffset<T>),
312    /// The type signature of a foreign type unit.
313    Foreign(DebugTypeSignature),
314}
315
316/// A single name index from the `.debug_names` section.
317///
318/// It provides access to the compilation unit table, type unit tables, hash table, name
319/// table, and entry pool that make up the accelerated lookup structure.
320#[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    // Pre-sliced readers for each section
330    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    /// Create a new name index from a header.
344    pub fn new(header: NameIndexHeader<R>) -> Result<Self> {
345        let mut reader = header.content;
346
347        // Calculate section sizes once
348        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; // Always 8 bytes per signature
353        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        // Slice each section once (split() advances the reader automatically)
363        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        // Remaining data is the entry pool
375        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    /// Return the number of compilation units in this index.
397    pub fn compile_unit_count(&self) -> u32 {
398        self.compile_unit_count
399    }
400
401    /// Get the `.debug_info` offset of a compilation unit.
402    ///
403    /// `index` must be less than [`Self::compile_unit_count`].
404    ///
405    /// Returns an error if `index` is invalid.
406    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    /// Return the `.debug_info` offset of the default compilation unit, if any.
415    ///
416    /// If there is only one compilation unit, then entries may omit the `DW_IDX_compile_unit`
417    /// attribute.
418    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    /// Return the number of local type units in this index.
427    pub fn local_type_unit_count(&self) -> u32 {
428        self.local_type_unit_count
429    }
430
431    /// Get the `.debug_info` offset of a local type unit.
432    ///
433    /// `index` must be less than [`Self::local_type_unit_count`].
434    ///
435    /// Returns an error if `index` is invalid.
436    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    /// Return the number of foreign type units in this index.
445    pub fn foreign_type_unit_count(&self) -> u32 {
446        self.foreign_type_unit_count
447    }
448
449    /// Get the signature of a foreign type unit.
450    ///
451    /// `index` must be less than [`Self::foreign_type_unit_count`].
452    ///
453    /// Returns an error if `index` is invalid.
454    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    /// Return the number of type units in this index, both local and foreign.
461    pub fn type_unit_count(&self) -> u32 {
462        self.local_type_unit_count + self.foreign_type_unit_count
463    }
464
465    /// Get a type unit reference.
466    ///
467    /// `index` must be less than [`Self::type_unit_count`], and normally is
468    /// obtained from a `DW_IDX_type_unit` attribute.
469    ///
470    /// Returns an error if `index` is invalid.
471    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    /// Return true if the name index contains a hash table.
481    pub fn has_hash_table(&self) -> bool {
482        self.bucket_count != 0
483    }
484
485    /// Return the number of buckets in the hash table.
486    pub fn bucket_count(&self) -> u32 {
487        self.bucket_count
488    }
489
490    /// Iterate over the hash entries for a bucket in the hash table.
491    ///
492    /// This function is only for diagnostic uses. Usually [`Self::find_by_hash`] should be
493    /// called instead.
494    ///
495    /// The given bucket index is 0 based, and must be less than [`Self::bucket_count`].
496    ///
497    /// Returns an error if there is no hash table or the bucket index is invalid.
498    /// Returns `Ok(None)` if the bucket is empty.
499    pub fn find_by_bucket(&self, bucket_index: u32) -> Result<Option<NameBucketIter<R>>> {
500        NameBucketIter::new(self, bucket_index)
501    }
502
503    /// Iterate over the indexes of the names with the given hash value.
504    ///
505    /// The user must then check each name to see if it matches the desired name.
506    ///
507    /// Returns an error if there is no hash table.
508    pub fn find_by_hash(&self, hash_value: u32) -> Result<NameHashIter<R>> {
509        NameHashIter::new(self, hash_value)
510    }
511
512    /// Get the number of names in the name index.
513    ///
514    /// This is 1 greater than the maximum valid [`NameTableIndex`].
515    pub fn name_count(&self) -> u32 {
516        self.name_count
517    }
518
519    /// Iterate over the indexes of all names in the name table.
520    pub fn names(&self) -> NameTableIter {
521        NameTableIter::new(self)
522    }
523
524    /// Get the string table offset for the name at the given index.
525    ///
526    /// Returns an error if `index` is invalid.
527    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    /// Get the name at the given index using the provided `.debug_str` section.
536    ///
537    /// Returns an error if `index` is invalid, or the string table offset is invalid.
538    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    /// Iterate over the series of entries for the given name table index.
544    ///
545    /// Each name in the name table has a corresponding series of entries
546    /// with that name in the entry pool.
547    ///
548    /// Returns an error if `index` is invalid, or the entry pool offset is invalid.
549    pub fn name_entries(&self, index: NameTableIndex) -> Result<NameEntryIter<'_, R>> {
550        NameEntryIter::new(self, index)
551    }
552
553    /// Parse the entry at the given entry pool offset.
554    ///
555    /// This is useful for reading the entry referenced by a `DW_IDX_parent` attribute.
556    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    /// Get the abbreviation table for name entries in this name index.
564    pub fn abbreviations(&self) -> &NameAbbreviations {
565        &self.abbreviations
566    }
567}
568
569/// An iterator over the indexes of all names in a name index.
570#[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/// An iterator over the hash entries for a bucket in a name index hash table.
599#[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    /// Advance the iterator and return the next name table index and hash.
631    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/// An iterator over the indexes of the names in a name index hash table that match a hash
664/// value.
665#[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    /// Advance the iterator and return the next name table index.
684    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/// An iterator for a series of name entries in a name index entry pool.
716///
717/// Each name in a name index corresponds to a series of entries
718/// with that name.
719#[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    /// Advance the iterator and return the next name entry.
747    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                // Series end.
757                self.entries.empty();
758                Ok(None)
759            }
760            Err(e) => {
761                // On error, prevent further iteration
762                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/// An offset into the entry pool of a name index.
788#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
789pub struct NameEntryOffset<T = usize>(pub T);
790
791/// A parsed entry from the `.debug_names` section.
792#[derive(Debug, Clone, PartialEq, Eq)]
793pub struct NameEntry<R: Reader> {
794    /// The offset of the entry in the entries pool.
795    pub offset: NameEntryOffset<R::Offset>,
796
797    /// The abbreviation code for this entry.
798    pub abbrev_code: u64,
799
800    /// The DIE tag for this entry.
801    pub tag: constants::DwTag,
802
803    /// The attributes for this entry.
804    pub attrs: Vec<NameAttribute<R>>,
805}
806
807impl<R: Reader> NameEntry<R> {
808    /// Get the value of the `DW_IDX_compile_unit` attribute, if any.
809    ///
810    /// If neither `DW_IDX_compile_unit` nor `DW_IDX_type_unit` exist then you should use
811    /// [`NameIndex::default_compile_unit`].
812    ///
813    /// If both `DW_IDX_compile_unit` and `DW_IDX_type_unit` exist then this value is for
814    /// a skeleton CU that may be used to locate a split DWARF object file containing
815    /// the type unit.
816    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    /// Get the value of the `DW_IDX_type_unit` attribute, if any.
826    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    /// Get the value of the `DW_IDX_die_offset` attribute, if any.
836    ///
837    /// This is the offset of the DIE within the compile unit or type unit.
838    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    /// Get the value of the `DW_IDX_parent` attribute, if any.
848    ///
849    /// Returns `Ok(Some(Some(offset)))` if the DIE parent is indexed.
850    /// Returns `Ok(Some(None))` if the DIE parent is not indexed.
851    /// Returns `Ok(None)` if it is unknown whether the DIE parent is indexed
852    /// because the producer did not generate a `DW_IDX_parent` attribute.
853    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    /// Get the value of the `DW_IDX_type_hash` attribute, if any.
863    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    /// Parse a single entry from the entry pool.
873    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/// A parsed attribute for a [`NameEntry`].
905#[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    /// Get the attribute name.
914    pub fn name(&self) -> constants::DwIdx {
915        self.name
916    }
917
918    /// Get the attribute form.
919    pub fn form(&self) -> constants::DwForm {
920        self.form
921    }
922
923    /// Get the attribute value.
924    ///
925    /// Interpretation of this value depends on the name and form.
926    pub fn value(&self) -> &NameAttributeValue<R> {
927        &self.value
928    }
929
930    /// Get the value of a `DW_IDX_compile_unit` attribute.
931    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    /// Get the value of a `DW_IDX_type_unit` attribute.
943    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    /// Get the value of a `DW_IDX_die_offset` attribute.
955    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    /// Get the value of a `DW_IDX_parent` attribute.
963    ///
964    /// Returns `Ok(Some(offset))` if the DIE parent is indexed.
965    /// Returns `Ok(None)` if the DIE parent is not indexed.
966    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    /// Get the value of a `DW_IDX_type_hash` attribute.
975    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/// A parsed attribute value for a [`NameEntry`].
984#[derive(Debug, Clone, Copy, PartialEq, Eq)]
985pub enum NameAttributeValue<R: Reader> {
986    /// An unsigned integer.
987    ///
988    /// This can be from the following forms:
989    /// `DW_FORM_data1`, `DW_FORM_data2`, `DW_FORM_data4`, `DW_FORM_data8`, `DW_FORM_udata`
990    Unsigned(u64),
991    /// An offset within a DWARF section or part thereof.
992    ///
993    /// This can be from the following forms:
994    /// `DW_FORM_ref1`, `DW_FORM_ref2`, `DW_FORM_ref4`, `DW_FORM_ref8`, `DW_FORM_ref_udata`
995    Offset(R::Offset),
996    /// A boolean flag.
997    ///
998    /// This can be from the following forms:
999    /// `DW_FORM_flag`, `DW_FORM_flag_present`
1000    Flag(bool),
1001}
1002
1003/// Read an attribute value.
1004///
1005/// This handles the subset of DWARF forms used in `.debug_names` entry pools
1006/// (`DW_IDX_*` attributes).
1007fn 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/// A table of name entry abbreviations.
1062#[derive(Debug, Default, Clone)]
1063pub struct NameAbbreviations {
1064    /// The abbreviations in this table.
1065    abbreviations: Vec<NameAbbreviation>,
1066}
1067
1068impl NameAbbreviations {
1069    /// Get an abbreviation by its code.
1070    pub fn get(&self, code: u64) -> Option<&NameAbbreviation> {
1071        self.abbreviations.iter().find(|abbrev| abbrev.code == code)
1072    }
1073
1074    /// Get all abbreviations.
1075    pub fn abbreviations(&self) -> &[NameAbbreviation] {
1076        &self.abbreviations
1077    }
1078
1079    /// Parse the abbreviation table from a reader.
1080    fn parse<R: Reader>(mut reader: R) -> Result<NameAbbreviations> {
1081        let mut abbreviations = Vec::new();
1082
1083        // Allow missing null terminator.
1084        while !reader.is_empty() {
1085            let code = reader.read_uleb128()?;
1086            if code == 0 {
1087                break; // End of abbreviation table
1088            }
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/// A name abbreviation entry defines how name entries are encoded.
1124#[derive(Debug, Clone)]
1125pub struct NameAbbreviation {
1126    /// The abbreviation code.
1127    code: u64,
1128    /// The DIE tag.
1129    tag: constants::DwTag,
1130    /// The list of attribute specifications.
1131    attributes: Vec<NameAbbreviationAttribute>,
1132}
1133
1134impl NameAbbreviation {
1135    /// Get the abbreviation code.
1136    pub fn code(&self) -> u64 {
1137        self.code
1138    }
1139
1140    /// Get the DIE tag.
1141    pub fn tag(&self) -> constants::DwTag {
1142        self.tag
1143    }
1144
1145    /// Get the attribute specifications.
1146    pub fn attributes(&self) -> &[NameAbbreviationAttribute] {
1147        &self.attributes
1148    }
1149}
1150
1151/// An attribute specification in a name abbreviation.
1152#[derive(Debug, Clone)]
1153pub struct NameAbbreviationAttribute {
1154    /// The attribute name (index type).
1155    name: constants::DwIdx,
1156    /// The attribute form.
1157    form: constants::DwForm,
1158}
1159
1160impl NameAbbreviationAttribute {
1161    /// Get the attribute name (index type).
1162    pub fn name(&self) -> constants::DwIdx {
1163        self.name
1164    }
1165
1166    /// Get the attribute form.
1167    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    /// Debug names section builder methods for testing
1181    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) // Padding
1210                .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) // Null terminator
1236        }
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                // CU offsets
1290                .offset(0x101, format)
1291                // Local TU offsets
1292                .offset(0x201, format)
1293                .offset(0x202, format)
1294                // Foreign TU signatures
1295                .D64(0x1234_5678) // Hash for "int"
1296                // Hash buckets
1297                .D32(1) // Bucket 0: points to name 1 ("int")
1298                .D32(0) // Bucket 1: empty
1299                .D32(2) // Bucket 2: points to name 2 ("main")
1300                .D32(3) // Bucket 3: points to name 3 ("__ARRAY_SIZE_TYPE__")
1301                // Hash array
1302                .D32(0x0b88_8030) // Hash for "int"
1303                .D32(0x7c9a_7f6a) // Hash for "main"
1304                .D32(0x0cef_4cfb) // Hash for "__ARRAY_SIZE_TYPE__"
1305                .D32(0x7c95_2063) // Hash for "char"
1306                // String offsets
1307                .offset(0xf7, format) // String offset for "int"
1308                .offset(0xf2, format) // String offset for "main"
1309                .offset(0xde, format) // String offset for "__ARRAY_SIZE_TYPE__"
1310                .offset(0xd9, format) // String offset for "char"
1311                // Entry series offsets
1312                .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                // Entries series for name 1
1339                .mark(&entries_1)
1340                // Local TU
1341                .uleb(1)
1342                .uleb(0)
1343                .offset(0x10, format)
1344                // Foreign TU
1345                .uleb(1)
1346                .uleb(2)
1347                .offset(0x20, format)
1348                // Invalid TU
1349                .uleb(1)
1350                .uleb(4)
1351                .offset(0x30, format)
1352                .debug_names_entry_null()
1353                // Entries series for name 2
1354                .mark(&entries_2)
1355                // No CU
1356                .uleb(2)
1357                .offset(0x40, format)
1358                // CU
1359                .uleb(3)
1360                .D8(0)
1361                .offset(0x50, format)
1362                .offset((&entries_2 - &entries_1) as usize, format)
1363                .debug_names_entry_null()
1364                // Entries series for name 3
1365                .mark(&entries_3)
1366                .uleb(4) // Invalid
1367                .debug_names_entry_null()
1368                // Entries series for name 4
1369                .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            // Bucket 0 contains 1 name
1452            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            // Bucket 1 is empty
1457            assert!(matches!(name_index.find_by_bucket(1), Ok(None)));
1458
1459            // Bucket 3 contains 2 names
1460            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            // Bucket 4 is invalid
1466            assert!(name_index.find_by_bucket(4).is_err());
1467
1468            // Hash present
1469            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            // No bucket for hash
1479            let mut names = name_index.find_by_hash(0x0b88_8031).unwrap();
1480            assert!(matches!(names.next(), Ok(None)));
1481
1482            // Bucket for hash, but hash not present
1483            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            // TU entries
1490            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            // CU entries
1537            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            // Invalid entry
1575            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            // No entries
1593            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    // Tests:
1613    // - no hash table
1614    // - no augmentation string
1615    // - no default compile unit
1616    #[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                // CU offsets
1631                .offset(0x101, format)
1632                .offset(0x102, format)
1633                // Local TU offset
1634                .offset(0x201, format)
1635                // Foreign TU signatures
1636                .D64(0x1234_5678) // Hash for "int"
1637                // String offsets
1638                .offset(0x0, format) // String offset for "main"
1639                // Entry offsets
1640                .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                // Entry 0: abbrev=1, die_offset=0x3c
1653                .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            // Hash table is not present
1721            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            // Names and entries are still accessible
1727            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) // code
1820            .uleb(0) // invalid tag
1821            .uleb(2) // name
1822            .uleb(3) // form
1823            .D8(0) // name terminator
1824            .D8(0) // form terminator
1825            .D8(0) // code terminator
1826            .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) // code
1836            .uleb(2) // tag
1837            .uleb(0) // invalid name
1838            .uleb(3) // form
1839            .D8(0) // name terminator
1840            .D8(0) // form terminator
1841            .D8(0) // code terminator
1842            .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) // code
1852            .uleb(2) // tag
1853            .uleb(3) // name
1854            .uleb(0) // invalid form
1855            .D8(0) // name terminator
1856            .D8(0) // form terminator
1857            .D8(0) // code terminator
1858            .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}