1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use probe_rs::MemoryInterface;
use stackdump_core::{
    device_memory::MemoryReadError, memory_region::MemoryRegion, register_data::VecRegisterData,
};
use std::{cell::RefCell, rc::Rc};

pub struct StackdumpCapturer<'a, 'probe>(RefCell<&'a mut probe_rs::Core<'probe>>);

impl<'a, 'probe> StackdumpCapturer<'a, 'probe> {
    pub fn new(core: &'a mut probe_rs::Core<'probe>) -> Self {
        Self(RefCell::new(core))
    }

    pub fn capture_core_registers(&mut self) -> Result<VecRegisterData<u32>, probe_rs::Error> {
        let mut register_data = Vec::new();
        let registers = self.0.get_mut().registers();

        for register in registers.platform_registers() {
            register_data.push(self.0.get_mut().read_core_reg(register)?)
        }

        let starting_register = match self.0.get_mut().architecture() {
            probe_rs::Architecture::Arm => stackdump_core::gimli::Arm::R0,
            probe_rs::Architecture::Riscv => stackdump_core::gimli::RiscV::X0,
        };

        Ok(VecRegisterData::new(starting_register, register_data))
    }

    pub fn capture_fpu_registers(
        &mut self,
    ) -> Result<Option<VecRegisterData<u32>>, probe_rs::Error> {
        let registers = self.0.get_mut().registers();

        match registers.fpu_registers() {
            Some(fpu_registers) => {
                let mut register_data = Vec::new();

                for register in fpu_registers {
                    register_data.push(self.0.get_mut().read_core_reg(register)?)
                }

                let starting_register = match self.0.get_mut().architecture() {
                    probe_rs::Architecture::Arm => stackdump_core::gimli::Arm::S0,
                    probe_rs::Architecture::Riscv => stackdump_core::gimli::RiscV::F0,
                };

                Ok(Some(VecRegisterData::new(starting_register, register_data)))
            }
            None => Ok(None),
        }
    }
}

impl<'a, 'probe> MemoryRegion for StackdumpCapturer<'a, 'probe> {
    fn read(
        &self,
        address_range: std::ops::Range<u64>,
    ) -> Result<Option<Vec<u8>>, MemoryReadError> {
        let mut buffer = vec![0; address_range.clone().count()];

        // Truncating to u32 is alright because probe-rs only supports 32-bit devices
        match self
            .0
            .borrow_mut()
            .read(address_range.start as _, &mut buffer)
        {
            Ok(_) => Ok(Some(buffer)),
            Err(e) => Err(MemoryReadError(Rc::new(e))),
        }
    }
}