3 use crate::common
::SectionId
;
5 use crate::endianity
::Endianity
;
6 use crate::read
::{EndianSlice, Error, Reader, ReaderOffset, Result, Section}
;
8 /// The data in the `.debug_cu_index` section of a `.dwp` file.
10 /// This section contains the compilation unit index.
11 #[derive(Debug, Default, Clone, Copy)]
12 pub struct DebugCuIndex
<R
> {
16 impl<'input
, Endian
> DebugCuIndex
<EndianSlice
<'input
, Endian
>>
20 /// Construct a new `DebugCuIndex` instance from the data in the `.debug_cu_index`
22 pub fn new(section
: &'input
[u8], endian
: Endian
) -> Self {
23 Self::from(EndianSlice
::new(section
, endian
))
27 impl<R
> Section
<R
> for DebugCuIndex
<R
> {
28 fn id() -> SectionId
{
29 SectionId
::DebugCuIndex
32 fn reader(&self) -> &R
{
37 impl<R
> From
<R
> for DebugCuIndex
<R
> {
38 fn from(section
: R
) -> Self {
39 DebugCuIndex { section }
43 impl<R
: Reader
> DebugCuIndex
<R
> {
44 /// Parse the index header.
45 pub fn index(self) -> Result
<UnitIndex
<R
>> {
46 UnitIndex
::parse(self.section
)
50 /// The data in the `.debug_tu_index` section of a `.dwp` file.
52 /// This section contains the type unit index.
53 #[derive(Debug, Default, Clone, Copy)]
54 pub struct DebugTuIndex
<R
> {
58 impl<'input
, Endian
> DebugTuIndex
<EndianSlice
<'input
, Endian
>>
62 /// Construct a new `DebugTuIndex` instance from the data in the `.debug_tu_index`
64 pub fn new(section
: &'input
[u8], endian
: Endian
) -> Self {
65 Self::from(EndianSlice
::new(section
, endian
))
69 impl<R
> Section
<R
> for DebugTuIndex
<R
> {
70 fn id() -> SectionId
{
71 SectionId
::DebugTuIndex
74 fn reader(&self) -> &R
{
79 impl<R
> From
<R
> for DebugTuIndex
<R
> {
80 fn from(section
: R
) -> Self {
81 DebugTuIndex { section }
85 impl<R
: Reader
> DebugTuIndex
<R
> {
86 /// Parse the index header.
87 pub fn index(self) -> Result
<UnitIndex
<R
>> {
88 UnitIndex
::parse(self.section
)
92 const SECTION_COUNT_MAX
: u8 = 8;
94 /// The partially parsed index from a `DebugCuIndex` or `DebugTuIndex`.
95 #[derive(Debug, Clone)]
96 pub struct UnitIndex
<R
: Reader
> {
103 // Only `section_count` values are valid.
104 sections
: [SectionId
; SECTION_COUNT_MAX
as usize],
109 impl<R
: Reader
> UnitIndex
<R
> {
110 fn parse(mut input
: R
) -> Result
<UnitIndex
<R
>> {
111 if input
.is_empty() {
112 return Ok(UnitIndex
{
117 hash_ids
: input
.clone(),
118 hash_rows
: input
.clone(),
119 sections
: [SectionId
::DebugAbbrev
; SECTION_COUNT_MAX
as usize],
120 offsets
: input
.clone(),
121 sizes
: input
.clone(),
125 // GNU split-dwarf extension to DWARF 4 uses a 32-bit version,
126 // but DWARF 5 uses a 16-bit version followed by 16-bit padding.
127 let mut original_input
= input
.clone();
129 if input
.read_u32()?
== 2 {
132 version
= original_input
.read_u16()?
;
134 return Err(Error
::UnknownVersion(version
.into()));
138 let section_count
= input
.read_u32()?
;
139 let unit_count
= input
.read_u32()?
;
140 let slot_count
= input
.read_u32()?
;
141 if slot_count
== 0 || slot_count
& (slot_count
- 1) != 0 || slot_count
<= unit_count
{
142 return Err(Error
::InvalidIndexSlotCount
);
145 let hash_ids
= input
.split(R
::Offset
::from_u64(u64::from(slot_count
) * 8)?
)?
;
146 let hash_rows
= input
.split(R
::Offset
::from_u64(u64::from(slot_count
) * 4)?
)?
;
148 let mut sections
= [SectionId
::DebugAbbrev
; SECTION_COUNT_MAX
as usize];
149 if section_count
> SECTION_COUNT_MAX
.into() {
150 return Err(Error
::InvalidIndexSectionCount
);
152 for i
in 0..section_count
{
153 let section
= input
.read_u32()?
;
154 sections
[i
as usize] = if version
== 2 {
155 match constants
::DwSectV2(section
) {
156 constants
::DW_SECT_V2_INFO
=> SectionId
::DebugInfo
,
157 constants
::DW_SECT_V2_TYPES
=> SectionId
::DebugTypes
,
158 constants
::DW_SECT_V2_ABBREV
=> SectionId
::DebugAbbrev
,
159 constants
::DW_SECT_V2_LINE
=> SectionId
::DebugLine
,
160 constants
::DW_SECT_V2_LOC
=> SectionId
::DebugLoc
,
161 constants
::DW_SECT_V2_STR_OFFSETS
=> SectionId
::DebugStrOffsets
,
162 constants
::DW_SECT_V2_MACINFO
=> SectionId
::DebugMacinfo
,
163 constants
::DW_SECT_V2_MACRO
=> SectionId
::DebugMacro
,
164 _
=> return Err(Error
::UnknownIndexSection
),
167 match constants
::DwSect(section
) {
168 constants
::DW_SECT_INFO
=> SectionId
::DebugInfo
,
169 constants
::DW_SECT_ABBREV
=> SectionId
::DebugAbbrev
,
170 constants
::DW_SECT_LINE
=> SectionId
::DebugLine
,
171 constants
::DW_SECT_LOCLISTS
=> SectionId
::DebugLocLists
,
172 constants
::DW_SECT_STR_OFFSETS
=> SectionId
::DebugStrOffsets
,
173 constants
::DW_SECT_MACRO
=> SectionId
::DebugMacro
,
174 constants
::DW_SECT_RNGLISTS
=> SectionId
::DebugRngLists
,
175 _
=> return Err(Error
::UnknownIndexSection
),
180 let offsets
= input
.split(R
::Offset
::from_u64(
181 u64::from(unit_count
) * u64::from(section_count
) * 4,
183 let sizes
= input
.split(R
::Offset
::from_u64(
184 u64::from(unit_count
) * u64::from(section_count
) * 4,
200 /// Find `id` in the index hash table, and return the row index.
202 /// `id` may be a compilation unit ID if this index is from `.debug_cu_index`,
203 /// or a type signature if this index is from `.debug_tu_index`.
204 pub fn find(&self, id
: u64) -> Option
<u32> {
205 if self.slot_count
== 0 {
208 let mask
= u64::from(self.slot_count
- 1);
209 let mut hash1
= id
& mask
;
210 let hash2
= ((id
>> 32) & mask
) | 1;
211 for _
in 0..self.slot_count
{
212 // The length of these arrays was validated in `UnitIndex::parse`.
213 let mut hash_ids
= self.hash_ids
.clone();
214 hash_ids
.skip(R
::Offset
::from_u64(hash1
* 8).ok()?
).ok()?
;
215 let hash_id
= hash_ids
.read_u64().ok()?
;
217 let mut hash_rows
= self.hash_rows
.clone();
218 hash_rows
.skip(R
::Offset
::from_u64(hash1
* 4).ok()?
).ok()?
;
219 let hash_row
= hash_rows
.read_u32().ok()?
;
220 return Some(hash_row
);
225 hash1
= (hash1
+ hash2
) & mask
;
230 /// Return the section offsets and sizes for the given row index.
231 pub fn sections(&self, mut row
: u32) -> Result
<UnitIndexSectionIterator
<R
>> {
233 return Err(Error
::InvalidIndexRow
);
236 if row
>= self.unit_count
{
237 return Err(Error
::InvalidIndexRow
);
239 let mut offsets
= self.offsets
.clone();
240 offsets
.skip(R
::Offset
::from_u64(
241 u64::from(row
) * u64::from(self.section_count
) * 4,
243 let mut sizes
= self.sizes
.clone();
244 sizes
.skip(R
::Offset
::from_u64(
245 u64::from(row
) * u64::from(self.section_count
) * 4,
247 Ok(UnitIndexSectionIterator
{
248 sections
: self.sections
[..self.section_count
as usize].iter(),
254 /// Return the version.
255 pub fn version(&self) -> u16 {
259 /// Return the number of sections.
260 pub fn section_count(&self) -> u32 {
264 /// Return the number of units.
265 pub fn unit_count(&self) -> u32 {
269 /// Return the number of slots.
270 pub fn slot_count(&self) -> u32 {
275 /// An iterator over the section offsets and sizes for a row in a `UnitIndex`.
276 #[derive(Debug, Clone)]
277 pub struct UnitIndexSectionIterator
<'index
, R
: Reader
> {
278 sections
: slice
::Iter
<'index
, SectionId
>,
283 impl<'index
, R
: Reader
> Iterator
for UnitIndexSectionIterator
<'index
, R
> {
284 type Item
= UnitIndexSection
;
286 fn next(&mut self) -> Option
<UnitIndexSection
> {
287 let section
= *self.sections
.next()?
;
288 // The length of these arrays was validated in `UnitIndex::parse`.
289 let offset
= self.offsets
.read_u32().ok()?
;
290 let size
= self.sizes
.read_u32().ok()?
;
291 Some(UnitIndexSection
{
299 /// Information about a unit's contribution to a section in a `.dwp` file.
300 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
301 pub struct UnitIndexSection
{
302 /// The section kind.
303 pub section
: SectionId
,
304 /// The base offset of the unit's contribution to the section.
306 /// The size of the unit's contribution to the section.
313 use crate::endianity
::BigEndian
;
314 use test_assembler
::{Endian, Section}
;
318 let buf
= EndianSlice
::new(&[], BigEndian
);
319 let index
= UnitIndex
::parse(buf
).unwrap();
320 assert
!(index
.find(0).is_none());
324 fn test_version_2() {
326 let section
= Section
::with_endian(Endian
::Big
)
328 .D32(2).D32(0).D32(0).D32(1)
331 let buf
= section
.get_contents().unwrap();
332 let buf
= EndianSlice
::new(&buf
, BigEndian
);
333 let index
= UnitIndex
::parse(buf
).unwrap();
334 assert_eq
!(index
.version
, 2);
338 fn test_version_5() {
340 let section
= Section
::with_endian(Endian
::Big
)
342 .D16(5).D16(0).D32(0).D32(0).D32(1)
345 let buf
= section
.get_contents().unwrap();
346 let buf
= EndianSlice
::new(&buf
, BigEndian
);
347 let index
= UnitIndex
::parse(buf
).unwrap();
348 assert_eq
!(index
.version
, 5);
352 fn test_version_5_invalid() {
354 let section
= Section
::with_endian(Endian
::Big
)
356 .D32(5).D32(0).D32(0).D32(1)
359 let buf
= section
.get_contents().unwrap();
360 let buf
= EndianSlice
::new(&buf
, BigEndian
);
361 assert
!(UnitIndex
::parse(buf
).is_err());
365 fn test_version_2_sections() {
367 let section
= Section
::with_endian(Endian
::Big
)
369 .D32(2).D32(8).D32(1).D32(2)
371 .D64(0).D64(0).D32(0).D32(0)
373 .D32(constants
::DW_SECT_V2_INFO
.0)
374 .D32(constants
::DW_SECT_V2_TYPES
.0)
375 .D32(constants
::DW_SECT_V2_ABBREV
.0)
376 .D32(constants
::DW_SECT_V2_LINE
.0)
377 .D32(constants
::DW_SECT_V2_LOC
.0)
378 .D32(constants
::DW_SECT_V2_STR_OFFSETS
.0)
379 .D32(constants
::DW_SECT_V2_MACINFO
.0)
380 .D32(constants
::DW_SECT_V2_MACRO
.0)
382 .D32(11).D32(12).D32(13).D32(14).D32(15).D32(16).D32(17).D32(18)
384 .D32(21).D32(22).D32(23).D32(24).D32(25).D32(26).D32(27).D32(28);
385 let buf
= section
.get_contents().unwrap();
386 let buf
= EndianSlice
::new(&buf
, BigEndian
);
387 let index
= UnitIndex
::parse(buf
).unwrap();
388 assert_eq
!(index
.section_count
, 8);
392 SectionId
::DebugInfo
,
393 SectionId
::DebugTypes
,
394 SectionId
::DebugAbbrev
,
395 SectionId
::DebugLine
,
397 SectionId
::DebugStrOffsets
,
398 SectionId
::DebugMacinfo
,
399 SectionId
::DebugMacro
,
404 UnitIndexSection { section: SectionId::DebugInfo, offset: 11, size: 21 }
,
405 UnitIndexSection { section: SectionId::DebugTypes, offset: 12, size: 22 }
,
406 UnitIndexSection { section: SectionId::DebugAbbrev, offset: 13, size: 23 }
,
407 UnitIndexSection { section: SectionId::DebugLine, offset: 14, size: 24 }
,
408 UnitIndexSection { section: SectionId::DebugLoc, offset: 15, size: 25 }
,
409 UnitIndexSection { section: SectionId::DebugStrOffsets, offset: 16, size: 26 }
,
410 UnitIndexSection { section: SectionId::DebugMacinfo, offset: 17, size: 27 }
,
411 UnitIndexSection { section: SectionId::DebugMacro, offset: 18, size: 28 }
,
413 let mut sections
= index
.sections(1).unwrap();
414 for section
in &expect
{
415 assert_eq
!(*section
, sections
.next().unwrap());
417 assert
!(sections
.next().is_none());
421 fn test_version_5_sections() {
423 let section
= Section
::with_endian(Endian
::Big
)
425 .D16(5).D16(0).D32(7).D32(1).D32(2)
427 .D64(0).D64(0).D32(0).D32(0)
429 .D32(constants
::DW_SECT_INFO
.0)
430 .D32(constants
::DW_SECT_ABBREV
.0)
431 .D32(constants
::DW_SECT_LINE
.0)
432 .D32(constants
::DW_SECT_LOCLISTS
.0)
433 .D32(constants
::DW_SECT_STR_OFFSETS
.0)
434 .D32(constants
::DW_SECT_MACRO
.0)
435 .D32(constants
::DW_SECT_RNGLISTS
.0)
437 .D32(11).D32(12).D32(13).D32(14).D32(15).D32(16).D32(17)
439 .D32(21).D32(22).D32(23).D32(24).D32(25).D32(26).D32(27);
440 let buf
= section
.get_contents().unwrap();
441 let buf
= EndianSlice
::new(&buf
, BigEndian
);
442 let index
= UnitIndex
::parse(buf
).unwrap();
443 assert_eq
!(index
.section_count
, 7);
447 SectionId
::DebugInfo
,
448 SectionId
::DebugAbbrev
,
449 SectionId
::DebugLine
,
450 SectionId
::DebugLocLists
,
451 SectionId
::DebugStrOffsets
,
452 SectionId
::DebugMacro
,
453 SectionId
::DebugRngLists
,
458 UnitIndexSection { section: SectionId::DebugInfo, offset: 11, size: 21 }
,
459 UnitIndexSection { section: SectionId::DebugAbbrev, offset: 12, size: 22 }
,
460 UnitIndexSection { section: SectionId::DebugLine, offset: 13, size: 23 }
,
461 UnitIndexSection { section: SectionId::DebugLocLists, offset: 14, size: 24 }
,
462 UnitIndexSection { section: SectionId::DebugStrOffsets, offset: 15, size: 25 }
,
463 UnitIndexSection { section: SectionId::DebugMacro, offset: 16, size: 26 }
,
464 UnitIndexSection { section: SectionId::DebugRngLists, offset: 17, size: 27 }
,
466 let mut sections
= index
.sections(1).unwrap();
467 for section
in &expect
{
468 assert_eq
!(*section
, sections
.next().unwrap());
470 assert
!(sections
.next().is_none());
472 assert
!(index
.sections(0).is_err());
473 assert
!(index
.sections(2).is_err());
479 let section
= Section
::with_endian(Endian
::Big
)
481 .D16(5).D16(0).D32(2).D32(3).D32(4)
483 .D64(0xffff_fff2_ffff_fff1)
484 .D64(0xffff_fff0_ffff_fff1)
485 .D64(0xffff_fff1_ffff_fff1)
487 .D32(3).D32(1).D32(2).D32(0)
489 .D32(constants
::DW_SECT_INFO
.0)
490 .D32(constants
::DW_SECT_ABBREV
.0)
492 .D32(0).D32(0).D32(0).D32(0).D32(0).D32(0)
494 .D32(0).D32(0).D32(0).D32(0).D32(0).D32(0);
495 let buf
= section
.get_contents().unwrap();
496 let buf
= EndianSlice
::new(&buf
, BigEndian
);
497 let index
= UnitIndex
::parse(buf
).unwrap();
498 assert_eq
!(index
.version(), 5);
499 assert_eq
!(index
.slot_count(), 4);
500 assert_eq
!(index
.unit_count(), 3);
501 assert_eq
!(index
.section_count(), 2);
502 assert_eq
!(index
.find(0xffff_fff0_ffff_fff1), Some(1));
503 assert_eq
!(index
.find(0xffff_fff1_ffff_fff1), Some(2));
504 assert_eq
!(index
.find(0xffff_fff2_ffff_fff1), Some(3));
505 assert_eq
!(index
.find(0xffff_fff3_ffff_fff1), None
);
511 let section
= Section
::with_endian(Endian
::Big
)
513 .D16(5).D16(0).D32(0).D32(0).D32(1)
516 let buf
= section
.get_contents().unwrap();
517 let cu_index
= DebugCuIndex
::new(&buf
, BigEndian
);
518 let index
= cu_index
.index().unwrap();
519 assert_eq
!(index
.version
, 5);
525 let section
= Section
::with_endian(Endian
::Big
)
527 .D16(5).D16(0).D32(0).D32(0).D32(1)
530 let buf
= section
.get_contents().unwrap();
531 let tu_index
= DebugTuIndex
::new(&buf
, BigEndian
);
532 let index
= tu_index
.index().unwrap();
533 assert_eq
!(index
.version
, 5);