Skip to content

Commit

Permalink
read: add Evaluation::value_result (#676)
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.

Currently a value computation will result in a location description that
contains one `Piece` whose `location` is set to `Location::Address`,
and this address is the computed value.

`Evaluation::value_result` makes it easier to obtain this value,
supports results that are typed values, and checks there were no
operations that only valid for location descriptions.
  • Loading branch information
philipc authored Nov 24, 2023
1 parent 531636d commit e6adc47
Showing 1 changed file with 26 additions and 5 deletions.
31 changes: 26 additions & 5 deletions src/read/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1077,10 +1077,10 @@ impl<R: Reader> EvaluationStorage<R> for StoreOnHeap {
///
/// # Examples
/// ```rust,no_run
/// use gimli::{EndianSlice, Evaluation, EvaluationResult, Format, LittleEndian, Value};
/// # let bytecode = EndianSlice::new(&[], LittleEndian);
/// use gimli::{Evaluation, EvaluationResult, Expression};
/// # let bytecode = gimli::EndianSlice::new(&[], gimli::LittleEndian);
/// # let encoding = unimplemented!();
/// # let get_register_value = |_, _| Value::Generic(42);
/// # let get_register_value = |_, _| gimli::Value::Generic(42);
/// # let get_frame_base = || 0xdeadbeef;
///
/// let mut eval = Evaluation::new(bytecode, encoding);
Expand Down Expand Up @@ -1126,6 +1126,7 @@ pub struct Evaluation<R: Reader, S: EvaluationStorage<R> = StoreOnHeap> {
// is stored here while evaluating the subroutine.
expression_stack: ArrayVec<S::ExpressionStack>,

value_result: Option<Value>,
result: ArrayVec<S::Result>,
}

Expand Down Expand Up @@ -1175,6 +1176,7 @@ impl<R: Reader, S: EvaluationStorage<R>> Evaluation<R, S> {
stack: Default::default(),
expression_stack: Default::default(),
pc,
value_result: None,
result: Default::default(),
}
}
Expand Down Expand Up @@ -1600,6 +1602,22 @@ impl<R: Reader, S: EvaluationStorage<R>> Evaluation<R, S> {
Ok(OperationEvaluationResult::Incomplete)
}

/// Get the result if this is an evaluation for a value.
///
/// Returns `None` if the evaluation contained operations that are only
/// valid for location descriptions.
///
/// # Panics
/// Panics if this `Evaluation` has not been driven to completion.
pub fn value_result(&self) -> Option<Value> {
match self.state {
EvaluationState::Complete => self.value_result,
_ => {
panic!("Called `Evaluation::value_result` on an `Evaluation` that has not been completed")
}
}
}

/// Get the result of this `Evaluation`.
///
/// # Panics
Expand All @@ -1608,7 +1626,9 @@ impl<R: Reader, S: EvaluationStorage<R>> Evaluation<R, S> {
match self.state {
EvaluationState::Complete => &self.result,
_ => {
panic!("Called `Evaluation::result` on an `Evaluation` that has not been completed")
panic!(
"Called `Evaluation::as_result` on an `Evaluation` that has not been completed"
)
}
}
}
Expand Down Expand Up @@ -1968,13 +1988,14 @@ impl<R: Reader, S: EvaluationStorage<R>> Evaluation<R, S> {
self.state = EvaluationState::Waiting(waiting);
return Ok(result);
}
};
}
}

// If no pieces have been seen, use the stack top as the
// result.
if self.result.is_empty() {
let entry = self.pop()?;
self.value_result = Some(entry);
let addr = entry.to_u64(self.addr_mask)?;
self.result
.try_push(Piece {
Expand Down

0 comments on commit e6adc47

Please sign in to comment.