1pub mod attributes;
3
4pub mod evaluate;
6
7use crate::call_stack::MemoryAccess;
8use crate::registers::Registers;
9use anyhow::{anyhow, Result};
10use evaluate::{convert_to_gimli_value, BaseTypeValue, EvaluatorValue};
11use gimli::{
12 AttributeValue::UnitRef,
13 DebuggingInformationEntry, DieReference, Dwarf, Evaluation, EvaluationResult,
14 EvaluationResult::{
15 Complete, RequiresAtLocation, RequiresBaseType, RequiresCallFrameCfa, RequiresEntryValue,
16 RequiresFrameBase, RequiresIndexedAddress, RequiresMemory, RequiresParameterRef,
17 RequiresRegister, RequiresRelocatedAddress, RequiresTls,
18 },
19 Expression, Reader, Unit, UnitOffset,
20};
21use log::{error, info};
22use std::convert::TryInto;
23
24pub fn call_evaluate<R: Reader<Offset = usize>, T: MemoryAccess>(
40 dwarf: &Dwarf<R>,
41 pc: u32,
42 expr: gimli::Expression<R>,
43 frame_base: Option<u64>,
44 unit: &Unit<R>,
45 die: &DebuggingInformationEntry<R>,
46 registers: &Registers,
47 mem: &mut T,
48) -> Result<EvaluatorValue<R>> {
49 if let Ok(Some(tattr)) = die.attr_value(gimli::DW_AT_type) {
50 match tattr {
51 gimli::AttributeValue::UnitRef(offset) => {
52 let die = unit.entry(offset)?;
53 return evaluate(
54 dwarf,
55 unit,
56 pc,
57 expr,
58 frame_base,
59 Some(unit),
60 Some(&die),
61 registers,
62 mem,
63 );
64 }
65 gimli::AttributeValue::DebugInfoRef(di_offset) => {
66 let offset = gimli::UnitSectionOffset::DebugInfoOffset(di_offset);
67 let mut iter = dwarf.debug_info.units();
68 while let Ok(Some(header)) = iter.next() {
69 let type_unit = dwarf.unit(header)?;
70 if let Some(offset) = offset.to_unit_offset(&type_unit) {
71 let die = type_unit.entry(offset)?;
72 return evaluate(
73 dwarf,
74 unit,
75 pc,
76 expr,
77 frame_base,
78 Some(&type_unit),
79 Some(&die),
80 registers,
81 mem,
82 );
83 }
84 }
85
86 error!("Unreachable");
87 return Err(anyhow!("Unreachable"));
88 }
89 attribute => {
90 error!("Unimplemented for attribute {:?}", attribute);
91 return Err(anyhow!("Unimplemented for attribute {:?}", attribute));
92 }
93 };
94 } else if let Ok(Some(die_offset)) = die.attr_value(gimli::DW_AT_abstract_origin) {
95 match die_offset {
96 UnitRef(offset) => {
97 if let Ok(ndie) = unit.entry(offset) {
98 return call_evaluate(dwarf, pc, expr, frame_base, unit, &ndie, registers, mem);
99 }
100 }
101 _ => {
102 error!("Unimplemented");
103 return Err(anyhow!("Unimplemented"));
104 }
105 };
106 }
107
108 error!("Unreachable");
109 Err(anyhow!("Unreachable"))
110}
111
112pub fn evaluate<R: Reader<Offset = usize>, T: MemoryAccess>(
131 dwarf: &Dwarf<R>,
132 unit: &Unit<R>,
133 pc: u32,
134 expr: Expression<R>,
135 frame_base: Option<u64>,
136 type_unit: Option<&gimli::Unit<R>>,
137 type_die: Option<&gimli::DebuggingInformationEntry<'_, '_, R>>,
138 registers: &Registers,
139 mem: &mut T,
140) -> Result<EvaluatorValue<R>> {
141 let pieces = evaluate_pieces(dwarf, unit, pc, expr, frame_base, registers, mem)?;
142 info!("Got pieces");
143 evaluate_value(dwarf, pieces, type_unit, type_die, registers, mem)
144}
145
146pub fn evaluate_value<R: Reader<Offset = usize>, T: MemoryAccess>(
161 dwarf: &Dwarf<R>,
162 pieces: Vec<gimli::Piece<R>>,
163 type_unit: Option<&gimli::Unit<R>>,
164 type_die: Option<&gimli::DebuggingInformationEntry<'_, '_, R>>,
165 registers: &Registers,
166 mem: &mut T,
167) -> Result<EvaluatorValue<R>> {
168 match type_unit {
169 Some(unit) => match type_die {
170 Some(die) => {
171 info!("with type info");
172 return EvaluatorValue::evaluate_variable_with_type(
173 dwarf,
174 registers,
175 mem,
176 &pieces,
177 unit.header.offset(),
178 die.offset(),
179 );
180 }
181 None => (),
182 },
183 None => (),
184 };
185 info!("without type info");
186 EvaluatorValue::evaluate_variable(registers, mem, &pieces)
187}
188
189pub fn evaluate_pieces<R: Reader<Offset = usize>, T: MemoryAccess>(
204 dwarf: &Dwarf<R>,
205 unit: &Unit<R>,
206 pc: u32,
207 expr: Expression<R>,
208 frame_base: Option<u64>,
209 registers: &Registers,
210 mem: &mut T,
211) -> Result<Vec<gimli::Piece<R>>> {
212 let mut eval = expr.evaluation(unit.encoding());
213 let mut result = eval.evaluate()?;
214
215 loop {
216 match result {
217 Complete => break,
218 RequiresMemory {
219 address,
220 size,
221 space: _, base_type,
223 } => match mem.get_address(&(address as u32), size as usize) {
224 Some(data) => {
225 let value = eval_base_type(unit, data, base_type)?;
226 result = eval.resume_with_memory(convert_to_gimli_value(value))?;
227 }
228 None => {
229 return Err(anyhow!("Requires Memory"));
230 }
231 },
232
233 RequiresRegister {
234 register,
235 base_type,
236 } => match registers.get_register_value(®ister.0) {
237 Some(data) => {
238 let bytes = data.to_le_bytes().to_vec();
239 let value = eval_base_type(unit, bytes, base_type)?;
240 result = eval.resume_with_register(convert_to_gimli_value(value))?;
241 }
242 None => {
243 return Err(anyhow!("Requires register {}", register.0));
244 }
245 },
246
247 RequiresFrameBase => {
248 result = eval.resume_with_frame_base(match frame_base {
249 Some(val) => val,
250 None => {
251 error!("Requires frame base");
252 return Err(anyhow!("Requires frame base"));
253 }
254 })?;
255 }
256
257 RequiresTls(_tls) => {
258 error!("Unimplemented");
259 return Err(anyhow!("Unimplemented")); }
261
262 RequiresCallFrameCfa => {
263 result = eval.resume_with_call_frame_cfa(
264 registers.cfa.ok_or_else(|| anyhow!("Requires CFA"))? as u64,
265 )?;
266 }
267
268 RequiresAtLocation(die_ref) => match die_ref {
269 DieReference::UnitRef(unit_offset) => help_at_location(
270 dwarf,
271 unit,
272 pc,
273 &mut eval,
274 &mut result,
275 frame_base,
276 unit_offset,
277 registers,
278 mem,
279 )?,
280
281 DieReference::DebugInfoRef(debug_info_offset) => {
282 let unit_header = dwarf.debug_info.header_from_offset(debug_info_offset)?;
283 if let Some(unit_offset) = debug_info_offset.to_unit_offset(&unit_header) {
284 let new_unit = dwarf.unit(unit_header)?;
285 help_at_location(
286 dwarf,
287 &new_unit,
288 pc,
289 &mut eval,
290 &mut result,
291 frame_base,
292 unit_offset,
293 registers,
294 mem,
295 )?;
296 } else {
297 return Err(anyhow!("Could not find at location"));
298 }
299 }
300 },
301
302 RequiresEntryValue(entry) => {
303 let entry_value = evaluate(
304 dwarf, unit, pc, entry, frame_base, None, None, registers, mem,
305 )?;
306
307 result = eval.resume_with_entry_value(convert_to_gimli_value(match entry_value
308 .to_value()
309 {
310 Some(val) => val,
311 None => {
312 error!("Optimized Out");
313 return Err(anyhow!("Optimized Out"));
314 }
315 }))?;
316 }
317
318 RequiresParameterRef(unit_offset) => {
319 let die = unit.entry(unit_offset)?;
320 let call_value = match die.attr_value(gimli::DW_AT_call_value)? {
321 Some(val) => val,
322 None => {
323 error!("Could not find required paramter");
324 return Err(anyhow!("Could not find required parameter"));
325 }
326 };
327
328 let expr = match call_value.exprloc_value() {
329 Some(val) => val,
330 None => {
331 error!("Could not find required paramter");
332 return Err(anyhow!("Could not find required parameter"));
333 }
334 };
335 let value = evaluate(
336 dwarf,
337 unit,
338 pc,
339 expr,
340 frame_base,
341 Some(unit),
342 Some(&die),
343 registers,
344 mem,
345 )?;
346
347 if let EvaluatorValue::Value(BaseTypeValue::U64(val), _) = value {
348 result = eval.resume_with_parameter_ref(val)?;
349 } else {
350 error!("Could not find required paramter");
351 return Err(anyhow!("Could not find required parameter"));
352 }
353 }
354
355 RequiresRelocatedAddress(_num) => {
356 error!("Unimplemented");
357 return Err(anyhow!("Unimplemented"));
358 }
360
361 RequiresIndexedAddress {
362 index: _,
363 relocate: _,
364 } => {
365 error!("Unimplemented");
367 return Err(anyhow!("Unimplemented"));
368 }
370
371 RequiresBaseType(unit_offset) => {
372 let die = unit.entry(unit_offset)?;
373 let mut attrs = die.attrs();
374 while let Some(attr) = match attrs.next() {
375 Ok(val) => val,
376 Err(err) => {
377 error!("{:?}", err);
378 return Err(anyhow!("{:?}", err));
379 }
380 } {
381 println!("Attribute name = {:?}", attr.name());
382 println!("Attribute value = {:?}", attr.value());
383 }
384
385 error!("Unimplemented");
386 return Err(anyhow!("Unimplemented"));
387 }
388 };
389 }
390
391 Ok(eval.result())
392}
393
394fn eval_base_type<R>(
405 unit: &gimli::Unit<R>,
406 data: Vec<u8>,
407 base_type: gimli::UnitOffset<usize>,
408) -> Result<BaseTypeValue>
409where
410 R: Reader<Offset = usize>,
411{
412 if base_type.0 == 0 {
413 let value = match data.len() {
415 0 => 0,
416 1 => u8::from_le_bytes(match data.try_into() {
417 Ok(val) => val,
418 Err(err) => {
419 error!("{:?}", err);
420 return Err(anyhow!("{:?}", err));
421 }
422 }) as u64,
423 2 => u16::from_le_bytes(match data.try_into() {
424 Ok(val) => val,
425 Err(err) => {
426 error!("{:?}", err);
427 return Err(anyhow!("{:?}", err));
428 }
429 }) as u64,
430 4 => u32::from_le_bytes(match data.try_into() {
431 Ok(val) => val,
432 Err(err) => {
433 error!("{:?}", err);
434 return Err(anyhow!("{:?}", err));
435 }
436 }) as u64,
437 8 => u64::from_le_bytes(match data.try_into() {
438 Ok(val) => val,
439 Err(err) => {
440 error!("{:?}", err);
441 return Err(anyhow!("{:?}", err));
442 }
443 }),
444 _ => {
445 error!("Unreachable");
446 return Err(anyhow!("Unreachable"));
447 }
448 };
449 return Ok(BaseTypeValue::Generic(value));
450 }
451 let die = unit.entry(base_type)?;
452
453 if die.tag() != gimli::DW_TAG_base_type {
455 error!("Requires at the die has tag DW_TAG_base_type");
456 return Err(anyhow!("Requires at the die has tag DW_TAG_base_type"));
457 }
458
459 let encoding = match die.attr_value(gimli::DW_AT_encoding)? {
460 Some(gimli::AttributeValue::Encoding(dwate)) => dwate,
461 _ => {
462 error!("Expected base type die to have attribute DW_AT_encoding");
463 return Err(anyhow!(
464 "Expected base type die to have attribute DW_AT_encoding"
465 ));
466 }
467 };
468
469 BaseTypeValue::parse_base_type(data, encoding)
470}
471
472fn help_at_location<R: Reader<Offset = usize>, T: MemoryAccess>(
489 dwarf: &Dwarf<R>,
490 unit: &Unit<R>,
491 pc: u32,
492 eval: &mut Evaluation<R>,
493 result: &mut EvaluationResult<R>,
494 frame_base: Option<u64>,
495 unit_offset: UnitOffset<usize>,
496 registers: &Registers,
497 mem: &mut T,
498) -> Result<()>
499where
500 R: Reader<Offset = usize>,
501{
502 let die = unit.entry(unit_offset)?;
503 let location = match die.attr_value(gimli::DW_AT_location)? {
504 Some(val) => val,
505 None => {
506 error!("Could not find location attribute");
507 return Err(anyhow!("Could not find location attribute"));
508 }
509 };
510 if let Some(expr) = location.exprloc_value() {
511 let val = call_evaluate(dwarf, pc, expr, frame_base, unit, &die, registers, mem)?;
512
513 if let EvaluatorValue::Bytes(b) = val {
514 *result = eval.resume_with_at_location(b)?;
515 Ok(())
516 } else {
517 error!("Error expected bytes");
518 Err(anyhow!("Error expected bytes"))
519 }
520 } else {
521 error!("die has no at location");
522 Err(anyhow!("die has no at location"))
523 }
524}