1 //===-- RegisterContextDarwin_arm.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 "RegisterContextDarwin_arm.h"
10 #include "RegisterContextDarwinConstants.h"
12 #include "lldb/Utility/DataBufferHeap.h"
13 #include "lldb/Utility/DataExtractor.h"
14 #include "lldb/Utility/Endian.h"
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/RegisterValue.h"
17 #include "lldb/Utility/Scalar.h"
18 #include "llvm/Support/Compiler.h"
20 #include "Plugins/Process/Utility/InstructionUtils.h"
24 #include "Utility/ARM_DWARF_Registers.h"
25 #include "Utility/ARM_ehframe_Registers.h"
27 #include "llvm/ADT/STLExtras.h"
30 using namespace lldb_private
;
163 #define GPR_OFFSET(idx) ((idx)*4)
164 #define FPU_OFFSET(idx) ((idx)*4 + sizeof(RegisterContextDarwin_arm::GPR))
165 #define EXC_OFFSET(idx) \
166 ((idx)*4 + sizeof(RegisterContextDarwin_arm::GPR) + \
167 sizeof(RegisterContextDarwin_arm::FPU))
168 #define DBG_OFFSET(reg) \
169 ((LLVM_EXTENSION offsetof(RegisterContextDarwin_arm::DBG, reg) + \
170 sizeof(RegisterContextDarwin_arm::GPR) + \
171 sizeof(RegisterContextDarwin_arm::FPU) + \
172 sizeof(RegisterContextDarwin_arm::EXC)))
174 #define DEFINE_DBG(reg, i) \
175 #reg, NULL, sizeof(((RegisterContextDarwin_arm::DBG *) NULL)->reg[i]), \
176 DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, \
177 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
178 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
179 LLDB_INVALID_REGNUM }, \
180 nullptr, nullptr, nullptr,
181 #define REG_CONTEXT_SIZE \
182 (sizeof(RegisterContextDarwin_arm::GPR) + \
183 sizeof(RegisterContextDarwin_arm::FPU) + \
184 sizeof(RegisterContextDarwin_arm::EXC))
186 static RegisterInfo g_register_infos
[] = {
193 {ehframe_r0
, dwarf_r0
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
, gpr_r0
},
204 {ehframe_r1
, dwarf_r1
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
, gpr_r1
},
215 {ehframe_r2
, dwarf_r2
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
, gpr_r2
},
226 {ehframe_r3
, dwarf_r3
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
, gpr_r3
},
237 {ehframe_r4
, dwarf_r4
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
, gpr_r4
},
248 {ehframe_r5
, dwarf_r5
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
, gpr_r5
},
259 {ehframe_r6
, dwarf_r6
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
, gpr_r6
},
270 {ehframe_r7
, dwarf_r7
, LLDB_REGNUM_GENERIC_FP
, LLDB_INVALID_REGNUM
,
282 {ehframe_r8
, dwarf_r8
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
, gpr_r8
},
293 {ehframe_r9
, dwarf_r9
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
, gpr_r9
},
304 {ehframe_r10
, dwarf_r10
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
316 {ehframe_r11
, dwarf_r11
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
328 {ehframe_r12
, dwarf_r12
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
340 {ehframe_sp
, dwarf_sp
, LLDB_REGNUM_GENERIC_SP
, LLDB_INVALID_REGNUM
,
352 {ehframe_lr
, dwarf_lr
, LLDB_REGNUM_GENERIC_RA
, LLDB_INVALID_REGNUM
,
364 {ehframe_pc
, dwarf_pc
, LLDB_REGNUM_GENERIC_PC
, LLDB_INVALID_REGNUM
,
376 {ehframe_cpsr
, dwarf_cpsr
, LLDB_REGNUM_GENERIC_FLAGS
, LLDB_INVALID_REGNUM
,
389 {LLDB_INVALID_REGNUM
, dwarf_s0
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
401 {LLDB_INVALID_REGNUM
, dwarf_s1
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
413 {LLDB_INVALID_REGNUM
, dwarf_s2
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
425 {LLDB_INVALID_REGNUM
, dwarf_s3
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
437 {LLDB_INVALID_REGNUM
, dwarf_s4
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
449 {LLDB_INVALID_REGNUM
, dwarf_s5
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
461 {LLDB_INVALID_REGNUM
, dwarf_s6
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
473 {LLDB_INVALID_REGNUM
, dwarf_s7
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
485 {LLDB_INVALID_REGNUM
, dwarf_s8
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
497 {LLDB_INVALID_REGNUM
, dwarf_s9
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
509 {LLDB_INVALID_REGNUM
, dwarf_s10
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
521 {LLDB_INVALID_REGNUM
, dwarf_s11
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
533 {LLDB_INVALID_REGNUM
, dwarf_s12
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
545 {LLDB_INVALID_REGNUM
, dwarf_s13
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
557 {LLDB_INVALID_REGNUM
, dwarf_s14
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
569 {LLDB_INVALID_REGNUM
, dwarf_s15
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
581 {LLDB_INVALID_REGNUM
, dwarf_s16
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
593 {LLDB_INVALID_REGNUM
, dwarf_s17
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
605 {LLDB_INVALID_REGNUM
, dwarf_s18
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
617 {LLDB_INVALID_REGNUM
, dwarf_s19
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
629 {LLDB_INVALID_REGNUM
, dwarf_s20
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
641 {LLDB_INVALID_REGNUM
, dwarf_s21
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
653 {LLDB_INVALID_REGNUM
, dwarf_s22
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
665 {LLDB_INVALID_REGNUM
, dwarf_s23
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
677 {LLDB_INVALID_REGNUM
, dwarf_s24
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
689 {LLDB_INVALID_REGNUM
, dwarf_s25
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
701 {LLDB_INVALID_REGNUM
, dwarf_s26
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
713 {LLDB_INVALID_REGNUM
, dwarf_s27
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
725 {LLDB_INVALID_REGNUM
, dwarf_s28
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
737 {LLDB_INVALID_REGNUM
, dwarf_s29
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
749 {LLDB_INVALID_REGNUM
, dwarf_s30
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
761 {LLDB_INVALID_REGNUM
, dwarf_s31
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
773 {LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
774 LLDB_INVALID_REGNUM
, fpu_fpscr
},
786 {LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
787 LLDB_INVALID_REGNUM
, exc_exception
},
798 {LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
799 LLDB_INVALID_REGNUM
, exc_fsr
},
810 {LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
811 LLDB_INVALID_REGNUM
, exc_far
},
817 {DEFINE_DBG(bvr
, 0)},
818 {DEFINE_DBG(bvr
, 1)},
819 {DEFINE_DBG(bvr
, 2)},
820 {DEFINE_DBG(bvr
, 3)},
821 {DEFINE_DBG(bvr
, 4)},
822 {DEFINE_DBG(bvr
, 5)},
823 {DEFINE_DBG(bvr
, 6)},
824 {DEFINE_DBG(bvr
, 7)},
825 {DEFINE_DBG(bvr
, 8)},
826 {DEFINE_DBG(bvr
, 9)},
827 {DEFINE_DBG(bvr
, 10)},
828 {DEFINE_DBG(bvr
, 11)},
829 {DEFINE_DBG(bvr
, 12)},
830 {DEFINE_DBG(bvr
, 13)},
831 {DEFINE_DBG(bvr
, 14)},
832 {DEFINE_DBG(bvr
, 15)},
834 {DEFINE_DBG(bcr
, 0)},
835 {DEFINE_DBG(bcr
, 1)},
836 {DEFINE_DBG(bcr
, 2)},
837 {DEFINE_DBG(bcr
, 3)},
838 {DEFINE_DBG(bcr
, 4)},
839 {DEFINE_DBG(bcr
, 5)},
840 {DEFINE_DBG(bcr
, 6)},
841 {DEFINE_DBG(bcr
, 7)},
842 {DEFINE_DBG(bcr
, 8)},
843 {DEFINE_DBG(bcr
, 9)},
844 {DEFINE_DBG(bcr
, 10)},
845 {DEFINE_DBG(bcr
, 11)},
846 {DEFINE_DBG(bcr
, 12)},
847 {DEFINE_DBG(bcr
, 13)},
848 {DEFINE_DBG(bcr
, 14)},
849 {DEFINE_DBG(bcr
, 15)},
851 {DEFINE_DBG(wvr
, 0)},
852 {DEFINE_DBG(wvr
, 1)},
853 {DEFINE_DBG(wvr
, 2)},
854 {DEFINE_DBG(wvr
, 3)},
855 {DEFINE_DBG(wvr
, 4)},
856 {DEFINE_DBG(wvr
, 5)},
857 {DEFINE_DBG(wvr
, 6)},
858 {DEFINE_DBG(wvr
, 7)},
859 {DEFINE_DBG(wvr
, 8)},
860 {DEFINE_DBG(wvr
, 9)},
861 {DEFINE_DBG(wvr
, 10)},
862 {DEFINE_DBG(wvr
, 11)},
863 {DEFINE_DBG(wvr
, 12)},
864 {DEFINE_DBG(wvr
, 13)},
865 {DEFINE_DBG(wvr
, 14)},
866 {DEFINE_DBG(wvr
, 15)},
868 {DEFINE_DBG(wcr
, 0)},
869 {DEFINE_DBG(wcr
, 1)},
870 {DEFINE_DBG(wcr
, 2)},
871 {DEFINE_DBG(wcr
, 3)},
872 {DEFINE_DBG(wcr
, 4)},
873 {DEFINE_DBG(wcr
, 5)},
874 {DEFINE_DBG(wcr
, 6)},
875 {DEFINE_DBG(wcr
, 7)},
876 {DEFINE_DBG(wcr
, 8)},
877 {DEFINE_DBG(wcr
, 9)},
878 {DEFINE_DBG(wcr
, 10)},
879 {DEFINE_DBG(wcr
, 11)},
880 {DEFINE_DBG(wcr
, 12)},
881 {DEFINE_DBG(wcr
, 13)},
882 {DEFINE_DBG(wcr
, 14)},
883 {DEFINE_DBG(wcr
, 15)}};
885 // General purpose registers
886 static uint32_t g_gpr_regnums
[] = {
887 gpr_r0
, gpr_r1
, gpr_r2
, gpr_r3
, gpr_r4
, gpr_r5
, gpr_r6
, gpr_r7
, gpr_r8
,
888 gpr_r9
, gpr_r10
, gpr_r11
, gpr_r12
, gpr_sp
, gpr_lr
, gpr_pc
, gpr_cpsr
};
890 // Floating point registers
891 static uint32_t g_fpu_regnums
[] = {
892 fpu_s0
, fpu_s1
, fpu_s2
, fpu_s3
, fpu_s4
, fpu_s5
, fpu_s6
,
893 fpu_s7
, fpu_s8
, fpu_s9
, fpu_s10
, fpu_s11
, fpu_s12
, fpu_s13
,
894 fpu_s14
, fpu_s15
, fpu_s16
, fpu_s17
, fpu_s18
, fpu_s19
, fpu_s20
,
895 fpu_s21
, fpu_s22
, fpu_s23
, fpu_s24
, fpu_s25
, fpu_s26
, fpu_s27
,
896 fpu_s28
, fpu_s29
, fpu_s30
, fpu_s31
, fpu_fpscr
,
899 // Exception registers
901 static uint32_t g_exc_regnums
[] = {
902 exc_exception
, exc_fsr
, exc_far
,
905 static size_t k_num_register_infos
= std::size(g_register_infos
);
907 RegisterContextDarwin_arm::RegisterContextDarwin_arm(
908 Thread
&thread
, uint32_t concrete_frame_idx
)
909 : RegisterContext(thread
, concrete_frame_idx
), gpr(), fpu(), exc() {
911 for (i
= 0; i
< kNumErrors
; i
++) {
918 RegisterContextDarwin_arm::~RegisterContextDarwin_arm() = default;
920 void RegisterContextDarwin_arm::InvalidateAllRegisters() {
921 InvalidateAllRegisterStates();
924 size_t RegisterContextDarwin_arm::GetRegisterCount() {
925 assert(k_num_register_infos
== k_num_registers
);
926 return k_num_registers
;
930 RegisterContextDarwin_arm::GetRegisterInfoAtIndex(size_t reg
) {
931 assert(k_num_register_infos
== k_num_registers
);
932 if (reg
< k_num_registers
)
933 return &g_register_infos
[reg
];
937 size_t RegisterContextDarwin_arm::GetRegisterInfosCount() {
938 return k_num_register_infos
;
941 const RegisterInfo
*RegisterContextDarwin_arm::GetRegisterInfos() {
942 return g_register_infos
;
945 // Number of registers in each register set
946 const size_t k_num_gpr_registers
= std::size(g_gpr_regnums
);
947 const size_t k_num_fpu_registers
= std::size(g_fpu_regnums
);
948 const size_t k_num_exc_registers
= std::size(g_exc_regnums
);
950 // Register set definitions. The first definitions at register set index of
951 // zero is for all registers, followed by other registers sets. The register
952 // information for the all register set need not be filled in.
953 static const RegisterSet g_reg_sets
[] = {
955 "General Purpose Registers", "gpr", k_num_gpr_registers
, g_gpr_regnums
,
957 {"Floating Point Registers", "fpu", k_num_fpu_registers
, g_fpu_regnums
},
958 {"Exception State Registers", "exc", k_num_exc_registers
, g_exc_regnums
}};
960 const size_t k_num_regsets
= std::size(g_reg_sets
);
962 size_t RegisterContextDarwin_arm::GetRegisterSetCount() {
963 return k_num_regsets
;
966 const RegisterSet
*RegisterContextDarwin_arm::GetRegisterSet(size_t reg_set
) {
967 if (reg_set
< k_num_regsets
)
968 return &g_reg_sets
[reg_set
];
972 // Register information definitions for 32 bit i386.
973 int RegisterContextDarwin_arm::GetSetForNativeRegNum(int reg
) {
976 else if (reg
< exc_exception
)
978 else if (reg
< k_num_registers
)
983 int RegisterContextDarwin_arm::ReadGPR(bool force
) {
985 if (force
|| !RegisterSetIsCached(set
)) {
986 SetError(set
, Read
, DoReadGPR(GetThreadID(), set
, gpr
));
988 return GetError(GPRRegSet
, Read
);
991 int RegisterContextDarwin_arm::ReadFPU(bool force
) {
993 if (force
|| !RegisterSetIsCached(set
)) {
994 SetError(set
, Read
, DoReadFPU(GetThreadID(), set
, fpu
));
996 return GetError(FPURegSet
, Read
);
999 int RegisterContextDarwin_arm::ReadEXC(bool force
) {
1000 int set
= EXCRegSet
;
1001 if (force
|| !RegisterSetIsCached(set
)) {
1002 SetError(set
, Read
, DoReadEXC(GetThreadID(), set
, exc
));
1004 return GetError(EXCRegSet
, Read
);
1007 int RegisterContextDarwin_arm::ReadDBG(bool force
) {
1008 int set
= DBGRegSet
;
1009 if (force
|| !RegisterSetIsCached(set
)) {
1010 SetError(set
, Read
, DoReadDBG(GetThreadID(), set
, dbg
));
1012 return GetError(DBGRegSet
, Read
);
1015 int RegisterContextDarwin_arm::WriteGPR() {
1016 int set
= GPRRegSet
;
1017 if (!RegisterSetIsCached(set
)) {
1018 SetError(set
, Write
, -1);
1019 return KERN_INVALID_ARGUMENT
;
1021 SetError(set
, Write
, DoWriteGPR(GetThreadID(), set
, gpr
));
1022 SetError(set
, Read
, -1);
1023 return GetError(GPRRegSet
, Write
);
1026 int RegisterContextDarwin_arm::WriteFPU() {
1027 int set
= FPURegSet
;
1028 if (!RegisterSetIsCached(set
)) {
1029 SetError(set
, Write
, -1);
1030 return KERN_INVALID_ARGUMENT
;
1032 SetError(set
, Write
, DoWriteFPU(GetThreadID(), set
, fpu
));
1033 SetError(set
, Read
, -1);
1034 return GetError(FPURegSet
, Write
);
1037 int RegisterContextDarwin_arm::WriteEXC() {
1038 int set
= EXCRegSet
;
1039 if (!RegisterSetIsCached(set
)) {
1040 SetError(set
, Write
, -1);
1041 return KERN_INVALID_ARGUMENT
;
1043 SetError(set
, Write
, DoWriteEXC(GetThreadID(), set
, exc
));
1044 SetError(set
, Read
, -1);
1045 return GetError(EXCRegSet
, Write
);
1048 int RegisterContextDarwin_arm::WriteDBG() {
1049 int set
= DBGRegSet
;
1050 if (!RegisterSetIsCached(set
)) {
1051 SetError(set
, Write
, -1);
1052 return KERN_INVALID_ARGUMENT
;
1054 SetError(set
, Write
, DoWriteDBG(GetThreadID(), set
, dbg
));
1055 SetError(set
, Read
, -1);
1056 return GetError(DBGRegSet
, Write
);
1059 int RegisterContextDarwin_arm::ReadRegisterSet(uint32_t set
, bool force
) {
1062 return ReadGPR(force
);
1064 return ReadGPR(force
);
1066 return ReadFPU(force
);
1068 return ReadEXC(force
);
1070 return ReadDBG(force
);
1074 return KERN_INVALID_ARGUMENT
;
1077 int RegisterContextDarwin_arm::WriteRegisterSet(uint32_t set
) {
1078 // Make sure we have a valid context to set.
1079 if (RegisterSetIsCached(set
)) {
1095 return KERN_INVALID_ARGUMENT
;
1098 void RegisterContextDarwin_arm::LogDBGRegisters(Log
*log
, const DBG
&dbg
) {
1100 for (uint32_t i
= 0; i
< 16; i
++)
1102 "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { "
1103 "0x%8.8x, 0x%8.8x }",
1104 i
, i
, dbg
.bvr
[i
], dbg
.bcr
[i
], i
, i
, dbg
.wvr
[i
], dbg
.wcr
[i
]);
1108 bool RegisterContextDarwin_arm::ReadRegister(const RegisterInfo
*reg_info
,
1109 RegisterValue
&value
) {
1110 const uint32_t reg
= reg_info
->kinds
[eRegisterKindLLDB
];
1111 int set
= RegisterContextDarwin_arm::GetSetForNativeRegNum(reg
);
1116 if (ReadRegisterSet(set
, false) != KERN_SUCCESS
)
1136 value
.SetUInt32(gpr
.r
[reg
- gpr_r0
]);
1139 value
.SetUInt32(gpr
.cpsr
);
1173 value
.SetUInt32(fpu
.floats
.s
[reg
], RegisterValue::eTypeFloat
);
1177 value
.SetUInt32(fpu
.fpscr
);
1181 value
.SetUInt32(exc
.exception
);
1184 value
.SetUInt32(exc
.fsr
);
1187 value
.SetUInt32(exc
.far
);
1191 value
.SetValueToInvalid();
1197 bool RegisterContextDarwin_arm::WriteRegister(const RegisterInfo
*reg_info
,
1198 const RegisterValue
&value
) {
1199 const uint32_t reg
= reg_info
->kinds
[eRegisterKindLLDB
];
1200 int set
= GetSetForNativeRegNum(reg
);
1205 if (ReadRegisterSet(set
, false) != KERN_SUCCESS
)
1226 gpr
.r
[reg
- gpr_r0
] = value
.GetAsUInt32();
1261 fpu
.floats
.s
[reg
] = value
.GetAsUInt32();
1265 fpu
.fpscr
= value
.GetAsUInt32();
1269 exc
.exception
= value
.GetAsUInt32();
1272 exc
.fsr
= value
.GetAsUInt32();
1275 exc
.far
= value
.GetAsUInt32();
1281 return WriteRegisterSet(set
) == KERN_SUCCESS
;
1284 bool RegisterContextDarwin_arm::ReadAllRegisterValues(
1285 lldb::WritableDataBufferSP
&data_sp
) {
1286 data_sp
= std::make_shared
<DataBufferHeap
>(REG_CONTEXT_SIZE
, 0);
1287 if (data_sp
&& ReadGPR(false) == KERN_SUCCESS
&&
1288 ReadFPU(false) == KERN_SUCCESS
&& ReadEXC(false) == KERN_SUCCESS
) {
1289 uint8_t *dst
= data_sp
->GetBytes();
1290 ::memcpy(dst
, &gpr
, sizeof(gpr
));
1293 ::memcpy(dst
, &fpu
, sizeof(fpu
));
1296 ::memcpy(dst
, &exc
, sizeof(exc
));
1302 bool RegisterContextDarwin_arm::WriteAllRegisterValues(
1303 const lldb::DataBufferSP
&data_sp
) {
1304 if (data_sp
&& data_sp
->GetByteSize() == REG_CONTEXT_SIZE
) {
1305 const uint8_t *src
= data_sp
->GetBytes();
1306 ::memcpy(&gpr
, src
, sizeof(gpr
));
1309 ::memcpy(&fpu
, src
, sizeof(fpu
));
1312 ::memcpy(&exc
, src
, sizeof(exc
));
1313 uint32_t success_count
= 0;
1314 if (WriteGPR() == KERN_SUCCESS
)
1316 if (WriteFPU() == KERN_SUCCESS
)
1318 if (WriteEXC() == KERN_SUCCESS
)
1320 return success_count
== 3;
1325 uint32_t RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber(
1326 lldb::RegisterKind kind
, uint32_t reg
) {
1327 if (kind
== eRegisterKindGeneric
) {
1329 case LLDB_REGNUM_GENERIC_PC
:
1331 case LLDB_REGNUM_GENERIC_SP
:
1333 case LLDB_REGNUM_GENERIC_FP
:
1335 case LLDB_REGNUM_GENERIC_RA
:
1337 case LLDB_REGNUM_GENERIC_FLAGS
:
1342 } else if (kind
== eRegisterKindDWARF
) {
1447 } else if (kind
== eRegisterKindEHFrame
) {
1484 } else if (kind
== eRegisterKindLLDB
) {
1487 return LLDB_INVALID_REGNUM
;
1490 uint32_t RegisterContextDarwin_arm::NumSupportedHardwareBreakpoints() {
1491 #if defined(__APPLE__) && defined(__arm__)
1492 // Set the init value to something that will let us know that we need to
1493 // autodetect how many breakpoints are supported dynamically...
1494 static uint32_t g_num_supported_hw_breakpoints
= UINT32_MAX
;
1495 if (g_num_supported_hw_breakpoints
== UINT32_MAX
) {
1496 // Set this to zero in case we can't tell if there are any HW breakpoints
1497 g_num_supported_hw_breakpoints
= 0;
1499 uint32_t register_DBGDIDR
;
1501 asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR
));
1502 g_num_supported_hw_breakpoints
= Bits32(register_DBGDIDR
, 27, 24);
1503 // Zero is reserved for the BRP count, so don't increment it if it is zero
1504 if (g_num_supported_hw_breakpoints
> 0)
1505 g_num_supported_hw_breakpoints
++;
1507 return g_num_supported_hw_breakpoints
;
1509 // TODO: figure out remote case here!
1514 uint32_t RegisterContextDarwin_arm::SetHardwareBreakpoint(lldb::addr_t addr
,
1516 // Make sure our address isn't bogus
1518 return LLDB_INVALID_INDEX32
;
1520 int kret
= ReadDBG(false);
1522 if (kret
== KERN_SUCCESS
) {
1523 const uint32_t num_hw_breakpoints
= NumSupportedHardwareBreakpoints();
1525 for (i
= 0; i
< num_hw_breakpoints
; ++i
) {
1526 if ((dbg
.bcr
[i
] & BCR_ENABLE
) == 0)
1527 break; // We found an available hw breakpoint slot (in i)
1530 // See if we found an available hw breakpoint slot above
1531 if (i
< num_hw_breakpoints
) {
1532 // Make sure bits 1:0 are clear in our address
1533 dbg
.bvr
[i
] = addr
& ~((lldb::addr_t
)3);
1535 if (size
== 2 || addr
& 2) {
1536 uint32_t byte_addr_select
= (addr
& 2) ? BAS_IMVA_2_3
: BAS_IMVA_0_1
;
1538 // We have a thumb breakpoint
1539 // We have an ARM breakpoint
1540 dbg
.bcr
[i
] = BCR_M_IMVA_MATCH
| // Stop on address match
1541 byte_addr_select
| // Set the correct byte address select
1542 // so we only trigger on the correct
1544 S_USER
| // Which modes should this breakpoint stop in?
1545 BCR_ENABLE
; // Enable this hardware breakpoint
1546 // if (log) log->Printf
1547 // ("RegisterContextDarwin_arm::EnableHardwareBreakpoint(
1548 // addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x /
1549 // 0x%8.8x (Thumb)",
1556 } else if (size
== 4) {
1557 // We have an ARM breakpoint
1559 BCR_M_IMVA_MATCH
| // Stop on address match
1560 BAS_IMVA_ALL
| // Stop on any of the four bytes following the IMVA
1561 S_USER
| // Which modes should this breakpoint stop in?
1562 BCR_ENABLE
; // Enable this hardware breakpoint
1563 // if (log) log->Printf
1564 // ("RegisterContextDarwin_arm::EnableHardwareBreakpoint(
1565 // addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x /
1576 // if (log) log->Printf
1577 // ("RegisterContextDarwin_arm::EnableHardwareBreakpoint()
1578 // WriteDBG() => 0x%8.8x.", kret);
1580 if (kret
== KERN_SUCCESS
)
1585 // if (log) log->Printf
1586 // ("RegisterContextDarwin_arm::EnableHardwareBreakpoint(addr =
1587 // %8.8p, size = %u) => all hardware breakpoint resources are
1588 // being used.", addr, size);
1592 return LLDB_INVALID_INDEX32
;
1595 bool RegisterContextDarwin_arm::ClearHardwareBreakpoint(uint32_t hw_index
) {
1596 int kret
= ReadDBG(false);
1598 const uint32_t num_hw_points
= NumSupportedHardwareBreakpoints();
1599 if (kret
== KERN_SUCCESS
) {
1600 if (hw_index
< num_hw_points
) {
1601 dbg
.bcr
[hw_index
] = 0;
1602 // if (log) log->Printf
1603 // ("RegisterContextDarwin_arm::SetHardwareBreakpoint( %u ) -
1604 // BVR%u = 0x%8.8x BCR%u = 0x%8.8x",
1607 // dbg.bvr[hw_index],
1609 // dbg.bcr[hw_index]);
1613 if (kret
== KERN_SUCCESS
)
1620 uint32_t RegisterContextDarwin_arm::NumSupportedHardwareWatchpoints() {
1621 #if defined(__APPLE__) && defined(__arm__)
1622 // Set the init value to something that will let us know that we need to
1623 // autodetect how many watchpoints are supported dynamically...
1624 static uint32_t g_num_supported_hw_watchpoints
= UINT32_MAX
;
1625 if (g_num_supported_hw_watchpoints
== UINT32_MAX
) {
1626 // Set this to zero in case we can't tell if there are any HW breakpoints
1627 g_num_supported_hw_watchpoints
= 0;
1629 uint32_t register_DBGDIDR
;
1630 asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR
));
1631 g_num_supported_hw_watchpoints
= Bits32(register_DBGDIDR
, 31, 28) + 1;
1633 return g_num_supported_hw_watchpoints
;
1635 // TODO: figure out remote case here!
1640 uint32_t RegisterContextDarwin_arm::SetHardwareWatchpoint(lldb::addr_t addr
,
1644 const uint32_t num_hw_watchpoints
= NumSupportedHardwareWatchpoints();
1646 // Can't watch zero bytes
1648 return LLDB_INVALID_INDEX32
;
1650 // We must watch for either read or write
1651 if (!read
&& !write
)
1652 return LLDB_INVALID_INDEX32
;
1654 // Can't watch more than 4 bytes per WVR/WCR pair
1656 return LLDB_INVALID_INDEX32
;
1658 // We can only watch up to four bytes that follow a 4 byte aligned address
1659 // per watchpoint register pair. Since we have at most so we can only watch
1660 // until the next 4 byte boundary and we need to make sure we can properly
1662 uint32_t addr_word_offset
= addr
% 4;
1663 // if (log) log->Printf
1664 // ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() -
1665 // addr_word_offset = 0x%8.8x", addr_word_offset);
1667 uint32_t byte_mask
= ((1u << size
) - 1u) << addr_word_offset
;
1668 // if (log) log->Printf
1669 // ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() - byte_mask =
1670 // 0x%8.8x", byte_mask);
1671 if (byte_mask
> 0xfu
)
1672 return LLDB_INVALID_INDEX32
;
1674 // Read the debug state
1675 int kret
= ReadDBG(false);
1677 if (kret
== KERN_SUCCESS
) {
1678 // Check to make sure we have the needed hardware support
1681 for (i
= 0; i
< num_hw_watchpoints
; ++i
) {
1682 if ((dbg
.wcr
[i
] & WCR_ENABLE
) == 0)
1683 break; // We found an available hw breakpoint slot (in i)
1686 // See if we found an available hw breakpoint slot above
1687 if (i
< num_hw_watchpoints
) {
1688 // Make the byte_mask into a valid Byte Address Select mask
1689 uint32_t byte_address_select
= byte_mask
<< 5;
1690 // Make sure bits 1:0 are clear in our address
1691 dbg
.wvr
[i
] = addr
& ~((lldb::addr_t
)3);
1692 dbg
.wcr
[i
] = byte_address_select
| // Which bytes that follow the IMVA
1693 // that we will watch
1694 S_USER
| // Stop only in user mode
1695 (read
? WCR_LOAD
: 0) | // Stop on read access?
1696 (write
? WCR_STORE
: 0) | // Stop on write access?
1697 WCR_ENABLE
; // Enable this watchpoint;
1700 // if (log) log->Printf
1701 // ("RegisterContextDarwin_arm::EnableHardwareWatchpoint()
1702 // WriteDBG() => 0x%8.8x.", kret);
1704 if (kret
== KERN_SUCCESS
)
1707 // if (log) log->Printf
1708 // ("RegisterContextDarwin_arm::EnableHardwareWatchpoint(): All
1709 // hardware resources (%u) are in use.", num_hw_watchpoints);
1712 return LLDB_INVALID_INDEX32
;
1715 bool RegisterContextDarwin_arm::ClearHardwareWatchpoint(uint32_t hw_index
) {
1716 int kret
= ReadDBG(false);
1718 const uint32_t num_hw_points
= NumSupportedHardwareWatchpoints();
1719 if (kret
== KERN_SUCCESS
) {
1720 if (hw_index
< num_hw_points
) {
1721 dbg
.wcr
[hw_index
] = 0;
1722 // if (log) log->Printf
1723 // ("RegisterContextDarwin_arm::ClearHardwareWatchpoint( %u ) -
1724 // WVR%u = 0x%8.8x WCR%u = 0x%8.8x",
1727 // dbg.wvr[hw_index],
1729 // dbg.wcr[hw_index]);
1733 if (kret
== KERN_SUCCESS
)