Skip to content

Commit

Permalink
Add read::Dwarf::line_program()
Browse files Browse the repository at this point in the history
  • Loading branch information
philipc committed Jan 9, 2019
1 parent 2b83730 commit 8ea8483
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 28 deletions.
27 changes: 6 additions & 21 deletions examples/dwarfdump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1690,30 +1690,15 @@ fn dump_line_program<R: Reader, W: Write>(
dwarf: &gimli::Dwarf<R, R::Endian>,
) -> Result<()> {
let abbrevs = dwarf.abbreviations(unit)?;

let mut cursor = unit.entries(&abbrevs);
cursor.next_dfs()?;

let root = cursor.current().ok_or(Error::MissingDIE)?;
let offset = match root.attr_value(gimli::DW_AT_stmt_list)? {
Some(gimli::AttributeValue::DebugLineRef(offset)) => offset,
_ => return Ok(()),
};
let comp_dir = root
.attr(gimli::DW_AT_comp_dir)?
.and_then(|attr| dwarf.attr_string(&attr));
let comp_name = root
.attr(gimli::DW_AT_name)?
.and_then(|attr| dwarf.attr_string(&attr));

let program = dwarf
.debug_line
.program(offset, unit.address_size(), comp_dir, comp_name);
if let Ok(program) = program {
if let Ok(Some(program)) = dwarf.line_program(unit, &abbrevs) {
{
let header = program.header();
writeln!(w)?;
writeln!(w, "Offset: 0x{:x}", offset.0)?;
writeln!(
w,
"Offset: 0x{:x}",
header.offset().0
)?;
writeln!(
w,
"Length: {}",
Expand Down
30 changes: 28 additions & 2 deletions src/read/dwarf.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use constants;
use read::{
Abbreviations, Attribute, AttributeValue, CompilationUnitHeader, CompilationUnitHeadersIter,
DebugAbbrev, DebugInfo, DebugLine, DebugStr, DebugTypes, LocationLists, RangeLists, Reader,
Result, TypeUnitHeader, TypeUnitHeadersIter,
DebugAbbrev, DebugInfo, DebugLine, DebugStr, DebugTypes, Error, IncompleteLineNumberProgram,
LocationLists, RangeLists, Reader, Result, TypeUnitHeader, TypeUnitHeadersIter,
};
use Endianity;

Expand Down Expand Up @@ -82,6 +83,31 @@ where
unit.abbreviations(&self.debug_abbrev)
}

/// Return the line number program for a unit.
pub fn line_program(
&self,
unit: &CompilationUnitHeader<R, R::Offset>,
abbrevs: &Abbreviations,
) -> Result<Option<IncompleteLineNumberProgram<R, R::Offset>>> {
let mut cursor = unit.entries(abbrevs);
cursor.next_dfs()?;
let root = cursor.current().ok_or(Error::MissingUnitDie)?;
let offset = match root.attr_value(constants::DW_AT_stmt_list)? {
Some(AttributeValue::DebugLineRef(offset)) => offset,
Some(_) => return Err(Error::UnsupportedAttributeForm),
None => return Ok(None),
};
let comp_dir = root
.attr(constants::DW_AT_comp_dir)?
.and_then(|attr| self.attr_string(&attr));
let comp_name = root
.attr(constants::DW_AT_name)?
.and_then(|attr| self.attr_string(&attr));
self.debug_line
.program(offset, unit.address_size(), comp_dir, comp_name)
.map(Option::Some)
}

/// Try to return an attribute's value as a string slice.
///
/// If the attribute's value is either an inline `DW_FORM_string` string,
Expand Down
27 changes: 22 additions & 5 deletions src/read/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ impl<R: Reader> DebugLine<R> {
) -> Result<IncompleteLineNumberProgram<R, R::Offset>> {
let input = &mut self.debug_line_section.clone();
input.skip(offset.0)?;
let header = LineNumberProgramHeader::parse(input, address_size, comp_dir, comp_name)?;
let header =
LineNumberProgramHeader::parse(input, offset, address_size, comp_dir, comp_name)?;
let program = IncompleteLineNumberProgram { header };
Ok(program)
}
Expand Down Expand Up @@ -1008,6 +1009,7 @@ where
R: Reader<Offset = Offset>,
Offset: ReaderOffset,
{
offset: DebugLineOffset<Offset>,
unit_length: Offset,

/// "A version number. This number is specific to the line number
Expand Down Expand Up @@ -1085,6 +1087,11 @@ where
R: Reader<Offset = Offset>,
Offset: ReaderOffset,
{
/// Return the offset of the line number program header in the `.debug_line` section.
pub fn offset(&self) -> DebugLineOffset<R::Offset> {
self.offset
}

/// Return the length of the line number program and header, not including
/// the length of the encoded length itself.
pub fn unit_length(&self) -> R::Offset {
Expand Down Expand Up @@ -1221,6 +1228,7 @@ where

fn parse(
input: &mut R,
offset: DebugLineOffset<Offset>,
address_size: u8,
comp_dir: Option<R>,
comp_name: Option<R>,
Expand Down Expand Up @@ -1292,6 +1300,7 @@ where
});

let header = LineNumberProgramHeader {
offset,
unit_length,
version,
header_length,
Expand Down Expand Up @@ -1589,14 +1598,21 @@ mod tests {
let comp_dir = EndianSlice::new(b"/comp_dir", LittleEndian);
let comp_name = EndianSlice::new(b"/comp_name", LittleEndian);

let header = LineNumberProgramHeader::parse(rest, 4, Some(comp_dir), Some(comp_name))
.expect("should parse header ok");
let header = LineNumberProgramHeader::parse(
rest,
DebugLineOffset(0),
4,
Some(comp_dir),
Some(comp_name),
)
.expect("should parse header ok");

assert_eq!(
*rest,
EndianSlice::new(&buf[buf.len() - 16..], LittleEndian)
);

assert_eq!(header.offset, DebugLineOffset(0));
assert_eq!(header.version, 4);
assert_eq!(header.minimum_instruction_length(), 1);
assert_eq!(header.maximum_operations_per_instruction(), 1);
Expand Down Expand Up @@ -1688,7 +1704,7 @@ mod tests {

let input = &mut EndianSlice::new(&buf, LittleEndian);

match LineNumberProgramHeader::parse(input, 4, None, None) {
match LineNumberProgramHeader::parse(input, DebugLineOffset(0), 4, None, None) {
Err(Error::UnexpectedEof) => return,
otherwise => panic!("Unexpected result: {:?}", otherwise),
}
Expand Down Expand Up @@ -1749,7 +1765,7 @@ mod tests {

let input = &mut EndianSlice::new(&buf, LittleEndian);

match LineNumberProgramHeader::parse(input, 4, None, None) {
match LineNumberProgramHeader::parse(input, DebugLineOffset(0), 4, None, None) {
Err(Error::UnexpectedEof) => return,
otherwise => panic!("Unexpected result: {:?}", otherwise),
}
Expand All @@ -1762,6 +1778,7 @@ mod tests {
buf: EndianSlice<LittleEndian>,
) -> LineNumberProgramHeader<EndianSlice<LittleEndian>> {
LineNumberProgramHeader {
offset: DebugLineOffset(0),
opcode_base: OPCODE_BASE,
address_size: 8,
minimum_instruction_length: 1,
Expand Down
8 changes: 8 additions & 0 deletions src/read/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ pub enum Error {
UnsupportedAddressIndex,
/// Nonzero segment selector sizes aren't supported yet.
UnsupportedSegmentSize,
/// A compilation unit or type unit is missing its top level DIE.
MissingUnitDie,
/// A DIE attribute used an unsupported form.
UnsupportedAttributeForm,
}

impl fmt::Display for Error {
Expand Down Expand Up @@ -338,6 +342,10 @@ impl Error {
Error::UnsupportedUnitType => "The `DW_UT_*` value for this unit is not supported yet",
Error::UnsupportedAddressIndex => "Ranges involving AddressIndex are not supported yet",
Error::UnsupportedSegmentSize => "Nonzero segment size not supported yet",
Error::MissingUnitDie => {
"A compilation unit or type unit is missing its top level DIE."
}
Error::UnsupportedAttributeForm => "A DIE attribute used an unsupported form.",
}
}
}
Expand Down

0 comments on commit 8ea8483

Please sign in to comment.