1 | //===-- RegisterContextDarwin_arm.cpp -------------------------------------===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "RegisterContextDarwin_arm.h" |
10 | #include "RegisterContextDarwinConstants.h" |
11 | |
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" |
19 | |
20 | #include "Plugins/Process/Utility/InstructionUtils.h" |
21 | |
22 | #include <memory> |
23 | |
24 | #include "Utility/ARM_DWARF_Registers.h" |
25 | #include "Utility/ARM_ehframe_Registers.h" |
26 | |
27 | #include "llvm/ADT/STLExtras.h" |
28 | |
29 | using namespace lldb; |
30 | using namespace lldb_private; |
31 | |
32 | enum { |
33 | gpr_r0 = 0, |
34 | gpr_r1, |
35 | gpr_r2, |
36 | gpr_r3, |
37 | gpr_r4, |
38 | gpr_r5, |
39 | gpr_r6, |
40 | gpr_r7, |
41 | gpr_r8, |
42 | gpr_r9, |
43 | gpr_r10, |
44 | gpr_r11, |
45 | gpr_r12, |
46 | gpr_r13, |
47 | gpr_sp = gpr_r13, |
48 | gpr_r14, |
49 | gpr_lr = gpr_r14, |
50 | gpr_r15, |
51 | gpr_pc = gpr_r15, |
52 | gpr_cpsr, |
53 | |
54 | fpu_s0, |
55 | fpu_s1, |
56 | fpu_s2, |
57 | fpu_s3, |
58 | fpu_s4, |
59 | fpu_s5, |
60 | fpu_s6, |
61 | fpu_s7, |
62 | fpu_s8, |
63 | fpu_s9, |
64 | fpu_s10, |
65 | fpu_s11, |
66 | fpu_s12, |
67 | fpu_s13, |
68 | fpu_s14, |
69 | fpu_s15, |
70 | fpu_s16, |
71 | fpu_s17, |
72 | fpu_s18, |
73 | fpu_s19, |
74 | fpu_s20, |
75 | fpu_s21, |
76 | fpu_s22, |
77 | fpu_s23, |
78 | fpu_s24, |
79 | fpu_s25, |
80 | fpu_s26, |
81 | fpu_s27, |
82 | fpu_s28, |
83 | fpu_s29, |
84 | fpu_s30, |
85 | fpu_s31, |
86 | fpu_fpscr, |
87 | |
88 | exc_exception, |
89 | exc_fsr, |
90 | exc_far, |
91 | |
92 | dbg_bvr0, |
93 | dbg_bvr1, |
94 | dbg_bvr2, |
95 | dbg_bvr3, |
96 | dbg_bvr4, |
97 | dbg_bvr5, |
98 | dbg_bvr6, |
99 | dbg_bvr7, |
100 | dbg_bvr8, |
101 | dbg_bvr9, |
102 | dbg_bvr10, |
103 | dbg_bvr11, |
104 | dbg_bvr12, |
105 | dbg_bvr13, |
106 | dbg_bvr14, |
107 | dbg_bvr15, |
108 | |
109 | dbg_bcr0, |
110 | dbg_bcr1, |
111 | dbg_bcr2, |
112 | dbg_bcr3, |
113 | dbg_bcr4, |
114 | dbg_bcr5, |
115 | dbg_bcr6, |
116 | dbg_bcr7, |
117 | dbg_bcr8, |
118 | dbg_bcr9, |
119 | dbg_bcr10, |
120 | dbg_bcr11, |
121 | dbg_bcr12, |
122 | dbg_bcr13, |
123 | dbg_bcr14, |
124 | dbg_bcr15, |
125 | |
126 | dbg_wvr0, |
127 | dbg_wvr1, |
128 | dbg_wvr2, |
129 | dbg_wvr3, |
130 | dbg_wvr4, |
131 | dbg_wvr5, |
132 | dbg_wvr6, |
133 | dbg_wvr7, |
134 | dbg_wvr8, |
135 | dbg_wvr9, |
136 | dbg_wvr10, |
137 | dbg_wvr11, |
138 | dbg_wvr12, |
139 | dbg_wvr13, |
140 | dbg_wvr14, |
141 | dbg_wvr15, |
142 | |
143 | dbg_wcr0, |
144 | dbg_wcr1, |
145 | dbg_wcr2, |
146 | dbg_wcr3, |
147 | dbg_wcr4, |
148 | dbg_wcr5, |
149 | dbg_wcr6, |
150 | dbg_wcr7, |
151 | dbg_wcr8, |
152 | dbg_wcr9, |
153 | dbg_wcr10, |
154 | dbg_wcr11, |
155 | dbg_wcr12, |
156 | dbg_wcr13, |
157 | dbg_wcr14, |
158 | dbg_wcr15, |
159 | |
160 | k_num_registers |
161 | }; |
162 | |
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))) |
173 | |
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)) |
185 | |
186 | static RegisterInfo g_register_infos[] = { |
187 | // General purpose registers |
188 | // NAME ALT SZ OFFSET ENCODING FORMAT |
189 | // EH_FRAME DWARF GENERIC |
190 | // PROCESS PLUGIN LLDB NATIVE |
191 | // ====== ======= == ============= ============= ============ |
192 | // =============== =============== ========================= |
193 | // ===================== ============= |
194 | {.name: "r0" , |
195 | .alt_name: nullptr, |
196 | .byte_size: 4, |
197 | GPR_OFFSET(0), |
198 | .encoding: eEncodingUint, |
199 | .format: eFormatHex, |
200 | .kinds: {ehframe_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r0}, |
201 | .value_regs: nullptr, |
202 | .invalidate_regs: nullptr, |
203 | .flags_type: nullptr, |
204 | }, |
205 | {.name: "r1" , |
206 | .alt_name: nullptr, |
207 | .byte_size: 4, |
208 | GPR_OFFSET(1), |
209 | .encoding: eEncodingUint, |
210 | .format: eFormatHex, |
211 | .kinds: {ehframe_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r1}, |
212 | .value_regs: nullptr, |
213 | .invalidate_regs: nullptr, |
214 | .flags_type: nullptr, |
215 | }, |
216 | {.name: "r2" , |
217 | .alt_name: nullptr, |
218 | .byte_size: 4, |
219 | GPR_OFFSET(2), |
220 | .encoding: eEncodingUint, |
221 | .format: eFormatHex, |
222 | .kinds: {ehframe_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r2}, |
223 | .value_regs: nullptr, |
224 | .invalidate_regs: nullptr, |
225 | .flags_type: nullptr, |
226 | }, |
227 | {.name: "r3" , |
228 | .alt_name: nullptr, |
229 | .byte_size: 4, |
230 | GPR_OFFSET(3), |
231 | .encoding: eEncodingUint, |
232 | .format: eFormatHex, |
233 | .kinds: {ehframe_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r3}, |
234 | .value_regs: nullptr, |
235 | .invalidate_regs: nullptr, |
236 | .flags_type: nullptr, |
237 | }, |
238 | {.name: "r4" , |
239 | .alt_name: nullptr, |
240 | .byte_size: 4, |
241 | GPR_OFFSET(4), |
242 | .encoding: eEncodingUint, |
243 | .format: eFormatHex, |
244 | .kinds: {ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r4}, |
245 | .value_regs: nullptr, |
246 | .invalidate_regs: nullptr, |
247 | .flags_type: nullptr, |
248 | }, |
249 | {.name: "r5" , |
250 | .alt_name: nullptr, |
251 | .byte_size: 4, |
252 | GPR_OFFSET(5), |
253 | .encoding: eEncodingUint, |
254 | .format: eFormatHex, |
255 | .kinds: {ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r5}, |
256 | .value_regs: nullptr, |
257 | .invalidate_regs: nullptr, |
258 | .flags_type: nullptr, |
259 | }, |
260 | {.name: "r6" , |
261 | .alt_name: nullptr, |
262 | .byte_size: 4, |
263 | GPR_OFFSET(6), |
264 | .encoding: eEncodingUint, |
265 | .format: eFormatHex, |
266 | .kinds: {ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r6}, |
267 | .value_regs: nullptr, |
268 | .invalidate_regs: nullptr, |
269 | .flags_type: nullptr, |
270 | }, |
271 | {.name: "r7" , |
272 | .alt_name: nullptr, |
273 | .byte_size: 4, |
274 | GPR_OFFSET(7), |
275 | .encoding: eEncodingUint, |
276 | .format: eFormatHex, |
277 | .kinds: {ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, |
278 | gpr_r7}, |
279 | .value_regs: nullptr, |
280 | .invalidate_regs: nullptr, |
281 | .flags_type: nullptr, |
282 | }, |
283 | {.name: "r8" , |
284 | .alt_name: nullptr, |
285 | .byte_size: 4, |
286 | GPR_OFFSET(8), |
287 | .encoding: eEncodingUint, |
288 | .format: eFormatHex, |
289 | .kinds: {ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r8}, |
290 | .value_regs: nullptr, |
291 | .invalidate_regs: nullptr, |
292 | .flags_type: nullptr, |
293 | }, |
294 | {.name: "r9" , |
295 | .alt_name: nullptr, |
296 | .byte_size: 4, |
297 | GPR_OFFSET(9), |
298 | .encoding: eEncodingUint, |
299 | .format: eFormatHex, |
300 | .kinds: {ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r9}, |
301 | .value_regs: nullptr, |
302 | .invalidate_regs: nullptr, |
303 | .flags_type: nullptr, |
304 | }, |
305 | {.name: "r10" , |
306 | .alt_name: nullptr, |
307 | .byte_size: 4, |
308 | GPR_OFFSET(10), |
309 | .encoding: eEncodingUint, |
310 | .format: eFormatHex, |
311 | .kinds: {ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
312 | gpr_r10}, |
313 | .value_regs: nullptr, |
314 | .invalidate_regs: nullptr, |
315 | .flags_type: nullptr, |
316 | }, |
317 | {.name: "r11" , |
318 | .alt_name: nullptr, |
319 | .byte_size: 4, |
320 | GPR_OFFSET(11), |
321 | .encoding: eEncodingUint, |
322 | .format: eFormatHex, |
323 | .kinds: {ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
324 | gpr_r11}, |
325 | .value_regs: nullptr, |
326 | .invalidate_regs: nullptr, |
327 | .flags_type: nullptr, |
328 | }, |
329 | {.name: "r12" , |
330 | .alt_name: nullptr, |
331 | .byte_size: 4, |
332 | GPR_OFFSET(12), |
333 | .encoding: eEncodingUint, |
334 | .format: eFormatHex, |
335 | .kinds: {ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
336 | gpr_r12}, |
337 | .value_regs: nullptr, |
338 | .invalidate_regs: nullptr, |
339 | .flags_type: nullptr, |
340 | }, |
341 | {.name: "sp" , |
342 | .alt_name: "r13" , |
343 | .byte_size: 4, |
344 | GPR_OFFSET(13), |
345 | .encoding: eEncodingUint, |
346 | .format: eFormatHex, |
347 | .kinds: {ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, |
348 | gpr_sp}, |
349 | .value_regs: nullptr, |
350 | .invalidate_regs: nullptr, |
351 | .flags_type: nullptr, |
352 | }, |
353 | {.name: "lr" , |
354 | .alt_name: "r14" , |
355 | .byte_size: 4, |
356 | GPR_OFFSET(14), |
357 | .encoding: eEncodingUint, |
358 | .format: eFormatHex, |
359 | .kinds: {ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, |
360 | gpr_lr}, |
361 | .value_regs: nullptr, |
362 | .invalidate_regs: nullptr, |
363 | .flags_type: nullptr, |
364 | }, |
365 | {.name: "pc" , |
366 | .alt_name: "r15" , |
367 | .byte_size: 4, |
368 | GPR_OFFSET(15), |
369 | .encoding: eEncodingUint, |
370 | .format: eFormatHex, |
371 | .kinds: {ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, |
372 | gpr_pc}, |
373 | .value_regs: nullptr, |
374 | .invalidate_regs: nullptr, |
375 | .flags_type: nullptr, |
376 | }, |
377 | {.name: "cpsr" , |
378 | .alt_name: "psr" , |
379 | .byte_size: 4, |
380 | GPR_OFFSET(16), |
381 | .encoding: eEncodingUint, |
382 | .format: eFormatHex, |
383 | .kinds: {ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, |
384 | gpr_cpsr}, |
385 | .value_regs: nullptr, |
386 | .invalidate_regs: nullptr, |
387 | .flags_type: nullptr, |
388 | }, |
389 | |
390 | {.name: "s0" , |
391 | .alt_name: nullptr, |
392 | .byte_size: 4, |
393 | FPU_OFFSET(0), |
394 | .encoding: eEncodingIEEE754, |
395 | .format: eFormatFloat, |
396 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
397 | fpu_s0}, |
398 | .value_regs: nullptr, |
399 | .invalidate_regs: nullptr, |
400 | .flags_type: nullptr, |
401 | }, |
402 | {.name: "s1" , |
403 | .alt_name: nullptr, |
404 | .byte_size: 4, |
405 | FPU_OFFSET(1), |
406 | .encoding: eEncodingIEEE754, |
407 | .format: eFormatFloat, |
408 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
409 | fpu_s1}, |
410 | .value_regs: nullptr, |
411 | .invalidate_regs: nullptr, |
412 | .flags_type: nullptr, |
413 | }, |
414 | {.name: "s2" , |
415 | .alt_name: nullptr, |
416 | .byte_size: 4, |
417 | FPU_OFFSET(2), |
418 | .encoding: eEncodingIEEE754, |
419 | .format: eFormatFloat, |
420 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
421 | fpu_s2}, |
422 | .value_regs: nullptr, |
423 | .invalidate_regs: nullptr, |
424 | .flags_type: nullptr, |
425 | }, |
426 | {.name: "s3" , |
427 | .alt_name: nullptr, |
428 | .byte_size: 4, |
429 | FPU_OFFSET(3), |
430 | .encoding: eEncodingIEEE754, |
431 | .format: eFormatFloat, |
432 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
433 | fpu_s3}, |
434 | .value_regs: nullptr, |
435 | .invalidate_regs: nullptr, |
436 | .flags_type: nullptr, |
437 | }, |
438 | {.name: "s4" , |
439 | .alt_name: nullptr, |
440 | .byte_size: 4, |
441 | FPU_OFFSET(4), |
442 | .encoding: eEncodingIEEE754, |
443 | .format: eFormatFloat, |
444 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
445 | fpu_s4}, |
446 | .value_regs: nullptr, |
447 | .invalidate_regs: nullptr, |
448 | .flags_type: nullptr, |
449 | }, |
450 | {.name: "s5" , |
451 | .alt_name: nullptr, |
452 | .byte_size: 4, |
453 | FPU_OFFSET(5), |
454 | .encoding: eEncodingIEEE754, |
455 | .format: eFormatFloat, |
456 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
457 | fpu_s5}, |
458 | .value_regs: nullptr, |
459 | .invalidate_regs: nullptr, |
460 | .flags_type: nullptr, |
461 | }, |
462 | {.name: "s6" , |
463 | .alt_name: nullptr, |
464 | .byte_size: 4, |
465 | FPU_OFFSET(6), |
466 | .encoding: eEncodingIEEE754, |
467 | .format: eFormatFloat, |
468 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
469 | fpu_s6}, |
470 | .value_regs: nullptr, |
471 | .invalidate_regs: nullptr, |
472 | .flags_type: nullptr, |
473 | }, |
474 | {.name: "s7" , |
475 | .alt_name: nullptr, |
476 | .byte_size: 4, |
477 | FPU_OFFSET(7), |
478 | .encoding: eEncodingIEEE754, |
479 | .format: eFormatFloat, |
480 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
481 | fpu_s7}, |
482 | .value_regs: nullptr, |
483 | .invalidate_regs: nullptr, |
484 | .flags_type: nullptr, |
485 | }, |
486 | {.name: "s8" , |
487 | .alt_name: nullptr, |
488 | .byte_size: 4, |
489 | FPU_OFFSET(8), |
490 | .encoding: eEncodingIEEE754, |
491 | .format: eFormatFloat, |
492 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
493 | fpu_s8}, |
494 | .value_regs: nullptr, |
495 | .invalidate_regs: nullptr, |
496 | .flags_type: nullptr, |
497 | }, |
498 | {.name: "s9" , |
499 | .alt_name: nullptr, |
500 | .byte_size: 4, |
501 | FPU_OFFSET(9), |
502 | .encoding: eEncodingIEEE754, |
503 | .format: eFormatFloat, |
504 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
505 | fpu_s9}, |
506 | .value_regs: nullptr, |
507 | .invalidate_regs: nullptr, |
508 | .flags_type: nullptr, |
509 | }, |
510 | {.name: "s10" , |
511 | .alt_name: nullptr, |
512 | .byte_size: 4, |
513 | FPU_OFFSET(10), |
514 | .encoding: eEncodingIEEE754, |
515 | .format: eFormatFloat, |
516 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
517 | fpu_s10}, |
518 | .value_regs: nullptr, |
519 | .invalidate_regs: nullptr, |
520 | .flags_type: nullptr, |
521 | }, |
522 | {.name: "s11" , |
523 | .alt_name: nullptr, |
524 | .byte_size: 4, |
525 | FPU_OFFSET(11), |
526 | .encoding: eEncodingIEEE754, |
527 | .format: eFormatFloat, |
528 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
529 | fpu_s11}, |
530 | .value_regs: nullptr, |
531 | .invalidate_regs: nullptr, |
532 | .flags_type: nullptr, |
533 | }, |
534 | {.name: "s12" , |
535 | .alt_name: nullptr, |
536 | .byte_size: 4, |
537 | FPU_OFFSET(12), |
538 | .encoding: eEncodingIEEE754, |
539 | .format: eFormatFloat, |
540 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
541 | fpu_s12}, |
542 | .value_regs: nullptr, |
543 | .invalidate_regs: nullptr, |
544 | .flags_type: nullptr, |
545 | }, |
546 | {.name: "s13" , |
547 | .alt_name: nullptr, |
548 | .byte_size: 4, |
549 | FPU_OFFSET(13), |
550 | .encoding: eEncodingIEEE754, |
551 | .format: eFormatFloat, |
552 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
553 | fpu_s13}, |
554 | .value_regs: nullptr, |
555 | .invalidate_regs: nullptr, |
556 | .flags_type: nullptr, |
557 | }, |
558 | {.name: "s14" , |
559 | .alt_name: nullptr, |
560 | .byte_size: 4, |
561 | FPU_OFFSET(14), |
562 | .encoding: eEncodingIEEE754, |
563 | .format: eFormatFloat, |
564 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
565 | fpu_s14}, |
566 | .value_regs: nullptr, |
567 | .invalidate_regs: nullptr, |
568 | .flags_type: nullptr, |
569 | }, |
570 | {.name: "s15" , |
571 | .alt_name: nullptr, |
572 | .byte_size: 4, |
573 | FPU_OFFSET(15), |
574 | .encoding: eEncodingIEEE754, |
575 | .format: eFormatFloat, |
576 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
577 | fpu_s15}, |
578 | .value_regs: nullptr, |
579 | .invalidate_regs: nullptr, |
580 | .flags_type: nullptr, |
581 | }, |
582 | {.name: "s16" , |
583 | .alt_name: nullptr, |
584 | .byte_size: 4, |
585 | FPU_OFFSET(16), |
586 | .encoding: eEncodingIEEE754, |
587 | .format: eFormatFloat, |
588 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
589 | fpu_s16}, |
590 | .value_regs: nullptr, |
591 | .invalidate_regs: nullptr, |
592 | .flags_type: nullptr, |
593 | }, |
594 | {.name: "s17" , |
595 | .alt_name: nullptr, |
596 | .byte_size: 4, |
597 | FPU_OFFSET(17), |
598 | .encoding: eEncodingIEEE754, |
599 | .format: eFormatFloat, |
600 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
601 | fpu_s17}, |
602 | .value_regs: nullptr, |
603 | .invalidate_regs: nullptr, |
604 | .flags_type: nullptr, |
605 | }, |
606 | {.name: "s18" , |
607 | .alt_name: nullptr, |
608 | .byte_size: 4, |
609 | FPU_OFFSET(18), |
610 | .encoding: eEncodingIEEE754, |
611 | .format: eFormatFloat, |
612 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
613 | fpu_s18}, |
614 | .value_regs: nullptr, |
615 | .invalidate_regs: nullptr, |
616 | .flags_type: nullptr, |
617 | }, |
618 | {.name: "s19" , |
619 | .alt_name: nullptr, |
620 | .byte_size: 4, |
621 | FPU_OFFSET(19), |
622 | .encoding: eEncodingIEEE754, |
623 | .format: eFormatFloat, |
624 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
625 | fpu_s19}, |
626 | .value_regs: nullptr, |
627 | .invalidate_regs: nullptr, |
628 | .flags_type: nullptr, |
629 | }, |
630 | {.name: "s20" , |
631 | .alt_name: nullptr, |
632 | .byte_size: 4, |
633 | FPU_OFFSET(20), |
634 | .encoding: eEncodingIEEE754, |
635 | .format: eFormatFloat, |
636 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
637 | fpu_s20}, |
638 | .value_regs: nullptr, |
639 | .invalidate_regs: nullptr, |
640 | .flags_type: nullptr, |
641 | }, |
642 | {.name: "s21" , |
643 | .alt_name: nullptr, |
644 | .byte_size: 4, |
645 | FPU_OFFSET(21), |
646 | .encoding: eEncodingIEEE754, |
647 | .format: eFormatFloat, |
648 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
649 | fpu_s21}, |
650 | .value_regs: nullptr, |
651 | .invalidate_regs: nullptr, |
652 | .flags_type: nullptr, |
653 | }, |
654 | {.name: "s22" , |
655 | .alt_name: nullptr, |
656 | .byte_size: 4, |
657 | FPU_OFFSET(22), |
658 | .encoding: eEncodingIEEE754, |
659 | .format: eFormatFloat, |
660 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
661 | fpu_s22}, |
662 | .value_regs: nullptr, |
663 | .invalidate_regs: nullptr, |
664 | .flags_type: nullptr, |
665 | }, |
666 | {.name: "s23" , |
667 | .alt_name: nullptr, |
668 | .byte_size: 4, |
669 | FPU_OFFSET(23), |
670 | .encoding: eEncodingIEEE754, |
671 | .format: eFormatFloat, |
672 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
673 | fpu_s23}, |
674 | .value_regs: nullptr, |
675 | .invalidate_regs: nullptr, |
676 | .flags_type: nullptr, |
677 | }, |
678 | {.name: "s24" , |
679 | .alt_name: nullptr, |
680 | .byte_size: 4, |
681 | FPU_OFFSET(24), |
682 | .encoding: eEncodingIEEE754, |
683 | .format: eFormatFloat, |
684 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
685 | fpu_s24}, |
686 | .value_regs: nullptr, |
687 | .invalidate_regs: nullptr, |
688 | .flags_type: nullptr, |
689 | }, |
690 | {.name: "s25" , |
691 | .alt_name: nullptr, |
692 | .byte_size: 4, |
693 | FPU_OFFSET(25), |
694 | .encoding: eEncodingIEEE754, |
695 | .format: eFormatFloat, |
696 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
697 | fpu_s25}, |
698 | .value_regs: nullptr, |
699 | .invalidate_regs: nullptr, |
700 | .flags_type: nullptr, |
701 | }, |
702 | {.name: "s26" , |
703 | .alt_name: nullptr, |
704 | .byte_size: 4, |
705 | FPU_OFFSET(26), |
706 | .encoding: eEncodingIEEE754, |
707 | .format: eFormatFloat, |
708 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
709 | fpu_s26}, |
710 | .value_regs: nullptr, |
711 | .invalidate_regs: nullptr, |
712 | .flags_type: nullptr, |
713 | }, |
714 | {.name: "s27" , |
715 | .alt_name: nullptr, |
716 | .byte_size: 4, |
717 | FPU_OFFSET(27), |
718 | .encoding: eEncodingIEEE754, |
719 | .format: eFormatFloat, |
720 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
721 | fpu_s27}, |
722 | .value_regs: nullptr, |
723 | .invalidate_regs: nullptr, |
724 | .flags_type: nullptr, |
725 | }, |
726 | {.name: "s28" , |
727 | .alt_name: nullptr, |
728 | .byte_size: 4, |
729 | FPU_OFFSET(28), |
730 | .encoding: eEncodingIEEE754, |
731 | .format: eFormatFloat, |
732 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
733 | fpu_s28}, |
734 | .value_regs: nullptr, |
735 | .invalidate_regs: nullptr, |
736 | .flags_type: nullptr, |
737 | }, |
738 | {.name: "s29" , |
739 | .alt_name: nullptr, |
740 | .byte_size: 4, |
741 | FPU_OFFSET(29), |
742 | .encoding: eEncodingIEEE754, |
743 | .format: eFormatFloat, |
744 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
745 | fpu_s29}, |
746 | .value_regs: nullptr, |
747 | .invalidate_regs: nullptr, |
748 | .flags_type: nullptr, |
749 | }, |
750 | {.name: "s30" , |
751 | .alt_name: nullptr, |
752 | .byte_size: 4, |
753 | FPU_OFFSET(30), |
754 | .encoding: eEncodingIEEE754, |
755 | .format: eFormatFloat, |
756 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
757 | fpu_s30}, |
758 | .value_regs: nullptr, |
759 | .invalidate_regs: nullptr, |
760 | .flags_type: nullptr, |
761 | }, |
762 | {.name: "s31" , |
763 | .alt_name: nullptr, |
764 | .byte_size: 4, |
765 | FPU_OFFSET(31), |
766 | .encoding: eEncodingIEEE754, |
767 | .format: eFormatFloat, |
768 | .kinds: {LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
769 | fpu_s31}, |
770 | .value_regs: nullptr, |
771 | .invalidate_regs: nullptr, |
772 | .flags_type: nullptr, |
773 | }, |
774 | {.name: "fpscr" , |
775 | .alt_name: nullptr, |
776 | .byte_size: 4, |
777 | FPU_OFFSET(32), |
778 | .encoding: eEncodingUint, |
779 | .format: eFormatHex, |
780 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
781 | LLDB_INVALID_REGNUM, fpu_fpscr}, |
782 | .value_regs: nullptr, |
783 | .invalidate_regs: nullptr, |
784 | .flags_type: nullptr, |
785 | }, |
786 | |
787 | {.name: "exception" , |
788 | .alt_name: nullptr, |
789 | .byte_size: 4, |
790 | EXC_OFFSET(0), |
791 | .encoding: eEncodingUint, |
792 | .format: eFormatHex, |
793 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
794 | LLDB_INVALID_REGNUM, exc_exception}, |
795 | .value_regs: nullptr, |
796 | .invalidate_regs: nullptr, |
797 | .flags_type: nullptr, |
798 | }, |
799 | {.name: "fsr" , |
800 | .alt_name: nullptr, |
801 | .byte_size: 4, |
802 | EXC_OFFSET(1), |
803 | .encoding: eEncodingUint, |
804 | .format: eFormatHex, |
805 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
806 | LLDB_INVALID_REGNUM, exc_fsr}, |
807 | .value_regs: nullptr, |
808 | .invalidate_regs: nullptr, |
809 | .flags_type: nullptr, |
810 | }, |
811 | {.name: "far" , |
812 | .alt_name: nullptr, |
813 | .byte_size: 4, |
814 | EXC_OFFSET(2), |
815 | .encoding: eEncodingUint, |
816 | .format: eFormatHex, |
817 | .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
818 | LLDB_INVALID_REGNUM, exc_far}, |
819 | .value_regs: nullptr, |
820 | .invalidate_regs: nullptr, |
821 | .flags_type: nullptr, |
822 | }, |
823 | |
824 | {DEFINE_DBG(bvr, 0)}, |
825 | {DEFINE_DBG(bvr, 1)}, |
826 | {DEFINE_DBG(bvr, 2)}, |
827 | {DEFINE_DBG(bvr, 3)}, |
828 | {DEFINE_DBG(bvr, 4)}, |
829 | {DEFINE_DBG(bvr, 5)}, |
830 | {DEFINE_DBG(bvr, 6)}, |
831 | {DEFINE_DBG(bvr, 7)}, |
832 | {DEFINE_DBG(bvr, 8)}, |
833 | {DEFINE_DBG(bvr, 9)}, |
834 | {DEFINE_DBG(bvr, 10)}, |
835 | {DEFINE_DBG(bvr, 11)}, |
836 | {DEFINE_DBG(bvr, 12)}, |
837 | {DEFINE_DBG(bvr, 13)}, |
838 | {DEFINE_DBG(bvr, 14)}, |
839 | {DEFINE_DBG(bvr, 15)}, |
840 | |
841 | {DEFINE_DBG(bcr, 0)}, |
842 | {DEFINE_DBG(bcr, 1)}, |
843 | {DEFINE_DBG(bcr, 2)}, |
844 | {DEFINE_DBG(bcr, 3)}, |
845 | {DEFINE_DBG(bcr, 4)}, |
846 | {DEFINE_DBG(bcr, 5)}, |
847 | {DEFINE_DBG(bcr, 6)}, |
848 | {DEFINE_DBG(bcr, 7)}, |
849 | {DEFINE_DBG(bcr, 8)}, |
850 | {DEFINE_DBG(bcr, 9)}, |
851 | {DEFINE_DBG(bcr, 10)}, |
852 | {DEFINE_DBG(bcr, 11)}, |
853 | {DEFINE_DBG(bcr, 12)}, |
854 | {DEFINE_DBG(bcr, 13)}, |
855 | {DEFINE_DBG(bcr, 14)}, |
856 | {DEFINE_DBG(bcr, 15)}, |
857 | |
858 | {DEFINE_DBG(wvr, 0)}, |
859 | {DEFINE_DBG(wvr, 1)}, |
860 | {DEFINE_DBG(wvr, 2)}, |
861 | {DEFINE_DBG(wvr, 3)}, |
862 | {DEFINE_DBG(wvr, 4)}, |
863 | {DEFINE_DBG(wvr, 5)}, |
864 | {DEFINE_DBG(wvr, 6)}, |
865 | {DEFINE_DBG(wvr, 7)}, |
866 | {DEFINE_DBG(wvr, 8)}, |
867 | {DEFINE_DBG(wvr, 9)}, |
868 | {DEFINE_DBG(wvr, 10)}, |
869 | {DEFINE_DBG(wvr, 11)}, |
870 | {DEFINE_DBG(wvr, 12)}, |
871 | {DEFINE_DBG(wvr, 13)}, |
872 | {DEFINE_DBG(wvr, 14)}, |
873 | {DEFINE_DBG(wvr, 15)}, |
874 | |
875 | {DEFINE_DBG(wcr, 0)}, |
876 | {DEFINE_DBG(wcr, 1)}, |
877 | {DEFINE_DBG(wcr, 2)}, |
878 | {DEFINE_DBG(wcr, 3)}, |
879 | {DEFINE_DBG(wcr, 4)}, |
880 | {DEFINE_DBG(wcr, 5)}, |
881 | {DEFINE_DBG(wcr, 6)}, |
882 | {DEFINE_DBG(wcr, 7)}, |
883 | {DEFINE_DBG(wcr, 8)}, |
884 | {DEFINE_DBG(wcr, 9)}, |
885 | {DEFINE_DBG(wcr, 10)}, |
886 | {DEFINE_DBG(wcr, 11)}, |
887 | {DEFINE_DBG(wcr, 12)}, |
888 | {DEFINE_DBG(wcr, 13)}, |
889 | {DEFINE_DBG(wcr, 14)}, |
890 | {DEFINE_DBG(wcr, 15)}}; |
891 | |
892 | // General purpose registers |
893 | static uint32_t g_gpr_regnums[] = { |
894 | gpr_r0, gpr_r1, gpr_r2, gpr_r3, gpr_r4, gpr_r5, gpr_r6, gpr_r7, gpr_r8, |
895 | gpr_r9, gpr_r10, gpr_r11, gpr_r12, gpr_sp, gpr_lr, gpr_pc, gpr_cpsr}; |
896 | |
897 | // Floating point registers |
898 | static uint32_t g_fpu_regnums[] = { |
899 | fpu_s0, fpu_s1, fpu_s2, fpu_s3, fpu_s4, fpu_s5, fpu_s6, |
900 | fpu_s7, fpu_s8, fpu_s9, fpu_s10, fpu_s11, fpu_s12, fpu_s13, |
901 | fpu_s14, fpu_s15, fpu_s16, fpu_s17, fpu_s18, fpu_s19, fpu_s20, |
902 | fpu_s21, fpu_s22, fpu_s23, fpu_s24, fpu_s25, fpu_s26, fpu_s27, |
903 | fpu_s28, fpu_s29, fpu_s30, fpu_s31, fpu_fpscr, |
904 | }; |
905 | |
906 | // Exception registers |
907 | |
908 | static uint32_t g_exc_regnums[] = { |
909 | exc_exception, exc_fsr, exc_far, |
910 | }; |
911 | |
912 | static size_t k_num_register_infos = std::size(g_register_infos); |
913 | |
914 | RegisterContextDarwin_arm::RegisterContextDarwin_arm( |
915 | Thread &thread, uint32_t concrete_frame_idx) |
916 | : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc() { |
917 | uint32_t i; |
918 | for (i = 0; i < kNumErrors; i++) { |
919 | gpr_errs[i] = -1; |
920 | fpu_errs[i] = -1; |
921 | exc_errs[i] = -1; |
922 | } |
923 | } |
924 | |
925 | RegisterContextDarwin_arm::~RegisterContextDarwin_arm() = default; |
926 | |
927 | void RegisterContextDarwin_arm::InvalidateAllRegisters() { |
928 | InvalidateAllRegisterStates(); |
929 | } |
930 | |
931 | size_t RegisterContextDarwin_arm::GetRegisterCount() { |
932 | assert(k_num_register_infos == k_num_registers); |
933 | return k_num_registers; |
934 | } |
935 | |
936 | const RegisterInfo * |
937 | RegisterContextDarwin_arm::GetRegisterInfoAtIndex(size_t reg) { |
938 | assert(k_num_register_infos == k_num_registers); |
939 | if (reg < k_num_registers) |
940 | return &g_register_infos[reg]; |
941 | return nullptr; |
942 | } |
943 | |
944 | size_t RegisterContextDarwin_arm::GetRegisterInfosCount() { |
945 | return k_num_register_infos; |
946 | } |
947 | |
948 | const RegisterInfo *RegisterContextDarwin_arm::GetRegisterInfos() { |
949 | return g_register_infos; |
950 | } |
951 | |
952 | // Number of registers in each register set |
953 | const size_t k_num_gpr_registers = std::size(g_gpr_regnums); |
954 | const size_t k_num_fpu_registers = std::size(g_fpu_regnums); |
955 | const size_t k_num_exc_registers = std::size(g_exc_regnums); |
956 | |
957 | // Register set definitions. The first definitions at register set index of |
958 | // zero is for all registers, followed by other registers sets. The register |
959 | // information for the all register set need not be filled in. |
960 | static const RegisterSet g_reg_sets[] = { |
961 | { |
962 | .name: "General Purpose Registers" , .short_name: "gpr" , .num_registers: k_num_gpr_registers, .registers: g_gpr_regnums, |
963 | }, |
964 | {.name: "Floating Point Registers" , .short_name: "fpu" , .num_registers: k_num_fpu_registers, .registers: g_fpu_regnums}, |
965 | {.name: "Exception State Registers" , .short_name: "exc" , .num_registers: k_num_exc_registers, .registers: g_exc_regnums}}; |
966 | |
967 | const size_t k_num_regsets = std::size(g_reg_sets); |
968 | |
969 | size_t RegisterContextDarwin_arm::GetRegisterSetCount() { |
970 | return k_num_regsets; |
971 | } |
972 | |
973 | const RegisterSet *RegisterContextDarwin_arm::GetRegisterSet(size_t reg_set) { |
974 | if (reg_set < k_num_regsets) |
975 | return &g_reg_sets[reg_set]; |
976 | return nullptr; |
977 | } |
978 | |
979 | // Register information definitions for 32 bit i386. |
980 | int RegisterContextDarwin_arm::GetSetForNativeRegNum(int reg) { |
981 | if (reg < fpu_s0) |
982 | return GPRRegSet; |
983 | else if (reg < exc_exception) |
984 | return FPURegSet; |
985 | else if (reg < k_num_registers) |
986 | return EXCRegSet; |
987 | return -1; |
988 | } |
989 | |
990 | int RegisterContextDarwin_arm::ReadGPR(bool force) { |
991 | int set = GPRRegSet; |
992 | if (force || !RegisterSetIsCached(set)) { |
993 | SetError(flavor: set, err_idx: Read, err: DoReadGPR(tid: GetThreadID(), flavor: set, gpr)); |
994 | } |
995 | return GetError(flavor: GPRRegSet, err_idx: Read); |
996 | } |
997 | |
998 | int RegisterContextDarwin_arm::ReadFPU(bool force) { |
999 | int set = FPURegSet; |
1000 | if (force || !RegisterSetIsCached(set)) { |
1001 | SetError(flavor: set, err_idx: Read, err: DoReadFPU(tid: GetThreadID(), flavor: set, fpu)); |
1002 | } |
1003 | return GetError(flavor: FPURegSet, err_idx: Read); |
1004 | } |
1005 | |
1006 | int RegisterContextDarwin_arm::ReadEXC(bool force) { |
1007 | int set = EXCRegSet; |
1008 | if (force || !RegisterSetIsCached(set)) { |
1009 | SetError(flavor: set, err_idx: Read, err: DoReadEXC(tid: GetThreadID(), flavor: set, exc)); |
1010 | } |
1011 | return GetError(flavor: EXCRegSet, err_idx: Read); |
1012 | } |
1013 | |
1014 | int RegisterContextDarwin_arm::ReadDBG(bool force) { |
1015 | int set = DBGRegSet; |
1016 | if (force || !RegisterSetIsCached(set)) { |
1017 | SetError(flavor: set, err_idx: Read, err: DoReadDBG(tid: GetThreadID(), flavor: set, dbg)); |
1018 | } |
1019 | return GetError(flavor: DBGRegSet, err_idx: Read); |
1020 | } |
1021 | |
1022 | int RegisterContextDarwin_arm::WriteGPR() { |
1023 | int set = GPRRegSet; |
1024 | if (!RegisterSetIsCached(set)) { |
1025 | SetError(flavor: set, err_idx: Write, err: -1); |
1026 | return KERN_INVALID_ARGUMENT; |
1027 | } |
1028 | SetError(flavor: set, err_idx: Write, err: DoWriteGPR(tid: GetThreadID(), flavor: set, gpr)); |
1029 | SetError(flavor: set, err_idx: Read, err: -1); |
1030 | return GetError(flavor: GPRRegSet, err_idx: Write); |
1031 | } |
1032 | |
1033 | int RegisterContextDarwin_arm::WriteFPU() { |
1034 | int set = FPURegSet; |
1035 | if (!RegisterSetIsCached(set)) { |
1036 | SetError(flavor: set, err_idx: Write, err: -1); |
1037 | return KERN_INVALID_ARGUMENT; |
1038 | } |
1039 | SetError(flavor: set, err_idx: Write, err: DoWriteFPU(tid: GetThreadID(), flavor: set, fpu)); |
1040 | SetError(flavor: set, err_idx: Read, err: -1); |
1041 | return GetError(flavor: FPURegSet, err_idx: Write); |
1042 | } |
1043 | |
1044 | int RegisterContextDarwin_arm::WriteEXC() { |
1045 | int set = EXCRegSet; |
1046 | if (!RegisterSetIsCached(set)) { |
1047 | SetError(flavor: set, err_idx: Write, err: -1); |
1048 | return KERN_INVALID_ARGUMENT; |
1049 | } |
1050 | SetError(flavor: set, err_idx: Write, err: DoWriteEXC(tid: GetThreadID(), flavor: set, exc)); |
1051 | SetError(flavor: set, err_idx: Read, err: -1); |
1052 | return GetError(flavor: EXCRegSet, err_idx: Write); |
1053 | } |
1054 | |
1055 | int RegisterContextDarwin_arm::WriteDBG() { |
1056 | int set = DBGRegSet; |
1057 | if (!RegisterSetIsCached(set)) { |
1058 | SetError(flavor: set, err_idx: Write, err: -1); |
1059 | return KERN_INVALID_ARGUMENT; |
1060 | } |
1061 | SetError(flavor: set, err_idx: Write, err: DoWriteDBG(tid: GetThreadID(), flavor: set, dbg)); |
1062 | SetError(flavor: set, err_idx: Read, err: -1); |
1063 | return GetError(flavor: DBGRegSet, err_idx: Write); |
1064 | } |
1065 | |
1066 | int RegisterContextDarwin_arm::ReadRegisterSet(uint32_t set, bool force) { |
1067 | switch (set) { |
1068 | case GPRRegSet: |
1069 | return ReadGPR(force); |
1070 | case GPRAltRegSet: |
1071 | return ReadGPR(force); |
1072 | case FPURegSet: |
1073 | return ReadFPU(force); |
1074 | case EXCRegSet: |
1075 | return ReadEXC(force); |
1076 | case DBGRegSet: |
1077 | return ReadDBG(force); |
1078 | default: |
1079 | break; |
1080 | } |
1081 | return KERN_INVALID_ARGUMENT; |
1082 | } |
1083 | |
1084 | int RegisterContextDarwin_arm::WriteRegisterSet(uint32_t set) { |
1085 | // Make sure we have a valid context to set. |
1086 | if (RegisterSetIsCached(set)) { |
1087 | switch (set) { |
1088 | case GPRRegSet: |
1089 | return WriteGPR(); |
1090 | case GPRAltRegSet: |
1091 | return WriteGPR(); |
1092 | case FPURegSet: |
1093 | return WriteFPU(); |
1094 | case EXCRegSet: |
1095 | return WriteEXC(); |
1096 | case DBGRegSet: |
1097 | return WriteDBG(); |
1098 | default: |
1099 | break; |
1100 | } |
1101 | } |
1102 | return KERN_INVALID_ARGUMENT; |
1103 | } |
1104 | |
1105 | void RegisterContextDarwin_arm::LogDBGRegisters(Log *log, const DBG &dbg) { |
1106 | if (log) { |
1107 | for (uint32_t i = 0; i < 16; i++) |
1108 | LLDB_LOGF(log, |
1109 | "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { " |
1110 | "0x%8.8x, 0x%8.8x }" , |
1111 | i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]); |
1112 | } |
1113 | } |
1114 | |
1115 | bool RegisterContextDarwin_arm::ReadRegister(const RegisterInfo *reg_info, |
1116 | RegisterValue &value) { |
1117 | const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; |
1118 | int set = RegisterContextDarwin_arm::GetSetForNativeRegNum(reg); |
1119 | |
1120 | if (set == -1) |
1121 | return false; |
1122 | |
1123 | if (ReadRegisterSet(set, force: false) != KERN_SUCCESS) |
1124 | return false; |
1125 | |
1126 | switch (reg) { |
1127 | case gpr_r0: |
1128 | case gpr_r1: |
1129 | case gpr_r2: |
1130 | case gpr_r3: |
1131 | case gpr_r4: |
1132 | case gpr_r5: |
1133 | case gpr_r6: |
1134 | case gpr_r7: |
1135 | case gpr_r8: |
1136 | case gpr_r9: |
1137 | case gpr_r10: |
1138 | case gpr_r11: |
1139 | case gpr_r12: |
1140 | case gpr_sp: |
1141 | case gpr_lr: |
1142 | case gpr_pc: |
1143 | value.SetUInt32(uint: gpr.r[reg - gpr_r0]); |
1144 | break; |
1145 | case gpr_cpsr: |
1146 | value.SetUInt32(uint: gpr.cpsr); |
1147 | break; |
1148 | case fpu_s0: |
1149 | case fpu_s1: |
1150 | case fpu_s2: |
1151 | case fpu_s3: |
1152 | case fpu_s4: |
1153 | case fpu_s5: |
1154 | case fpu_s6: |
1155 | case fpu_s7: |
1156 | case fpu_s8: |
1157 | case fpu_s9: |
1158 | case fpu_s10: |
1159 | case fpu_s11: |
1160 | case fpu_s12: |
1161 | case fpu_s13: |
1162 | case fpu_s14: |
1163 | case fpu_s15: |
1164 | case fpu_s16: |
1165 | case fpu_s17: |
1166 | case fpu_s18: |
1167 | case fpu_s19: |
1168 | case fpu_s20: |
1169 | case fpu_s21: |
1170 | case fpu_s22: |
1171 | case fpu_s23: |
1172 | case fpu_s24: |
1173 | case fpu_s25: |
1174 | case fpu_s26: |
1175 | case fpu_s27: |
1176 | case fpu_s28: |
1177 | case fpu_s29: |
1178 | case fpu_s30: |
1179 | case fpu_s31: |
1180 | value.SetUInt32(uint: fpu.floats.s[reg], t: RegisterValue::eTypeFloat); |
1181 | break; |
1182 | |
1183 | case fpu_fpscr: |
1184 | value.SetUInt32(uint: fpu.fpscr); |
1185 | break; |
1186 | |
1187 | case exc_exception: |
1188 | value.SetUInt32(uint: exc.exception); |
1189 | break; |
1190 | case exc_fsr: |
1191 | value.SetUInt32(uint: exc.fsr); |
1192 | break; |
1193 | case exc_far: |
1194 | value.SetUInt32(uint: exc.far); |
1195 | break; |
1196 | |
1197 | default: |
1198 | value.SetValueToInvalid(); |
1199 | return false; |
1200 | } |
1201 | return true; |
1202 | } |
1203 | |
1204 | bool RegisterContextDarwin_arm::WriteRegister(const RegisterInfo *reg_info, |
1205 | const RegisterValue &value) { |
1206 | const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; |
1207 | int set = GetSetForNativeRegNum(reg); |
1208 | |
1209 | if (set == -1) |
1210 | return false; |
1211 | |
1212 | if (ReadRegisterSet(set, force: false) != KERN_SUCCESS) |
1213 | return false; |
1214 | |
1215 | switch (reg) { |
1216 | case gpr_r0: |
1217 | case gpr_r1: |
1218 | case gpr_r2: |
1219 | case gpr_r3: |
1220 | case gpr_r4: |
1221 | case gpr_r5: |
1222 | case gpr_r6: |
1223 | case gpr_r7: |
1224 | case gpr_r8: |
1225 | case gpr_r9: |
1226 | case gpr_r10: |
1227 | case gpr_r11: |
1228 | case gpr_r12: |
1229 | case gpr_sp: |
1230 | case gpr_lr: |
1231 | case gpr_pc: |
1232 | case gpr_cpsr: |
1233 | gpr.r[reg - gpr_r0] = value.GetAsUInt32(); |
1234 | break; |
1235 | |
1236 | case fpu_s0: |
1237 | case fpu_s1: |
1238 | case fpu_s2: |
1239 | case fpu_s3: |
1240 | case fpu_s4: |
1241 | case fpu_s5: |
1242 | case fpu_s6: |
1243 | case fpu_s7: |
1244 | case fpu_s8: |
1245 | case fpu_s9: |
1246 | case fpu_s10: |
1247 | case fpu_s11: |
1248 | case fpu_s12: |
1249 | case fpu_s13: |
1250 | case fpu_s14: |
1251 | case fpu_s15: |
1252 | case fpu_s16: |
1253 | case fpu_s17: |
1254 | case fpu_s18: |
1255 | case fpu_s19: |
1256 | case fpu_s20: |
1257 | case fpu_s21: |
1258 | case fpu_s22: |
1259 | case fpu_s23: |
1260 | case fpu_s24: |
1261 | case fpu_s25: |
1262 | case fpu_s26: |
1263 | case fpu_s27: |
1264 | case fpu_s28: |
1265 | case fpu_s29: |
1266 | case fpu_s30: |
1267 | case fpu_s31: |
1268 | fpu.floats.s[reg] = value.GetAsUInt32(); |
1269 | break; |
1270 | |
1271 | case fpu_fpscr: |
1272 | fpu.fpscr = value.GetAsUInt32(); |
1273 | break; |
1274 | |
1275 | case exc_exception: |
1276 | exc.exception = value.GetAsUInt32(); |
1277 | break; |
1278 | case exc_fsr: |
1279 | exc.fsr = value.GetAsUInt32(); |
1280 | break; |
1281 | case exc_far: |
1282 | exc.far = value.GetAsUInt32(); |
1283 | break; |
1284 | |
1285 | default: |
1286 | return false; |
1287 | } |
1288 | return WriteRegisterSet(set) == KERN_SUCCESS; |
1289 | } |
1290 | |
1291 | bool RegisterContextDarwin_arm::ReadAllRegisterValues( |
1292 | lldb::WritableDataBufferSP &data_sp) { |
1293 | data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, args: 0); |
1294 | if (data_sp && ReadGPR(force: false) == KERN_SUCCESS && |
1295 | ReadFPU(force: false) == KERN_SUCCESS && ReadEXC(force: false) == KERN_SUCCESS) { |
1296 | uint8_t *dst = data_sp->GetBytes(); |
1297 | ::memcpy(dest: dst, src: &gpr, n: sizeof(gpr)); |
1298 | dst += sizeof(gpr); |
1299 | |
1300 | ::memcpy(dest: dst, src: &fpu, n: sizeof(fpu)); |
1301 | dst += sizeof(gpr); |
1302 | |
1303 | ::memcpy(dest: dst, src: &exc, n: sizeof(exc)); |
1304 | return true; |
1305 | } |
1306 | return false; |
1307 | } |
1308 | |
1309 | bool RegisterContextDarwin_arm::WriteAllRegisterValues( |
1310 | const lldb::DataBufferSP &data_sp) { |
1311 | if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) { |
1312 | const uint8_t *src = data_sp->GetBytes(); |
1313 | ::memcpy(dest: &gpr, src: src, n: sizeof(gpr)); |
1314 | src += sizeof(gpr); |
1315 | |
1316 | ::memcpy(dest: &fpu, src: src, n: sizeof(fpu)); |
1317 | src += sizeof(gpr); |
1318 | |
1319 | ::memcpy(dest: &exc, src: src, n: sizeof(exc)); |
1320 | uint32_t success_count = 0; |
1321 | if (WriteGPR() == KERN_SUCCESS) |
1322 | ++success_count; |
1323 | if (WriteFPU() == KERN_SUCCESS) |
1324 | ++success_count; |
1325 | if (WriteEXC() == KERN_SUCCESS) |
1326 | ++success_count; |
1327 | return success_count == 3; |
1328 | } |
1329 | return false; |
1330 | } |
1331 | |
1332 | uint32_t RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber( |
1333 | lldb::RegisterKind kind, uint32_t reg) { |
1334 | if (kind == eRegisterKindGeneric) { |
1335 | switch (reg) { |
1336 | case LLDB_REGNUM_GENERIC_PC: |
1337 | return gpr_pc; |
1338 | case LLDB_REGNUM_GENERIC_SP: |
1339 | return gpr_sp; |
1340 | case LLDB_REGNUM_GENERIC_FP: |
1341 | return gpr_r7; |
1342 | case LLDB_REGNUM_GENERIC_RA: |
1343 | return gpr_lr; |
1344 | case LLDB_REGNUM_GENERIC_FLAGS: |
1345 | return gpr_cpsr; |
1346 | default: |
1347 | break; |
1348 | } |
1349 | } else if (kind == eRegisterKindDWARF) { |
1350 | switch (reg) { |
1351 | case dwarf_r0: |
1352 | return gpr_r0; |
1353 | case dwarf_r1: |
1354 | return gpr_r1; |
1355 | case dwarf_r2: |
1356 | return gpr_r2; |
1357 | case dwarf_r3: |
1358 | return gpr_r3; |
1359 | case dwarf_r4: |
1360 | return gpr_r4; |
1361 | case dwarf_r5: |
1362 | return gpr_r5; |
1363 | case dwarf_r6: |
1364 | return gpr_r6; |
1365 | case dwarf_r7: |
1366 | return gpr_r7; |
1367 | case dwarf_r8: |
1368 | return gpr_r8; |
1369 | case dwarf_r9: |
1370 | return gpr_r9; |
1371 | case dwarf_r10: |
1372 | return gpr_r10; |
1373 | case dwarf_r11: |
1374 | return gpr_r11; |
1375 | case dwarf_r12: |
1376 | return gpr_r12; |
1377 | case dwarf_sp: |
1378 | return gpr_sp; |
1379 | case dwarf_lr: |
1380 | return gpr_lr; |
1381 | case dwarf_pc: |
1382 | return gpr_pc; |
1383 | case dwarf_spsr: |
1384 | return gpr_cpsr; |
1385 | |
1386 | case dwarf_s0: |
1387 | return fpu_s0; |
1388 | case dwarf_s1: |
1389 | return fpu_s1; |
1390 | case dwarf_s2: |
1391 | return fpu_s2; |
1392 | case dwarf_s3: |
1393 | return fpu_s3; |
1394 | case dwarf_s4: |
1395 | return fpu_s4; |
1396 | case dwarf_s5: |
1397 | return fpu_s5; |
1398 | case dwarf_s6: |
1399 | return fpu_s6; |
1400 | case dwarf_s7: |
1401 | return fpu_s7; |
1402 | case dwarf_s8: |
1403 | return fpu_s8; |
1404 | case dwarf_s9: |
1405 | return fpu_s9; |
1406 | case dwarf_s10: |
1407 | return fpu_s10; |
1408 | case dwarf_s11: |
1409 | return fpu_s11; |
1410 | case dwarf_s12: |
1411 | return fpu_s12; |
1412 | case dwarf_s13: |
1413 | return fpu_s13; |
1414 | case dwarf_s14: |
1415 | return fpu_s14; |
1416 | case dwarf_s15: |
1417 | return fpu_s15; |
1418 | case dwarf_s16: |
1419 | return fpu_s16; |
1420 | case dwarf_s17: |
1421 | return fpu_s17; |
1422 | case dwarf_s18: |
1423 | return fpu_s18; |
1424 | case dwarf_s19: |
1425 | return fpu_s19; |
1426 | case dwarf_s20: |
1427 | return fpu_s20; |
1428 | case dwarf_s21: |
1429 | return fpu_s21; |
1430 | case dwarf_s22: |
1431 | return fpu_s22; |
1432 | case dwarf_s23: |
1433 | return fpu_s23; |
1434 | case dwarf_s24: |
1435 | return fpu_s24; |
1436 | case dwarf_s25: |
1437 | return fpu_s25; |
1438 | case dwarf_s26: |
1439 | return fpu_s26; |
1440 | case dwarf_s27: |
1441 | return fpu_s27; |
1442 | case dwarf_s28: |
1443 | return fpu_s28; |
1444 | case dwarf_s29: |
1445 | return fpu_s29; |
1446 | case dwarf_s30: |
1447 | return fpu_s30; |
1448 | case dwarf_s31: |
1449 | return fpu_s31; |
1450 | |
1451 | default: |
1452 | break; |
1453 | } |
1454 | } else if (kind == eRegisterKindEHFrame) { |
1455 | switch (reg) { |
1456 | case ehframe_r0: |
1457 | return gpr_r0; |
1458 | case ehframe_r1: |
1459 | return gpr_r1; |
1460 | case ehframe_r2: |
1461 | return gpr_r2; |
1462 | case ehframe_r3: |
1463 | return gpr_r3; |
1464 | case ehframe_r4: |
1465 | return gpr_r4; |
1466 | case ehframe_r5: |
1467 | return gpr_r5; |
1468 | case ehframe_r6: |
1469 | return gpr_r6; |
1470 | case ehframe_r7: |
1471 | return gpr_r7; |
1472 | case ehframe_r8: |
1473 | return gpr_r8; |
1474 | case ehframe_r9: |
1475 | return gpr_r9; |
1476 | case ehframe_r10: |
1477 | return gpr_r10; |
1478 | case ehframe_r11: |
1479 | return gpr_r11; |
1480 | case ehframe_r12: |
1481 | return gpr_r12; |
1482 | case ehframe_sp: |
1483 | return gpr_sp; |
1484 | case ehframe_lr: |
1485 | return gpr_lr; |
1486 | case ehframe_pc: |
1487 | return gpr_pc; |
1488 | case ehframe_cpsr: |
1489 | return gpr_cpsr; |
1490 | } |
1491 | } else if (kind == eRegisterKindLLDB) { |
1492 | return reg; |
1493 | } |
1494 | return LLDB_INVALID_REGNUM; |
1495 | } |
1496 | |
1497 | uint32_t RegisterContextDarwin_arm::NumSupportedHardwareBreakpoints() { |
1498 | #if defined(__APPLE__) && defined(__arm__) |
1499 | // Set the init value to something that will let us know that we need to |
1500 | // autodetect how many breakpoints are supported dynamically... |
1501 | static uint32_t g_num_supported_hw_breakpoints = UINT32_MAX; |
1502 | if (g_num_supported_hw_breakpoints == UINT32_MAX) { |
1503 | // Set this to zero in case we can't tell if there are any HW breakpoints |
1504 | g_num_supported_hw_breakpoints = 0; |
1505 | |
1506 | uint32_t register_DBGDIDR; |
1507 | |
1508 | asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); |
1509 | g_num_supported_hw_breakpoints = Bits32(register_DBGDIDR, 27, 24); |
1510 | // Zero is reserved for the BRP count, so don't increment it if it is zero |
1511 | if (g_num_supported_hw_breakpoints > 0) |
1512 | g_num_supported_hw_breakpoints++; |
1513 | } |
1514 | return g_num_supported_hw_breakpoints; |
1515 | #else |
1516 | // TODO: figure out remote case here! |
1517 | return 6; |
1518 | #endif |
1519 | } |
1520 | |
1521 | uint32_t RegisterContextDarwin_arm::SetHardwareBreakpoint(lldb::addr_t addr, |
1522 | size_t size) { |
1523 | // Make sure our address isn't bogus |
1524 | if (addr & 1) |
1525 | return LLDB_INVALID_INDEX32; |
1526 | |
1527 | int kret = ReadDBG(force: false); |
1528 | |
1529 | if (kret == KERN_SUCCESS) { |
1530 | const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints(); |
1531 | uint32_t i; |
1532 | for (i = 0; i < num_hw_breakpoints; ++i) { |
1533 | if ((dbg.bcr[i] & BCR_ENABLE) == 0) |
1534 | break; // We found an available hw breakpoint slot (in i) |
1535 | } |
1536 | |
1537 | // See if we found an available hw breakpoint slot above |
1538 | if (i < num_hw_breakpoints) { |
1539 | // Make sure bits 1:0 are clear in our address |
1540 | dbg.bvr[i] = addr & ~((lldb::addr_t)3); |
1541 | |
1542 | if (size == 2 || addr & 2) { |
1543 | uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1; |
1544 | |
1545 | // We have a thumb breakpoint |
1546 | // We have an ARM breakpoint |
1547 | dbg.bcr[i] = BCR_M_IMVA_MATCH | // Stop on address match |
1548 | byte_addr_select | // Set the correct byte address select |
1549 | // so we only trigger on the correct |
1550 | // opcode |
1551 | S_USER | // Which modes should this breakpoint stop in? |
1552 | BCR_ENABLE; // Enable this hardware breakpoint |
1553 | // if (log) log->Printf |
1554 | // ("RegisterContextDarwin_arm::EnableHardwareBreakpoint( |
1555 | // addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / |
1556 | // 0x%8.8x (Thumb)", |
1557 | // addr, |
1558 | // size, |
1559 | // i, |
1560 | // i, |
1561 | // dbg.bvr[i], |
1562 | // dbg.bcr[i]); |
1563 | } else if (size == 4) { |
1564 | // We have an ARM breakpoint |
1565 | dbg.bcr[i] = |
1566 | BCR_M_IMVA_MATCH | // Stop on address match |
1567 | BAS_IMVA_ALL | // Stop on any of the four bytes following the IMVA |
1568 | S_USER | // Which modes should this breakpoint stop in? |
1569 | BCR_ENABLE; // Enable this hardware breakpoint |
1570 | // if (log) log->Printf |
1571 | // ("RegisterContextDarwin_arm::EnableHardwareBreakpoint( |
1572 | // addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / |
1573 | // 0x%8.8x (ARM)", |
1574 | // addr, |
1575 | // size, |
1576 | // i, |
1577 | // i, |
1578 | // dbg.bvr[i], |
1579 | // dbg.bcr[i]); |
1580 | } |
1581 | |
1582 | kret = WriteDBG(); |
1583 | // if (log) log->Printf |
1584 | // ("RegisterContextDarwin_arm::EnableHardwareBreakpoint() |
1585 | // WriteDBG() => 0x%8.8x.", kret); |
1586 | |
1587 | if (kret == KERN_SUCCESS) |
1588 | return i; |
1589 | } |
1590 | // else |
1591 | // { |
1592 | // if (log) log->Printf |
1593 | // ("RegisterContextDarwin_arm::EnableHardwareBreakpoint(addr = |
1594 | // %8.8p, size = %u) => all hardware breakpoint resources are |
1595 | // being used.", addr, size); |
1596 | // } |
1597 | } |
1598 | |
1599 | return LLDB_INVALID_INDEX32; |
1600 | } |
1601 | |
1602 | bool RegisterContextDarwin_arm::ClearHardwareBreakpoint(uint32_t hw_index) { |
1603 | int kret = ReadDBG(force: false); |
1604 | |
1605 | const uint32_t num_hw_points = NumSupportedHardwareBreakpoints(); |
1606 | if (kret == KERN_SUCCESS) { |
1607 | if (hw_index < num_hw_points) { |
1608 | dbg.bcr[hw_index] = 0; |
1609 | // if (log) log->Printf |
1610 | // ("RegisterContextDarwin_arm::SetHardwareBreakpoint( %u ) - |
1611 | // BVR%u = 0x%8.8x BCR%u = 0x%8.8x", |
1612 | // hw_index, |
1613 | // hw_index, |
1614 | // dbg.bvr[hw_index], |
1615 | // hw_index, |
1616 | // dbg.bcr[hw_index]); |
1617 | |
1618 | kret = WriteDBG(); |
1619 | |
1620 | if (kret == KERN_SUCCESS) |
1621 | return true; |
1622 | } |
1623 | } |
1624 | return false; |
1625 | } |
1626 | |
1627 | uint32_t RegisterContextDarwin_arm::NumSupportedHardwareWatchpoints() { |
1628 | #if defined(__APPLE__) && defined(__arm__) |
1629 | // Set the init value to something that will let us know that we need to |
1630 | // autodetect how many watchpoints are supported dynamically... |
1631 | static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX; |
1632 | if (g_num_supported_hw_watchpoints == UINT32_MAX) { |
1633 | // Set this to zero in case we can't tell if there are any HW breakpoints |
1634 | g_num_supported_hw_watchpoints = 0; |
1635 | |
1636 | uint32_t register_DBGDIDR; |
1637 | asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); |
1638 | g_num_supported_hw_watchpoints = Bits32(register_DBGDIDR, 31, 28) + 1; |
1639 | } |
1640 | return g_num_supported_hw_watchpoints; |
1641 | #else |
1642 | // TODO: figure out remote case here! |
1643 | return 2; |
1644 | #endif |
1645 | } |
1646 | |
1647 | uint32_t RegisterContextDarwin_arm::SetHardwareWatchpoint(lldb::addr_t addr, |
1648 | size_t size, |
1649 | bool read, |
1650 | bool write) { |
1651 | const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); |
1652 | |
1653 | // Can't watch zero bytes |
1654 | if (size == 0) |
1655 | return LLDB_INVALID_INDEX32; |
1656 | |
1657 | // We must watch for either read or write |
1658 | if (!read && !write) |
1659 | return LLDB_INVALID_INDEX32; |
1660 | |
1661 | // Can't watch more than 4 bytes per WVR/WCR pair |
1662 | if (size > 4) |
1663 | return LLDB_INVALID_INDEX32; |
1664 | |
1665 | // We can only watch up to four bytes that follow a 4 byte aligned address |
1666 | // per watchpoint register pair. Since we have at most so we can only watch |
1667 | // until the next 4 byte boundary and we need to make sure we can properly |
1668 | // encode this. |
1669 | uint32_t addr_word_offset = addr % 4; |
1670 | // if (log) log->Printf |
1671 | // ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() - |
1672 | // addr_word_offset = 0x%8.8x", addr_word_offset); |
1673 | |
1674 | uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset; |
1675 | // if (log) log->Printf |
1676 | // ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() - byte_mask = |
1677 | // 0x%8.8x", byte_mask); |
1678 | if (byte_mask > 0xfu) |
1679 | return LLDB_INVALID_INDEX32; |
1680 | |
1681 | // Read the debug state |
1682 | int kret = ReadDBG(force: false); |
1683 | |
1684 | if (kret == KERN_SUCCESS) { |
1685 | // Check to make sure we have the needed hardware support |
1686 | uint32_t i = 0; |
1687 | |
1688 | for (i = 0; i < num_hw_watchpoints; ++i) { |
1689 | if ((dbg.wcr[i] & WCR_ENABLE) == 0) |
1690 | break; // We found an available hw breakpoint slot (in i) |
1691 | } |
1692 | |
1693 | // See if we found an available hw breakpoint slot above |
1694 | if (i < num_hw_watchpoints) { |
1695 | // Make the byte_mask into a valid Byte Address Select mask |
1696 | uint32_t byte_address_select = byte_mask << 5; |
1697 | // Make sure bits 1:0 are clear in our address |
1698 | dbg.wvr[i] = addr & ~((lldb::addr_t)3); |
1699 | dbg.wcr[i] = byte_address_select | // Which bytes that follow the IMVA |
1700 | // that we will watch |
1701 | S_USER | // Stop only in user mode |
1702 | (read ? WCR_LOAD : 0) | // Stop on read access? |
1703 | (write ? WCR_STORE : 0) | // Stop on write access? |
1704 | WCR_ENABLE; // Enable this watchpoint; |
1705 | |
1706 | kret = WriteDBG(); |
1707 | // if (log) log->Printf |
1708 | // ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() |
1709 | // WriteDBG() => 0x%8.8x.", kret); |
1710 | |
1711 | if (kret == KERN_SUCCESS) |
1712 | return i; |
1713 | } else { |
1714 | // if (log) log->Printf |
1715 | // ("RegisterContextDarwin_arm::EnableHardwareWatchpoint(): All |
1716 | // hardware resources (%u) are in use.", num_hw_watchpoints); |
1717 | } |
1718 | } |
1719 | return LLDB_INVALID_INDEX32; |
1720 | } |
1721 | |
1722 | bool RegisterContextDarwin_arm::ClearHardwareWatchpoint(uint32_t hw_index) { |
1723 | int kret = ReadDBG(force: false); |
1724 | |
1725 | const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); |
1726 | if (kret == KERN_SUCCESS) { |
1727 | if (hw_index < num_hw_points) { |
1728 | dbg.wcr[hw_index] = 0; |
1729 | // if (log) log->Printf |
1730 | // ("RegisterContextDarwin_arm::ClearHardwareWatchpoint( %u ) - |
1731 | // WVR%u = 0x%8.8x WCR%u = 0x%8.8x", |
1732 | // hw_index, |
1733 | // hw_index, |
1734 | // dbg.wvr[hw_index], |
1735 | // hw_index, |
1736 | // dbg.wcr[hw_index]); |
1737 | |
1738 | kret = WriteDBG(); |
1739 | |
1740 | if (kret == KERN_SUCCESS) |
1741 | return true; |
1742 | } |
1743 | } |
1744 | return false; |
1745 | } |
1746 | |