Coverage Report

Created: 2026-01-25 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/gimli-0.32.3/src/read/index.rs
Line
Count
Source
1
use core::slice;
2
3
use crate::common::SectionId;
4
use crate::constants;
5
use crate::endianity::Endianity;
6
use crate::read::{EndianSlice, Error, Reader, ReaderOffset, Result, Section};
7
8
/// The data in the `.debug_cu_index` section of a `.dwp` file.
9
///
10
/// This section contains the compilation unit index.
11
#[derive(Debug, Default, Clone, Copy)]
12
pub struct DebugCuIndex<R> {
13
    section: R,
14
}
15
16
impl<'input, Endian> DebugCuIndex<EndianSlice<'input, Endian>>
17
where
18
    Endian: Endianity,
19
{
20
    /// Construct a new `DebugCuIndex` instance from the data in the `.debug_cu_index`
21
    /// section.
22
0
    pub fn new(section: &'input [u8], endian: Endian) -> Self {
23
0
        Self::from(EndianSlice::new(section, endian))
24
0
    }
25
}
26
27
impl<T> DebugCuIndex<T> {
28
    /// Create a `DebugCuIndex` section that references the data in `self`.
29
    ///
30
    /// This is useful when `R` implements `Reader` but `T` does not.
31
    ///
32
    /// Used by `DwarfPackageSections::borrow`.
33
0
    pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugCuIndex<R>
34
0
    where
35
0
        F: FnMut(&'a T) -> R,
36
    {
37
0
        borrow(&self.section).into()
38
0
    }
39
}
40
41
impl<R> Section<R> for DebugCuIndex<R> {
42
0
    fn id() -> SectionId {
43
0
        SectionId::DebugCuIndex
44
0
    }
Unexecuted instantiation: <gimli::read::index::DebugCuIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>> as gimli::read::Section<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::id
Unexecuted instantiation: <gimli::read::index::DebugCuIndex<_> as gimli::read::Section<_>>::id
45
46
0
    fn reader(&self) -> &R {
47
0
        &self.section
48
0
    }
49
}
50
51
impl<R> From<R> for DebugCuIndex<R> {
52
0
    fn from(section: R) -> Self {
53
0
        DebugCuIndex { section }
54
0
    }
Unexecuted instantiation: <gimli::read::index::DebugCuIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>> as core::convert::From<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::from
Unexecuted instantiation: <gimli::read::index::DebugCuIndex<_> as core::convert::From<_>>::from
55
}
56
57
impl<R: Reader> DebugCuIndex<R> {
58
    /// Parse the index header.
59
0
    pub fn index(self) -> Result<UnitIndex<R>> {
60
0
        UnitIndex::parse(self.section)
61
0
    }
Unexecuted instantiation: <gimli::read::index::DebugCuIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::index
Unexecuted instantiation: <gimli::read::index::DebugCuIndex<_>>::index
62
}
63
64
/// The data in the `.debug_tu_index` section of a `.dwp` file.
65
///
66
/// This section contains the type unit index.
67
#[derive(Debug, Default, Clone, Copy)]
68
pub struct DebugTuIndex<R> {
69
    section: R,
70
}
71
72
impl<'input, Endian> DebugTuIndex<EndianSlice<'input, Endian>>
73
where
74
    Endian: Endianity,
75
{
76
    /// Construct a new `DebugTuIndex` instance from the data in the `.debug_tu_index`
77
    /// section.
78
0
    pub fn new(section: &'input [u8], endian: Endian) -> Self {
79
0
        Self::from(EndianSlice::new(section, endian))
80
0
    }
81
}
82
83
impl<T> DebugTuIndex<T> {
84
    /// Create a `DebugTuIndex` section that references the data in `self`.
85
    ///
86
    /// This is useful when `R` implements `Reader` but `T` does not.
87
    ///
88
    /// Used by `DwarfPackageSections::borrow`.
89
0
    pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugTuIndex<R>
90
0
    where
91
0
        F: FnMut(&'a T) -> R,
92
    {
93
0
        borrow(&self.section).into()
94
0
    }
95
}
96
97
impl<R> Section<R> for DebugTuIndex<R> {
98
0
    fn id() -> SectionId {
99
0
        SectionId::DebugTuIndex
100
0
    }
Unexecuted instantiation: <gimli::read::index::DebugTuIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>> as gimli::read::Section<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::id
Unexecuted instantiation: <gimli::read::index::DebugTuIndex<_> as gimli::read::Section<_>>::id
101
102
0
    fn reader(&self) -> &R {
103
0
        &self.section
104
0
    }
105
}
106
107
impl<R> From<R> for DebugTuIndex<R> {
108
0
    fn from(section: R) -> Self {
109
0
        DebugTuIndex { section }
110
0
    }
Unexecuted instantiation: <gimli::read::index::DebugTuIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>> as core::convert::From<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::from
Unexecuted instantiation: <gimli::read::index::DebugTuIndex<_> as core::convert::From<_>>::from
111
}
112
113
impl<R: Reader> DebugTuIndex<R> {
114
    /// Parse the index header.
115
0
    pub fn index(self) -> Result<UnitIndex<R>> {
116
0
        UnitIndex::parse(self.section)
117
0
    }
Unexecuted instantiation: <gimli::read::index::DebugTuIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::index
Unexecuted instantiation: <gimli::read::index::DebugTuIndex<_>>::index
118
}
119
120
const SECTION_COUNT_MAX: u8 = 8;
121
122
/// The partially parsed index from a `DebugCuIndex` or `DebugTuIndex`.
123
#[derive(Debug, Clone)]
124
pub struct UnitIndex<R: Reader> {
125
    version: u16,
126
    section_count: u32,
127
    unit_count: u32,
128
    slot_count: u32,
129
    hash_ids: R,
130
    hash_rows: R,
131
    // Only `section_count` values are valid.
132
    sections: [IndexSectionId; SECTION_COUNT_MAX as usize],
133
    offsets: R,
134
    sizes: R,
135
}
136
137
impl<R: Reader> UnitIndex<R> {
138
0
    fn parse(mut input: R) -> Result<UnitIndex<R>> {
139
0
        if input.is_empty() {
140
0
            return Ok(UnitIndex {
141
0
                version: 0,
142
0
                section_count: 0,
143
0
                unit_count: 0,
144
0
                slot_count: 0,
145
0
                hash_ids: input.clone(),
146
0
                hash_rows: input.clone(),
147
0
                sections: [IndexSectionId::DebugAbbrev; SECTION_COUNT_MAX as usize],
148
0
                offsets: input.clone(),
149
0
                sizes: input.clone(),
150
0
            });
151
0
        }
152
153
        // GNU split-dwarf extension to DWARF 4 uses a 32-bit version,
154
        // but DWARF 5 uses a 16-bit version followed by 16-bit padding.
155
0
        let mut original_input = input.clone();
156
        let version;
157
0
        if input.read_u32()? == 2 {
158
0
            version = 2
159
        } else {
160
0
            version = original_input.read_u16()?;
161
0
            if version != 5 {
162
0
                return Err(Error::UnknownVersion(version.into()));
163
0
            }
164
        }
165
166
0
        let section_count = input.read_u32()?;
167
0
        let unit_count = input.read_u32()?;
168
0
        let slot_count = input.read_u32()?;
169
0
        if slot_count != 0 && (slot_count & (slot_count - 1) != 0 || slot_count <= unit_count) {
170
0
            return Err(Error::InvalidIndexSlotCount);
171
0
        }
172
173
0
        let hash_ids = input.split(R::Offset::from_u64(u64::from(slot_count) * 8)?)?;
174
0
        let hash_rows = input.split(R::Offset::from_u64(u64::from(slot_count) * 4)?)?;
175
176
0
        let mut sections = [IndexSectionId::DebugAbbrev; SECTION_COUNT_MAX as usize];
177
0
        if section_count > SECTION_COUNT_MAX.into() {
178
0
            return Err(Error::InvalidIndexSectionCount);
179
0
        }
180
0
        for i in 0..section_count {
181
0
            let section = input.read_u32()?;
182
0
            sections[i as usize] = if version == 2 {
183
0
                match constants::DwSectV2(section) {
184
0
                    constants::DW_SECT_V2_INFO => IndexSectionId::DebugInfo,
185
0
                    constants::DW_SECT_V2_TYPES => IndexSectionId::DebugTypes,
186
0
                    constants::DW_SECT_V2_ABBREV => IndexSectionId::DebugAbbrev,
187
0
                    constants::DW_SECT_V2_LINE => IndexSectionId::DebugLine,
188
0
                    constants::DW_SECT_V2_LOC => IndexSectionId::DebugLoc,
189
0
                    constants::DW_SECT_V2_STR_OFFSETS => IndexSectionId::DebugStrOffsets,
190
0
                    constants::DW_SECT_V2_MACINFO => IndexSectionId::DebugMacinfo,
191
0
                    constants::DW_SECT_V2_MACRO => IndexSectionId::DebugMacro,
192
0
                    section => return Err(Error::UnknownIndexSectionV2(section)),
193
                }
194
            } else {
195
0
                match constants::DwSect(section) {
196
0
                    constants::DW_SECT_INFO => IndexSectionId::DebugInfo,
197
0
                    constants::DW_SECT_ABBREV => IndexSectionId::DebugAbbrev,
198
0
                    constants::DW_SECT_LINE => IndexSectionId::DebugLine,
199
0
                    constants::DW_SECT_LOCLISTS => IndexSectionId::DebugLocLists,
200
0
                    constants::DW_SECT_STR_OFFSETS => IndexSectionId::DebugStrOffsets,
201
0
                    constants::DW_SECT_MACRO => IndexSectionId::DebugMacro,
202
0
                    constants::DW_SECT_RNGLISTS => IndexSectionId::DebugRngLists,
203
0
                    section => return Err(Error::UnknownIndexSection(section)),
204
                }
205
            };
206
        }
207
208
0
        let offsets = input.split(R::Offset::from_u64(
209
0
            u64::from(unit_count) * u64::from(section_count) * 4,
210
0
        )?)?;
211
0
        let sizes = input.split(R::Offset::from_u64(
212
0
            u64::from(unit_count) * u64::from(section_count) * 4,
213
0
        )?)?;
214
215
0
        Ok(UnitIndex {
216
0
            version,
217
0
            section_count,
218
0
            unit_count,
219
0
            slot_count,
220
0
            hash_ids,
221
0
            hash_rows,
222
0
            sections,
223
0
            offsets,
224
0
            sizes,
225
0
        })
226
0
    }
Unexecuted instantiation: <gimli::read::index::UnitIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::parse
Unexecuted instantiation: <gimli::read::index::UnitIndex<_>>::parse
227
228
    /// Find `id` in the index hash table, and return the row index.
229
    ///
230
    /// `id` may be a compilation unit ID if this index is from `.debug_cu_index`,
231
    /// or a type signature if this index is from `.debug_tu_index`.
232
0
    pub fn find(&self, id: u64) -> Option<u32> {
233
0
        if self.slot_count == 0 {
234
0
            return None;
235
0
        }
236
0
        let mask = u64::from(self.slot_count - 1);
237
0
        let mut hash1 = id & mask;
238
0
        let hash2 = ((id >> 32) & mask) | 1;
239
0
        for _ in 0..self.slot_count {
240
            // The length of these arrays was validated in `UnitIndex::parse`.
241
0
            let mut hash_ids = self.hash_ids.clone();
242
0
            hash_ids.skip(R::Offset::from_u64(hash1 * 8).ok()?).ok()?;
243
0
            let hash_id = hash_ids.read_u64().ok()?;
244
0
            if hash_id == id {
245
0
                let mut hash_rows = self.hash_rows.clone();
246
0
                hash_rows.skip(R::Offset::from_u64(hash1 * 4).ok()?).ok()?;
247
0
                let hash_row = hash_rows.read_u32().ok()?;
248
0
                return Some(hash_row);
249
0
            }
250
0
            if hash_id == 0 {
251
0
                return None;
252
0
            }
253
0
            hash1 = (hash1 + hash2) & mask;
254
        }
255
0
        None
256
0
    }
Unexecuted instantiation: <gimli::read::index::UnitIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::find
Unexecuted instantiation: <gimli::read::index::UnitIndex<_>>::find
257
258
    /// Return the section offsets and sizes for the given row index.
259
0
    pub fn sections(&self, mut row: u32) -> Result<UnitIndexSectionIterator<'_, R>> {
260
0
        if row == 0 {
261
0
            return Err(Error::InvalidIndexRow);
262
0
        }
263
0
        row -= 1;
264
0
        if row >= self.unit_count {
265
0
            return Err(Error::InvalidIndexRow);
266
0
        }
267
0
        let mut offsets = self.offsets.clone();
268
0
        offsets.skip(R::Offset::from_u64(
269
0
            u64::from(row) * u64::from(self.section_count) * 4,
270
0
        )?)?;
271
0
        let mut sizes = self.sizes.clone();
272
0
        sizes.skip(R::Offset::from_u64(
273
0
            u64::from(row) * u64::from(self.section_count) * 4,
274
0
        )?)?;
275
0
        Ok(UnitIndexSectionIterator {
276
0
            sections: self.sections[..self.section_count as usize].iter(),
277
0
            offsets,
278
0
            sizes,
279
0
        })
280
0
    }
Unexecuted instantiation: <gimli::read::index::UnitIndex<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::sections
Unexecuted instantiation: <gimli::read::index::UnitIndex<_>>::sections
281
282
    /// Return the version.
283
    ///
284
    /// Defaults to 0 for empty sections.
285
0
    pub fn version(&self) -> u16 {
286
0
        self.version
287
0
    }
288
289
    /// Return the number of sections.
290
0
    pub fn section_count(&self) -> u32 {
291
0
        self.section_count
292
0
    }
293
294
    /// Return the number of units.
295
0
    pub fn unit_count(&self) -> u32 {
296
0
        self.unit_count
297
0
    }
298
299
    /// Return the number of slots.
300
0
    pub fn slot_count(&self) -> u32 {
301
0
        self.slot_count
302
0
    }
303
}
304
305
/// An iterator over the section offsets and sizes for a row in a `UnitIndex`.
306
#[derive(Debug, Clone)]
307
pub struct UnitIndexSectionIterator<'index, R: Reader> {
308
    sections: slice::Iter<'index, IndexSectionId>,
309
    offsets: R,
310
    sizes: R,
311
}
312
313
impl<'index, R: Reader> Iterator for UnitIndexSectionIterator<'index, R> {
314
    type Item = UnitIndexSection;
315
316
0
    fn next(&mut self) -> Option<UnitIndexSection> {
317
0
        let section = *self.sections.next()?;
318
        // The length of these arrays was validated in `UnitIndex::parse`.
319
0
        let offset = self.offsets.read_u32().ok()?;
320
0
        let size = self.sizes.read_u32().ok()?;
321
0
        Some(UnitIndexSection {
322
0
            section,
323
0
            offset,
324
0
            size,
325
0
        })
326
0
    }
Unexecuted instantiation: <gimli::read::index::UnitIndexSectionIterator<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>> as core::iter::traits::iterator::Iterator>::next
Unexecuted instantiation: <gimli::read::index::UnitIndexSectionIterator<_> as core::iter::traits::iterator::Iterator>::next
327
}
328
329
/// Information about a unit's contribution to a section in a `.dwp` file.
330
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
331
pub struct UnitIndexSection {
332
    /// The section kind.
333
    pub section: IndexSectionId,
334
    /// The base offset of the unit's contribution to the section.
335
    pub offset: u32,
336
    /// The size of the unit's contribution to the section.
337
    pub size: u32,
338
}
339
340
/// Section kinds which are permitted in a `.dwp` index.
341
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
342
pub enum IndexSectionId {
343
    /// The `.debug_abbrev.dwo` section.
344
    DebugAbbrev,
345
    /// The `.debug_info.dwo` section.
346
    DebugInfo,
347
    /// The `.debug_line.dwo` section.
348
    DebugLine,
349
    /// The `.debug_loc.dwo` section.
350
    DebugLoc,
351
    /// The `.debug_loclists.dwo` section.
352
    DebugLocLists,
353
    /// The `.debug_macinfo.dwo` section.
354
    DebugMacinfo,
355
    /// The `.debug_macro.dwo` section.
356
    DebugMacro,
357
    /// The `.debug_rnglists.dwo` section.
358
    DebugRngLists,
359
    /// The `.debug_str_offsets.dwo` section.
360
    DebugStrOffsets,
361
    /// The `.debug_types.dwo` section.
362
    DebugTypes,
363
}
364
365
impl IndexSectionId {
366
    /// Returns the corresponding `SectionId`.
367
0
    pub fn section_id(self) -> SectionId {
368
0
        match self {
369
0
            IndexSectionId::DebugAbbrev => SectionId::DebugAbbrev,
370
0
            IndexSectionId::DebugInfo => SectionId::DebugInfo,
371
0
            IndexSectionId::DebugLine => SectionId::DebugLine,
372
0
            IndexSectionId::DebugLoc => SectionId::DebugLoc,
373
0
            IndexSectionId::DebugLocLists => SectionId::DebugLocLists,
374
0
            IndexSectionId::DebugMacro => SectionId::DebugMacro,
375
0
            IndexSectionId::DebugMacinfo => SectionId::DebugMacinfo,
376
0
            IndexSectionId::DebugRngLists => SectionId::DebugRngLists,
377
0
            IndexSectionId::DebugStrOffsets => SectionId::DebugStrOffsets,
378
0
            IndexSectionId::DebugTypes => SectionId::DebugTypes,
379
        }
380
0
    }
381
382
    /// Returns the ELF section name for this kind, when found in a .dwo or .dwp file.
383
0
    pub fn dwo_name(self) -> &'static str {
384
0
        self.section_id().dwo_name().unwrap()
385
0
    }
386
}
387
388
#[cfg(test)]
389
mod tests {
390
    use super::*;
391
    use crate::endianity::BigEndian;
392
    use test_assembler::{Endian, Section};
393
394
    #[test]
395
    fn test_empty() {
396
        let buf = EndianSlice::new(&[], BigEndian);
397
        let index = UnitIndex::parse(buf).unwrap();
398
        assert_eq!(index.version(), 0);
399
        assert_eq!(index.unit_count(), 0);
400
        assert_eq!(index.slot_count(), 0);
401
        assert!(index.find(0).is_none());
402
    }
403
404
    #[test]
405
    fn test_zero_slots() {
406
        #[rustfmt::skip]
407
        let section = Section::with_endian(Endian::Big)
408
            // Header.
409
            .D32(2).D32(0).D32(0).D32(0);
410
        let buf = section.get_contents().unwrap();
411
        let buf = EndianSlice::new(&buf, BigEndian);
412
        let index = UnitIndex::parse(buf).unwrap();
413
        assert_eq!(index.version(), 2);
414
        assert_eq!(index.unit_count(), 0);
415
        assert_eq!(index.slot_count(), 0);
416
        assert!(index.find(0).is_none());
417
    }
418
419
    #[test]
420
    fn test_version_2() {
421
        #[rustfmt::skip]
422
        let section = Section::with_endian(Endian::Big)
423
            // Header.
424
            .D32(2).D32(0).D32(0).D32(1)
425
            // Slots.
426
            .D64(0).D32(0);
427
        let buf = section.get_contents().unwrap();
428
        let buf = EndianSlice::new(&buf, BigEndian);
429
        let index = UnitIndex::parse(buf).unwrap();
430
        assert_eq!(index.version, 2);
431
    }
432
433
    #[test]
434
    fn test_version_5() {
435
        #[rustfmt::skip]
436
        let section = Section::with_endian(Endian::Big)
437
            // Header.
438
            .D16(5).D16(0).D32(0).D32(0).D32(1)
439
            // Slots.
440
            .D64(0).D32(0);
441
        let buf = section.get_contents().unwrap();
442
        let buf = EndianSlice::new(&buf, BigEndian);
443
        let index = UnitIndex::parse(buf).unwrap();
444
        assert_eq!(index.version, 5);
445
    }
446
447
    #[test]
448
    fn test_version_5_invalid() {
449
        #[rustfmt::skip]
450
        let section = Section::with_endian(Endian::Big)
451
            // Header.
452
            .D32(5).D32(0).D32(0).D32(1)
453
            // Slots.
454
            .D64(0).D32(0);
455
        let buf = section.get_contents().unwrap();
456
        let buf = EndianSlice::new(&buf, BigEndian);
457
        assert!(UnitIndex::parse(buf).is_err());
458
    }
459
460
    #[test]
461
    fn test_version_2_sections() {
462
        #[rustfmt::skip]
463
        let section = Section::with_endian(Endian::Big)
464
            // Header.
465
            .D32(2).D32(8).D32(1).D32(2)
466
            // Slots.
467
            .D64(0).D64(0).D32(0).D32(0)
468
            // Sections.
469
            .D32(constants::DW_SECT_V2_INFO.0)
470
            .D32(constants::DW_SECT_V2_TYPES.0)
471
            .D32(constants::DW_SECT_V2_ABBREV.0)
472
            .D32(constants::DW_SECT_V2_LINE.0)
473
            .D32(constants::DW_SECT_V2_LOC.0)
474
            .D32(constants::DW_SECT_V2_STR_OFFSETS.0)
475
            .D32(constants::DW_SECT_V2_MACINFO.0)
476
            .D32(constants::DW_SECT_V2_MACRO.0)
477
            // Offsets.
478
            .D32(11).D32(12).D32(13).D32(14).D32(15).D32(16).D32(17).D32(18)
479
            // Sizes.
480
            .D32(21).D32(22).D32(23).D32(24).D32(25).D32(26).D32(27).D32(28);
481
        let buf = section.get_contents().unwrap();
482
        let buf = EndianSlice::new(&buf, BigEndian);
483
        let index = UnitIndex::parse(buf).unwrap();
484
        assert_eq!(index.section_count, 8);
485
        assert_eq!(
486
            index.sections,
487
            [
488
                IndexSectionId::DebugInfo,
489
                IndexSectionId::DebugTypes,
490
                IndexSectionId::DebugAbbrev,
491
                IndexSectionId::DebugLine,
492
                IndexSectionId::DebugLoc,
493
                IndexSectionId::DebugStrOffsets,
494
                IndexSectionId::DebugMacinfo,
495
                IndexSectionId::DebugMacro,
496
            ]
497
        );
498
        #[rustfmt::skip]
499
        let expect = [
500
            UnitIndexSection { section: IndexSectionId::DebugInfo, offset: 11, size: 21 },
501
            UnitIndexSection { section: IndexSectionId::DebugTypes, offset: 12, size: 22 },
502
            UnitIndexSection { section: IndexSectionId::DebugAbbrev, offset: 13, size: 23 },
503
            UnitIndexSection { section: IndexSectionId::DebugLine, offset: 14, size: 24 },
504
            UnitIndexSection { section: IndexSectionId::DebugLoc, offset: 15, size: 25 },
505
            UnitIndexSection { section: IndexSectionId::DebugStrOffsets, offset: 16, size: 26 },
506
            UnitIndexSection { section: IndexSectionId::DebugMacinfo, offset: 17, size: 27 },
507
            UnitIndexSection { section: IndexSectionId::DebugMacro, offset: 18, size: 28 },
508
        ];
509
        let mut sections = index.sections(1).unwrap();
510
        for section in &expect {
511
            assert_eq!(*section, sections.next().unwrap());
512
        }
513
        assert!(sections.next().is_none());
514
    }
515
516
    #[test]
517
    fn test_version_5_sections() {
518
        #[rustfmt::skip]
519
        let section = Section::with_endian(Endian::Big)
520
            // Header.
521
            .D16(5).D16(0).D32(7).D32(1).D32(2)
522
            // Slots.
523
            .D64(0).D64(0).D32(0).D32(0)
524
            // Sections.
525
            .D32(constants::DW_SECT_INFO.0)
526
            .D32(constants::DW_SECT_ABBREV.0)
527
            .D32(constants::DW_SECT_LINE.0)
528
            .D32(constants::DW_SECT_LOCLISTS.0)
529
            .D32(constants::DW_SECT_STR_OFFSETS.0)
530
            .D32(constants::DW_SECT_MACRO.0)
531
            .D32(constants::DW_SECT_RNGLISTS.0)
532
            // Offsets.
533
            .D32(11).D32(12).D32(13).D32(14).D32(15).D32(16).D32(17)
534
            // Sizes.
535
            .D32(21).D32(22).D32(23).D32(24).D32(25).D32(26).D32(27);
536
        let buf = section.get_contents().unwrap();
537
        let buf = EndianSlice::new(&buf, BigEndian);
538
        let index = UnitIndex::parse(buf).unwrap();
539
        assert_eq!(index.section_count, 7);
540
        assert_eq!(
541
            index.sections[..7],
542
            [
543
                IndexSectionId::DebugInfo,
544
                IndexSectionId::DebugAbbrev,
545
                IndexSectionId::DebugLine,
546
                IndexSectionId::DebugLocLists,
547
                IndexSectionId::DebugStrOffsets,
548
                IndexSectionId::DebugMacro,
549
                IndexSectionId::DebugRngLists,
550
            ]
551
        );
552
        #[rustfmt::skip]
553
        let expect = [
554
            UnitIndexSection { section: IndexSectionId::DebugInfo, offset: 11, size: 21 },
555
            UnitIndexSection { section: IndexSectionId::DebugAbbrev, offset: 12, size: 22 },
556
            UnitIndexSection { section: IndexSectionId::DebugLine, offset: 13, size: 23 },
557
            UnitIndexSection { section: IndexSectionId::DebugLocLists, offset: 14, size: 24 },
558
            UnitIndexSection { section: IndexSectionId::DebugStrOffsets, offset: 15, size: 25 },
559
            UnitIndexSection { section: IndexSectionId::DebugMacro, offset: 16, size: 26 },
560
            UnitIndexSection { section: IndexSectionId::DebugRngLists, offset: 17, size: 27 },
561
        ];
562
        let mut sections = index.sections(1).unwrap();
563
        for section in &expect {
564
            assert_eq!(*section, sections.next().unwrap());
565
        }
566
        assert!(sections.next().is_none());
567
568
        assert!(index.sections(0).is_err());
569
        assert!(index.sections(2).is_err());
570
    }
571
572
    #[test]
573
    fn test_hash() {
574
        #[rustfmt::skip]
575
        let section = Section::with_endian(Endian::Big)
576
            // Header.
577
            .D16(5).D16(0).D32(2).D32(3).D32(4)
578
            // Slots.
579
            .D64(0xffff_fff2_ffff_fff1)
580
            .D64(0xffff_fff0_ffff_fff1)
581
            .D64(0xffff_fff1_ffff_fff1)
582
            .D64(0)
583
            .D32(3).D32(1).D32(2).D32(0)
584
            // Sections.
585
            .D32(constants::DW_SECT_INFO.0)
586
            .D32(constants::DW_SECT_ABBREV.0)
587
            // Offsets.
588
            .D32(0).D32(0).D32(0).D32(0).D32(0).D32(0)
589
            // Sizes.
590
            .D32(0).D32(0).D32(0).D32(0).D32(0).D32(0);
591
        let buf = section.get_contents().unwrap();
592
        let buf = EndianSlice::new(&buf, BigEndian);
593
        let index = UnitIndex::parse(buf).unwrap();
594
        assert_eq!(index.version(), 5);
595
        assert_eq!(index.slot_count(), 4);
596
        assert_eq!(index.unit_count(), 3);
597
        assert_eq!(index.section_count(), 2);
598
        assert_eq!(index.find(0xffff_fff0_ffff_fff1), Some(1));
599
        assert_eq!(index.find(0xffff_fff1_ffff_fff1), Some(2));
600
        assert_eq!(index.find(0xffff_fff2_ffff_fff1), Some(3));
601
        assert_eq!(index.find(0xffff_fff3_ffff_fff1), None);
602
    }
603
604
    #[test]
605
    fn test_cu_index() {
606
        #[rustfmt::skip]
607
        let section = Section::with_endian(Endian::Big)
608
            // Header.
609
            .D16(5).D16(0).D32(0).D32(0).D32(1)
610
            // Slots.
611
            .D64(0).D32(0);
612
        let buf = section.get_contents().unwrap();
613
        let cu_index = DebugCuIndex::new(&buf, BigEndian);
614
        let index = cu_index.index().unwrap();
615
        assert_eq!(index.version, 5);
616
    }
617
618
    #[test]
619
    fn test_tu_index() {
620
        #[rustfmt::skip]
621
        let section = Section::with_endian(Endian::Big)
622
            // Header.
623
            .D16(5).D16(0).D32(0).D32(0).D32(1)
624
            // Slots.
625
            .D64(0).D32(0);
626
        let buf = section.get_contents().unwrap();
627
        let tu_index = DebugTuIndex::new(&buf, BigEndian);
628
        let index = tu_index.index().unwrap();
629
        assert_eq!(index.version, 5);
630
    }
631
}