1 //===-- RegisterContextDarwin_arm.cpp ---------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #if defined(__APPLE__)
11 
12 #include "RegisterContextDarwin_arm.h"
13 
14 // C Includes
15 #include <mach/mach_types.h>
16 #include <mach/thread_act.h>
17 
18 // C++ Includes
19 // Other libraries and framework includes
20 #include "lldb/Core/DataBufferHeap.h"
21 #include "lldb/Core/DataExtractor.h"
22 #include "lldb/Core/Log.h"
23 #include "lldb/Core/RegisterValue.h"
24 #include "lldb/Core/Scalar.h"
25 #include "lldb/Host/Endian.h"
26 #include "llvm/Support/Compiler.h"
27 
28 #include "Plugins/Process/Utility/InstructionUtils.h"
29 
30 // Support building against older versions of LLVM, this macro was added
31 // recently.
32 #ifndef LLVM_EXTENSION
33 #define LLVM_EXTENSION
34 #endif
35 
36 // Project includes
37 #include "ARM_DWARF_Registers.h"
38 #include "Utility/ARM_ehframe_Registers.h"
39 
40 #include "llvm/ADT/STLExtras.h"
41 
42 using namespace lldb;
43 using namespace lldb_private;
44 
45 enum
46 {
47     gpr_r0 = 0,
48     gpr_r1,
49     gpr_r2,
50     gpr_r3,
51     gpr_r4,
52     gpr_r5,
53     gpr_r6,
54     gpr_r7,
55     gpr_r8,
56     gpr_r9,
57     gpr_r10,
58     gpr_r11,
59     gpr_r12,
60     gpr_r13, gpr_sp = gpr_r13,
61     gpr_r14, gpr_lr = gpr_r14,
62     gpr_r15, gpr_pc = gpr_r15,
63     gpr_cpsr,
64 
65     fpu_s0,
66     fpu_s1,
67     fpu_s2,
68     fpu_s3,
69     fpu_s4,
70     fpu_s5,
71     fpu_s6,
72     fpu_s7,
73     fpu_s8,
74     fpu_s9,
75     fpu_s10,
76     fpu_s11,
77     fpu_s12,
78     fpu_s13,
79     fpu_s14,
80     fpu_s15,
81     fpu_s16,
82     fpu_s17,
83     fpu_s18,
84     fpu_s19,
85     fpu_s20,
86     fpu_s21,
87     fpu_s22,
88     fpu_s23,
89     fpu_s24,
90     fpu_s25,
91     fpu_s26,
92     fpu_s27,
93     fpu_s28,
94     fpu_s29,
95     fpu_s30,
96     fpu_s31,
97     fpu_fpscr,
98 
99     exc_exception,
100     exc_fsr,
101     exc_far,
102 
103     dbg_bvr0,
104     dbg_bvr1,
105     dbg_bvr2,
106     dbg_bvr3,
107     dbg_bvr4,
108     dbg_bvr5,
109     dbg_bvr6,
110     dbg_bvr7,
111     dbg_bvr8,
112     dbg_bvr9,
113     dbg_bvr10,
114     dbg_bvr11,
115     dbg_bvr12,
116     dbg_bvr13,
117     dbg_bvr14,
118     dbg_bvr15,
119 
120     dbg_bcr0,
121     dbg_bcr1,
122     dbg_bcr2,
123     dbg_bcr3,
124     dbg_bcr4,
125     dbg_bcr5,
126     dbg_bcr6,
127     dbg_bcr7,
128     dbg_bcr8,
129     dbg_bcr9,
130     dbg_bcr10,
131     dbg_bcr11,
132     dbg_bcr12,
133     dbg_bcr13,
134     dbg_bcr14,
135     dbg_bcr15,
136 
137     dbg_wvr0,
138     dbg_wvr1,
139     dbg_wvr2,
140     dbg_wvr3,
141     dbg_wvr4,
142     dbg_wvr5,
143     dbg_wvr6,
144     dbg_wvr7,
145     dbg_wvr8,
146     dbg_wvr9,
147     dbg_wvr10,
148     dbg_wvr11,
149     dbg_wvr12,
150     dbg_wvr13,
151     dbg_wvr14,
152     dbg_wvr15,
153 
154     dbg_wcr0,
155     dbg_wcr1,
156     dbg_wcr2,
157     dbg_wcr3,
158     dbg_wcr4,
159     dbg_wcr5,
160     dbg_wcr6,
161     dbg_wcr7,
162     dbg_wcr8,
163     dbg_wcr9,
164     dbg_wcr10,
165     dbg_wcr11,
166     dbg_wcr12,
167     dbg_wcr13,
168     dbg_wcr14,
169     dbg_wcr15,
170 
171     k_num_registers
172 };
173 
174 
175 #define GPR_OFFSET(idx) ((idx) * 4)
176 #define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR))
177 #define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU))
178 #define DBG_OFFSET(reg) ((LLVM_EXTENSION offsetof (RegisterContextDarwin_arm::DBG, reg) + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC)))
179 
180 #define DEFINE_DBG(reg, i)  #reg, NULL, sizeof(((RegisterContextDarwin_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL
181 #define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC))
182 
183 static RegisterInfo g_register_infos[] = {
184 // General purpose registers
185 //  NAME        ALT     SZ  OFFSET              ENCODING        FORMAT          EH_FRAME                DWARF               GENERIC                     PROCESS PLUGIN          LLDB NATIVE   VALUE REGS    INVALIDATE REGS
186 //  ======      ======= ==  =============       =============   ============    ===============         ===============     =========================   =====================   ============= ==========    ===============
187 {   "r0",       NULL,   4,  GPR_OFFSET(0),      eEncodingUint,  eFormatHex,     { ehframe_r0,               dwarf_r0,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r0      },      NULL,              NULL},
188 {   "r1",       NULL,   4,  GPR_OFFSET(1),      eEncodingUint,  eFormatHex,     { ehframe_r1,               dwarf_r1,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r1      },      NULL,              NULL},
189 {   "r2",       NULL,   4,  GPR_OFFSET(2),      eEncodingUint,  eFormatHex,     { ehframe_r2,               dwarf_r2,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r2      },      NULL,              NULL},
190 {   "r3",       NULL,   4,  GPR_OFFSET(3),      eEncodingUint,  eFormatHex,     { ehframe_r3,               dwarf_r3,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r3      },      NULL,              NULL},
191 {   "r4",       NULL,   4,  GPR_OFFSET(4),      eEncodingUint,  eFormatHex,     { ehframe_r4,               dwarf_r4,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r4      },      NULL,              NULL},
192 {   "r5",       NULL,   4,  GPR_OFFSET(5),      eEncodingUint,  eFormatHex,     { ehframe_r5,               dwarf_r5,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r5      },      NULL,              NULL},
193 {   "r6",       NULL,   4,  GPR_OFFSET(6),      eEncodingUint,  eFormatHex,     { ehframe_r6,               dwarf_r6,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r6      },      NULL,              NULL},
194 {   "r7",       NULL,   4,  GPR_OFFSET(7),      eEncodingUint,  eFormatHex,     { ehframe_r7,               dwarf_r7,           LLDB_REGNUM_GENERIC_FP,     LLDB_INVALID_REGNUM,    gpr_r7      },      NULL,              NULL},
195 {   "r8",       NULL,   4,  GPR_OFFSET(8),      eEncodingUint,  eFormatHex,     { ehframe_r8,               dwarf_r8,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r8      },      NULL,              NULL},
196 {   "r9",       NULL,   4,  GPR_OFFSET(9),      eEncodingUint,  eFormatHex,     { ehframe_r9,               dwarf_r9,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r9      },      NULL,              NULL},
197 {   "r10",      NULL,   4,  GPR_OFFSET(10),     eEncodingUint,  eFormatHex,     { ehframe_r10,              dwarf_r10,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r10     },      NULL,              NULL},
198 {   "r11",      NULL,   4,  GPR_OFFSET(11),     eEncodingUint,  eFormatHex,     { ehframe_r11,              dwarf_r11,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r11     },      NULL,              NULL},
199 {   "r12",      NULL,   4,  GPR_OFFSET(12),     eEncodingUint,  eFormatHex,     { ehframe_r12,              dwarf_r12,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r12     },      NULL,              NULL},
200 {   "sp",       "r13",  4,  GPR_OFFSET(13),     eEncodingUint,  eFormatHex,     { ehframe_sp,               dwarf_sp,           LLDB_REGNUM_GENERIC_SP,     LLDB_INVALID_REGNUM,    gpr_sp      },      NULL,              NULL},
201 {   "lr",       "r14",  4,  GPR_OFFSET(14),     eEncodingUint,  eFormatHex,     { ehframe_lr,               dwarf_lr,           LLDB_REGNUM_GENERIC_RA,     LLDB_INVALID_REGNUM,    gpr_lr      },      NULL,              NULL},
202 {   "pc",       "r15",  4,  GPR_OFFSET(15),     eEncodingUint,  eFormatHex,     { ehframe_pc,               dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     LLDB_INVALID_REGNUM,    gpr_pc      },      NULL,              NULL},
203 {   "cpsr",     "psr",  4,  GPR_OFFSET(16),     eEncodingUint,  eFormatHex,     { ehframe_cpsr,             dwarf_cpsr,         LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM,    gpr_cpsr    },      NULL,              NULL},
204 
205 {   "s0",       NULL,   4,  FPU_OFFSET(0),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s0,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s0      },      NULL,              NULL},
206 {   "s1",       NULL,   4,  FPU_OFFSET(1),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s1,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s1      },      NULL,              NULL},
207 {   "s2",       NULL,   4,  FPU_OFFSET(2),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s2,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s2      },      NULL,              NULL},
208 {   "s3",       NULL,   4,  FPU_OFFSET(3),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s3,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s3      },      NULL,              NULL},
209 {   "s4",       NULL,   4,  FPU_OFFSET(4),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s4,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s4      },      NULL,              NULL},
210 {   "s5",       NULL,   4,  FPU_OFFSET(5),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s5,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s5      },      NULL,              NULL},
211 {   "s6",       NULL,   4,  FPU_OFFSET(6),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s6,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s6      },      NULL,              NULL},
212 {   "s7",       NULL,   4,  FPU_OFFSET(7),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s7,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s7      },      NULL,              NULL},
213 {   "s8",       NULL,   4,  FPU_OFFSET(8),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s8,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s8      },      NULL,              NULL},
214 {   "s9",       NULL,   4,  FPU_OFFSET(9),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s9,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s9      },      NULL,              NULL},
215 {   "s10",      NULL,   4,  FPU_OFFSET(10),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s10,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s10     },      NULL,              NULL},
216 {   "s11",      NULL,   4,  FPU_OFFSET(11),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s11,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s11     },      NULL,              NULL},
217 {   "s12",      NULL,   4,  FPU_OFFSET(12),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s12,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s12     },      NULL,              NULL},
218 {   "s13",      NULL,   4,  FPU_OFFSET(13),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s13,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s13     },      NULL,              NULL},
219 {   "s14",      NULL,   4,  FPU_OFFSET(14),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s14,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s14     },      NULL,              NULL},
220 {   "s15",      NULL,   4,  FPU_OFFSET(15),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s15,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s15     },      NULL,              NULL},
221 {   "s16",      NULL,   4,  FPU_OFFSET(16),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s16,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s16     },      NULL,              NULL},
222 {   "s17",      NULL,   4,  FPU_OFFSET(17),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s17,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s17     },      NULL,              NULL},
223 {   "s18",      NULL,   4,  FPU_OFFSET(18),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s18,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s18     },      NULL,              NULL},
224 {   "s19",      NULL,   4,  FPU_OFFSET(19),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s19,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s19     },      NULL,              NULL},
225 {   "s20",      NULL,   4,  FPU_OFFSET(20),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s20,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s20     },      NULL,              NULL},
226 {   "s21",      NULL,   4,  FPU_OFFSET(21),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s21,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s21     },      NULL,              NULL},
227 {   "s22",      NULL,   4,  FPU_OFFSET(22),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s22,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s22     },      NULL,              NULL},
228 {   "s23",      NULL,   4,  FPU_OFFSET(23),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s23,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s23     },      NULL,              NULL},
229 {   "s24",      NULL,   4,  FPU_OFFSET(24),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s24,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s24     },      NULL,              NULL},
230 {   "s25",      NULL,   4,  FPU_OFFSET(25),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s25,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s25     },      NULL,              NULL},
231 {   "s26",      NULL,   4,  FPU_OFFSET(26),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s26,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s26     },      NULL,              NULL},
232 {   "s27",      NULL,   4,  FPU_OFFSET(27),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s27,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s27     },      NULL,              NULL},
233 {   "s28",      NULL,   4,  FPU_OFFSET(28),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s28,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s28     },      NULL,              NULL},
234 {   "s29",      NULL,   4,  FPU_OFFSET(29),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s29,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s29     },      NULL,              NULL},
235 {   "s30",      NULL,   4,  FPU_OFFSET(30),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s30,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s30     },      NULL,              NULL},
236 {   "s31",      NULL,   4,  FPU_OFFSET(31),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s31,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s31     },      NULL,              NULL},
237 {   "fpscr",    NULL,   4,  FPU_OFFSET(32),     eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_fpscr   },      NULL,              NULL},
238 
239 {   "exception",NULL,   4,  EXC_OFFSET(0),      eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_exception },    NULL,              NULL},
240 {   "fsr",      NULL,   4,  EXC_OFFSET(1),      eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_fsr       },    NULL,              NULL},
241 {   "far",      NULL,   4,  EXC_OFFSET(2),      eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_far       },    NULL,              NULL},
242 
243 {   DEFINE_DBG (bvr, 0) },
244 {   DEFINE_DBG (bvr, 1) },
245 {   DEFINE_DBG (bvr, 2) },
246 {   DEFINE_DBG (bvr, 3) },
247 {   DEFINE_DBG (bvr, 4) },
248 {   DEFINE_DBG (bvr, 5) },
249 {   DEFINE_DBG (bvr, 6) },
250 {   DEFINE_DBG (bvr, 7) },
251 {   DEFINE_DBG (bvr, 8) },
252 {   DEFINE_DBG (bvr, 9) },
253 {   DEFINE_DBG (bvr, 10) },
254 {   DEFINE_DBG (bvr, 11) },
255 {   DEFINE_DBG (bvr, 12) },
256 {   DEFINE_DBG (bvr, 13) },
257 {   DEFINE_DBG (bvr, 14) },
258 {   DEFINE_DBG (bvr, 15) },
259 
260 {   DEFINE_DBG (bcr, 0) },
261 {   DEFINE_DBG (bcr, 1) },
262 {   DEFINE_DBG (bcr, 2) },
263 {   DEFINE_DBG (bcr, 3) },
264 {   DEFINE_DBG (bcr, 4) },
265 {   DEFINE_DBG (bcr, 5) },
266 {   DEFINE_DBG (bcr, 6) },
267 {   DEFINE_DBG (bcr, 7) },
268 {   DEFINE_DBG (bcr, 8) },
269 {   DEFINE_DBG (bcr, 9) },
270 {   DEFINE_DBG (bcr, 10) },
271 {   DEFINE_DBG (bcr, 11) },
272 {   DEFINE_DBG (bcr, 12) },
273 {   DEFINE_DBG (bcr, 13) },
274 {   DEFINE_DBG (bcr, 14) },
275 {   DEFINE_DBG (bcr, 15) },
276 
277 {   DEFINE_DBG (wvr, 0) },
278 {   DEFINE_DBG (wvr, 1) },
279 {   DEFINE_DBG (wvr, 2) },
280 {   DEFINE_DBG (wvr, 3) },
281 {   DEFINE_DBG (wvr, 4) },
282 {   DEFINE_DBG (wvr, 5) },
283 {   DEFINE_DBG (wvr, 6) },
284 {   DEFINE_DBG (wvr, 7) },
285 {   DEFINE_DBG (wvr, 8) },
286 {   DEFINE_DBG (wvr, 9) },
287 {   DEFINE_DBG (wvr, 10) },
288 {   DEFINE_DBG (wvr, 11) },
289 {   DEFINE_DBG (wvr, 12) },
290 {   DEFINE_DBG (wvr, 13) },
291 {   DEFINE_DBG (wvr, 14) },
292 {   DEFINE_DBG (wvr, 15) },
293 
294 {   DEFINE_DBG (wcr, 0) },
295 {   DEFINE_DBG (wcr, 1) },
296 {   DEFINE_DBG (wcr, 2) },
297 {   DEFINE_DBG (wcr, 3) },
298 {   DEFINE_DBG (wcr, 4) },
299 {   DEFINE_DBG (wcr, 5) },
300 {   DEFINE_DBG (wcr, 6) },
301 {   DEFINE_DBG (wcr, 7) },
302 {   DEFINE_DBG (wcr, 8) },
303 {   DEFINE_DBG (wcr, 9) },
304 {   DEFINE_DBG (wcr, 10) },
305 {   DEFINE_DBG (wcr, 11) },
306 {   DEFINE_DBG (wcr, 12) },
307 {   DEFINE_DBG (wcr, 13) },
308 {   DEFINE_DBG (wcr, 14) },
309 {   DEFINE_DBG (wcr, 15) }
310 };
311 
312 // General purpose registers
313 static uint32_t
314 g_gpr_regnums[] =
315 {
316     gpr_r0,
317     gpr_r1,
318     gpr_r2,
319     gpr_r3,
320     gpr_r4,
321     gpr_r5,
322     gpr_r6,
323     gpr_r7,
324     gpr_r8,
325     gpr_r9,
326     gpr_r10,
327     gpr_r11,
328     gpr_r12,
329     gpr_sp,
330     gpr_lr,
331     gpr_pc,
332     gpr_cpsr
333 };
334 
335 // Floating point registers
336 static uint32_t
337 g_fpu_regnums[] =
338 {
339     fpu_s0,
340     fpu_s1,
341     fpu_s2,
342     fpu_s3,
343     fpu_s4,
344     fpu_s5,
345     fpu_s6,
346     fpu_s7,
347     fpu_s8,
348     fpu_s9,
349     fpu_s10,
350     fpu_s11,
351     fpu_s12,
352     fpu_s13,
353     fpu_s14,
354     fpu_s15,
355     fpu_s16,
356     fpu_s17,
357     fpu_s18,
358     fpu_s19,
359     fpu_s20,
360     fpu_s21,
361     fpu_s22,
362     fpu_s23,
363     fpu_s24,
364     fpu_s25,
365     fpu_s26,
366     fpu_s27,
367     fpu_s28,
368     fpu_s29,
369     fpu_s30,
370     fpu_s31,
371     fpu_fpscr,
372 };
373 
374 // Exception registers
375 
376 static uint32_t
377 g_exc_regnums[] =
378 {
379     exc_exception,
380     exc_fsr,
381     exc_far,
382 };
383 
384 static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
385 
386 RegisterContextDarwin_arm::RegisterContextDarwin_arm(Thread &thread, uint32_t concrete_frame_idx) :
387     RegisterContext(thread, concrete_frame_idx),
388     gpr(),
389     fpu(),
390     exc()
391 {
392     uint32_t i;
393     for (i=0; i<kNumErrors; i++)
394     {
395         gpr_errs[i] = -1;
396         fpu_errs[i] = -1;
397         exc_errs[i] = -1;
398     }
399 }
400 
401 RegisterContextDarwin_arm::~RegisterContextDarwin_arm()
402 {
403 }
404 
405 
406 void
407 RegisterContextDarwin_arm::InvalidateAllRegisters ()
408 {
409     InvalidateAllRegisterStates();
410 }
411 
412 
413 size_t
414 RegisterContextDarwin_arm::GetRegisterCount ()
415 {
416     assert(k_num_register_infos == k_num_registers);
417     return k_num_registers;
418 }
419 
420 const RegisterInfo *
421 RegisterContextDarwin_arm::GetRegisterInfoAtIndex (size_t reg)
422 {
423     assert(k_num_register_infos == k_num_registers);
424     if (reg < k_num_registers)
425         return &g_register_infos[reg];
426     return NULL;
427 }
428 
429 size_t
430 RegisterContextDarwin_arm::GetRegisterInfosCount ()
431 {
432     return k_num_register_infos;
433 }
434 
435 const RegisterInfo *
436 RegisterContextDarwin_arm::GetRegisterInfos ()
437 {
438     return g_register_infos;
439 }
440 
441 
442 // Number of registers in each register set
443 const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
444 const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
445 const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
446 
447 //----------------------------------------------------------------------
448 // Register set definitions. The first definitions at register set index
449 // of zero is for all registers, followed by other registers sets. The
450 // register information for the all register set need not be filled in.
451 //----------------------------------------------------------------------
452 static const RegisterSet g_reg_sets[] =
453 {
454     { "General Purpose Registers",  "gpr",  k_num_gpr_registers,    g_gpr_regnums,      },
455     { "Floating Point Registers",   "fpu",  k_num_fpu_registers,    g_fpu_regnums       },
456     { "Exception State Registers",  "exc",  k_num_exc_registers,    g_exc_regnums       }
457 };
458 
459 const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
460 
461 
462 size_t
463 RegisterContextDarwin_arm::GetRegisterSetCount ()
464 {
465     return k_num_regsets;
466 }
467 
468 const RegisterSet *
469 RegisterContextDarwin_arm::GetRegisterSet (size_t reg_set)
470 {
471     if (reg_set < k_num_regsets)
472         return &g_reg_sets[reg_set];
473     return NULL;
474 }
475 
476 
477 //----------------------------------------------------------------------
478 // Register information definitions for 32 bit i386.
479 //----------------------------------------------------------------------
480 int
481 RegisterContextDarwin_arm::GetSetForNativeRegNum (int reg)
482 {
483     if (reg < fpu_s0)
484         return GPRRegSet;
485     else if (reg < exc_exception)
486         return FPURegSet;
487     else if (reg < k_num_registers)
488         return EXCRegSet;
489     return -1;
490 }
491 
492 int
493 RegisterContextDarwin_arm::ReadGPR (bool force)
494 {
495     int set = GPRRegSet;
496     if (force || !RegisterSetIsCached(set))
497     {
498         SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
499     }
500     return GetError(GPRRegSet, Read);
501 }
502 
503 int
504 RegisterContextDarwin_arm::ReadFPU (bool force)
505 {
506     int set = FPURegSet;
507     if (force || !RegisterSetIsCached(set))
508     {
509         SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
510     }
511     return GetError(FPURegSet, Read);
512 }
513 
514 int
515 RegisterContextDarwin_arm::ReadEXC (bool force)
516 {
517     int set = EXCRegSet;
518     if (force || !RegisterSetIsCached(set))
519     {
520         SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
521     }
522     return GetError(EXCRegSet, Read);
523 }
524 
525 int
526 RegisterContextDarwin_arm::ReadDBG (bool force)
527 {
528     int set = DBGRegSet;
529     if (force || !RegisterSetIsCached(set))
530     {
531         SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg));
532     }
533     return GetError(DBGRegSet, Read);
534 }
535 
536 int
537 RegisterContextDarwin_arm::WriteGPR ()
538 {
539     int set = GPRRegSet;
540     if (!RegisterSetIsCached(set))
541     {
542         SetError (set, Write, -1);
543         return KERN_INVALID_ARGUMENT;
544     }
545     SetError (set, Write, DoWriteGPR(GetThreadID(), set, gpr));
546     SetError (set, Read, -1);
547     return GetError(GPRRegSet, Write);
548 }
549 
550 int
551 RegisterContextDarwin_arm::WriteFPU ()
552 {
553     int set = FPURegSet;
554     if (!RegisterSetIsCached(set))
555     {
556         SetError (set, Write, -1);
557         return KERN_INVALID_ARGUMENT;
558     }
559     SetError (set, Write, DoWriteFPU(GetThreadID(), set, fpu));
560     SetError (set, Read, -1);
561     return GetError(FPURegSet, Write);
562 }
563 
564 int
565 RegisterContextDarwin_arm::WriteEXC ()
566 {
567     int set = EXCRegSet;
568     if (!RegisterSetIsCached(set))
569     {
570         SetError (set, Write, -1);
571         return KERN_INVALID_ARGUMENT;
572     }
573     SetError (set, Write, DoWriteEXC(GetThreadID(), set, exc));
574     SetError (set, Read, -1);
575     return GetError(EXCRegSet, Write);
576 }
577 
578 int
579 RegisterContextDarwin_arm::WriteDBG ()
580 {
581     int set = DBGRegSet;
582     if (!RegisterSetIsCached(set))
583     {
584         SetError (set, Write, -1);
585         return KERN_INVALID_ARGUMENT;
586     }
587     SetError (set, Write, DoWriteDBG(GetThreadID(), set, dbg));
588     SetError (set, Read, -1);
589     return GetError(DBGRegSet, Write);
590 }
591 
592 
593 int
594 RegisterContextDarwin_arm::ReadRegisterSet (uint32_t set, bool force)
595 {
596     switch (set)
597     {
598     case GPRRegSet:    return ReadGPR(force);
599     case GPRAltRegSet: return ReadGPR(force);
600     case FPURegSet:    return ReadFPU(force);
601     case EXCRegSet:    return ReadEXC(force);
602     case DBGRegSet:    return ReadDBG(force);
603     default: break;
604     }
605     return KERN_INVALID_ARGUMENT;
606 }
607 
608 int
609 RegisterContextDarwin_arm::WriteRegisterSet (uint32_t set)
610 {
611     // Make sure we have a valid context to set.
612     if (RegisterSetIsCached(set))
613     {
614         switch (set)
615         {
616         case GPRRegSet:    return WriteGPR();
617         case GPRAltRegSet: return WriteGPR();
618         case FPURegSet:    return WriteFPU();
619         case EXCRegSet:    return WriteEXC();
620         case DBGRegSet:    return WriteDBG();
621         default: break;
622         }
623     }
624     return KERN_INVALID_ARGUMENT;
625 }
626 
627 void
628 RegisterContextDarwin_arm::LogDBGRegisters (Log *log, const DBG& dbg)
629 {
630     if (log)
631     {
632         for (uint32_t i=0; i<16; i++)
633             log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }",
634                 i, i, dbg.bvr[i], dbg.bcr[i],
635                 i, i, dbg.wvr[i], dbg.wcr[i]);
636     }
637 }
638 
639 
640 bool
641 RegisterContextDarwin_arm::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value)
642 {
643     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
644     int set = RegisterContextDarwin_arm::GetSetForNativeRegNum (reg);
645 
646     if (set == -1)
647         return false;
648 
649     if (ReadRegisterSet(set, false) != KERN_SUCCESS)
650         return false;
651 
652     switch (reg)
653     {
654     case gpr_r0:
655     case gpr_r1:
656     case gpr_r2:
657     case gpr_r3:
658     case gpr_r4:
659     case gpr_r5:
660     case gpr_r6:
661     case gpr_r7:
662     case gpr_r8:
663     case gpr_r9:
664     case gpr_r10:
665     case gpr_r11:
666     case gpr_r12:
667     case gpr_sp:
668     case gpr_lr:
669     case gpr_pc:
670     case gpr_cpsr:
671         value.SetUInt32 (gpr.r[reg - gpr_r0]);
672         break;
673 
674     case fpu_s0:
675     case fpu_s1:
676     case fpu_s2:
677     case fpu_s3:
678     case fpu_s4:
679     case fpu_s5:
680     case fpu_s6:
681     case fpu_s7:
682     case fpu_s8:
683     case fpu_s9:
684     case fpu_s10:
685     case fpu_s11:
686     case fpu_s12:
687     case fpu_s13:
688     case fpu_s14:
689     case fpu_s15:
690     case fpu_s16:
691     case fpu_s17:
692     case fpu_s18:
693     case fpu_s19:
694     case fpu_s20:
695     case fpu_s21:
696     case fpu_s22:
697     case fpu_s23:
698     case fpu_s24:
699     case fpu_s25:
700     case fpu_s26:
701     case fpu_s27:
702     case fpu_s28:
703     case fpu_s29:
704     case fpu_s30:
705     case fpu_s31:
706         value.SetUInt32 (fpu.floats.s[reg], RegisterValue::eTypeFloat);
707         break;
708 
709     case fpu_fpscr:
710         value.SetUInt32 (fpu.fpscr);
711         break;
712 
713     case exc_exception:
714         value.SetUInt32 (exc.exception);
715         break;
716     case exc_fsr:
717         value.SetUInt32 (exc.fsr);
718         break;
719     case exc_far:
720         value.SetUInt32 (exc.far);
721         break;
722 
723     default:
724         value.SetValueToInvalid();
725         return false;
726 
727     }
728     return true;
729 }
730 
731 
732 bool
733 RegisterContextDarwin_arm::WriteRegister (const RegisterInfo *reg_info,
734                                         const RegisterValue &value)
735 {
736     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
737     int set = GetSetForNativeRegNum (reg);
738 
739     if (set == -1)
740         return false;
741 
742     if (ReadRegisterSet(set, false) != KERN_SUCCESS)
743         return false;
744 
745     switch (reg)
746     {
747     case gpr_r0:
748     case gpr_r1:
749     case gpr_r2:
750     case gpr_r3:
751     case gpr_r4:
752     case gpr_r5:
753     case gpr_r6:
754     case gpr_r7:
755     case gpr_r8:
756     case gpr_r9:
757     case gpr_r10:
758     case gpr_r11:
759     case gpr_r12:
760     case gpr_sp:
761     case gpr_lr:
762     case gpr_pc:
763     case gpr_cpsr:
764             gpr.r[reg - gpr_r0] = value.GetAsUInt32();
765         break;
766 
767     case fpu_s0:
768     case fpu_s1:
769     case fpu_s2:
770     case fpu_s3:
771     case fpu_s4:
772     case fpu_s5:
773     case fpu_s6:
774     case fpu_s7:
775     case fpu_s8:
776     case fpu_s9:
777     case fpu_s10:
778     case fpu_s11:
779     case fpu_s12:
780     case fpu_s13:
781     case fpu_s14:
782     case fpu_s15:
783     case fpu_s16:
784     case fpu_s17:
785     case fpu_s18:
786     case fpu_s19:
787     case fpu_s20:
788     case fpu_s21:
789     case fpu_s22:
790     case fpu_s23:
791     case fpu_s24:
792     case fpu_s25:
793     case fpu_s26:
794     case fpu_s27:
795     case fpu_s28:
796     case fpu_s29:
797     case fpu_s30:
798     case fpu_s31:
799         fpu.floats.s[reg] = value.GetAsUInt32();
800         break;
801 
802     case fpu_fpscr:
803         fpu.fpscr = value.GetAsUInt32();
804         break;
805 
806     case exc_exception:
807         exc.exception = value.GetAsUInt32();
808         break;
809     case exc_fsr:
810         exc.fsr = value.GetAsUInt32();
811         break;
812     case exc_far:
813         exc.far = value.GetAsUInt32();
814         break;
815 
816     default:
817         return false;
818 
819     }
820     return WriteRegisterSet(set) == KERN_SUCCESS;
821 }
822 
823 bool
824 RegisterContextDarwin_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
825 {
826     data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
827     if (data_sp &&
828         ReadGPR (false) == KERN_SUCCESS &&
829         ReadFPU (false) == KERN_SUCCESS &&
830         ReadEXC (false) == KERN_SUCCESS)
831     {
832         uint8_t *dst = data_sp->GetBytes();
833         ::memcpy (dst, &gpr, sizeof(gpr));
834         dst += sizeof(gpr);
835 
836         ::memcpy (dst, &fpu, sizeof(fpu));
837         dst += sizeof(gpr);
838 
839         ::memcpy (dst, &exc, sizeof(exc));
840         return true;
841     }
842     return false;
843 }
844 
845 bool
846 RegisterContextDarwin_arm::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
847 {
848     if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
849     {
850         const uint8_t *src = data_sp->GetBytes();
851         ::memcpy (&gpr, src, sizeof(gpr));
852         src += sizeof(gpr);
853 
854         ::memcpy (&fpu, src, sizeof(fpu));
855         src += sizeof(gpr);
856 
857         ::memcpy (&exc, src, sizeof(exc));
858         uint32_t success_count = 0;
859         if (WriteGPR() == KERN_SUCCESS)
860             ++success_count;
861         if (WriteFPU() == KERN_SUCCESS)
862             ++success_count;
863         if (WriteEXC() == KERN_SUCCESS)
864             ++success_count;
865         return success_count == 3;
866     }
867     return false;
868 }
869 
870 uint32_t
871 RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t reg)
872 {
873     if (kind == eRegisterKindGeneric)
874     {
875         switch (reg)
876         {
877         case LLDB_REGNUM_GENERIC_PC: return gpr_pc;
878         case LLDB_REGNUM_GENERIC_SP: return gpr_sp;
879         case LLDB_REGNUM_GENERIC_FP: return gpr_r7;
880         case LLDB_REGNUM_GENERIC_RA: return gpr_lr;
881         case LLDB_REGNUM_GENERIC_FLAGS: return gpr_cpsr;
882         default:
883             break;
884         }
885     }
886     else if (kind == eRegisterKindDWARF)
887     {
888         switch (reg)
889         {
890         case dwarf_r0:  return gpr_r0;
891         case dwarf_r1:  return gpr_r1;
892         case dwarf_r2:  return gpr_r2;
893         case dwarf_r3:  return gpr_r3;
894         case dwarf_r4:  return gpr_r4;
895         case dwarf_r5:  return gpr_r5;
896         case dwarf_r6:  return gpr_r6;
897         case dwarf_r7:  return gpr_r7;
898         case dwarf_r8:  return gpr_r8;
899         case dwarf_r9:  return gpr_r9;
900         case dwarf_r10: return gpr_r10;
901         case dwarf_r11: return gpr_r11;
902         case dwarf_r12: return gpr_r12;
903         case dwarf_sp:  return gpr_sp;
904         case dwarf_lr:  return gpr_lr;
905         case dwarf_pc:  return gpr_pc;
906         case dwarf_spsr: return gpr_cpsr;
907 
908         case dwarf_s0:  return fpu_s0;
909         case dwarf_s1:  return fpu_s1;
910         case dwarf_s2:  return fpu_s2;
911         case dwarf_s3:  return fpu_s3;
912         case dwarf_s4:  return fpu_s4;
913         case dwarf_s5:  return fpu_s5;
914         case dwarf_s6:  return fpu_s6;
915         case dwarf_s7:  return fpu_s7;
916         case dwarf_s8:  return fpu_s8;
917         case dwarf_s9:  return fpu_s9;
918         case dwarf_s10: return fpu_s10;
919         case dwarf_s11: return fpu_s11;
920         case dwarf_s12: return fpu_s12;
921         case dwarf_s13: return fpu_s13;
922         case dwarf_s14: return fpu_s14;
923         case dwarf_s15: return fpu_s15;
924         case dwarf_s16: return fpu_s16;
925         case dwarf_s17: return fpu_s17;
926         case dwarf_s18: return fpu_s18;
927         case dwarf_s19: return fpu_s19;
928         case dwarf_s20: return fpu_s20;
929         case dwarf_s21: return fpu_s21;
930         case dwarf_s22: return fpu_s22;
931         case dwarf_s23: return fpu_s23;
932         case dwarf_s24: return fpu_s24;
933         case dwarf_s25: return fpu_s25;
934         case dwarf_s26: return fpu_s26;
935         case dwarf_s27: return fpu_s27;
936         case dwarf_s28: return fpu_s28;
937         case dwarf_s29: return fpu_s29;
938         case dwarf_s30: return fpu_s30;
939         case dwarf_s31: return fpu_s31;
940 
941         default:
942             break;
943         }
944     }
945     else if (kind == eRegisterKindEHFrame)
946     {
947         switch (reg)
948         {
949         case ehframe_r0:    return gpr_r0;
950         case ehframe_r1:    return gpr_r1;
951         case ehframe_r2:    return gpr_r2;
952         case ehframe_r3:    return gpr_r3;
953         case ehframe_r4:    return gpr_r4;
954         case ehframe_r5:    return gpr_r5;
955         case ehframe_r6:    return gpr_r6;
956         case ehframe_r7:    return gpr_r7;
957         case ehframe_r8:    return gpr_r8;
958         case ehframe_r9:    return gpr_r9;
959         case ehframe_r10:   return gpr_r10;
960         case ehframe_r11:   return gpr_r11;
961         case ehframe_r12:   return gpr_r12;
962         case ehframe_sp:    return gpr_sp;
963         case ehframe_lr:    return gpr_lr;
964         case ehframe_pc:    return gpr_pc;
965         case ehframe_cpsr:  return gpr_cpsr;
966         }
967     }
968     else if (kind == eRegisterKindLLDB)
969     {
970         return reg;
971     }
972     return LLDB_INVALID_REGNUM;
973 }
974 
975 
976 uint32_t
977 RegisterContextDarwin_arm::NumSupportedHardwareBreakpoints ()
978 {
979 #if defined (__arm__)
980     // Set the init value to something that will let us know that we need to
981     // autodetect how many breakpoints are supported dynamically...
982     static uint32_t g_num_supported_hw_breakpoints = UINT32_MAX;
983     if (g_num_supported_hw_breakpoints == UINT32_MAX)
984     {
985         // Set this to zero in case we can't tell if there are any HW breakpoints
986         g_num_supported_hw_breakpoints = 0;
987 
988         uint32_t register_DBGDIDR;
989 
990         asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR));
991         g_num_supported_hw_breakpoints = Bits32 (register_DBGDIDR, 27, 24);
992         // Zero is reserved for the BRP count, so don't increment it if it is zero
993         if (g_num_supported_hw_breakpoints > 0)
994             g_num_supported_hw_breakpoints++;
995 //        if (log) log->Printf ("DBGDIDR=0x%8.8x (number BRP pairs = %u)", register_DBGDIDR, g_num_supported_hw_breakpoints);
996 
997     }
998     return g_num_supported_hw_breakpoints;
999 #else
1000     // TODO: figure out remote case here!
1001     return 6;
1002 #endif
1003 }
1004 
1005 uint32_t
1006 RegisterContextDarwin_arm::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
1007 {
1008     // Make sure our address isn't bogus
1009     if (addr & 1)
1010         return LLDB_INVALID_INDEX32;
1011 
1012     int kret = ReadDBG (false);
1013 
1014     if (kret == KERN_SUCCESS)
1015     {
1016         const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints();
1017         uint32_t i;
1018         for (i=0; i<num_hw_breakpoints; ++i)
1019         {
1020             if ((dbg.bcr[i] & BCR_ENABLE) == 0)
1021                 break; // We found an available hw breakpoint slot (in i)
1022         }
1023 
1024         // See if we found an available hw breakpoint slot above
1025         if (i < num_hw_breakpoints)
1026         {
1027             // Make sure bits 1:0 are clear in our address
1028             dbg.bvr[i] = addr & ~((lldb::addr_t)3);
1029 
1030             if (size == 2 || addr & 2)
1031             {
1032                 uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1;
1033 
1034                 // We have a thumb breakpoint
1035                 // We have an ARM breakpoint
1036                 dbg.bcr[i] =  BCR_M_IMVA_MATCH |    // Stop on address mismatch
1037                                         byte_addr_select |  // Set the correct byte address select so we only trigger on the correct opcode
1038                                         S_USER |            // Which modes should this breakpoint stop in?
1039                                         BCR_ENABLE;         // Enable this hardware breakpoint
1040 //                if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (Thumb)",
1041 //                        addr,
1042 //                        size,
1043 //                        i,
1044 //                        i,
1045 //                        dbg.bvr[i],
1046 //                        dbg.bcr[i]);
1047             }
1048             else if (size == 4)
1049             {
1050                 // We have an ARM breakpoint
1051                 dbg.bcr[i] =  BCR_M_IMVA_MATCH |    // Stop on address mismatch
1052                                         BAS_IMVA_ALL |      // Stop on any of the four bytes following the IMVA
1053                                         S_USER |            // Which modes should this breakpoint stop in?
1054                                         BCR_ENABLE;         // Enable this hardware breakpoint
1055 //                if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (ARM)",
1056 //                        addr,
1057 //                        size,
1058 //                        i,
1059 //                        i,
1060 //                        dbg.bvr[i],
1061 //                        dbg.bcr[i]);
1062             }
1063 
1064             kret = WriteDBG();
1065 //            if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint() WriteDBG() => 0x%8.8x.", kret);
1066 
1067             if (kret == KERN_SUCCESS)
1068                 return i;
1069         }
1070 //        else
1071 //        {
1072 //            if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint(addr = %8.8p, size = %u) => all hardware breakpoint resources are being used.", addr, size);
1073 //        }
1074     }
1075 
1076     return LLDB_INVALID_INDEX32;
1077 }
1078 
1079 bool
1080 RegisterContextDarwin_arm::ClearHardwareBreakpoint (uint32_t hw_index)
1081 {
1082     int kret = ReadDBG (false);
1083 
1084     const uint32_t num_hw_points = NumSupportedHardwareBreakpoints();
1085     if (kret == KERN_SUCCESS)
1086     {
1087         if (hw_index < num_hw_points)
1088         {
1089             dbg.bcr[hw_index] = 0;
1090 //            if (log) log->Printf ("RegisterContextDarwin_arm::SetHardwareBreakpoint( %u ) - BVR%u = 0x%8.8x  BCR%u = 0x%8.8x",
1091 //                    hw_index,
1092 //                    hw_index,
1093 //                    dbg.bvr[hw_index],
1094 //                    hw_index,
1095 //                    dbg.bcr[hw_index]);
1096 
1097             kret = WriteDBG();
1098 
1099             if (kret == KERN_SUCCESS)
1100                 return true;
1101         }
1102     }
1103     return false;
1104 }
1105 
1106 uint32_t
1107 RegisterContextDarwin_arm::NumSupportedHardwareWatchpoints ()
1108 {
1109 #if defined (__arm__)
1110     // Set the init value to something that will let us know that we need to
1111     // autodetect how many watchpoints are supported dynamically...
1112     static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
1113     if (g_num_supported_hw_watchpoints == UINT32_MAX)
1114     {
1115         // Set this to zero in case we can't tell if there are any HW breakpoints
1116         g_num_supported_hw_watchpoints = 0;
1117 
1118         uint32_t register_DBGDIDR;
1119         asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR));
1120         g_num_supported_hw_watchpoints = Bits32 (register_DBGDIDR, 31, 28) + 1;
1121 //        if (log) log->Printf ("DBGDIDR=0x%8.8x (number WRP pairs = %u)", register_DBGDIDR, g_num_supported_hw_watchpoints);
1122     }
1123     return g_num_supported_hw_watchpoints;
1124 #else
1125     // TODO: figure out remote case here!
1126     return 2;
1127 #endif
1128 }
1129 
1130 
1131 uint32_t
1132 RegisterContextDarwin_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write)
1133 {
1134 //    if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint(addr = %8.8p, size = %u, read = %u, write = %u)", addr, size, read, write);
1135 
1136     const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
1137 
1138     // Can't watch zero bytes
1139     if (size == 0)
1140         return LLDB_INVALID_INDEX32;
1141 
1142     // We must watch for either read or write
1143     if (read == false && write == false)
1144         return LLDB_INVALID_INDEX32;
1145 
1146     // Can't watch more than 4 bytes per WVR/WCR pair
1147     if (size > 4)
1148         return LLDB_INVALID_INDEX32;
1149 
1150     // We can only watch up to four bytes that follow a 4 byte aligned address
1151     // per watchpoint register pair. Since we have at most so we can only watch
1152     // until the next 4 byte boundary and we need to make sure we can properly
1153     // encode this.
1154     uint32_t addr_word_offset = addr % 4;
1155 //    if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset);
1156 
1157     uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
1158 //    if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask);
1159     if (byte_mask > 0xfu)
1160         return LLDB_INVALID_INDEX32;
1161 
1162     // Read the debug state
1163     int kret = ReadDBG (false);
1164 
1165     if (kret == KERN_SUCCESS)
1166     {
1167         // Check to make sure we have the needed hardware support
1168         uint32_t i = 0;
1169 
1170         for (i=0; i<num_hw_watchpoints; ++i)
1171         {
1172             if ((dbg.wcr[i] & WCR_ENABLE) == 0)
1173                 break; // We found an available hw breakpoint slot (in i)
1174         }
1175 
1176         // See if we found an available hw breakpoint slot above
1177         if (i < num_hw_watchpoints)
1178         {
1179             // Make the byte_mask into a valid Byte Address Select mask
1180             uint32_t byte_address_select = byte_mask << 5;
1181             // Make sure bits 1:0 are clear in our address
1182             dbg.wvr[i] = addr & ~((lldb::addr_t)3);
1183             dbg.wcr[i] =  byte_address_select |       // Which bytes that follow the IMVA that we will watch
1184                                     S_USER |                    // Stop only in user mode
1185                                     (read ? WCR_LOAD : 0) |     // Stop on read access?
1186                                     (write ? WCR_STORE : 0) |   // Stop on write access?
1187                                     WCR_ENABLE;                 // Enable this watchpoint;
1188 
1189             kret = WriteDBG();
1190 //            if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() WriteDBG() => 0x%8.8x.", kret);
1191 
1192             if (kret == KERN_SUCCESS)
1193                 return i;
1194         }
1195         else
1196         {
1197 //            if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints);
1198         }
1199     }
1200     return LLDB_INVALID_INDEX32;
1201 }
1202 
1203 bool
1204 RegisterContextDarwin_arm::ClearHardwareWatchpoint (uint32_t hw_index)
1205 {
1206     int kret = ReadDBG (false);
1207 
1208     const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
1209     if (kret == KERN_SUCCESS)
1210     {
1211         if (hw_index < num_hw_points)
1212         {
1213             dbg.wcr[hw_index] = 0;
1214 //            if (log) log->Printf ("RegisterContextDarwin_arm::ClearHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x  WCR%u = 0x%8.8x",
1215 //                    hw_index,
1216 //                    hw_index,
1217 //                    dbg.wvr[hw_index],
1218 //                    hw_index,
1219 //                    dbg.wcr[hw_index]);
1220 
1221             kret = WriteDBG();
1222 
1223             if (kret == KERN_SUCCESS)
1224                 return true;
1225         }
1226     }
1227     return false;
1228 }
1229 
1230 #endif
1231