Skip to content

Commit

Permalink
Include the full UnitHeader in Unit.
Browse files Browse the repository at this point in the history
  • Loading branch information
khuey committed Jul 2, 2020
1 parent d118b24 commit b987e40
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 86 deletions.
156 changes: 106 additions & 50 deletions src/read/dwarf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ use crate::common::{
};
use crate::constants;
use crate::read::{
Abbreviations, AttributeValue, CommonUnitHeader, CompilationUnitHeader,
CompilationUnitHeadersIter, DebugAbbrev, DebugAddr, DebugInfo, DebugLine, DebugLineStr,
DebugStr, DebugStrOffsets, DebugTypes, DebuggingInformationEntry, EntriesCursor, EntriesRaw,
EntriesTree, Error, IncompleteLineProgram, LocListIter, LocationLists, Range, RangeLists,
Reader, ReaderOffset, ReaderOffsetId, Result, RngListIter, Section, TypeUnitHeader,
TypeUnitHeadersIter, UnitHeader, UnitOffset,
Abbreviations, AttributeValue, CompilationUnitHeader, CompilationUnitHeadersIter, DebugAbbrev,
DebugAddr, DebugInfo, DebugLine, DebugLineStr, DebugStr, DebugStrOffsets, DebugTypes,
DebuggingInformationEntry, EntriesCursor, EntriesRaw, EntriesTree, Error,
IncompleteLineProgram, LocListIter, LocationLists, Range, RangeLists, Reader, ReaderOffset,
ReaderOffsetId, Result, RngListIter, Section, TypeUnitHeader, TypeUnitHeadersIter, UnitHeader,
UnitOffset,
};

/// All of the commonly used DWARF sections, and other common information.
Expand Down Expand Up @@ -147,7 +147,10 @@ impl<R: Reader> Dwarf<R> {

/// Construct a new `Unit` from the given compilation unit header.
#[inline]
pub fn unit(&self, header: CompilationUnitHeader<R>) -> Result<Unit<R>> {
pub fn unit(
&self,
header: CompilationUnitHeader<R>,
) -> Result<Unit<CompilationUnitHeader<R>, R>> {
Unit::new(self, header)
}

Expand All @@ -162,7 +165,7 @@ impl<R: Reader> Dwarf<R> {

/// Construct a new `Unit` from the given type unit header.
#[inline]
pub fn type_unit(&self, header: TypeUnitHeader<R>) -> Result<Unit<R>> {
pub fn type_unit(&self, header: TypeUnitHeader<R>) -> Result<Unit<TypeUnitHeader<R>, R>> {
Unit::new_type_unit(self, header)
}

Expand All @@ -182,11 +185,14 @@ impl<R: Reader> Dwarf<R> {

/// Return the string offset at the given index.
#[inline]
pub fn string_offset(
pub fn string_offset<Header>(
&self,
unit: &Unit<R>,
unit: &Unit<Header, R>,
index: DebugStrOffsetsIndex<R::Offset>,
) -> Result<DebugStrOffset<R::Offset>> {
) -> Result<DebugStrOffset<R::Offset>>
where
Header: UnitHeader<R, R::Offset>,
{
self.debug_str_offsets
.get_str_offset(unit.header.format(), unit.str_offsets_base, index)
}
Expand Down Expand Up @@ -217,7 +223,10 @@ impl<R: Reader> Dwarf<R> {
///
/// then return the attribute's string value. Returns an error if the attribute
/// value does not have a string form, or if a string form has an invalid value.
pub fn attr_string(&self, unit: &Unit<R>, attr: AttributeValue<R>) -> Result<R> {
pub fn attr_string<Header>(&self, unit: &Unit<Header, R>, attr: AttributeValue<R>) -> Result<R>
where
Header: UnitHeader<R, R::Offset>,
{
match attr {
AttributeValue::String(string) => Ok(string),
AttributeValue::DebugStrRef(offset) => self.debug_str.get_str(offset),
Expand All @@ -236,27 +245,40 @@ impl<R: Reader> Dwarf<R> {
}

/// Return the address at the given index.
pub fn address(&self, unit: &Unit<R>, index: DebugAddrIndex<R::Offset>) -> Result<u64> {
pub fn address<Header>(
&self,
unit: &Unit<Header, R>,
index: DebugAddrIndex<R::Offset>,
) -> Result<u64>
where
Header: UnitHeader<R, R::Offset>,
{
self.debug_addr
.get_address(unit.encoding().address_size, unit.addr_base, index)
}

/// Return the range list offset at the given index.
pub fn ranges_offset(
pub fn ranges_offset<Header>(
&self,
unit: &Unit<R>,
unit: &Unit<Header, R>,
index: DebugRngListsIndex<R::Offset>,
) -> Result<RangeListsOffset<R::Offset>> {
) -> Result<RangeListsOffset<R::Offset>>
where
Header: UnitHeader<R, R::Offset>,
{
self.ranges
.get_offset(unit.encoding(), unit.rnglists_base, index)
}

/// Iterate over the `RangeListEntry`s starting at the given offset.
pub fn ranges(
pub fn ranges<Header>(
&self,
unit: &Unit<R>,
unit: &Unit<Header, R>,
offset: RangeListsOffset<R::Offset>,
) -> Result<RngListIter<R>> {
) -> Result<RngListIter<R>>
where
Header: UnitHeader<R, R::Offset>,
{
self.ranges.ranges(
offset,
unit.encoding(),
Expand All @@ -275,11 +297,14 @@ impl<R: Reader> Dwarf<R> {
///
/// then return the range list offset of the range list.
/// Returns `None` for other forms.
pub fn attr_ranges_offset(
pub fn attr_ranges_offset<Header>(
&self,
unit: &Unit<R>,
unit: &Unit<Header, R>,
attr: AttributeValue<R>,
) -> Result<Option<RangeListsOffset<R::Offset>>> {
) -> Result<Option<RangeListsOffset<R::Offset>>>
where
Header: UnitHeader<R, R::Offset>,
{
match attr {
AttributeValue::RangeListsRef(offset) => Ok(Some(offset)),
AttributeValue::DebugRngListsIndex(index) => self.ranges_offset(unit, index).map(Some),
Expand All @@ -296,11 +321,14 @@ impl<R: Reader> Dwarf<R> {
///
/// then return an iterator over the entries in the range list.
/// Returns `None` for other forms.
pub fn attr_ranges(
pub fn attr_ranges<Header>(
&self,
unit: &Unit<R>,
unit: &Unit<Header, R>,
attr: AttributeValue<R>,
) -> Result<Option<RngListIter<R>>> {
) -> Result<Option<RngListIter<R>>>
where
Header: UnitHeader<R, R::Offset>,
{
match self.attr_ranges_offset(unit, attr)? {
Some(offset) => Ok(Some(self.ranges(unit, offset)?)),
None => Ok(None),
Expand All @@ -310,11 +338,14 @@ impl<R: Reader> Dwarf<R> {
/// Return an iterator for the address ranges of a `DebuggingInformationEntry`.
///
/// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges`.
pub fn die_ranges(
pub fn die_ranges<Header>(
&self,
unit: &Unit<R>,
unit: &Unit<Header, R>,
entry: &DebuggingInformationEntry<R>,
) -> Result<RangeIter<R>> {
) -> Result<RangeIter<R>>
where
Header: UnitHeader<R, R::Offset>,
{
let mut low_pc = None;
let mut high_pc = None;
let mut size = None;
Expand Down Expand Up @@ -351,29 +382,38 @@ impl<R: Reader> Dwarf<R> {
///
/// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges` of the
/// root `DebuggingInformationEntry`.
pub fn unit_ranges(&self, unit: &Unit<R>) -> Result<RangeIter<R>> {
pub fn unit_ranges<Header>(&self, unit: &Unit<Header, R>) -> Result<RangeIter<R>>
where
Header: UnitHeader<R, R::Offset>,
{
let mut cursor = unit.header.entries(&unit.abbreviations);
cursor.next_dfs()?;
let root = cursor.current().ok_or(Error::MissingUnitDie)?;
self.die_ranges(unit, root)
}

/// Return the location list offset at the given index.
pub fn locations_offset(
pub fn locations_offset<Header>(
&self,
unit: &Unit<R>,
unit: &Unit<Header, R>,
index: DebugLocListsIndex<R::Offset>,
) -> Result<LocationListsOffset<R::Offset>> {
) -> Result<LocationListsOffset<R::Offset>>
where
Header: UnitHeader<R, R::Offset>,
{
self.locations
.get_offset(unit.encoding(), unit.loclists_base, index)
}

/// Iterate over the `LocationListEntry`s starting at the given offset.
pub fn locations(
pub fn locations<Header>(
&self,
unit: &Unit<R>,
unit: &Unit<Header, R>,
offset: LocationListsOffset<R::Offset>,
) -> Result<LocListIter<R>> {
) -> Result<LocListIter<R>>
where
Header: UnitHeader<R, R::Offset>,
{
self.locations.locations(
offset,
unit.encoding(),
Expand All @@ -392,11 +432,14 @@ impl<R: Reader> Dwarf<R> {
///
/// then return the location list offset of the location list.
/// Returns `None` for other forms.
pub fn attr_locations_offset(
pub fn attr_locations_offset<Header>(
&self,
unit: &Unit<R>,
unit: &Unit<Header, R>,
attr: AttributeValue<R>,
) -> Result<Option<LocationListsOffset<R::Offset>>> {
) -> Result<Option<LocationListsOffset<R::Offset>>>
where
Header: UnitHeader<R, R::Offset>,
{
match attr {
AttributeValue::LocationListsRef(offset) => Ok(Some(offset)),
AttributeValue::DebugLocListsIndex(index) => {
Expand All @@ -415,11 +458,14 @@ impl<R: Reader> Dwarf<R> {
///
/// then return an iterator over the entries in the location list.
/// Returns `None` for other forms.
pub fn attr_locations(
pub fn attr_locations<Header>(
&self,
unit: &Unit<R>,
unit: &Unit<Header, R>,
attr: AttributeValue<R>,
) -> Result<Option<LocListIter<R>>> {
) -> Result<Option<LocListIter<R>>>
where
Header: UnitHeader<R, R::Offset>,
{
match self.attr_locations_offset(unit, attr)? {
Some(offset) => Ok(Some(self.locations(unit, offset)?)),
None => Ok(None),
Expand Down Expand Up @@ -475,16 +521,17 @@ impl<R: Reader> Dwarf<R> {
/// All of the commonly used information for a unit in the `.debug_info` or `.debug_types`
/// sections.
#[derive(Debug)]
pub struct Unit<R, Offset = <R as Reader>::Offset>
pub struct Unit<Header, R, Offset = <R as Reader>::Offset>
where
Header: UnitHeader<R, Offset>,
R: Reader<Offset = Offset>,
Offset: ReaderOffset,
{
/// The section offset of the unit.
pub offset: UnitSectionOffset<Offset>,

/// The header of the unit.
pub header: CommonUnitHeader<R, Offset>,
pub header: Header,

/// The parsed abbreviations for the unit.
pub abbreviations: Abbreviations,
Expand Down Expand Up @@ -514,31 +561,38 @@ where
pub line_program: Option<IncompleteLineProgram<R, Offset>>,
}

impl<R: Reader> Unit<R> {
impl<R: Reader> Unit<CompilationUnitHeader<R>, R> {
/// Construct a new `Unit` from the given compilation unit header.
#[inline]
pub fn new(dwarf: &Dwarf<R>, header: CompilationUnitHeader<R>) -> Result<Self> {
Self::new_internal(
dwarf,
UnitSectionOffset::DebugInfoOffset(header.offset()),
header.header(),
header,
)
}
}

impl<R: Reader> Unit<TypeUnitHeader<R>, R> {
/// Construct a new `Unit` from the given type unit header.
#[inline]
pub fn new_type_unit(dwarf: &Dwarf<R>, header: TypeUnitHeader<R>) -> Result<Self> {
Self::new_internal(
dwarf,
UnitSectionOffset::DebugTypesOffset(header.offset()),
header.header(),
header,
)
}
}

impl<Header, R: Reader> Unit<Header, R>
where
Header: UnitHeader<R, R::Offset>,
{
fn new_internal(
dwarf: &Dwarf<R>,
offset: UnitSectionOffset<R::Offset>,
header: CommonUnitHeader<R>,
header: Header,
) -> Result<Self> {
let abbreviations = header.abbreviations(&dwarf.debug_abbrev)?;
let mut unit = Unit {
Expand Down Expand Up @@ -669,8 +723,9 @@ impl<T: ReaderOffset> UnitSectionOffset<T> {
/// Convert an offset to be relative to the start of the given unit,
/// instead of relative to the start of the section.
/// Returns `None` if the offset is not within the unit entries.
pub fn to_unit_offset<R>(&self, unit: &Unit<R>) -> Option<UnitOffset<T>>
pub fn to_unit_offset<Header, R>(&self, unit: &Unit<Header, R>) -> Option<UnitOffset<T>>
where
Header: UnitHeader<R, R::Offset>,
R: Reader<Offset = T>,
{
let (offset, unit_offset) = match (self, unit.offset) {
Expand All @@ -688,7 +743,7 @@ impl<T: ReaderOffset> UnitSectionOffset<T> {
Some(offset) => UnitOffset(offset),
None => return None,
};
if !unit.header.is_valid_offset(offset) {
if !unit.header.header_ref().is_valid_offset(offset) {
return None;
}
Some(offset)
Expand All @@ -700,8 +755,9 @@ impl<T: ReaderOffset> UnitOffset<T> {
/// instead of relative to the start of the given compilation unit.
///
/// Does not check that the offset is valid.
pub fn to_unit_section_offset<R>(&self, unit: &Unit<R>) -> UnitSectionOffset<T>
pub fn to_unit_section_offset<Header, R>(&self, unit: &Unit<Header, R>) -> UnitSectionOffset<T>
where
Header: UnitHeader<R, R::Offset>,
R: Reader<Offset = T>,
{
match unit.offset {
Expand Down
12 changes: 10 additions & 2 deletions src/write/cfi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,8 +745,16 @@ pub(crate) mod convert {
convert_address: &dyn Fn(u64) -> Option<Address>,
offset: &mut u32,
) -> ConvertResult<Option<CallFrameInstruction>> {
let convert_expression =
|x| Expression::from(x, from_cie.encoding(), None, None, None, convert_address);
let convert_expression = |x| {
Expression::from::<read::CompilationUnitHeader<R>, R>(
x,
from_cie.encoding(),
None,
None,
None,
convert_address,
)
};
// TODO: validate integer type conversions
Ok(Some(match from_instruction {
read::CallFrameInstruction::SetLoc { .. } => {
Expand Down
12 changes: 8 additions & 4 deletions src/write/loc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,15 +298,19 @@ fn write_expression<W: Writer>(
mod convert {
use super::*;

use crate::read::{self, Reader};
use crate::read::{self, Reader, UnitHeader};
use crate::write::{ConvertError, ConvertResult, ConvertUnitContext};

impl LocationList {
/// Create a location list by reading the data from the give location list iter.
pub(crate) fn from<R: Reader<Offset = usize>>(
pub(crate) fn from<Header, R>(
mut from: read::RawLocListIter<R>,
context: &ConvertUnitContext<R>,
) -> ConvertResult<Self> {
context: &ConvertUnitContext<Header, R>,
) -> ConvertResult<Self>
where
Header: UnitHeader<R, R::Offset>,
R: Reader<Offset = usize>,
{
let mut have_base_address = context.base_address != Address::Constant(0);
let convert_address =
|x| (context.convert_address)(x).ok_or(ConvertError::InvalidAddress);
Expand Down
Loading

0 comments on commit b987e40

Please sign in to comment.