1 //===-- DNBArchImpl.cpp -----------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Created by Greg Clayton on 6/25/07.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #if defined (__arm__)
15
16 #include "MacOSX/arm/DNBArchImpl.h"
17 #include "MacOSX/MachProcess.h"
18 #include "MacOSX/MachThread.h"
19 #include "DNBBreakpoint.h"
20 #include "DNBLog.h"
21 #include "DNBRegisterInfo.h"
22 #include "DNB.h"
23 #include "ARM_GCC_Registers.h"
24 #include "ARM_DWARF_Registers.h"
25
26 #include <sys/sysctl.h>
27
28 // BCR address match type
29 #define BCR_M_IMVA_MATCH ((uint32_t)(0u << 21))
30 #define BCR_M_CONTEXT_ID_MATCH ((uint32_t)(1u << 21))
31 #define BCR_M_IMVA_MISMATCH ((uint32_t)(2u << 21))
32 #define BCR_M_RESERVED ((uint32_t)(3u << 21))
33
34 // Link a BVR/BCR or WVR/WCR pair to another
35 #define E_ENABLE_LINKING ((uint32_t)(1u << 20))
36
37 // Byte Address Select
38 #define BAS_IMVA_PLUS_0 ((uint32_t)(1u << 5))
39 #define BAS_IMVA_PLUS_1 ((uint32_t)(1u << 6))
40 #define BAS_IMVA_PLUS_2 ((uint32_t)(1u << 7))
41 #define BAS_IMVA_PLUS_3 ((uint32_t)(1u << 8))
42 #define BAS_IMVA_0_1 ((uint32_t)(3u << 5))
43 #define BAS_IMVA_2_3 ((uint32_t)(3u << 7))
44 #define BAS_IMVA_ALL ((uint32_t)(0xfu << 5))
45
46 // Break only in priveleged or user mode
47 #define S_RSVD ((uint32_t)(0u << 1))
48 #define S_PRIV ((uint32_t)(1u << 1))
49 #define S_USER ((uint32_t)(2u << 1))
50 #define S_PRIV_USER ((S_PRIV) | (S_USER))
51
52 #define BCR_ENABLE ((uint32_t)(1u))
53 #define WCR_ENABLE ((uint32_t)(1u))
54
55 // Watchpoint load/store
56 #define WCR_LOAD ((uint32_t)(1u << 3))
57 #define WCR_STORE ((uint32_t)(1u << 4))
58
59 // Definitions for the Debug Status and Control Register fields:
60 // [5:2] => Method of debug entry
61 //#define WATCHPOINT_OCCURRED ((uint32_t)(2u))
62 // I'm seeing this, instead.
63 #define WATCHPOINT_OCCURRED ((uint32_t)(10u))
64
65 static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 };
66 static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE };
67
68 // ARM constants used during decoding
69 #define REG_RD 0
70 #define LDM_REGLIST 1
71 #define PC_REG 15
72 #define PC_REGLIST_BIT 0x8000
73
74 // ARM conditions
75 #define COND_EQ 0x0
76 #define COND_NE 0x1
77 #define COND_CS 0x2
78 #define COND_HS 0x2
79 #define COND_CC 0x3
80 #define COND_LO 0x3
81 #define COND_MI 0x4
82 #define COND_PL 0x5
83 #define COND_VS 0x6
84 #define COND_VC 0x7
85 #define COND_HI 0x8
86 #define COND_LS 0x9
87 #define COND_GE 0xA
88 #define COND_LT 0xB
89 #define COND_GT 0xC
90 #define COND_LE 0xD
91 #define COND_AL 0xE
92 #define COND_UNCOND 0xF
93
94 #define MASK_CPSR_T (1u << 5)
95 #define MASK_CPSR_J (1u << 24)
96
97 #define MNEMONIC_STRING_SIZE 32
98 #define OPERAND_STRING_SIZE 128
99
100
101 void
Initialize()102 DNBArchMachARM::Initialize()
103 {
104 DNBArchPluginInfo arch_plugin_info =
105 {
106 CPU_TYPE_ARM,
107 DNBArchMachARM::Create,
108 DNBArchMachARM::GetRegisterSetInfo,
109 DNBArchMachARM::SoftwareBreakpointOpcode
110 };
111
112 // Register this arch plug-in with the main protocol class
113 DNBArchProtocol::RegisterArchPlugin (arch_plugin_info);
114 }
115
116
117 DNBArchProtocol *
Create(MachThread * thread)118 DNBArchMachARM::Create (MachThread *thread)
119 {
120 DNBArchMachARM *obj = new DNBArchMachARM (thread);
121 return obj;
122 }
123
124 const uint8_t * const
SoftwareBreakpointOpcode(nub_size_t byte_size)125 DNBArchMachARM::SoftwareBreakpointOpcode (nub_size_t byte_size)
126 {
127 switch (byte_size)
128 {
129 case 2: return g_thumb_breakpooint_opcode;
130 case 4: return g_arm_breakpoint_opcode;
131 }
132 return NULL;
133 }
134
135 uint32_t
GetCPUType()136 DNBArchMachARM::GetCPUType()
137 {
138 return CPU_TYPE_ARM;
139 }
140
141 uint64_t
GetPC(uint64_t failValue)142 DNBArchMachARM::GetPC(uint64_t failValue)
143 {
144 // Get program counter
145 if (GetGPRState(false) == KERN_SUCCESS)
146 return m_state.context.gpr.__pc;
147 return failValue;
148 }
149
150 kern_return_t
SetPC(uint64_t value)151 DNBArchMachARM::SetPC(uint64_t value)
152 {
153 // Get program counter
154 kern_return_t err = GetGPRState(false);
155 if (err == KERN_SUCCESS)
156 {
157 m_state.context.gpr.__pc = value;
158 err = SetGPRState();
159 }
160 return err == KERN_SUCCESS;
161 }
162
163 uint64_t
GetSP(uint64_t failValue)164 DNBArchMachARM::GetSP(uint64_t failValue)
165 {
166 // Get stack pointer
167 if (GetGPRState(false) == KERN_SUCCESS)
168 return m_state.context.gpr.__sp;
169 return failValue;
170 }
171
172 kern_return_t
GetGPRState(bool force)173 DNBArchMachARM::GetGPRState(bool force)
174 {
175 int set = e_regSetGPR;
176 // Check if we have valid cached registers
177 if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
178 return KERN_SUCCESS;
179
180 // Read the registers from our thread
181 mach_msg_type_number_t count = ARM_THREAD_STATE_COUNT;
182 kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_THREAD_STATE, (thread_state_t)&m_state.context.gpr, &count);
183 uint32_t *r = &m_state.context.gpr.__r[0];
184 DNBLogThreadedIf(LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count = %u) regs r0=%8.8x r1=%8.8x r2=%8.8x r3=%8.8x r4=%8.8x r5=%8.8x r6=%8.8x r7=%8.8x r8=%8.8x r9=%8.8x r10=%8.8x r11=%8.8x s12=%8.8x sp=%8.8x lr=%8.8x pc=%8.8x cpsr=%8.8x",
185 m_thread->MachPortNumber(),
186 ARM_THREAD_STATE,
187 ARM_THREAD_STATE_COUNT,
188 kret,
189 count,
190 r[0],
191 r[1],
192 r[2],
193 r[3],
194 r[4],
195 r[5],
196 r[6],
197 r[7],
198 r[8],
199 r[9],
200 r[10],
201 r[11],
202 r[12],
203 r[13],
204 r[14],
205 r[15],
206 r[16]);
207 m_state.SetError(set, Read, kret);
208 return kret;
209 }
210
211 kern_return_t
GetVFPState(bool force)212 DNBArchMachARM::GetVFPState(bool force)
213 {
214 int set = e_regSetVFP;
215 // Check if we have valid cached registers
216 if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
217 return KERN_SUCCESS;
218
219 // Read the registers from our thread
220 mach_msg_type_number_t count = ARM_VFP_STATE_COUNT;
221 kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, &count);
222 if (DNBLogEnabledForAny (LOG_THREAD))
223 {
224 uint32_t *r = &m_state.context.vfp.__r[0];
225 DNBLogThreaded ("thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count => %u)",
226 m_thread->MachPortNumber(),
227 ARM_THREAD_STATE,
228 ARM_THREAD_STATE_COUNT,
229 kret,
230 count);
231 DNBLogThreaded(" s0=%8.8x s1=%8.8x s2=%8.8x s3=%8.8x s4=%8.8x s5=%8.8x s6=%8.8x s7=%8.8x",r[ 0],r[ 1],r[ 2],r[ 3],r[ 4],r[ 5],r[ 6],r[ 7]);
232 DNBLogThreaded(" s8=%8.8x s9=%8.8x s10=%8.8x s11=%8.8x s12=%8.8x s13=%8.8x s14=%8.8x s15=%8.8x",r[ 8],r[ 9],r[10],r[11],r[12],r[13],r[14],r[15]);
233 DNBLogThreaded(" s16=%8.8x s17=%8.8x s18=%8.8x s19=%8.8x s20=%8.8x s21=%8.8x s22=%8.8x s23=%8.8x",r[16],r[17],r[18],r[19],r[20],r[21],r[22],r[23]);
234 DNBLogThreaded(" s24=%8.8x s25=%8.8x s26=%8.8x s27=%8.8x s28=%8.8x s29=%8.8x s30=%8.8x s31=%8.8x",r[24],r[25],r[26],r[27],r[28],r[29],r[30],r[31]);
235 DNBLogThreaded(" s32=%8.8x s33=%8.8x s34=%8.8x s35=%8.8x s36=%8.8x s37=%8.8x s38=%8.8x s39=%8.8x",r[32],r[33],r[34],r[35],r[36],r[37],r[38],r[39]);
236 DNBLogThreaded(" s40=%8.8x s41=%8.8x s42=%8.8x s43=%8.8x s44=%8.8x s45=%8.8x s46=%8.8x s47=%8.8x",r[40],r[41],r[42],r[43],r[44],r[45],r[46],r[47]);
237 DNBLogThreaded(" s48=%8.8x s49=%8.8x s50=%8.8x s51=%8.8x s52=%8.8x s53=%8.8x s54=%8.8x s55=%8.8x",r[48],r[49],r[50],r[51],r[52],r[53],r[54],r[55]);
238 DNBLogThreaded(" s56=%8.8x s57=%8.8x s58=%8.8x s59=%8.8x s60=%8.8x s61=%8.8x s62=%8.8x s63=%8.8x fpscr=%8.8x",r[56],r[57],r[58],r[59],r[60],r[61],r[62],r[63],r[64]);
239 }
240 m_state.SetError(set, Read, kret);
241 return kret;
242 }
243
244 kern_return_t
GetEXCState(bool force)245 DNBArchMachARM::GetEXCState(bool force)
246 {
247 int set = e_regSetEXC;
248 // Check if we have valid cached registers
249 if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
250 return KERN_SUCCESS;
251
252 // Read the registers from our thread
253 mach_msg_type_number_t count = ARM_EXCEPTION_STATE_COUNT;
254 kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, &count);
255 m_state.SetError(set, Read, kret);
256 return kret;
257 }
258
259 static void
DumpDBGState(const DNBArchMachARM::DBG & dbg)260 DumpDBGState(const DNBArchMachARM::DBG& dbg)
261 {
262 uint32_t i = 0;
263 for (i=0; i<16; i++) {
264 DNBLogThreadedIf(LOG_STEP, "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }",
265 i, i, dbg.__bvr[i], dbg.__bcr[i],
266 i, i, dbg.__wvr[i], dbg.__wcr[i]);
267 }
268 }
269
270 kern_return_t
GetDBGState(bool force)271 DNBArchMachARM::GetDBGState(bool force)
272 {
273 int set = e_regSetDBG;
274
275 // Check if we have valid cached registers
276 if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
277 return KERN_SUCCESS;
278
279 // Read the registers from our thread
280 mach_msg_type_number_t count = ARM_DEBUG_STATE_COUNT;
281 kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE, (thread_state_t)&m_state.dbg, &count);
282 m_state.SetError(set, Read, kret);
283 return kret;
284 }
285
286 kern_return_t
SetGPRState()287 DNBArchMachARM::SetGPRState()
288 {
289 int set = e_regSetGPR;
290 kern_return_t kret = ::thread_set_state(m_thread->MachPortNumber(), ARM_THREAD_STATE, (thread_state_t)&m_state.context.gpr, ARM_THREAD_STATE_COUNT);
291 m_state.SetError(set, Write, kret); // Set the current write error for this register set
292 m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently
293 return kret; // Return the error code
294 }
295
296 kern_return_t
SetVFPState()297 DNBArchMachARM::SetVFPState()
298 {
299 int set = e_regSetVFP;
300 kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, ARM_VFP_STATE_COUNT);
301 m_state.SetError(set, Write, kret); // Set the current write error for this register set
302 m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently
303 return kret; // Return the error code
304 }
305
306 kern_return_t
SetEXCState()307 DNBArchMachARM::SetEXCState()
308 {
309 int set = e_regSetEXC;
310 kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, ARM_EXCEPTION_STATE_COUNT);
311 m_state.SetError(set, Write, kret); // Set the current write error for this register set
312 m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently
313 return kret; // Return the error code
314 }
315
316 kern_return_t
SetDBGState(bool also_set_on_task)317 DNBArchMachARM::SetDBGState(bool also_set_on_task)
318 {
319 int set = e_regSetDBG;
320 kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_DEBUG_STATE, (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE_COUNT);
321 if (also_set_on_task)
322 {
323 kern_return_t task_kret = ::task_set_state (m_thread->Process()->Task().TaskPort(), ARM_DEBUG_STATE, (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE_COUNT);
324 if (task_kret != KERN_SUCCESS)
325 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::SetDBGState failed to set debug control register state: 0x%8.8x.", kret);
326 }
327
328 m_state.SetError(set, Write, kret); // Set the current write error for this register set
329 m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently
330 return kret; // Return the error code
331 }
332
333 void
ThreadWillResume()334 DNBArchMachARM::ThreadWillResume()
335 {
336 // Do we need to step this thread? If so, let the mach thread tell us so.
337 if (m_thread->IsStepping())
338 {
339 // This is the primary thread, let the arch do anything it needs
340 if (NumSupportedHardwareBreakpoints() > 0)
341 {
342 if (EnableHardwareSingleStep(true) != KERN_SUCCESS)
343 {
344 DNBLogThreaded("DNBArchMachARM::ThreadWillResume() failed to enable hardware single step");
345 }
346 }
347 }
348
349 // Disable the triggered watchpoint temporarily before we resume.
350 // Plus, we try to enable hardware single step to execute past the instruction which triggered our watchpoint.
351 if (m_watchpoint_did_occur)
352 {
353 if (m_watchpoint_hw_index >= 0)
354 {
355 kern_return_t kret = GetDBGState(false);
356 if (kret == KERN_SUCCESS && !IsWatchpointEnabled(m_state.dbg, m_watchpoint_hw_index)) {
357 // The watchpoint might have been disabled by the user. We don't need to do anything at all
358 // to enable hardware single stepping.
359 m_watchpoint_did_occur = false;
360 m_watchpoint_hw_index = -1;
361 return;
362 }
363
364 DisableHardwareWatchpoint0(m_watchpoint_hw_index, true, false);
365 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() DisableHardwareWatchpoint(%d) called",
366 m_watchpoint_hw_index);
367
368 // Enable hardware single step to move past the watchpoint-triggering instruction.
369 m_watchpoint_resume_single_step_enabled = (EnableHardwareSingleStep(true) == KERN_SUCCESS);
370
371 // If we are not able to enable single step to move past the watchpoint-triggering instruction,
372 // at least we should reset the two watchpoint member variables so that the next time around
373 // this callback function is invoked, the enclosing logical branch is skipped.
374 if (!m_watchpoint_resume_single_step_enabled) {
375 // Reset the two watchpoint member variables.
376 m_watchpoint_did_occur = false;
377 m_watchpoint_hw_index = -1;
378 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() failed to enable single step");
379 }
380 else
381 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() succeeded to enable single step");
382 }
383 }
384 }
385
386 bool
ThreadDidStop()387 DNBArchMachARM::ThreadDidStop()
388 {
389 bool success = true;
390
391 m_state.InvalidateRegisterSetState (e_regSetALL);
392
393 if (m_watchpoint_resume_single_step_enabled)
394 {
395 // Great! We now disable the hardware single step as well as re-enable the hardware watchpoint.
396 // See also ThreadWillResume().
397 if (EnableHardwareSingleStep(false) == KERN_SUCCESS)
398 {
399 if (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0)
400 {
401 EnableHardwareWatchpoint0(m_watchpoint_hw_index, true, false);
402 m_watchpoint_resume_single_step_enabled = false;
403 m_watchpoint_did_occur = false;
404 m_watchpoint_hw_index = -1;
405 }
406 else
407 {
408 DNBLogError("internal error detected: m_watchpoint_resume_step_enabled is true but (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0) does not hold!");
409 }
410 }
411 else
412 {
413 DNBLogError("internal error detected: m_watchpoint_resume_step_enabled is true but unable to disable single step!");
414 }
415 }
416
417 // Are we stepping a single instruction?
418 if (GetGPRState(true) == KERN_SUCCESS)
419 {
420 // We are single stepping, was this the primary thread?
421 if (m_thread->IsStepping())
422 {
423 success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
424 }
425 else
426 {
427 // The MachThread will automatically restore the suspend count
428 // in ThreadDidStop(), so we don't need to do anything here if
429 // we weren't the primary thread the last time
430 }
431 }
432 return success;
433 }
434
435 bool
NotifyException(MachException::Data & exc)436 DNBArchMachARM::NotifyException(MachException::Data& exc)
437 {
438 switch (exc.exc_type)
439 {
440 default:
441 break;
442 case EXC_BREAKPOINT:
443 if (exc.exc_data.size() == 2 && exc.exc_data[0] == EXC_ARM_DA_DEBUG)
444 {
445 // exc_code = EXC_ARM_DA_DEBUG
446 //
447 // Check whether this corresponds to a watchpoint hit event.
448 // If yes, retrieve the exc_sub_code as the data break address.
449 if (!HasWatchpointOccurred())
450 break;
451
452 // The data break address is passed as exc_data[1].
453 nub_addr_t addr = exc.exc_data[1];
454 // Find the hardware index with the side effect of possibly massaging the
455 // addr to return the starting address as seen from the debugger side.
456 uint32_t hw_index = GetHardwareWatchpointHit(addr);
457 if (hw_index != INVALID_NUB_HW_INDEX)
458 {
459 m_watchpoint_did_occur = true;
460 m_watchpoint_hw_index = hw_index;
461 exc.exc_data[1] = addr;
462 // Piggyback the hw_index in the exc.data.
463 exc.exc_data.push_back(hw_index);
464 }
465
466 return true;
467 }
468 break;
469 }
470 return false;
471 }
472
473 bool
StepNotComplete()474 DNBArchMachARM::StepNotComplete ()
475 {
476 if (m_hw_single_chained_step_addr != INVALID_NUB_ADDRESS)
477 {
478 kern_return_t kret = KERN_INVALID_ARGUMENT;
479 kret = GetGPRState(false);
480 if (kret == KERN_SUCCESS)
481 {
482 if (m_state.context.gpr.__pc == m_hw_single_chained_step_addr)
483 {
484 DNBLogThreadedIf(LOG_STEP, "Need to step some more at 0x%8.8x", m_hw_single_chained_step_addr);
485 return true;
486 }
487 }
488 }
489
490 m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS;
491 return false;
492 }
493
494
495 // Set the single step bit in the processor status register.
496 kern_return_t
EnableHardwareSingleStep(bool enable)497 DNBArchMachARM::EnableHardwareSingleStep (bool enable)
498 {
499 DNBError err;
500 DNBLogThreadedIf(LOG_STEP, "%s( enable = %d )", __FUNCTION__, enable);
501
502 err = GetGPRState(false);
503
504 if (err.Fail())
505 {
506 err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__);
507 return err.Error();
508 }
509
510 err = GetDBGState(false);
511
512 if (err.Fail())
513 {
514 err.LogThreaded("%s: failed to read the DBG registers", __FUNCTION__);
515 return err.Error();
516 }
517
518 const uint32_t i = 0;
519 if (enable)
520 {
521 m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS;
522
523 // Save our previous state
524 m_dbg_save = m_state.dbg;
525 // Set a breakpoint that will stop when the PC doesn't match the current one!
526 m_state.dbg.__bvr[i] = m_state.context.gpr.__pc & 0xFFFFFFFCu; // Set the current PC as the breakpoint address
527 m_state.dbg.__bcr[i] = BCR_M_IMVA_MISMATCH | // Stop on address mismatch
528 S_USER | // Stop only in user mode
529 BCR_ENABLE; // Enable this breakpoint
530 if (m_state.context.gpr.__cpsr & 0x20)
531 {
532 // Thumb breakpoint
533 if (m_state.context.gpr.__pc & 2)
534 m_state.dbg.__bcr[i] |= BAS_IMVA_2_3;
535 else
536 m_state.dbg.__bcr[i] |= BAS_IMVA_0_1;
537
538 uint16_t opcode;
539 if (sizeof(opcode) == m_thread->Process()->Task().ReadMemory(m_state.context.gpr.__pc, sizeof(opcode), &opcode))
540 {
541 if (((opcode & 0xE000) == 0xE000) && opcode & 0x1800)
542 {
543 // 32 bit thumb opcode...
544 if (m_state.context.gpr.__pc & 2)
545 {
546 // We can't take care of a 32 bit thumb instruction single step
547 // with just IVA mismatching. We will need to chain an extra
548 // hardware single step in order to complete this single step...
549 m_hw_single_chained_step_addr = m_state.context.gpr.__pc + 2;
550 }
551 else
552 {
553 // Extend the number of bits to ignore for the mismatch
554 m_state.dbg.__bcr[i] |= BAS_IMVA_ALL;
555 }
556 }
557 }
558 }
559 else
560 {
561 // ARM breakpoint
562 m_state.dbg.__bcr[i] |= BAS_IMVA_ALL; // Stop when any address bits change
563 }
564
565 DNBLogThreadedIf(LOG_STEP, "%s: BVR%u=0x%8.8x BCR%u=0x%8.8x", __FUNCTION__, i, m_state.dbg.__bvr[i], i, m_state.dbg.__bcr[i]);
566
567 for (uint32_t j=i+1; j<16; ++j)
568 {
569 // Disable all others
570 m_state.dbg.__bvr[j] = 0;
571 m_state.dbg.__bcr[j] = 0;
572 }
573 }
574 else
575 {
576 // Just restore the state we had before we did single stepping
577 m_state.dbg = m_dbg_save;
578 }
579
580 return SetDBGState(false);
581 }
582
583 // return 1 if bit "BIT" is set in "value"
bit(uint32_t value,uint32_t bit)584 static inline uint32_t bit(uint32_t value, uint32_t bit)
585 {
586 return (value >> bit) & 1u;
587 }
588
589 // return the bitfield "value[msbit:lsbit]".
bits(uint32_t value,uint32_t msbit,uint32_t lsbit)590 static inline uint32_t bits(uint32_t value, uint32_t msbit, uint32_t lsbit)
591 {
592 assert(msbit >= lsbit);
593 uint32_t shift_left = sizeof(value) * 8 - 1 - msbit;
594 value <<= shift_left; // shift anything above the msbit off of the unsigned edge
595 value >>= (shift_left + lsbit); // shift it back again down to the lsbit (including undoing any shift from above)
596 return value; // return our result
597 }
598
599 bool
ConditionPassed(uint8_t condition,uint32_t cpsr)600 DNBArchMachARM::ConditionPassed(uint8_t condition, uint32_t cpsr)
601 {
602 uint32_t cpsr_n = bit(cpsr, 31); // Negative condition code flag
603 uint32_t cpsr_z = bit(cpsr, 30); // Zero condition code flag
604 uint32_t cpsr_c = bit(cpsr, 29); // Carry condition code flag
605 uint32_t cpsr_v = bit(cpsr, 28); // Overflow condition code flag
606
607 switch (condition) {
608 case COND_EQ: // (0x0)
609 if (cpsr_z == 1) return true;
610 break;
611 case COND_NE: // (0x1)
612 if (cpsr_z == 0) return true;
613 break;
614 case COND_CS: // (0x2)
615 if (cpsr_c == 1) return true;
616 break;
617 case COND_CC: // (0x3)
618 if (cpsr_c == 0) return true;
619 break;
620 case COND_MI: // (0x4)
621 if (cpsr_n == 1) return true;
622 break;
623 case COND_PL: // (0x5)
624 if (cpsr_n == 0) return true;
625 break;
626 case COND_VS: // (0x6)
627 if (cpsr_v == 1) return true;
628 break;
629 case COND_VC: // (0x7)
630 if (cpsr_v == 0) return true;
631 break;
632 case COND_HI: // (0x8)
633 if ((cpsr_c == 1) && (cpsr_z == 0)) return true;
634 break;
635 case COND_LS: // (0x9)
636 if ((cpsr_c == 0) || (cpsr_z == 1)) return true;
637 break;
638 case COND_GE: // (0xA)
639 if (cpsr_n == cpsr_v) return true;
640 break;
641 case COND_LT: // (0xB)
642 if (cpsr_n != cpsr_v) return true;
643 break;
644 case COND_GT: // (0xC)
645 if ((cpsr_z == 0) && (cpsr_n == cpsr_v)) return true;
646 break;
647 case COND_LE: // (0xD)
648 if ((cpsr_z == 1) || (cpsr_n != cpsr_v)) return true;
649 break;
650 default:
651 return true;
652 break;
653 }
654
655 return false;
656 }
657
658 uint32_t
NumSupportedHardwareBreakpoints()659 DNBArchMachARM::NumSupportedHardwareBreakpoints()
660 {
661 // Set the init value to something that will let us know that we need to
662 // autodetect how many breakpoints are supported dynamically...
663 static uint32_t g_num_supported_hw_breakpoints = UINT_MAX;
664 if (g_num_supported_hw_breakpoints == UINT_MAX)
665 {
666 // Set this to zero in case we can't tell if there are any HW breakpoints
667 g_num_supported_hw_breakpoints = 0;
668
669 size_t len;
670 uint32_t n = 0;
671 len = sizeof (n);
672 if (::sysctlbyname("hw.optional.breakpoint", &n, &len, NULL, 0) == 0)
673 {
674 g_num_supported_hw_breakpoints = n;
675 DNBLogThreadedIf(LOG_THREAD, "hw.optional.breakpoint=%u", n);
676 }
677 else
678 {
679 // Read the DBGDIDR to get the number of available hardware breakpoints
680 // However, in some of our current armv7 processors, hardware
681 // breakpoints/watchpoints were not properly connected. So detect those
682 // cases using a field in a sysctl. For now we are using "hw.cpusubtype"
683 // field to distinguish CPU architectures. This is a hack until we can
684 // get <rdar://problem/6372672> fixed, at which point we will switch to
685 // using a different sysctl string that will tell us how many BRPs
686 // are available to us directly without having to read DBGDIDR.
687 uint32_t register_DBGDIDR;
688
689 asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR));
690 uint32_t numBRPs = bits(register_DBGDIDR, 27, 24);
691 // Zero is reserved for the BRP count, so don't increment it if it is zero
692 if (numBRPs > 0)
693 numBRPs++;
694 DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number BRP pairs = %u)", register_DBGDIDR, numBRPs);
695
696 if (numBRPs > 0)
697 {
698 uint32_t cpusubtype;
699 len = sizeof(cpusubtype);
700 // TODO: remove this hack and change to using hw.optional.xx when implmented
701 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
702 {
703 DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=%d", cpusubtype);
704 if (cpusubtype == CPU_SUBTYPE_ARM_V7)
705 DNBLogThreadedIf(LOG_THREAD, "Hardware breakpoints disabled for armv7 (rdar://problem/6372672)");
706 else
707 g_num_supported_hw_breakpoints = numBRPs;
708 }
709 }
710 }
711 }
712 return g_num_supported_hw_breakpoints;
713 }
714
715
716 uint32_t
NumSupportedHardwareWatchpoints()717 DNBArchMachARM::NumSupportedHardwareWatchpoints()
718 {
719 // Set the init value to something that will let us know that we need to
720 // autodetect how many watchpoints are supported dynamically...
721 static uint32_t g_num_supported_hw_watchpoints = UINT_MAX;
722 if (g_num_supported_hw_watchpoints == UINT_MAX)
723 {
724 // Set this to zero in case we can't tell if there are any HW breakpoints
725 g_num_supported_hw_watchpoints = 0;
726
727
728 size_t len;
729 uint32_t n = 0;
730 len = sizeof (n);
731 if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0)
732 {
733 g_num_supported_hw_watchpoints = n;
734 DNBLogThreadedIf(LOG_THREAD, "hw.optional.watchpoint=%u", n);
735 }
736 else
737 {
738 // Read the DBGDIDR to get the number of available hardware breakpoints
739 // However, in some of our current armv7 processors, hardware
740 // breakpoints/watchpoints were not properly connected. So detect those
741 // cases using a field in a sysctl. For now we are using "hw.cpusubtype"
742 // field to distinguish CPU architectures. This is a hack until we can
743 // get <rdar://problem/6372672> fixed, at which point we will switch to
744 // using a different sysctl string that will tell us how many WRPs
745 // are available to us directly without having to read DBGDIDR.
746
747 uint32_t register_DBGDIDR;
748 asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR));
749 uint32_t numWRPs = bits(register_DBGDIDR, 31, 28) + 1;
750 DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number WRP pairs = %u)", register_DBGDIDR, numWRPs);
751
752 if (numWRPs > 0)
753 {
754 uint32_t cpusubtype;
755 size_t len;
756 len = sizeof(cpusubtype);
757 // TODO: remove this hack and change to using hw.optional.xx when implmented
758 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
759 {
760 DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=0x%d", cpusubtype);
761
762 if (cpusubtype == CPU_SUBTYPE_ARM_V7)
763 DNBLogThreadedIf(LOG_THREAD, "Hardware watchpoints disabled for armv7 (rdar://problem/6372672)");
764 else
765 g_num_supported_hw_watchpoints = numWRPs;
766 }
767 }
768 }
769 }
770 return g_num_supported_hw_watchpoints;
771 }
772
773
774 uint32_t
EnableHardwareBreakpoint(nub_addr_t addr,nub_size_t size)775 DNBArchMachARM::EnableHardwareBreakpoint (nub_addr_t addr, nub_size_t size)
776 {
777 // Make sure our address isn't bogus
778 if (addr & 1)
779 return INVALID_NUB_HW_INDEX;
780
781 kern_return_t kret = GetDBGState(false);
782
783 if (kret == KERN_SUCCESS)
784 {
785 const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints();
786 uint32_t i;
787 for (i=0; i<num_hw_breakpoints; ++i)
788 {
789 if ((m_state.dbg.__bcr[i] & BCR_ENABLE) == 0)
790 break; // We found an available hw breakpoint slot (in i)
791 }
792
793 // See if we found an available hw breakpoint slot above
794 if (i < num_hw_breakpoints)
795 {
796 // Make sure bits 1:0 are clear in our address
797 m_state.dbg.__bvr[i] = addr & ~((nub_addr_t)3);
798
799 if (size == 2 || addr & 2)
800 {
801 uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1;
802
803 // We have a thumb breakpoint
804 // We have an ARM breakpoint
805 m_state.dbg.__bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch
806 byte_addr_select | // Set the correct byte address select so we only trigger on the correct opcode
807 S_USER | // Which modes should this breakpoint stop in?
808 BCR_ENABLE; // Enable this hardware breakpoint
809 DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint( addr = 0x%8.8llx, size = %llu ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (Thumb)",
810 (uint64_t)addr,
811 (uint64_t)size,
812 i,
813 i,
814 m_state.dbg.__bvr[i],
815 m_state.dbg.__bcr[i]);
816 }
817 else if (size == 4)
818 {
819 // We have an ARM breakpoint
820 m_state.dbg.__bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch
821 BAS_IMVA_ALL | // Stop on any of the four bytes following the IMVA
822 S_USER | // Which modes should this breakpoint stop in?
823 BCR_ENABLE; // Enable this hardware breakpoint
824 DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint( addr = 0x%8.8llx, size = %llu ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (ARM)",
825 (uint64_t)addr,
826 (uint64_t)size,
827 i,
828 i,
829 m_state.dbg.__bvr[i],
830 m_state.dbg.__bcr[i]);
831 }
832
833 kret = SetDBGState(false);
834 DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint() SetDBGState() => 0x%8.8x.", kret);
835
836 if (kret == KERN_SUCCESS)
837 return i;
838 }
839 else
840 {
841 DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint(addr = 0x%8.8llx, size = %llu) => all hardware breakpoint resources are being used.", (uint64_t)addr, (uint64_t)size);
842 }
843 }
844
845 return INVALID_NUB_HW_INDEX;
846 }
847
848 bool
DisableHardwareBreakpoint(uint32_t hw_index)849 DNBArchMachARM::DisableHardwareBreakpoint (uint32_t hw_index)
850 {
851 kern_return_t kret = GetDBGState(false);
852
853 const uint32_t num_hw_points = NumSupportedHardwareBreakpoints();
854 if (kret == KERN_SUCCESS)
855 {
856 if (hw_index < num_hw_points)
857 {
858 m_state.dbg.__bcr[hw_index] = 0;
859 DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::SetHardwareBreakpoint( %u ) - BVR%u = 0x%8.8x BCR%u = 0x%8.8x",
860 hw_index,
861 hw_index,
862 m_state.dbg.__bvr[hw_index],
863 hw_index,
864 m_state.dbg.__bcr[hw_index]);
865
866 kret = SetDBGState(false);
867
868 if (kret == KERN_SUCCESS)
869 return true;
870 }
871 }
872 return false;
873 }
874
875 // This stores the lo->hi mappings. It's safe to initialize to all 0's
876 // since hi > lo and therefore LoHi[i] cannot be 0.
877 static uint32_t LoHi[16] = { 0 };
878
879 uint32_t
EnableHardwareWatchpoint(nub_addr_t addr,nub_size_t size,bool read,bool write,bool also_set_on_task)880 DNBArchMachARM::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task)
881 {
882 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(addr = 0x%8.8llx, size = %llu, read = %u, write = %u)", (uint64_t)addr, (uint64_t)size, read, write);
883
884 const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
885
886 // Can't watch zero bytes
887 if (size == 0)
888 return INVALID_NUB_HW_INDEX;
889
890 // We must watch for either read or write
891 if (read == false && write == false)
892 return INVALID_NUB_HW_INDEX;
893
894 // Divide-and-conquer for size == 8.
895 if (size == 8)
896 {
897 uint32_t lo = EnableHardwareWatchpoint(addr, 4, read, write, also_set_on_task);
898 if (lo == INVALID_NUB_HW_INDEX)
899 return INVALID_NUB_HW_INDEX;
900 uint32_t hi = EnableHardwareWatchpoint(addr+4, 4, read, write, also_set_on_task);
901 if (hi == INVALID_NUB_HW_INDEX)
902 {
903 DisableHardwareWatchpoint(lo, also_set_on_task);
904 return INVALID_NUB_HW_INDEX;
905 }
906 // Tag this lo->hi mapping in our database.
907 LoHi[lo] = hi;
908 return lo;
909 }
910
911 // Otherwise, can't watch more than 4 bytes per WVR/WCR pair
912 if (size > 4)
913 return INVALID_NUB_HW_INDEX;
914
915 // We can only watch up to four bytes that follow a 4 byte aligned address
916 // per watchpoint register pair. Since we can only watch until the next 4
917 // byte boundary, we need to make sure we can properly encode this.
918
919 // addr_word_offset = addr % 4, i.e, is in set([0, 1, 2, 3])
920 //
921 // +---+---+---+---+
922 // | 0 | 1 | 2 | 3 |
923 // +---+---+---+---+
924 // ^
925 // |
926 // word address (4-byte aligned) = addr & 0xFFFFFFFC => goes into WVR
927 //
928 // examples:
929 // 1. addr_word_offset = 1, size = 1 to watch a uint_8 => byte_mask = (0b0001 << 1) = 0b0010
930 // 2. addr_word_offset = 2, size = 2 to watch a uint_16 => byte_mask = (0b0011 << 2) = 0b1100
931 //
932 // where byte_mask goes into WCR[8:5]
933
934 uint32_t addr_word_offset = addr % 4;
935 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset);
936
937 uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
938 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask);
939 if (byte_mask > 0xfu)
940 return INVALID_NUB_HW_INDEX;
941
942 // Read the debug state
943 kern_return_t kret = GetDBGState(true);
944
945 if (kret == KERN_SUCCESS)
946 {
947 // Check to make sure we have the needed hardware support
948 uint32_t i = 0;
949
950 for (i=0; i<num_hw_watchpoints; ++i)
951 {
952 if ((m_state.dbg.__wcr[i] & WCR_ENABLE) == 0)
953 break; // We found an available hw watchpoint slot (in i)
954 }
955
956 // See if we found an available hw watchpoint slot above
957 if (i < num_hw_watchpoints)
958 {
959 //DumpDBGState(m_state.dbg);
960
961 // Make the byte_mask into a valid Byte Address Select mask
962 uint32_t byte_address_select = byte_mask << 5;
963 // Make sure bits 1:0 are clear in our address
964 m_state.dbg.__wvr[i] = addr & ~((nub_addr_t)3); // DVA (Data Virtual Address)
965 m_state.dbg.__wcr[i] = byte_address_select | // Which bytes that follow the DVA that we will watch
966 S_USER | // Stop only in user mode
967 (read ? WCR_LOAD : 0) | // Stop on read access?
968 (write ? WCR_STORE : 0) | // Stop on write access?
969 WCR_ENABLE; // Enable this watchpoint;
970
971 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() adding watchpoint on address 0x%llx with control register value 0x%x", (uint64_t) m_state.dbg.__wvr[i], (uint32_t) m_state.dbg.__wcr[i]);
972
973 kret = SetDBGState(also_set_on_task);
974 //DumpDBGState(m_state.dbg);
975
976 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret);
977
978 if (kret == KERN_SUCCESS)
979 return i;
980 }
981 else
982 {
983 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints);
984 }
985 }
986 return INVALID_NUB_HW_INDEX;
987 }
988
989 bool
EnableHardwareWatchpoint0(uint32_t hw_index,bool Delegate,bool also_set_on_task)990 DNBArchMachARM::EnableHardwareWatchpoint0 (uint32_t hw_index, bool Delegate, bool also_set_on_task)
991 {
992 kern_return_t kret = GetDBGState(false);
993 if (kret != KERN_SUCCESS)
994 return false;
995
996 const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
997 if (hw_index >= num_hw_points)
998 return false;
999
1000 if (Delegate && LoHi[hw_index]) {
1001 // Enable lo and hi watchpoint hardware indexes.
1002 return EnableHardwareWatchpoint0(hw_index, false, also_set_on_task) &&
1003 EnableHardwareWatchpoint0(LoHi[hw_index], false, also_set_on_task);
1004 }
1005
1006 m_state.dbg.__wcr[hw_index] |= (nub_addr_t)WCR_ENABLE;
1007 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x WCR%u = 0x%8.8x",
1008 hw_index,
1009 hw_index,
1010 m_state.dbg.__wvr[hw_index],
1011 hw_index,
1012 m_state.dbg.__wcr[hw_index]);
1013
1014 kret = SetDBGState(false);
1015
1016 return (kret == KERN_SUCCESS);
1017 }
1018
1019 bool
DisableHardwareWatchpoint(uint32_t hw_index,bool also_set_on_task)1020 DNBArchMachARM::DisableHardwareWatchpoint (uint32_t hw_index, bool also_set_on_task)
1021 {
1022 return DisableHardwareWatchpoint0(hw_index, true, also_set_on_task);
1023 }
1024 bool
DisableHardwareWatchpoint0(uint32_t hw_index,bool Delegate,bool also_set_on_task)1025 DNBArchMachARM::DisableHardwareWatchpoint0 (uint32_t hw_index, bool Delegate, bool also_set_on_task)
1026 {
1027 kern_return_t kret = GetDBGState(false);
1028 if (kret != KERN_SUCCESS)
1029 return false;
1030
1031 const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
1032 if (hw_index >= num_hw_points)
1033 return false;
1034
1035 if (Delegate && LoHi[hw_index]) {
1036 // Disable lo and hi watchpoint hardware indexes.
1037 return DisableHardwareWatchpoint0(hw_index, false, also_set_on_task) &&
1038 DisableHardwareWatchpoint0(LoHi[hw_index], false, also_set_on_task);
1039 }
1040
1041 m_state.dbg.__wcr[hw_index] &= ~((nub_addr_t)WCR_ENABLE);
1042 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::DisableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x WCR%u = 0x%8.8x",
1043 hw_index,
1044 hw_index,
1045 m_state.dbg.__wvr[hw_index],
1046 hw_index,
1047 m_state.dbg.__wcr[hw_index]);
1048
1049 kret = SetDBGState(also_set_on_task);
1050
1051 return (kret == KERN_SUCCESS);
1052 }
1053
1054 // Returns -1 if the trailing bit patterns are not one of:
1055 // { 0b???1, 0b??10, 0b?100, 0b1000 }.
1056 static inline
1057 int32_t
LowestBitSet(uint32_t val)1058 LowestBitSet(uint32_t val)
1059 {
1060 for (unsigned i = 0; i < 4; ++i) {
1061 if (bit(val, i))
1062 return i;
1063 }
1064 return -1;
1065 }
1066
1067 // Iterate through the debug registers; return the index of the first watchpoint whose address matches.
1068 // As a side effect, the starting address as understood by the debugger is returned which could be
1069 // different from 'addr' passed as an in/out argument.
1070 uint32_t
GetHardwareWatchpointHit(nub_addr_t & addr)1071 DNBArchMachARM::GetHardwareWatchpointHit(nub_addr_t &addr)
1072 {
1073 // Read the debug state
1074 kern_return_t kret = GetDBGState(true);
1075 //DumpDBGState(m_state.dbg);
1076 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret);
1077 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::GetHardwareWatchpointHit() addr = 0x%llx", (uint64_t)addr);
1078
1079 // This is the watchpoint value to match against, i.e., word address.
1080 nub_addr_t wp_val = addr & ~((nub_addr_t)3);
1081 if (kret == KERN_SUCCESS)
1082 {
1083 DBG &debug_state = m_state.dbg;
1084 uint32_t i, num = NumSupportedHardwareWatchpoints();
1085 for (i = 0; i < num; ++i)
1086 {
1087 nub_addr_t wp_addr = GetWatchAddress(debug_state, i);
1088 DNBLogThreadedIf(LOG_WATCHPOINTS,
1089 "DNBArchMachARM::GetHardwareWatchpointHit() slot: %u (addr = 0x%llx).",
1090 i, (uint64_t)wp_addr);
1091 if (wp_val == wp_addr) {
1092 uint32_t byte_mask = bits(debug_state.__wcr[i], 8, 5);
1093
1094 // Sanity check the byte_mask, first.
1095 if (LowestBitSet(byte_mask) < 0)
1096 continue;
1097
1098 // Compute the starting address (from the point of view of the debugger).
1099 addr = wp_addr + LowestBitSet(byte_mask);
1100 return i;
1101 }
1102 }
1103 }
1104 return INVALID_NUB_HW_INDEX;
1105 }
1106
1107 // ThreadWillResume() calls this to clear bits[5:2] (Method of entry bits) of
1108 // the Debug Status and Control Register (DSCR).
1109 //
1110 // b0010 = a watchpoint occurred
1111 // b0000 is the reset value
1112 void
ClearWatchpointOccurred()1113 DNBArchMachARM::ClearWatchpointOccurred()
1114 {
1115 uint32_t register_DBGDSCR;
1116 asm("mrc p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR));
1117 if (bits(register_DBGDSCR, 5, 2) == WATCHPOINT_OCCURRED)
1118 {
1119 uint32_t mask = ~(0xF << 2);
1120 register_DBGDSCR &= mask;
1121 asm("mcr p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR));
1122 }
1123 return;
1124 }
1125
1126 // NotifyException() calls this to double check that a watchpoint has occurred
1127 // by inspecting the bits[5:2] field of the Debug Status and Control Register
1128 // (DSCR).
1129 //
1130 // b0010 = a watchpoint occurred
1131 bool
HasWatchpointOccurred()1132 DNBArchMachARM::HasWatchpointOccurred()
1133 {
1134 uint32_t register_DBGDSCR;
1135 asm("mrc p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR));
1136 return (bits(register_DBGDSCR, 5, 2) == WATCHPOINT_OCCURRED);
1137 }
1138
1139 bool
IsWatchpointEnabled(const DBG & debug_state,uint32_t hw_index)1140 DNBArchMachARM::IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index)
1141 {
1142 // Watchpoint Control Registers, bitfield definitions
1143 // ...
1144 // Bits Value Description
1145 // [0] 0 Watchpoint disabled
1146 // 1 Watchpoint enabled.
1147 return (debug_state.__wcr[hw_index] & 1u);
1148 }
1149
1150 nub_addr_t
GetWatchAddress(const DBG & debug_state,uint32_t hw_index)1151 DNBArchMachARM::GetWatchAddress(const DBG &debug_state, uint32_t hw_index)
1152 {
1153 // Watchpoint Value Registers, bitfield definitions
1154 // Bits Description
1155 // [31:2] Watchpoint value (word address, i.e., 4-byte aligned)
1156 // [1:0] RAZ/SBZP
1157 return bits(debug_state.__wvr[hw_index], 31, 0);
1158 }
1159
1160 //----------------------------------------------------------------------
1161 // Register information defintions for 32 bit ARMV7.
1162 //----------------------------------------------------------------------
1163 enum gpr_regnums
1164 {
1165 gpr_r0 = 0,
1166 gpr_r1,
1167 gpr_r2,
1168 gpr_r3,
1169 gpr_r4,
1170 gpr_r5,
1171 gpr_r6,
1172 gpr_r7,
1173 gpr_r8,
1174 gpr_r9,
1175 gpr_r10,
1176 gpr_r11,
1177 gpr_r12,
1178 gpr_sp,
1179 gpr_lr,
1180 gpr_pc,
1181 gpr_cpsr
1182 };
1183
1184 enum
1185 {
1186 vfp_s0 = 17, // match the g_gdb_register_map_arm table in RNBRemote.cpp
1187 vfp_s1,
1188 vfp_s2,
1189 vfp_s3,
1190 vfp_s4,
1191 vfp_s5,
1192 vfp_s6,
1193 vfp_s7,
1194 vfp_s8,
1195 vfp_s9,
1196 vfp_s10,
1197 vfp_s11,
1198 vfp_s12,
1199 vfp_s13,
1200 vfp_s14,
1201 vfp_s15,
1202 vfp_s16,
1203 vfp_s17,
1204 vfp_s18,
1205 vfp_s19,
1206 vfp_s20,
1207 vfp_s21,
1208 vfp_s22,
1209 vfp_s23,
1210 vfp_s24,
1211 vfp_s25,
1212 vfp_s26,
1213 vfp_s27,
1214 vfp_s28,
1215 vfp_s29,
1216 vfp_s30,
1217 vfp_s31
1218 };
1219
1220 enum
1221 {
1222 vfp_d0 = 49, // match the g_gdb_register_map_arm table in RNBRemote.cpp
1223 vfp_d1,
1224 vfp_d2,
1225 vfp_d3,
1226 vfp_d4,
1227 vfp_d5,
1228 vfp_d6,
1229 vfp_d7,
1230 vfp_d8,
1231 vfp_d9,
1232 vfp_d10,
1233 vfp_d11,
1234 vfp_d12,
1235 vfp_d13,
1236 vfp_d14,
1237 vfp_d15,
1238 vfp_d16,
1239 vfp_d17,
1240 vfp_d18,
1241 vfp_d19,
1242 vfp_d20,
1243 vfp_d21,
1244 vfp_d22,
1245 vfp_d23,
1246 vfp_d24,
1247 vfp_d25,
1248 vfp_d26,
1249 vfp_d27,
1250 vfp_d28,
1251 vfp_d29,
1252 vfp_d30,
1253 vfp_d31
1254 };
1255
1256 enum
1257 {
1258 vfp_q0 = 81, // match the g_gdb_register_map_arm table in RNBRemote.cpp
1259 vfp_q1,
1260 vfp_q2,
1261 vfp_q3,
1262 vfp_q4,
1263 vfp_q5,
1264 vfp_q6,
1265 vfp_q7,
1266 vfp_q8,
1267 vfp_q9,
1268 vfp_q10,
1269 vfp_q11,
1270 vfp_q12,
1271 vfp_q13,
1272 vfp_q14,
1273 vfp_q15,
1274 vfp_fpscr
1275 };
1276
1277 enum
1278 {
1279 exc_exception,
1280 exc_fsr,
1281 exc_far,
1282 };
1283
1284 #define GPR_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::GPR, __r[idx]))
1285 #define GPR_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::GPR, __##reg))
1286
1287 #define EXC_OFFSET(reg) (offsetof (DNBArchMachARM::EXC, __##reg) + offsetof (DNBArchMachARM::Context, exc))
1288
1289 // These macros will auto define the register name, alt name, register size,
1290 // register offset, encoding, format and native register. This ensures that
1291 // the register state structures are defined correctly and have the correct
1292 // sizes and offsets.
1293 #define DEFINE_GPR_IDX(idx, reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_IDX(idx), gcc_##reg, dwarf_##reg, gen, INVALID_NUB_REGNUM, NULL, NULL}
1294 #define DEFINE_GPR_NAME(reg, alt, gen, inval) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_NAME(reg), gcc_##reg, dwarf_##reg, gen, INVALID_NUB_REGNUM, NULL, inval}
1295
1296 // In case we are debugging to a debug target that the ability to
1297 // change into the protected modes with folded registers (ABT, IRQ,
1298 // FIQ, SYS, USR, etc..), we should invalidate r8-r14 if the CPSR
1299 // gets modified.
1300
1301 uint32_t g_invalidate_cpsr[] = {
1302 gpr_r8,
1303 gpr_r9,
1304 gpr_r10,
1305 gpr_r11,
1306 gpr_r12,
1307 gpr_sp,
1308 gpr_lr,
1309 INVALID_NUB_REGNUM };
1310
1311 // General purpose registers
1312 const DNBRegisterInfo
1313 DNBArchMachARM::g_gpr_registers[] =
1314 {
1315 DEFINE_GPR_IDX ( 0, r0,"arg1", GENERIC_REGNUM_ARG1 ),
1316 DEFINE_GPR_IDX ( 1, r1,"arg2", GENERIC_REGNUM_ARG2 ),
1317 DEFINE_GPR_IDX ( 2, r2,"arg3", GENERIC_REGNUM_ARG3 ),
1318 DEFINE_GPR_IDX ( 3, r3,"arg4", GENERIC_REGNUM_ARG4 ),
1319 DEFINE_GPR_IDX ( 4, r4, NULL, INVALID_NUB_REGNUM ),
1320 DEFINE_GPR_IDX ( 5, r5, NULL, INVALID_NUB_REGNUM ),
1321 DEFINE_GPR_IDX ( 6, r6, NULL, INVALID_NUB_REGNUM ),
1322 DEFINE_GPR_IDX ( 7, r7, "fp", GENERIC_REGNUM_FP ),
1323 DEFINE_GPR_IDX ( 8, r8, NULL, INVALID_NUB_REGNUM ),
1324 DEFINE_GPR_IDX ( 9, r9, NULL, INVALID_NUB_REGNUM ),
1325 DEFINE_GPR_IDX (10, r10, NULL, INVALID_NUB_REGNUM ),
1326 DEFINE_GPR_IDX (11, r11, NULL, INVALID_NUB_REGNUM ),
1327 DEFINE_GPR_IDX (12, r12, NULL, INVALID_NUB_REGNUM ),
1328 DEFINE_GPR_NAME (sp, "r13", GENERIC_REGNUM_SP, NULL),
1329 DEFINE_GPR_NAME (lr, "r14", GENERIC_REGNUM_RA, NULL),
1330 DEFINE_GPR_NAME (pc, "r15", GENERIC_REGNUM_PC, NULL),
1331 DEFINE_GPR_NAME (cpsr, "flags", GENERIC_REGNUM_FLAGS, g_invalidate_cpsr)
1332 };
1333
1334 uint32_t g_contained_q0[] {vfp_q0, INVALID_NUB_REGNUM };
1335 uint32_t g_contained_q1[] {vfp_q1, INVALID_NUB_REGNUM };
1336 uint32_t g_contained_q2[] {vfp_q2, INVALID_NUB_REGNUM };
1337 uint32_t g_contained_q3[] {vfp_q3, INVALID_NUB_REGNUM };
1338 uint32_t g_contained_q4[] {vfp_q4, INVALID_NUB_REGNUM };
1339 uint32_t g_contained_q5[] {vfp_q5, INVALID_NUB_REGNUM };
1340 uint32_t g_contained_q6[] {vfp_q6, INVALID_NUB_REGNUM };
1341 uint32_t g_contained_q7[] {vfp_q7, INVALID_NUB_REGNUM };
1342 uint32_t g_contained_q8[] {vfp_q8, INVALID_NUB_REGNUM };
1343 uint32_t g_contained_q9[] {vfp_q9, INVALID_NUB_REGNUM };
1344 uint32_t g_contained_q10[] {vfp_q10, INVALID_NUB_REGNUM };
1345 uint32_t g_contained_q11[] {vfp_q11, INVALID_NUB_REGNUM };
1346 uint32_t g_contained_q12[] {vfp_q12, INVALID_NUB_REGNUM };
1347 uint32_t g_contained_q13[] {vfp_q13, INVALID_NUB_REGNUM };
1348 uint32_t g_contained_q14[] {vfp_q14, INVALID_NUB_REGNUM };
1349 uint32_t g_contained_q15[] {vfp_q15, INVALID_NUB_REGNUM };
1350
1351 uint32_t g_invalidate_q0[] {vfp_q0, vfp_d0, vfp_d1, vfp_s0, vfp_s1, vfp_s2, vfp_s3, INVALID_NUB_REGNUM };
1352 uint32_t g_invalidate_q1[] {vfp_q1, vfp_d2, vfp_d3, vfp_s4, vfp_s5, vfp_s6, vfp_s7, INVALID_NUB_REGNUM };
1353 uint32_t g_invalidate_q2[] {vfp_q2, vfp_d4, vfp_d5, vfp_s8, vfp_s9, vfp_s10, vfp_s11, INVALID_NUB_REGNUM };
1354 uint32_t g_invalidate_q3[] {vfp_q3, vfp_d6, vfp_d7, vfp_s12, vfp_s13, vfp_s14, vfp_s15, INVALID_NUB_REGNUM };
1355 uint32_t g_invalidate_q4[] {vfp_q4, vfp_d8, vfp_d9, vfp_s16, vfp_s17, vfp_s18, vfp_s19, INVALID_NUB_REGNUM };
1356 uint32_t g_invalidate_q5[] {vfp_q5, vfp_d10, vfp_d11, vfp_s20, vfp_s21, vfp_s22, vfp_s23, INVALID_NUB_REGNUM };
1357 uint32_t g_invalidate_q6[] {vfp_q6, vfp_d12, vfp_d13, vfp_s24, vfp_s25, vfp_s26, vfp_s27, INVALID_NUB_REGNUM };
1358 uint32_t g_invalidate_q7[] {vfp_q7, vfp_d14, vfp_d15, vfp_s28, vfp_s29, vfp_s30, vfp_s31, INVALID_NUB_REGNUM };
1359 uint32_t g_invalidate_q8[] {vfp_q8, vfp_d16, vfp_d17, INVALID_NUB_REGNUM };
1360 uint32_t g_invalidate_q9[] {vfp_q9, vfp_d18, vfp_d19, INVALID_NUB_REGNUM };
1361 uint32_t g_invalidate_q10[] {vfp_q10, vfp_d20, vfp_d21, INVALID_NUB_REGNUM };
1362 uint32_t g_invalidate_q11[] {vfp_q11, vfp_d22, vfp_d23, INVALID_NUB_REGNUM };
1363 uint32_t g_invalidate_q12[] {vfp_q12, vfp_d24, vfp_d25, INVALID_NUB_REGNUM };
1364 uint32_t g_invalidate_q13[] {vfp_q13, vfp_d26, vfp_d27, INVALID_NUB_REGNUM };
1365 uint32_t g_invalidate_q14[] {vfp_q14, vfp_d28, vfp_d29, INVALID_NUB_REGNUM };
1366 uint32_t g_invalidate_q15[] {vfp_q15, vfp_d30, vfp_d31, INVALID_NUB_REGNUM };
1367
1368 #define VFP_S_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::FPU, __r[(idx)]) + offsetof (DNBArchMachARM::Context, vfp))
1369 #define VFP_D_OFFSET_IDX(idx) (VFP_S_OFFSET_IDX ((idx) * 2))
1370 #define VFP_Q_OFFSET_IDX(idx) (VFP_S_OFFSET_IDX ((idx) * 4))
1371
1372 #define VFP_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::FPU, __##reg) + offsetof (DNBArchMachARM::Context, vfp))
1373
1374 #define FLOAT_FORMAT Float
1375
1376 #define DEFINE_VFP_S_IDX(idx) e_regSetVFP, vfp_s##idx - vfp_s0, "s" #idx, NULL, IEEE754, FLOAT_FORMAT, 4, VFP_S_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_s##idx, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM
1377 #define DEFINE_VFP_D_IDX(idx) e_regSetVFP, vfp_d##idx - vfp_s0, "d" #idx, NULL, IEEE754, FLOAT_FORMAT, 8, VFP_D_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_d##idx, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM
1378 #define DEFINE_VFP_Q_IDX(idx) e_regSetVFP, vfp_q##idx - vfp_s0, "q" #idx, NULL, Vector, VectorOfUInt8, 16, VFP_Q_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_q##idx, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM
1379
1380 // Floating point registers
1381 const DNBRegisterInfo
1382 DNBArchMachARM::g_vfp_registers[] =
1383 {
1384 { DEFINE_VFP_S_IDX ( 0), g_contained_q0, g_invalidate_q0 },
1385 { DEFINE_VFP_S_IDX ( 1), g_contained_q0, g_invalidate_q0 },
1386 { DEFINE_VFP_S_IDX ( 2), g_contained_q0, g_invalidate_q0 },
1387 { DEFINE_VFP_S_IDX ( 3), g_contained_q0, g_invalidate_q0 },
1388 { DEFINE_VFP_S_IDX ( 4), g_contained_q1, g_invalidate_q1 },
1389 { DEFINE_VFP_S_IDX ( 5), g_contained_q1, g_invalidate_q1 },
1390 { DEFINE_VFP_S_IDX ( 6), g_contained_q1, g_invalidate_q1 },
1391 { DEFINE_VFP_S_IDX ( 7), g_contained_q1, g_invalidate_q1 },
1392 { DEFINE_VFP_S_IDX ( 8), g_contained_q2, g_invalidate_q2 },
1393 { DEFINE_VFP_S_IDX ( 9), g_contained_q2, g_invalidate_q2 },
1394 { DEFINE_VFP_S_IDX (10), g_contained_q2, g_invalidate_q2 },
1395 { DEFINE_VFP_S_IDX (11), g_contained_q2, g_invalidate_q2 },
1396 { DEFINE_VFP_S_IDX (12), g_contained_q3, g_invalidate_q3 },
1397 { DEFINE_VFP_S_IDX (13), g_contained_q3, g_invalidate_q3 },
1398 { DEFINE_VFP_S_IDX (14), g_contained_q3, g_invalidate_q3 },
1399 { DEFINE_VFP_S_IDX (15), g_contained_q3, g_invalidate_q3 },
1400 { DEFINE_VFP_S_IDX (16), g_contained_q4, g_invalidate_q4 },
1401 { DEFINE_VFP_S_IDX (17), g_contained_q4, g_invalidate_q4 },
1402 { DEFINE_VFP_S_IDX (18), g_contained_q4, g_invalidate_q4 },
1403 { DEFINE_VFP_S_IDX (19), g_contained_q4, g_invalidate_q4 },
1404 { DEFINE_VFP_S_IDX (20), g_contained_q5, g_invalidate_q5 },
1405 { DEFINE_VFP_S_IDX (21), g_contained_q5, g_invalidate_q5 },
1406 { DEFINE_VFP_S_IDX (22), g_contained_q5, g_invalidate_q5 },
1407 { DEFINE_VFP_S_IDX (23), g_contained_q5, g_invalidate_q5 },
1408 { DEFINE_VFP_S_IDX (24), g_contained_q6, g_invalidate_q6 },
1409 { DEFINE_VFP_S_IDX (25), g_contained_q6, g_invalidate_q6 },
1410 { DEFINE_VFP_S_IDX (26), g_contained_q6, g_invalidate_q6 },
1411 { DEFINE_VFP_S_IDX (27), g_contained_q6, g_invalidate_q6 },
1412 { DEFINE_VFP_S_IDX (28), g_contained_q7, g_invalidate_q7 },
1413 { DEFINE_VFP_S_IDX (29), g_contained_q7, g_invalidate_q7 },
1414 { DEFINE_VFP_S_IDX (30), g_contained_q7, g_invalidate_q7 },
1415 { DEFINE_VFP_S_IDX (31), g_contained_q7, g_invalidate_q7 },
1416
1417 { DEFINE_VFP_D_IDX (0), g_contained_q0, g_invalidate_q0 },
1418 { DEFINE_VFP_D_IDX (1), g_contained_q0, g_invalidate_q0 },
1419 { DEFINE_VFP_D_IDX (2), g_contained_q1, g_invalidate_q1 },
1420 { DEFINE_VFP_D_IDX (3), g_contained_q1, g_invalidate_q1 },
1421 { DEFINE_VFP_D_IDX (4), g_contained_q2, g_invalidate_q2 },
1422 { DEFINE_VFP_D_IDX (5), g_contained_q2, g_invalidate_q2 },
1423 { DEFINE_VFP_D_IDX (6), g_contained_q3, g_invalidate_q3 },
1424 { DEFINE_VFP_D_IDX (7), g_contained_q3, g_invalidate_q3 },
1425 { DEFINE_VFP_D_IDX (8), g_contained_q4, g_invalidate_q4 },
1426 { DEFINE_VFP_D_IDX (9), g_contained_q4, g_invalidate_q4 },
1427 { DEFINE_VFP_D_IDX (10), g_contained_q5, g_invalidate_q5 },
1428 { DEFINE_VFP_D_IDX (11), g_contained_q5, g_invalidate_q5 },
1429 { DEFINE_VFP_D_IDX (12), g_contained_q6, g_invalidate_q6 },
1430 { DEFINE_VFP_D_IDX (13), g_contained_q6, g_invalidate_q6 },
1431 { DEFINE_VFP_D_IDX (14), g_contained_q7, g_invalidate_q7 },
1432 { DEFINE_VFP_D_IDX (15), g_contained_q7, g_invalidate_q7 },
1433 { DEFINE_VFP_D_IDX (16), g_contained_q8, g_invalidate_q8 },
1434 { DEFINE_VFP_D_IDX (17), g_contained_q8, g_invalidate_q8 },
1435 { DEFINE_VFP_D_IDX (18), g_contained_q9, g_invalidate_q9 },
1436 { DEFINE_VFP_D_IDX (19), g_contained_q9, g_invalidate_q9 },
1437 { DEFINE_VFP_D_IDX (20), g_contained_q10, g_invalidate_q10 },
1438 { DEFINE_VFP_D_IDX (21), g_contained_q10, g_invalidate_q10 },
1439 { DEFINE_VFP_D_IDX (22), g_contained_q11, g_invalidate_q11 },
1440 { DEFINE_VFP_D_IDX (23), g_contained_q11, g_invalidate_q11 },
1441 { DEFINE_VFP_D_IDX (24), g_contained_q12, g_invalidate_q12 },
1442 { DEFINE_VFP_D_IDX (25), g_contained_q12, g_invalidate_q12 },
1443 { DEFINE_VFP_D_IDX (26), g_contained_q13, g_invalidate_q13 },
1444 { DEFINE_VFP_D_IDX (27), g_contained_q13, g_invalidate_q13 },
1445 { DEFINE_VFP_D_IDX (28), g_contained_q14, g_invalidate_q14 },
1446 { DEFINE_VFP_D_IDX (29), g_contained_q14, g_invalidate_q14 },
1447 { DEFINE_VFP_D_IDX (30), g_contained_q15, g_invalidate_q15 },
1448 { DEFINE_VFP_D_IDX (31), g_contained_q15, g_invalidate_q15 },
1449
1450 { DEFINE_VFP_Q_IDX (0), NULL, g_invalidate_q0 },
1451 { DEFINE_VFP_Q_IDX (1), NULL, g_invalidate_q1 },
1452 { DEFINE_VFP_Q_IDX (2), NULL, g_invalidate_q2 },
1453 { DEFINE_VFP_Q_IDX (3), NULL, g_invalidate_q3 },
1454 { DEFINE_VFP_Q_IDX (4), NULL, g_invalidate_q4 },
1455 { DEFINE_VFP_Q_IDX (5), NULL, g_invalidate_q5 },
1456 { DEFINE_VFP_Q_IDX (6), NULL, g_invalidate_q6 },
1457 { DEFINE_VFP_Q_IDX (7), NULL, g_invalidate_q7 },
1458 { DEFINE_VFP_Q_IDX (8), NULL, g_invalidate_q8 },
1459 { DEFINE_VFP_Q_IDX (9), NULL, g_invalidate_q9 },
1460 { DEFINE_VFP_Q_IDX (10), NULL, g_invalidate_q10 },
1461 { DEFINE_VFP_Q_IDX (11), NULL, g_invalidate_q11 },
1462 { DEFINE_VFP_Q_IDX (12), NULL, g_invalidate_q12 },
1463 { DEFINE_VFP_Q_IDX (13), NULL, g_invalidate_q13 },
1464 { DEFINE_VFP_Q_IDX (14), NULL, g_invalidate_q14 },
1465 { DEFINE_VFP_Q_IDX (15), NULL, g_invalidate_q15 },
1466
1467 { e_regSetVFP, vfp_fpscr, "fpscr", NULL, Uint, Hex, 4, VFP_OFFSET_NAME(fpscr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }
1468 };
1469
1470 // Exception registers
1471
1472 const DNBRegisterInfo
1473 DNBArchMachARM::g_exc_registers[] =
1474 {
1475 { e_regSetVFP, exc_exception , "exception" , NULL, Uint, Hex, 4, EXC_OFFSET(exception) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM },
1476 { e_regSetVFP, exc_fsr , "fsr" , NULL, Uint, Hex, 4, EXC_OFFSET(fsr) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM },
1477 { e_regSetVFP, exc_far , "far" , NULL, Uint, Hex, 4, EXC_OFFSET(far) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM }
1478 };
1479
1480 // Number of registers in each register set
1481 const size_t DNBArchMachARM::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo);
1482 const size_t DNBArchMachARM::k_num_vfp_registers = sizeof(g_vfp_registers)/sizeof(DNBRegisterInfo);
1483 const size_t DNBArchMachARM::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo);
1484 const size_t DNBArchMachARM::k_num_all_registers = k_num_gpr_registers + k_num_vfp_registers + k_num_exc_registers;
1485
1486 //----------------------------------------------------------------------
1487 // Register set definitions. The first definitions at register set index
1488 // of zero is for all registers, followed by other registers sets. The
1489 // register information for the all register set need not be filled in.
1490 //----------------------------------------------------------------------
1491 const DNBRegisterSetInfo
1492 DNBArchMachARM::g_reg_sets[] =
1493 {
1494 { "ARM Registers", NULL, k_num_all_registers },
1495 { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers },
1496 { "Floating Point Registers", g_vfp_registers, k_num_vfp_registers },
1497 { "Exception State Registers", g_exc_registers, k_num_exc_registers }
1498 };
1499 // Total number of register sets for this architecture
1500 const size_t DNBArchMachARM::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo);
1501
1502
1503 const DNBRegisterSetInfo *
GetRegisterSetInfo(nub_size_t * num_reg_sets)1504 DNBArchMachARM::GetRegisterSetInfo(nub_size_t *num_reg_sets)
1505 {
1506 *num_reg_sets = k_num_register_sets;
1507 return g_reg_sets;
1508 }
1509
1510 bool
GetRegisterValue(int set,int reg,DNBRegisterValue * value)1511 DNBArchMachARM::GetRegisterValue(int set, int reg, DNBRegisterValue *value)
1512 {
1513 if (set == REGISTER_SET_GENERIC)
1514 {
1515 switch (reg)
1516 {
1517 case GENERIC_REGNUM_PC: // Program Counter
1518 set = e_regSetGPR;
1519 reg = gpr_pc;
1520 break;
1521
1522 case GENERIC_REGNUM_SP: // Stack Pointer
1523 set = e_regSetGPR;
1524 reg = gpr_sp;
1525 break;
1526
1527 case GENERIC_REGNUM_FP: // Frame Pointer
1528 set = e_regSetGPR;
1529 reg = gpr_r7; // is this the right reg?
1530 break;
1531
1532 case GENERIC_REGNUM_RA: // Return Address
1533 set = e_regSetGPR;
1534 reg = gpr_lr;
1535 break;
1536
1537 case GENERIC_REGNUM_FLAGS: // Processor flags register
1538 set = e_regSetGPR;
1539 reg = gpr_cpsr;
1540 break;
1541
1542 default:
1543 return false;
1544 }
1545 }
1546
1547 if (GetRegisterState(set, false) != KERN_SUCCESS)
1548 return false;
1549
1550 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
1551 if (regInfo)
1552 {
1553 value->info = *regInfo;
1554 switch (set)
1555 {
1556 case e_regSetGPR:
1557 if (reg < k_num_gpr_registers)
1558 {
1559 value->value.uint32 = m_state.context.gpr.__r[reg];
1560 return true;
1561 }
1562 break;
1563
1564 case e_regSetVFP:
1565 // "reg" is an index into the floating point register set at this point.
1566 // We need to translate it up so entry 0 in the fp reg set is the same as vfp_s0
1567 // in the enumerated values for case statement below.
1568 reg += vfp_s0;
1569 if (reg >= vfp_s0 && reg <= vfp_s31)
1570 {
1571 value->value.uint32 = m_state.context.vfp.__r[reg - vfp_s0];
1572 return true;
1573 }
1574 else if (reg >= vfp_d0 && reg <= vfp_d31)
1575 {
1576 uint32_t d_reg_idx = reg - vfp_d0;
1577 uint32_t s_reg_idx = d_reg_idx * 2;
1578 value->value.v_sint32[0] = m_state.context.vfp.__r[s_reg_idx + 0];
1579 value->value.v_sint32[1] = m_state.context.vfp.__r[s_reg_idx + 1];
1580 return true;
1581 }
1582 else if (reg >= vfp_q0 && reg <= vfp_q15)
1583 {
1584 uint32_t s_reg_idx = (reg - vfp_q0) * 4;
1585 memcpy (&value->value.v_uint8, (uint8_t *) &m_state.context.vfp.__r[s_reg_idx], 16);
1586 return true;
1587 }
1588
1589 else if (reg == vfp_fpscr)
1590 {
1591 value->value.uint32 = m_state.context.vfp.__fpscr;
1592 return true;
1593 }
1594 break;
1595
1596 case e_regSetEXC:
1597 if (reg < k_num_exc_registers)
1598 {
1599 value->value.uint32 = (&m_state.context.exc.__exception)[reg];
1600 return true;
1601 }
1602 break;
1603 }
1604 }
1605 return false;
1606 }
1607
1608 bool
SetRegisterValue(int set,int reg,const DNBRegisterValue * value)1609 DNBArchMachARM::SetRegisterValue(int set, int reg, const DNBRegisterValue *value)
1610 {
1611 if (set == REGISTER_SET_GENERIC)
1612 {
1613 switch (reg)
1614 {
1615 case GENERIC_REGNUM_PC: // Program Counter
1616 set = e_regSetGPR;
1617 reg = gpr_pc;
1618 break;
1619
1620 case GENERIC_REGNUM_SP: // Stack Pointer
1621 set = e_regSetGPR;
1622 reg = gpr_sp;
1623 break;
1624
1625 case GENERIC_REGNUM_FP: // Frame Pointer
1626 set = e_regSetGPR;
1627 reg = gpr_r7;
1628 break;
1629
1630 case GENERIC_REGNUM_RA: // Return Address
1631 set = e_regSetGPR;
1632 reg = gpr_lr;
1633 break;
1634
1635 case GENERIC_REGNUM_FLAGS: // Processor flags register
1636 set = e_regSetGPR;
1637 reg = gpr_cpsr;
1638 break;
1639
1640 default:
1641 return false;
1642 }
1643 }
1644
1645 if (GetRegisterState(set, false) != KERN_SUCCESS)
1646 return false;
1647
1648 bool success = false;
1649 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
1650 if (regInfo)
1651 {
1652 switch (set)
1653 {
1654 case e_regSetGPR:
1655 if (reg < k_num_gpr_registers)
1656 {
1657 m_state.context.gpr.__r[reg] = value->value.uint32;
1658 success = true;
1659 }
1660 break;
1661
1662 case e_regSetVFP:
1663 // "reg" is an index into the floating point register set at this point.
1664 // We need to translate it up so entry 0 in the fp reg set is the same as vfp_s0
1665 // in the enumerated values for case statement below.
1666 reg += vfp_s0;
1667
1668 if (reg >= vfp_s0 && reg <= vfp_s31)
1669 {
1670 m_state.context.vfp.__r[reg - vfp_s0] = value->value.uint32;
1671 success = true;
1672 }
1673 else if (reg >= vfp_d0 && reg <= vfp_d31)
1674 {
1675 uint32_t d_reg_idx = reg - vfp_d0;
1676 uint32_t s_reg_idx = d_reg_idx * 2;
1677 m_state.context.vfp.__r[s_reg_idx + 0] = value->value.v_sint32[0];
1678 m_state.context.vfp.__r[s_reg_idx + 1] = value->value.v_sint32[1];
1679 success = true;
1680 }
1681 else if (reg >= vfp_q0 && reg <= vfp_q15)
1682 {
1683 uint32_t s_reg_idx = (reg - vfp_q0) * 4;
1684 memcpy ((uint8_t *) &m_state.context.vfp.__r[s_reg_idx], &value->value.v_uint8, 16);
1685 return true;
1686 }
1687 else if (reg == vfp_fpscr)
1688 {
1689 m_state.context.vfp.__fpscr = value->value.uint32;
1690 success = true;
1691 }
1692 break;
1693
1694 case e_regSetEXC:
1695 if (reg < k_num_exc_registers)
1696 {
1697 (&m_state.context.exc.__exception)[reg] = value->value.uint32;
1698 success = true;
1699 }
1700 break;
1701 }
1702
1703 }
1704 if (success)
1705 return SetRegisterState(set) == KERN_SUCCESS;
1706 return false;
1707 }
1708
1709 kern_return_t
GetRegisterState(int set,bool force)1710 DNBArchMachARM::GetRegisterState(int set, bool force)
1711 {
1712 switch (set)
1713 {
1714 case e_regSetALL: return GetGPRState(force) |
1715 GetVFPState(force) |
1716 GetEXCState(force) |
1717 GetDBGState(force);
1718 case e_regSetGPR: return GetGPRState(force);
1719 case e_regSetVFP: return GetVFPState(force);
1720 case e_regSetEXC: return GetEXCState(force);
1721 case e_regSetDBG: return GetDBGState(force);
1722 default: break;
1723 }
1724 return KERN_INVALID_ARGUMENT;
1725 }
1726
1727 kern_return_t
SetRegisterState(int set)1728 DNBArchMachARM::SetRegisterState(int set)
1729 {
1730 // Make sure we have a valid context to set.
1731 kern_return_t err = GetRegisterState(set, false);
1732 if (err != KERN_SUCCESS)
1733 return err;
1734
1735 switch (set)
1736 {
1737 case e_regSetALL: return SetGPRState() |
1738 SetVFPState() |
1739 SetEXCState() |
1740 SetDBGState(false);
1741 case e_regSetGPR: return SetGPRState();
1742 case e_regSetVFP: return SetVFPState();
1743 case e_regSetEXC: return SetEXCState();
1744 case e_regSetDBG: return SetDBGState(false);
1745 default: break;
1746 }
1747 return KERN_INVALID_ARGUMENT;
1748 }
1749
1750 bool
RegisterSetStateIsValid(int set) const1751 DNBArchMachARM::RegisterSetStateIsValid (int set) const
1752 {
1753 return m_state.RegsAreValid(set);
1754 }
1755
1756
1757 nub_size_t
GetRegisterContext(void * buf,nub_size_t buf_len)1758 DNBArchMachARM::GetRegisterContext (void *buf, nub_size_t buf_len)
1759 {
1760 nub_size_t size = sizeof (m_state.context);
1761
1762 if (buf && buf_len)
1763 {
1764 if (size > buf_len)
1765 size = buf_len;
1766
1767 bool force = false;
1768 if (GetGPRState(force) | GetVFPState(force) | GetEXCState(force))
1769 return 0;
1770 ::memcpy (buf, &m_state.context, size);
1771 }
1772 DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::GetRegisterContext (buf = %p, len = %llu) => %llu", buf, (uint64_t)buf_len, (uint64_t)size);
1773 // Return the size of the register context even if NULL was passed in
1774 return size;
1775 }
1776
1777 nub_size_t
SetRegisterContext(const void * buf,nub_size_t buf_len)1778 DNBArchMachARM::SetRegisterContext (const void *buf, nub_size_t buf_len)
1779 {
1780 nub_size_t size = sizeof (m_state.context);
1781 if (buf == NULL || buf_len == 0)
1782 size = 0;
1783
1784 if (size)
1785 {
1786 if (size > buf_len)
1787 size = buf_len;
1788
1789 ::memcpy (&m_state.context, buf, size);
1790 SetGPRState();
1791 SetVFPState();
1792 SetEXCState();
1793 }
1794 DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::SetRegisterContext (buf = %p, len = %llu) => %llu", buf, (uint64_t)buf_len, (uint64_t)size);
1795 return size;
1796 }
1797
1798
1799 #endif // #if defined (__arm__)
1800
1801