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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
use std::collections::HashMap;
/// A struct to hold the register values and other register information.
#[derive(Debug, Clone)]
pub struct Registers {
/// Holds all the register values.
pub registers: HashMap<u16, u32>,
/// Holds stashed register values. It is used when evaluating values lower down in the stack.
stashed_registers: Option<HashMap<u16, u32>>,
/// The register number which is the program counter register.
pub program_counter_register: Option<usize>,
/// The register number which is the link register.
pub link_register: Option<usize>,
/// The register number which is the stack pointer register.
pub stack_pointer_register: Option<usize>,
/// Canonical Frame Address, which is sometimes needed to evaluate variables.
pub cfa: Option<u32>, // Canonical Frame Address
}
impl Registers {
/// Creates a empty `Registers` struct.
pub fn new() -> Registers {
Registers {
registers: HashMap::new(),
stashed_registers: None,
program_counter_register: None,
link_register: None,
stack_pointer_register: None,
cfa: None,
}
}
/// Add a register value to the struct.
///
/// Description:
///
/// * `register` - The register to add a value for.
/// * `value` - The value that will be stored for that registry.
///
/// This function will add the `value` to the `self.registers` HashMap with `register` as the hash
/// number.
pub fn add_register_value(&mut self, register: u16, value: u32) {
self.registers.insert(register, value);
}
/// Retrieve a register value.
///
/// Description:
///
/// * `register` - The register to get the value from.
///
/// Will retrieve the `register` value from the `self.registers` HashMap.
pub fn get_register_value(&self, register: &u16) -> Option<&u32> {
self.registers.get(register)
}
/// Sets all the register values to `None` in the struct.
pub fn clear(&mut self) {
self.registers = HashMap::new();
self.stashed_registers = None;
}
/// Temporally stash the current register values.
///
/// Description:
///
/// The current register values will be stashed allowing for other register values to be used
/// in the evaluation of variables.
/// This is only used when evaluating `StackFrame`s because preserved register values need to
/// be used in the evaluation.
pub fn stash_registers(&mut self) {
self.stashed_registers = Some(self.registers.clone());
self.registers = HashMap::new();
}
/// Pop the stashed register values.
///
/// Description:
///
/// This is used to pop back the stashed registers into `self.registers`.
/// This function is only called after doing a stack trace because preserved register values is
/// used for evaluating the `StackFrame`s.
pub fn pop_stashed_registers(&mut self) {
if let Some(registers) = self.stashed_registers.clone() {
self.registers = registers;
}
self.stashed_registers = None;
}
}