1use std::cell::{OnceCell, Ref, RefCell};
2use std::ffi::CStr;
3use std::path::{Path, PathBuf};
4use std::rc::Weak;
5use std::{collections::HashMap, ops::AddAssign, rc::Rc};
6
7use bytemuck::Pod;
8use bytes::Bytes;
9use gimli::{
10 DW_AT_abstract_origin, DW_AT_bit_offset, DW_AT_bit_size, DW_AT_byte_size, DW_AT_call_file,
11 DW_AT_call_line, DW_AT_comp_dir, DW_AT_data_bit_offset, DW_AT_decl_file, DW_AT_decl_line,
12 DW_AT_frame_base, DW_AT_high_pc, DW_AT_location, DW_AT_low_pc, DW_AT_name, DW_AT_ranges,
13 DW_AT_sibling, DW_AT_specification, DW_AT_stmt_list, DW_AT_type, DW_FORM_addr, DW_FORM_block,
14 DW_FORM_block1, DW_FORM_block2, DW_FORM_block4, DW_FORM_data1, DW_FORM_data2, DW_FORM_data4,
15 DW_FORM_data8, DW_FORM_exprloc, DW_FORM_flag, DW_FORM_flag_present, DW_FORM_indirect,
16 DW_FORM_ref_addr, DW_FORM_ref_udata, DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8,
17 DW_FORM_sdata, DW_FORM_sec_offset, DW_FORM_string, DW_FORM_strp, DW_FORM_udata,
18 DW_LNE_define_file, DW_LNE_end_sequence, DW_LNE_set_address, DW_LNE_set_discriminator,
19 DW_LNS_advance_line, DW_LNS_advance_pc, DW_LNS_const_add_pc, DW_LNS_copy,
20 DW_LNS_fixed_advance_pc, DW_LNS_negate_stmt, DW_LNS_set_basic_block, DW_LNS_set_column,
21 DW_LNS_set_epilogue_begin, DW_LNS_set_file, DW_LNS_set_isa, DW_LNS_set_prologue_end, DW_OP_abs,
22 DW_OP_addr, DW_OP_and, DW_OP_bit_piece, DW_OP_bra, DW_OP_breg0, DW_OP_breg31, DW_OP_bregx,
23 DW_OP_call_frame_cfa, DW_OP_call_ref, DW_OP_call2, DW_OP_call4, DW_OP_const1s, DW_OP_const1u,
24 DW_OP_const2s, DW_OP_const2u, DW_OP_const4s, DW_OP_const4u, DW_OP_const8s, DW_OP_const8u,
25 DW_OP_consts, DW_OP_constu, DW_OP_deref, DW_OP_deref_size, DW_OP_div, DW_OP_drop, DW_OP_dup,
26 DW_OP_eq, DW_OP_fbreg, DW_OP_form_tls_address, DW_OP_ge, DW_OP_gt, DW_OP_implicit_value,
27 DW_OP_le, DW_OP_lit0, DW_OP_lit31, DW_OP_lt, DW_OP_minus, DW_OP_mod, DW_OP_mul, DW_OP_ne,
28 DW_OP_neg, DW_OP_nop, DW_OP_not, DW_OP_or, DW_OP_over, DW_OP_pick, DW_OP_piece, DW_OP_plus,
29 DW_OP_plus_uconst, DW_OP_push_object_address, DW_OP_reg0, DW_OP_reg31, DW_OP_regx, DW_OP_rot,
30 DW_OP_shl, DW_OP_shr, DW_OP_shra, DW_OP_skip, DW_OP_stack_value, DW_OP_swap, DW_OP_xderef,
31 DW_OP_xderef_size, DW_OP_xor, DW_TAG_formal_parameter, DW_TAG_inlined_subroutine,
32 DW_TAG_subprogram, DW_TAG_variable, DwForm, DwLne, DwLns, DwOp,
33};
34use multimap::MultiMap;
35use typed_builder::TypedBuilder;
36
37use super::bit::from_bytes;
38use super::breakpoint::{CallFrameInformation, parse_eh_hdr};
39use super::elf::Elf;
40use super::process::Process;
41use super::register_info::{RegisterId, register_info_by_dwarf};
42use super::registers::{RegisterValue, Registers};
43use super::sdb_error::SdbError;
44use super::types::SdbType;
45use super::types::{FileAddress, VirtualAddress};
46
47type AbbrevTable = HashMap<u64, Rc<Abbrev>>;
48
49#[derive(Debug, Clone)]
50pub struct SourceLocation {
51 pub file: Rc<LineTableFile>,
52 pub line: u64,
53}
54
55#[derive(Debug, Clone, TypedBuilder, Default)]
56pub struct LineTableEntry {
57 #[builder(default = FileAddress::null())]
58 pub address: FileAddress,
59 #[builder(default = 1)]
60 pub file_index: u64,
61 #[builder(default = 1)]
62 pub line: u64,
63 #[builder(default = 0)]
64 pub column: u64,
65 #[builder(default = false)]
66 pub is_stmt: bool,
67 #[builder(default = false)]
68 pub basic_block_start: bool,
69 #[builder(default = false)]
70 pub end_sequence: bool,
71 #[builder(default = false)]
72 pub prologue_end: bool,
73 #[builder(default = false)]
74 pub epilogue_begin: bool,
75 #[builder(default = 0)]
76 pub discriminator: u64,
77 #[builder(default = None)]
78 pub file_entry: Option<Rc<LineTableFile>>,
79}
80
81impl PartialEq for LineTableEntry {
82 fn eq(&self, other: &Self) -> bool {
83 self.address == other.address
84 && self.file_index == other.file_index
85 && self.line == other.line
86 && self.column == other.column
87 && self.discriminator == other.discriminator
88 }
89}
90
91impl Eq for LineTableEntry {}
92
93#[derive(Debug, Clone, Default)]
94pub struct LineTableIter {
95 table: Rc<LineTable>,
96 current: Option<LineTableEntry>,
97 registers: LineTableEntry,
98 pos: Bytes,
99}
100
101impl PartialEq for LineTableIter {
102 fn eq(&self, other: &Self) -> bool {
103 self.current == other.current && self.pos == other.pos
104 }
105}
106
107impl LineTableIter {
108 pub fn new(table: &Rc<LineTable>) -> Result<Self, SdbError> {
109 let registers = LineTableEntry::builder()
110 .is_stmt(table.default_is_stmt)
111 .build();
112 let mut ret = Self {
113 table: table.clone(),
114 current: None,
115 registers,
116 pos: table.data.clone(),
117 };
118 ret.step()?;
119 Ok(ret)
120 }
121
122 pub fn step(&mut self) -> Result<(), SdbError> {
123 if self.pos.is_empty() {
124 self.pos = Bytes::new();
125 return Ok(());
126 }
127 let mut emitted;
128 loop {
129 emitted = self.execute_instruction()?;
130 if emitted {
131 break;
132 }
133 }
134 self.current.as_mut().unwrap().file_entry = Some(Rc::new(
135 self.table.file_names()[self.get_current().file_index as usize - 1].clone(),
136 ));
137 Ok(())
138 }
139
140 pub fn is_end(&self) -> bool {
141 self.pos.is_empty()
142 }
143
144 pub fn get_current(&self) -> &LineTableEntry {
145 self.current.as_ref().unwrap()
146 }
147
148 #[allow(non_upper_case_globals)]
149 pub fn execute_instruction(&mut self) -> Result<bool, SdbError> {
150 let elf = self.table.cu().dwarf_info().elf_file();
151 let mut cursor = Cursor::new(&self.pos.slice(
152 ..(self.table.data.as_ptr() as usize + self.table.data.len()
153 - self.pos.as_ptr() as usize),
154 ));
155 let opcode = cursor.u8();
156 let mut emitted = false;
157 if opcode > 0 && opcode < self.table.opcode_base {
158 match DwLns(opcode) {
159 DW_LNS_copy => {
160 self.current = Some(self.registers.clone());
161 self.registers.basic_block_start = false;
162 self.registers.prologue_end = false;
163 self.registers.epilogue_begin = false;
164 self.registers.discriminator = 0;
165 emitted = true;
166 }
167 DW_LNS_advance_pc => {
168 self.registers.address += cursor.uleb128() as i64;
169 }
170 DW_LNS_advance_line => {
171 self.registers.line =
172 (self.registers.line as i64).wrapping_add(cursor.sleb128()) as u64;
173 }
174 DW_LNS_set_file => {
175 self.registers.file_index = cursor.uleb128();
176 }
177 DW_LNS_set_column => {
178 self.registers.column = cursor.uleb128();
179 }
180 DW_LNS_negate_stmt => {
181 self.registers.is_stmt = !self.registers.is_stmt;
182 }
183 DW_LNS_set_basic_block => {
184 self.registers.basic_block_start = true;
185 }
186 DW_LNS_const_add_pc => {
187 self.registers.address +=
188 ((255 - self.table.opcode_base) / self.table.line_range) as i64;
189 }
190 DW_LNS_fixed_advance_pc => {
191 self.registers.address += cursor.u16() as i64;
192 }
193 DW_LNS_set_prologue_end => {
194 self.registers.prologue_end = true;
195 }
196 DW_LNS_set_epilogue_begin => {
197 self.registers.epilogue_begin = true;
198 }
199 DW_LNS_set_isa => {
200 }
202 _ => {
203 return SdbError::err("Unexpected standard opcode");
204 }
205 }
206 } else if opcode == 0 {
207 let _length = cursor.uleb128();
208 let extended_opcode = cursor.u8();
209 match DwLne(extended_opcode) {
210 DW_LNE_end_sequence => {
211 self.registers.end_sequence = true;
212 self.current = Some(self.registers.clone());
213 self.registers = LineTableEntry::builder()
214 .is_stmt(self.table.default_is_stmt)
215 .build();
216 emitted = true;
217 }
218 DW_LNE_set_address => {
219 self.registers.address = FileAddress::new(&elf, cursor.u64());
220 }
221 DW_LNE_define_file => {
222 let compilation_dir = self
223 .table
224 .cu()
225 .root()
226 .index(DW_AT_comp_dir.0 as u64)?
227 .as_string()?;
228 let file = parse_line_table_file(
229 &mut cursor,
230 &compilation_dir,
231 &self.table.include_directories,
232 );
233 self.table.file_names.borrow_mut().push(file);
234 }
235 DW_LNE_set_discriminator => {
236 self.registers.discriminator = cursor.uleb128();
237 }
238 _ => {
239 return SdbError::err("Unexpected extended opcode");
240 }
241 }
242 } else {
243 let adjusted_opcode = opcode - self.table.opcode_base;
244 self.registers.address += (adjusted_opcode / self.table.line_range) as i64;
245 self.registers.line = self.registers.line.wrapping_add(
246 ((self.table.line_base as i16)
247 .wrapping_add((adjusted_opcode % self.table.line_range) as i16))
248 as u64,
249 );
250 self.current = Some(self.registers.clone());
251 self.registers.basic_block_start = false;
252 self.registers.prologue_end = false;
253 self.registers.epilogue_begin = false;
254 self.registers.discriminator = 0;
255 emitted = true;
256 }
257 self.pos = cursor.position();
258 Ok(emitted)
259 }
260}
261
262impl Iterator for LineTableIter {
263 type Item = LineTableEntry;
264
265 fn next(&mut self) -> Option<Self::Item> {
266 if !self.is_end() {
267 let ret = self.get_current().clone();
268 self.step().unwrap();
269 Some(ret)
270 } else {
271 None
272 }
273 }
274}
275
276#[derive(Debug, Clone)]
277pub struct LineTableFile {
278 pub path: PathBuf,
279 pub modification_time: u64,
280 pub file_length: u64,
281}
282
283#[derive(Debug, Default)]
284pub struct LineTable {
285 data: Bytes,
286 cu: Weak<CompileUnit>,
287 default_is_stmt: bool,
288 line_base: i8,
289 line_range: u8,
290 opcode_base: u8,
291 include_directories: Vec<PathBuf>,
292 file_names: RefCell<Vec<LineTableFile>>,
293}
294
295impl LineTable {
296 pub fn get_entry_by_address(
297 self: &Rc<Self>,
298 address: &FileAddress,
299 ) -> Result<LineTableIter, SdbError> {
300 let mut prev = LineTableIter::new(self)?;
301 if prev.current.is_none() {
302 return Ok(LineTableIter::default());
303 }
304 let mut it = prev.clone();
305 it.step()?;
306 while it.current.is_some() {
307 if prev.get_current().address <= *address
308 && it.get_current().address > *address
309 && !prev.get_current().end_sequence
310 {
311 return Ok(prev);
312 }
313 prev = it.clone();
314 it.step()?;
315 }
316 Ok(LineTableIter::default())
317 }
318
319 pub fn get_entries_by_line(
320 self: &Rc<Self>,
321 path: &Path,
322 line: u64,
323 ) -> Result<Vec<LineTableIter>, SdbError> {
324 let mut entries = Vec::new();
325 let mut it = LineTableIter::new(self)?;
326 while !it.is_end() {
327 let entry_path = &it.get_current().file_entry.as_ref().unwrap().path;
328 #[allow(clippy::collapsible_if)]
329 if it.get_current().line == line {
330 if (path.is_absolute() && entry_path == path)
331 || (path.is_relative() && entry_path.ends_with(path))
332 {
333 entries.push(it.clone());
334 }
335 }
336 it.step()?;
337 }
338 Ok(entries)
339 }
340
341 pub fn iter(self: &Rc<Self>) -> Result<LineTableIter, SdbError> {
342 LineTableIter::new(self)
343 }
344
345 #[allow(clippy::too_many_arguments)]
346 pub fn new(
347 data: Bytes,
348 cu: &Rc<CompileUnit>,
349 default_is_stmt: bool,
350 line_base: i8,
351 line_range: u8,
352 opcode_base: u8,
353 include_directories: Vec<PathBuf>,
354 file_names: Vec<LineTableFile>,
355 ) -> Rc<Self> {
356 Rc::new(Self {
357 data,
358 cu: Rc::downgrade(cu),
359 default_is_stmt,
360 line_base,
361 line_range,
362 opcode_base,
363 include_directories,
364 file_names: RefCell::new(file_names),
365 })
366 }
367
368 pub fn cu(&self) -> Rc<CompileUnit> {
369 self.cu.upgrade().unwrap()
370 }
371
372 pub fn file_names(&self) -> Ref<Vec<LineTableFile>> {
373 self.file_names.borrow()
374 }
375}
376
377#[derive(Debug, Clone)]
378pub struct Die {
379 pos: Bytes,
380 cu: Weak<CompileUnit>,
381 abbrev: Option<Rc<Abbrev>>,
382 next: Bytes,
383 attr_locs: Vec<Bytes>,
384}
385
386#[derive(Debug, Clone, Copy)]
387pub struct BitfieldInformation {
388 pub bit_size: u64,
389 pub storage_byte_size: u64,
390 pub bit_offset: u8,
391}
392
393impl Die {
394 pub fn parameter_types(self: &Rc<Self>) -> Result<Vec<SdbType>, SdbError> {
395 let mut ret = Vec::new();
396 if self.abbrev_entry().tag as u16 != DW_TAG_subprogram.0 {
397 return Ok(ret);
398 }
399 for c in self.children() {
400 if c.abbrev_entry().tag as u16 == DW_TAG_formal_parameter.0 {
401 ret.push(c.index(DW_AT_type.0 as u64)?.as_type());
402 }
403 }
404 Ok(ret)
405 }
406
407 pub fn children(self: &Rc<Self>) -> DieChildenIter {
408 DieChildenIter::new(self)
409 }
410
411 pub fn get_bitfield_information(
412 &self,
413 class_byte_size: u64,
414 ) -> Result<Option<BitfieldInformation>, SdbError> {
415 if !self.contains(DW_AT_bit_offset.0 as u64)
416 && !self.contains(DW_AT_data_bit_offset.0 as u64)
417 {
418 return Ok(None);
419 }
420 let bit_size = self.index(DW_AT_bit_size.0 as u64)?.as_int()?;
421 let storage_byte_size = if self.contains(DW_AT_byte_size.0 as u64) {
422 self.index(DW_AT_byte_size.0 as u64)?.as_int()?
423 } else {
424 class_byte_size
425 };
426 let storage_bit_size = storage_byte_size * 8;
427 let mut bit_offset = 0u8;
428 if self.contains(DW_AT_bit_offset.0 as u64) {
429 let offset_field = self.index(DW_AT_bit_offset.0 as u64)?.as_int()?;
430 bit_offset = (storage_bit_size - offset_field - bit_size) as u8;
431 }
432 if self.contains(DW_AT_data_bit_offset.0 as u64) {
433 bit_offset = self.index(DW_AT_data_bit_offset.0 as u64)?.as_int()? as u8 % 8;
434 }
435 Ok(Some(BitfieldInformation {
436 bit_size,
437 storage_byte_size,
438 bit_offset,
439 }))
440 }
441 pub fn new(
442 pos: Bytes,
443 cu: &Rc<CompileUnit>,
444 abbrev: Rc<Abbrev>,
445 attr_locs: Vec<Bytes>,
446 next: Bytes,
447 ) -> Rc<Self> {
448 Rc::new(Self {
449 pos,
450 cu: Rc::downgrade(cu),
451 abbrev: Some(abbrev),
452 next,
453 attr_locs,
454 })
455 }
456
457 pub fn null(next: Bytes) -> Rc<Self> {
458 Rc::new(Self {
459 pos: Bytes::new(),
460 cu: Weak::new(),
461 abbrev: None,
462 next,
463 attr_locs: Vec::new(),
464 })
465 }
466
467 pub fn cu(&self) -> Rc<CompileUnit> {
468 self.cu.upgrade().unwrap()
469 }
470
471 pub fn abbrev_entry(&self) -> Rc<Abbrev> {
472 self.abbrev.as_ref().unwrap().clone()
473 }
474
475 pub fn position(&self) -> Bytes {
476 self.pos.clone()
477 }
478
479 pub fn next(&self) -> Bytes {
480 self.next.clone()
481 }
482
483 pub fn contains(&self, attribute: u64) -> bool {
484 if let Some(abbrev) = &self.abbrev {
485 return abbrev.attr_specs.iter().any(|spec| spec.attr == attribute);
486 }
487 false
488 }
489
490 pub fn index(&self, attribute: u64) -> Result<DieAttr, SdbError> {
491 if let Some(abbrev) = &self.abbrev
492 && let Some((i, spec)) = abbrev
493 .attr_specs
494 .iter()
495 .enumerate()
496 .find(|(_, spec)| spec.attr == attribute)
497 {
498 return Ok(DieAttr::new(
499 &self.cu(),
500 spec.attr,
501 spec.form,
502 self.attr_locs[i].clone(),
503 ));
504 }
505 SdbError::err("Attribute not found")
506 }
507
508 pub fn low_pc(&self) -> Result<FileAddress, SdbError> {
509 if self.contains(DW_AT_ranges.0 as u64) {
510 let first_entry = self
511 .index(DW_AT_ranges.0 as u64)?
512 .as_range_list()?
513 .into_iter()
514 .next()
515 .unwrap();
516 return Ok(first_entry.low);
517 } else if self.contains(DW_AT_low_pc.0 as u64) {
518 return self.index(DW_AT_low_pc.0 as u64)?.as_address();
519 }
520 SdbError::err("DIE does not have low PC")
521 }
522
523 pub fn high_pc(&self) -> Result<FileAddress, SdbError> {
524 if self.contains(DW_AT_ranges.0 as u64) {
525 let last_entry = self
526 .index(DW_AT_ranges.0 as u64)?
527 .as_range_list()?
528 .into_iter()
529 .last()
530 .unwrap();
531 return Ok(last_entry.high);
532 } else if self.contains(DW_AT_high_pc.0 as u64) {
533 let attr = self.index(DW_AT_high_pc.0 as u64)?;
534 let addr: u64 = if attr.form() == DW_FORM_addr.0.into() {
535 attr.as_address()?.addr()
536 } else {
537 self.low_pc()?.addr() + attr.as_int()?
538 };
539 return Ok(FileAddress::new(
540 &self.cu.upgrade().unwrap().dwarf_info().elf_file(),
541 addr,
542 ));
543 }
544 SdbError::err("DIE does not have high PC")
545 }
546
547 pub fn contains_address(&self, addr: &FileAddress) -> Result<bool, SdbError> {
548 if !addr.has_elf()
549 || !Rc::ptr_eq(
550 &self.cu.upgrade().unwrap().dwarf_info().elf_file(),
551 &addr.rc_elf_file(),
552 )
553 {
554 return Ok(false);
555 }
556 if self.contains(DW_AT_ranges.0 as u64) {
557 return Ok(self
558 .index(DW_AT_ranges.0 as u64)?
559 .as_range_list()?
560 .contains(addr));
561 } else if self.contains(DW_AT_low_pc.0 as u64) {
562 let low_pc = self.low_pc()?;
563 let high_pc = self.high_pc()?;
564 return Ok(&low_pc <= addr && &high_pc > addr);
565 }
566 Ok(false)
567 }
568
569 pub fn name(&self) -> Result<Option<String>, SdbError> {
570 if self.contains(DW_AT_name.0 as u64) {
571 return Ok(Some(self.index(DW_AT_name.0 as u64)?.as_string()?));
572 }
573 if self.contains(DW_AT_specification.0 as u64) {
574 return self
575 .index(DW_AT_specification.0 as u64)?
576 .as_reference()
577 .name();
578 }
579 if self.contains(DW_AT_abstract_origin.0 as u64) {
580 return self
581 .index(DW_AT_abstract_origin.0 as u64)?
582 .as_reference()
583 .name();
584 }
585 Ok(None)
586 }
587
588 pub fn location(&self) -> Result<SourceLocation, SdbError> {
589 Ok(SourceLocation {
590 file: self.file()?,
591 line: self.line()?,
592 })
593 }
594
595 pub fn file(&self) -> Result<Rc<LineTableFile>, SdbError> {
596 let idx = if self.abbrev_entry().tag as u16 == DW_TAG_inlined_subroutine.0 {
597 self.index(DW_AT_call_file.0 as u64)?.as_int()?
598 } else {
599 self.index(DW_AT_decl_file.0 as u64)?.as_int()?
600 };
601 Ok(Rc::new(
602 self.cu().lines().file_names()[idx as usize - 1].clone(),
603 ))
604 }
605
606 pub fn line(&self) -> Result<u64, SdbError> {
607 if self.abbrev_entry().tag as u16 == DW_TAG_inlined_subroutine.0 {
608 return self.index(DW_AT_call_line.0 as u64)?.as_int();
609 }
610 self.index(DW_AT_decl_line.0 as u64)?.as_int()
611 }
612}
613
614pub struct DieAttr {
615 cu: Weak<CompileUnit>,
616 type_: u64,
617 form: u64,
618 location: Bytes,
619}
620
621impl DieAttr {
622 pub fn new(cu: &Rc<CompileUnit>, type_: u64, form: u64, location: Bytes) -> Self {
623 Self {
624 cu: Rc::downgrade(cu),
625 type_,
626 form,
627 location: location.clone(),
628 }
629 }
630
631 pub fn name(&self) -> u64 {
632 self.type_
633 }
634
635 pub fn form(&self) -> u64 {
636 self.form
637 }
638
639 pub fn as_address(&self) -> Result<FileAddress, SdbError> {
640 let mut cursor = Cursor::new(&self.location);
641 if self.form as u16 != DW_FORM_addr.0 {
642 return SdbError::err("Invalid address type");
643 }
644 let elf = self.cu.upgrade().unwrap().dwarf_info().elf_file();
645 return Ok(FileAddress::new(&elf, cursor.u64()));
646 }
647
648 pub fn as_section_offset(&self) -> Result<u32, SdbError> {
649 let mut cursor = Cursor::new(&self.location);
650 if self.form as u16 != DW_FORM_sec_offset.0 {
651 return SdbError::err("Invalid offset type");
652 }
653 return Ok(cursor.u32());
654 }
655
656 pub fn as_block(&self) -> Result<Bytes, SdbError> {
657 let mut cursor = Cursor::new(&self.location);
658 #[allow(non_upper_case_globals)]
659 let size = match DwForm(self.form as u16) {
660 DW_FORM_block1 => cursor.u8() as usize,
661 DW_FORM_block2 => cursor.u16() as usize,
662 DW_FORM_block4 => cursor.u32() as usize,
663 DW_FORM_block => cursor.uleb128() as usize,
664 _ => return SdbError::err("Invalid block type"),
665 };
666 Ok(cursor.position().slice(..size))
667 }
668
669 pub fn as_int(&self) -> Result<u64, SdbError> {
670 let mut cursor = Cursor::new(&self.location);
671 #[allow(non_upper_case_globals)]
672 return match DwForm(self.form as u16) {
673 DW_FORM_data1 => Ok(cursor.u8() as u64),
674 DW_FORM_data2 => Ok(cursor.u16() as u64),
675 DW_FORM_data4 => Ok(cursor.u32() as u64),
676 DW_FORM_data8 => Ok(cursor.u64()),
677 DW_FORM_udata => Ok(cursor.uleb128()),
678 _ => SdbError::err("Invalid integer type"),
679 };
680 }
681
682 pub fn as_string(&self) -> Result<String, SdbError> {
683 let mut cursor = Cursor::new(&self.location);
684 #[allow(non_upper_case_globals)]
685 match DwForm(self.form as u16) {
686 DW_FORM_string => Ok(cursor.string()),
687 DW_FORM_strp => {
688 let offset = cursor.u32() as usize;
689 let stab = self
690 .cu
691 .upgrade()
692 .unwrap()
693 .dwarf_info()
694 .elf_file()
695 .get_section_contents(".debug_str");
696 let mut stab_cur = Cursor::new(&stab.slice(offset..));
697 Ok(stab_cur.string())
698 }
699 _ => SdbError::err("Invalid string type"),
700 }
701 }
702
703 pub fn as_reference(&self) -> Rc<Die> {
704 let mut cursor = Cursor::new(&self.location);
705 #[allow(non_upper_case_globals)]
706 let offset = match DwForm(self.form as u16) {
707 DW_FORM_ref1 => cursor.u8() as usize,
708 DW_FORM_ref2 => cursor.u16() as usize,
709 DW_FORM_ref4 => cursor.u32() as usize,
710 DW_FORM_ref8 => cursor.u64() as usize,
711 DW_FORM_ref_udata => cursor.uleb128() as usize,
712 DW_FORM_ref_addr => {
713 let offset = cursor.u32() as usize;
714 let cu = self.cu.upgrade().unwrap();
715 let dwarf_info = cu.dwarf_info();
716 let section = dwarf_info.elf_file().get_section_contents(".debug_info");
717 let die_pos = section.slice(offset..);
718 let die_ptr = die_pos.as_ptr() as usize;
719 let cus = dwarf_info.compile_units();
720 let cu_for_offset = cus
721 .iter()
722 .find(|cu| {
723 let cu_ptr = cu.data.as_ptr() as usize;
724 let cu_end = cu_ptr + cu.data.len();
725 cu_ptr <= die_ptr && cu_end > die_ptr
726 })
727 .unwrap();
728 let offset_in_cu = die_ptr - (cu_for_offset.data().as_ptr() as usize);
729 let ref_cursor = Cursor::new(&cu_for_offset.data.slice(offset_in_cu..));
730 return parse_die(cu_for_offset, ref_cursor);
731 }
732 _ => panic!("Invalid reference type"),
733 };
734 let cu = self.cu.upgrade().unwrap();
735 let ref_cursor = Cursor::new(&cu.data.slice(offset..));
736 parse_die(&cu, ref_cursor)
737 }
738
739 pub fn as_range_list(&self) -> Result<CompileUnitRangeList, SdbError> {
740 let cu = self.cu.upgrade().unwrap();
741 let section = cu
742 .dwarf_info()
743 .elf_file()
744 .get_section_contents(".debug_ranges");
745 let offset = self.as_section_offset()? as usize;
746 let data = section.slice(offset..);
747 let root = cu.root();
748 let base_address = if root.contains(DW_AT_low_pc.0 as u64) {
749 root.index(DW_AT_low_pc.0 as u64)?.as_address()?
750 } else {
751 FileAddress::default()
752 };
753 Ok(CompileUnitRangeList::new(&cu, &data, base_address))
754 }
755
756 pub fn as_expression(&self, in_frame_info: bool) -> DwarfExpression {
757 let cu_data_end = {
758 let cu = self.cu.upgrade().unwrap();
759 cu.data.as_ptr() as usize + cu.data.len()
760 };
761 let slice = cu_data_end - self.location.as_ptr() as usize;
762 let mut cur = Cursor::new(&self.location.slice(..slice));
763 let length = cur.uleb128();
764 let data = cur.position().slice(..length as usize);
765
766 DwarfExpression::builder()
767 .parent(Rc::downgrade(&self.cu.upgrade().unwrap().dwarf_info()))
768 .expr_data(data)
769 .in_frame_info(in_frame_info)
770 .build()
771 }
772
773 pub fn as_location_list(&self, in_frame_info: bool) -> LocationList {
774 let section = self
775 .cu
776 .upgrade()
777 .unwrap()
778 .dwarf_info()
779 .elf_file()
780 .get_section_contents(".debug_loc");
781 let cu_data_end = {
782 let cu = self.cu.upgrade().unwrap();
783 cu.data.as_ptr() as usize + cu.data.len()
784 };
785 let slice = cu_data_end - self.location.as_ptr() as usize;
786 let mut cur = Cursor::new(&self.location.slice(..slice));
787 let offset = cur.u32();
788
789 let data = section.slice(offset as usize..);
790
791 LocationList::new(
792 Rc::downgrade(&self.cu.upgrade().unwrap().dwarf_info()),
793 self.cu.clone(),
794 data,
795 in_frame_info,
796 )
797 }
798
799 pub fn as_evaluated_location(
800 &self,
801 proc: &Process,
802 regs: &Registers,
803 in_frame_info: bool,
804 ) -> Result<DwarfExpressionResult, SdbError> {
805 if self.form == DW_FORM_exprloc.0 as u64 {
806 let expr = self.as_expression(in_frame_info);
807 expr.eval(proc, regs, false)
808 } else if self.form == DW_FORM_sec_offset.0 as u64 {
809 let loc_list = self.as_location_list(in_frame_info);
810 Ok(loc_list.eval(proc, regs))
811 } else {
812 SdbError::err("Invalid location type")
813 }
814 }
815
816 pub fn as_type(&self) -> SdbType {
817 return SdbType::new(self.as_reference());
818 }
819}
820
821pub struct LocationList {
822 parent: Weak<Dwarf>,
823 cu: Weak<CompileUnit>,
824 expr_data: Bytes,
825 in_frame_info: bool,
826}
827
828impl LocationList {
829 pub fn new(
830 parent: Weak<Dwarf>,
831 cu: Weak<CompileUnit>,
832 expr_data: Bytes,
833 in_frame_info: bool,
834 ) -> Self {
835 Self {
836 parent,
837 cu,
838 expr_data,
839 in_frame_info,
840 }
841 }
842
843 pub fn eval(&self, proc: &Process, regs: &Registers) -> DwarfExpressionResult {
844 let virt_pc = VirtualAddress::new(regs.read_by_id_as::<u64>(RegisterId::rip).unwrap());
845 let pc = virt_pc.to_file_addr_elf(&self.parent.upgrade().unwrap().elf_file());
846
847 let mut cur = Cursor::new(&self.expr_data);
848 let base_address_flag = !0u64;
849 let mut base_address = self
850 .cu
851 .upgrade()
852 .unwrap()
853 .root()
854 .index(DW_AT_low_pc.0 as u64)
855 .unwrap()
856 .as_address()
857 .unwrap()
858 .addr();
859
860 let mut first = cur.u64();
861 let mut second = cur.u64();
862 while !(first == 0 && second == 0) {
863 if first == base_address_flag {
864 base_address = second;
865 } else {
866 let length = cur.u16();
867 if pc.addr() >= base_address + first && pc.addr() < base_address + second {
868 let expr_data = cur.position().slice(..length as usize);
869 let expr = DwarfExpression::builder()
870 .parent(self.parent.clone())
871 .expr_data(expr_data)
872 .in_frame_info(self.in_frame_info)
873 .build();
874 return expr.eval(proc, regs, false).unwrap();
875 } else {
876 cur += length as usize;
877 }
878 }
879 first = cur.u64();
880 second = cur.u64();
881 }
882
883 DwarfExpressionResult::SimpleLocation(DwarfExpressionSimpleLocation::Empty {})
884 }
885}
886
887pub struct DieChildenIter {
888 die: Option<Rc<Die>>,
889}
890
891impl DieChildenIter {
892 pub fn new(die: &Rc<Die>) -> Self {
893 if let Some(abbrev) = &die.abbrev
894 && abbrev.has_children
895 {
896 let next_cursor = Cursor::new(&die.next);
897 return Self {
898 die: Some(parse_die(&die.cu.upgrade().unwrap(), next_cursor)),
899 };
900 }
901 Self { die: None }
902 }
903}
904
905impl Iterator for DieChildenIter {
906 type Item = Rc<Die>;
907
908 fn next(&mut self) -> Option<Self::Item> {
909 if let Some(current_die) = self.die.take()
910 && let Some(abbrev) = ¤t_die.abbrev
911 {
912 if !abbrev.has_children {
913 let next_cursor = Cursor::new(¤t_die.next);
914 self.die = Some(parse_die(¤t_die.cu.upgrade().unwrap(), next_cursor));
915 return Some(current_die);
916 } else if current_die.contains(DW_AT_sibling.0 as u64) {
917 self.die = Some(
918 current_die
919 .index(DW_AT_sibling.0 as u64)
920 .unwrap()
921 .as_reference(),
922 );
923 return Some(current_die);
924 } else {
925 let sub_children = DieChildenIter::new(¤t_die);
926 for d in sub_children {
927 if d.abbrev.is_none() {
928 let next_cursor = Cursor::new(&d.next);
929 self.die = Some(parse_die(¤t_die.cu.upgrade().unwrap(), next_cursor));
930 break;
931 }
932 }
933 return Some(current_die);
934 }
935 }
936 None
937 }
938}
939
940#[derive(Debug)]
941pub struct CompileUnit {
942 parent: Weak<Dwarf>,
943 data: Bytes,
944 abbrev_offset: usize,
945 line_table: RefCell<Option<Rc<LineTable>>>,
946}
947
948fn parse_line_table_file<T: AsRef<Path>>(
949 cur: &mut Cursor,
950 compilation_dir: &T,
951 include_directories: &[PathBuf],
952) -> LineTableFile {
953 let file = PathBuf::from(cur.string());
954 let dir_index = cur.uleb128();
955 let modification_time = cur.uleb128();
956 let file_length = cur.uleb128();
957 let mut path = file.clone();
958 if !file.as_os_str().to_str().unwrap().starts_with('/') {
959 if dir_index == 0 {
960 path = compilation_dir.as_ref().join(file);
961 } else {
962 path = include_directories[dir_index as usize - 1].join(file);
963 }
964 }
965 LineTableFile {
966 path,
967 modification_time,
968 file_length,
969 }
970}
971
972fn parse_line_table(cu: &Rc<CompileUnit>) -> Result<Option<Rc<LineTable>>, SdbError> {
973 let section = cu
974 .dwarf_info()
975 .elf_file()
976 .get_section_contents(".debug_line");
977 if !cu.root().contains(DW_AT_stmt_list.0 as u64) {
978 return Ok(None);
979 }
980 let offset = cu
981 .root()
982 .index(DW_AT_stmt_list.0 as u64)?
983 .as_section_offset()? as usize;
984 let mut cursor = Cursor::new(§ion.slice(offset..));
985 let size = cursor.u32();
986 let end = cursor.position().as_ptr() as usize + size as usize;
987 let version = cursor.u16();
988 if version != 4 {
989 return SdbError::err("Only DWARF 4 is supported");
990 }
991 let _header_length = cursor.u32();
992 let minimum_instruction_length = cursor.u8();
993 if minimum_instruction_length != 1 {
994 return SdbError::err("Invalid minimum instruction length");
995 }
996 let maximum_operations_per_instruction = cursor.u8();
997 if maximum_operations_per_instruction != 1 {
998 return SdbError::err("Invalid maximum operations per instruction");
999 }
1000 let default_is_stmt = cursor.u8();
1001 let line_base = cursor.s8();
1002 let line_range = cursor.u8();
1003 let opcode_base = cursor.u8();
1004 let expected_opcode_lengths = [0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1];
1005 for i in 0..opcode_base - 1 {
1006 if cursor.u8() != expected_opcode_lengths[i as usize] {
1007 return SdbError::err("Unexpected opcode length");
1008 }
1009 }
1010 let mut include_directories: Vec<PathBuf> = vec![];
1011 let compilation_dir = PathBuf::from(cu.root().index(DW_AT_comp_dir.0 as u64)?.as_string()?);
1012 let mut dir = cursor.string();
1013 while !dir.is_empty() {
1014 if dir.starts_with('/') {
1015 include_directories.push(PathBuf::from(dir));
1016 } else {
1017 include_directories.push(compilation_dir.clone().join(dir));
1018 }
1019 dir = cursor.string();
1020 }
1021 let mut file_names: Vec<LineTableFile> = vec![];
1022 while cursor.position()[0] != 0 {
1023 file_names.push(parse_line_table_file(
1024 &mut cursor,
1025 &compilation_dir,
1026 &include_directories,
1027 ));
1028 }
1029 cursor += 1;
1030 let data = cursor
1032 .position()
1033 .slice(0..(end - cursor.position().as_ptr() as usize));
1034 Ok(Some(LineTable::new(
1035 data,
1036 cu,
1037 default_is_stmt != 0,
1038 line_base,
1039 line_range,
1040 opcode_base,
1041 include_directories,
1042 file_names,
1043 )))
1044}
1045
1046impl CompileUnit {
1047 pub fn root(self: &Rc<Self>) -> Rc<Die> {
1048 let header_size = 11usize;
1049 let cursor = Cursor::new(&self.data.slice(header_size..));
1050 parse_die(self, cursor)
1051 }
1052
1053 pub fn new(
1054 parent: &Rc<Dwarf>,
1055 data: Bytes,
1056 abbrev_offset: usize,
1057 ) -> Result<Rc<Self>, SdbError> {
1058 let ret = Rc::new(Self {
1059 parent: Rc::downgrade(parent),
1060 data,
1061 abbrev_offset,
1062 line_table: RefCell::new(None),
1063 });
1064 *ret.line_table.borrow_mut() = parse_line_table(&ret)?;
1065 Ok(ret)
1066 }
1067
1068 pub fn dwarf_info(&self) -> Rc<Dwarf> {
1069 self.parent.upgrade().unwrap()
1070 }
1071
1072 pub fn data(&self) -> &[u8] {
1073 &self.data
1074 }
1075
1076 pub fn abbrev_table(&self) -> Rc<AbbrevTable> {
1077 self.parent
1078 .upgrade()
1079 .unwrap()
1080 .get_abbrev_table(self.abbrev_offset)
1081 }
1082
1083 pub fn lines(&self) -> Rc<LineTable> {
1084 self.line_table.borrow().clone().unwrap()
1085 }
1086}
1087
1088#[derive(Debug, Clone)]
1089pub struct CompileUnitRangeList {
1090 cu: Rc<CompileUnit>,
1091 data: Bytes,
1092 base_address: FileAddress,
1093}
1094
1095impl CompileUnitRangeList {
1096 pub fn new(cu: &Rc<CompileUnit>, data: &Bytes, base_address: FileAddress) -> Self {
1097 Self {
1098 cu: cu.clone(),
1099 data: data.clone(),
1100 base_address,
1101 }
1102 }
1103
1104 pub fn contains(&self, addr: &FileAddress) -> bool {
1105 let mut iter =
1106 CompileUnitRangeListIter::new(&self.cu, &self.data, self.base_address.clone());
1107 iter.any(|e| e.contains(addr))
1108 }
1109}
1110
1111impl IntoIterator for CompileUnitRangeList {
1112 type Item = CompileUnitRangeEntry;
1113 type IntoIter = CompileUnitRangeListIter;
1114
1115 fn into_iter(self) -> Self::IntoIter {
1116 CompileUnitRangeListIter::new(&self.cu, &self.data, self.base_address)
1117 }
1118}
1119
1120pub struct CompileUnitRangeListIter {
1121 cu: Rc<CompileUnit>,
1122 pos: Bytes,
1123 base_address: FileAddress,
1124 current: CompileUnitRangeEntry,
1125}
1126
1127impl CompileUnitRangeListIter {
1128 pub fn new(cu: &Rc<CompileUnit>, data: &Bytes, base_address: FileAddress) -> Self {
1129 let mut ret = Self {
1130 cu: cu.clone(),
1131 pos: data.clone(),
1132 base_address,
1133 current: CompileUnitRangeEntry::default(),
1134 };
1135 ret.next();
1136 ret
1137 }
1138}
1139
1140impl Iterator for CompileUnitRangeListIter {
1141 type Item = CompileUnitRangeEntry;
1142
1143 fn next(&mut self) -> Option<Self::Item> {
1144 if self.pos.is_empty() {
1145 return None;
1146 }
1147 let elf = self.cu.dwarf_info().elf_file();
1148 let base_address_flag = !0u64;
1149 let mut cursor = Cursor::new(&self.pos);
1150 let prev_current = self.current.clone();
1151 loop {
1152 self.current.low = FileAddress::new(&elf, cursor.u64());
1153 self.current.high = FileAddress::new(&elf, cursor.u64());
1154 if self.current.low.addr() == base_address_flag {
1155 self.base_address = self.current.high.clone();
1156 } else if self.current.low.addr() == 0 && self.current.high.addr() == 0 {
1157 self.pos = Bytes::new();
1158 break;
1159 } else {
1160 self.pos = cursor.position();
1161 self.current.low += self.base_address.addr() as i64;
1162 self.current.high += self.base_address.addr() as i64;
1163 break;
1164 }
1165 }
1166 return Some(prev_current);
1167 }
1168}
1169#[derive(Debug, Clone, Default)]
1170pub struct CompileUnitRangeEntry {
1171 pub low: FileAddress,
1172 pub high: FileAddress,
1173}
1174
1175impl CompileUnitRangeEntry {
1176 pub fn contains(&self, addr: &FileAddress) -> bool {
1177 &self.low <= addr && addr < &self.high
1178 }
1179}
1180
1181fn parse_die(cu: &Rc<CompileUnit>, mut cursor: Cursor) -> Rc<Die> {
1182 let pos = cursor.position();
1183 let abbrev_code = cursor.uleb128();
1184 if abbrev_code == 0 {
1185 let next = cursor.position();
1186 return Die::null(next);
1187 }
1188 let abbrev_table = cu.abbrev_table();
1189 let abbrev = &abbrev_table[&abbrev_code];
1190 let mut attr_locs = Vec::<Bytes>::with_capacity(abbrev.attr_specs.len());
1191 for attr in &abbrev.attr_specs {
1192 attr_locs.push(cursor.position());
1193 cursor.skip_form(attr.form).unwrap();
1194 }
1195 let next = cursor.position();
1196 Die::new(pos, cu, abbrev.clone(), attr_locs, next)
1197}
1198
1199fn parse_call_frame_information(
1200 dwarf: &Rc<Dwarf>,
1201) -> Result<Rc<RefCell<CallFrameInformation>>, SdbError> {
1202 let eh_hdr = parse_eh_hdr(dwarf)?;
1203 Ok(CallFrameInformation::new(dwarf, eh_hdr))
1204}
1205
1206#[derive(Debug)]
1207pub struct Dwarf {
1208 elf: Weak<Elf>,
1209 abbrev_tables: RefCell<HashMap<usize, Rc<AbbrevTable>>>,
1210 compile_units: OnceCell<Vec<Rc<CompileUnit>>>,
1211 function_index: RefCell<MultiMap<String, DwarfIndexEntry>>,
1212 cfi: OnceCell<Rc<RefCell<CallFrameInformation>>>,
1213 global_variable_index: RefCell<MultiMap<String, DwarfIndexEntry>>,
1214 member_function_index: RefCell<HashMap<Bytes, DwarfIndexEntry>>,
1215}
1216
1217fn scopes_at_address_in_die(
1218 die: &Rc<Die>,
1219 address: &FileAddress,
1220 scopes: &mut Vec<Rc<Die>>,
1221) -> Result<(), SdbError> {
1222 for c in die.children() {
1223 if c.contains_address(address)? {
1224 scopes_at_address_in_die(&c, address, scopes)?;
1225 scopes.push(c);
1226 }
1227 }
1228 Ok(())
1229}
1230impl Dwarf {
1231 pub fn get_member_function_definition(
1232 &self,
1233 declaration: &Rc<Die>,
1234 ) -> Result<Option<Rc<Die>>, SdbError> {
1235 self.index()?;
1236 let it = self
1237 .member_function_index
1238 .borrow()
1239 .get(&declaration.position())
1240 .cloned();
1241 if it.is_some() {
1242 let it = it.unwrap();
1243 let cu = it.cu.upgrade().unwrap();
1244 let cu_data_end = cu.data().as_ptr() as usize + cu.data().len();
1245
1246 let cursor = Cursor::new(&it.pos.slice(..(cu_data_end - it.pos.as_ptr() as usize)));
1247 let die = parse_die(&cu, cursor);
1248 if die.contains(DW_AT_low_pc.0 as u64) || die.contains(DW_AT_ranges.0 as u64) {
1249 return Ok(Some(die));
1250 }
1251 return self.get_member_function_definition(&die);
1252 }
1253 return Ok(None);
1254 }
1255 pub fn find_local_variable(
1256 &self,
1257 name: &str,
1258 pc: &FileAddress,
1259 ) -> Result<Option<Rc<Die>>, SdbError> {
1260 let scopes = self.scopes_at_address(pc)?;
1261 for scope in scopes {
1262 for child in scope.children() {
1263 let tag = child.abbrev_entry().tag;
1264 if (tag as u16 == DW_TAG_variable.0 || tag as u16 == DW_TAG_formal_parameter.0)
1265 && let Some(child_name) = child.name()?
1266 && child_name == name
1267 {
1268 return Ok(Some(child));
1269 }
1270 }
1271 }
1272 Ok(None)
1273 }
1274
1275 pub fn scopes_at_address(&self, address: &FileAddress) -> Result<Vec<Rc<Die>>, SdbError> {
1276 let func = self.function_containing_address(address)?;
1277 match func {
1278 Some(func) => {
1279 let mut scopes = Vec::new();
1280 scopes_at_address_in_die(&func, address, &mut scopes)?;
1281 scopes.push(func);
1282 Ok(scopes)
1283 }
1284 None => Ok(vec![]),
1285 }
1286 }
1287
1288 pub fn find_global_variable(&self, name: &str) -> Result<Option<Rc<Die>>, SdbError> {
1289 self.index()?;
1290 let global_variable_index = self.global_variable_index.borrow();
1291 let indices = global_variable_index.get_vec(name);
1292 if let Some(entrys) = indices
1293 && let Some(entry) = entrys.iter().next()
1294 {
1295 let cu = entry.cu.upgrade().unwrap();
1296 let cu_data_end = cu.data().as_ptr() as usize + cu.data().len();
1297 let len = cu_data_end - entry.pos.as_ptr() as usize;
1298 let cursor = Cursor::new(&entry.pos.slice(0..len));
1299 return Ok(Some(parse_die(&cu, cursor)));
1300 }
1301 Ok(None)
1302 }
1303
1304 pub fn cfi(&self) -> Rc<RefCell<CallFrameInformation>> {
1305 self.cfi.get().unwrap().clone()
1306 }
1307
1308 pub fn new(parent: &Weak<Elf>) -> Result<Rc<Self>, SdbError> {
1309 let ret = Rc::new(Self {
1310 elf: parent.clone(),
1311 abbrev_tables: RefCell::new(HashMap::default()),
1312 compile_units: OnceCell::new(),
1313 function_index: RefCell::new(MultiMap::default()),
1314 global_variable_index: RefCell::new(MultiMap::default()),
1315 cfi: OnceCell::new(),
1316 member_function_index: RefCell::new(HashMap::default()),
1317 });
1318 let t = parse_compile_units(&ret, &ret.elf_file())?;
1319 ret.compile_units
1320 .set(t)
1321 .map_err(|_| SdbError::new_err("Failed to set compile units"))?;
1322 ret.cfi
1323 .set(parse_call_frame_information(&ret)?)
1324 .map_err(|_| SdbError::new_err("Failed to set call frame information"))?;
1325 Ok(ret)
1326 }
1327
1328 pub fn elf_file(&self) -> Rc<Elf> {
1329 self.elf.upgrade().unwrap()
1330 }
1331
1332 pub fn get_abbrev_table(&self, offset: usize) -> Rc<AbbrevTable> {
1333 if !self.abbrev_tables.borrow().contains_key(&offset) {
1334 self.abbrev_tables.borrow_mut().insert(
1335 offset,
1336 Rc::new(parse_abbrev_table(&self.elf_file(), offset)),
1337 );
1338 }
1339 self.abbrev_tables.borrow()[&offset].clone()
1340 }
1341
1342 pub fn compile_units(&self) -> &Vec<Rc<CompileUnit>> {
1343 self.compile_units.get().unwrap()
1344 }
1345
1346 pub fn compile_unit_containing_address(
1347 &self,
1348 address: &FileAddress,
1349 ) -> Result<Option<Rc<CompileUnit>>, SdbError> {
1350 for cu in self.compile_units().iter() {
1351 if cu.root().contains_address(address)? {
1352 return Ok(Some(cu.clone()));
1353 }
1354 }
1355 Ok(None)
1356 }
1357
1358 pub fn function_containing_address(
1359 &self,
1360 address: &FileAddress,
1361 ) -> Result<Option<Rc<Die>>, SdbError> {
1362 self.index()?;
1363 for (_name, entry) in self.function_index.borrow().iter() {
1364 let cursor = Cursor::new(&entry.pos);
1365 let die = parse_die(&entry.cu.upgrade().unwrap(), cursor);
1366 if die.contains_address(address)?
1367 && die.abbrev_entry().tag == DW_TAG_subprogram.0 as u64
1368 {
1369 return Ok(Some(die));
1370 }
1371 }
1372 Ok(None)
1373 }
1374
1375 pub fn find_functions(&self, name: &str) -> Result<Vec<Rc<Die>>, SdbError> {
1376 self.index()?;
1377 let mut found: Vec<Rc<Die>> = Vec::new();
1378 let function_index = self.function_index.borrow();
1379 let entrys = function_index.get_vec(name);
1380 if let Some(entrys) = entrys {
1381 for entry in entrys {
1382 let cursor = Cursor::new(&entry.pos);
1383 let die = parse_die(&entry.cu.upgrade().unwrap(), cursor);
1384 found.push(die);
1385 }
1386 }
1387 Ok(found)
1388 }
1389
1390 fn index(&self) -> Result<(), SdbError> {
1391 if !self.function_index.borrow().is_empty() {
1392 return Ok(());
1393 }
1394 for cu in self.compile_units().iter() {
1395 self.index_die(&cu.root(), false)?;
1396 }
1397 Ok(())
1398 }
1399
1400 fn index_die(
1401 &self,
1402 current: &Rc<Die>,
1403 mut in_function: bool, ) -> Result<(), SdbError> {
1405 let has_range =
1406 current.contains(DW_AT_low_pc.0 as u64) || current.contains(DW_AT_ranges.0 as u64);
1407 let is_function = current.abbrev_entry().tag == DW_TAG_subprogram.0 as u64
1408 || current.abbrev_entry().tag == DW_TAG_inlined_subroutine.0 as u64;
1409 if has_range
1410 && is_function
1411 && let Some(name) = current.name()?
1412 {
1413 let entry = DwarfIndexEntry {
1414 cu: current.cu.clone(),
1415 pos: current.pos.clone(),
1416 };
1417 self.function_index.borrow_mut().insert(name, entry);
1418 }
1419 if is_function {
1420 if current.contains(DW_AT_specification.0 as u64) {
1421 let index_entry = DwarfIndexEntry {
1422 cu: current.cu.clone(),
1423 pos: current.position(),
1424 };
1425 self.member_function_index.borrow_mut().insert(
1426 current
1427 .index(DW_AT_specification.0 as u64)?
1428 .as_reference()
1429 .position(),
1430 index_entry,
1431 );
1432 } else if current.contains(DW_AT_abstract_origin.0 as u64) {
1433 let index_entry = DwarfIndexEntry {
1434 cu: current.cu.clone(),
1435 pos: current.position(),
1436 };
1437 self.member_function_index.borrow_mut().insert(
1438 current
1439 .index(DW_AT_abstract_origin.0 as u64)?
1440 .as_reference()
1441 .position(),
1442 index_entry,
1443 );
1444 }
1445 }
1446 let has_location = current.contains(DW_AT_location.0 as u64);
1447 let is_variable = current.abbrev_entry().tag == DW_TAG_variable.0 as u64;
1448 if has_location
1449 && is_variable
1450 && !in_function
1451 && let Some(name) = current.name()?
1452 {
1453 let entry = DwarfIndexEntry {
1454 cu: current.cu.clone(),
1455 pos: current.position(),
1456 };
1457 self.global_variable_index.borrow_mut().insert(name, entry);
1458 }
1459 if is_function {
1460 in_function = true;
1461 }
1462 for child in current.children() {
1463 self.index_die(&child, in_function)?;
1464 }
1465 Ok(())
1466 }
1467
1468 pub fn line_entry_at_address(&self, address: &FileAddress) -> Result<LineTableIter, SdbError> {
1469 let cu = self.compile_unit_containing_address(address)?;
1470 if let Some(cu) = cu {
1471 return cu.lines().get_entry_by_address(address);
1472 }
1473 Ok(LineTableIter::default())
1474 }
1475
1476 pub fn inline_stack_at_address(&self, address: &FileAddress) -> Result<Vec<Rc<Die>>, SdbError> {
1477 let func = self.function_containing_address(address)?;
1478 let mut stack: Vec<Rc<Die>> = Vec::new();
1479 if let Some(func) = func {
1480 stack.push(func);
1481 loop {
1482 let mut children = stack.last().unwrap().children();
1483 let found = children.find(|child| {
1484 child.abbrev_entry().tag == DW_TAG_inlined_subroutine.0 as u64
1485 && child.contains_address(address).unwrap_or(false)
1486 });
1487 if let Some(found) = found {
1488 stack.push(found);
1489 } else {
1490 break;
1491 }
1492 }
1493 }
1494 Ok(stack)
1495 }
1496}
1497
1498#[derive(Debug, Clone)]
1499pub struct DwarfIndexEntry {
1500 cu: Weak<CompileUnit>,
1501 pos: Bytes,
1502}
1503
1504fn parse_compile_units(dwarf: &Rc<Dwarf>, obj: &Elf) -> Result<Vec<Rc<CompileUnit>>, SdbError> {
1505 let debug_info = obj.get_section_contents(".debug_info");
1506 let mut cursor = Cursor::new(&debug_info);
1507 let mut units: Vec<Rc<CompileUnit>> = Vec::new();
1508 while !cursor.finished() {
1509 if let Ok(unit) = parse_compile_unit(dwarf, obj, cursor.clone()) {
1510 cursor += unit.data.len();
1511 units.push(unit);
1512 } else {
1513 break;
1514 }
1515 }
1516 Ok(units)
1517}
1518
1519fn parse_compile_unit(
1520 dwarf: &Rc<Dwarf>,
1521 _obj: &Elf,
1522 mut cursor: Cursor,
1523) -> Result<Rc<CompileUnit>, SdbError> {
1524 let start = cursor.position();
1525 let mut size = cursor.u32();
1526 let version = cursor.u16();
1527 let abbrev = cursor.u32();
1528 let address_size = cursor.u8();
1529 if size == 0xffffffff {
1530 return SdbError::err("Only DWARF32 is supported");
1531 }
1532 if version != 4 {
1533 return SdbError::err(&format!(
1534 "Only DWARF version 4 is supported, found version {version}"
1535 ));
1536 }
1537 if address_size != 8 {
1538 return SdbError::err("Invalid address size for DWARF");
1539 }
1540 size += size_of::<u32>() as u32;
1541 let data = start.slice(..size as usize);
1542 CompileUnit::new(dwarf, data, abbrev as usize)
1543}
1544
1545fn parse_abbrev_table(obj: &Elf, offset: usize) -> AbbrevTable {
1546 let mut cursor = Cursor::new(&obj.get_section_contents(".debug_abbrev"));
1547 cursor += offset;
1548 let mut table: AbbrevTable = HashMap::new();
1549 let mut code: u64;
1550 loop {
1551 code = cursor.uleb128();
1552 if code == 0 {
1554 break;
1555 }
1556 let tag = cursor.uleb128();
1557 let has_children = cursor.u8() != 0;
1558 let mut attr_specs = Vec::<AttrSpec>::new();
1559 let mut attr: u64;
1560 loop {
1561 attr = cursor.uleb128();
1562 let form = cursor.uleb128();
1563 if attr != 0 {
1564 attr_specs.push(AttrSpec { attr, form });
1565 }
1566 if attr == 0 {
1567 break;
1568 }
1569 }
1570 table.insert(
1571 code,
1572 Rc::new(Abbrev {
1573 code,
1574 tag,
1575 has_children,
1576 attr_specs,
1577 }),
1578 );
1579 }
1580
1581 table
1582}
1583
1584#[derive(Debug, Clone, Copy)]
1585pub struct AttrSpec {
1586 attr: u64,
1587 form: u64,
1588}
1589
1590#[derive(Debug)]
1591pub struct Abbrev {
1592 pub code: u64,
1593 pub tag: u64,
1594 pub has_children: bool,
1595 pub attr_specs: Vec<AttrSpec>,
1596}
1597
1598#[derive(Debug, Clone, Default)]
1599pub struct Cursor {
1600 data: Bytes,
1601}
1602
1603macro_rules! gen_fixed_int {
1604 ($( $name:ident : $ty:ty ),* $(,)?) => {
1605 $(
1606 pub fn $name(&mut self) -> $ty {
1607 self.fixed_int::<$ty>()
1608 }
1609 )*
1610 };
1611}
1612
1613impl Cursor {
1614 pub fn new(data: &Bytes) -> Self {
1615 Self { data: data.clone() }
1616 }
1617
1618 pub fn finished(&self) -> bool {
1619 self.data.is_empty()
1620 }
1621
1622 pub fn position(&self) -> Bytes {
1623 self.data.clone()
1624 }
1625
1626 pub fn fixed_int<T: Pod>(&mut self) -> T {
1627 let t = from_bytes::<T>(&self.data);
1628 self.data = self.data.slice(size_of::<T>()..);
1629 t
1630 }
1631
1632 pub fn string(&mut self) -> String {
1633 if let Some(pos) = self.data.iter().position(|&b| b == 0) {
1634 let next = pos + 1;
1635 let s = self.data.slice(..next);
1636 let s = CStr::from_bytes_with_nul(&s).unwrap().to_str().unwrap();
1637 if next < self.data.len() {
1638 self.data = self.data.slice(next..);
1639 } else {
1640 self.data = Bytes::new();
1641 }
1642 return s.to_owned();
1643 }
1644
1645 panic!("Cannot find cstr")
1646 }
1647
1648 pub fn uleb128(&mut self) -> u64 {
1649 let mut res = 0u64;
1650 let mut shift = 0i32;
1651 let mut byte: u8;
1652 loop {
1653 byte = self.u8();
1654 let masked = (byte & 0x7f) as u64;
1655 res |= masked << shift;
1656 shift += 7;
1657 if (byte & 0x80) == 0 {
1658 break;
1659 }
1660 }
1661 return res;
1662 }
1663
1664 pub fn sleb128(&mut self) -> i64 {
1665 let mut res = 0u64;
1666 let mut shift = 0i32;
1667 let mut byte: u8;
1668 loop {
1669 byte = self.u8();
1670 let masked = (byte & 0x7f) as u64;
1671 res |= masked << shift;
1672 shift += 7;
1673 if byte & 0x80 == 0 {
1674 break;
1675 }
1676 }
1677 if ((shift as usize) < u64::BITS as usize) && ((byte & 0x40) != 0) {
1678 res |= !0u64 << shift;
1679 }
1680 res as i64
1681 }
1682 #[allow(non_upper_case_globals)]
1683 pub fn skip_form(&mut self, form: u64) -> Result<(), SdbError> {
1684 return match DwForm(form.try_into().unwrap()) {
1685 DW_FORM_flag_present => Ok(()),
1687
1688 DW_FORM_data1 | DW_FORM_ref1 | DW_FORM_flag => {
1690 self.data = self.data.slice(1..);
1691 Ok(())
1692 }
1693 DW_FORM_data2 | DW_FORM_ref2 => {
1694 self.data = self.data.slice(2..);
1695 Ok(())
1696 }
1697 DW_FORM_data4 | DW_FORM_ref4 | DW_FORM_ref_addr | DW_FORM_sec_offset | DW_FORM_strp => {
1698 self.data = self.data.slice(4..);
1699 Ok(())
1700 }
1701 DW_FORM_data8 | DW_FORM_addr => {
1702 self.data = self.data.slice(8..);
1703 Ok(())
1704 }
1705
1706 DW_FORM_sdata => {
1708 self.sleb128();
1709 Ok(())
1710 }
1711 DW_FORM_udata | DW_FORM_ref_udata => {
1712 self.uleb128();
1713 Ok(())
1714 }
1715
1716 DW_FORM_block1 => {
1718 let s = self.u8() as usize;
1719 self.data = self.data.slice(s..);
1720 Ok(())
1721 }
1722 DW_FORM_block2 => {
1723 let s = self.u16() as usize;
1724 self.data = self.data.slice(s..);
1725 Ok(())
1726 }
1727 DW_FORM_block4 => {
1728 let s = self.u32() as usize;
1729 self.data = self.data.slice(s..);
1730 Ok(())
1731 }
1732 DW_FORM_block | DW_FORM_exprloc => {
1733 let s = self.uleb128() as usize;
1734 self.data = self.data.slice(s..);
1735 Ok(())
1736 }
1737
1738 DW_FORM_string => {
1740 while !self.finished() && self.data[0] != 0 {
1741 self.data = self.data.slice(1..);
1742 }
1743 self.data = self.data.slice(1..); Ok(())
1745 }
1746 DW_FORM_indirect => {
1748 let s = self.uleb128();
1749 self.skip_form(s)?;
1750 Ok(())
1751 }
1752 _ => SdbError::err("Unrecognized DWARF form"),
1753 };
1754 }
1755
1756 gen_fixed_int! {
1757 u8 : u8,
1758 u16 : u16,
1759 u32 : u32,
1760 u64 : u64,
1761 s8 : i8,
1762 s16 : i16,
1763 s32 : i32,
1764 s64 : i64,
1765 }
1766}
1767
1768impl AddAssign<usize> for Cursor {
1769 fn add_assign(&mut self, rhs: usize) {
1770 self.data = self.data.slice(rhs..);
1771 }
1772}
1773
1774#[derive(Debug, Clone, Copy)]
1775pub struct UndefinedRule {}
1776#[derive(Debug, Clone, Copy)]
1777pub struct SameRule {}
1778#[derive(Debug, Clone, Copy)]
1779pub struct OffsetRule {
1780 pub offset: i64,
1781}
1782#[derive(Debug, Clone, Copy)]
1783pub struct ValOffsetRule {
1784 pub offset: i64,
1785}
1786#[derive(Debug, Clone, Copy)]
1787pub struct RegisterRule {
1788 pub reg: u32,
1789}
1790#[derive(Debug, Clone, Copy, Default)]
1791pub struct CfaRegisterRule {
1792 pub reg: u32,
1793 pub offset: i64,
1794}
1795#[derive(Clone)]
1796pub struct ExprRule {
1797 pub expr: DwarfExpression,
1798}
1799#[derive(Clone)]
1800pub struct ValExprRule {
1801 pub expr: DwarfExpression,
1802}
1803#[derive(Clone, Default)]
1804pub struct CfaExprRule {
1805 pub expr: DwarfExpression,
1806}
1807
1808#[derive(Clone)]
1809pub enum Rule {
1810 Undefined(UndefinedRule),
1811 Same(SameRule),
1812 Offset(OffsetRule),
1813 ValOffset(ValOffsetRule),
1814 Register(RegisterRule),
1815 CfaRegister(CfaRegisterRule),
1816 Expr(ExprRule),
1817 ValExpr(ValExprRule),
1818}
1819
1820#[derive(Clone)]
1821pub enum CfaRuleType {
1822 Register(CfaRegisterRule),
1823 Expr(CfaExprRule),
1824}
1825
1826impl Default for CfaRuleType {
1827 fn default() -> Self {
1828 Self::Register(CfaRegisterRule::default())
1829 }
1830}
1831
1832pub type RuleSet = HashMap<u32, Rule>;
1833
1834#[derive(Default)]
1835pub struct UnwindContext {
1836 pub cursor: Cursor,
1837 pub location: FileAddress,
1838 pub cfa_rule: CfaRuleType,
1839 pub cie_register_rules: RuleSet,
1840 pub register_rules: RuleSet,
1841 pub rule_stack: Vec<(RuleSet, CfaRuleType)>,
1842}
1843
1844#[derive(Clone)]
1845pub enum DwarfExpressionSimpleLocation {
1846 Address { address: VirtualAddress },
1847 Register { reg_num: u64 },
1848 Data { data: Bytes },
1849 Literal { value: u64 },
1850 Empty {},
1851}
1852
1853#[derive(Clone)]
1854pub struct DwarfExpressionPiece {
1855 pub location: DwarfExpressionSimpleLocation,
1856 pub bit_size: u64,
1857 pub offset: u64, }
1859
1860pub struct DwarfExpressionPiecesResult {
1861 pub pieces: Vec<DwarfExpressionPiece>,
1862}
1863
1864pub enum DwarfExpressionResult {
1865 SimpleLocation(DwarfExpressionSimpleLocation),
1866 Pieces(DwarfExpressionPiecesResult),
1867}
1868
1869#[derive(TypedBuilder, Clone, Default)]
1870pub struct DwarfExpression {
1871 parent: Weak<Dwarf>,
1872 expr_data: Bytes,
1873 in_frame_info: bool,
1874}
1875
1876impl DwarfExpression {
1877 pub fn eval(
1878 &self,
1879 proc: &Process,
1880 regs: &Registers,
1881 push_cfa: bool, ) -> Result<DwarfExpressionResult, SdbError> {
1883 let mut cursor = Cursor::new(&self.expr_data);
1884 let mut stack = Vec::<u64>::new();
1885
1886 if push_cfa {
1887 stack.push(regs.cfa().addr());
1888 }
1889
1890 let mut most_recent_location: Option<DwarfExpressionSimpleLocation> = None;
1891 let mut pieces = Vec::<DwarfExpressionPiece>::new();
1892 let mut result_is_address = true;
1893
1894 let virt_pc = VirtualAddress::from(regs.read_by_id_as::<u64>(RegisterId::rip)?);
1896 let pc = virt_pc.to_file_addr_elf(&self.parent.upgrade().unwrap().elf_file());
1897 let func = self
1898 .parent
1899 .upgrade()
1900 .unwrap()
1901 .function_containing_address(&pc)?;
1902
1903 let binop = |stack: &mut Vec<u64>, op: fn(u64, u64) -> u64| {
1905 let rhs = stack.pop().unwrap();
1906 let lhs = stack.pop().unwrap();
1907 stack.push(op(lhs, rhs));
1908 };
1909
1910 let relop = |stack: &mut Vec<u64>, op: fn(i64, i64) -> bool| {
1912 let rhs = stack.pop().unwrap() as i64;
1913 let lhs = stack.pop().unwrap() as i64;
1914 stack.push(if op(lhs, rhs) { 1 } else { 0 });
1915 };
1916
1917 let get_current_location =
1919 |stack: &mut Vec<u64>,
1920 most_recent_location: &mut Option<DwarfExpressionSimpleLocation>,
1921 result_is_address: &mut bool|
1922 -> DwarfExpressionSimpleLocation {
1923 if stack.is_empty() {
1924 most_recent_location
1925 .take()
1926 .unwrap_or(DwarfExpressionSimpleLocation::Empty {})
1927 } else if *result_is_address {
1928 DwarfExpressionSimpleLocation::Address {
1929 address: VirtualAddress::from(stack.pop().unwrap()),
1930 }
1931 } else {
1932 let value = stack.pop().unwrap();
1933 *result_is_address = true;
1934 DwarfExpressionSimpleLocation::Literal { value }
1935 }
1936 };
1937
1938 while !cursor.finished() {
1939 let opcode = cursor.u8();
1940
1941 if (DW_OP_lit0.0..=DW_OP_lit31.0).contains(&opcode) {
1943 stack.push((opcode - DW_OP_lit0.0) as u64);
1944 }
1945 else if (DW_OP_breg0.0..=DW_OP_breg31.0).contains(&opcode) {
1947 let reg = (opcode - DW_OP_breg0.0) as i32;
1948 let reg_info = register_info_by_dwarf(reg)?;
1949 let reg_val = regs.read(®_info)?;
1950 let offset = cursor.sleb128();
1951 let val = match reg_val {
1952 RegisterValue::U64(v) => v,
1953 _ => return SdbError::err("Invalid register value type for breg operation"),
1954 };
1955 stack.push((val as i64 + offset) as u64);
1956 }
1957 else if (DW_OP_reg0.0..=DW_OP_reg31.0).contains(&opcode) {
1959 let reg = (opcode - DW_OP_reg0.0) as u64;
1960 if self.in_frame_info {
1961 let reg_info = register_info_by_dwarf(reg as i32)?;
1962 let reg_val = regs.read(®_info)?;
1963 let val = match reg_val {
1964 RegisterValue::U64(v) => v,
1965 _ => return SdbError::err("Invalid register value type for reg operation"),
1966 };
1967 stack.push(val);
1968 } else {
1969 most_recent_location =
1970 Some(DwarfExpressionSimpleLocation::Register { reg_num: reg });
1971 }
1972 }
1973
1974 #[allow(non_upper_case_globals)]
1975 match DwOp(opcode) {
1976 DW_OP_addr => {
1977 let addr =
1978 FileAddress::new(&self.parent.upgrade().unwrap().elf_file(), cursor.u64());
1979 let virt_addr = addr.to_virt_addr();
1980 stack.push(virt_addr.addr());
1981 }
1982 DW_OP_const1u => stack.push(cursor.u8() as u64),
1983 DW_OP_const1s => stack.push(cursor.s8() as u64),
1984 DW_OP_const2u => stack.push(cursor.u16() as u64),
1985 DW_OP_const2s => stack.push(cursor.s16() as u64),
1986 DW_OP_const4u => stack.push(cursor.u32() as u64),
1987 DW_OP_const4s => stack.push(cursor.s32() as u64),
1988 DW_OP_const8u => stack.push(cursor.u64()),
1989 DW_OP_const8s => stack.push(cursor.s64() as u64),
1990 DW_OP_constu => stack.push(cursor.uleb128()),
1991 DW_OP_consts => stack.push(cursor.sleb128() as u64),
1992
1993 DW_OP_bregx => {
1994 let reg = cursor.uleb128() as i32;
1995 let reg_info = register_info_by_dwarf(reg)?;
1996 let reg_val = regs.read(®_info)?;
1997 let offset = cursor.sleb128();
1998 let val = match reg_val {
1999 RegisterValue::U64(v) => v,
2000 _ => {
2001 return SdbError::err(
2002 "Invalid register value type for bregx operation",
2003 );
2004 }
2005 };
2006 stack.push((val as i64 + offset) as u64);
2007 }
2008
2009 DW_OP_fbreg => {
2010 let offset = cursor.sleb128();
2011 if let Some(func) = &func {
2012 let fb_loc = func
2013 .index(DW_AT_frame_base.0 as u64)?
2014 .as_evaluated_location(proc, regs, true)?;
2015 let fb_addr = read_frame_base_result(&fb_loc, regs)?;
2016 stack.push((fb_addr.addr() as i64 + offset) as u64);
2017 } else {
2018 return SdbError::err("No function context for DW_OP_fbreg");
2019 }
2020 }
2021
2022 DW_OP_dup => {
2024 let val = *stack.last().unwrap();
2025 stack.push(val);
2026 }
2027 DW_OP_drop => {
2028 stack.pop();
2029 }
2030 DW_OP_pick => {
2031 let idx = cursor.u8() as usize;
2032 let val = stack[stack.len() - 1 - idx];
2033 stack.push(val);
2034 }
2035 DW_OP_over => {
2036 let val = stack[stack.len() - 2];
2037 stack.push(val);
2038 }
2039 DW_OP_swap => {
2040 let len = stack.len();
2041 stack.swap(len - 1, len - 2);
2042 }
2043 DW_OP_rot => {
2044 let c = stack.pop().unwrap();
2045 let b = stack.pop().unwrap();
2046 let a = stack.pop().unwrap();
2047 stack.push(c);
2048 stack.push(a);
2049 stack.push(b);
2050 }
2051
2052 DW_OP_deref => {
2054 let addr = VirtualAddress::from(stack.pop().unwrap());
2055 let val = proc.read_memory_as::<u64>(addr)?;
2056 stack.push(val);
2057 }
2058 DW_OP_deref_size => {
2059 let addr = VirtualAddress::from(stack.pop().unwrap());
2060 let size = cursor.u8() as usize;
2061 let mem = proc.read_memory(addr, size)?;
2062 let mut val = 0u64;
2063 for (i, &byte) in mem.iter().enumerate().take(8) {
2064 val |= (byte as u64) << (i * 8);
2065 }
2066 stack.push(val);
2067 }
2068
2069 DW_OP_xderef => return SdbError::err("DW_OP_xderef not supported"),
2071 DW_OP_xderef_size => return SdbError::err("DW_OP_xderef_size not supported"),
2072 DW_OP_push_object_address => {
2073 return SdbError::err("Unsupported opcode DW_OP_push_object_address");
2074 }
2075 DW_OP_form_tls_address => {
2076 return SdbError::err("Unsupported opcode DW_OP_form_tls_address");
2077 }
2078
2079 DW_OP_call_frame_cfa => {
2080 stack.push(regs.cfa().addr());
2081 }
2082
2083 DW_OP_minus => binop(&mut stack, |lhs, rhs| lhs.wrapping_sub(rhs)),
2085 DW_OP_mod => binop(&mut stack, |lhs, rhs| lhs % rhs),
2086 DW_OP_mul => binop(&mut stack, |lhs, rhs| lhs.wrapping_mul(rhs)),
2087 DW_OP_and => binop(&mut stack, |lhs, rhs| lhs & rhs),
2088 DW_OP_or => binop(&mut stack, |lhs, rhs| lhs | rhs),
2089 DW_OP_plus => binop(&mut stack, |lhs, rhs| lhs.wrapping_add(rhs)),
2090 DW_OP_shl => binop(&mut stack, |lhs, rhs| lhs << rhs),
2091 DW_OP_shr => binop(&mut stack, |lhs, rhs| lhs >> rhs),
2092 DW_OP_shra => binop(&mut stack, |lhs, rhs| ((lhs as i64) >> rhs) as u64),
2093 DW_OP_xor => binop(&mut stack, |lhs, rhs| lhs ^ rhs),
2094
2095 DW_OP_div => {
2096 let rhs = stack.pop().unwrap() as i64;
2097 let lhs = stack.pop().unwrap() as i64;
2098 stack.push((lhs / rhs) as u64);
2099 }
2100
2101 DW_OP_abs => {
2103 let val = stack.pop().unwrap() as i64;
2104 stack.push(val.unsigned_abs());
2105 }
2106 DW_OP_neg => {
2107 let val = stack.pop().unwrap() as i64;
2108 stack.push((-val) as u64);
2109 }
2110 DW_OP_plus_uconst => {
2111 let val = stack.pop().unwrap();
2112 let const_val = cursor.uleb128();
2113 stack.push(val + const_val);
2114 }
2115 DW_OP_not => {
2116 let val = stack.pop().unwrap();
2117 stack.push(!val);
2118 }
2119
2120 DW_OP_le => relop(&mut stack, |lhs, rhs| lhs <= rhs),
2122 DW_OP_ge => relop(&mut stack, |lhs, rhs| lhs >= rhs),
2123 DW_OP_eq => relop(&mut stack, |lhs, rhs| lhs == rhs),
2124 DW_OP_lt => relop(&mut stack, |lhs, rhs| lhs < rhs),
2125 DW_OP_gt => relop(&mut stack, |lhs, rhs| lhs > rhs),
2126 DW_OP_ne => relop(&mut stack, |lhs, rhs| lhs != rhs),
2127
2128 DW_OP_skip => {
2130 let offset = cursor.s16();
2131 cursor += offset as usize;
2132 }
2133 DW_OP_bra => {
2134 let test_val = stack.pop().unwrap();
2135 let offset = cursor.s16();
2136 if test_val != 0 {
2137 cursor += offset as usize;
2138 }
2139 }
2140
2141 DW_OP_call2 => return SdbError::err("Unsupported opcode DW_OP_call2"),
2143 DW_OP_call4 => return SdbError::err("Unsupported opcode DW_OP_call4"),
2144 DW_OP_call_ref => return SdbError::err("Unsupported opcode DW_OP_call_ref"),
2145
2146 DW_OP_regx => {
2147 let reg = cursor.uleb128();
2148 if self.in_frame_info {
2149 let reg_info = register_info_by_dwarf(reg as i32)?;
2150 let reg_val = regs.read(®_info)?;
2151 let val = match reg_val {
2152 RegisterValue::U64(v) => v,
2153 _ => {
2154 return SdbError::err(
2155 "Invalid register value type for regx operation",
2156 );
2157 }
2158 };
2159 stack.push(val);
2160 } else {
2161 most_recent_location =
2162 Some(DwarfExpressionSimpleLocation::Register { reg_num: reg });
2163 }
2164 }
2165
2166 DW_OP_implicit_value => {
2167 let length = cursor.uleb128() as usize;
2168 let data = cursor.position().slice(..length);
2169 most_recent_location = Some(DwarfExpressionSimpleLocation::Data { data });
2170 }
2171
2172 DW_OP_stack_value => {
2173 result_is_address = false;
2174 }
2175
2176 DW_OP_nop => {
2177 }
2179
2180 DW_OP_piece => {
2182 let byte_size = cursor.uleb128();
2183 let loc = get_current_location(
2184 &mut stack,
2185 &mut most_recent_location,
2186 &mut result_is_address,
2187 );
2188 pieces.push(DwarfExpressionPiece {
2189 location: loc,
2190 bit_size: byte_size * 8,
2191 offset: 0,
2192 });
2193 }
2194
2195 DW_OP_bit_piece => {
2196 let bit_size = cursor.uleb128();
2197 let offset = cursor.uleb128();
2198 let loc = get_current_location(
2199 &mut stack,
2200 &mut most_recent_location,
2201 &mut result_is_address,
2202 );
2203 pieces.push(DwarfExpressionPiece {
2204 location: loc,
2205 bit_size,
2206 offset,
2207 });
2208 }
2209
2210 _ => {}
2211 }
2212 }
2213
2214 if !pieces.is_empty() {
2215 return Ok(DwarfExpressionResult::Pieces(DwarfExpressionPiecesResult {
2216 pieces,
2217 }));
2218 }
2219
2220 let final_location = get_current_location(
2221 &mut stack,
2222 &mut most_recent_location,
2223 &mut result_is_address,
2224 );
2225 Ok(DwarfExpressionResult::SimpleLocation(final_location))
2226 }
2227}
2228
2229fn read_frame_base_result(
2230 loc: &DwarfExpressionResult,
2231 _regs: &Registers,
2232) -> Result<VirtualAddress, SdbError> {
2233 let simple_loc = match loc {
2234 DwarfExpressionResult::SimpleLocation(simple_loc) => simple_loc,
2235 _ => return SdbError::err("Unsupported frame base location"),
2236 };
2237 let addr_res = match simple_loc {
2238 DwarfExpressionSimpleLocation::Address { address } => address,
2239 _ => return SdbError::err("Unsupported frame base location"),
2240 };
2241 Ok(*addr_res)
2242}