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