1 use core::convert::TryInto; 2 use gdbstub::arch::Registers; 3 4 /// AArch64 core registers. 5 /// 6 /// Registers from the `org.gnu.gdb.aarch64.core` and `org.gnu.gdb.aarch64.fpu` 7 /// [AArch64 Standard GDB Target Features](https://sourceware.org/gdb/onlinedocs/gdb/AArch64-Features.html). 8 #[derive(Debug, Default, Clone, Eq, PartialEq)] 9 pub struct AArch64CoreRegs { 10 /// General Purpose Registers (X0-X30) 11 pub x: [u64; 31], 12 /// Stack Pointer 13 pub sp: u64, 14 /// Program Counter 15 pub pc: u64, 16 /// Process State (GDB uses the AArch32 CPSR name) 17 pub cpsr: u32, 18 /// FP & SIMD Registers (V0-V31) 19 pub v: [u128; 32], 20 /// Floating-point Control Register 21 pub fpcr: u32, 22 /// Floating-point Status Register 23 pub fpsr: u32, 24 } 25 26 impl Registers for AArch64CoreRegs { 27 type ProgramCounter = u64; 28 pc(&self) -> Self::ProgramCounter29 fn pc(&self) -> Self::ProgramCounter { 30 self.pc 31 } 32 gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>))33 fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) { 34 macro_rules! write_bytes { 35 ($var: expr) => { 36 for b in $var.to_le_bytes() { 37 write_byte(Some(b)) 38 } 39 }; 40 } 41 42 for reg in self.x.iter() { 43 write_bytes!(reg); 44 } 45 write_bytes!(self.sp); 46 write_bytes!(self.pc); 47 write_bytes!(self.cpsr); 48 for reg in self.v.iter() { 49 write_bytes!(reg); 50 } 51 write_bytes!(self.fpcr); 52 write_bytes!(self.fpsr); 53 } 54 gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>55 fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> { 56 const CPSR_OFF: usize = core::mem::size_of::<u64>() * 33; 57 const FPSIMD_OFF: usize = CPSR_OFF + core::mem::size_of::<u32>(); 58 const FPCR_OFF: usize = FPSIMD_OFF + core::mem::size_of::<u128>() * 32; 59 const END: usize = FPCR_OFF + core::mem::size_of::<u32>() * 2; 60 61 if bytes.len() < END { 62 return Err(()); 63 } 64 65 let mut regs = bytes[0..CPSR_OFF] 66 .chunks_exact(core::mem::size_of::<u64>()) 67 .map(|c| u64::from_le_bytes(c.try_into().unwrap())); 68 69 for reg in self.x.iter_mut() { 70 *reg = regs.next().ok_or(())? 71 } 72 self.sp = regs.next().ok_or(())?; 73 self.pc = regs.next().ok_or(())?; 74 75 let mut regs = bytes[CPSR_OFF..FPSIMD_OFF] 76 .chunks_exact(core::mem::size_of::<u32>()) 77 .map(|c| u32::from_le_bytes(c.try_into().unwrap())); 78 79 self.cpsr = regs.next().ok_or(())?; 80 81 let mut regs = bytes[FPSIMD_OFF..FPCR_OFF] 82 .chunks_exact(core::mem::size_of::<u128>()) 83 .map(|c| u128::from_le_bytes(c.try_into().unwrap())); 84 85 for reg in self.v.iter_mut() { 86 *reg = regs.next().ok_or(())? 87 } 88 89 let mut regs = bytes[FPCR_OFF..] 90 .chunks_exact(core::mem::size_of::<u32>()) 91 .map(|c| u32::from_le_bytes(c.try_into().unwrap())); 92 93 self.fpcr = regs.next().ok_or(())?; 94 self.fpsr = regs.next().ok_or(())?; 95 96 Ok(()) 97 } 98 } 99