Skip to content

Commit

Permalink
read: Introduce new enum for section IDs in a .dwp index (#716)
Browse files Browse the repository at this point in the history
Keeping this type distinct from the `SectionId` enum ensures that the
compiler will report an error if someone adds incomplete support for new
split DWARF sections.

The existing `SectionId::dwo_name` method did not match the list of
sections actually supported elsewhere in gimli. I've added the one
section ID that was missing (`.debug_macinfo.dwo`), but I have not
removed the section IDs which are only present there: `.debug_str.dwo`,
`.debug_cu_index`, and `.debug_tu_index`.
  • Loading branch information
jameysharp committed May 25, 2024
1 parent e095972 commit 1b8a280
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 67 deletions.
2 changes: 1 addition & 1 deletion crates/examples/src/bin/dwarfdump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -968,7 +968,7 @@ where
writeln!(
w,
" {}: offset = 0x{:x}, size = 0x{:x}",
section.section.dwo_name().unwrap(),
section.section.dwo_name(),
section.offset,
section.size
)?;
Expand Down
1 change: 1 addition & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ impl SectionId {
// GNU split-dwarf extension to DWARF4.
SectionId::DebugLoc => ".debug_loc.dwo",
SectionId::DebugLocLists => ".debug_loclists.dwo",
SectionId::DebugMacinfo => ".debug_macinfo.dwo",
SectionId::DebugMacro => ".debug_macro.dwo",
SectionId::DebugRngLists => ".debug_rnglists.dwo",
SectionId::DebugStr => ".debug_str.dwo",
Expand Down
26 changes: 13 additions & 13 deletions src/read/dwarf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ use crate::read::{
DebugAddr, DebugAranges, DebugCuIndex, DebugInfo, DebugInfoUnitHeadersIter, DebugLine,
DebugLineStr, DebugLoc, DebugLocLists, DebugRanges, DebugRngLists, DebugStr, DebugStrOffsets,
DebugTuIndex, DebugTypes, DebugTypesUnitHeadersIter, DebuggingInformationEntry, EntriesCursor,
EntriesRaw, EntriesTree, Error, IncompleteLineProgram, LocListIter, LocationLists, Range,
RangeLists, RawLocListIter, RawRngListIter, Reader, ReaderOffset, ReaderOffsetId, Result,
RngListIter, Section, UnitHeader, UnitIndex, UnitIndexSectionIterator, UnitOffset, UnitType,
EntriesRaw, EntriesTree, Error, IncompleteLineProgram, IndexSectionId, LocListIter,
LocationLists, Range, RangeLists, RawLocListIter, RawRngListIter, Reader, ReaderOffset,
ReaderOffsetId, Result, RngListIter, Section, UnitHeader, UnitIndex, UnitIndexSectionIterator,
UnitOffset, UnitType,
};

/// All of the commonly used DWARF sections.
Expand Down Expand Up @@ -1013,42 +1014,41 @@ impl<R: Reader> DwarfPackage<R> {
let mut types_size = 0;
for section in sections {
match section.section {
SectionId::DebugAbbrev => {
IndexSectionId::DebugAbbrev => {
abbrev_offset = section.offset;
abbrev_size = section.size;
}
SectionId::DebugInfo => {
IndexSectionId::DebugInfo => {
info_offset = section.offset;
info_size = section.size;
}
SectionId::DebugLine => {
IndexSectionId::DebugLine => {
line_offset = section.offset;
line_size = section.size;
}
SectionId::DebugLoc => {
IndexSectionId::DebugLoc => {
loc_offset = section.offset;
loc_size = section.size;
}
SectionId::DebugLocLists => {
IndexSectionId::DebugLocLists => {
loclists_offset = section.offset;
loclists_size = section.size;
}
SectionId::DebugStrOffsets => {
IndexSectionId::DebugStrOffsets => {
str_offsets_offset = section.offset;
str_offsets_size = section.size;
}
SectionId::DebugRngLists => {
IndexSectionId::DebugRngLists => {
rnglists_offset = section.offset;
rnglists_size = section.size;
}
SectionId::DebugTypes => {
IndexSectionId::DebugTypes => {
types_offset = section.offset;
types_size = section.size;
}
SectionId::DebugMacro | SectionId::DebugMacinfo => {
IndexSectionId::DebugMacro | IndexSectionId::DebugMacinfo => {
// These are valid but we can't parse these yet.
}
_ => return Err(Error::UnknownSection(section.section)),
}
}

Expand Down
144 changes: 94 additions & 50 deletions src/read/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ pub struct UnitIndex<R: Reader> {
hash_ids: R,
hash_rows: R,
// Only `section_count` values are valid.
sections: [SectionId; SECTION_COUNT_MAX as usize],
sections: [IndexSectionId; SECTION_COUNT_MAX as usize],
offsets: R,
sizes: R,
}
Expand All @@ -144,7 +144,7 @@ impl<R: Reader> UnitIndex<R> {
slot_count: 0,
hash_ids: input.clone(),
hash_rows: input.clone(),
sections: [SectionId::DebugAbbrev; SECTION_COUNT_MAX as usize],
sections: [IndexSectionId::DebugAbbrev; SECTION_COUNT_MAX as usize],
offsets: input.clone(),
sizes: input.clone(),
});
Expand Down Expand Up @@ -173,33 +173,33 @@ impl<R: Reader> UnitIndex<R> {
let hash_ids = input.split(R::Offset::from_u64(u64::from(slot_count) * 8)?)?;
let hash_rows = input.split(R::Offset::from_u64(u64::from(slot_count) * 4)?)?;

let mut sections = [SectionId::DebugAbbrev; SECTION_COUNT_MAX as usize];
let mut sections = [IndexSectionId::DebugAbbrev; SECTION_COUNT_MAX as usize];
if section_count > SECTION_COUNT_MAX.into() {
return Err(Error::InvalidIndexSectionCount);
}
for i in 0..section_count {
let section = input.read_u32()?;
sections[i as usize] = if version == 2 {
match constants::DwSectV2(section) {
constants::DW_SECT_V2_INFO => SectionId::DebugInfo,
constants::DW_SECT_V2_TYPES => SectionId::DebugTypes,
constants::DW_SECT_V2_ABBREV => SectionId::DebugAbbrev,
constants::DW_SECT_V2_LINE => SectionId::DebugLine,
constants::DW_SECT_V2_LOC => SectionId::DebugLoc,
constants::DW_SECT_V2_STR_OFFSETS => SectionId::DebugStrOffsets,
constants::DW_SECT_V2_MACINFO => SectionId::DebugMacinfo,
constants::DW_SECT_V2_MACRO => SectionId::DebugMacro,
constants::DW_SECT_V2_INFO => IndexSectionId::DebugInfo,
constants::DW_SECT_V2_TYPES => IndexSectionId::DebugTypes,
constants::DW_SECT_V2_ABBREV => IndexSectionId::DebugAbbrev,
constants::DW_SECT_V2_LINE => IndexSectionId::DebugLine,
constants::DW_SECT_V2_LOC => IndexSectionId::DebugLoc,
constants::DW_SECT_V2_STR_OFFSETS => IndexSectionId::DebugStrOffsets,
constants::DW_SECT_V2_MACINFO => IndexSectionId::DebugMacinfo,
constants::DW_SECT_V2_MACRO => IndexSectionId::DebugMacro,
section => return Err(Error::UnknownIndexSectionV2(section)),
}
} else {
match constants::DwSect(section) {
constants::DW_SECT_INFO => SectionId::DebugInfo,
constants::DW_SECT_ABBREV => SectionId::DebugAbbrev,
constants::DW_SECT_LINE => SectionId::DebugLine,
constants::DW_SECT_LOCLISTS => SectionId::DebugLocLists,
constants::DW_SECT_STR_OFFSETS => SectionId::DebugStrOffsets,
constants::DW_SECT_MACRO => SectionId::DebugMacro,
constants::DW_SECT_RNGLISTS => SectionId::DebugRngLists,
constants::DW_SECT_INFO => IndexSectionId::DebugInfo,
constants::DW_SECT_ABBREV => IndexSectionId::DebugAbbrev,
constants::DW_SECT_LINE => IndexSectionId::DebugLine,
constants::DW_SECT_LOCLISTS => IndexSectionId::DebugLocLists,
constants::DW_SECT_STR_OFFSETS => IndexSectionId::DebugStrOffsets,
constants::DW_SECT_MACRO => IndexSectionId::DebugMacro,
constants::DW_SECT_RNGLISTS => IndexSectionId::DebugRngLists,
section => return Err(Error::UnknownIndexSection(section)),
}
};
Expand Down Expand Up @@ -305,7 +305,7 @@ impl<R: Reader> UnitIndex<R> {
/// An iterator over the section offsets and sizes for a row in a `UnitIndex`.
#[derive(Debug, Clone)]
pub struct UnitIndexSectionIterator<'index, R: Reader> {
sections: slice::Iter<'index, SectionId>,
sections: slice::Iter<'index, IndexSectionId>,
offsets: R,
sizes: R,
}
Expand All @@ -330,13 +330,57 @@ impl<'index, R: Reader> Iterator for UnitIndexSectionIterator<'index, R> {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct UnitIndexSection {
/// The section kind.
pub section: SectionId,
pub section: IndexSectionId,
/// The base offset of the unit's contribution to the section.
pub offset: u32,
/// The size of the unit's contribution to the section.
pub size: u32,
}

/// Section kinds which are permitted in a `.dwp` index.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IndexSectionId {
/// The `.debug_abbrev.dwo` section.
DebugAbbrev,
/// The `.debug_info.dwo` section.
DebugInfo,
/// The `.debug_line.dwo` section.
DebugLine,
/// The `.debug_loc.dwo` section.
DebugLoc,
/// The `.debug_loclists.dwo` section.
DebugLocLists,
/// The `.debug_macinfo.dwo` section.
DebugMacinfo,
/// The `.debug_macro.dwo` section.
DebugMacro,
/// The `.debug_rnglists.dwo` section.
DebugRngLists,
/// The `.debug_str_offsets.dwo` section.
DebugStrOffsets,
/// The `.debug_types.dwo` section.
DebugTypes,
}

impl IndexSectionId {
/// Returns the ELF section name for this kind, when found in a .dwo or .dwp file.
pub fn dwo_name(self) -> &'static str {
let section_id = match self {
IndexSectionId::DebugAbbrev => SectionId::DebugAbbrev,
IndexSectionId::DebugInfo => SectionId::DebugInfo,
IndexSectionId::DebugLine => SectionId::DebugLine,
IndexSectionId::DebugLoc => SectionId::DebugLoc,
IndexSectionId::DebugLocLists => SectionId::DebugLocLists,
IndexSectionId::DebugMacro => SectionId::DebugMacro,
IndexSectionId::DebugMacinfo => SectionId::DebugMacinfo,
IndexSectionId::DebugRngLists => SectionId::DebugRngLists,
IndexSectionId::DebugStrOffsets => SectionId::DebugStrOffsets,
IndexSectionId::DebugTypes => SectionId::DebugTypes,
};
section_id.dwo_name().unwrap()
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -437,26 +481,26 @@ mod tests {
assert_eq!(
index.sections,
[
SectionId::DebugInfo,
SectionId::DebugTypes,
SectionId::DebugAbbrev,
SectionId::DebugLine,
SectionId::DebugLoc,
SectionId::DebugStrOffsets,
SectionId::DebugMacinfo,
SectionId::DebugMacro,
IndexSectionId::DebugInfo,
IndexSectionId::DebugTypes,
IndexSectionId::DebugAbbrev,
IndexSectionId::DebugLine,
IndexSectionId::DebugLoc,
IndexSectionId::DebugStrOffsets,
IndexSectionId::DebugMacinfo,
IndexSectionId::DebugMacro,
]
);
#[rustfmt::skip]
let expect = [
UnitIndexSection { section: SectionId::DebugInfo, offset: 11, size: 21 },
UnitIndexSection { section: SectionId::DebugTypes, offset: 12, size: 22 },
UnitIndexSection { section: SectionId::DebugAbbrev, offset: 13, size: 23 },
UnitIndexSection { section: SectionId::DebugLine, offset: 14, size: 24 },
UnitIndexSection { section: SectionId::DebugLoc, offset: 15, size: 25 },
UnitIndexSection { section: SectionId::DebugStrOffsets, offset: 16, size: 26 },
UnitIndexSection { section: SectionId::DebugMacinfo, offset: 17, size: 27 },
UnitIndexSection { section: SectionId::DebugMacro, offset: 18, size: 28 },
UnitIndexSection { section: IndexSectionId::DebugInfo, offset: 11, size: 21 },
UnitIndexSection { section: IndexSectionId::DebugTypes, offset: 12, size: 22 },
UnitIndexSection { section: IndexSectionId::DebugAbbrev, offset: 13, size: 23 },
UnitIndexSection { section: IndexSectionId::DebugLine, offset: 14, size: 24 },
UnitIndexSection { section: IndexSectionId::DebugLoc, offset: 15, size: 25 },
UnitIndexSection { section: IndexSectionId::DebugStrOffsets, offset: 16, size: 26 },
UnitIndexSection { section: IndexSectionId::DebugMacinfo, offset: 17, size: 27 },
UnitIndexSection { section: IndexSectionId::DebugMacro, offset: 18, size: 28 },
];
let mut sections = index.sections(1).unwrap();
for section in &expect {
Expand Down Expand Up @@ -492,24 +536,24 @@ mod tests {
assert_eq!(
index.sections[..7],
[
SectionId::DebugInfo,
SectionId::DebugAbbrev,
SectionId::DebugLine,
SectionId::DebugLocLists,
SectionId::DebugStrOffsets,
SectionId::DebugMacro,
SectionId::DebugRngLists,
IndexSectionId::DebugInfo,
IndexSectionId::DebugAbbrev,
IndexSectionId::DebugLine,
IndexSectionId::DebugLocLists,
IndexSectionId::DebugStrOffsets,
IndexSectionId::DebugMacro,
IndexSectionId::DebugRngLists,
]
);
#[rustfmt::skip]
let expect = [
UnitIndexSection { section: SectionId::DebugInfo, offset: 11, size: 21 },
UnitIndexSection { section: SectionId::DebugAbbrev, offset: 12, size: 22 },
UnitIndexSection { section: SectionId::DebugLine, offset: 13, size: 23 },
UnitIndexSection { section: SectionId::DebugLocLists, offset: 14, size: 24 },
UnitIndexSection { section: SectionId::DebugStrOffsets, offset: 15, size: 25 },
UnitIndexSection { section: SectionId::DebugMacro, offset: 16, size: 26 },
UnitIndexSection { section: SectionId::DebugRngLists, offset: 17, size: 27 },
UnitIndexSection { section: IndexSectionId::DebugInfo, offset: 11, size: 21 },
UnitIndexSection { section: IndexSectionId::DebugAbbrev, offset: 12, size: 22 },
UnitIndexSection { section: IndexSectionId::DebugLine, offset: 13, size: 23 },
UnitIndexSection { section: IndexSectionId::DebugLocLists, offset: 14, size: 24 },
UnitIndexSection { section: IndexSectionId::DebugStrOffsets, offset: 15, size: 25 },
UnitIndexSection { section: IndexSectionId::DebugMacro, offset: 16, size: 26 },
UnitIndexSection { section: IndexSectionId::DebugRngLists, offset: 17, size: 27 },
];
let mut sections = index.sections(1).unwrap();
for section in &expect {
Expand Down
3 changes: 0 additions & 3 deletions src/read/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,8 +438,6 @@ pub enum Error {
InvalidIndexSlotCount,
/// Invalid hash row in `.dwp` index.
InvalidIndexRow,
/// Unknown section type.
UnknownSection(SectionId),
/// Unknown section type in `.dwp` index.
UnknownIndexSection(constants::DwSect),
/// Unknown section type in version 2 `.dwp` index.
Expand Down Expand Up @@ -591,7 +589,6 @@ impl Error {
Error::InvalidIndexSectionCount => "Invalid section count in `.dwp` index.",
Error::InvalidIndexSlotCount => "Invalid slot count in `.dwp` index.",
Error::InvalidIndexRow => "Invalid hash row in `.dwp` index.",
Error::UnknownSection(_) => "Unknown section type.",
Error::UnknownIndexSection(_) => "Unknown section type in `.dwp` index.",
Error::UnknownIndexSectionV2(_) => "Unknown section type in version 2 `.dwp` index.",
}
Expand Down

0 comments on commit 1b8a280

Please sign in to comment.