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 #include "RegisterContextDarwin_i386.h"
25 using namespace lldb_private;
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))
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
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) \
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, \
157 nullptr, nullptr, nullptr, 0
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))
167 static RegisterInfo g_register_infos[] = {
168 // Macro auto defines most stuff eh_frame DWARF
169 // GENERIC PROCESS PLUGIN LLDB
170 // =============================== =======================
171 // =================== ========================= ==================
173 {DEFINE_GPR(eax, nullptr),
174 {ehframe_eax, dwarf_eax, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
180 {DEFINE_GPR(ebx, nullptr),
181 {ehframe_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
187 {DEFINE_GPR(ecx, nullptr),
188 {ehframe_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
194 {DEFINE_GPR(edx, nullptr),
195 {ehframe_edx, dwarf_edx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
201 {DEFINE_GPR(edi, nullptr),
202 {ehframe_edi, dwarf_edi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
208 {DEFINE_GPR(esi, nullptr),
209 {ehframe_esi, dwarf_esi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
215 {DEFINE_GPR(ebp, "fp"),
216 {ehframe_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
222 {DEFINE_GPR(esp, "sp"),
223 {ehframe_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
229 {DEFINE_GPR(ss, nullptr),
230 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
231 LLDB_INVALID_REGNUM, gpr_ss},
236 {DEFINE_GPR(eflags, "flags"),
237 {ehframe_eflags, dwarf_eflags, LLDB_REGNUM_GENERIC_FLAGS,
238 LLDB_INVALID_REGNUM, gpr_eflags},
243 {DEFINE_GPR(eip, "pc"),
244 {ehframe_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
250 {DEFINE_GPR(cs, nullptr),
251 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
252 LLDB_INVALID_REGNUM, gpr_cs},
257 {DEFINE_GPR(ds, nullptr),
258 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
259 LLDB_INVALID_REGNUM, gpr_ds},
264 {DEFINE_GPR(es, nullptr),
265 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
266 LLDB_INVALID_REGNUM, gpr_es},
271 {DEFINE_GPR(fs, nullptr),
272 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
273 LLDB_INVALID_REGNUM, gpr_fs},
278 {DEFINE_GPR(gs, nullptr),
279 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
280 LLDB_INVALID_REGNUM, gpr_gs},
286 {DEFINE_FPU_UINT(fcw),
287 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
288 LLDB_INVALID_REGNUM, fpu_fcw},
293 {DEFINE_FPU_UINT(fsw),
294 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
295 LLDB_INVALID_REGNUM, fpu_fsw},
300 {DEFINE_FPU_UINT(ftw),
301 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
302 LLDB_INVALID_REGNUM, fpu_ftw},
307 {DEFINE_FPU_UINT(fop),
308 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
309 LLDB_INVALID_REGNUM, fpu_fop},
314 {DEFINE_FPU_UINT(ip),
315 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
316 LLDB_INVALID_REGNUM, fpu_ip},
321 {DEFINE_FPU_UINT(cs),
322 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
323 LLDB_INVALID_REGNUM, fpu_cs},
328 {DEFINE_FPU_UINT(dp),
329 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
330 LLDB_INVALID_REGNUM, fpu_dp},
335 {DEFINE_FPU_UINT(ds),
336 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
337 LLDB_INVALID_REGNUM, fpu_ds},
342 {DEFINE_FPU_UINT(mxcsr),
343 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
344 LLDB_INVALID_REGNUM, fpu_mxcsr},
349 {DEFINE_FPU_UINT(mxcsrmask),
350 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
351 LLDB_INVALID_REGNUM, fpu_mxcsrmask},
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)},
374 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
375 LLDB_INVALID_REGNUM, exc_trapno},
381 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
382 LLDB_INVALID_REGNUM, exc_err},
387 {DEFINE_EXC(faultvaddr),
388 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
389 LLDB_INVALID_REGNUM, exc_faultvaddr},
395 static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
397 RegisterContextDarwin_i386::RegisterContextDarwin_i386(
398 Thread &thread, uint32_t concrete_frame_idx)
399 : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc() {
401 for (i = 0; i < kNumErrors; i++) {
408 RegisterContextDarwin_i386::~RegisterContextDarwin_i386() {}
410 void RegisterContextDarwin_i386::InvalidateAllRegisters() {
411 InvalidateAllRegisterStates();
414 size_t RegisterContextDarwin_i386::GetRegisterCount() {
415 assert(k_num_register_infos == k_num_registers);
416 return k_num_registers;
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];
427 size_t RegisterContextDarwin_i386::GetRegisterInfosCount() {
428 return k_num_register_infos;
431 const RegisterInfo *RegisterContextDarwin_i386::GetRegisterInfos() {
432 return g_register_infos;
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};
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,
448 // Exception registers
450 static uint32_t g_exc_regnums[] = {exc_trapno, exc_err, exc_faultvaddr};
452 // Number of registers in each register set
453 const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
454 const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
455 const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
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[] = {
462 "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums,
464 {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums},
465 {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}};
467 const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
469 size_t RegisterContextDarwin_i386::GetRegisterSetCount() {
470 return k_num_regsets;
473 const RegisterSet *RegisterContextDarwin_i386::GetRegisterSet(size_t reg_set) {
474 if (reg_set < k_num_regsets)
475 return &g_reg_sets[reg_set];
479 // Register information definitions for 32 bit i386.
480 int RegisterContextDarwin_i386::GetSetForNativeRegNum(int reg_num) {
481 if (reg_num < fpu_fcw)
483 else if (reg_num < exc_trapno)
485 else if (reg_num < k_num_registers)
490 void RegisterContextDarwin_i386::LogGPR(Log *log, const char *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,
502 int RegisterContextDarwin_i386::ReadGPR(bool force) {
504 if (force || !RegisterSetIsCached(set)) {
505 SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
507 return GetError(set, Read);
510 int RegisterContextDarwin_i386::ReadFPU(bool force) {
512 if (force || !RegisterSetIsCached(set)) {
513 SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
515 return GetError(set, Read);
518 int RegisterContextDarwin_i386::ReadEXC(bool force) {
520 if (force || !RegisterSetIsCached(set)) {
521 SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
523 return GetError(set, Read);
526 int RegisterContextDarwin_i386::WriteGPR() {
528 if (!RegisterSetIsCached(set)) {
529 SetError(set, Write, -1);
532 SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr));
533 SetError(set, Read, -1);
534 return GetError(set, Write);
537 int RegisterContextDarwin_i386::WriteFPU() {
539 if (!RegisterSetIsCached(set)) {
540 SetError(set, Write, -1);
543 SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu));
544 SetError(set, Read, -1);
545 return GetError(set, Write);
548 int RegisterContextDarwin_i386::WriteEXC() {
550 if (!RegisterSetIsCached(set)) {
551 SetError(set, Write, -1);
554 SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc));
555 SetError(set, Read, -1);
556 return GetError(set, Write);
559 int RegisterContextDarwin_i386::ReadRegisterSet(uint32_t set, bool force) {
562 return ReadGPR(force);
564 return ReadFPU(force);
566 return ReadEXC(force);
573 int RegisterContextDarwin_i386::WriteRegisterSet(uint32_t set) {
574 // Make sure we have a valid context to set.
575 if (RegisterSetIsCached(set)) {
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);
598 if (ReadRegisterSet(set, false) != 0)
618 value = (&gpr.eax)[reg - gpr_eax];
658 value = fpu.mxcsrmask;
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,
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,
698 value = exc.faultvaddr;
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);
715 if (ReadRegisterSet(set, false) != 0)
735 (&gpr.eax)[reg - gpr_eax] = value.GetAsUInt32();
739 fpu.fcw = value.GetAsUInt16();
743 fpu.fsw = value.GetAsUInt16();
747 fpu.ftw = value.GetAsUInt8();
751 fpu.fop = value.GetAsUInt16();
755 fpu.ip = value.GetAsUInt32();
759 fpu.cs = value.GetAsUInt16();
763 fpu.dp = value.GetAsUInt32();
767 fpu.ds = value.GetAsUInt16();
771 fpu.mxcsr = value.GetAsUInt32();
775 fpu.mxcsrmask = value.GetAsUInt32();
786 // These values don't fit into scalar types,
787 // RegisterContext::ReadRegisterBytes() must be used for these registers
788 ::memcpy(fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(),
789 value.GetByteSize());
800 // These values don't fit into scalar types,
801 // RegisterContext::ReadRegisterBytes() must be used for these registers
802 ::memcpy(fpu.xmm[reg - fpu_xmm0].bytes, value.GetBytes(),
803 value.GetByteSize());
807 exc.trapno = value.GetAsUInt32();
811 exc.err = value.GetAsUInt32();
815 exc.faultvaddr = value.GetAsUInt32();
821 return WriteRegisterSet(set) == 0;
824 bool RegisterContextDarwin_i386::ReadAllRegisterValues(
825 lldb::DataBufferSP &data_sp) {
826 data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);
827 if (ReadGPR(false) == 0 && ReadFPU(false) == 0 && ReadEXC(false) == 0) {
828 uint8_t *dst = data_sp->GetBytes();
829 ::memcpy(dst, &gpr, sizeof(gpr));
832 ::memcpy(dst, &fpu, sizeof(fpu));
835 ::memcpy(dst, &exc, sizeof(exc));
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(&gpr, src, sizeof(gpr));
848 ::memcpy(&fpu, src, sizeof(fpu));
851 ::memcpy(&exc, src, sizeof(exc));
852 uint32_t success_count = 0;
859 return success_count == 3;
864 uint32_t RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber(
865 lldb::RegisterKind kind, uint32_t reg) {
866 if (kind == eRegisterKindGeneric) {
868 case LLDB_REGNUM_GENERIC_PC:
870 case LLDB_REGNUM_GENERIC_SP:
872 case LLDB_REGNUM_GENERIC_FP:
874 case LLDB_REGNUM_GENERIC_FLAGS:
876 case LLDB_REGNUM_GENERIC_RA:
880 } else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF) {
937 } else if (kind == eRegisterKindLLDB) {
940 return LLDB_INVALID_REGNUM;
943 bool RegisterContextDarwin_i386::HardwareSingleStep(bool enable) {
944 if (ReadGPR(false) != 0)
947 const uint32_t trace_bit = 0x100u;
949 // If the trace bit is already set, there is nothing to do
950 if (gpr.eflags & trace_bit)
953 gpr.eflags |= trace_bit;
955 // If the trace bit is already cleared, there is nothing to do
956 if (gpr.eflags & trace_bit)
957 gpr.eflags &= ~trace_bit;
962 return WriteGPR() == 0;