1use crate::debugger::context::gcx;
2use crate::debugger::debugee::dwarf::DebugInformation;
3use crate::debugger::debugee::dwarf::eval::{EvaluationContext, ExpressionEvaluator};
4use crate::debugger::debugee::dwarf::r#type::ComplexType;
5use crate::debugger::debugee::dwarf::unit::BsUnit;
6use crate::debugger::debugee::dwarf::unit::die_ref::{Argument, FatDieRef, Typed, Variable};
7use crate::debugger::error::Error;
8use crate::debugger::error::Error::FunctionNotFound;
9use crate::debugger::variable::dqe::{DataCast, Dqe, PointerCast, Selector};
10use crate::debugger::variable::value::Value;
11use crate::debugger::variable::value::parser::{ParseContext, ValueModifiers, ValueParser};
12use crate::debugger::variable::r#virtual::VirtualVariableDie;
13use crate::debugger::variable::{Identity, ObjectBinaryRepr};
14use crate::debugger::{Debugger, read_memory_by_pid};
15use crate::{ref_resolve_unit_call, resolve_unit_call, weak_error};
16use bytes::Bytes;
17use gimli::Range;
18use std::fmt::Debug;
19use std::rc::Rc;
20
21#[derive(Debug, Clone, Copy, PartialEq)]
22pub enum QueryResultKind {
23 Root,
25 Expression,
27}
28
29#[derive(Clone)]
31pub struct QueryResult<'a> {
32 pub value: Option<Value>,
34 scope: Option<Box<[Range]>>,
35 kind: QueryResultKind,
36 base_type: Rc<ComplexType>,
37 identity: Identity,
38 evcx_builder: EvaluationContextBuilder<'a>,
39}
40
41impl QueryResult<'_> {
42 pub fn unit(&self) -> &BsUnit {
44 self.evcx_builder.unit()
45 }
46
47 #[inline(always)]
49 pub fn value(&self) -> &Value {
50 self.value.as_ref().expect("should be `Some`")
51 }
52
53 #[inline(always)]
55 pub fn into_value(mut self) -> Value {
56 self.value.take().expect("should be `Some`")
57 }
58
59 #[inline(always)]
61 pub fn into_identified_value(mut self) -> (Identity, Value) {
62 (self.identity, self.value.take().expect("should be `Some`"))
63 }
64
65 #[inline(always)]
69 pub fn kind(&self) -> QueryResultKind {
70 self.kind
71 }
72
73 #[inline(always)]
75 pub fn type_graph(&self) -> &ComplexType {
76 self.base_type.as_ref()
77 }
78
79 #[inline(always)]
81 pub fn identity(&self) -> &Identity {
82 &self.identity
83 }
84
85 #[inline(always)]
88 pub fn scope(&self) -> &Option<Box<[Range]>> {
89 &self.scope
90 }
91
92 pub fn with_evcx<T, F: FnOnce(&EvaluationContext) -> T>(&self, cb: F) -> T {
94 self.evcx_builder.with_evcx(cb)
95 }
96
97 pub fn modify_value<F: FnOnce(&ParseContext, Value) -> Option<Value>>(
99 mut self,
100 cb: F,
101 ) -> Option<Self> {
102 let value = self.value.take().expect("should be `Some`");
103 let type_graph = self.type_graph();
104 let eval_cb = |evcx: &EvaluationContext| {
105 let pcx = &ParseContext { evcx, type_graph };
106 cb(pcx, value)
107 };
108 let new_value = self.evcx_builder.with_evcx(eval_cb)?;
109 self.value = Some(new_value);
110 Some(self)
111 }
112}
113
114impl PartialEq for QueryResult<'_> {
115 fn eq(&self, other: &Self) -> bool {
116 self.value == other.value && self.identity == other.identity
117 }
118}
119
120#[derive(Clone)]
121enum EvaluationContextBuilder<'a> {
122 Ready(&'a Debugger, ExpressionEvaluator<'a>),
123 Virtual {
124 debugger: &'a Debugger,
125 debug_info: &'a DebugInformation,
126 unit: &'a BsUnit,
127 },
128}
129
130impl EvaluationContextBuilder<'_> {
131 pub fn unit(&self) -> &BsUnit {
132 match self {
133 EvaluationContextBuilder::Ready(_, evaluator) => evaluator.unit(),
134 EvaluationContextBuilder::Virtual { unit, .. } => unit,
135 }
136 }
137
138 fn with_evcx<T, F: FnOnce(&EvaluationContext) -> T>(&self, cb: F) -> T {
139 let evaluator;
140 let evcx = match self {
141 EvaluationContextBuilder::Ready(debugger, evaluator) => EvaluationContext {
142 evaluator,
143 ecx: debugger.ecx(),
144 },
145 EvaluationContextBuilder::Virtual {
146 debugger,
147 debug_info,
148 unit,
149 ..
150 } => {
151 let dwarf = debug_info.dwarf();
152 evaluator = resolve_unit_call!(
153 dwarf,
154 unit,
155 evaluator,
156 &debugger.debugee,
157 debug_info.dwarf()
158 );
159 EvaluationContext {
160 evaluator: &evaluator,
161 ecx: debugger.ecx(),
162 }
163 }
164 };
165 cb(&evcx)
166 }
167}
168
169#[macro_export]
170macro_rules! type_from_cache {
171 ($variable: expr, $cache: expr) => {
172 $variable
173 .deref_ensure()
174 .type_ref()
175 .and_then(
176 |type_ref| match $cache.entry(($variable.unit().id, type_ref)) {
177 std::collections::hash_map::Entry::Occupied(o) => {
178 Some(std::rc::Rc::clone(o.get()))
179 }
180 std::collections::hash_map::Entry::Vacant(v) => $variable.r#type().map(|t| {
181 let t = std::rc::Rc::new(t);
182 v.insert(t.clone());
183 t
184 }),
185 },
186 )
187 .ok_or_else(|| {
188 $crate::debugger::variable::value::ParsingError::Assume(
189 $crate::debugger::variable::value::AssumeError::NoType("variable"),
190 )
191 })
192 };
193}
194
195pub struct DqeExecutor<'a> {
197 debugger: &'a Debugger,
198}
199
200impl<'dbg> DqeExecutor<'dbg> {
201 pub fn new(debugger: &'dbg Debugger) -> Self {
202 Self { debugger }
203 }
204
205 fn variable_die_by_selector(
206 &self,
207 selector: &Selector,
208 ) -> Result<Vec<FatDieRef<'dbg, Variable>>, Error> {
209 let ecx = self.debugger.ecx();
210
211 let debugee = &self.debugger.debugee;
212 let (current_func, _) = debugee
213 .debug_info(ecx.location().pc)?
214 .find_function_by_pc(ecx.location().global_pc)?
215 .ok_or(FunctionNotFound(ecx.location().global_pc))?;
216
217 let vars = match selector {
218 Selector::Name {
219 var_name,
220 local_only: local,
221 } => {
222 let local_variants = current_func
223 .local_variable(ecx.location().global_pc, var_name)
224 .map(|v| vec![v])
225 .unwrap_or_default();
226
227 let local = *local;
228
229 if !local && local_variants.is_empty() {
232 debugee
233 .debug_info(ecx.location().pc)?
234 .find_variables(ecx.location(), var_name)?
235 } else {
236 local_variants
237 }
238 }
239 Selector::Any => current_func.local_variables(ecx.location().global_pc),
240 };
241
242 Ok(vars)
243 }
244
245 fn param_die_by_selector(
246 &self,
247 selector: &Selector,
248 ) -> Result<Vec<FatDieRef<'dbg, Argument>>, Error> {
249 let ecx_loc = self.debugger.ecx().location();
250 let debugee = &self.debugger.debugee;
251 let (current_function, _) = debugee
252 .debug_info(ecx_loc.pc)?
253 .find_function_by_pc(ecx_loc.global_pc)?
254 .ok_or(FunctionNotFound(ecx_loc.global_pc))?;
255 let params = current_function.parameters();
256 let params = match selector {
257 Selector::Name { var_name, .. } => params
258 .into_iter()
259 .filter(|r| r.deref_ensure().name().as_ref() == Some(var_name))
260 .collect::<Vec<_>>(),
261 Selector::Any => params,
262 };
263 Ok(params)
264 }
265
266 fn apply_select_die(
268 &self,
269 selector: &Selector,
270 on_args: bool,
271 ) -> Result<Vec<QueryResult<'dbg>>, Error> {
272 fn root_from_die<'dbg, H: Typed>(
273 debugger: &'dbg Debugger,
274 die_ref: &FatDieRef<'dbg, H>,
275 ranges: Option<Box<[Range]>>,
276 ) -> Option<QueryResult<'dbg>> {
277 let r#type = gcx().with_type_cache(|tc| weak_error!(type_from_cache!(die_ref, tc)))?;
278
279 let evaluator = ref_resolve_unit_call!(
280 die_ref,
281 evaluator,
282 &debugger.debugee,
283 die_ref.debug_info.dwarf()
284 );
285 let context_builder = EvaluationContextBuilder::Ready(debugger, evaluator);
286
287 let value = context_builder.with_evcx(|evcx| {
288 let data = die_ref.read_value(debugger.ecx(), &debugger.debugee, &r#type);
289
290 let parser = ValueParser::new();
291 let pcx = &ParseContext {
292 evcx,
293 type_graph: &r#type,
294 };
295 let modifiers = &ValueModifiers::from_identity(pcx, Identity::from_die(die_ref));
296 parser.parse(pcx, data, modifiers)
297 })?;
298
299 Some(QueryResult {
300 value: Some(value),
301 scope: ranges,
302 kind: QueryResultKind::Root,
303 base_type: r#type,
304 identity: Identity::from_die(die_ref),
305 evcx_builder: context_builder,
306 })
307 }
308
309 match on_args {
310 true => {
311 let params = self.param_die_by_selector(selector)?;
312 Ok(params
313 .iter()
314 .filter_map(|arg_die| {
315 root_from_die(
316 self.debugger,
317 arg_die,
318 arg_die.max_range().map(|r| {
319 let scope: Box<[Range]> = Box::new([r]);
320 scope
321 }),
322 )
323 })
324 .collect())
325 }
326 false => {
327 let vars = self.variable_die_by_selector(selector)?;
328 Ok(vars
329 .iter()
330 .filter_map(|var_die| root_from_die(self.debugger, var_die, var_die.ranges()))
331 .collect())
332 }
333 }
334 }
335
336 fn apply_ptr_cast_op(&self, ptr_cast: &PointerCast) -> Result<QueryResult<'dbg>, Error> {
339 let mut var_die = VirtualVariableDie::workpiece();
340 let var_die_ref = var_die.init_with_type(&self.debugger.debugee, &ptr_cast.ty)?;
341
342 let r#type = gcx().with_type_cache(|tc| type_from_cache!(var_die_ref, tc))?;
343
344 let context_builder = EvaluationContextBuilder::Virtual {
345 debugger: self.debugger,
346 debug_info: var_die_ref.debug_info,
347 unit: var_die_ref.unit(),
348 };
349
350 let value = context_builder.with_evcx(|evcx| {
351 let data = ObjectBinaryRepr {
352 raw_data: Bytes::copy_from_slice(&ptr_cast.ptr.to_le_bytes()),
353 address: None,
354 size: std::mem::size_of::<usize>(),
355 };
356
357 let parser = ValueParser::new();
358 let pcx = &ParseContext {
359 evcx,
360 type_graph: &r#type,
361 };
362 parser.parse(pcx, Some(data), &ValueModifiers::default())
363 });
364
365 Ok(QueryResult {
366 value,
367 scope: None,
368 kind: QueryResultKind::Expression,
369 base_type: r#type,
370 identity: Identity::default(),
371 evcx_builder: context_builder,
372 })
373 }
374
375 fn apply_data_cast(&self, data_cast: &DataCast) -> Result<QueryResult<'dbg>, Error> {
378 let mut var_die = VirtualVariableDie::workpiece();
379 let debug_info = self
380 .debugger
381 .debugee
382 .debug_info_from_file(&data_cast.ty_debug_info)?;
383 let var_die_ref = var_die.init_with_known_type(
384 debug_info,
385 data_cast.ty_unit_off,
386 data_cast.ty_die_off,
387 )?;
388
389 let r#type = gcx().with_type_cache(|tc| type_from_cache!(var_die_ref, tc))?;
390
391 let context_builder = EvaluationContextBuilder::Virtual {
392 debugger: self.debugger,
393 debug_info: var_die_ref.debug_info,
394 unit: var_die_ref.unit(),
395 };
396
397 let value = context_builder.with_evcx(|evcx| {
398 let size = r#type.type_size_in_bytes(evcx, r#type.root())? as usize;
399
400 let raw_data = weak_error!(read_memory_by_pid(
401 evcx.ecx.pid_on_focus(),
402 data_cast.ptr,
403 size
404 ))?;
405
406 let data = ObjectBinaryRepr {
407 raw_data: Bytes::copy_from_slice(&raw_data),
408 address: Some(data_cast.ptr),
409 size,
410 };
411
412 let parser = ValueParser::new();
413 let pcx = &ParseContext {
414 evcx,
415 type_graph: &r#type,
416 };
417 parser.parse(pcx, Some(data), &ValueModifiers::default())
418 });
419
420 Ok(QueryResult {
421 value,
422 scope: None,
423 kind: QueryResultKind::Expression,
424 base_type: r#type,
425 identity: Identity::default(),
426 evcx_builder: context_builder,
427 })
428 }
429
430 fn apply_dqe(&self, dqe: &Dqe, on_args: bool) -> Result<Vec<QueryResult<'dbg>>, Error> {
431 match dqe {
432 Dqe::Variable(selector) => self.apply_select_die(selector, on_args),
433 Dqe::PtrCast(ptr_cast) => self.apply_ptr_cast_op(ptr_cast).map(|q| vec![q]),
434 Dqe::DataCast(data_cast) => self.apply_data_cast(data_cast).map(|q| vec![q]),
435 Dqe::Field(next, field) => {
436 let results = self.apply_dqe(next, on_args)?;
437 Ok(results
438 .into_iter()
439 .filter_map(|q| q.modify_value(|_, val| val.field(field)))
440 .collect())
441 }
442 Dqe::Index(next, idx) => {
443 let results = self.apply_dqe(next, on_args)?;
444 Ok(results
445 .into_iter()
446 .filter_map(|q| q.modify_value(|_, val| val.index(idx)))
447 .collect())
448 }
449 Dqe::Slice(next, left, right) => {
450 let results = self.apply_dqe(next, on_args)?;
451 Ok(results
452 .into_iter()
453 .filter_map(|q| q.modify_value(|pcx, val| val.slice(pcx, *left, *right)))
454 .collect())
455 }
456 Dqe::Deref(next) => {
457 let results = self.apply_dqe(next, on_args)?;
458 Ok(results
459 .into_iter()
460 .filter_map(|q| q.modify_value(|pcx, val| val.deref(pcx)))
461 .collect())
462 }
463 Dqe::Address(next) => {
464 let results = self.apply_dqe(next, on_args)?;
465 Ok(results
466 .into_iter()
467 .filter_map(|q| q.modify_value(|pcx, val| val.address(pcx)))
468 .collect())
469 }
470 Dqe::Canonic(next) => {
471 let results = self.apply_dqe(next, on_args)?;
472 Ok(results
473 .into_iter()
474 .filter_map(|q| q.modify_value(|_, val| Some(val.canonic())))
475 .collect())
476 }
477 }
478 }
479
480 pub fn query(&self, dqe: &Dqe) -> Result<Vec<QueryResult<'dbg>>, Error> {
482 self.apply_dqe(dqe, false)
483 }
484
485 pub fn query_names(&self, dqe: &Dqe) -> Result<Vec<String>, Error> {
493 match dqe {
494 Dqe::Variable(selector) => {
495 let vars = self.variable_die_by_selector(selector)?;
496 Ok(vars
497 .into_iter()
498 .filter_map(|die_ref| die_ref.deref_ensure().name())
499 .collect())
500 }
501 _ => unreachable!("unexpected expression variant"),
502 }
503 }
504
505 pub fn query_arguments(&self, dqe: &Dqe) -> Result<Vec<QueryResult<'dbg>>, Error> {
507 self.apply_dqe(dqe, true)
508 }
509
510 pub fn query_arguments_names(&self, dqe: &Dqe) -> Result<Vec<String>, Error> {
512 match dqe {
513 Dqe::Variable(selector) => {
514 let params = self.param_die_by_selector(selector)?;
515 Ok(params
516 .into_iter()
517 .filter_map(|r| r.deref_ensure().name())
518 .collect())
519 }
520 _ => unreachable!("unexpected expression variant"),
521 }
522 }
523}