stackdump_capture_probe/
lib.rs1use probe_rs::MemoryInterface;
2use stackdump_core::{
3 device_memory::MemoryReadError, memory_region::MemoryRegion, register_data::VecRegisterData,
4};
5use std::{cell::RefCell, rc::Rc};
6
7pub struct StackdumpCapturer<'a, 'probe>(RefCell<&'a mut probe_rs::Core<'probe>>);
8
9impl<'a, 'probe> StackdumpCapturer<'a, 'probe> {
10 pub fn new(core: &'a mut probe_rs::Core<'probe>) -> Self {
11 Self(RefCell::new(core))
12 }
13
14 pub fn capture_core_registers(&mut self) -> Result<VecRegisterData<u32>, probe_rs::Error> {
15 let mut register_data = Vec::new();
16 let registers = self.0.get_mut().registers();
17
18 for register in registers.all_registers() {
19 register_data.push(self.0.get_mut().read_core_reg(register)?)
20 }
21
22 let starting_register = match self.0.get_mut().architecture() {
23 probe_rs::Architecture::Arm => stackdump_core::gimli::Arm::R0,
24 probe_rs::Architecture::Riscv => stackdump_core::gimli::RiscV::X0,
25 probe_rs::Architecture::Xtensa => {
26 return Err(probe_rs::Error::NotImplemented(
27 "register capture for Xtensa",
28 ))
29 }
30 };
31
32 Ok(VecRegisterData::new(starting_register, register_data))
33 }
34
35 pub fn capture_fpu_registers(
36 &mut self,
37 ) -> Result<Option<VecRegisterData<u32>>, probe_rs::Error> {
38 let registers = self.0.get_mut().registers();
39
40 match registers.fpu_registers() {
41 Some(fpu_registers) => {
42 let mut register_data = Vec::new();
43
44 for register in fpu_registers {
45 register_data.push(self.0.get_mut().read_core_reg(register)?)
46 }
47
48 let starting_register = match self.0.get_mut().architecture() {
49 probe_rs::Architecture::Arm => stackdump_core::gimli::Arm::S0,
50 probe_rs::Architecture::Riscv => stackdump_core::gimli::RiscV::F0,
51 probe_rs::Architecture::Xtensa => {
52 return Err(probe_rs::Error::NotImplemented(
53 "register capture for Xtensa",
54 ))
55 }
56 };
57
58 Ok(Some(VecRegisterData::new(starting_register, register_data)))
59 }
60 None => Ok(None),
61 }
62 }
63}
64
65impl<'a, 'probe> MemoryRegion for StackdumpCapturer<'a, 'probe> {
66 fn range(&self) -> std::ops::Range<u64> {
67 0..u64::MAX }
69
70 fn read(
71 &self,
72 address_range: std::ops::Range<u64>,
73 ) -> Result<Option<Vec<u8>>, MemoryReadError> {
74 let mut buffer = vec![0; address_range.clone().count()];
75
76 match self
77 .0
78 .borrow_mut()
79 .read(address_range.start as _, &mut buffer)
80 {
81 Ok(_) => Ok(Some(buffer)),
82 Err(e) => Err(MemoryReadError(Rc::new(e))),
83 }
84 }
85}