1 //===-- RegisterContextDarwin_i386.cpp --------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 #include <stddef.h> // offsetof
14 // Other libraries and framework includes
15 #include "lldb/Core/RegisterValue.h"
16 #include "lldb/Core/Scalar.h"
17 #include "lldb/Utility/DataBufferHeap.h"
18 #include "lldb/Utility/DataExtractor.h"
19 #include "lldb/Utility/Endian.h"
20 #include "lldb/Utility/Log.h"
21 #include "llvm/ADT/STLExtras.h"
22 #include "llvm/Support/Compiler.h"
24 // Support building against older versions of LLVM, this macro was added
26 #ifndef LLVM_EXTENSION
27 #define LLVM_EXTENSION
31 #include "RegisterContextDarwin_i386.h"
34 using namespace lldb_private;
139 #define GPR_OFFSET(reg) \
140 (LLVM_EXTENSION offsetof(RegisterContextDarwin_i386::GPR, reg))
141 #define FPU_OFFSET(reg) \
142 (LLVM_EXTENSION offsetof(RegisterContextDarwin_i386::FPU, reg) + \
143 sizeof(RegisterContextDarwin_i386::GPR))
144 #define EXC_OFFSET(reg) \
145 (LLVM_EXTENSION offsetof(RegisterContextDarwin_i386::EXC, reg) + \
146 sizeof(RegisterContextDarwin_i386::GPR) + \
147 sizeof(RegisterContextDarwin_i386::FPU))
149 // These macros will auto define the register name, alt name, register size,
150 // register offset, encoding, format and native register. This ensures that the
151 // register state structures are defined correctly and have the correct sizes
153 #define DEFINE_GPR(reg, alt) \
154 #reg, alt, sizeof(((RegisterContextDarwin_i386::GPR *) NULL)->reg), \
155 GPR_OFFSET(reg), eEncodingUint, eFormatHex
156 #define DEFINE_FPU_UINT(reg) \
157 #reg, NULL, sizeof(((RegisterContextDarwin_i386::FPU *) NULL)->reg), \
158 FPU_OFFSET(reg), eEncodingUint, eFormatHex
159 #define DEFINE_FPU_VECT(reg, i) \
161 sizeof(((RegisterContextDarwin_i386::FPU *) NULL)->reg[i].bytes), \
162 FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, \
163 {LLDB_INVALID_REGNUM, dwarf_##reg##i, \
164 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
166 nullptr, nullptr, nullptr, 0
168 #define DEFINE_EXC(reg) \
169 #reg, NULL, sizeof(((RegisterContextDarwin_i386::EXC *) NULL)->reg), \
170 EXC_OFFSET(reg), eEncodingUint, eFormatHex
171 #define REG_CONTEXT_SIZE \
172 (sizeof(RegisterContextDarwin_i386::GPR) + \
173 sizeof(RegisterContextDarwin_i386::FPU) + \
174 sizeof(RegisterContextDarwin_i386::EXC))
176 static RegisterInfo g_register_infos[] = {
177 // Macro auto defines most stuff eh_frame DWARF
178 // GENERIC PROCESS PLUGIN LLDB
179 // =============================== =======================
180 // =================== ========================= ==================
182 {DEFINE_GPR(eax, NULL),
183 {ehframe_eax, dwarf_eax, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
189 {DEFINE_GPR(ebx, NULL),
190 {ehframe_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
196 {DEFINE_GPR(ecx, NULL),
197 {ehframe_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
203 {DEFINE_GPR(edx, NULL),
204 {ehframe_edx, dwarf_edx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
210 {DEFINE_GPR(edi, NULL),
211 {ehframe_edi, dwarf_edi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
217 {DEFINE_GPR(esi, NULL),
218 {ehframe_esi, dwarf_esi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
224 {DEFINE_GPR(ebp, "fp"),
225 {ehframe_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
231 {DEFINE_GPR(esp, "sp"),
232 {ehframe_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
238 {DEFINE_GPR(ss, NULL),
239 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
240 LLDB_INVALID_REGNUM, gpr_ss},
245 {DEFINE_GPR(eflags, "flags"),
246 {ehframe_eflags, dwarf_eflags, LLDB_REGNUM_GENERIC_FLAGS,
247 LLDB_INVALID_REGNUM, gpr_eflags},
252 {DEFINE_GPR(eip, "pc"),
253 {ehframe_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
259 {DEFINE_GPR(cs, NULL),
260 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
261 LLDB_INVALID_REGNUM, gpr_cs},
266 {DEFINE_GPR(ds, NULL),
267 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
268 LLDB_INVALID_REGNUM, gpr_ds},
273 {DEFINE_GPR(es, NULL),
274 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
275 LLDB_INVALID_REGNUM, gpr_es},
280 {DEFINE_GPR(fs, NULL),
281 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
282 LLDB_INVALID_REGNUM, gpr_fs},
287 {DEFINE_GPR(gs, NULL),
288 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
289 LLDB_INVALID_REGNUM, gpr_gs},
295 {DEFINE_FPU_UINT(fcw),
296 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
297 LLDB_INVALID_REGNUM, fpu_fcw},
302 {DEFINE_FPU_UINT(fsw),
303 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
304 LLDB_INVALID_REGNUM, fpu_fsw},
309 {DEFINE_FPU_UINT(ftw),
310 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
311 LLDB_INVALID_REGNUM, fpu_ftw},
316 {DEFINE_FPU_UINT(fop),
317 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
318 LLDB_INVALID_REGNUM, fpu_fop},
323 {DEFINE_FPU_UINT(ip),
324 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
325 LLDB_INVALID_REGNUM, fpu_ip},
330 {DEFINE_FPU_UINT(cs),
331 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
332 LLDB_INVALID_REGNUM, fpu_cs},
337 {DEFINE_FPU_UINT(dp),
338 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
339 LLDB_INVALID_REGNUM, fpu_dp},
344 {DEFINE_FPU_UINT(ds),
345 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
346 LLDB_INVALID_REGNUM, fpu_ds},
351 {DEFINE_FPU_UINT(mxcsr),
352 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
353 LLDB_INVALID_REGNUM, fpu_mxcsr},
358 {DEFINE_FPU_UINT(mxcsrmask),
359 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
360 LLDB_INVALID_REGNUM, fpu_mxcsrmask},
365 {DEFINE_FPU_VECT(stmm, 0)},
366 {DEFINE_FPU_VECT(stmm, 1)},
367 {DEFINE_FPU_VECT(stmm, 2)},
368 {DEFINE_FPU_VECT(stmm, 3)},
369 {DEFINE_FPU_VECT(stmm, 4)},
370 {DEFINE_FPU_VECT(stmm, 5)},
371 {DEFINE_FPU_VECT(stmm, 6)},
372 {DEFINE_FPU_VECT(stmm, 7)},
373 {DEFINE_FPU_VECT(xmm, 0)},
374 {DEFINE_FPU_VECT(xmm, 1)},
375 {DEFINE_FPU_VECT(xmm, 2)},
376 {DEFINE_FPU_VECT(xmm, 3)},
377 {DEFINE_FPU_VECT(xmm, 4)},
378 {DEFINE_FPU_VECT(xmm, 5)},
379 {DEFINE_FPU_VECT(xmm, 6)},
380 {DEFINE_FPU_VECT(xmm, 7)},
383 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
384 LLDB_INVALID_REGNUM, exc_trapno},
390 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
391 LLDB_INVALID_REGNUM, exc_err},
396 {DEFINE_EXC(faultvaddr),
397 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
398 LLDB_INVALID_REGNUM, exc_faultvaddr},
404 static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
406 RegisterContextDarwin_i386::RegisterContextDarwin_i386(
407 Thread &thread, uint32_t concrete_frame_idx)
408 : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc() {
410 for (i = 0; i < kNumErrors; i++) {
417 RegisterContextDarwin_i386::~RegisterContextDarwin_i386() {}
419 void RegisterContextDarwin_i386::InvalidateAllRegisters() {
420 InvalidateAllRegisterStates();
423 size_t RegisterContextDarwin_i386::GetRegisterCount() {
424 assert(k_num_register_infos == k_num_registers);
425 return k_num_registers;
429 RegisterContextDarwin_i386::GetRegisterInfoAtIndex(size_t reg) {
430 assert(k_num_register_infos == k_num_registers);
431 if (reg < k_num_registers)
432 return &g_register_infos[reg];
436 size_t RegisterContextDarwin_i386::GetRegisterInfosCount() {
437 return k_num_register_infos;
440 const RegisterInfo *RegisterContextDarwin_i386::GetRegisterInfos() {
441 return g_register_infos;
444 // General purpose registers
445 static uint32_t g_gpr_regnums[] = {
446 gpr_eax, gpr_ebx, gpr_ecx, gpr_edx, gpr_edi, gpr_esi, gpr_ebp, gpr_esp,
447 gpr_ss, gpr_eflags, gpr_eip, gpr_cs, gpr_ds, gpr_es, gpr_fs, gpr_gs};
449 // Floating point registers
450 static uint32_t g_fpu_regnums[] = {
451 fpu_fcw, fpu_fsw, fpu_ftw, fpu_fop, fpu_ip, fpu_cs,
452 fpu_dp, fpu_ds, fpu_mxcsr, fpu_mxcsrmask, fpu_stmm0, fpu_stmm1,
453 fpu_stmm2, fpu_stmm3, fpu_stmm4, fpu_stmm5, fpu_stmm6, fpu_stmm7,
454 fpu_xmm0, fpu_xmm1, fpu_xmm2, fpu_xmm3, fpu_xmm4, fpu_xmm5,
457 // Exception registers
459 static uint32_t g_exc_regnums[] = {exc_trapno, exc_err, exc_faultvaddr};
461 // Number of registers in each register set
462 const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
463 const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
464 const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
466 //----------------------------------------------------------------------
467 // Register set definitions. The first definitions at register set index of
468 // zero is for all registers, followed by other registers sets. The register
469 // information for the all register set need not be filled in.
470 //----------------------------------------------------------------------
471 static const RegisterSet g_reg_sets[] = {
473 "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums,
475 {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums},
476 {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}};
478 const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
480 size_t RegisterContextDarwin_i386::GetRegisterSetCount() {
481 return k_num_regsets;
484 const RegisterSet *RegisterContextDarwin_i386::GetRegisterSet(size_t reg_set) {
485 if (reg_set < k_num_regsets)
486 return &g_reg_sets[reg_set];
490 //----------------------------------------------------------------------
491 // Register information definitions for 32 bit i386.
492 //----------------------------------------------------------------------
493 int RegisterContextDarwin_i386::GetSetForNativeRegNum(int reg_num) {
494 if (reg_num < fpu_fcw)
496 else if (reg_num < exc_trapno)
498 else if (reg_num < k_num_registers)
503 void RegisterContextDarwin_i386::LogGPR(Log *log, const char *title) {
506 log->Printf("%s", title);
507 for (uint32_t i = 0; i < k_num_gpr_registers; i++) {
508 uint32_t reg = gpr_eax + i;
509 log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name,
515 int RegisterContextDarwin_i386::ReadGPR(bool force) {
517 if (force || !RegisterSetIsCached(set)) {
518 SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
520 return GetError(set, Read);
523 int RegisterContextDarwin_i386::ReadFPU(bool force) {
525 if (force || !RegisterSetIsCached(set)) {
526 SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
528 return GetError(set, Read);
531 int RegisterContextDarwin_i386::ReadEXC(bool force) {
533 if (force || !RegisterSetIsCached(set)) {
534 SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
536 return GetError(set, Read);
539 int RegisterContextDarwin_i386::WriteGPR() {
541 if (!RegisterSetIsCached(set)) {
542 SetError(set, Write, -1);
545 SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr));
546 SetError(set, Read, -1);
547 return GetError(set, Write);
550 int RegisterContextDarwin_i386::WriteFPU() {
552 if (!RegisterSetIsCached(set)) {
553 SetError(set, Write, -1);
556 SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu));
557 SetError(set, Read, -1);
558 return GetError(set, Write);
561 int RegisterContextDarwin_i386::WriteEXC() {
563 if (!RegisterSetIsCached(set)) {
564 SetError(set, Write, -1);
567 SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc));
568 SetError(set, Read, -1);
569 return GetError(set, Write);
572 int RegisterContextDarwin_i386::ReadRegisterSet(uint32_t set, bool force) {
575 return ReadGPR(force);
577 return ReadFPU(force);
579 return ReadEXC(force);
586 int RegisterContextDarwin_i386::WriteRegisterSet(uint32_t set) {
587 // Make sure we have a valid context to set.
588 if (RegisterSetIsCached(set)) {
603 bool RegisterContextDarwin_i386::ReadRegister(const RegisterInfo *reg_info,
604 RegisterValue &value) {
605 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
606 int set = RegisterContextDarwin_i386::GetSetForNativeRegNum(reg);
611 if (ReadRegisterSet(set, false) != 0)
631 value = (&gpr.eax)[reg - gpr_eax];
671 value = fpu.mxcsrmask;
682 // These values don't fit into scalar types,
683 // RegisterContext::ReadRegisterBytes() must be used for these registers
684 //::memcpy (reg_value.value.vector.uint8, fpu.stmm[reg - fpu_stmm0].bytes,
696 // These values don't fit into scalar types,
697 // RegisterContext::ReadRegisterBytes() must be used for these registers
698 //::memcpy (reg_value.value.vector.uint8, fpu.xmm[reg - fpu_xmm0].bytes,
711 value = exc.faultvaddr;
720 bool RegisterContextDarwin_i386::WriteRegister(const RegisterInfo *reg_info,
721 const RegisterValue &value) {
722 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
723 int set = GetSetForNativeRegNum(reg);
728 if (ReadRegisterSet(set, false) != 0)
748 (&gpr.eax)[reg - gpr_eax] = value.GetAsUInt32();
752 fpu.fcw = value.GetAsUInt16();
756 fpu.fsw = value.GetAsUInt16();
760 fpu.ftw = value.GetAsUInt8();
764 fpu.fop = value.GetAsUInt16();
768 fpu.ip = value.GetAsUInt32();
772 fpu.cs = value.GetAsUInt16();
776 fpu.dp = value.GetAsUInt32();
780 fpu.ds = value.GetAsUInt16();
784 fpu.mxcsr = value.GetAsUInt32();
788 fpu.mxcsrmask = value.GetAsUInt32();
799 // These values don't fit into scalar types,
800 // RegisterContext::ReadRegisterBytes() must be used for these registers
801 ::memcpy(fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(),
802 value.GetByteSize());
813 // These values don't fit into scalar types,
814 // RegisterContext::ReadRegisterBytes() must be used for these registers
815 ::memcpy(fpu.xmm[reg - fpu_xmm0].bytes, value.GetBytes(),
816 value.GetByteSize());
820 exc.trapno = value.GetAsUInt32();
824 exc.err = value.GetAsUInt32();
828 exc.faultvaddr = value.GetAsUInt32();
834 return WriteRegisterSet(set) == 0;
837 bool RegisterContextDarwin_i386::ReadAllRegisterValues(
838 lldb::DataBufferSP &data_sp) {
839 data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
840 if (data_sp && ReadGPR(false) == 0 && ReadFPU(false) == 0 &&
841 ReadEXC(false) == 0) {
842 uint8_t *dst = data_sp->GetBytes();
843 ::memcpy(dst, &gpr, sizeof(gpr));
846 ::memcpy(dst, &fpu, sizeof(fpu));
849 ::memcpy(dst, &exc, sizeof(exc));
855 bool RegisterContextDarwin_i386::WriteAllRegisterValues(
856 const lldb::DataBufferSP &data_sp) {
857 if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
858 const uint8_t *src = data_sp->GetBytes();
859 ::memcpy(&gpr, src, sizeof(gpr));
862 ::memcpy(&fpu, src, sizeof(fpu));
865 ::memcpy(&exc, src, sizeof(exc));
866 uint32_t success_count = 0;
873 return success_count == 3;
878 uint32_t RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber(
879 lldb::RegisterKind kind, uint32_t reg) {
880 if (kind == eRegisterKindGeneric) {
882 case LLDB_REGNUM_GENERIC_PC:
884 case LLDB_REGNUM_GENERIC_SP:
886 case LLDB_REGNUM_GENERIC_FP:
888 case LLDB_REGNUM_GENERIC_FLAGS:
890 case LLDB_REGNUM_GENERIC_RA:
894 } else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF) {
951 } else if (kind == eRegisterKindLLDB) {
954 return LLDB_INVALID_REGNUM;
957 bool RegisterContextDarwin_i386::HardwareSingleStep(bool enable) {
958 if (ReadGPR(false) != 0)
961 const uint32_t trace_bit = 0x100u;
963 // If the trace bit is already set, there is nothing to do
964 if (gpr.eflags & trace_bit)
967 gpr.eflags |= trace_bit;
969 // If the trace bit is already cleared, there is nothing to do
970 if (gpr.eflags & trace_bit)
971 gpr.eflags &= ~trace_bit;
976 return WriteGPR() == 0;