Skip to content

Commit

Permalink
read: implement DW_OP_addrx and DW_OP_constx
Browse files Browse the repository at this point in the history
  • Loading branch information
philipc committed Jan 14, 2019
1 parent db16150 commit 725d0a2
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 2 deletions.
6 changes: 6 additions & 0 deletions examples/dwarfdump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1536,6 +1536,12 @@ fn dump_op<R: Reader, W: Write>(
gimli::Operation::Address { address } => {
write!(w, " 0x{:08x}", address)?;
}
gimli::Operation::AddressIndex { index } => {
write!(w, " 0x{:08x}", index.0)?;
}
gimli::Operation::ConstantIndex { index } => {
write!(w, " 0x{:08x}", index.0)?;
}
gimli::Operation::TypedLiteral { base_type, value } => {
write!(w, " type 0x{:08x} contents 0x", base_type.0)?;
for byte in value.to_slice()?.iter() {
Expand Down
120 changes: 118 additions & 2 deletions src/read/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::mem;
use vec::Vec;

use common::{DebugInfoOffset, Format, Register};
use common::{DebugAddrIndex, DebugInfoOffset, Format, Register};
use constants;
use read::{Error, Reader, ReaderOffset, Result, UnitOffset, Value, ValueType};

Expand Down Expand Up @@ -206,9 +206,23 @@ where
/// Represents `DW_OP_addr`.
/// Relocate the address if needed, and push it on the stack.
Address {
/// The offfset to add.
/// The offset to add.
address: u64,
},
/// Represents `DW_OP_addrx`.
/// Read the address at the given index in `.debug_addr, relocate the address if needed,
/// and push it on the stack.
AddressIndex {
/// The index of the address in `.debug_addr`.
index: DebugAddrIndex<Offset>,
},
/// Represents `DW_OP_constx`.
/// Read the address at the given index in `.debug_addr, and push it on the stack.
/// Do not relocate the address.
ConstantIndex {
/// The index of the address in `.debug_addr`.
index: DebugAddrIndex<Offset>,
},
/// Represents `DW_OP_const_type`.
/// Interpret the value bytes as a constant of a given type, and push it on the stack.
TypedLiteral {
Expand Down Expand Up @@ -667,6 +681,18 @@ where
byte_offset,
})
}
constants::DW_OP_addrx => {
let index = bytes.read_uleb128().and_then(R::Offset::from_u64)?;
Ok(Operation::AddressIndex {
index: DebugAddrIndex(index),
})
}
constants::DW_OP_constx => {
let index = bytes.read_uleb128().and_then(R::Offset::from_u64)?;
Ok(Operation::ConstantIndex {
index: DebugAddrIndex(index),
})
}
constants::DW_OP_entry_value | constants::DW_OP_GNU_entry_value => {
let len = bytes.read_uleb128().and_then(R::Offset::from_u64)?;
let expression = bytes.split(len)?;
Expand Down Expand Up @@ -752,6 +778,7 @@ enum EvaluationWaiting<R: Reader> {
EntryValue,
ParameterRef,
RelocatedAddress,
IndexedAddress,
TypedLiteral { value: R },
Convert,
Reinterpret,
Expand Down Expand Up @@ -820,6 +847,17 @@ pub enum EvaluationResult<R: Reader> {
/// Once the caller determines what value to provide it should resume the
/// `Evaluation` by calling `Evaluation::resume_with_relocated_address`.
RequiresRelocatedAddress(u64),
/// The `Evaluation` needs an address from the `.debug_addr` section.
/// This address may also need to be relocated.
/// Once the caller determines what value to provide it should resume the
/// `Evaluation` by calling `Evaluation::resume_with_indexed_address`.
RequiresIndexedAddress {
/// The index of the address in the `.debug_addr` section,
/// relative to the `DW_AT_addr_base` of the compilation unit.
index: DebugAddrIndex<R::Offset>,
/// Whether the address also needs to be relocated.
relocate: bool,
},
/// The `Evaluation` needs the `ValueType` for the base type DIE at
/// the give unit offset. Once the caller determines what value to provide it
/// should resume the `Evaluation` by calling
Expand Down Expand Up @@ -1307,6 +1345,26 @@ impl<R: Reader> Evaluation<R> {
));
}

Operation::AddressIndex { index } => {
return Ok(OperationEvaluationResult::Waiting(
EvaluationWaiting::IndexedAddress,
EvaluationResult::RequiresIndexedAddress {
index,
relocate: true,
},
));
}

Operation::ConstantIndex { index } => {
return Ok(OperationEvaluationResult::Waiting(
EvaluationWaiting::IndexedAddress,
EvaluationResult::RequiresIndexedAddress {
index,
relocate: false,
},
));
}

Operation::Piece {
size_in_bits,
bit_offset,
Expand Down Expand Up @@ -1590,6 +1648,28 @@ impl<R: Reader> Evaluation<R> {
self.evaluate_internal()
}

/// Resume the `Evaluation` with the provided indexed `address`. This will use the
/// provided indexed address for the operation that required it, and continue evaluating
/// opcodes until the evaluation is completed, reaches an error, or needs
/// more information again.
///
/// # Panics
/// Panics if this `Evaluation` did not previously stop with
/// `EvaluationResult::RequiresIndexedAddress`.
pub fn resume_with_indexed_address(&mut self, address: u64) -> Result<EvaluationResult<R>> {
match self.state {
EvaluationState::Error(err) => return Err(err),
EvaluationState::Waiting(EvaluationWaiting::IndexedAddress) => {
self.push(Value::Generic(address));
}
_ => panic!(
"Called `Evaluation::resume_with_indexed_address` without a preceding `EvaluationResult::RequiresIndexedAddress`"
),
};

self.evaluate_internal()
}

/// Resume the `Evaluation` with the provided `base_type`. This will use the
/// provided base type for the operation that required it, and continue evaluating
/// opcodes until the evaluation is completed, reaches an error, or needs
Expand Down Expand Up @@ -2243,6 +2323,23 @@ mod tests {
));
}

if *value <= (!0u32).into() {
inputs.extend(&[
(
constants::DW_OP_addrx,
Operation::AddressIndex {
index: DebugAddrIndex(*value as usize),
},
),
(
constants::DW_OP_constx,
Operation::ConstantIndex {
index: DebugAddrIndex(*value as usize),
},
),
]);
}

// FIXME
if *value < !0u64 / 8 {
inputs.push((
Expand Down Expand Up @@ -3165,6 +3262,18 @@ mod tests {
Op(DW_OP_ne),
Op(DW_OP_bra), Branch(fail),

Op(DW_OP_addrx), Uleb(0x10),
Op(DW_OP_deref),
Op(DW_OP_const4u), U32(0x4040),
Op(DW_OP_ne),
Op(DW_OP_bra), Branch(fail),

Op(DW_OP_constx), Uleb(17),
Op(DW_OP_form_tls_address),
Op(DW_OP_constu), Uleb(!27),
Op(DW_OP_ne),
Op(DW_OP_bra), Branch(fail),

// Success.
Op(DW_OP_lit0),
Op(DW_OP_nop),
Expand Down Expand Up @@ -3214,6 +3323,13 @@ mod tests {
EvaluationResult::RequiresRelocatedAddress(address) => {
eval.resume_with_relocated_address(address)?
}
EvaluationResult::RequiresIndexedAddress { index, relocate } => {
if relocate {
eval.resume_with_indexed_address(0x1000 + index.0 as u64)?
} else {
eval.resume_with_indexed_address(10 + index.0 as u64)?
}
}
_ => panic!(),
};
}
Expand Down

0 comments on commit 725d0a2

Please sign in to comment.