1 //===-- RegisterContextDarwin_i386.cpp --------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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"
22 // Support building against older versions of LLVM, this macro was added
24 #ifndef LLVM_EXTENSION
25 #define LLVM_EXTENSION
28 #include "RegisterContextDarwin_i386.h"
31 using namespace lldb_private;
136 #define GPR_OFFSET(reg) \
137 (LLVM_EXTENSION offsetof(RegisterContextDarwin_i386::GPR, reg))
138 #define FPU_OFFSET(reg) \
139 (LLVM_EXTENSION offsetof(RegisterContextDarwin_i386::FPU, reg) + \
140 sizeof(RegisterContextDarwin_i386::GPR))
141 #define EXC_OFFSET(reg) \
142 (LLVM_EXTENSION offsetof(RegisterContextDarwin_i386::EXC, reg) + \
143 sizeof(RegisterContextDarwin_i386::GPR) + \
144 sizeof(RegisterContextDarwin_i386::FPU))
146 // These macros will auto define the register name, alt name, register size,
147 // register offset, encoding, format and native register. This ensures that the
148 // register state structures are defined correctly and have the correct sizes
150 #define DEFINE_GPR(reg, alt) \
151 #reg, alt, sizeof(((RegisterContextDarwin_i386::GPR *) NULL)->reg), \
152 GPR_OFFSET(reg), eEncodingUint, eFormatHex
153 #define DEFINE_FPU_UINT(reg) \
154 #reg, NULL, sizeof(((RegisterContextDarwin_i386::FPU *) NULL)->reg), \
155 FPU_OFFSET(reg), eEncodingUint, eFormatHex
156 #define DEFINE_FPU_VECT(reg, i) \
158 sizeof(((RegisterContextDarwin_i386::FPU *) NULL)->reg[i].bytes), \
159 FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, \
160 {LLDB_INVALID_REGNUM, dwarf_##reg##i, \
161 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
163 nullptr, nullptr, nullptr, 0
165 #define DEFINE_EXC(reg) \
166 #reg, NULL, sizeof(((RegisterContextDarwin_i386::EXC *) NULL)->reg), \
167 EXC_OFFSET(reg), eEncodingUint, eFormatHex
168 #define REG_CONTEXT_SIZE \
169 (sizeof(RegisterContextDarwin_i386::GPR) + \
170 sizeof(RegisterContextDarwin_i386::FPU) + \
171 sizeof(RegisterContextDarwin_i386::EXC))
173 static RegisterInfo g_register_infos[] = {
174 // Macro auto defines most stuff eh_frame DWARF
175 // GENERIC PROCESS PLUGIN LLDB
176 // =============================== =======================
177 // =================== ========================= ==================
179 {DEFINE_GPR(eax, nullptr),
180 {ehframe_eax, dwarf_eax, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
186 {DEFINE_GPR(ebx, nullptr),
187 {ehframe_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
193 {DEFINE_GPR(ecx, nullptr),
194 {ehframe_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
200 {DEFINE_GPR(edx, nullptr),
201 {ehframe_edx, dwarf_edx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
207 {DEFINE_GPR(edi, nullptr),
208 {ehframe_edi, dwarf_edi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
214 {DEFINE_GPR(esi, nullptr),
215 {ehframe_esi, dwarf_esi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
221 {DEFINE_GPR(ebp, "fp"),
222 {ehframe_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
228 {DEFINE_GPR(esp, "sp"),
229 {ehframe_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
235 {DEFINE_GPR(ss, nullptr),
236 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
237 LLDB_INVALID_REGNUM, gpr_ss},
242 {DEFINE_GPR(eflags, "flags"),
243 {ehframe_eflags, dwarf_eflags, LLDB_REGNUM_GENERIC_FLAGS,
244 LLDB_INVALID_REGNUM, gpr_eflags},
249 {DEFINE_GPR(eip, "pc"),
250 {ehframe_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
256 {DEFINE_GPR(cs, nullptr),
257 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
258 LLDB_INVALID_REGNUM, gpr_cs},
263 {DEFINE_GPR(ds, nullptr),
264 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
265 LLDB_INVALID_REGNUM, gpr_ds},
270 {DEFINE_GPR(es, nullptr),
271 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
272 LLDB_INVALID_REGNUM, gpr_es},
277 {DEFINE_GPR(fs, nullptr),
278 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
279 LLDB_INVALID_REGNUM, gpr_fs},
284 {DEFINE_GPR(gs, nullptr),
285 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
286 LLDB_INVALID_REGNUM, gpr_gs},
292 {DEFINE_FPU_UINT(fcw),
293 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
294 LLDB_INVALID_REGNUM, fpu_fcw},
299 {DEFINE_FPU_UINT(fsw),
300 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
301 LLDB_INVALID_REGNUM, fpu_fsw},
306 {DEFINE_FPU_UINT(ftw),
307 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
308 LLDB_INVALID_REGNUM, fpu_ftw},
313 {DEFINE_FPU_UINT(fop),
314 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
315 LLDB_INVALID_REGNUM, fpu_fop},
320 {DEFINE_FPU_UINT(ip),
321 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
322 LLDB_INVALID_REGNUM, fpu_ip},
327 {DEFINE_FPU_UINT(cs),
328 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
329 LLDB_INVALID_REGNUM, fpu_cs},
334 {DEFINE_FPU_UINT(dp),
335 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
336 LLDB_INVALID_REGNUM, fpu_dp},
341 {DEFINE_FPU_UINT(ds),
342 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
343 LLDB_INVALID_REGNUM, fpu_ds},
348 {DEFINE_FPU_UINT(mxcsr),
349 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
350 LLDB_INVALID_REGNUM, fpu_mxcsr},
355 {DEFINE_FPU_UINT(mxcsrmask),
356 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
357 LLDB_INVALID_REGNUM, fpu_mxcsrmask},
362 {DEFINE_FPU_VECT(stmm, 0)},
363 {DEFINE_FPU_VECT(stmm, 1)},
364 {DEFINE_FPU_VECT(stmm, 2)},
365 {DEFINE_FPU_VECT(stmm, 3)},
366 {DEFINE_FPU_VECT(stmm, 4)},
367 {DEFINE_FPU_VECT(stmm, 5)},
368 {DEFINE_FPU_VECT(stmm, 6)},
369 {DEFINE_FPU_VECT(stmm, 7)},
370 {DEFINE_FPU_VECT(xmm, 0)},
371 {DEFINE_FPU_VECT(xmm, 1)},
372 {DEFINE_FPU_VECT(xmm, 2)},
373 {DEFINE_FPU_VECT(xmm, 3)},
374 {DEFINE_FPU_VECT(xmm, 4)},
375 {DEFINE_FPU_VECT(xmm, 5)},
376 {DEFINE_FPU_VECT(xmm, 6)},
377 {DEFINE_FPU_VECT(xmm, 7)},
380 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
381 LLDB_INVALID_REGNUM, exc_trapno},
387 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
388 LLDB_INVALID_REGNUM, exc_err},
393 {DEFINE_EXC(faultvaddr),
394 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
395 LLDB_INVALID_REGNUM, exc_faultvaddr},
401 static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
403 RegisterContextDarwin_i386::RegisterContextDarwin_i386(
404 Thread &thread, uint32_t concrete_frame_idx)
405 : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc() {
407 for (i = 0; i < kNumErrors; i++) {
414 RegisterContextDarwin_i386::~RegisterContextDarwin_i386() {}
416 void RegisterContextDarwin_i386::InvalidateAllRegisters() {
417 InvalidateAllRegisterStates();
420 size_t RegisterContextDarwin_i386::GetRegisterCount() {
421 assert(k_num_register_infos == k_num_registers);
422 return k_num_registers;
426 RegisterContextDarwin_i386::GetRegisterInfoAtIndex(size_t reg) {
427 assert(k_num_register_infos == k_num_registers);
428 if (reg < k_num_registers)
429 return &g_register_infos[reg];
433 size_t RegisterContextDarwin_i386::GetRegisterInfosCount() {
434 return k_num_register_infos;
437 const RegisterInfo *RegisterContextDarwin_i386::GetRegisterInfos() {
438 return g_register_infos;
441 // General purpose registers
442 static uint32_t g_gpr_regnums[] = {
443 gpr_eax, gpr_ebx, gpr_ecx, gpr_edx, gpr_edi, gpr_esi, gpr_ebp, gpr_esp,
444 gpr_ss, gpr_eflags, gpr_eip, gpr_cs, gpr_ds, gpr_es, gpr_fs, gpr_gs};
446 // Floating point registers
447 static uint32_t g_fpu_regnums[] = {
448 fpu_fcw, fpu_fsw, fpu_ftw, fpu_fop, fpu_ip, fpu_cs,
449 fpu_dp, fpu_ds, fpu_mxcsr, fpu_mxcsrmask, fpu_stmm0, fpu_stmm1,
450 fpu_stmm2, fpu_stmm3, fpu_stmm4, fpu_stmm5, fpu_stmm6, fpu_stmm7,
451 fpu_xmm0, fpu_xmm1, fpu_xmm2, fpu_xmm3, fpu_xmm4, fpu_xmm5,
454 // Exception registers
456 static uint32_t g_exc_regnums[] = {exc_trapno, exc_err, exc_faultvaddr};
458 // Number of registers in each register set
459 const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
460 const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
461 const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
463 // Register set definitions. The first definitions at register set index of
464 // zero is for all registers, followed by other registers sets. The register
465 // information for the all register set need not be filled in.
466 static const RegisterSet g_reg_sets[] = {
468 "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums,
470 {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums},
471 {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}};
473 const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
475 size_t RegisterContextDarwin_i386::GetRegisterSetCount() {
476 return k_num_regsets;
479 const RegisterSet *RegisterContextDarwin_i386::GetRegisterSet(size_t reg_set) {
480 if (reg_set < k_num_regsets)
481 return &g_reg_sets[reg_set];
485 // Register information definitions for 32 bit i386.
486 int RegisterContextDarwin_i386::GetSetForNativeRegNum(int reg_num) {
487 if (reg_num < fpu_fcw)
489 else if (reg_num < exc_trapno)
491 else if (reg_num < k_num_registers)
496 void RegisterContextDarwin_i386::LogGPR(Log *log, const char *title) {
499 log->Printf("%s", title);
500 for (uint32_t i = 0; i < k_num_gpr_registers; i++) {
501 uint32_t reg = gpr_eax + i;
502 log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name,
508 int RegisterContextDarwin_i386::ReadGPR(bool force) {
510 if (force || !RegisterSetIsCached(set)) {
511 SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
513 return GetError(set, Read);
516 int RegisterContextDarwin_i386::ReadFPU(bool force) {
518 if (force || !RegisterSetIsCached(set)) {
519 SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
521 return GetError(set, Read);
524 int RegisterContextDarwin_i386::ReadEXC(bool force) {
526 if (force || !RegisterSetIsCached(set)) {
527 SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
529 return GetError(set, Read);
532 int RegisterContextDarwin_i386::WriteGPR() {
534 if (!RegisterSetIsCached(set)) {
535 SetError(set, Write, -1);
538 SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr));
539 SetError(set, Read, -1);
540 return GetError(set, Write);
543 int RegisterContextDarwin_i386::WriteFPU() {
545 if (!RegisterSetIsCached(set)) {
546 SetError(set, Write, -1);
549 SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu));
550 SetError(set, Read, -1);
551 return GetError(set, Write);
554 int RegisterContextDarwin_i386::WriteEXC() {
556 if (!RegisterSetIsCached(set)) {
557 SetError(set, Write, -1);
560 SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc));
561 SetError(set, Read, -1);
562 return GetError(set, Write);
565 int RegisterContextDarwin_i386::ReadRegisterSet(uint32_t set, bool force) {
568 return ReadGPR(force);
570 return ReadFPU(force);
572 return ReadEXC(force);
579 int RegisterContextDarwin_i386::WriteRegisterSet(uint32_t set) {
580 // Make sure we have a valid context to set.
581 if (RegisterSetIsCached(set)) {
596 bool RegisterContextDarwin_i386::ReadRegister(const RegisterInfo *reg_info,
597 RegisterValue &value) {
598 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
599 int set = RegisterContextDarwin_i386::GetSetForNativeRegNum(reg);
604 if (ReadRegisterSet(set, false) != 0)
624 value = (&gpr.eax)[reg - gpr_eax];
664 value = fpu.mxcsrmask;
675 // These values don't fit into scalar types,
676 // RegisterContext::ReadRegisterBytes() must be used for these registers
677 //::memcpy (reg_value.value.vector.uint8, fpu.stmm[reg - fpu_stmm0].bytes,
689 // These values don't fit into scalar types,
690 // RegisterContext::ReadRegisterBytes() must be used for these registers
691 //::memcpy (reg_value.value.vector.uint8, fpu.xmm[reg - fpu_xmm0].bytes,
704 value = exc.faultvaddr;
713 bool RegisterContextDarwin_i386::WriteRegister(const RegisterInfo *reg_info,
714 const RegisterValue &value) {
715 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
716 int set = GetSetForNativeRegNum(reg);
721 if (ReadRegisterSet(set, false) != 0)
741 (&gpr.eax)[reg - gpr_eax] = value.GetAsUInt32();
745 fpu.fcw = value.GetAsUInt16();
749 fpu.fsw = value.GetAsUInt16();
753 fpu.ftw = value.GetAsUInt8();
757 fpu.fop = value.GetAsUInt16();
761 fpu.ip = value.GetAsUInt32();
765 fpu.cs = value.GetAsUInt16();
769 fpu.dp = value.GetAsUInt32();
773 fpu.ds = value.GetAsUInt16();
777 fpu.mxcsr = value.GetAsUInt32();
781 fpu.mxcsrmask = value.GetAsUInt32();
792 // These values don't fit into scalar types,
793 // RegisterContext::ReadRegisterBytes() must be used for these registers
794 ::memcpy(fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(),
795 value.GetByteSize());
806 // These values don't fit into scalar types,
807 // RegisterContext::ReadRegisterBytes() must be used for these registers
808 ::memcpy(fpu.xmm[reg - fpu_xmm0].bytes, value.GetBytes(),
809 value.GetByteSize());
813 exc.trapno = value.GetAsUInt32();
817 exc.err = value.GetAsUInt32();
821 exc.faultvaddr = value.GetAsUInt32();
827 return WriteRegisterSet(set) == 0;
830 bool RegisterContextDarwin_i386::ReadAllRegisterValues(
831 lldb::DataBufferSP &data_sp) {
832 data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);
833 if (ReadGPR(false) == 0 && ReadFPU(false) == 0 && ReadEXC(false) == 0) {
834 uint8_t *dst = data_sp->GetBytes();
835 ::memcpy(dst, &gpr, sizeof(gpr));
838 ::memcpy(dst, &fpu, sizeof(fpu));
841 ::memcpy(dst, &exc, sizeof(exc));
847 bool RegisterContextDarwin_i386::WriteAllRegisterValues(
848 const lldb::DataBufferSP &data_sp) {
849 if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
850 const uint8_t *src = data_sp->GetBytes();
851 ::memcpy(&gpr, src, sizeof(gpr));
854 ::memcpy(&fpu, src, sizeof(fpu));
857 ::memcpy(&exc, src, sizeof(exc));
858 uint32_t success_count = 0;
865 return success_count == 3;
870 uint32_t RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber(
871 lldb::RegisterKind kind, uint32_t reg) {
872 if (kind == eRegisterKindGeneric) {
874 case LLDB_REGNUM_GENERIC_PC:
876 case LLDB_REGNUM_GENERIC_SP:
878 case LLDB_REGNUM_GENERIC_FP:
880 case LLDB_REGNUM_GENERIC_FLAGS:
882 case LLDB_REGNUM_GENERIC_RA:
886 } else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF) {
943 } else if (kind == eRegisterKindLLDB) {
946 return LLDB_INVALID_REGNUM;
949 bool RegisterContextDarwin_i386::HardwareSingleStep(bool enable) {
950 if (ReadGPR(false) != 0)
953 const uint32_t trace_bit = 0x100u;
955 // If the trace bit is already set, there is nothing to do
956 if (gpr.eflags & trace_bit)
959 gpr.eflags |= trace_bit;
961 // If the trace bit is already cleared, there is nothing to do
962 if (gpr.eflags & trace_bit)
963 gpr.eflags &= ~trace_bit;
968 return WriteGPR() == 0;