Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dwarfdump: handle empty unit in dump_line #330

Merged
merged 1 commit into from
Sep 22, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
318 changes: 170 additions & 148 deletions examples/dwarfdump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::GimliError(ref err) => err.description(),
Error::IoError => "An I/O error occurred while reading.",
Error::IoError => "An I/O error occurred while writing.",
Error::MissingDIE => "Expected a DIE but none was found",
}
}
Expand Down Expand Up @@ -1477,167 +1477,189 @@ fn dump_line<R: Reader, W: Write>(
debug_abbrev: &gimli::DebugAbbrev<R>,
debug_str: &gimli::DebugStr<R>,
) -> Result<()> {
writeln!(w, "\n.debug_line")?;

let mut iter = debug_info.units();
while let Some(unit) = iter.next()? {
let abbrevs = unit.abbreviations(debug_abbrev)?;
while let Some(ref unit) = iter.next()? {
writeln!(
w,
"\n.debug_line: line number info for unit at .debug_info offset 0x{:08x}",
unit.offset().0
)?;
match dump_line_program(w, unit, debug_line, debug_abbrev, debug_str) {
Ok(_) => (),
Err(Error::IoError) => return Err(Error::IoError),
Err(err) => writeln!(
w,
"Failed to dump line program: {}",
error::Error::description(&err)
)?,
}
}
Ok(())
}

fn dump_line_program<R: Reader, W: Write>(
w: &mut W,
unit: &CompilationUnitHeader<R, R::Offset>,
debug_line: &gimli::DebugLine<R>,
debug_abbrev: &gimli::DebugAbbrev<R>,
debug_str: &gimli::DebugStr<R>,
) -> Result<()> {
let abbrevs = unit.abbreviations(debug_abbrev)?;

let mut cursor = unit.entries(&abbrevs);
cursor.next_dfs()?;
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,
_ => continue,
};
let comp_dir = root.attr(gimli::DW_AT_comp_dir)?
.and_then(|attr| attr.string_value(debug_str));
let comp_name = root.attr(gimli::DW_AT_name)?
.and_then(|attr| attr.string_value(debug_str));
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| attr.string_value(debug_str));
let comp_name = root.attr(gimli::DW_AT_name)?
.and_then(|attr| attr.string_value(debug_str));

let program = debug_line.program(offset, unit.address_size(), comp_dir, comp_name);
if let Ok(program) = program {
{
let header = program.header();
writeln!(w)?;
writeln!(w, "Offset: 0x{:x}", offset.0)?;
writeln!(
w,
"Length: {}",
header.unit_length()
)?;
writeln!(
w,
"DWARF version: {}",
header.version()
)?;
writeln!(
w,
"Prologue length: {}",
header.header_length()
)?;
writeln!(
w,
"Minimum instruction length: {}",
header.minimum_instruction_length()
)?;
writeln!(
w,
"Maximum operations per instruction: {}",
header.maximum_operations_per_instruction()
)?;
writeln!(
w,
"Default is_stmt: {}",
header.default_is_stmt()
)?;
writeln!(
w,
"Line base: {}",
header.line_base()
)?;
writeln!(
w,
"Line range: {}",
header.line_range()
)?;
writeln!(
w,
"Opcode base: {}",
header.opcode_base()
)?;

let program = debug_line.program(offset, unit.address_size(), comp_dir, comp_name);
if let Ok(program) = program {
writeln!(w)?;
writeln!(w, "Opcodes:")?;
for (i, length) in header
.standard_opcode_lengths()
.to_slice()?
.iter()
.enumerate()
{
let header = program.header();
writeln!(w)?;
writeln!(w, "Offset: 0x{:x}", offset.0)?;
writeln!(
w,
"Length: {}",
header.unit_length()
)?;
writeln!(
w,
"DWARF version: {}",
header.version()
)?;
writeln!(
w,
"Prologue length: {}",
header.header_length()
)?;
writeln!(
w,
"Minimum instruction length: {}",
header.minimum_instruction_length()
)?;
writeln!(
w,
"Maximum operations per instruction: {}",
header.maximum_operations_per_instruction()
)?;
writeln!(
w,
"Default is_stmt: {}",
header.default_is_stmt()
)?;
writeln!(
w,
"Line base: {}",
header.line_base()
)?;
writeln!(
w,
"Line range: {}",
header.line_range()
)?;
writeln!(w, " Opcode {} as {} args", i + 1, length)?;
}

writeln!(w)?;
writeln!(w, "The Directory Table:")?;
for (i, dir) in header.include_directories().iter().enumerate() {
writeln!(w, " {} {}", i + 1, dir.to_string_lossy()?)?;
}

writeln!(w)?;
writeln!(w, "The File Name Table")?;
writeln!(w, " Entry\tDir\tTime\tSize\tName")?;
for (i, file) in header.file_names().iter().enumerate() {
writeln!(
w,
"Opcode base: {}",
header.opcode_base()
" {}\t{}\t{}\t{}\t{}",
i + 1,
file.directory_index(),
file.last_modification(),
file.length(),
file.path_name().to_string_lossy()?
)?;
}

writeln!(w)?;
writeln!(w, "Opcodes:")?;
for (i, length) in header
.standard_opcode_lengths()
.to_slice()?
.iter()
.enumerate()
{
writeln!(w, " Opcode {} as {} args", i + 1, length)?;
}

writeln!(w)?;
writeln!(w, "The Directory Table:")?;
for (i, dir) in header.include_directories().iter().enumerate() {
writeln!(w, " {} {}", i + 1, dir.to_string_lossy()?)?;
}

writeln!(w)?;
writeln!(w, "The File Name Table")?;
writeln!(w, " Entry\tDir\tTime\tSize\tName")?;
for (i, file) in header.file_names().iter().enumerate() {
writeln!(
w,
" {}\t{}\t{}\t{}\t{}",
i + 1,
file.directory_index(),
file.last_modification(),
file.length(),
file.path_name().to_string_lossy()?
)?;
}

writeln!(w)?;
writeln!(w, "Line Number Statements:")?;
let mut opcodes = header.opcodes();
while let Some(opcode) = opcodes.next_opcode(header)? {
writeln!(w, " {}", opcode)?;
}
writeln!(w)?;
writeln!(w, "Line Number Statements:")?;
let mut opcodes = header.opcodes();
while let Some(opcode) = opcodes.next_opcode(header)? {
writeln!(w, " {}", opcode)?;
}

writeln!(w)?;
writeln!(w, "Line Number Rows:")?;
writeln!(w, "<pc> [lno,col]")?;
writeln!(w)?;
writeln!(w, "Line Number Rows:")?;
writeln!(w, "<pc> [lno,col]")?;
}
let mut rows = program.rows();
let mut file_index = 0;
while let Some((header, row)) = rows.next_row()? {
let line = row.line().unwrap_or(0);
let column = match row.column() {
gimli::ColumnType::Column(column) => column,
gimli::ColumnType::LeftEdge => 0,
};
write!(w, "0x{:08x} [{:4},{:2}]", row.address(), line, column)?;
if row.is_stmt() {
write!(w, " NS")?;
}
let mut rows = program.rows();
let mut file_index = 0;
while let Some((header, row)) = rows.next_row()? {
let line = row.line().unwrap_or(0);
let column = match row.column() {
gimli::ColumnType::Column(column) => column,
gimli::ColumnType::LeftEdge => 0,
};
write!(w, "0x{:08x} [{:4},{:2}]", row.address(), line, column)?;
if row.is_stmt() {
write!(w, " NS")?;
}
if row.basic_block() {
write!(w, " BB")?;
}
if row.end_sequence() {
write!(w, " ET")?;
}
if row.prologue_end() {
write!(w, " PE")?;
}
if row.epilogue_begin() {
write!(w, " EB")?;
}
if row.isa() != 0 {
write!(w, " IS={}", row.isa())?;
}
if row.discriminator() != 0 {
write!(w, " DI={}", row.discriminator())?;
}
if file_index != row.file_index() {
file_index = row.file_index();
if let Some(file) = row.file(header) {
if let Some(directory) = file.directory(header) {
write!(
w,
" uri: \"{}/{}\"",
directory.to_string_lossy()?,
file.path_name().to_string_lossy()?
)?;
} else {
write!(w, " uri: \"{}\"", file.path_name().to_string_lossy()?)?;
}
if row.basic_block() {
write!(w, " BB")?;
}
if row.end_sequence() {
write!(w, " ET")?;
}
if row.prologue_end() {
write!(w, " PE")?;
}
if row.epilogue_begin() {
write!(w, " EB")?;
}
if row.isa() != 0 {
write!(w, " IS={}", row.isa())?;
}
if row.discriminator() != 0 {
write!(w, " DI={}", row.discriminator())?;
}
if file_index != row.file_index() {
file_index = row.file_index();
if let Some(file) = row.file(header) {
if let Some(directory) = file.directory(header) {
write!(
w,
" uri: \"{}/{}\"",
directory.to_string_lossy()?,
file.path_name().to_string_lossy()?
)?;
} else {
write!(w, " uri: \"{}\"", file.path_name().to_string_lossy()?)?;
}
}
writeln!(w)?;
}
writeln!(w)?;
}
}
Ok(())
Expand Down