1 //===-- RegisterContextDarwin_i386.cpp ------------------------------------===//
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,
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
= std::size(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() = default;
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
= 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
);
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
= std::size(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::WritableDataBufferSP
&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;