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

Implement indexed values for DWARF 5 #358

Merged
merged 12 commits into from
Jan 15, 2019
81 changes: 77 additions & 4 deletions examples/dwarfdump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,9 +530,11 @@ where

// The type of each section variable is inferred from its use below.
let debug_abbrev = load_section(&arena, file, endian);
let debug_addr = load_section(&arena, file, endian);
let debug_info = load_section(&arena, file, endian);
let debug_line = load_section(&arena, file, endian);
let debug_str = load_section(&arena, file, endian);
let debug_str_offsets = load_section(&arena, file, endian);
let debug_types = load_section(&arena, file, endian);

let debug_loc = load_section(&arena, file, endian);
Expand All @@ -546,9 +548,11 @@ where
let dwarf = gimli::Dwarf {
endian,
debug_abbrev,
debug_addr,
debug_info,
debug_line,
debug_str,
debug_str_offsets,
debug_str_sup: no_reader.clone().into(),
debug_types,
locations,
Expand Down Expand Up @@ -982,6 +986,10 @@ struct Unit<R: Reader> {
line_program: Option<gimli::IncompleteLineNumberProgram<R>>,
comp_dir: Option<R>,
comp_name: Option<R>,
str_offsets_base: gimli::DebugStrOffsetsBase,
addr_base: gimli::DebugAddrBase,
loclists_base: gimli::DebugLocListsBase,
rnglists_base: gimli::DebugRngListsBase,
}

fn spaces(buf: &mut String, len: usize) -> &str {
Expand Down Expand Up @@ -1010,6 +1018,11 @@ fn dump_entries<R: Reader, W: Write>(
line_program: None,
comp_dir: None,
comp_name: None,
// Defaults to 0 for GNU extensions
str_offsets_base: gimli::DebugStrOffsetsBase(0),
addr_base: gimli::DebugAddrBase(0),
loclists_base: gimli::DebugLocListsBase(0),
rnglists_base: gimli::DebugRngListsBase(0),
};

let mut spaces_buf = String::new();
Expand Down Expand Up @@ -1063,6 +1076,26 @@ fn dump_entries<R: Reader, W: Write>(
)
.ok(),
_ => None,
};
if let Some(gimli::AttributeValue::DebugStrOffsetsBase(base)) =
entry.attr_value(gimli::DW_AT_str_offsets_base)?
{
unit.str_offsets_base = base;
}
if let Some(gimli::AttributeValue::DebugAddrBase(base)) =
entry.attr_value(gimli::DW_AT_addr_base)?
{
unit.addr_base = base;
}
if let Some(gimli::AttributeValue::DebugLocListsBase(base)) =
entry.attr_value(gimli::DW_AT_loclists_base)?
{
unit.loclists_base = base;
}
if let Some(gimli::AttributeValue::DebugRngListsBase(base)) =
entry.attr_value(gimli::DW_AT_rnglists_base)?
{
unit.rnglists_base = base;
}
}

Expand Down Expand Up @@ -1184,28 +1217,53 @@ fn dump_attr_value<R: Reader, W: Write>(
gimli::AttributeValue::SecOffset(offset) => {
writeln!(w, "0x{:08x}", offset)?;
}
gimli::AttributeValue::DebugAddrBase(base) => {
writeln!(w, "<.debug_addr+0x{:08x}>", base.0)?;
}
gimli::AttributeValue::DebugAddrIndex(index) => {
let address = dwarf
.debug_addr
.get_address(unit.address_size, unit.addr_base, index)?;
writeln!(w, "0x{:08x}", address)?;
}
gimli::AttributeValue::UnitRef(gimli::UnitOffset(offset)) => {
writeln!(w, "<0x{:08x}>", offset)?;
}
gimli::AttributeValue::DebugInfoRef(gimli::DebugInfoOffset(offset)) => {
writeln!(w, "<GOFF=0x{:08x}>", offset)?;
writeln!(w, "<.debug_info+0x{:08x}>", offset)?;
}
gimli::AttributeValue::DebugInfoRefSup(gimli::DebugInfoOffset(offset)) => {
writeln!(w, "<SUP_GOFF=0x{:08x}>", offset)?;
writeln!(w, "<.debug_info(sup)+0x{:08x}>", offset)?;
}
gimli::AttributeValue::DebugLineRef(gimli::DebugLineOffset(offset)) => {
writeln!(w, "0x{:08x}", offset)?;
}
gimli::AttributeValue::LocationListsRef(offset) => {
dump_loc_list(w, &dwarf.locations, offset, unit)?;
}
gimli::AttributeValue::DebugLocListsBase(base) => {
writeln!(w, "<.debug_loclists+0x{:08x}>", base.0)?;
}
gimli::AttributeValue::DebugLocListsIndex(index) => {
let offset = dwarf.locations.get_offset(unit.loclists_base, index)?;
writeln!(w, "0x{:08x}", offset.0)?;
dump_loc_list(w, &dwarf.locations, offset, unit)?;
}
gimli::AttributeValue::DebugMacinfoRef(gimli::DebugMacinfoOffset(offset)) => {
writeln!(w, "{}", offset)?;
}
gimli::AttributeValue::RangeListsRef(offset) => {
writeln!(w, "0x{:08x}", offset.0)?;
dump_range_list(w, &dwarf.ranges, offset, unit)?;
}
gimli::AttributeValue::DebugRngListsBase(base) => {
writeln!(w, "<.debug_rnglists+0x{:08x}>", base.0)?;
}
gimli::AttributeValue::DebugRngListsIndex(index) => {
let offset = dwarf.ranges.get_offset(unit.rnglists_base, index)?;
writeln!(w, "0x{:08x}", offset.0)?;
dump_range_list(w, &dwarf.ranges, offset, unit)?;
}
gimli::AttributeValue::DebugTypesRef(signature) => {
dump_type_signature(w, signature, dwarf.endian)?;
writeln!(w, " <type signature>")?;
Expand All @@ -1214,11 +1272,26 @@ fn dump_attr_value<R: Reader, W: Write>(
if let Ok(s) = dwarf.debug_str.get_str(offset) {
writeln!(w, "{}", s.to_string_lossy()?)?;
} else {
writeln!(w, "<GOFF=0x{:08x}>", offset.0)?;
writeln!(w, "<.debug_str+0x{:08x}>", offset.0)?;
}
}
gimli::AttributeValue::DebugStrRefSup(offset) => {
writeln!(w, "<SUP_GOFF=0x{:08x}>", offset.0)?;
writeln!(w, "<.debug_str(sup)+0x{:08x}>", offset.0)?;
}
gimli::AttributeValue::DebugStrOffsetsBase(base) => {
writeln!(w, "<.debug_str_offsets+0x{:08x}>", base.0)?;
}
gimli::AttributeValue::DebugStrOffsetsIndex(index) => {
let offset = dwarf.debug_str_offsets.get_str_offset(
unit.format,
unit.str_offsets_base,
index,
)?;
if let Ok(s) = dwarf.debug_str.get_str(offset) {
writeln!(w, "{}", s.to_string_lossy()?)?;
} else {
writeln!(w, "<.debug_str+0x{:08x}>", offset.0)?;
}
}
gimli::AttributeValue::String(s) => {
writeln!(w, "{}", s.to_string_lossy()?)?;
Expand Down
32 changes: 32 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ pub struct Register(pub u16);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugAbbrevOffset<T = usize>(pub T);

/// An offset to a set of entries in the `.debug_addr` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugAddrBase<T = usize>(pub T);

/// An index into a set of addresses in the `.debug_addr` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugAddrIndex<T = usize>(pub T);

/// An offset into the `.debug_info` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct DebugInfoOffset<T = usize>(pub T);
Expand All @@ -51,6 +59,14 @@ pub struct DebugLineOffset<T = usize>(pub T);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LocationListsOffset<T = usize>(pub T);

/// An offset to a set of location list offsets in the `.debug_loclists` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugLocListsBase<T = usize>(pub T);

/// An index into a set of location list offsets in the `.debug_loclists` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugLocListsIndex<T = usize>(pub T);

/// An offset into the `.debug_macinfo` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugMacinfoOffset<T = usize>(pub T);
Expand All @@ -60,10 +76,26 @@ pub struct DebugMacinfoOffset<T = usize>(pub T);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct RangeListsOffset<T = usize>(pub T);

/// An offset to a set of range list offsets in the `.debug_rnglists` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugRngListsBase<T = usize>(pub T);

/// An index into a set of range list offsets in the `.debug_rnglists` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugRngListsIndex<T = usize>(pub T);

/// An offset into the `.debug_str` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugStrOffset<T = usize>(pub T);

/// An offset to a set of entries in the `.debug_str_offsets` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugStrOffsetsBase<T = usize>(pub T);

/// An index into a set of entries in the `.debug_str_offsets` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugStrOffsetsIndex<T = usize>(pub T);

/// An offset into the `.debug_types` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugTypesOffset<T = usize>(pub T);
Expand Down
53 changes: 53 additions & 0 deletions src/read/addr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use common::{DebugAddrBase, DebugAddrIndex};
use read::{Reader, ReaderOffset, Result, Section};

/// The raw contents of the `.debug_addr` section.
#[derive(Debug, Default, Clone, Copy)]
pub struct DebugAddr<R: Reader> {
section: R,
}

impl<R: Reader> DebugAddr<R> {
// TODO: add an iterator over the sets of addresses in the section.
// This is not needed for common usage of the section though.

/// Returns the address at the given `base` and `index`.
///
/// A set of addresses in the `.debug_addr` section consists of a header
/// followed by a series of addresses.
///
/// The `base` must be the `DW_AT_addr_base` value from the compilation unit DIE.
/// This is an offset that points to the first address following the header.
///
/// The `index` is the value of a `DW_FORM_addrx` attribute.
///
/// The `address_size` must be the size of the address for the compilation unit.
/// This value must also match the header. However, note that we do not parse the
/// header to validate this, since locating the header is unreliable, and the GNU
/// extensions do not emit it.
pub fn get_address(
&self,
address_size: u8,
base: DebugAddrBase<R::Offset>,
index: DebugAddrIndex<R::Offset>,
) -> Result<u64> {
let input = &mut self.section.clone();
input.skip(base.0)?;
input.skip(R::Offset::from_u64(
index.0.into_u64() * u64::from(address_size),
)?)?;
input.read_address(address_size)
}
}

impl<R: Reader> Section<R> for DebugAddr<R> {
fn section_name() -> &'static str {
".debug_addr"
}
}

impl<R: Reader> From<R> for DebugAddr<R> {
fn from(section: R) -> Self {
DebugAddr { section }
}
}
Loading