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