Skip to content

Commit

Permalink
read/op: add ExpressionKind
Browse files Browse the repository at this point in the history
DWARF expressions can be used to either compute a value or
a location description, depending on context, and this affects
the result of the evaluation, and which operations are valid
within them.

Use the attribute tag to determine the expression kind for
expressions in DIE attributes.
  • Loading branch information
philipc committed Aug 14, 2023
1 parent 3947879 commit 5f71609
Show file tree
Hide file tree
Showing 7 changed files with 266 additions and 150 deletions.
18 changes: 9 additions & 9 deletions benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ extern crate test;
use gimli::{
AttributeValue, DebugAbbrev, DebugAddr, DebugAddrBase, DebugAranges, DebugInfo, DebugLine,
DebugLineOffset, DebugLoc, DebugLocLists, DebugPubNames, DebugPubTypes, DebugRanges,
DebugRngLists, Encoding, EndianSlice, EntriesTreeNode, Expression, LittleEndian, LocationLists,
Operation, RangeLists, RangeListsOffset, Reader, ReaderOffset,
DebugRngLists, Encoding, EndianSlice, EntriesTreeNode, Expression, ExpressionKind,
LittleEndian, LocationLists, Operation, RangeLists, RangeListsOffset, Reader, ReaderOffset,
};
use std::env;
use std::fs::File;
Expand Down Expand Up @@ -405,7 +405,7 @@ fn bench_parsing_debug_ranges(b: &mut test::Bencher) {
fn debug_info_expressions<R: Reader>(
debug_info: &DebugInfo<R>,
debug_abbrev: &DebugAbbrev<R>,
) -> Vec<(Expression<R>, Encoding)> {
) -> Vec<(Expression<R>, ExpressionKind, Encoding)> {
let mut expressions = Vec::new();

let mut iter = debug_info.units();
Expand All @@ -418,8 +418,8 @@ fn debug_info_expressions<R: Reader>(
while let Some((_, entry)) = cursor.next_dfs().expect("Should parse next dfs") {
let mut attrs = entry.attrs();
while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
if let AttributeValue::Exprloc(expression) = attr.value() {
expressions.push((expression, unit.encoding()));
if let AttributeValue::Exprloc(expression, kind) = attr.value() {
expressions.push((expression, kind, unit.encoding()));
}
}
}
Expand All @@ -439,7 +439,7 @@ fn bench_parsing_debug_info_expressions(b: &mut test::Bencher) {
let expressions = debug_info_expressions(&debug_info, &debug_abbrev);

b.iter(|| {
for &(expression, encoding) in &*expressions {
for &(expression, _kind, encoding) in &*expressions {
let mut pc = expression.0;
while !pc.is_empty() {
Operation::parse(&mut pc, encoding).expect("Should parse operation");
Expand All @@ -459,8 +459,8 @@ fn bench_evaluating_debug_info_expressions(b: &mut test::Bencher) {
let expressions = debug_info_expressions(&debug_info, &debug_abbrev);

b.iter(|| {
for &(expression, encoding) in &*expressions {
let mut eval = expression.evaluation(encoding);
for &(expression, kind, encoding) in &*expressions {
let mut eval = expression.evaluation(kind, encoding);
eval.set_initial_value(0);
let result = eval.evaluate().expect("Should evaluate expression");
test::black_box(result);
Expand Down Expand Up @@ -564,7 +564,7 @@ fn bench_evaluating_debug_loc_expressions(b: &mut test::Bencher) {

b.iter(|| {
for &(expression, encoding) in &*expressions {
let mut eval = expression.evaluation(encoding);
let mut eval = expression.evaluation(ExpressionKind::Location, encoding);
eval.set_initial_value(0);
let result = eval.evaluate().expect("Should evaluate expression");
test::black_box(result);
Expand Down
4 changes: 2 additions & 2 deletions crates/examples/src/bin/dwarfdump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1434,8 +1434,8 @@ fn dump_attr_value<R: Reader, W: Write>(
}
};
}
gimli::AttributeValue::Exprloc(ref data) => {
if let gimli::AttributeValue::Exprloc(_) = attr.raw_value() {
gimli::AttributeValue::Exprloc(ref data, _kind) => {
if let gimli::AttributeValue::Exprloc(..) = attr.raw_value() {
write!(w, "len 0x{:04x}: ", data.0.len())?;
for byte in data.0.to_slice()?.iter() {
write!(w, "{:02x}", byte)?;
Expand Down
12 changes: 12 additions & 0 deletions src/read/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,11 @@ pub enum Error {
/// An expression-terminating operation was followed by something
/// other than the end of the expression or a piece operation.
InvalidExpressionTerminator(u64),
/// An expression for a value contained an operation that is only valid for location
/// descriptions.
InvalidValueExpression,
/// Cannot evaluate an expression without knowing its kind.
UnknownExpressionKind,
/// Division or modulus by zero when evaluating an expression.
DivisionByZero,
/// An expression operation used mismatching types.
Expand Down Expand Up @@ -520,6 +525,13 @@ impl Error {
"DWARF expression has piece followed by non-piece expression at end"
}
Error::InvalidExpressionTerminator(_) => "Expected DW_OP_piece or DW_OP_bit_piece",
Error::InvalidValueExpression => {
"An expression for a value contained an operation that is only valid for location \
descriptions"
}
Error::UnknownExpressionKind => {
"Cannot evaluate an expression without knowing its kind"
}
Error::DivisionByZero => "Division or modulus by zero when evaluating expression",
Error::TypeMismatch => "Type mismatch when evaluating expression",
Error::IntegralTypeRequired => "Integral type expected when evaluating expression",
Expand Down
Loading

0 comments on commit 5f71609

Please sign in to comment.