DebugServer2
Loading...
Searching...
No Matches
CPUState.h
1//
2// Copyright (c) 2014-present, Facebook, Inc.
3// All rights reserved.
4//
5// This source code is licensed under the University of Illinois/NCSA Open
6// Source License found in the LICENSE file in the root directory of this
7// source tree. An additional grant of patent rights can be found in the
8// PATENTS file in the same directory.
9//
10
11#pragma once
12
13#if !defined(CPUSTATE_H_INTERNAL)
14#error "You shall not include this file directly."
15#endif
16
17#include "DebugServer2/Architecture/X86/RegistersDescriptors.h"
18
19#include <cstring>
20
21namespace ds2 {
22namespace Architecture {
23namespace X86 {
24
25#pragma pack(push, 1)
26
27struct SSEVector {
28 uint64_t value[2]; // 128-bit values
29};
30
31struct AVXVector {
32 uint64_t value[4]; // 256-bit values
33};
34
36 uint8_t data[10];
37};
38
39enum XFeature : uint64_t {
40 X86_X87 = 1 << 0,
41 X86_SSE = 1 << 1,
42 X86_AVX = 1 << 2,
43 X86_MPX_BNDREGS = 1 << 3,
44 X86_MPX_CSR = 1 << 4,
45 X86_AVX_512_OPMASK = 1 << 5,
46 X86_AVX_512_HI256 = 1 << 6,
47 X86_AVX_512_ZMM = 1 << 7,
48 X86_PROC_TRACE = 1 << 8,
49 X86_PROT_KEYS_USER_REGS = 1 << 9,
50 X86_UNKNOWN_XFEATURE = 1 << 10,
51};
52
53struct CPUState {
54 union {
55 uint32_t regs[16];
56 struct {
57 uint32_t eax, ecx, edx, ebx, esi, edi, esp, ebp, eip, cs, ss, ds, es, fs,
58 gs, eflags;
59 };
60 } gp;
61
62 struct {
63 X87Register regs[8];
64 uint16_t fstw;
65 uint16_t fctw;
66 uint16_t ftag;
67 uint32_t fiseg;
68 uint32_t fioff;
69 uint32_t foseg;
70 uint32_t fooff;
71 uint16_t fop;
72 } x87;
73
74 union {
75 struct {
76 uint32_t mxcsr;
77 uint32_t mxcsrmask;
78 struct {
79 // Dirty hack to map AVX register locations
80 union {
81 AVXVector _avx[8];
82 SSEVector _sse[16];
83 };
84 SSEVector const &operator[](size_t index) const {
85 return _sse[index << 1];
86 }
87 SSEVector &operator[](size_t index) { return _sse[index << 1]; }
88 } regs;
89 } sse;
90
91 struct {
92 uint32_t mxcsr;
93 uint32_t mxcsrmask;
94 AVXVector regs[8];
95 } avx;
96 };
97
98 struct {
99 uint64_t xfeatures_mask;
100 } xsave_header;
101
102 struct {
103 uint32_t dr[8];
104 } dr;
105
106 uint64_t xcr0;
107
108#if defined(OS_LINUX)
109 struct {
110 uint32_t orig_eax;
111 } linux_gp;
112#endif
113
114public:
115 CPUState() { clear(); }
116
117 inline void clear() {
118 std::memset(&gp, 0, sizeof(gp));
119 std::memset(&x87, 0, sizeof(x87));
120 std::memset(&xsave_header, 0, sizeof(xsave_header));
121 std::memset(&avx, 0, sizeof(avx));
122 std::memset(&dr, 0, sizeof(dr));
123 std::memset(&xcr0, 0, sizeof(xcr0));
124#if defined(OS_LINUX)
125 std::memset(&linux_gp, 0, sizeof(linux_gp));
126#endif
127 }
128
129public:
130 //
131 // Accessors
132 //
133 inline uint32_t pc() const { return gp.eip; }
134 inline void setPC(uint32_t pc) { gp.eip = pc; }
135
136 inline uint32_t xpc() const { return gp.eip; }
137
138 inline uint32_t sp() const { return gp.esp; }
139 inline void setSP(uint32_t sp) { gp.esp = sp; }
140
141 inline uint32_t retval() const { return gp.eax; }
142
143public:
144#define _REGVALUE(REG) \
145 GPRegisterValue { sizeof(gp.REG), gp.REG }
146 //
147 // These two functions interprets regs as GDB packed registers,
148 // the order of GPR state, which is NOT the same order as the reg_gdb_*
149 // (*sigh*)
150 // is as follow:
151 //
152 // eax, ebx, ecx, edx, esi, edi, ebp, esp, eip, eflags, cs, ss, ds, es, fs, gs
153 //
154 inline void getGPState(GPRegisterValueVector &regs) const {
155 regs.clear();
156 regs.push_back(_REGVALUE(eax));
157 regs.push_back(_REGVALUE(ebx));
158 regs.push_back(_REGVALUE(ecx));
159 regs.push_back(_REGVALUE(edx));
160 regs.push_back(_REGVALUE(esi));
161 regs.push_back(_REGVALUE(edi));
162 regs.push_back(_REGVALUE(ebp));
163 regs.push_back(_REGVALUE(esp));
164 regs.push_back(_REGVALUE(eip));
165 regs.push_back(_REGVALUE(eflags));
166 regs.push_back(_REGVALUE(cs));
167 regs.push_back(_REGVALUE(ss));
168 regs.push_back(_REGVALUE(ds));
169 regs.push_back(_REGVALUE(es));
170 regs.push_back(_REGVALUE(fs));
171 regs.push_back(_REGVALUE(gs));
172 }
173
174 inline void setGPState(std::vector<uint64_t> const &regs) {
175 gp.eax = static_cast<uint32_t>(regs[0]);
176 gp.ebx = static_cast<uint32_t>(regs[1]);
177 gp.ecx = static_cast<uint32_t>(regs[2]);
178 gp.edx = static_cast<uint32_t>(regs[3]);
179 gp.esi = static_cast<uint32_t>(regs[4]);
180 gp.edi = static_cast<uint32_t>(regs[5]);
181 gp.ebp = static_cast<uint32_t>(regs[6]);
182 gp.esp = static_cast<uint32_t>(regs[7]);
183 gp.eip = static_cast<uint32_t>(regs[8]);
184 gp.eflags = static_cast<uint32_t>(regs[9]);
185 gp.cs = static_cast<uint32_t>(regs[10]);
186 gp.ss = static_cast<uint32_t>(regs[11]);
187 gp.ds = static_cast<uint32_t>(regs[12]);
188 gp.es = static_cast<uint32_t>(regs[13]);
189 gp.fs = static_cast<uint32_t>(regs[14]);
190 gp.gs = static_cast<uint32_t>(regs[15]);
191 }
192
193public:
194 inline void getStopGPState(GPRegisterStopMap &regs, bool forLLDB) const {
195 auto set = [&](uint32_t lldbReg, uint32_t gdbReg,
196 const GPRegisterValue &value) {
197 regs[forLLDB ? lldbReg : gdbReg] = value;
198 };
199
200 set(reg_lldb_eax, reg_gdb_eax, _REGVALUE(eax));
201 set(reg_lldb_ebx, reg_gdb_ebx, _REGVALUE(ebx));
202 set(reg_lldb_ecx, reg_gdb_ecx, _REGVALUE(ecx));
203 set(reg_lldb_edx, reg_gdb_edx, _REGVALUE(edx));
204 set(reg_lldb_esi, reg_gdb_esi, _REGVALUE(esi));
205 set(reg_lldb_edi, reg_gdb_edi, _REGVALUE(edi));
206 set(reg_lldb_ebp, reg_gdb_ebp, _REGVALUE(ebp));
207 set(reg_lldb_esp, reg_gdb_esp, _REGVALUE(esp));
208 set(reg_lldb_eip, reg_gdb_eip, _REGVALUE(eip));
209 set(reg_lldb_cs, reg_gdb_cs, _REGVALUE(cs));
210 set(reg_lldb_ss, reg_gdb_ss, _REGVALUE(ss));
211 set(reg_lldb_ds, reg_gdb_ds, _REGVALUE(ds));
212 set(reg_lldb_es, reg_gdb_es, _REGVALUE(es));
213 set(reg_lldb_fs, reg_gdb_fs, _REGVALUE(fs));
214 set(reg_lldb_gs, reg_gdb_gs, _REGVALUE(gs));
215 set(reg_lldb_eflags, reg_gdb_eflags, _REGVALUE(eflags));
216 }
217#undef _REGVALUE
218
219public:
220 inline bool getLLDBRegisterPtr(int regno, void **ptr, size_t *length) const {
221#define _GETREG2(T, REG, FLD) \
222 case reg_lldb_##REG: \
223 *ptr = &const_cast<CPUState *>(this)->T.FLD, *length = sizeof(T.FLD); \
224 break
225#define _GETREG8L(T, REG, FREG) \
226 case reg_lldb_##REG: \
227 *ptr = reinterpret_cast<uint8_t *>(&const_cast<CPUState *>(this)->T.FREG), \
228 *length = sizeof(uint8_t); \
229 break
230#define _GETREG8H(T, REG, FREG) \
231 case reg_lldb_##REG: \
232 *ptr = \
233 reinterpret_cast<uint8_t *>(&const_cast<CPUState *>(this)->T.FREG) + \
234 1, \
235 *length = sizeof(uint8_t); \
236 break
237#define _GETREG16(T, REG, FREG) \
238 case reg_lldb_##REG: \
239 *ptr = \
240 reinterpret_cast<uint16_t *>(&const_cast<CPUState *>(this)->T.FREG), \
241 *length = sizeof(uint16_t); \
242 break
243#define _GETREG(T, REG) _GETREG2(T, REG, REG)
244
245 switch (regno) {
246 _GETREG(gp, eax);
247 _GETREG(gp, ebx);
248 _GETREG(gp, ecx);
249 _GETREG(gp, edx);
250 _GETREG(gp, esi);
251 _GETREG(gp, edi);
252 _GETREG(gp, esp);
253 _GETREG(gp, ebp);
254 _GETREG(gp, eip);
255 _GETREG(gp, cs);
256 _GETREG(gp, ss);
257 _GETREG(gp, ds);
258 _GETREG(gp, es);
259 _GETREG(gp, fs);
260 _GETREG(gp, gs);
261 _GETREG(gp, eflags);
262
263 _GETREG16(gp, ax, eax);
264 _GETREG16(gp, bx, ebx);
265 _GETREG16(gp, cx, ecx);
266 _GETREG16(gp, dx, edx);
267 _GETREG16(gp, si, esi);
268 _GETREG16(gp, di, edi);
269 _GETREG16(gp, sp, esp);
270 _GETREG16(gp, bp, ebp);
271
272 _GETREG8L(gp, al, eax);
273 _GETREG8L(gp, bl, ebx);
274 _GETREG8L(gp, cl, ecx);
275 _GETREG8L(gp, dl, edx);
276
277 _GETREG8H(gp, ah, eax);
278 _GETREG8H(gp, bh, ebx);
279 _GETREG8H(gp, ch, ecx);
280 _GETREG8H(gp, dh, edx);
281
282 _GETREG2(x87, st0, regs[0].data);
283 _GETREG2(x87, st1, regs[1].data);
284 _GETREG2(x87, st2, regs[2].data);
285 _GETREG2(x87, st3, regs[3].data);
286 _GETREG2(x87, st4, regs[4].data);
287 _GETREG2(x87, st5, regs[5].data);
288 _GETREG2(x87, st6, regs[6].data);
289 _GETREG2(x87, st7, regs[7].data);
290 _GETREG2(x87, fstat, fstw);
291 _GETREG2(x87, fctrl, fctw);
292 _GETREG(x87, ftag);
293 _GETREG(x87, fiseg);
294 _GETREG(x87, fioff);
295 _GETREG(x87, foseg);
296 _GETREG(x87, fooff);
297 _GETREG(x87, fop);
298
299 _GETREG(avx, mxcsr);
300 _GETREG(avx, mxcsrmask);
301 _GETREG2(avx, ymm0, regs[0]);
302 _GETREG2(avx, ymm1, regs[1]);
303 _GETREG2(avx, ymm2, regs[2]);
304 _GETREG2(avx, ymm3, regs[3]);
305 _GETREG2(avx, ymm4, regs[4]);
306 _GETREG2(avx, ymm5, regs[5]);
307 _GETREG2(avx, ymm6, regs[6]);
308 _GETREG2(avx, ymm7, regs[7]);
309
310 default:
311 return false;
312 }
313#undef _GETREG16
314#undef _GETREG8H
315#undef _GETREG8L
316#undef _GETREG
317#undef _GETREG2
318
319 return true;
320 }
321
322 inline bool getGDBRegisterPtr(int regno, void **ptr, size_t *length) const {
323#define _GETREG2(T, REG, FLD) \
324 case reg_gdb_##REG: \
325 *ptr = &const_cast<CPUState *>(this)->T.FLD, *length = sizeof(T.FLD); \
326 break
327#define _GETREG(T, REG) _GETREG2(T, REG, REG)
328
329 switch (regno) {
330 _GETREG(gp, eax);
331 _GETREG(gp, ebx);
332 _GETREG(gp, ecx);
333 _GETREG(gp, edx);
334 _GETREG(gp, esi);
335 _GETREG(gp, edi);
336 _GETREG(gp, esp);
337 _GETREG(gp, ebp);
338 _GETREG(gp, eip);
339 _GETREG(gp, cs);
340 _GETREG(gp, ss);
341 _GETREG(gp, ds);
342 _GETREG(gp, es);
343 _GETREG(gp, fs);
344 _GETREG(gp, gs);
345 _GETREG(gp, eflags);
346
347 _GETREG2(x87, st0, regs[0].data);
348 _GETREG2(x87, st1, regs[1].data);
349 _GETREG2(x87, st2, regs[2].data);
350 _GETREG2(x87, st3, regs[3].data);
351 _GETREG2(x87, st4, regs[4].data);
352 _GETREG2(x87, st5, regs[5].data);
353 _GETREG2(x87, st6, regs[6].data);
354 _GETREG2(x87, st7, regs[7].data);
355 _GETREG2(x87, fstat, fstw);
356 _GETREG2(x87, fctrl, fctw);
357 _GETREG(x87, ftag);
358 _GETREG(x87, fiseg);
359 _GETREG(x87, fioff);
360 _GETREG(x87, foseg);
361 _GETREG(x87, fooff);
362 _GETREG(x87, fop);
363
364 // ymm0 maps to xmm0 for gdb
365 _GETREG2(sse, ymm0, regs[0]);
366 _GETREG2(sse, ymm1, regs[1]);
367 _GETREG2(sse, ymm2, regs[2]);
368 _GETREG2(sse, ymm3, regs[3]);
369 _GETREG2(sse, ymm4, regs[4]);
370 _GETREG2(sse, ymm5, regs[5]);
371 _GETREG2(sse, ymm6, regs[6]);
372 _GETREG2(sse, ymm7, regs[7]);
373
374 _GETREG(sse, mxcsr);
375
376#if defined(OS_LINUX)
377 _GETREG(linux_gp, orig_eax);
378#endif
379
380 default:
381 return false;
382 }
383#undef _GETREG
384#undef _GETREG2
385
386 return true;
387 }
388};
389
390#pragma pack(pop)
391} // namespace X86
392} // namespace Architecture
393} // namespace ds2
Definition RegisterLayout.h:167
Definition CPUState.h:31
Definition CPUState.h:53
Definition CPUState.h:27
Definition CPUState.h:35