Skip to content

Commit

Permalink
refactoring(debugger):
Browse files Browse the repository at this point in the history
- rename `VariableSelector` into `Selector`
- rename `DqeResult` into `ScopedVariable`
- use `Selector::by_name` instead of manual creating of `Name` selector
- add reminder comment for oracle watchpoints
  • Loading branch information
godzie44 committed Jun 4, 2024
1 parent afb62bc commit e8e77d4
Show file tree
Hide file tree
Showing 11 changed files with 215 additions and 362 deletions.
8 changes: 3 additions & 5 deletions src/debugger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use crate::debugger::process::{Child, Installed};
use crate::debugger::register::debug::BreakCondition;
use crate::debugger::register::{DwarfRegisterMap, Register, RegisterMap};
use crate::debugger::step::StepResult;
use crate::debugger::variable::select::{VariableSelector, DQE};
use crate::debugger::variable::select::{Selector, DQE};
use crate::debugger::variable::VariableIR;
use crate::debugger::watchpoint::WatchpointRegistry;
use crate::debugger::Error::Syscall;
Expand Down Expand Up @@ -875,10 +875,8 @@ impl Debugger {
pub fn read_local_variables(&self) -> Result<Vec<VariableIR>, Error> {
disable_when_not_stared!(self);

let evaluator = variable::select::SelectExpressionEvaluator::new(
self,
DQE::Variable(VariableSelector::Any),
);
let evaluator =
variable::select::SelectExpressionEvaluator::new(self, DQE::Variable(Selector::Any));
let eval_result = evaluator.evaluate()?;
Ok(eval_result.into_iter().map(|res| res.variable).collect())
}
Expand Down
66 changes: 33 additions & 33 deletions src/debugger/variable/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,6 @@ impl AsAllocatedData for VirtualVariableDie {
}
}

#[derive(Debug, PartialEq, Clone)]
pub enum VariableSelector {
Name { var_name: String, only_local: bool },
Any,
}

impl VariableSelector {
pub fn by_name(name: &str, only_local: bool) -> Self {
Self::Name {
var_name: name.to_string(),
only_local,
}
}
}

/// Literal object. Using it for a searching element by key in key-value containers.
#[derive(Debug, PartialEq, Clone)]
pub enum Literal {
Expand Down Expand Up @@ -127,6 +112,21 @@ pub struct ObjectBinaryRepr {
pub size: usize,
}

#[derive(Debug, PartialEq, Clone)]
pub enum Selector {
Name { var_name: String, local_only: bool },
Any,
}

impl Selector {
pub fn by_name(name: impl ToString, local_only: bool) -> Self {
Self::Name {
var_name: name.to_string(),
local_only,
}
}
}

/// Data query expression.
/// List of operations for select variables and their properties.
///
Expand All @@ -136,7 +136,7 @@ pub struct ObjectBinaryRepr {
/// Supported operations are: dereference, get an element by index, get field by name, make slice from a pointer.
#[derive(Debug, PartialEq, Clone)]
pub enum DQE {
Variable(VariableSelector),
Variable(Selector),
PtrCast(usize, String),
Field(Box<DQE>, String),
Index(Box<DQE>, Literal),
Expand All @@ -154,7 +154,7 @@ impl DQE {
}

/// Result of DQE evaluation.
pub struct DqeResult {
pub struct ScopedVariable {
/// Variable intermediate representation.
pub variable: VariableIR,
/// PC ranges where value is valid, `None` for global or virtual variables.
Expand Down Expand Up @@ -192,7 +192,7 @@ impl<'a> SelectExpressionEvaluator<'a> {

fn extract_variable_by_selector(
&self,
selector: &VariableSelector,
selector: &Selector,
) -> Result<Vec<ContextualDieRef<VariableDie>>, Error> {
let ctx = self.debugger.exploration_ctx();

Expand All @@ -203,9 +203,9 @@ impl<'a> SelectExpressionEvaluator<'a> {
.ok_or(FunctionNotFound(ctx.location().global_pc))?;

let vars = match selector {
VariableSelector::Name {
Selector::Name {
var_name,
only_local: local,
local_only: local,
} => {
let local_variants = current_func
.local_variable(ctx.location().global_pc, var_name)
Expand All @@ -224,7 +224,7 @@ impl<'a> SelectExpressionEvaluator<'a> {
local_variants
}
}
VariableSelector::Any => current_func.local_variables(ctx.location().global_pc),
Selector::Any => current_func.local_variables(ctx.location().global_pc),
};

Ok(vars)
Expand Down Expand Up @@ -280,7 +280,7 @@ impl<'a> SelectExpressionEvaluator<'a> {
}
}

fn evaluate_inner(&self, expression: &DQE) -> Result<Vec<DqeResult>, Error> {
fn evaluate_inner(&self, expression: &DQE) -> Result<Vec<ScopedVariable>, Error> {
// evaluate variable one by one in `evaluate_single_variable` method
// here just filter variables
match expression {
Expand All @@ -294,7 +294,7 @@ impl<'a> SelectExpressionEvaluator<'a> {
let r#type = weak_error!(type_from_cache!(var, type_cache))?;
let var_ir =
self.evaluate_single_variable(&self.expression, var, r#type)?;
Some(DqeResult {
Some(ScopedVariable {
variable: var_ir,
scope: var.ranges().map(Box::from),
})
Expand All @@ -305,7 +305,7 @@ impl<'a> SelectExpressionEvaluator<'a> {
let vars_ir = self.evaluate_from_ptr_cast(target_type_name)?;
Ok(vars_ir
.into_iter()
.map(|var_ir| DqeResult {
.map(|var_ir| ScopedVariable {
variable: var_ir,
scope: None,
})
Expand Down Expand Up @@ -336,7 +336,7 @@ impl<'a> SelectExpressionEvaluator<'a> {
}

/// Evaluate a select expression and returns list of matched variables.
pub fn evaluate(&self) -> Result<Vec<DqeResult>, Error> {
pub fn evaluate(&self) -> Result<Vec<ScopedVariable>, Error> {
self.evaluate_inner(&self.expression)
}

Expand All @@ -354,11 +354,11 @@ impl<'a> SelectExpressionEvaluator<'a> {
let params = current_function.parameters();

let params = match selector {
VariableSelector::Name { var_name, .. } => params
Selector::Name { var_name, .. } => params
.into_iter()
.filter(|param| param.die.base_attributes.name.as_ref() == Some(var_name))
.collect::<Vec<_>>(),
VariableSelector::Any => params,
Selector::Any => params,
};

Ok(params
Expand All @@ -371,11 +371,11 @@ impl<'a> SelectExpressionEvaluator<'a> {
}

/// Same as [`SelectExpressionEvaluator::evaluate`] but for function arguments.
pub fn evaluate_on_arguments(&self) -> Result<Vec<DqeResult>, Error> {
pub fn evaluate_on_arguments(&self) -> Result<Vec<ScopedVariable>, Error> {
self.evaluate_on_arguments_inner(&self.expression)
}

fn evaluate_on_arguments_inner(&self, expression: &DQE) -> Result<Vec<DqeResult>, Error> {
fn evaluate_on_arguments_inner(&self, expression: &DQE) -> Result<Vec<ScopedVariable>, Error> {
match expression {
DQE::Variable(selector) => {
let expl_ctx_loc = self.debugger.exploration_ctx().location();
Expand All @@ -387,11 +387,11 @@ impl<'a> SelectExpressionEvaluator<'a> {
let params = current_function.parameters();

let params = match selector {
VariableSelector::Name { var_name, .. } => params
Selector::Name { var_name, .. } => params
.into_iter()
.filter(|param| param.die.base_attributes.name.as_ref() == Some(var_name))
.collect::<Vec<_>>(),
VariableSelector::Any => params,
Selector::Any => params,
};

let mut type_cache = self.debugger.type_cache.borrow_mut();
Expand All @@ -402,7 +402,7 @@ impl<'a> SelectExpressionEvaluator<'a> {
let r#type = weak_error!(type_from_cache!(var, type_cache))?;
let var_ir =
self.evaluate_single_variable(&self.expression, var, r#type)?;
Some(DqeResult {
Some(ScopedVariable {
variable: var_ir,
scope: var.max_range().map(|r| {
let scope: Box<[Range]> = Box::new([r]);
Expand All @@ -416,7 +416,7 @@ impl<'a> SelectExpressionEvaluator<'a> {
let vars = self.evaluate_from_ptr_cast(target_type_name)?;
Ok(vars
.into_iter()
.map(|v| DqeResult {
.map(|v| ScopedVariable {
variable: v,
scope: None,
})
Expand Down
8 changes: 6 additions & 2 deletions src/debugger/watchpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::debugger::register::debug::{
BreakCondition, BreakSize, DebugRegisterNumber, HardwareDebugState,
};
use crate::debugger::unwind::FrameID;
use crate::debugger::variable::select::{DqeResult, SelectExpressionEvaluator, DQE};
use crate::debugger::variable::select::{ScopedVariable, SelectExpressionEvaluator, DQE};
use crate::debugger::variable::{ScalarVariable, SupportedScalar, VariableIR, VariableIdentity};
use crate::debugger::Error::Hook;
use crate::debugger::{Debugger, Error, ExplorationContext, Tracee};
Expand Down Expand Up @@ -222,7 +222,11 @@ where
}

impl Watchpoint {
fn evaluate_dqe(debugger: &Debugger, expr_source: &str, dqe: DQE) -> Result<DqeResult, Error> {
fn evaluate_dqe(
debugger: &Debugger,
expr_source: &str,
dqe: DQE,
) -> Result<ScopedVariable, Error> {
let expr_evaluator = SelectExpressionEvaluator::new(debugger, dqe);

// trying to evaluate at variables first,
Expand Down
13 changes: 3 additions & 10 deletions src/oracle/builtin/tokio.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::debugger::unwind::{Backtrace, FrameSpan};
use crate::debugger::variable::select::{VariableSelector, DQE};
use crate::debugger::variable::select::{Selector, DQE};
use crate::debugger::variable::{ScalarVariable, StructVariable, SupportedScalar, VariableIR};
use crate::debugger::CreateTransparentBreakpointRequest;
use crate::debugger::{Debugger, Error};
Expand Down Expand Up @@ -342,11 +342,7 @@ impl TokioOracle {
fn get_header_from_self(dbg: &mut Debugger) -> Result<Option<(u64, *const ())>, Error> {
let header_pointer_expr = DQE::Field(
DQE::Field(
DQE::Variable(VariableSelector::Name {
var_name: "self".to_string(),
only_local: true,
})
.boxed(),
DQE::Variable(Selector::by_name("self", true)).boxed(),
"ptr".to_string(),
)
.boxed(),
Expand Down Expand Up @@ -410,10 +406,7 @@ impl TokioOracle {

fn on_new(&self, debugger: &mut Debugger) -> Result<(), Error> {
let id_args = debugger.read_argument(DQE::Field(
Box::new(DQE::Variable(VariableSelector::Name {
var_name: "id".to_string(),
only_local: true,
})),
Box::new(DQE::Variable(Selector::by_name("id", true))),
"0".to_string(),
))?;

Expand Down
8 changes: 6 additions & 2 deletions src/oracle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ pub trait Oracle: ConsolePlugin + TuiPlugin {
/// Return oracle name.
fn name(&self) -> &'static str;

/// True if oracle is ready for install on specific debugee. If false then debugger will
/// not use this oracle. Typically, in this method, oracle will check some symbols and
/// True if oracle is ready for install on specific debugee.
/// If false, then the debugger will not use this oracle.
/// Typically, in this method, oracle will check some symbols and
/// make a decision about the possibility of further work.
///
/// # Arguments
Expand All @@ -50,5 +51,8 @@ pub trait Oracle: ConsolePlugin + TuiPlugin {

/// A list of watch_point using by oracle.
/// In debugger watch point implemented by transparent breakpoints.
///
/// FIXME now oracle `watchpoint` name clashes with debugger watchpoint (data breakpoint).
/// Let's rename it.
fn watch_points(self: Arc<Self>) -> Vec<CreateTransparentBreakpointRequest>;
}
Loading

0 comments on commit e8e77d4

Please sign in to comment.