1 | //===-- RegisterContextDarwin_i386.cpp ------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "lldb/Utility/DataBufferHeap.h" |
10 | #include "lldb/Utility/DataExtractor.h" |
11 | #include "lldb/Utility/Endian.h" |
12 | #include "lldb/Utility/Log.h" |
13 | #include "lldb/Utility/RegisterValue.h" |
14 | #include "lldb/Utility/Scalar.h" |
15 | #include "llvm/ADT/STLExtras.h" |
16 | #include "llvm/Support/Compiler.h" |
17 | |
18 | #include <cstddef> |
19 | |
20 | #include <memory> |
21 | |
22 | #include "RegisterContextDarwin_i386.h" |
23 | |
24 | using namespace lldb; |
25 | using namespace lldb_private; |
26 | |
27 | enum { |
28 | gpr_eax = 0, |
29 | gpr_ebx, |
30 | gpr_ecx, |
31 | gpr_edx, |
32 | gpr_edi, |
33 | gpr_esi, |
34 | gpr_ebp, |
35 | gpr_esp, |
36 | gpr_ss, |
37 | gpr_eflags, |
38 | gpr_eip, |
39 | gpr_cs, |
40 | gpr_ds, |
41 | gpr_es, |
42 | gpr_fs, |
43 | gpr_gs, |
44 | |
45 | fpu_fcw, |
46 | fpu_fsw, |
47 | fpu_ftw, |
48 | fpu_fop, |
49 | fpu_ip, |
50 | fpu_cs, |
51 | fpu_dp, |
52 | fpu_ds, |
53 | fpu_mxcsr, |
54 | fpu_mxcsrmask, |
55 | fpu_stmm0, |
56 | fpu_stmm1, |
57 | fpu_stmm2, |
58 | fpu_stmm3, |
59 | fpu_stmm4, |
60 | fpu_stmm5, |
61 | fpu_stmm6, |
62 | fpu_stmm7, |
63 | fpu_xmm0, |
64 | fpu_xmm1, |
65 | fpu_xmm2, |
66 | fpu_xmm3, |
67 | fpu_xmm4, |
68 | fpu_xmm5, |
69 | fpu_xmm6, |
70 | fpu_xmm7, |
71 | |
72 | exc_trapno, |
73 | exc_err, |
74 | exc_faultvaddr, |
75 | |
76 | k_num_registers, |
77 | |
78 | // Aliases |
79 | fpu_fctrl = fpu_fcw, |
80 | fpu_fstat = fpu_fsw, |
81 | fpu_ftag = fpu_ftw, |
82 | fpu_fiseg = fpu_cs, |
83 | fpu_fioff = fpu_ip, |
84 | fpu_foseg = fpu_ds, |
85 | fpu_fooff = fpu_dp |
86 | }; |
87 | |
88 | enum { |
89 | ehframe_eax = 0, |
90 | ehframe_ecx, |
91 | ehframe_edx, |
92 | ehframe_ebx, |
93 | ehframe_ebp, |
94 | ehframe_esp, |
95 | ehframe_esi, |
96 | ehframe_edi, |
97 | ehframe_eip, |
98 | ehframe_eflags |
99 | }; |
100 | |
101 | enum { |
102 | dwarf_eax = 0, |
103 | dwarf_ecx, |
104 | dwarf_edx, |
105 | dwarf_ebx, |
106 | dwarf_esp, |
107 | dwarf_ebp, |
108 | dwarf_esi, |
109 | dwarf_edi, |
110 | dwarf_eip, |
111 | dwarf_eflags, |
112 | dwarf_stmm0 = 11, |
113 | dwarf_stmm1, |
114 | dwarf_stmm2, |
115 | dwarf_stmm3, |
116 | dwarf_stmm4, |
117 | dwarf_stmm5, |
118 | dwarf_stmm6, |
119 | dwarf_stmm7, |
120 | dwarf_xmm0 = 21, |
121 | dwarf_xmm1, |
122 | dwarf_xmm2, |
123 | dwarf_xmm3, |
124 | dwarf_xmm4, |
125 | dwarf_xmm5, |
126 | dwarf_xmm6, |
127 | dwarf_xmm7 |
128 | }; |
129 | |
130 | #define GPR_OFFSET(reg) \ |
131 | (LLVM_EXTENSION offsetof(RegisterContextDarwin_i386::GPR, reg)) |
132 | #define FPU_OFFSET(reg) \ |
133 | (LLVM_EXTENSION offsetof(RegisterContextDarwin_i386::FPU, reg) + \ |
134 | sizeof(RegisterContextDarwin_i386::GPR)) |
135 | #define EXC_OFFSET(reg) \ |
136 | (LLVM_EXTENSION offsetof(RegisterContextDarwin_i386::EXC, reg) + \ |
137 | sizeof(RegisterContextDarwin_i386::GPR) + \ |
138 | sizeof(RegisterContextDarwin_i386::FPU)) |
139 | |
140 | // These macros will auto define the register name, alt name, register size, |
141 | // register offset, encoding, format and native register. This ensures that the |
142 | // register state structures are defined correctly and have the correct sizes |
143 | // and offsets. |
144 | #define DEFINE_GPR(reg, alt) \ |
145 | #reg, alt, sizeof(((RegisterContextDarwin_i386::GPR *) NULL)->reg), \ |
146 | GPR_OFFSET(reg), eEncodingUint, eFormatHex |
147 | #define DEFINE_FPU_UINT(reg) \ |
148 | #reg, NULL, sizeof(((RegisterContextDarwin_i386::FPU *) NULL)->reg), \ |
149 | FPU_OFFSET(reg), eEncodingUint, eFormatHex |
150 | #define DEFINE_FPU_VECT(reg, i) \ |
151 | #reg #i, NULL, \ |
152 | sizeof(((RegisterContextDarwin_i386::FPU *) NULL)->reg[i].bytes), \ |
153 | FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, \ |
154 | {LLDB_INVALID_REGNUM, dwarf_##reg##i, \ |
155 | LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ |
156 | fpu_##reg##i }, \ |
157 | nullptr, nullptr, nullptr, |
158 | |
159 | #define DEFINE_EXC(reg) \ |
160 | #reg, NULL, sizeof(((RegisterContextDarwin_i386::EXC *) NULL)->reg), \ |
161 | EXC_OFFSET(reg), eEncodingUint, eFormatHex |
162 | #define REG_CONTEXT_SIZE \ |
163 | (sizeof(RegisterContextDarwin_i386::GPR) + \ |
164 | sizeof(RegisterContextDarwin_i386::FPU) + \ |
165 | sizeof(RegisterContextDarwin_i386::EXC)) |
166 | |
167 | static RegisterInfo g_register_infos[] = { |
168 | // Macro auto defines most stuff eh_frame DWARF |
169 | // GENERIC PROCESS PLUGIN LLDB |
170 | // =============================== ======================= |
171 | // =================== ========================= ================== |
172 | // ================= |
173 | {DEFINE_GPR(eax, nullptr), |
174 | .kinds: {ehframe_eax, dwarf_eax, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
175 | gpr_eax}, |
176 | .value_regs: nullptr, |
177 | .invalidate_regs: nullptr, |
178 | .flags_type: nullptr, |
179 | }, |
180 | {DEFINE_GPR(ebx, nullptr), |
181 | .kinds: {ehframe_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
182 | gpr_ebx}, |
183 | .value_regs: nullptr, |
184 | .invalidate_regs: nullptr, |
185 | .flags_type: nullptr, |
186 | }, |
187 | {DEFINE_GPR(ecx, nullptr), |
188 | .kinds: {ehframe_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
189 | gpr_ecx}, |
190 | .value_regs: nullptr, |
191 | .invalidate_regs: nullptr, |
192 | .flags_type: nullptr, |
193 | }, |
194 | {DEFINE_GPR(edx, nullptr), |
195 | .kinds: {ehframe_edx, dwarf_edx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
196 | gpr_edx}, |
197 | .value_regs: nullptr, |
198 | .invalidate_regs: nullptr, |
199 | .flags_type: nullptr, |
200 | }, |
201 | {DEFINE_GPR(edi, nullptr), |
202 | .kinds: {ehframe_edi, dwarf_edi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
203 | gpr_edi}, |
204 | .value_regs: nullptr, |
205 | .invalidate_regs: nullptr, |
206 | .flags_type: nullptr, |
207 | }, |
208 | {DEFINE_GPR(esi, nullptr), |
209 | .kinds: {ehframe_esi, dwarf_esi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
210 | gpr_esi}, |
211 | .value_regs: nullptr, |
212 | .invalidate_regs: nullptr, |
213 | .flags_type: nullptr, |
214 | }, |
215 | {DEFINE_GPR(ebp, "fp" ), |
216 | .kinds: {ehframe_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, |
217 | gpr_ebp}, |
218 | .value_regs: nullptr, |
219 | .invalidate_regs: nullptr, |
220 | .flags_type: nullptr, |
221 | }, |
222 | {DEFINE_GPR(esp, "sp" ), |
223 | .kinds: {ehframe_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, |
224 | gpr_esp}, |
225 | .value_regs: nullptr, |
226 | .invalidate_regs: nullptr, |
227 | .flags_type: nullptr, |
228 | }, |
229 | {DEFINE_GPR(ss, nullptr), |
230 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
231 | LLDB_INVALID_REGNUM, gpr_ss}, |
232 | .value_regs: nullptr, |
233 | .invalidate_regs: nullptr, |
234 | .flags_type: nullptr, |
235 | }, |
236 | {DEFINE_GPR(eflags, "flags" ), |
237 | .kinds: {ehframe_eflags, dwarf_eflags, LLDB_REGNUM_GENERIC_FLAGS, |
238 | LLDB_INVALID_REGNUM, gpr_eflags}, |
239 | .value_regs: nullptr, |
240 | .invalidate_regs: nullptr, |
241 | .flags_type: nullptr, |
242 | }, |
243 | {DEFINE_GPR(eip, "pc" ), |
244 | .kinds: {ehframe_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, |
245 | gpr_eip}, |
246 | .value_regs: nullptr, |
247 | .invalidate_regs: nullptr, |
248 | .flags_type: nullptr, |
249 | }, |
250 | {DEFINE_GPR(cs, nullptr), |
251 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
252 | LLDB_INVALID_REGNUM, gpr_cs}, |
253 | .value_regs: nullptr, |
254 | .invalidate_regs: nullptr, |
255 | .flags_type: nullptr, |
256 | }, |
257 | {DEFINE_GPR(ds, nullptr), |
258 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
259 | LLDB_INVALID_REGNUM, gpr_ds}, |
260 | .value_regs: nullptr, |
261 | .invalidate_regs: nullptr, |
262 | .flags_type: nullptr, |
263 | }, |
264 | {DEFINE_GPR(es, nullptr), |
265 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
266 | LLDB_INVALID_REGNUM, gpr_es}, |
267 | .value_regs: nullptr, |
268 | .invalidate_regs: nullptr, |
269 | .flags_type: nullptr, |
270 | }, |
271 | {DEFINE_GPR(fs, nullptr), |
272 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
273 | LLDB_INVALID_REGNUM, gpr_fs}, |
274 | .value_regs: nullptr, |
275 | .invalidate_regs: nullptr, |
276 | .flags_type: nullptr, |
277 | }, |
278 | {DEFINE_GPR(gs, nullptr), |
279 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
280 | LLDB_INVALID_REGNUM, gpr_gs}, |
281 | .value_regs: nullptr, |
282 | .invalidate_regs: nullptr, |
283 | .flags_type: nullptr, |
284 | }, |
285 | |
286 | {DEFINE_FPU_UINT(fcw), |
287 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
288 | LLDB_INVALID_REGNUM, fpu_fcw}, |
289 | .value_regs: nullptr, |
290 | .invalidate_regs: nullptr, |
291 | .flags_type: nullptr, |
292 | }, |
293 | {DEFINE_FPU_UINT(fsw), |
294 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
295 | LLDB_INVALID_REGNUM, fpu_fsw}, |
296 | .value_regs: nullptr, |
297 | .invalidate_regs: nullptr, |
298 | .flags_type: nullptr, |
299 | }, |
300 | {DEFINE_FPU_UINT(ftw), |
301 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
302 | LLDB_INVALID_REGNUM, fpu_ftw}, |
303 | .value_regs: nullptr, |
304 | .invalidate_regs: nullptr, |
305 | .flags_type: nullptr, |
306 | }, |
307 | {DEFINE_FPU_UINT(fop), |
308 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
309 | LLDB_INVALID_REGNUM, fpu_fop}, |
310 | .value_regs: nullptr, |
311 | .invalidate_regs: nullptr, |
312 | .flags_type: nullptr, |
313 | }, |
314 | {DEFINE_FPU_UINT(ip), |
315 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
316 | LLDB_INVALID_REGNUM, fpu_ip}, |
317 | .value_regs: nullptr, |
318 | .invalidate_regs: nullptr, |
319 | .flags_type: nullptr, |
320 | }, |
321 | {DEFINE_FPU_UINT(cs), |
322 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
323 | LLDB_INVALID_REGNUM, fpu_cs}, |
324 | .value_regs: nullptr, |
325 | .invalidate_regs: nullptr, |
326 | .flags_type: nullptr, |
327 | }, |
328 | {DEFINE_FPU_UINT(dp), |
329 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
330 | LLDB_INVALID_REGNUM, fpu_dp}, |
331 | .value_regs: nullptr, |
332 | .invalidate_regs: nullptr, |
333 | .flags_type: nullptr, |
334 | }, |
335 | {DEFINE_FPU_UINT(ds), |
336 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
337 | LLDB_INVALID_REGNUM, fpu_ds}, |
338 | .value_regs: nullptr, |
339 | .invalidate_regs: nullptr, |
340 | .flags_type: nullptr, |
341 | }, |
342 | {DEFINE_FPU_UINT(mxcsr), |
343 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
344 | LLDB_INVALID_REGNUM, fpu_mxcsr}, |
345 | .value_regs: nullptr, |
346 | .invalidate_regs: nullptr, |
347 | .flags_type: nullptr, |
348 | }, |
349 | {DEFINE_FPU_UINT(mxcsrmask), |
350 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
351 | LLDB_INVALID_REGNUM, fpu_mxcsrmask}, |
352 | .value_regs: nullptr, |
353 | .invalidate_regs: nullptr, |
354 | .flags_type: nullptr, |
355 | }, |
356 | {DEFINE_FPU_VECT(stmm, 0)}, |
357 | {DEFINE_FPU_VECT(stmm, 1)}, |
358 | {DEFINE_FPU_VECT(stmm, 2)}, |
359 | {DEFINE_FPU_VECT(stmm, 3)}, |
360 | {DEFINE_FPU_VECT(stmm, 4)}, |
361 | {DEFINE_FPU_VECT(stmm, 5)}, |
362 | {DEFINE_FPU_VECT(stmm, 6)}, |
363 | {DEFINE_FPU_VECT(stmm, 7)}, |
364 | {DEFINE_FPU_VECT(xmm, 0)}, |
365 | {DEFINE_FPU_VECT(xmm, 1)}, |
366 | {DEFINE_FPU_VECT(xmm, 2)}, |
367 | {DEFINE_FPU_VECT(xmm, 3)}, |
368 | {DEFINE_FPU_VECT(xmm, 4)}, |
369 | {DEFINE_FPU_VECT(xmm, 5)}, |
370 | {DEFINE_FPU_VECT(xmm, 6)}, |
371 | {DEFINE_FPU_VECT(xmm, 7)}, |
372 | |
373 | {DEFINE_EXC(trapno), |
374 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
375 | LLDB_INVALID_REGNUM, exc_trapno}, |
376 | .value_regs: nullptr, |
377 | .invalidate_regs: nullptr, |
378 | .flags_type: nullptr, |
379 | }, |
380 | {DEFINE_EXC(err), |
381 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
382 | LLDB_INVALID_REGNUM, exc_err}, |
383 | .value_regs: nullptr, |
384 | .invalidate_regs: nullptr, |
385 | .flags_type: nullptr, |
386 | }, |
387 | {DEFINE_EXC(faultvaddr), |
388 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
389 | LLDB_INVALID_REGNUM, exc_faultvaddr}, |
390 | .value_regs: nullptr, |
391 | .invalidate_regs: nullptr, |
392 | .flags_type: nullptr, |
393 | }}; |
394 | |
395 | static size_t k_num_register_infos = std::size(g_register_infos); |
396 | |
397 | RegisterContextDarwin_i386::RegisterContextDarwin_i386( |
398 | Thread &thread, uint32_t concrete_frame_idx) |
399 | : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc() { |
400 | uint32_t i; |
401 | for (i = 0; i < kNumErrors; i++) { |
402 | gpr_errs[i] = -1; |
403 | fpu_errs[i] = -1; |
404 | exc_errs[i] = -1; |
405 | } |
406 | } |
407 | |
408 | RegisterContextDarwin_i386::~RegisterContextDarwin_i386() = default; |
409 | |
410 | void RegisterContextDarwin_i386::InvalidateAllRegisters() { |
411 | InvalidateAllRegisterStates(); |
412 | } |
413 | |
414 | size_t RegisterContextDarwin_i386::GetRegisterCount() { |
415 | assert(k_num_register_infos == k_num_registers); |
416 | return k_num_registers; |
417 | } |
418 | |
419 | const RegisterInfo * |
420 | RegisterContextDarwin_i386::GetRegisterInfoAtIndex(size_t reg) { |
421 | assert(k_num_register_infos == k_num_registers); |
422 | if (reg < k_num_registers) |
423 | return &g_register_infos[reg]; |
424 | return nullptr; |
425 | } |
426 | |
427 | size_t RegisterContextDarwin_i386::GetRegisterInfosCount() { |
428 | return k_num_register_infos; |
429 | } |
430 | |
431 | const RegisterInfo *RegisterContextDarwin_i386::GetRegisterInfos() { |
432 | return g_register_infos; |
433 | } |
434 | |
435 | // General purpose registers |
436 | static uint32_t g_gpr_regnums[] = { |
437 | gpr_eax, gpr_ebx, gpr_ecx, gpr_edx, gpr_edi, gpr_esi, gpr_ebp, gpr_esp, |
438 | gpr_ss, gpr_eflags, gpr_eip, gpr_cs, gpr_ds, gpr_es, gpr_fs, gpr_gs}; |
439 | |
440 | // Floating point registers |
441 | static uint32_t g_fpu_regnums[] = { |
442 | fpu_fcw, fpu_fsw, fpu_ftw, fpu_fop, fpu_ip, fpu_cs, |
443 | fpu_dp, fpu_ds, fpu_mxcsr, fpu_mxcsrmask, fpu_stmm0, fpu_stmm1, |
444 | fpu_stmm2, fpu_stmm3, fpu_stmm4, fpu_stmm5, fpu_stmm6, fpu_stmm7, |
445 | fpu_xmm0, fpu_xmm1, fpu_xmm2, fpu_xmm3, fpu_xmm4, fpu_xmm5, |
446 | fpu_xmm6, fpu_xmm7}; |
447 | |
448 | // Exception registers |
449 | |
450 | static uint32_t g_exc_regnums[] = {exc_trapno, exc_err, exc_faultvaddr}; |
451 | |
452 | // Number of registers in each register set |
453 | const size_t k_num_gpr_registers = std::size(g_gpr_regnums); |
454 | const size_t k_num_fpu_registers = std::size(g_fpu_regnums); |
455 | const size_t k_num_exc_registers = std::size(g_exc_regnums); |
456 | |
457 | // Register set definitions. The first definitions at register set index of |
458 | // zero is for all registers, followed by other registers sets. The register |
459 | // information for the all register set need not be filled in. |
460 | static const RegisterSet g_reg_sets[] = { |
461 | { |
462 | .name: "General Purpose Registers" , .short_name: "gpr" , .num_registers: k_num_gpr_registers, .registers: g_gpr_regnums, |
463 | }, |
464 | {.name: "Floating Point Registers" , .short_name: "fpu" , .num_registers: k_num_fpu_registers, .registers: g_fpu_regnums}, |
465 | {.name: "Exception State Registers" , .short_name: "exc" , .num_registers: k_num_exc_registers, .registers: g_exc_regnums}}; |
466 | |
467 | const size_t k_num_regsets = std::size(g_reg_sets); |
468 | |
469 | size_t RegisterContextDarwin_i386::GetRegisterSetCount() { |
470 | return k_num_regsets; |
471 | } |
472 | |
473 | const RegisterSet *RegisterContextDarwin_i386::GetRegisterSet(size_t reg_set) { |
474 | if (reg_set < k_num_regsets) |
475 | return &g_reg_sets[reg_set]; |
476 | return nullptr; |
477 | } |
478 | |
479 | // Register information definitions for 32 bit i386. |
480 | int RegisterContextDarwin_i386::GetSetForNativeRegNum(int reg_num) { |
481 | if (reg_num < fpu_fcw) |
482 | return GPRRegSet; |
483 | else if (reg_num < exc_trapno) |
484 | return FPURegSet; |
485 | else if (reg_num < k_num_registers) |
486 | return EXCRegSet; |
487 | return -1; |
488 | } |
489 | |
490 | void RegisterContextDarwin_i386::LogGPR(Log *log, const char *title) { |
491 | if (log) { |
492 | if (title) |
493 | LLDB_LOGF(log, "%s" , title); |
494 | for (uint32_t i = 0; i < k_num_gpr_registers; i++) { |
495 | uint32_t reg = gpr_eax + i; |
496 | LLDB_LOGF(log, "%12s = 0x%8.8x" , g_register_infos[reg].name, |
497 | (&gpr.eax)[reg]); |
498 | } |
499 | } |
500 | } |
501 | |
502 | int RegisterContextDarwin_i386::ReadGPR(bool force) { |
503 | int set = GPRRegSet; |
504 | if (force || !RegisterSetIsCached(set)) { |
505 | SetError(flavor: set, err_idx: Read, err: DoReadGPR(tid: GetThreadID(), flavor: set, gpr)); |
506 | } |
507 | return GetError(flavor: set, err_idx: Read); |
508 | } |
509 | |
510 | int RegisterContextDarwin_i386::ReadFPU(bool force) { |
511 | int set = FPURegSet; |
512 | if (force || !RegisterSetIsCached(set)) { |
513 | SetError(flavor: set, err_idx: Read, err: DoReadFPU(tid: GetThreadID(), flavor: set, fpu)); |
514 | } |
515 | return GetError(flavor: set, err_idx: Read); |
516 | } |
517 | |
518 | int RegisterContextDarwin_i386::ReadEXC(bool force) { |
519 | int set = EXCRegSet; |
520 | if (force || !RegisterSetIsCached(set)) { |
521 | SetError(flavor: set, err_idx: Read, err: DoReadEXC(tid: GetThreadID(), flavor: set, exc)); |
522 | } |
523 | return GetError(flavor: set, err_idx: Read); |
524 | } |
525 | |
526 | int RegisterContextDarwin_i386::WriteGPR() { |
527 | int set = GPRRegSet; |
528 | if (!RegisterSetIsCached(set)) { |
529 | SetError(flavor: set, err_idx: Write, err: -1); |
530 | return -1; |
531 | } |
532 | SetError(flavor: set, err_idx: Write, err: DoWriteGPR(tid: GetThreadID(), flavor: set, gpr)); |
533 | SetError(flavor: set, err_idx: Read, err: -1); |
534 | return GetError(flavor: set, err_idx: Write); |
535 | } |
536 | |
537 | int RegisterContextDarwin_i386::WriteFPU() { |
538 | int set = FPURegSet; |
539 | if (!RegisterSetIsCached(set)) { |
540 | SetError(flavor: set, err_idx: Write, err: -1); |
541 | return -1; |
542 | } |
543 | SetError(flavor: set, err_idx: Write, err: DoWriteFPU(tid: GetThreadID(), flavor: set, fpu)); |
544 | SetError(flavor: set, err_idx: Read, err: -1); |
545 | return GetError(flavor: set, err_idx: Write); |
546 | } |
547 | |
548 | int RegisterContextDarwin_i386::WriteEXC() { |
549 | int set = EXCRegSet; |
550 | if (!RegisterSetIsCached(set)) { |
551 | SetError(flavor: set, err_idx: Write, err: -1); |
552 | return -1; |
553 | } |
554 | SetError(flavor: set, err_idx: Write, err: DoWriteEXC(tid: GetThreadID(), flavor: set, exc)); |
555 | SetError(flavor: set, err_idx: Read, err: -1); |
556 | return GetError(flavor: set, err_idx: Write); |
557 | } |
558 | |
559 | int RegisterContextDarwin_i386::ReadRegisterSet(uint32_t set, bool force) { |
560 | switch (set) { |
561 | case GPRRegSet: |
562 | return ReadGPR(force); |
563 | case FPURegSet: |
564 | return ReadFPU(force); |
565 | case EXCRegSet: |
566 | return ReadEXC(force); |
567 | default: |
568 | break; |
569 | } |
570 | return -1; |
571 | } |
572 | |
573 | int RegisterContextDarwin_i386::WriteRegisterSet(uint32_t set) { |
574 | // Make sure we have a valid context to set. |
575 | if (RegisterSetIsCached(set)) { |
576 | switch (set) { |
577 | case GPRRegSet: |
578 | return WriteGPR(); |
579 | case FPURegSet: |
580 | return WriteFPU(); |
581 | case EXCRegSet: |
582 | return WriteEXC(); |
583 | default: |
584 | break; |
585 | } |
586 | } |
587 | return -1; |
588 | } |
589 | |
590 | bool RegisterContextDarwin_i386::ReadRegister(const RegisterInfo *reg_info, |
591 | RegisterValue &value) { |
592 | const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; |
593 | int set = RegisterContextDarwin_i386::GetSetForNativeRegNum(reg_num: reg); |
594 | |
595 | if (set == -1) |
596 | return false; |
597 | |
598 | if (ReadRegisterSet(set, force: false) != 0) |
599 | return false; |
600 | |
601 | switch (reg) { |
602 | case gpr_eax: |
603 | case gpr_ebx: |
604 | case gpr_ecx: |
605 | case gpr_edx: |
606 | case gpr_edi: |
607 | case gpr_esi: |
608 | case gpr_ebp: |
609 | case gpr_esp: |
610 | case gpr_ss: |
611 | case gpr_eflags: |
612 | case gpr_eip: |
613 | case gpr_cs: |
614 | case gpr_ds: |
615 | case gpr_es: |
616 | case gpr_fs: |
617 | case gpr_gs: |
618 | value = (&gpr.eax)[reg - gpr_eax]; |
619 | break; |
620 | |
621 | case fpu_fcw: |
622 | value = fpu.fcw; |
623 | break; |
624 | |
625 | case fpu_fsw: |
626 | value = fpu.fsw; |
627 | break; |
628 | |
629 | case fpu_ftw: |
630 | value = fpu.ftw; |
631 | break; |
632 | |
633 | case fpu_fop: |
634 | value = fpu.fop; |
635 | break; |
636 | |
637 | case fpu_ip: |
638 | value = fpu.ip; |
639 | break; |
640 | |
641 | case fpu_cs: |
642 | value = fpu.cs; |
643 | break; |
644 | |
645 | case fpu_dp: |
646 | value = fpu.dp; |
647 | break; |
648 | |
649 | case fpu_ds: |
650 | value = fpu.ds; |
651 | break; |
652 | |
653 | case fpu_mxcsr: |
654 | value = fpu.mxcsr; |
655 | break; |
656 | |
657 | case fpu_mxcsrmask: |
658 | value = fpu.mxcsrmask; |
659 | break; |
660 | |
661 | case fpu_stmm0: |
662 | case fpu_stmm1: |
663 | case fpu_stmm2: |
664 | case fpu_stmm3: |
665 | case fpu_stmm4: |
666 | case fpu_stmm5: |
667 | case fpu_stmm6: |
668 | case fpu_stmm7: |
669 | // These values don't fit into scalar types, |
670 | // RegisterContext::ReadRegisterBytes() must be used for these registers |
671 | //::memcpy (reg_value.value.vector.uint8, fpu.stmm[reg - fpu_stmm0].bytes, |
672 | //10); |
673 | return false; |
674 | |
675 | case fpu_xmm0: |
676 | case fpu_xmm1: |
677 | case fpu_xmm2: |
678 | case fpu_xmm3: |
679 | case fpu_xmm4: |
680 | case fpu_xmm5: |
681 | case fpu_xmm6: |
682 | case fpu_xmm7: |
683 | // These values don't fit into scalar types, |
684 | // RegisterContext::ReadRegisterBytes() must be used for these registers |
685 | //::memcpy (reg_value.value.vector.uint8, fpu.xmm[reg - fpu_xmm0].bytes, |
686 | //16); |
687 | return false; |
688 | |
689 | case exc_trapno: |
690 | value = exc.trapno; |
691 | break; |
692 | |
693 | case exc_err: |
694 | value = exc.err; |
695 | break; |
696 | |
697 | case exc_faultvaddr: |
698 | value = exc.faultvaddr; |
699 | break; |
700 | |
701 | default: |
702 | return false; |
703 | } |
704 | return true; |
705 | } |
706 | |
707 | bool RegisterContextDarwin_i386::WriteRegister(const RegisterInfo *reg_info, |
708 | const RegisterValue &value) { |
709 | const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; |
710 | int set = GetSetForNativeRegNum(reg_num: reg); |
711 | |
712 | if (set == -1) |
713 | return false; |
714 | |
715 | if (ReadRegisterSet(set, force: false) != 0) |
716 | return false; |
717 | |
718 | switch (reg) { |
719 | case gpr_eax: |
720 | case gpr_ebx: |
721 | case gpr_ecx: |
722 | case gpr_edx: |
723 | case gpr_edi: |
724 | case gpr_esi: |
725 | case gpr_ebp: |
726 | case gpr_esp: |
727 | case gpr_ss: |
728 | case gpr_eflags: |
729 | case gpr_eip: |
730 | case gpr_cs: |
731 | case gpr_ds: |
732 | case gpr_es: |
733 | case gpr_fs: |
734 | case gpr_gs: |
735 | (&gpr.eax)[reg - gpr_eax] = value.GetAsUInt32(); |
736 | break; |
737 | |
738 | case fpu_fcw: |
739 | fpu.fcw = value.GetAsUInt16(); |
740 | break; |
741 | |
742 | case fpu_fsw: |
743 | fpu.fsw = value.GetAsUInt16(); |
744 | break; |
745 | |
746 | case fpu_ftw: |
747 | fpu.ftw = value.GetAsUInt8(); |
748 | break; |
749 | |
750 | case fpu_fop: |
751 | fpu.fop = value.GetAsUInt16(); |
752 | break; |
753 | |
754 | case fpu_ip: |
755 | fpu.ip = value.GetAsUInt32(); |
756 | break; |
757 | |
758 | case fpu_cs: |
759 | fpu.cs = value.GetAsUInt16(); |
760 | break; |
761 | |
762 | case fpu_dp: |
763 | fpu.dp = value.GetAsUInt32(); |
764 | break; |
765 | |
766 | case fpu_ds: |
767 | fpu.ds = value.GetAsUInt16(); |
768 | break; |
769 | |
770 | case fpu_mxcsr: |
771 | fpu.mxcsr = value.GetAsUInt32(); |
772 | break; |
773 | |
774 | case fpu_mxcsrmask: |
775 | fpu.mxcsrmask = value.GetAsUInt32(); |
776 | break; |
777 | |
778 | case fpu_stmm0: |
779 | case fpu_stmm1: |
780 | case fpu_stmm2: |
781 | case fpu_stmm3: |
782 | case fpu_stmm4: |
783 | case fpu_stmm5: |
784 | case fpu_stmm6: |
785 | case fpu_stmm7: |
786 | // These values don't fit into scalar types, |
787 | // RegisterContext::ReadRegisterBytes() must be used for these registers |
788 | ::memcpy(dest: fpu.stmm[reg - fpu_stmm0].bytes, src: value.GetBytes(), |
789 | n: value.GetByteSize()); |
790 | return false; |
791 | |
792 | case fpu_xmm0: |
793 | case fpu_xmm1: |
794 | case fpu_xmm2: |
795 | case fpu_xmm3: |
796 | case fpu_xmm4: |
797 | case fpu_xmm5: |
798 | case fpu_xmm6: |
799 | case fpu_xmm7: |
800 | // These values don't fit into scalar types, |
801 | // RegisterContext::ReadRegisterBytes() must be used for these registers |
802 | ::memcpy(dest: fpu.xmm[reg - fpu_xmm0].bytes, src: value.GetBytes(), |
803 | n: value.GetByteSize()); |
804 | return false; |
805 | |
806 | case exc_trapno: |
807 | exc.trapno = value.GetAsUInt32(); |
808 | break; |
809 | |
810 | case exc_err: |
811 | exc.err = value.GetAsUInt32(); |
812 | break; |
813 | |
814 | case exc_faultvaddr: |
815 | exc.faultvaddr = value.GetAsUInt32(); |
816 | break; |
817 | |
818 | default: |
819 | return false; |
820 | } |
821 | return WriteRegisterSet(set) == 0; |
822 | } |
823 | |
824 | bool RegisterContextDarwin_i386::ReadAllRegisterValues( |
825 | lldb::WritableDataBufferSP &data_sp) { |
826 | data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, args: 0); |
827 | if (ReadGPR(force: false) == 0 && ReadFPU(force: false) == 0 && ReadEXC(force: false) == 0) { |
828 | uint8_t *dst = data_sp->GetBytes(); |
829 | ::memcpy(dest: dst, src: &gpr, n: sizeof(gpr)); |
830 | dst += sizeof(gpr); |
831 | |
832 | ::memcpy(dest: dst, src: &fpu, n: sizeof(fpu)); |
833 | dst += sizeof(gpr); |
834 | |
835 | ::memcpy(dest: dst, src: &exc, n: sizeof(exc)); |
836 | return true; |
837 | } |
838 | return false; |
839 | } |
840 | |
841 | bool RegisterContextDarwin_i386::WriteAllRegisterValues( |
842 | const lldb::DataBufferSP &data_sp) { |
843 | if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) { |
844 | const uint8_t *src = data_sp->GetBytes(); |
845 | ::memcpy(dest: &gpr, src: src, n: sizeof(gpr)); |
846 | src += sizeof(gpr); |
847 | |
848 | ::memcpy(dest: &fpu, src: src, n: sizeof(fpu)); |
849 | src += sizeof(gpr); |
850 | |
851 | ::memcpy(dest: &exc, src: src, n: sizeof(exc)); |
852 | uint32_t success_count = 0; |
853 | if (WriteGPR() == 0) |
854 | ++success_count; |
855 | if (WriteFPU() == 0) |
856 | ++success_count; |
857 | if (WriteEXC() == 0) |
858 | ++success_count; |
859 | return success_count == 3; |
860 | } |
861 | return false; |
862 | } |
863 | |
864 | uint32_t RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber( |
865 | lldb::RegisterKind kind, uint32_t reg) { |
866 | if (kind == eRegisterKindGeneric) { |
867 | switch (reg) { |
868 | case LLDB_REGNUM_GENERIC_PC: |
869 | return gpr_eip; |
870 | case LLDB_REGNUM_GENERIC_SP: |
871 | return gpr_esp; |
872 | case LLDB_REGNUM_GENERIC_FP: |
873 | return gpr_ebp; |
874 | case LLDB_REGNUM_GENERIC_FLAGS: |
875 | return gpr_eflags; |
876 | case LLDB_REGNUM_GENERIC_RA: |
877 | default: |
878 | break; |
879 | } |
880 | } else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF) { |
881 | switch (reg) { |
882 | case dwarf_eax: |
883 | return gpr_eax; |
884 | case dwarf_ecx: |
885 | return gpr_ecx; |
886 | case dwarf_edx: |
887 | return gpr_edx; |
888 | case dwarf_ebx: |
889 | return gpr_ebx; |
890 | case dwarf_esp: |
891 | return gpr_esp; |
892 | case dwarf_ebp: |
893 | return gpr_ebp; |
894 | case dwarf_esi: |
895 | return gpr_esi; |
896 | case dwarf_edi: |
897 | return gpr_edi; |
898 | case dwarf_eip: |
899 | return gpr_eip; |
900 | case dwarf_eflags: |
901 | return gpr_eflags; |
902 | case dwarf_stmm0: |
903 | return fpu_stmm0; |
904 | case dwarf_stmm1: |
905 | return fpu_stmm1; |
906 | case dwarf_stmm2: |
907 | return fpu_stmm2; |
908 | case dwarf_stmm3: |
909 | return fpu_stmm3; |
910 | case dwarf_stmm4: |
911 | return fpu_stmm4; |
912 | case dwarf_stmm5: |
913 | return fpu_stmm5; |
914 | case dwarf_stmm6: |
915 | return fpu_stmm6; |
916 | case dwarf_stmm7: |
917 | return fpu_stmm7; |
918 | case dwarf_xmm0: |
919 | return fpu_xmm0; |
920 | case dwarf_xmm1: |
921 | return fpu_xmm1; |
922 | case dwarf_xmm2: |
923 | return fpu_xmm2; |
924 | case dwarf_xmm3: |
925 | return fpu_xmm3; |
926 | case dwarf_xmm4: |
927 | return fpu_xmm4; |
928 | case dwarf_xmm5: |
929 | return fpu_xmm5; |
930 | case dwarf_xmm6: |
931 | return fpu_xmm6; |
932 | case dwarf_xmm7: |
933 | return fpu_xmm7; |
934 | default: |
935 | break; |
936 | } |
937 | } else if (kind == eRegisterKindLLDB) { |
938 | return reg; |
939 | } |
940 | return LLDB_INVALID_REGNUM; |
941 | } |
942 | |
943 | bool RegisterContextDarwin_i386::HardwareSingleStep(bool enable) { |
944 | if (ReadGPR(force: false) != 0) |
945 | return false; |
946 | |
947 | const uint32_t trace_bit = 0x100u; |
948 | if (enable) { |
949 | // If the trace bit is already set, there is nothing to do |
950 | if (gpr.eflags & trace_bit) |
951 | return true; |
952 | else |
953 | gpr.eflags |= trace_bit; |
954 | } else { |
955 | // If the trace bit is already cleared, there is nothing to do |
956 | if (gpr.eflags & trace_bit) |
957 | gpr.eflags &= ~trace_bit; |
958 | else |
959 | return true; |
960 | } |
961 | |
962 | return WriteGPR() == 0; |
963 | } |
964 | |