1 use super::X86SegmentRegs; 2 use super::X87FpuInternalRegs; 3 use super::F80; 4 use core::convert::TryInto; 5 use gdbstub::arch::Registers; 6 7 /// 64-bit x86 core registers (+ SSE extensions). 8 /// 9 /// Source: <https://github.com/bminor/binutils-gdb/blob/master/gdb/features/i386/64bit-core.xml> 10 /// Additionally: <https://github.com/bminor/binutils-gdb/blob/master/gdb/features/i386/64bit-sse.xml> 11 #[derive(Debug, Default, Clone, PartialEq, Eq)] 12 pub struct X86_64CoreRegs { 13 /// RAX, RBX, RCX, RDX, RSI, RDI, RBP, RSP, r8-r15 14 pub regs: [u64; 16], 15 /// Status register 16 pub eflags: u32, 17 /// Instruction pointer 18 pub rip: u64, 19 /// Segment registers: CS, SS, DS, ES, FS, GS 20 pub segments: X86SegmentRegs, 21 /// FPU registers: ST0 through ST7 22 pub st: [F80; 8], 23 /// FPU internal registers 24 pub fpu: X87FpuInternalRegs, 25 /// SIMD Registers: XMM0 through XMM15 26 pub xmm: [u128; 0x10], 27 /// SSE Status/Control Register 28 pub mxcsr: u32, 29 } 30 31 impl Registers for X86_64CoreRegs { 32 type ProgramCounter = u64; 33 pc(&self) -> Self::ProgramCounter34 fn pc(&self) -> Self::ProgramCounter { 35 self.rip 36 } 37 gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>))38 fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) { 39 macro_rules! write_bytes { 40 ($bytes:expr) => { 41 for b in $bytes { 42 write_byte(Some(*b)) 43 } 44 }; 45 } 46 47 // rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp, r8-r15 48 for reg in &self.regs { 49 write_bytes!(®.to_le_bytes()); 50 } 51 52 // rip 53 write_bytes!(&self.rip.to_le_bytes()); 54 55 // eflags 56 write_bytes!(&self.eflags.to_le_bytes()); 57 58 self.segments.gdb_serialize(&mut write_byte); 59 60 // st0 to st7 61 for st_reg in &self.st { 62 write_bytes!(st_reg); 63 } 64 65 self.fpu.gdb_serialize(&mut write_byte); 66 67 // xmm0 to xmm15 68 for xmm_reg in &self.xmm { 69 write_bytes!(&xmm_reg.to_le_bytes()); 70 } 71 72 // mxcsr 73 write_bytes!(&self.mxcsr.to_le_bytes()); 74 75 // padding? 76 // XXX: Couldn't figure out what these do and GDB doesn't actually display any 77 // registers that use these values. 78 (0..0x18).for_each(|_| write_byte(None)) 79 } 80 gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>81 fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> { 82 if bytes.len() < 0x218 { 83 return Err(()); 84 } 85 86 let mut regs = bytes[0..0x80] 87 .chunks_exact(8) 88 .map(|x| u64::from_le_bytes(x.try_into().unwrap())); 89 90 for reg in self.regs.iter_mut() { 91 *reg = regs.next().ok_or(())?; 92 } 93 94 self.rip = u64::from_le_bytes(bytes[0x80..0x88].try_into().unwrap()); 95 self.eflags = u32::from_le_bytes(bytes[0x88..0x8C].try_into().unwrap()); 96 97 self.segments.gdb_deserialize(&bytes[0x8C..0xA4])?; 98 99 let mut regs = bytes[0xA4..0xF4].chunks_exact(10).map(TryInto::try_into); 100 101 for reg in self.st.iter_mut() { 102 *reg = regs.next().ok_or(())?.map_err(|_| ())?; 103 } 104 105 self.fpu.gdb_deserialize(&bytes[0xF4..0x114])?; 106 107 let mut regs = bytes[0x114..0x214] 108 .chunks_exact(0x10) 109 .map(|x| u128::from_le_bytes(x.try_into().unwrap())); 110 111 for reg in self.xmm.iter_mut() { 112 *reg = regs.next().ok_or(())?; 113 } 114 115 self.mxcsr = u32::from_le_bytes(bytes[0x214..0x218].try_into().unwrap()); 116 117 Ok(()) 118 } 119 } 120