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