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