• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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