1 //! `Register` structs for x86 architectures. 2 3 use core::convert::TryInto; 4 use gdbstub::arch::Registers; 5 6 /// `RegId` definitions for x86 architectures. 7 pub mod id; 8 9 mod core32; 10 mod core64; 11 12 pub use core32::X86CoreRegs; 13 pub use core64::X86_64CoreRegs; 14 15 /// 80-bit floating point value 16 pub type F80 = [u8; 10]; 17 18 /// FPU registers 19 #[derive(Debug, Default, Clone, PartialEq, Eq)] 20 pub struct X87FpuInternalRegs { 21 /// Floating-point control register 22 pub fctrl: u32, 23 /// Floating-point status register 24 pub fstat: u32, 25 /// Tag word 26 pub ftag: u32, 27 /// FPU instruction pointer segment 28 pub fiseg: u32, 29 /// FPU instruction pointer offset 30 pub fioff: u32, 31 /// FPU operand segment 32 pub foseg: u32, 33 /// FPU operand offset 34 pub fooff: u32, 35 /// Floating-point opcode 36 pub fop: u32, 37 } 38 39 impl Registers for X87FpuInternalRegs { 40 type ProgramCounter = u32; 41 42 // HACK: this struct is never used as an architecture's main register file, so 43 // using a dummy value here is fine. pc(&self) -> Self::ProgramCounter44 fn pc(&self) -> Self::ProgramCounter { 45 0 46 } 47 gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>))48 fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) { 49 macro_rules! write_bytes { 50 ($bytes:expr) => { 51 for b in $bytes { 52 write_byte(Some(*b)) 53 } 54 }; 55 } 56 57 // Note: GDB section names don't make sense unless you read x87 FPU section 8.1: 58 // https://web.archive.org/web/20150123212110/http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-1-manual.pdf 59 write_bytes!(&self.fctrl.to_le_bytes()); 60 write_bytes!(&self.fstat.to_le_bytes()); 61 write_bytes!(&self.ftag.to_le_bytes()); 62 write_bytes!(&self.fiseg.to_le_bytes()); 63 write_bytes!(&self.fioff.to_le_bytes()); 64 write_bytes!(&self.foseg.to_le_bytes()); 65 write_bytes!(&self.fooff.to_le_bytes()); 66 write_bytes!(&self.fop.to_le_bytes()); 67 } 68 gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>69 fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> { 70 if bytes.len() != 0x20 { 71 return Err(()); 72 } 73 74 let mut regs = bytes 75 .chunks_exact(4) 76 .map(|x| u32::from_le_bytes(x.try_into().unwrap())); 77 78 self.fctrl = regs.next().ok_or(())?; 79 self.fstat = regs.next().ok_or(())?; 80 self.ftag = regs.next().ok_or(())?; 81 self.fiseg = regs.next().ok_or(())?; 82 self.fioff = regs.next().ok_or(())?; 83 self.foseg = regs.next().ok_or(())?; 84 self.fooff = regs.next().ok_or(())?; 85 self.fop = regs.next().ok_or(())?; 86 87 Ok(()) 88 } 89 } 90 91 /// x86 segment registers. 92 /// 93 /// Source: <https://github.com/bminor/binutils-gdb/blob/master/gdb/features/i386/64bit-core.xml> 94 #[derive(Debug, Default, Clone, PartialEq, Eq)] 95 pub struct X86SegmentRegs { 96 /// Code Segment 97 pub cs: u32, 98 /// Stack Segment 99 pub ss: u32, 100 /// Data Segment 101 pub ds: u32, 102 /// Extra Segment 103 pub es: u32, 104 /// General Purpose Segment 105 pub fs: u32, 106 /// General Purpose Segment 107 pub gs: u32, 108 } 109 110 impl Registers for X86SegmentRegs { 111 type ProgramCounter = u32; 112 113 // HACK: this struct is never used as an architecture's main register file, so 114 // using a dummy value here is fine. pc(&self) -> Self::ProgramCounter115 fn pc(&self) -> Self::ProgramCounter { 116 0 117 } 118 gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>))119 fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) { 120 macro_rules! write_bytes { 121 ($bytes:expr) => { 122 for b in $bytes { 123 write_byte(Some(*b)) 124 } 125 }; 126 } 127 128 write_bytes!(&self.cs.to_le_bytes()); 129 write_bytes!(&self.ss.to_le_bytes()); 130 write_bytes!(&self.ds.to_le_bytes()); 131 write_bytes!(&self.es.to_le_bytes()); 132 write_bytes!(&self.fs.to_le_bytes()); 133 write_bytes!(&self.gs.to_le_bytes()); 134 } 135 gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>136 fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> { 137 if bytes.len() != core::mem::size_of::<u32>() * 6 { 138 return Err(()); 139 } 140 141 let mut regs = bytes 142 .chunks_exact(4) 143 .map(|x| u32::from_le_bytes(x.try_into().unwrap())); 144 145 self.cs = regs.next().ok_or(())?; 146 self.ss = regs.next().ok_or(())?; 147 self.ds = regs.next().ok_or(())?; 148 self.es = regs.next().ok_or(())?; 149 self.fs = regs.next().ok_or(())?; 150 self.gs = regs.next().ok_or(())?; 151 152 Ok(()) 153 } 154 } 155