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
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 
122     // When new thread comes along, it tries to inherit from the global debug state, if it is valid.
123     if (Valid_Global_Debug_State)
124     {
125         obj->m_state.dbg = Global_Debug_State;
126         kern_return_t kret = obj->SetDBGState();
127         DNBLogThreadedIf(LOG_WATCHPOINTS,
128                          "DNBArchMachARM::Create() Inherit and SetDBGState() => 0x%8.8x.", kret);
129     }
130     return obj;
131 }
132 
133 const uint8_t * const
134 DNBArchMachARM::SoftwareBreakpointOpcode (nub_size_t byte_size)
135 {
136     switch (byte_size)
137     {
138     case 2: return g_thumb_breakpooint_opcode;
139     case 4: return g_arm_breakpoint_opcode;
140     }
141     return NULL;
142 }
143 
144 uint32_t
145 DNBArchMachARM::GetCPUType()
146 {
147     return CPU_TYPE_ARM;
148 }
149 
150 uint64_t
151 DNBArchMachARM::GetPC(uint64_t failValue)
152 {
153     // Get program counter
154     if (GetGPRState(false) == KERN_SUCCESS)
155         return m_state.context.gpr.__pc;
156     return failValue;
157 }
158 
159 kern_return_t
160 DNBArchMachARM::SetPC(uint64_t value)
161 {
162     // Get program counter
163     kern_return_t err = GetGPRState(false);
164     if (err == KERN_SUCCESS)
165     {
166         m_state.context.gpr.__pc = value;
167         err = SetGPRState();
168     }
169     return err == KERN_SUCCESS;
170 }
171 
172 uint64_t
173 DNBArchMachARM::GetSP(uint64_t failValue)
174 {
175     // Get stack pointer
176     if (GetGPRState(false) == KERN_SUCCESS)
177         return m_state.context.gpr.__sp;
178     return failValue;
179 }
180 
181 kern_return_t
182 DNBArchMachARM::GetGPRState(bool force)
183 {
184     int set = e_regSetGPR;
185     // Check if we have valid cached registers
186     if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
187         return KERN_SUCCESS;
188 
189     // Read the registers from our thread
190     mach_msg_type_number_t count = ARM_THREAD_STATE_COUNT;
191     kern_return_t kret = ::thread_get_state(m_thread->ThreadID(), ARM_THREAD_STATE, (thread_state_t)&m_state.context.gpr, &count);
192     uint32_t *r = &m_state.context.gpr.__r[0];
193     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",
194                      m_thread->ThreadID(),
195                      ARM_THREAD_STATE,
196                      ARM_THREAD_STATE_COUNT,
197                      kret,
198                      count,
199                      r[0],
200                      r[1],
201                      r[2],
202                      r[3],
203                      r[4],
204                      r[5],
205                      r[6],
206                      r[7],
207                      r[8],
208                      r[9],
209                      r[10],
210                      r[11],
211                      r[12],
212                      r[13],
213                      r[14],
214                      r[15],
215                      r[16]);
216     m_state.SetError(set, Read, kret);
217     return kret;
218 }
219 
220 kern_return_t
221 DNBArchMachARM::GetVFPState(bool force)
222 {
223     int set = e_regSetVFP;
224     // Check if we have valid cached registers
225     if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
226         return KERN_SUCCESS;
227 
228     // Read the registers from our thread
229     mach_msg_type_number_t count = ARM_VFP_STATE_COUNT;
230     kern_return_t kret = ::thread_get_state(m_thread->ThreadID(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, &count);
231     if (DNBLogEnabledForAny (LOG_THREAD))
232     {
233         uint32_t *r = &m_state.context.vfp.__r[0];
234         DNBLogThreaded ("thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count => %u)",
235                         m_thread->ThreadID(),
236                         ARM_THREAD_STATE,
237                         ARM_THREAD_STATE_COUNT,
238                         kret,
239                         count);
240         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]);
241         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]);
242         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]);
243         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]);
244         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]);
245         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]);
246         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]);
247         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]);
248     }
249     m_state.SetError(set, Read, kret);
250     return kret;
251 }
252 
253 kern_return_t
254 DNBArchMachARM::GetEXCState(bool force)
255 {
256     int set = e_regSetEXC;
257     // Check if we have valid cached registers
258     if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
259         return KERN_SUCCESS;
260 
261     // Read the registers from our thread
262     mach_msg_type_number_t count = ARM_EXCEPTION_STATE_COUNT;
263     kern_return_t kret = ::thread_get_state(m_thread->ThreadID(), ARM_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, &count);
264     m_state.SetError(set, Read, kret);
265     return kret;
266 }
267 
268 static void
269 DumpDBGState(const DNBArchMachARM::DBG& dbg)
270 {
271     uint32_t i = 0;
272     for (i=0; i<16; i++) {
273         DNBLogThreadedIf(LOG_STEP, "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }",
274             i, i, dbg.__bvr[i], dbg.__bcr[i],
275             i, i, dbg.__wvr[i], dbg.__wcr[i]);
276     }
277 }
278 
279 kern_return_t
280 DNBArchMachARM::GetDBGState(bool force)
281 {
282     int set = e_regSetDBG;
283 
284     // Check if we have valid cached registers
285     if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
286         return KERN_SUCCESS;
287 
288     // Read the registers from our thread
289     mach_msg_type_number_t count = ARM_DEBUG_STATE_COUNT;
290     kern_return_t kret = ::thread_get_state(m_thread->ThreadID(), ARM_DEBUG_STATE, (thread_state_t)&m_state.dbg, &count);
291     m_state.SetError(set, Read, kret);
292     return kret;
293 }
294 
295 kern_return_t
296 DNBArchMachARM::SetGPRState()
297 {
298     int set = e_regSetGPR;
299     kern_return_t kret = ::thread_set_state(m_thread->ThreadID(), ARM_THREAD_STATE, (thread_state_t)&m_state.context.gpr, ARM_THREAD_STATE_COUNT);
300     m_state.SetError(set, Write, kret);         // Set the current write error for this register set
301     m_state.InvalidateRegisterSetState(set);    // Invalidate the current register state in case registers are read back differently
302     return kret;                                // Return the error code
303 }
304 
305 kern_return_t
306 DNBArchMachARM::SetVFPState()
307 {
308     int set = e_regSetVFP;
309     kern_return_t kret = ::thread_set_state (m_thread->ThreadID(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, ARM_VFP_STATE_COUNT);
310     m_state.SetError(set, Write, kret);         // Set the current write error for this register set
311     m_state.InvalidateRegisterSetState(set);    // Invalidate the current register state in case registers are read back differently
312     return kret;                                // Return the error code
313 }
314 
315 kern_return_t
316 DNBArchMachARM::SetEXCState()
317 {
318     int set = e_regSetEXC;
319     kern_return_t kret = ::thread_set_state (m_thread->ThreadID(), ARM_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, ARM_EXCEPTION_STATE_COUNT);
320     m_state.SetError(set, Write, kret);         // Set the current write error for this register set
321     m_state.InvalidateRegisterSetState(set);    // Invalidate the current register state in case registers are read back differently
322     return kret;                                // Return the error code
323 }
324 
325 kern_return_t
326 DNBArchMachARM::SetDBGState()
327 {
328     int set = e_regSetDBG;
329     kern_return_t kret = ::thread_set_state (m_thread->ThreadID(), ARM_DEBUG_STATE, (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE_COUNT);
330     m_state.SetError(set, Write, kret);         // Set the current write error for this register set
331     m_state.InvalidateRegisterSetState(set);    // Invalidate the current register state in case registers are read back differently
332     return kret;                                // Return the error code
333 }
334 
335 void
336 DNBArchMachARM::ThreadWillResume()
337 {
338     // Do we need to step this thread? If so, let the mach thread tell us so.
339     if (m_thread->IsStepping())
340     {
341         // This is the primary thread, let the arch do anything it needs
342         if (NumSupportedHardwareBreakpoints() > 0)
343         {
344             if (EnableHardwareSingleStep(true) != KERN_SUCCESS)
345             {
346                 DNBLogThreaded("DNBArchMachARM::ThreadWillResume() failed to enable hardware single step");
347             }
348         }
349         else
350         {
351             if (SetSingleStepSoftwareBreakpoints() != KERN_SUCCESS)
352             {
353                 DNBLogThreaded("DNBArchMachARM::ThreadWillResume() failed to enable software single step");
354             }
355         }
356     }
357 
358     // Disable the triggered watchpoint temporarily before we resume.
359     // Plus, we try to enable hardware single step to execute past the instruction which triggered our watchpoint.
360     if (m_watchpoint_did_occur)
361     {
362         if (m_watchpoint_hw_index >= 0)
363         {
364             kern_return_t kret = GetDBGState(false);
365             if (kret == KERN_SUCCESS && !IsWatchpointEnabled(m_state.dbg, m_watchpoint_hw_index)) {
366                 // The watchpoint might have been disabled by the user.  We don't need to do anything at all
367                 // to enable hardware single stepping.
368                 m_watchpoint_did_occur = false;
369                 m_watchpoint_hw_index = -1;
370                 return;
371             }
372 
373             DisableHardwareWatchpoint0(m_watchpoint_hw_index, true);
374             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() DisableHardwareWatchpoint(%d) called",
375                              m_watchpoint_hw_index);
376 
377             // Enable hardware single step to move past the watchpoint-triggering instruction.
378             m_watchpoint_resume_single_step_enabled = (EnableHardwareSingleStep(true) == KERN_SUCCESS);
379 
380             // If we are not able to enable single step to move past the watchpoint-triggering instruction,
381             // at least we should reset the two watchpoint member variables so that the next time around
382             // this callback function is invoked, the enclosing logical branch is skipped.
383             if (!m_watchpoint_resume_single_step_enabled) {
384                 // Reset the two watchpoint member variables.
385                 m_watchpoint_did_occur = false;
386                 m_watchpoint_hw_index = -1;
387                 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() failed to enable single step");
388             }
389             else
390                 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() succeeded to enable single step");
391         }
392     }
393 }
394 
395 bool
396 DNBArchMachARM::ThreadDidStop()
397 {
398     bool success = true;
399 
400     m_state.InvalidateRegisterSetState (e_regSetALL);
401 
402     if (m_watchpoint_resume_single_step_enabled)
403     {
404         // Great!  We now disable the hardware single step as well as re-enable the hardware watchpoint.
405         // See also ThreadWillResume().
406         if (EnableHardwareSingleStep(false) == KERN_SUCCESS)
407         {
408             if (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0)
409             {
410                 EnableHardwareWatchpoint0(m_watchpoint_hw_index, true);
411                 m_watchpoint_resume_single_step_enabled = false;
412                 m_watchpoint_did_occur = false;
413                 m_watchpoint_hw_index = -1;
414             }
415             else
416             {
417                 DNBLogError("internal error detected: m_watchpoint_resume_step_enabled is true but (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0) does not hold!");
418             }
419         }
420         else
421         {
422             DNBLogError("internal error detected: m_watchpoint_resume_step_enabled is true but unable to disable single step!");
423         }
424     }
425 
426     // Are we stepping a single instruction?
427     if (GetGPRState(true) == KERN_SUCCESS)
428     {
429         // We are single stepping, was this the primary thread?
430         if (m_thread->IsStepping())
431         {
432             // Are we software single stepping?
433             if (NUB_BREAK_ID_IS_VALID(m_sw_single_step_break_id) || m_sw_single_step_itblock_break_count)
434             {
435                 // Remove any software single stepping breakpoints that we have set
436 
437                 // Do we have a normal software single step breakpoint?
438                 if (NUB_BREAK_ID_IS_VALID(m_sw_single_step_break_id))
439                 {
440                     DNBLogThreadedIf(LOG_STEP, "%s: removing software single step breakpoint (breakID=%d)", __FUNCTION__, m_sw_single_step_break_id);
441                     success = m_thread->Process()->DisableBreakpoint(m_sw_single_step_break_id, true);
442                     m_sw_single_step_break_id = INVALID_NUB_BREAK_ID;
443                 }
444 
445                 // Do we have any Thumb IT breakpoints?
446                 if (m_sw_single_step_itblock_break_count > 0)
447                 {
448                     // See if we hit one of our Thumb IT breakpoints?
449                     DNBBreakpoint *step_bp = m_thread->Process()->Breakpoints().FindByAddress(m_state.context.gpr.__pc);
450 
451                     if (step_bp)
452                     {
453                         // We did hit our breakpoint, tell the breakpoint it was
454                         // hit so that it can run its callback routine and fixup
455                         // the PC.
456                         DNBLogThreadedIf(LOG_STEP, "%s: IT software single step breakpoint hit (breakID=%u)", __FUNCTION__, step_bp->GetID());
457                         step_bp->BreakpointHit(m_thread->Process()->ProcessID(), m_thread->ThreadID());
458                     }
459 
460                     // Remove all Thumb IT breakpoints
461                     for (int i = 0; i < m_sw_single_step_itblock_break_count; i++)
462                     {
463                         if (NUB_BREAK_ID_IS_VALID(m_sw_single_step_itblock_break_id[i]))
464                         {
465                             DNBLogThreadedIf(LOG_STEP, "%s: removing IT software single step breakpoint (breakID=%d)", __FUNCTION__, m_sw_single_step_itblock_break_id[i]);
466                             success = m_thread->Process()->DisableBreakpoint(m_sw_single_step_itblock_break_id[i], true);
467                             m_sw_single_step_itblock_break_id[i] = INVALID_NUB_BREAK_ID;
468                         }
469                     }
470                     m_sw_single_step_itblock_break_count = 0;
471 
472 #if defined (USE_ARM_DISASSEMBLER_FRAMEWORK)
473 
474                     // Decode instructions up to the current PC to ensure the internal decoder state is valid for the IT block
475                     // The decoder has to decode each instruction in the IT block even if it is not executed so that
476                     // the fields are correctly updated
477                     DecodeITBlockInstructions(m_state.context.gpr.__pc);
478 #endif
479                 }
480 
481             }
482             else
483                 success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
484         }
485         else
486         {
487             // The MachThread will automatically restore the suspend count
488             // in ThreadDidStop(), so we don't need to do anything here if
489             // we weren't the primary thread the last time
490         }
491     }
492     return success;
493 }
494 
495 bool
496 DNBArchMachARM::NotifyException(MachException::Data& exc)
497 {
498     switch (exc.exc_type)
499     {
500         default:
501             break;
502         case EXC_BREAKPOINT:
503             if (exc.exc_data.size() == 2 && exc.exc_data[0] == EXC_ARM_DA_DEBUG)
504             {
505                 // exc_code = EXC_ARM_DA_DEBUG
506                 //
507                 // Check whether this corresponds to a watchpoint hit event.
508                 // If yes, retrieve the exc_sub_code as the data break address.
509                 if (!HasWatchpointOccurred())
510                     break;
511 
512                 // The data break address is passed as exc_data[1].
513                 nub_addr_t addr = exc.exc_data[1];
514                 // Find the hardware index with the side effect of possibly massaging the
515                 // addr to return the starting address as seen from the debugger side.
516                 uint32_t hw_index = GetHardwareWatchpointHit(addr);
517                 if (hw_index != INVALID_NUB_HW_INDEX)
518                 {
519                     m_watchpoint_did_occur = true;
520                     m_watchpoint_hw_index = hw_index;
521                     exc.exc_data[1] = addr;
522                     // Piggyback the hw_index in the exc.data.
523                     exc.exc_data.push_back(hw_index);
524                 }
525 
526                 return true;
527             }
528             break;
529     }
530     return false;
531 }
532 
533 bool
534 DNBArchMachARM::StepNotComplete ()
535 {
536     if (m_hw_single_chained_step_addr != INVALID_NUB_ADDRESS)
537     {
538         kern_return_t kret = KERN_INVALID_ARGUMENT;
539         kret = GetGPRState(false);
540         if (kret == KERN_SUCCESS)
541         {
542             if (m_state.context.gpr.__pc == m_hw_single_chained_step_addr)
543             {
544                 DNBLogThreadedIf(LOG_STEP, "Need to step some more at 0x%8.8x", m_hw_single_chained_step_addr);
545                 return true;
546             }
547         }
548     }
549 
550     m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS;
551     return false;
552 }
553 
554 
555 #if defined (USE_ARM_DISASSEMBLER_FRAMEWORK)
556 
557 void
558 DNBArchMachARM::DecodeITBlockInstructions(nub_addr_t curr_pc)
559 
560 {
561     uint16_t opcode16;
562     uint32_t opcode32;
563     nub_addr_t next_pc_in_itblock;
564     nub_addr_t pc_in_itblock = m_last_decode_pc;
565 
566     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: last_decode_pc=0x%8.8x", __FUNCTION__, m_last_decode_pc);
567 
568     // Decode IT block instruction from the instruction following the m_last_decoded_instruction at
569     // PC m_last_decode_pc upto and including the instruction at curr_pc
570     if (m_thread->Process()->Task().ReadMemory(pc_in_itblock, 2, &opcode16) == 2)
571     {
572         opcode32 = opcode16;
573         pc_in_itblock += 2;
574         // Check for 32 bit thumb opcode and read the upper 16 bits if needed
575         if (((opcode32 & 0xE000) == 0xE000) && opcode32 & 0x1800)
576         {
577             // Adjust 'next_pc_in_itblock' to point to the default next Thumb instruction for
578             // a 32 bit Thumb opcode
579             // Read bits 31:16 of a 32 bit Thumb opcode
580             if (m_thread->Process()->Task().ReadMemory(pc_in_itblock, 2, &opcode16) == 2)
581             {
582                 pc_in_itblock += 2;
583                 // 32 bit thumb opcode
584                 opcode32 = (opcode32 << 16) | opcode16;
585             }
586             else
587             {
588                 DNBLogError("%s: Unable to read opcode bits 31:16 for a 32 bit thumb opcode at pc=0x%8.8llx", __FUNCTION__, (uint64_t)pc_in_itblock);
589             }
590         }
591     }
592     else
593     {
594         DNBLogError("%s: Error reading 16-bit Thumb instruction at pc=0x%8.8x", __FUNCTION__, pc_in_itblock);
595     }
596 
597     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: pc_in_itblock=0x%8.8x, curr_pc=0x%8.8x", __FUNCTION__, pc_in_itblock, curr_pc);
598 
599     next_pc_in_itblock = pc_in_itblock;
600     while (next_pc_in_itblock <= curr_pc)
601     {
602         arm_error_t decodeError;
603 
604         m_last_decode_pc = pc_in_itblock;
605         decodeError = DecodeInstructionUsingDisassembler(pc_in_itblock, m_state.context.gpr.__cpsr, &m_last_decode_arm, &m_last_decode_thumb, &next_pc_in_itblock);
606 
607         pc_in_itblock = next_pc_in_itblock;
608         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: next_pc_in_itblock=0x%8.8x", __FUNCTION__, next_pc_in_itblock);
609     }
610 }
611 #endif
612 
613 // Set the single step bit in the processor status register.
614 kern_return_t
615 DNBArchMachARM::EnableHardwareSingleStep (bool enable)
616 {
617     DNBError err;
618     DNBLogThreadedIf(LOG_STEP, "%s( enable = %d )", __FUNCTION__, enable);
619 
620     err = GetGPRState(false);
621 
622     if (err.Fail())
623     {
624         err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__);
625         return err.Error();
626     }
627 
628     err = GetDBGState(false);
629 
630     if (err.Fail())
631     {
632         err.LogThreaded("%s: failed to read the DBG registers", __FUNCTION__);
633         return err.Error();
634     }
635 
636     const uint32_t i = 0;
637     if (enable)
638     {
639         m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS;
640 
641         // Save our previous state
642         m_dbg_save = m_state.dbg;
643         // Set a breakpoint that will stop when the PC doesn't match the current one!
644         m_state.dbg.__bvr[i] = m_state.context.gpr.__pc & 0xFFFFFFFCu;      // Set the current PC as the breakpoint address
645         m_state.dbg.__bcr[i] = BCR_M_IMVA_MISMATCH |    // Stop on address mismatch
646                                S_USER |                 // Stop only in user mode
647                                BCR_ENABLE;              // Enable this breakpoint
648         if (m_state.context.gpr.__cpsr & 0x20)
649         {
650             // Thumb breakpoint
651             if (m_state.context.gpr.__pc & 2)
652                 m_state.dbg.__bcr[i] |= BAS_IMVA_2_3;
653             else
654                 m_state.dbg.__bcr[i] |= BAS_IMVA_0_1;
655 
656             uint16_t opcode;
657             if (sizeof(opcode) == m_thread->Process()->Task().ReadMemory(m_state.context.gpr.__pc, sizeof(opcode), &opcode))
658             {
659                 if (((opcode & 0xE000) == 0xE000) && opcode & 0x1800)
660                 {
661                     // 32 bit thumb opcode...
662                     if (m_state.context.gpr.__pc & 2)
663                     {
664                         // We can't take care of a 32 bit thumb instruction single step
665                         // with just IVA mismatching. We will need to chain an extra
666                         // hardware single step in order to complete this single step...
667                         m_hw_single_chained_step_addr = m_state.context.gpr.__pc + 2;
668                     }
669                     else
670                     {
671                         // Extend the number of bits to ignore for the mismatch
672                         m_state.dbg.__bcr[i] |= BAS_IMVA_ALL;
673                     }
674                 }
675             }
676         }
677         else
678         {
679             // ARM breakpoint
680             m_state.dbg.__bcr[i] |= BAS_IMVA_ALL; // Stop when any address bits change
681         }
682 
683         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]);
684 
685         for (uint32_t j=i+1; j<16; ++j)
686         {
687             // Disable all others
688             m_state.dbg.__bvr[j] = 0;
689             m_state.dbg.__bcr[j] = 0;
690         }
691     }
692     else
693     {
694         // Just restore the state we had before we did single stepping
695         m_state.dbg = m_dbg_save;
696     }
697 
698     return SetDBGState();
699 }
700 
701 // return 1 if bit "BIT" is set in "value"
702 static inline uint32_t bit(uint32_t value, uint32_t bit)
703 {
704     return (value >> bit) & 1u;
705 }
706 
707 // return the bitfield "value[msbit:lsbit]".
708 static inline uint32_t bits(uint32_t value, uint32_t msbit, uint32_t lsbit)
709 {
710     assert(msbit >= lsbit);
711     uint32_t shift_left = sizeof(value) * 8 - 1 - msbit;
712     value <<= shift_left;           // shift anything above the msbit off of the unsigned edge
713     value >>= (shift_left + lsbit); // shift it back again down to the lsbit (including undoing any shift from above)
714     return value;                   // return our result
715 }
716 
717 bool
718 DNBArchMachARM::ConditionPassed(uint8_t condition, uint32_t cpsr)
719 {
720     uint32_t cpsr_n = bit(cpsr, 31); // Negative condition code flag
721     uint32_t cpsr_z = bit(cpsr, 30); // Zero condition code flag
722     uint32_t cpsr_c = bit(cpsr, 29); // Carry condition code flag
723     uint32_t cpsr_v = bit(cpsr, 28); // Overflow condition code flag
724 
725     switch (condition) {
726         case COND_EQ: // (0x0)
727             if (cpsr_z == 1) return true;
728             break;
729         case COND_NE: // (0x1)
730             if (cpsr_z == 0) return true;
731             break;
732         case COND_CS: // (0x2)
733             if (cpsr_c == 1) return true;
734             break;
735         case COND_CC: // (0x3)
736             if (cpsr_c == 0) return true;
737             break;
738         case COND_MI: // (0x4)
739             if (cpsr_n == 1) return true;
740             break;
741         case COND_PL: // (0x5)
742             if (cpsr_n == 0) return true;
743             break;
744         case COND_VS: // (0x6)
745             if (cpsr_v == 1) return true;
746             break;
747         case COND_VC: // (0x7)
748             if (cpsr_v == 0) return true;
749             break;
750         case COND_HI: // (0x8)
751             if ((cpsr_c == 1) && (cpsr_z == 0)) return true;
752             break;
753         case COND_LS: // (0x9)
754             if ((cpsr_c == 0) || (cpsr_z == 1)) return true;
755             break;
756         case COND_GE: // (0xA)
757             if (cpsr_n == cpsr_v) return true;
758             break;
759         case COND_LT: // (0xB)
760             if (cpsr_n != cpsr_v) return true;
761             break;
762         case COND_GT: // (0xC)
763             if ((cpsr_z == 0) && (cpsr_n == cpsr_v)) return true;
764             break;
765         case COND_LE: // (0xD)
766             if ((cpsr_z == 1) || (cpsr_n != cpsr_v)) return true;
767             break;
768         default:
769             return true;
770             break;
771     }
772 
773     return false;
774 }
775 
776 #if defined (USE_ARM_DISASSEMBLER_FRAMEWORK)
777 
778 bool
779 DNBArchMachARM::ComputeNextPC(nub_addr_t currentPC, arm_decoded_instruction_t decodedInstruction, bool currentPCIsThumb, nub_addr_t *targetPC)
780 {
781     nub_addr_t myTargetPC, addressWherePCLives;
782     pid_t mypid;
783 
784     uint32_t cpsr_c = bit(m_state.context.gpr.__cpsr, 29); // Carry condition code flag
785 
786     uint32_t firstOperand=0, secondOperand=0, shiftAmount=0, secondOperandAfterShift=0, immediateValue=0;
787     uint32_t halfwords=0, baseAddress=0, immediateOffset=0, addressOffsetFromRegister=0, addressOffsetFromRegisterAfterShift;
788     uint32_t baseAddressIndex=INVALID_NUB_HW_INDEX;
789     uint32_t firstOperandIndex=INVALID_NUB_HW_INDEX;
790     uint32_t secondOperandIndex=INVALID_NUB_HW_INDEX;
791     uint32_t addressOffsetFromRegisterIndex=INVALID_NUB_HW_INDEX;
792     uint32_t shiftRegisterIndex=INVALID_NUB_HW_INDEX;
793     uint16_t registerList16, registerList16NoPC;
794     uint8_t registerList8;
795     uint32_t numRegistersToLoad=0;
796 
797     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: instruction->code=%d", __FUNCTION__, decodedInstruction.instruction->code);
798 
799     // Get the following in this switch statement:
800     //   - firstOperand, secondOperand, immediateValue, shiftAmount: For arithmetic, logical and move instructions
801     //   - baseAddress, immediateOffset, shiftAmount: For LDR
802     //   - numRegistersToLoad: For LDM and POP instructions
803     switch (decodedInstruction.instruction->code)
804     {
805             // Arithmetic operations that can change the PC
806         case ARM_INST_ADC:
807         case ARM_INST_ADCS:
808         case ARM_INST_ADD:
809         case ARM_INST_ADDS:
810         case ARM_INST_AND:
811         case ARM_INST_ANDS:
812         case ARM_INST_ASR:
813         case ARM_INST_ASRS:
814         case ARM_INST_BIC:
815         case ARM_INST_BICS:
816         case ARM_INST_EOR:
817         case ARM_INST_EORS:
818         case ARM_INST_ORR:
819         case ARM_INST_ORRS:
820         case ARM_INST_RSB:
821         case ARM_INST_RSBS:
822         case ARM_INST_RSC:
823         case ARM_INST_RSCS:
824         case ARM_INST_SBC:
825         case ARM_INST_SBCS:
826         case ARM_INST_SUB:
827         case ARM_INST_SUBS:
828             switch (decodedInstruction.addressMode)
829             {
830                 case ARM_ADDR_DATA_IMM:
831                     if (decodedInstruction.numOperands != 3)
832                     {
833                         DNBLogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
834                         return false;
835                     }
836 
837                     if (decodedInstruction.op[0].value != PC_REG)
838                     {
839                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
840                         return false;
841                     }
842 
843                     // Get firstOperand register value (at index=1)
844                     firstOperandIndex = decodedInstruction.op[1].value; // first operand register index
845                     firstOperand = m_state.context.gpr.__r[firstOperandIndex];
846 
847                     // Get immediateValue (at index=2)
848                     immediateValue = decodedInstruction.op[2].value;
849 
850                     break;
851 
852                 case ARM_ADDR_DATA_REG:
853                     if (decodedInstruction.numOperands != 3)
854                     {
855                         DNBLogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
856                         return false;
857                     }
858 
859                     if (decodedInstruction.op[0].value != PC_REG)
860                     {
861                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
862                         return false;
863                     }
864 
865                     // Get firstOperand register value (at index=1)
866                     firstOperandIndex = decodedInstruction.op[1].value; // first operand register index
867                     firstOperand = m_state.context.gpr.__r[firstOperandIndex];
868 
869                     // Get secondOperand register value (at index=2)
870                     secondOperandIndex = decodedInstruction.op[2].value; // second operand register index
871                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
872 
873                     break;
874 
875                 case ARM_ADDR_DATA_SCALED_IMM:
876                     if (decodedInstruction.numOperands != 4)
877                     {
878                         DNBLogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
879                         return false;
880                     }
881 
882                     if (decodedInstruction.op[0].value != PC_REG)
883                     {
884                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
885                         return false;
886                     }
887 
888                     // Get firstOperand register value (at index=1)
889                     firstOperandIndex = decodedInstruction.op[1].value; // first operand register index
890                     firstOperand = m_state.context.gpr.__r[firstOperandIndex];
891 
892                     // Get secondOperand register value (at index=2)
893                     secondOperandIndex = decodedInstruction.op[2].value; // second operand register index
894                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
895 
896                     // Get shiftAmount as immediate value (at index=3)
897                     shiftAmount = decodedInstruction.op[3].value;
898 
899                     break;
900 
901 
902                 case ARM_ADDR_DATA_SCALED_REG:
903                     if (decodedInstruction.numOperands != 4)
904                     {
905                         DNBLogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
906                         return false;
907                     }
908 
909                     if (decodedInstruction.op[0].value != PC_REG)
910                     {
911                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
912                         return false;
913                     }
914 
915                     // Get firstOperand register value (at index=1)
916                     firstOperandIndex = decodedInstruction.op[1].value; // first operand register index
917                     firstOperand = m_state.context.gpr.__r[firstOperandIndex];
918 
919                     // Get secondOperand register value (at index=2)
920                     secondOperandIndex = decodedInstruction.op[2].value; // second operand register index
921                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
922 
923                     // Get shiftAmount from register (at index=3)
924                     shiftRegisterIndex = decodedInstruction.op[3].value; // second operand register index
925                     shiftAmount = m_state.context.gpr.__r[shiftRegisterIndex];
926 
927                     break;
928 
929                 case THUMB_ADDR_HR_HR:
930                     if (decodedInstruction.numOperands != 2)
931                     {
932                         DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
933                         return false;
934                     }
935 
936                     if (decodedInstruction.op[0].value != PC_REG)
937                     {
938                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
939                         return false;
940                     }
941 
942                     // Get firstOperand register value (at index=0)
943                     firstOperandIndex = decodedInstruction.op[0].value; // first operand register index
944                     firstOperand = m_state.context.gpr.__r[firstOperandIndex];
945 
946                     // Get secondOperand register value (at index=1)
947                     secondOperandIndex = decodedInstruction.op[1].value; // second operand register index
948                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
949 
950                     break;
951 
952                 default:
953                     break;
954             }
955             break;
956 
957             // Logical shifts and move operations that can change the PC
958         case ARM_INST_LSL:
959         case ARM_INST_LSLS:
960         case ARM_INST_LSR:
961         case ARM_INST_LSRS:
962         case ARM_INST_MOV:
963         case ARM_INST_MOVS:
964         case ARM_INST_MVN:
965         case ARM_INST_MVNS:
966         case ARM_INST_ROR:
967         case ARM_INST_RORS:
968         case ARM_INST_RRX:
969         case ARM_INST_RRXS:
970             // In these cases, the firstOperand is always 0, as if it does not exist
971             switch (decodedInstruction.addressMode)
972             {
973                 case ARM_ADDR_DATA_IMM:
974                     if (decodedInstruction.numOperands != 2)
975                     {
976                         DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
977                         return false;
978                     }
979 
980                     if (decodedInstruction.op[0].value != PC_REG)
981                     {
982                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
983                         return false;
984                     }
985 
986                     // Get immediateValue (at index=1)
987                     immediateValue = decodedInstruction.op[1].value;
988 
989                     break;
990 
991                 case ARM_ADDR_DATA_REG:
992                     if (decodedInstruction.numOperands != 2)
993                     {
994                         DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
995                         return false;
996                     }
997 
998                     if (decodedInstruction.op[0].value != PC_REG)
999                     {
1000                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
1001                         return false;
1002                     }
1003 
1004                     // Get secondOperand register value (at index=1)
1005                     secondOperandIndex = decodedInstruction.op[1].value; // second operand register index
1006                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
1007 
1008                     break;
1009 
1010                 case ARM_ADDR_DATA_SCALED_IMM:
1011                     if (decodedInstruction.numOperands != 3)
1012                     {
1013                         DNBLogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
1014                         return false;
1015                     }
1016 
1017                     if (decodedInstruction.op[0].value != PC_REG)
1018                     {
1019                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
1020                         return false;
1021                     }
1022 
1023                     // Get secondOperand register value (at index=1)
1024                     secondOperandIndex = decodedInstruction.op[2].value; // second operand register index
1025                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
1026 
1027                     // Get shiftAmount as immediate value (at index=2)
1028                     shiftAmount = decodedInstruction.op[2].value;
1029 
1030                     break;
1031 
1032 
1033                 case ARM_ADDR_DATA_SCALED_REG:
1034                     if (decodedInstruction.numOperands != 3)
1035                     {
1036                         DNBLogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
1037                         return false;
1038                     }
1039 
1040                     if (decodedInstruction.op[0].value != PC_REG)
1041                     {
1042                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
1043                         return false;
1044                     }
1045 
1046                     // Get secondOperand register value (at index=1)
1047                     secondOperandIndex = decodedInstruction.op[1].value; // second operand register index
1048                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
1049 
1050                     // Get shiftAmount from register (at index=2)
1051                     shiftRegisterIndex = decodedInstruction.op[2].value; // second operand register index
1052                     shiftAmount = m_state.context.gpr.__r[shiftRegisterIndex];
1053 
1054                     break;
1055 
1056                 case THUMB_ADDR_HR_HR:
1057                     if (decodedInstruction.numOperands != 2)
1058                     {
1059                         DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
1060                         return false;
1061                     }
1062 
1063                     if (decodedInstruction.op[0].value != PC_REG)
1064                     {
1065                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
1066                         return false;
1067                     }
1068 
1069                     // Get secondOperand register value (at index=1)
1070                     secondOperandIndex = decodedInstruction.op[1].value; // second operand register index
1071                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
1072 
1073                     break;
1074 
1075                 default:
1076                     break;
1077             }
1078 
1079             break;
1080 
1081             // Simple branches, used to hop around within a routine
1082         case ARM_INST_B:
1083             *targetPC = decodedInstruction.targetPC; // Known targetPC
1084             return true;
1085             break;
1086 
1087             // Branch-and-link, used to call ARM subroutines
1088         case ARM_INST_BL:
1089             *targetPC = decodedInstruction.targetPC; // Known targetPC
1090             return true;
1091             break;
1092 
1093             // Branch-and-link with exchange, used to call opposite-mode subroutines
1094         case ARM_INST_BLX:
1095             if ((decodedInstruction.addressMode == ARM_ADDR_BRANCH_IMM) ||
1096                 (decodedInstruction.addressMode == THUMB_ADDR_UNCOND))
1097             {
1098                 *targetPC = decodedInstruction.targetPC; // Known targetPC
1099                 return true;
1100             }
1101             else    // addressMode == ARM_ADDR_BRANCH_REG
1102             {
1103                 // Unknown target unless we're branching to the PC itself,
1104                 //  although this may not work properly with BLX
1105                 if (decodedInstruction.op[REG_RD].value == PC_REG)
1106                 {
1107                     // this should (almost) never happen
1108                     *targetPC = decodedInstruction.targetPC; // Known targetPC
1109                     return true;
1110                 }
1111 
1112                 // Get the branch address and return
1113                 if (decodedInstruction.numOperands != 1)
1114                 {
1115                     DNBLogError("Expected 1 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
1116                     return false;
1117                 }
1118 
1119                 // Get branch address in register (at index=0)
1120                 *targetPC = m_state.context.gpr.__r[decodedInstruction.op[0].value];
1121                 return true;
1122             }
1123             break;
1124 
1125             // Branch with exchange, used to hop to opposite-mode code
1126             // Branch to Jazelle code, used to execute Java; included here since it
1127             //  acts just like BX unless the Jazelle unit is active and JPC is
1128             //  already loaded into it.
1129         case ARM_INST_BX:
1130         case ARM_INST_BXJ:
1131             // Unknown target unless we're branching to the PC itself,
1132             //  although this can never switch to Thumb mode and is
1133             //  therefore pretty much useless
1134             if (decodedInstruction.op[REG_RD].value == PC_REG)
1135             {
1136                 // this should (almost) never happen
1137                 *targetPC = decodedInstruction.targetPC; // Known targetPC
1138                 return true;
1139             }
1140 
1141             // Get the branch address and return
1142             if (decodedInstruction.numOperands != 1)
1143             {
1144                 DNBLogError("Expected 1 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
1145                 return false;
1146             }
1147 
1148             // Get branch address in register (at index=0)
1149             *targetPC = m_state.context.gpr.__r[decodedInstruction.op[0].value];
1150             return true;
1151             break;
1152 
1153             // Compare and branch on zero/non-zero (Thumb-16 only)
1154             // Unusual condition check built into the instruction
1155         case ARM_INST_CBZ:
1156         case ARM_INST_CBNZ:
1157             // Branch address is known at compile time
1158             // Get the branch address and return
1159             if (decodedInstruction.numOperands != 2)
1160             {
1161                 DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
1162                 return false;
1163             }
1164 
1165             // Get branch address as an immediate value (at index=1)
1166             *targetPC = decodedInstruction.op[1].value;
1167             return true;
1168             break;
1169 
1170             // Load register can be used to load PC, usually with a function pointer
1171         case ARM_INST_LDR:
1172             if (decodedInstruction.op[REG_RD].value != PC_REG)
1173             {
1174                 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
1175                 return false;
1176             }
1177             switch (decodedInstruction.addressMode)
1178             {
1179                 case ARM_ADDR_LSWUB_IMM:
1180                 case ARM_ADDR_LSWUB_IMM_PRE:
1181                 case ARM_ADDR_LSWUB_IMM_POST:
1182                     if (decodedInstruction.numOperands != 3)
1183                     {
1184                         DNBLogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
1185                         return false;
1186                     }
1187 
1188                     // Get baseAddress from register (at index=1)
1189                     baseAddressIndex = decodedInstruction.op[1].value;
1190                     baseAddress = m_state.context.gpr.__r[baseAddressIndex];
1191 
1192                     // Get immediateOffset (at index=2)
1193                     immediateOffset = decodedInstruction.op[2].value;
1194                     break;
1195 
1196                 case ARM_ADDR_LSWUB_REG:
1197                 case ARM_ADDR_LSWUB_REG_PRE:
1198                 case ARM_ADDR_LSWUB_REG_POST:
1199                     if (decodedInstruction.numOperands != 3)
1200                     {
1201                         DNBLogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
1202                         return false;
1203                     }
1204 
1205                     // Get baseAddress from register (at index=1)
1206                     baseAddressIndex = decodedInstruction.op[1].value;
1207                     baseAddress = m_state.context.gpr.__r[baseAddressIndex];
1208 
1209                     // Get immediateOffset from register (at index=2)
1210                     addressOffsetFromRegisterIndex = decodedInstruction.op[2].value;
1211                     addressOffsetFromRegister = m_state.context.gpr.__r[addressOffsetFromRegisterIndex];
1212 
1213                     break;
1214 
1215                 case ARM_ADDR_LSWUB_SCALED:
1216                 case ARM_ADDR_LSWUB_SCALED_PRE:
1217                 case ARM_ADDR_LSWUB_SCALED_POST:
1218                     if (decodedInstruction.numOperands != 4)
1219                     {
1220                         DNBLogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
1221                         return false;
1222                     }
1223 
1224                     // Get baseAddress from register (at index=1)
1225                     baseAddressIndex = decodedInstruction.op[1].value;
1226                     baseAddress = m_state.context.gpr.__r[baseAddressIndex];
1227 
1228                     // Get immediateOffset from register (at index=2)
1229                     addressOffsetFromRegisterIndex = decodedInstruction.op[2].value;
1230                     addressOffsetFromRegister = m_state.context.gpr.__r[addressOffsetFromRegisterIndex];
1231 
1232                     // Get shiftAmount (at index=3)
1233                     shiftAmount = decodedInstruction.op[3].value;
1234 
1235                     break;
1236 
1237                 default:
1238                     break;
1239             }
1240             break;
1241 
1242             // 32b load multiple operations can load the PC along with everything else,
1243             //  usually to return from a function call
1244         case ARM_INST_LDMDA:
1245         case ARM_INST_LDMDB:
1246         case ARM_INST_LDMIA:
1247         case ARM_INST_LDMIB:
1248             if (decodedInstruction.op[LDM_REGLIST].value & PC_REGLIST_BIT)
1249             {
1250                 if (decodedInstruction.numOperands != 2)
1251                 {
1252                     DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
1253                     return false;
1254                 }
1255 
1256                 // Get baseAddress from register (at index=0)
1257                 baseAddressIndex = decodedInstruction.op[0].value;
1258                 baseAddress = m_state.context.gpr.__r[baseAddressIndex];
1259 
1260                 // Get registerList from register (at index=1)
1261                 registerList16 = (uint16_t)decodedInstruction.op[1].value;
1262 
1263                 // Count number of registers to load in the multiple register list excluding the PC
1264                 registerList16NoPC = registerList16&0x3FFF; // exclude the PC
1265                 numRegistersToLoad=0;
1266                 for (int i = 0; i < 16; i++)
1267                 {
1268                     if (registerList16NoPC & 0x1) numRegistersToLoad++;
1269                     registerList16NoPC = registerList16NoPC >> 1;
1270                 }
1271             }
1272             else
1273             {
1274                 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
1275                 return false;
1276             }
1277             break;
1278 
1279             // Normal 16-bit LD multiple can't touch R15, but POP can
1280         case ARM_INST_POP:  // Can also get the PC & updates SP
1281             // Get baseAddress from SP (at index=0)
1282             baseAddress = m_state.context.gpr.__sp;
1283 
1284             if (decodedInstruction.thumb16b)
1285             {
1286                 // Get registerList from register (at index=0)
1287                 registerList8 = (uint8_t)decodedInstruction.op[0].value;
1288 
1289                 // Count number of registers to load in the multiple register list
1290                 numRegistersToLoad=0;
1291                 for (int i = 0; i < 8; i++)
1292                 {
1293                     if (registerList8 & 0x1) numRegistersToLoad++;
1294                     registerList8 = registerList8 >> 1;
1295                 }
1296             }
1297             else
1298             {
1299                 // Get registerList from register (at index=0)
1300                 registerList16 = (uint16_t)decodedInstruction.op[0].value;
1301 
1302                 // Count number of registers to load in the multiple register list excluding the PC
1303                 registerList16NoPC = registerList16&0x3FFF; // exclude the PC
1304                 numRegistersToLoad=0;
1305                 for (int i = 0; i < 16; i++)
1306                 {
1307                     if (registerList16NoPC & 0x1) numRegistersToLoad++;
1308                     registerList16NoPC = registerList16NoPC >> 1;
1309                 }
1310             }
1311             break;
1312 
1313             // 16b TBB and TBH instructions load a jump address from a table
1314         case ARM_INST_TBB:
1315         case ARM_INST_TBH:
1316             // Get baseAddress from register (at index=0)
1317             baseAddressIndex = decodedInstruction.op[0].value;
1318             baseAddress = m_state.context.gpr.__r[baseAddressIndex];
1319 
1320             // Get immediateOffset from register (at index=1)
1321             addressOffsetFromRegisterIndex = decodedInstruction.op[1].value;
1322             addressOffsetFromRegister = m_state.context.gpr.__r[addressOffsetFromRegisterIndex];
1323             break;
1324 
1325             // ThumbEE branch-to-handler instructions: Jump to handlers at some offset
1326             //  from a special base pointer register (which is unknown at disassembly time)
1327         case ARM_INST_HB:
1328         case ARM_INST_HBP:
1329 //          TODO: ARM_INST_HB, ARM_INST_HBP
1330             break;
1331 
1332         case ARM_INST_HBL:
1333         case ARM_INST_HBLP:
1334 //          TODO: ARM_INST_HBL, ARM_INST_HBLP
1335             break;
1336 
1337             // Breakpoint and software interrupt jump to interrupt handler (always ARM)
1338         case ARM_INST_BKPT:
1339         case ARM_INST_SMC:
1340         case ARM_INST_SVC:
1341 
1342             // Return from exception, obviously modifies PC [interrupt only!]
1343         case ARM_INST_RFEDA:
1344         case ARM_INST_RFEDB:
1345         case ARM_INST_RFEIA:
1346         case ARM_INST_RFEIB:
1347 
1348             // Other instructions either can't change R15 or are "undefined" if you do,
1349             //  so no sane compiler should ever generate them & we don't care here.
1350             //  Also, R15 can only legally be used in a read-only manner for the
1351             //  various ARM addressing mode (to get PC-relative addressing of constants),
1352             //  but can NOT be used with any of the update modes.
1353         default:
1354             DNBLogError("%s should not be called for instruction code %d!", __FUNCTION__, decodedInstruction.instruction->code);
1355             return false;
1356             break;
1357     }
1358 
1359     // Adjust PC if PC is one of the input operands
1360     if (baseAddressIndex == PC_REG)
1361     {
1362         if (currentPCIsThumb)
1363             baseAddress += 4;
1364         else
1365             baseAddress += 8;
1366     }
1367 
1368     if (firstOperandIndex == PC_REG)
1369     {
1370         if (currentPCIsThumb)
1371             firstOperand += 4;
1372         else
1373             firstOperand += 8;
1374     }
1375 
1376     if (secondOperandIndex == PC_REG)
1377     {
1378         if (currentPCIsThumb)
1379             secondOperand += 4;
1380         else
1381             secondOperand += 8;
1382     }
1383 
1384     if (addressOffsetFromRegisterIndex == PC_REG)
1385     {
1386         if (currentPCIsThumb)
1387             addressOffsetFromRegister += 4;
1388         else
1389             addressOffsetFromRegister += 8;
1390     }
1391 
1392     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE,
1393         "%s: firstOperand=%8.8x, secondOperand=%8.8x, immediateValue = %d, shiftAmount = %d, baseAddress = %8.8x, addressOffsetFromRegister = %8.8x, immediateOffset = %d, numRegistersToLoad = %d",
1394         __FUNCTION__,
1395         firstOperand,
1396         secondOperand,
1397         immediateValue,
1398         shiftAmount,
1399         baseAddress,
1400         addressOffsetFromRegister,
1401         immediateOffset,
1402         numRegistersToLoad);
1403 
1404 
1405     // Calculate following values after applying shiftAmount:
1406     //   - immediateOffsetAfterShift, secondOperandAfterShift
1407 
1408     switch (decodedInstruction.scaleMode)
1409     {
1410         case ARM_SCALE_NONE:
1411             addressOffsetFromRegisterAfterShift = addressOffsetFromRegister;
1412             secondOperandAfterShift = secondOperand;
1413             break;
1414 
1415         case ARM_SCALE_LSL:             // Logical shift left
1416             addressOffsetFromRegisterAfterShift = addressOffsetFromRegister << shiftAmount;
1417             secondOperandAfterShift = secondOperand << shiftAmount;
1418             break;
1419 
1420         case ARM_SCALE_LSR:             // Logical shift right
1421             addressOffsetFromRegisterAfterShift = addressOffsetFromRegister >> shiftAmount;
1422             secondOperandAfterShift = secondOperand >> shiftAmount;
1423             break;
1424 
1425         case ARM_SCALE_ASR:             // Arithmetic shift right
1426             asm("mov %0, %1, asr %2" : "=r" (addressOffsetFromRegisterAfterShift) : "r" (addressOffsetFromRegister), "r" (shiftAmount));
1427             asm("mov %0, %1, asr %2" : "=r" (secondOperandAfterShift) : "r" (secondOperand), "r" (shiftAmount));
1428             break;
1429 
1430         case ARM_SCALE_ROR:             // Rotate right
1431             asm("mov %0, %1, ror %2" : "=r" (addressOffsetFromRegisterAfterShift) : "r" (addressOffsetFromRegister), "r" (shiftAmount));
1432             asm("mov %0, %1, ror %2" : "=r" (secondOperandAfterShift) : "r" (secondOperand), "r" (shiftAmount));
1433             break;
1434 
1435         case ARM_SCALE_RRX:             // Rotate right, pulling in carry (1-bit shift only)
1436             asm("mov %0, %1, rrx" : "=r" (addressOffsetFromRegisterAfterShift) : "r" (addressOffsetFromRegister));
1437             asm("mov %0, %1, rrx" : "=r" (secondOperandAfterShift) : "r" (secondOperand));
1438             break;
1439     }
1440 
1441     // Emulate instruction to calculate targetPC
1442     // All branches are already handled in the first switch statement. A branch should not reach this switch
1443     switch (decodedInstruction.instruction->code)
1444     {
1445             // Arithmetic operations that can change the PC
1446         case ARM_INST_ADC:
1447         case ARM_INST_ADCS:
1448             // Add with Carry
1449             *targetPC = firstOperand + (secondOperandAfterShift + immediateValue) + cpsr_c;
1450             break;
1451 
1452         case ARM_INST_ADD:
1453         case ARM_INST_ADDS:
1454             *targetPC = firstOperand + (secondOperandAfterShift + immediateValue);
1455             break;
1456 
1457         case ARM_INST_AND:
1458         case ARM_INST_ANDS:
1459             *targetPC = firstOperand & (secondOperandAfterShift + immediateValue);
1460             break;
1461 
1462         case ARM_INST_ASR:
1463         case ARM_INST_ASRS:
1464             asm("mov %0, %1, asr %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
1465             *targetPC = myTargetPC;
1466             break;
1467 
1468         case ARM_INST_BIC:
1469         case ARM_INST_BICS:
1470             asm("bic %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
1471             *targetPC = myTargetPC;
1472             break;
1473 
1474         case ARM_INST_EOR:
1475         case ARM_INST_EORS:
1476             asm("eor %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
1477             *targetPC = myTargetPC;
1478             break;
1479 
1480         case ARM_INST_ORR:
1481         case ARM_INST_ORRS:
1482             asm("orr %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
1483             *targetPC = myTargetPC;
1484             break;
1485 
1486         case ARM_INST_RSB:
1487         case ARM_INST_RSBS:
1488             asm("rsb %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
1489             *targetPC = myTargetPC;
1490             break;
1491 
1492         case ARM_INST_RSC:
1493         case ARM_INST_RSCS:
1494             myTargetPC = secondOperandAfterShift - (firstOperand + !cpsr_c);
1495             *targetPC = myTargetPC;
1496             break;
1497 
1498         case ARM_INST_SBC:
1499         case ARM_INST_SBCS:
1500             asm("sbc %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue  + !cpsr_c));
1501             *targetPC = myTargetPC;
1502             break;
1503 
1504         case ARM_INST_SUB:
1505         case ARM_INST_SUBS:
1506             asm("sub %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
1507             *targetPC = myTargetPC;
1508             break;
1509 
1510             // Logical shifts and move operations that can change the PC
1511         case ARM_INST_LSL:
1512         case ARM_INST_LSLS:
1513         case ARM_INST_LSR:
1514         case ARM_INST_LSRS:
1515         case ARM_INST_MOV:
1516         case ARM_INST_MOVS:
1517         case ARM_INST_ROR:
1518         case ARM_INST_RORS:
1519         case ARM_INST_RRX:
1520         case ARM_INST_RRXS:
1521             myTargetPC = secondOperandAfterShift + immediateValue;
1522             *targetPC = myTargetPC;
1523             break;
1524 
1525         case ARM_INST_MVN:
1526         case ARM_INST_MVNS:
1527             myTargetPC = !(secondOperandAfterShift + immediateValue);
1528             *targetPC = myTargetPC;
1529             break;
1530 
1531             // Load register can be used to load PC, usually with a function pointer
1532         case ARM_INST_LDR:
1533             switch (decodedInstruction.addressMode) {
1534                 case ARM_ADDR_LSWUB_IMM_POST:
1535                 case ARM_ADDR_LSWUB_REG_POST:
1536                 case ARM_ADDR_LSWUB_SCALED_POST:
1537                     addressWherePCLives = baseAddress;
1538                     break;
1539 
1540                 case ARM_ADDR_LSWUB_IMM:
1541                 case ARM_ADDR_LSWUB_REG:
1542                 case ARM_ADDR_LSWUB_SCALED:
1543                 case ARM_ADDR_LSWUB_IMM_PRE:
1544                 case ARM_ADDR_LSWUB_REG_PRE:
1545                 case ARM_ADDR_LSWUB_SCALED_PRE:
1546                     addressWherePCLives = baseAddress + (addressOffsetFromRegisterAfterShift + immediateOffset);
1547                     break;
1548 
1549                 default:
1550                     break;
1551             }
1552 
1553             mypid = m_thread->ProcessID();
1554             if (DNBProcessMemoryRead(mypid, addressWherePCLives, sizeof(nub_addr_t), &myTargetPC) !=  sizeof(nub_addr_t))
1555             {
1556                 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives);
1557                 return false;
1558             }
1559 
1560             *targetPC = myTargetPC;
1561             break;
1562 
1563             // 32b load multiple operations can load the PC along with everything else,
1564             //  usually to return from a function call
1565         case ARM_INST_LDMDA:
1566             mypid = m_thread->ProcessID();
1567             addressWherePCLives = baseAddress;
1568             if (DNBProcessMemoryRead(mypid, addressWherePCLives, sizeof(nub_addr_t), &myTargetPC) !=  sizeof(nub_addr_t))
1569             {
1570                 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives);
1571                 return false;
1572             }
1573 
1574             *targetPC = myTargetPC;
1575             break;
1576 
1577         case ARM_INST_LDMDB:
1578             mypid = m_thread->ProcessID();
1579             addressWherePCLives = baseAddress - 4;
1580             if (DNBProcessMemoryRead(mypid, addressWherePCLives, sizeof(nub_addr_t), &myTargetPC) !=  sizeof(nub_addr_t))
1581             {
1582                 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives);
1583                 return false;
1584             }
1585 
1586             *targetPC = myTargetPC;
1587             break;
1588 
1589         case ARM_INST_LDMIB:
1590             mypid = m_thread->ProcessID();
1591             addressWherePCLives = baseAddress + numRegistersToLoad*4 + 4;
1592             if (DNBProcessMemoryRead(mypid, addressWherePCLives, sizeof(nub_addr_t), &myTargetPC) !=  sizeof(nub_addr_t))
1593             {
1594                 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives);
1595                 return false;
1596             }
1597 
1598             *targetPC = myTargetPC;
1599             break;
1600 
1601         case ARM_INST_LDMIA: // same as pop
1602             // Normal 16-bit LD multiple can't touch R15, but POP can
1603         case ARM_INST_POP:  // Can also get the PC & updates SP
1604             mypid = m_thread->ProcessID();
1605             addressWherePCLives = baseAddress + numRegistersToLoad*4;
1606             if (DNBProcessMemoryRead(mypid, addressWherePCLives, sizeof(nub_addr_t), &myTargetPC) !=  sizeof(nub_addr_t))
1607             {
1608                 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives);
1609                 return false;
1610             }
1611 
1612             *targetPC = myTargetPC;
1613             break;
1614 
1615             // 16b TBB and TBH instructions load a jump address from a table
1616         case ARM_INST_TBB:
1617             mypid = m_thread->ProcessID();
1618             addressWherePCLives = baseAddress + addressOffsetFromRegisterAfterShift;
1619             if (DNBProcessMemoryRead(mypid, addressWherePCLives, 1, &halfwords) !=  1)
1620             {
1621                 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the TBB instruction!", addressWherePCLives);
1622                 return false;
1623             }
1624             // add 4 to currentPC since we are in Thumb mode and then add 2*halfwords
1625             *targetPC = (currentPC + 4) + 2*halfwords;
1626             break;
1627 
1628         case ARM_INST_TBH:
1629             mypid = m_thread->ProcessID();
1630             addressWherePCLives = ((baseAddress + (addressOffsetFromRegisterAfterShift << 1)) & ~0x1);
1631             if (DNBProcessMemoryRead(mypid, addressWherePCLives, 2, &halfwords) !=  2)
1632             {
1633                 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the TBH instruction!", addressWherePCLives);
1634                 return false;
1635             }
1636             // add 4 to currentPC since we are in Thumb mode and then add 2*halfwords
1637             *targetPC = (currentPC + 4) + 2*halfwords;
1638             break;
1639 
1640             // ThumbEE branch-to-handler instructions: Jump to handlers at some offset
1641             //  from a special base pointer register (which is unknown at disassembly time)
1642         case ARM_INST_HB:
1643         case ARM_INST_HBP:
1644             //          TODO: ARM_INST_HB, ARM_INST_HBP
1645             break;
1646 
1647         case ARM_INST_HBL:
1648         case ARM_INST_HBLP:
1649             //          TODO: ARM_INST_HBL, ARM_INST_HBLP
1650             break;
1651 
1652             // Breakpoint and software interrupt jump to interrupt handler (always ARM)
1653         case ARM_INST_BKPT:
1654         case ARM_INST_SMC:
1655         case ARM_INST_SVC:
1656             //          TODO: ARM_INST_BKPT, ARM_INST_SMC, ARM_INST_SVC
1657             break;
1658 
1659             // Return from exception, obviously modifies PC [interrupt only!]
1660         case ARM_INST_RFEDA:
1661         case ARM_INST_RFEDB:
1662         case ARM_INST_RFEIA:
1663         case ARM_INST_RFEIB:
1664             //          TODO: ARM_INST_RFEDA, ARM_INST_RFEDB, ARM_INST_RFEIA, ARM_INST_RFEIB
1665             break;
1666 
1667             // Other instructions either can't change R15 or are "undefined" if you do,
1668             //  so no sane compiler should ever generate them & we don't care here.
1669             //  Also, R15 can only legally be used in a read-only manner for the
1670             //  various ARM addressing mode (to get PC-relative addressing of constants),
1671             //  but can NOT be used with any of the update modes.
1672         default:
1673             DNBLogError("%s should not be called for instruction code %d!", __FUNCTION__, decodedInstruction.instruction->code);
1674             return false;
1675             break;
1676     }
1677 
1678     return true;
1679 }
1680 
1681 void
1682 DNBArchMachARM::EvaluateNextInstructionForSoftwareBreakpointSetup(nub_addr_t currentPC, uint32_t cpsr, bool currentPCIsThumb, nub_addr_t *nextPC, bool *nextPCIsThumb)
1683 {
1684     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "DNBArchMachARM::EvaluateNextInstructionForSoftwareBreakpointSetup() called");
1685 
1686     nub_addr_t targetPC = INVALID_NUB_ADDRESS;
1687     uint32_t registerValue;
1688     arm_error_t decodeError;
1689     nub_addr_t currentPCInITBlock, nextPCInITBlock;
1690     int i;
1691     bool last_decoded_instruction_executes = true;
1692 
1693     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: default nextPC=0x%8.8x (%s)", __FUNCTION__, *nextPC, *nextPCIsThumb ? "Thumb" : "ARM");
1694 
1695     // Update *nextPC and *nextPCIsThumb for special cases
1696     if (m_last_decode_thumb.itBlockRemaining) // we are in an IT block
1697     {
1698         // Set the nextPC to the PC of the instruction which will execute in the IT block
1699         // If none of the instruction execute in the IT block based on the condition flags,
1700         // then point to the instruction immediately following the IT block
1701         const int itBlockRemaining = m_last_decode_thumb.itBlockRemaining;
1702         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: itBlockRemaining=%8.8x", __FUNCTION__, itBlockRemaining);
1703 
1704         // Determine the PC at which the next instruction resides
1705         if (m_last_decode_arm.thumb16b)
1706             currentPCInITBlock = currentPC + 2;
1707         else
1708             currentPCInITBlock = currentPC + 4;
1709 
1710         for (i = 0; i < itBlockRemaining; i++)
1711         {
1712             DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: currentPCInITBlock=%8.8x", __FUNCTION__, currentPCInITBlock);
1713             decodeError = DecodeInstructionUsingDisassembler(currentPCInITBlock, cpsr, &m_last_decode_arm, &m_last_decode_thumb, &nextPCInITBlock);
1714 
1715             if (decodeError != ARM_SUCCESS)
1716                 DNBLogError("unable to disassemble instruction at 0x%8.8llx", (uint64_t)currentPCInITBlock);
1717 
1718             DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: condition=%d", __FUNCTION__, m_last_decode_arm.condition);
1719             if (ConditionPassed(m_last_decode_arm.condition, cpsr))
1720             {
1721                 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Condition codes matched for instruction %d", __FUNCTION__, i);
1722                 break; // break from the for loop
1723             }
1724             else
1725             {
1726                 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Condition codes DID NOT matched for instruction %d", __FUNCTION__, i);
1727             }
1728 
1729             // update currentPC and nextPCInITBlock
1730             currentPCInITBlock = nextPCInITBlock;
1731         }
1732 
1733         if (i == itBlockRemaining) // We came out of the IT block without executing any instructions
1734             last_decoded_instruction_executes = false;
1735 
1736         *nextPC = currentPCInITBlock;
1737         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: After IT block step-through: *nextPC=%8.8x", __FUNCTION__, *nextPC);
1738     }
1739 
1740     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE,
1741                     "%s: cpsr = %8.8x, thumb16b = %d, thumb = %d, branch = %d, conditional = %d, knownTarget = %d, links = %d, canSwitchMode = %d, doesSwitchMode = %d",
1742                     __FUNCTION__,
1743                     cpsr,
1744                     m_last_decode_arm.thumb16b,
1745                     m_last_decode_arm.thumb,
1746                     m_last_decode_arm.branch,
1747                     m_last_decode_arm.conditional,
1748                     m_last_decode_arm.knownTarget,
1749                     m_last_decode_arm.links,
1750                     m_last_decode_arm.canSwitchMode,
1751                     m_last_decode_arm.doesSwitchMode);
1752 
1753 
1754     if (last_decoded_instruction_executes &&                    // Was this a conditional instruction that did execute?
1755         m_last_decode_arm.branch &&                             // Can this instruction change the PC?
1756         (m_last_decode_arm.instruction->code != ARM_INST_SVC))  // If this instruction is not an SVC instruction
1757     {
1758         // Set targetPC. Compute if needed.
1759         if (m_last_decode_arm.knownTarget)
1760         {
1761             // Fixed, known PC-relative
1762             targetPC = m_last_decode_arm.targetPC;
1763         }
1764         else
1765         {
1766             // if targetPC is not known at compile time (PC-relative target), compute targetPC
1767             if (!ComputeNextPC(currentPC, m_last_decode_arm, currentPCIsThumb, &targetPC))
1768             {
1769                 DNBLogError("%s: Unable to compute targetPC for instruction at 0x%8.8llx", __FUNCTION__, (uint64_t)currentPC);
1770                 targetPC = INVALID_NUB_ADDRESS;
1771             }
1772         }
1773 
1774         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: targetPC=0x%8.8x, cpsr=0x%8.8x, condition=0x%hhx", __FUNCTION__, targetPC, cpsr, m_last_decode_arm.condition);
1775 
1776         // Refine nextPC computation
1777         if ((m_last_decode_arm.instruction->code == ARM_INST_CBZ) ||
1778             (m_last_decode_arm.instruction->code == ARM_INST_CBNZ))
1779         {
1780             // Compare and branch on zero/non-zero (Thumb-16 only)
1781             // Unusual condition check built into the instruction
1782             registerValue = m_state.context.gpr.__r[m_last_decode_arm.op[REG_RD].value];
1783 
1784             if (m_last_decode_arm.instruction->code == ARM_INST_CBZ)
1785             {
1786                 if (registerValue == 0)
1787                     *nextPC = targetPC;
1788             }
1789             else
1790             {
1791                 if (registerValue != 0)
1792                     *nextPC = targetPC;
1793             }
1794         }
1795         else if (m_last_decode_arm.conditional) // Is the change conditional on flag results?
1796         {
1797             if (ConditionPassed(m_last_decode_arm.condition, cpsr)) // conditions match
1798             {
1799                 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Condition matched!", __FUNCTION__);
1800                 *nextPC = targetPC;
1801             }
1802             else
1803             {
1804                 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Condition did not match!", __FUNCTION__);
1805             }
1806         }
1807         else
1808         {
1809             *nextPC = targetPC;
1810         }
1811 
1812         // Refine nextPCIsThumb computation
1813         if (m_last_decode_arm.doesSwitchMode)
1814         {
1815             *nextPCIsThumb = !currentPCIsThumb;
1816         }
1817         else if (m_last_decode_arm.canSwitchMode)
1818         {
1819             // Legal to switch ARM <--> Thumb mode with this branch
1820             // dependent on bit[0] of targetPC
1821             *nextPCIsThumb = (*nextPC & 1u) != 0;
1822         }
1823         else
1824         {
1825             *nextPCIsThumb = currentPCIsThumb;
1826         }
1827     }
1828 
1829     DNBLogThreadedIf(LOG_STEP, "%s: calculated nextPC=0x%8.8x (%s)", __FUNCTION__, *nextPC, *nextPCIsThumb ? "Thumb" : "ARM");
1830 }
1831 
1832 
1833 arm_error_t
1834 DNBArchMachARM::DecodeInstructionUsingDisassembler(nub_addr_t curr_pc, uint32_t curr_cpsr, arm_decoded_instruction_t *decodedInstruction, thumb_static_data_t *thumbStaticData, nub_addr_t *next_pc)
1835 {
1836 
1837     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: pc=0x%8.8x, cpsr=0x%8.8x", __FUNCTION__, curr_pc, curr_cpsr);
1838 
1839     const uint32_t isetstate_mask = MASK_CPSR_T | MASK_CPSR_J;
1840     const uint32_t curr_isetstate = curr_cpsr & isetstate_mask;
1841     uint32_t opcode32;
1842     nub_addr_t nextPC = curr_pc;
1843     arm_error_t decodeReturnCode = ARM_SUCCESS;
1844 
1845     m_last_decode_pc = curr_pc;
1846     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: last_decode_pc=0x%8.8x", __FUNCTION__, m_last_decode_pc);
1847 
1848     switch (curr_isetstate) {
1849         case 0x0: // ARM Instruction
1850             // Read the ARM opcode
1851             if (m_thread->Process()->Task().ReadMemory(curr_pc, 4, &opcode32) != 4)
1852             {
1853                 DNBLogError("unable to read opcode bits 31:0 for an ARM opcode at 0x%8.8llx", (uint64_t)curr_pc);
1854                 decodeReturnCode = ARM_ERROR;
1855             }
1856             else
1857             {
1858                 nextPC += 4;
1859                 decodeReturnCode = ArmDisassembler((uint64_t)curr_pc, opcode32, false, decodedInstruction, NULL, 0, NULL, 0);
1860 
1861                 if (decodeReturnCode != ARM_SUCCESS)
1862                     DNBLogError("Unable to decode ARM instruction 0x%8.8x at 0x%8.8llx", opcode32, (uint64_t)curr_pc);
1863             }
1864             break;
1865 
1866         case 0x20: // Thumb Instruction
1867             uint16_t opcode16;
1868             // Read the a 16 bit Thumb opcode
1869             if (m_thread->Process()->Task().ReadMemory(curr_pc, 2, &opcode16) != 2)
1870             {
1871                 DNBLogError("unable to read opcode bits 15:0 for a thumb opcode at 0x%8.8llx", (uint64_t)curr_pc);
1872                 decodeReturnCode = ARM_ERROR;
1873             }
1874             else
1875             {
1876                 nextPC += 2;
1877                 opcode32 = opcode16;
1878 
1879                 decodeReturnCode = ThumbDisassembler((uint64_t)curr_pc, opcode16, false, false, thumbStaticData, decodedInstruction, NULL, 0, NULL, 0);
1880 
1881                 switch (decodeReturnCode) {
1882                     case ARM_SKIP:
1883                         // 32 bit thumb opcode
1884                         nextPC += 2;
1885                         if (m_thread->Process()->Task().ReadMemory(curr_pc+2, 2, &opcode16) != 2)
1886                         {
1887                             DNBLogError("unable to read opcode bits 15:0 for a thumb opcode at 0x%8.8llx", (uint64_t)curr_pc+2);
1888                         }
1889                         else
1890                         {
1891                             opcode32 = (opcode32 << 16) | opcode16;
1892 
1893                             decodeReturnCode = ThumbDisassembler((uint64_t)(curr_pc+2), opcode16, false, false, thumbStaticData, decodedInstruction, NULL, 0, NULL, 0);
1894 
1895                             if (decodeReturnCode != ARM_SUCCESS)
1896                                 DNBLogError("Unable to decode 2nd half of Thumb instruction 0x%8.4hx at 0x%8.8llx", opcode16, (uint64_t)curr_pc+2);
1897                             break;
1898                         }
1899                         break;
1900 
1901                     case ARM_SUCCESS:
1902                         // 16 bit thumb opcode; at this point we are done decoding the opcode
1903                         break;
1904 
1905                     default:
1906                         DNBLogError("Unable to decode Thumb instruction 0x%8.4hx at 0x%8.8llx", opcode16, (uint64_t)curr_pc);
1907                         decodeReturnCode = ARM_ERROR;
1908                         break;
1909                 }
1910             }
1911             break;
1912 
1913         default:
1914             break;
1915     }
1916 
1917     if (next_pc)
1918         *next_pc = nextPC;
1919 
1920     return decodeReturnCode;
1921 }
1922 
1923 #endif
1924 
1925 nub_bool_t
1926 DNBArchMachARM::BreakpointHit (nub_process_t pid, nub_thread_t tid, nub_break_t breakID, void *baton)
1927 {
1928     nub_addr_t bkpt_pc = (nub_addr_t)baton;
1929     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s(pid = %i, tid = %4.4x, breakID = %u, baton = %p): Setting PC to 0x%8.8x", __FUNCTION__, pid, tid, breakID, baton, bkpt_pc);
1930 
1931     DNBRegisterValue pc_value;
1932     DNBThreadGetRegisterValueByID (pid, tid, REGISTER_SET_GENERIC, GENERIC_REGNUM_PC, &pc_value);
1933     pc_value.value.uint32 = bkpt_pc;
1934     return DNBThreadSetRegisterValueByID (pid, tid, REGISTER_SET_GENERIC, GENERIC_REGNUM_PC, &pc_value);
1935 }
1936 
1937 // Set the single step bit in the processor status register.
1938 kern_return_t
1939 DNBArchMachARM::SetSingleStepSoftwareBreakpoints()
1940 {
1941     DNBError err;
1942 
1943 #if defined (USE_ARM_DISASSEMBLER_FRAMEWORK)
1944     err = GetGPRState(false);
1945 
1946     if (err.Fail())
1947     {
1948         err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__);
1949         return err.Error();
1950     }
1951 
1952     nub_addr_t curr_pc = m_state.context.gpr.__pc;
1953     uint32_t curr_cpsr = m_state.context.gpr.__cpsr;
1954     nub_addr_t next_pc = curr_pc;
1955 
1956     bool curr_pc_is_thumb = (m_state.context.gpr.__cpsr & 0x20) != 0;
1957     bool next_pc_is_thumb = curr_pc_is_thumb;
1958 
1959     uint32_t curr_itstate = ((curr_cpsr & 0x6000000) >> 25) | ((curr_cpsr & 0xFC00) >> 8);
1960     bool inITBlock = (curr_itstate & 0xF) ? 1 : 0;
1961     bool lastInITBlock = ((curr_itstate & 0xF) == 0x8) ? 1 : 0;
1962 
1963     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: curr_pc=0x%8.8x (%s), curr_itstate=0x%x, inITBlock=%d, lastInITBlock=%d", __FUNCTION__, curr_pc, curr_pc_is_thumb ? "Thumb" : "ARM", curr_itstate, inITBlock, lastInITBlock);
1964 
1965     // If the instruction is not in the IT block, then decode using the Disassembler and compute next_pc
1966     if (!inITBlock)
1967     {
1968         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Decoding an instruction NOT in the IT block", __FUNCTION__);
1969 
1970         arm_error_t decodeReturnCode =  DecodeInstructionUsingDisassembler(curr_pc, curr_cpsr, &m_last_decode_arm, &m_last_decode_thumb, &next_pc);
1971 
1972         if (decodeReturnCode != ARM_SUCCESS)
1973         {
1974             err = KERN_INVALID_ARGUMENT;
1975             DNBLogError("DNBArchMachARM::SetSingleStepSoftwareBreakpoints: Unable to disassemble instruction at 0x%8.8llx", (uint64_t)curr_pc);
1976         }
1977     }
1978     else
1979     {
1980         next_pc = curr_pc + ((m_last_decode_arm.thumb16b) ? 2 : 4);
1981     }
1982 
1983     // Instruction is NOT in the IT block OR
1984     if (!inITBlock)
1985     {
1986         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: normal instruction", __FUNCTION__);
1987         EvaluateNextInstructionForSoftwareBreakpointSetup(curr_pc, m_state.context.gpr.__cpsr, curr_pc_is_thumb, &next_pc, &next_pc_is_thumb);
1988     }
1989     else if (inITBlock && !m_last_decode_arm.setsFlags)
1990     {
1991         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: IT instruction that doesn't set flags", __FUNCTION__);
1992         EvaluateNextInstructionForSoftwareBreakpointSetup(curr_pc, m_state.context.gpr.__cpsr, curr_pc_is_thumb, &next_pc, &next_pc_is_thumb);
1993     }
1994     else if (lastInITBlock && m_last_decode_arm.branch)
1995     {
1996         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: IT instruction which last in the IT block and is a branch", __FUNCTION__);
1997         EvaluateNextInstructionForSoftwareBreakpointSetup(curr_pc, m_state.context.gpr.__cpsr, curr_pc_is_thumb, &next_pc, &next_pc_is_thumb);
1998     }
1999     else
2000     {
2001         // Instruction is in IT block and can modify the CPSR flags
2002         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: IT instruction that sets flags", __FUNCTION__);
2003 
2004         // NOTE: When this point of code is reached, the instruction at curr_pc has already been decoded
2005         // inside the function ThreadDidStop(). Therefore m_last_decode_arm, m_last_decode_thumb
2006         // reflect the decoded instruction at curr_pc
2007 
2008         // If we find an instruction inside the IT block which will set/modify the condition flags (NZCV bits in CPSR),
2009         // we set breakpoints at all remaining instructions inside the IT block starting from the instruction immediately
2010         // following this one AND a breakpoint at the instruction immediately following the IT block. We do this because
2011         // we cannot determine the next_pc until the instruction at which we are currently stopped executes. Hence we
2012         // insert (m_last_decode_thumb.itBlockRemaining+1) 16-bit Thumb breakpoints at consecutive memory locations
2013         // starting at addrOfNextInstructionInITBlock. We record these breakpoints in class variable m_sw_single_step_itblock_break_id[],
2014         // and also record the total number of IT breakpoints set in the variable 'm_sw_single_step_itblock_break_count'.
2015 
2016         // The instructions inside the IT block, which are replaced by the 16-bit Thumb breakpoints (opcode=0xDEFE)
2017         // instructions, can be either Thumb-16 or Thumb-32. When a Thumb-32 instruction (say, inst#1) is replaced  Thumb
2018         // by a 16-bit breakpoint (OS only supports 16-bit breakpoints in Thumb mode and 32-bit breakpoints in ARM mode), the
2019         // breakpoint for the next instruction (say instr#2) is saved in the upper half of this Thumb-32 (instr#1)
2020         // instruction. Hence if the execution stops at Breakpoint2 corresponding to instr#2, the PC is offset by 16-bits.
2021         // We therefore have to keep track of PC of each instruction in the IT block that is being replaced with the 16-bit
2022         // Thumb breakpoint, to ensure that when the breakpoint is hit, the PC is adjusted to the correct value. We save
2023         // the actual PC corresponding to each instruction in the IT block by associating a call back with each breakpoint
2024         // we set and passing it as a baton. When the breakpoint hits and the callback routine is called, the routine
2025         // adjusts the PC based on the baton that is passed to it.
2026 
2027         nub_addr_t addrOfNextInstructionInITBlock, pcInITBlock, nextPCInITBlock, bpAddressInITBlock;
2028         uint16_t opcode16;
2029         uint32_t opcode32;
2030 
2031         addrOfNextInstructionInITBlock = (m_last_decode_arm.thumb16b) ? curr_pc + 2 : curr_pc + 4;
2032 
2033         pcInITBlock = addrOfNextInstructionInITBlock;
2034 
2035         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: itBlockRemaining=%d", __FUNCTION__, m_last_decode_thumb.itBlockRemaining);
2036 
2037         m_sw_single_step_itblock_break_count = 0;
2038         for (int i = 0; i <= m_last_decode_thumb.itBlockRemaining; i++)
2039         {
2040             if (NUB_BREAK_ID_IS_VALID(m_sw_single_step_itblock_break_id[i]))
2041             {
2042                 DNBLogError("FunctionProfiler::SetSingleStepSoftwareBreakpoints(): Array m_sw_single_step_itblock_break_id should not contain any valid breakpoint IDs at this point. But found a valid breakID=%d at index=%d", m_sw_single_step_itblock_break_id[i], i);
2043             }
2044             else
2045             {
2046                 nextPCInITBlock = pcInITBlock;
2047                 // Compute nextPCInITBlock based on opcode present at pcInITBlock
2048                 if (m_thread->Process()->Task().ReadMemory(pcInITBlock, 2, &opcode16) == 2)
2049                 {
2050                     opcode32 = opcode16;
2051                     nextPCInITBlock += 2;
2052 
2053                     // Check for 32 bit thumb opcode and read the upper 16 bits if needed
2054                     if (((opcode32 & 0xE000) == 0xE000) && (opcode32 & 0x1800))
2055                     {
2056                         // Adjust 'next_pc_in_itblock' to point to the default next Thumb instruction for
2057                         // a 32 bit Thumb opcode
2058                         // Read bits 31:16 of a 32 bit Thumb opcode
2059                         if (m_thread->Process()->Task().ReadMemory(pcInITBlock+2, 2, &opcode16) == 2)
2060                         {
2061                             // 32 bit thumb opcode
2062                             opcode32 = (opcode32 << 16) | opcode16;
2063                             nextPCInITBlock += 2;
2064                         }
2065                         else
2066                         {
2067                             DNBLogError("FunctionProfiler::SetSingleStepSoftwareBreakpoints(): Unable to read opcode bits 31:16 for a 32 bit thumb opcode at pc=0x%8.8llx", (uint64_t)nextPCInITBlock);
2068                         }
2069                     }
2070                 }
2071                 else
2072                 {
2073                     DNBLogError("FunctionProfiler::SetSingleStepSoftwareBreakpoints(): Error reading 16-bit Thumb instruction at pc=0x%8.8x", nextPCInITBlock);
2074                 }
2075 
2076 
2077                 // Set breakpoint and associate a callback function with it
2078                 bpAddressInITBlock = addrOfNextInstructionInITBlock + 2*i;
2079                 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Setting IT breakpoint[%d] at address: 0x%8.8x", __FUNCTION__, i, bpAddressInITBlock);
2080 
2081                 m_sw_single_step_itblock_break_id[i] = m_thread->Process()->CreateBreakpoint(bpAddressInITBlock, 2, false, m_thread->ThreadID());
2082                 if (!NUB_BREAK_ID_IS_VALID(m_sw_single_step_itblock_break_id[i]))
2083                     err = KERN_INVALID_ARGUMENT;
2084                 else
2085                 {
2086                     DNBLogThreadedIf(LOG_STEP, "%s: Set IT breakpoint[%i]=%d set at 0x%8.8x for instruction at 0x%8.8x", __FUNCTION__, i, m_sw_single_step_itblock_break_id[i], bpAddressInITBlock, pcInITBlock);
2087 
2088                     // Set the breakpoint callback for these special IT breakpoints
2089                     // so that if one of these breakpoints gets hit, it knows to
2090                     // update the PC to the original address of the conditional
2091                     // IT instruction.
2092                     DNBBreakpointSetCallback(m_thread->ProcessID(), m_sw_single_step_itblock_break_id[i], DNBArchMachARM::BreakpointHit, (void*)pcInITBlock);
2093                     m_sw_single_step_itblock_break_count++;
2094                 }
2095             }
2096 
2097             pcInITBlock = nextPCInITBlock;
2098         }
2099 
2100         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Set %u IT software single breakpoints.", __FUNCTION__, m_sw_single_step_itblock_break_count);
2101 
2102     }
2103 
2104     DNBLogThreadedIf(LOG_STEP, "%s: next_pc=0x%8.8x (%s)", __FUNCTION__, next_pc, next_pc_is_thumb ? "Thumb" : "ARM");
2105 
2106     if (next_pc & 0x1)
2107     {
2108         assert(next_pc_is_thumb);
2109     }
2110 
2111     if (next_pc_is_thumb)
2112     {
2113         next_pc &= ~0x1;
2114     }
2115     else
2116     {
2117         assert((next_pc & 0x3) == 0);
2118     }
2119 
2120     if (!inITBlock || (inITBlock && !m_last_decode_arm.setsFlags) || (lastInITBlock && m_last_decode_arm.branch))
2121     {
2122         err = KERN_SUCCESS;
2123 
2124         const DNBBreakpoint *bp = m_thread->Process()->Breakpoints().FindByAddress(next_pc);
2125 
2126         if (bp == NULL)
2127         {
2128             m_sw_single_step_break_id = m_thread->Process()->CreateBreakpoint(next_pc, next_pc_is_thumb ? 2 : 4, false, m_thread->ThreadID());
2129             if (!NUB_BREAK_ID_IS_VALID(m_sw_single_step_break_id))
2130                 err = KERN_INVALID_ARGUMENT;
2131             DNBLogThreadedIf(LOG_STEP, "%s: software single step breakpoint with breakID=%d set at 0x%8.8x", __FUNCTION__, m_sw_single_step_break_id, next_pc);
2132         }
2133     }
2134 #else
2135     err.LogThreaded("%s: ARMDisassembler.framework support is disabled", __FUNCTION__);
2136 #endif
2137     return err.Error();
2138 }
2139 
2140 uint32_t
2141 DNBArchMachARM::NumSupportedHardwareBreakpoints()
2142 {
2143     // Set the init value to something that will let us know that we need to
2144     // autodetect how many breakpoints are supported dynamically...
2145     static uint32_t g_num_supported_hw_breakpoints = UINT_MAX;
2146     if (g_num_supported_hw_breakpoints == UINT_MAX)
2147     {
2148         // Set this to zero in case we can't tell if there are any HW breakpoints
2149         g_num_supported_hw_breakpoints = 0;
2150 
2151         size_t len;
2152         uint32_t n = 0;
2153         len = sizeof (n);
2154         if (::sysctlbyname("hw.optional.breakpoint", &n, &len, NULL, 0) == 0)
2155         {
2156             g_num_supported_hw_breakpoints = n;
2157             DNBLogThreadedIf(LOG_THREAD, "hw.optional.breakpoint=%u", n);
2158         }
2159         else
2160         {
2161             // Read the DBGDIDR to get the number of available hardware breakpoints
2162             // However, in some of our current armv7 processors, hardware
2163             // breakpoints/watchpoints were not properly connected. So detect those
2164             // cases using a field in a sysctl. For now we are using "hw.cpusubtype"
2165             // field to distinguish CPU architectures. This is a hack until we can
2166             // get <rdar://problem/6372672> fixed, at which point we will switch to
2167             // using a different sysctl string that will tell us how many BRPs
2168             // are available to us directly without having to read DBGDIDR.
2169             uint32_t register_DBGDIDR;
2170 
2171             asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR));
2172             uint32_t numBRPs = bits(register_DBGDIDR, 27, 24);
2173             // Zero is reserved for the BRP count, so don't increment it if it is zero
2174             if (numBRPs > 0)
2175                 numBRPs++;
2176             DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number BRP pairs = %u)", register_DBGDIDR, numBRPs);
2177 
2178             if (numBRPs > 0)
2179             {
2180                 uint32_t cpusubtype;
2181                 len = sizeof(cpusubtype);
2182                 // TODO: remove this hack and change to using hw.optional.xx when implmented
2183                 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
2184                 {
2185                     DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=%d", cpusubtype);
2186                     if (cpusubtype == CPU_SUBTYPE_ARM_V7)
2187                         DNBLogThreadedIf(LOG_THREAD, "Hardware breakpoints disabled for armv7 (rdar://problem/6372672)");
2188                     else
2189                         g_num_supported_hw_breakpoints = numBRPs;
2190                 }
2191             }
2192         }
2193     }
2194     return g_num_supported_hw_breakpoints;
2195 }
2196 
2197 
2198 uint32_t
2199 DNBArchMachARM::NumSupportedHardwareWatchpoints()
2200 {
2201     // Set the init value to something that will let us know that we need to
2202     // autodetect how many watchpoints are supported dynamically...
2203     static uint32_t g_num_supported_hw_watchpoints = UINT_MAX;
2204     if (g_num_supported_hw_watchpoints == UINT_MAX)
2205     {
2206         // Set this to zero in case we can't tell if there are any HW breakpoints
2207         g_num_supported_hw_watchpoints = 0;
2208 
2209 
2210         size_t len;
2211         uint32_t n = 0;
2212         len = sizeof (n);
2213         if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0)
2214         {
2215             g_num_supported_hw_watchpoints = n;
2216             DNBLogThreadedIf(LOG_THREAD, "hw.optional.watchpoint=%u", n);
2217         }
2218         else
2219         {
2220             // Read the DBGDIDR to get the number of available hardware breakpoints
2221             // However, in some of our current armv7 processors, hardware
2222             // breakpoints/watchpoints were not properly connected. So detect those
2223             // cases using a field in a sysctl. For now we are using "hw.cpusubtype"
2224             // field to distinguish CPU architectures. This is a hack until we can
2225             // get <rdar://problem/6372672> fixed, at which point we will switch to
2226             // using a different sysctl string that will tell us how many WRPs
2227             // are available to us directly without having to read DBGDIDR.
2228 
2229             uint32_t register_DBGDIDR;
2230             asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR));
2231             uint32_t numWRPs = bits(register_DBGDIDR, 31, 28) + 1;
2232             DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number WRP pairs = %u)", register_DBGDIDR, numWRPs);
2233 
2234             if (numWRPs > 0)
2235             {
2236                 uint32_t cpusubtype;
2237                 size_t len;
2238                 len = sizeof(cpusubtype);
2239                 // TODO: remove this hack and change to using hw.optional.xx when implmented
2240                 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
2241                 {
2242                     DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=0x%d", cpusubtype);
2243 
2244                     if (cpusubtype == CPU_SUBTYPE_ARM_V7)
2245                         DNBLogThreadedIf(LOG_THREAD, "Hardware watchpoints disabled for armv7 (rdar://problem/6372672)");
2246                     else
2247                         g_num_supported_hw_watchpoints = numWRPs;
2248                 }
2249             }
2250         }
2251     }
2252     return g_num_supported_hw_watchpoints;
2253 }
2254 
2255 
2256 uint32_t
2257 DNBArchMachARM::EnableHardwareBreakpoint (nub_addr_t addr, nub_size_t size)
2258 {
2259     // Make sure our address isn't bogus
2260     if (addr & 1)
2261         return INVALID_NUB_HW_INDEX;
2262 
2263     kern_return_t kret = GetDBGState(false);
2264 
2265     if (kret == KERN_SUCCESS)
2266     {
2267         const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints();
2268         uint32_t i;
2269         for (i=0; i<num_hw_breakpoints; ++i)
2270         {
2271             if ((m_state.dbg.__bcr[i] & BCR_ENABLE) == 0)
2272                 break; // We found an available hw breakpoint slot (in i)
2273         }
2274 
2275         // See if we found an available hw breakpoint slot above
2276         if (i < num_hw_breakpoints)
2277         {
2278             // Make sure bits 1:0 are clear in our address
2279             m_state.dbg.__bvr[i] = addr & ~((nub_addr_t)3);
2280 
2281             if (size == 2 || addr & 2)
2282             {
2283                 uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1;
2284 
2285                 // We have a thumb breakpoint
2286                 // We have an ARM breakpoint
2287                 m_state.dbg.__bcr[i] =  BCR_M_IMVA_MATCH |  // Stop on address mismatch
2288                                         byte_addr_select |  // Set the correct byte address select so we only trigger on the correct opcode
2289                                         S_USER |            // Which modes should this breakpoint stop in?
2290                                         BCR_ENABLE;         // Enable this hardware breakpoint
2291                 DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint( addr = 0x%8.8llx, size = %zu ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (Thumb)",
2292                                   (uint64_t)addr,
2293                                   size,
2294                                   i,
2295                                   i,
2296                                   m_state.dbg.__bvr[i],
2297                                   m_state.dbg.__bcr[i]);
2298             }
2299             else if (size == 4)
2300             {
2301                 // We have an ARM breakpoint
2302                 m_state.dbg.__bcr[i] =  BCR_M_IMVA_MATCH |  // Stop on address mismatch
2303                                         BAS_IMVA_ALL |      // Stop on any of the four bytes following the IMVA
2304                                         S_USER |            // Which modes should this breakpoint stop in?
2305                                         BCR_ENABLE;         // Enable this hardware breakpoint
2306                 DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint( addr = 0x%8.8llx, size = %zu ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (ARM)",
2307                                   (uint64_t)addr,
2308                                   size,
2309                                   i,
2310                                   i,
2311                                   m_state.dbg.__bvr[i],
2312                                   m_state.dbg.__bcr[i]);
2313             }
2314 
2315             kret = SetDBGState();
2316             DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint() SetDBGState() => 0x%8.8x.", kret);
2317 
2318             if (kret == KERN_SUCCESS)
2319                 return i;
2320         }
2321         else
2322         {
2323             DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint(addr = 0x%8.8llx, size = %zu) => all hardware breakpoint resources are being used.", (uint64_t)addr, size);
2324         }
2325     }
2326 
2327     return INVALID_NUB_HW_INDEX;
2328 }
2329 
2330 bool
2331 DNBArchMachARM::DisableHardwareBreakpoint (uint32_t hw_index)
2332 {
2333     kern_return_t kret = GetDBGState(false);
2334 
2335     const uint32_t num_hw_points = NumSupportedHardwareBreakpoints();
2336     if (kret == KERN_SUCCESS)
2337     {
2338         if (hw_index < num_hw_points)
2339         {
2340             m_state.dbg.__bcr[hw_index] = 0;
2341             DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::SetHardwareBreakpoint( %u ) - BVR%u = 0x%8.8x  BCR%u = 0x%8.8x",
2342                     hw_index,
2343                     hw_index,
2344                     m_state.dbg.__bvr[hw_index],
2345                     hw_index,
2346                     m_state.dbg.__bcr[hw_index]);
2347 
2348             kret = SetDBGState();
2349 
2350             if (kret == KERN_SUCCESS)
2351                 return true;
2352         }
2353     }
2354     return false;
2355 }
2356 
2357 // This stores the lo->hi mappings.  It's safe to initialize to all 0's
2358 // since hi > lo and therefore LoHi[i] cannot be 0.
2359 static uint32_t LoHi[16] = { 0 };
2360 
2361 uint32_t
2362 DNBArchMachARM::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write)
2363 {
2364     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(addr = 0x%8.8llx, size = %zu, read = %u, write = %u)", (uint64_t)addr, size, read, write);
2365 
2366     const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
2367 
2368     // Can't watch zero bytes
2369     if (size == 0)
2370         return INVALID_NUB_HW_INDEX;
2371 
2372     // We must watch for either read or write
2373     if (read == false && write == false)
2374         return INVALID_NUB_HW_INDEX;
2375 
2376     // Divide-and-conquer for size == 8.
2377     if (size == 8)
2378     {
2379         uint32_t lo = EnableHardwareWatchpoint(addr, 4, read, write);
2380         if (lo == INVALID_NUB_HW_INDEX)
2381             return INVALID_NUB_HW_INDEX;
2382         uint32_t hi = EnableHardwareWatchpoint(addr+4, 4, read, write);
2383         if (hi == INVALID_NUB_HW_INDEX)
2384         {
2385             DisableHardwareWatchpoint(lo);
2386             return INVALID_NUB_HW_INDEX;
2387         }
2388         // Tag this lo->hi mapping in our database.
2389         LoHi[lo] = hi;
2390         return lo;
2391     }
2392 
2393     // Otherwise, can't watch more than 4 bytes per WVR/WCR pair
2394     if (size > 4)
2395         return INVALID_NUB_HW_INDEX;
2396 
2397     // We can only watch up to four bytes that follow a 4 byte aligned address
2398     // per watchpoint register pair. Since we can only watch until the next 4
2399     // byte boundary, we need to make sure we can properly encode this.
2400 
2401     // addr_word_offset = addr % 4, i.e, is in set([0, 1, 2, 3])
2402     //
2403     //     +---+---+---+---+
2404     //     | 0 | 1 | 2 | 3 |
2405     //     +---+---+---+---+
2406     //     ^
2407     //     |
2408     // word address (4-byte aligned) = addr & 0xFFFFFFFC => goes into WVR
2409     //
2410     // examples:
2411     // 1. addr_word_offset = 1, size = 1 to watch a uint_8 => byte_mask = (0b0001 << 1) = 0b0010
2412     // 2. addr_word_offset = 2, size = 2 to watch a uint_16 => byte_mask = (0b0011 << 2) = 0b1100
2413     //
2414     // where byte_mask goes into WCR[8:5]
2415 
2416     uint32_t addr_word_offset = addr % 4;
2417     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset);
2418 
2419     uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
2420     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask);
2421     if (byte_mask > 0xfu)
2422         return INVALID_NUB_HW_INDEX;
2423 
2424     // Read the debug state
2425     kern_return_t kret = GetDBGState(false);
2426 
2427     if (kret == KERN_SUCCESS)
2428     {
2429         // Check to make sure we have the needed hardware support
2430         uint32_t i = 0;
2431 
2432         for (i=0; i<num_hw_watchpoints; ++i)
2433         {
2434             if ((m_state.dbg.__wcr[i] & WCR_ENABLE) == 0)
2435                 break; // We found an available hw watchpoint slot (in i)
2436         }
2437 
2438         // See if we found an available hw watchpoint slot above
2439         if (i < num_hw_watchpoints)
2440         {
2441             //DumpDBGState(m_state.dbg);
2442 
2443             // Make the byte_mask into a valid Byte Address Select mask
2444             uint32_t byte_address_select = byte_mask << 5;
2445             // Make sure bits 1:0 are clear in our address
2446             m_state.dbg.__wvr[i] = addr & ~((nub_addr_t)3);     // DVA (Data Virtual Address)
2447             m_state.dbg.__wcr[i] =  byte_address_select |       // Which bytes that follow the DVA that we will watch
2448                                     S_USER |                    // Stop only in user mode
2449                                     (read ? WCR_LOAD : 0) |     // Stop on read access?
2450                                     (write ? WCR_STORE : 0) |   // Stop on write access?
2451                                     WCR_ENABLE;                 // Enable this watchpoint;
2452 
2453             kret = SetDBGState();
2454             //DumpDBGState(m_state.dbg);
2455 
2456             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret);
2457 
2458             if (kret == KERN_SUCCESS)
2459                 return i;
2460         }
2461         else
2462         {
2463             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints);
2464         }
2465     }
2466     return INVALID_NUB_HW_INDEX;
2467 }
2468 
2469 bool
2470 DNBArchMachARM::EnableHardwareWatchpoint0 (uint32_t hw_index, bool Delegate)
2471 {
2472     kern_return_t kret = GetDBGState(false);
2473     if (kret != KERN_SUCCESS)
2474         return false;
2475 
2476     const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
2477     if (hw_index >= num_hw_points)
2478         return false;
2479 
2480     if (Delegate && LoHi[hw_index]) {
2481         // Enable lo and hi watchpoint hardware indexes.
2482         return EnableHardwareWatchpoint0(hw_index, false) &&
2483             EnableHardwareWatchpoint0(LoHi[hw_index], false);
2484     }
2485 
2486     m_state.dbg.__wcr[hw_index] |= (nub_addr_t)WCR_ENABLE;
2487     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x  WCR%u = 0x%8.8x",
2488                      hw_index,
2489                      hw_index,
2490                      m_state.dbg.__wvr[hw_index],
2491                      hw_index,
2492                      m_state.dbg.__wcr[hw_index]);
2493 
2494     kret = SetDBGState();
2495 
2496     return (kret == KERN_SUCCESS);
2497 }
2498 
2499 bool
2500 DNBArchMachARM::DisableHardwareWatchpoint (uint32_t hw_index)
2501 {
2502     return DisableHardwareWatchpoint0(hw_index, true);
2503 }
2504 bool
2505 DNBArchMachARM::DisableHardwareWatchpoint0 (uint32_t hw_index, bool Delegate)
2506 {
2507     kern_return_t kret = GetDBGState(false);
2508     if (kret != KERN_SUCCESS)
2509         return false;
2510 
2511     const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
2512     if (hw_index >= num_hw_points)
2513         return false;
2514 
2515     if (Delegate && LoHi[hw_index]) {
2516         // Disable lo and hi watchpoint hardware indexes.
2517         return DisableHardwareWatchpoint0(hw_index, false) &&
2518             DisableHardwareWatchpoint0(LoHi[hw_index], false);
2519     }
2520 
2521     m_state.dbg.__wcr[hw_index] &= ~((nub_addr_t)WCR_ENABLE);
2522     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::DisableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x  WCR%u = 0x%8.8x",
2523                      hw_index,
2524                      hw_index,
2525                      m_state.dbg.__wvr[hw_index],
2526                      hw_index,
2527                      m_state.dbg.__wcr[hw_index]);
2528 
2529     kret = SetDBGState();
2530 
2531     return (kret == KERN_SUCCESS);
2532 }
2533 
2534 // {0} -> __bvr[16], {0} -> __bcr[16], {0} --> __wvr[16], {0} -> __wcr{16}
2535 DNBArchMachARM::DBG DNBArchMachARM::Global_Debug_State = {{0},{0},{0},{0}};
2536 bool DNBArchMachARM::Valid_Global_Debug_State = false;
2537 
2538 // Use this callback from MachThread, which in turn was called from MachThreadList, to update
2539 // the global view of the hardware watchpoint state, so that when new thread comes along, they
2540 // get to inherit the existing hardware watchpoint state.
2541 void
2542 DNBArchMachARM::HardwareWatchpointStateChanged ()
2543 {
2544     Global_Debug_State = m_state.dbg;
2545     Valid_Global_Debug_State = true;
2546 }
2547 
2548 // Returns -1 if the trailing bit patterns are not one of:
2549 // { 0b???1, 0b??10, 0b?100, 0b1000 }.
2550 static inline
2551 int32_t
2552 LowestBitSet(uint32_t val)
2553 {
2554     for (unsigned i = 0; i < 4; ++i) {
2555         if (bit(val, i))
2556             return i;
2557     }
2558     return -1;
2559 }
2560 
2561 // Iterate through the debug registers; return the index of the first watchpoint whose address matches.
2562 // As a side effect, the starting address as understood by the debugger is returned which could be
2563 // different from 'addr' passed as an in/out argument.
2564 uint32_t
2565 DNBArchMachARM::GetHardwareWatchpointHit(nub_addr_t &addr)
2566 {
2567     // Read the debug state
2568     kern_return_t kret = GetDBGState(true);
2569     //DumpDBGState(m_state.dbg);
2570     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret);
2571     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::GetHardwareWatchpointHit() addr = 0x%llx", (uint64_t)addr);
2572 
2573     // This is the watchpoint value to match against, i.e., word address.
2574     nub_addr_t wp_val = addr & ~((nub_addr_t)3);
2575     if (kret == KERN_SUCCESS)
2576     {
2577         DBG &debug_state = m_state.dbg;
2578         uint32_t i, num = NumSupportedHardwareWatchpoints();
2579         for (i = 0; i < num; ++i)
2580         {
2581             nub_addr_t wp_addr = GetWatchAddress(debug_state, i);
2582             DNBLogThreadedIf(LOG_WATCHPOINTS,
2583                              "DNBArchMachARM::GetHardwareWatchpointHit() slot: %u (addr = 0x%llx).",
2584                              i, (uint64_t)wp_addr);
2585             if (wp_val == wp_addr) {
2586                 uint32_t byte_mask = bits(debug_state.__wcr[i], 8, 5);
2587 
2588                 // Sanity check the byte_mask, first.
2589                 if (LowestBitSet(byte_mask) < 0)
2590                     continue;
2591 
2592                 // Compute the starting address (from the point of view of the debugger).
2593                 addr = wp_addr + LowestBitSet(byte_mask);
2594                 return i;
2595             }
2596         }
2597     }
2598     return INVALID_NUB_HW_INDEX;
2599 }
2600 
2601 // ThreadWillResume() calls this to clear bits[5:2] (Method of entry bits) of
2602 // the Debug Status and Control Register (DSCR).
2603 //
2604 // b0010 = a watchpoint occurred
2605 // b0000 is the reset value
2606 void
2607 DNBArchMachARM::ClearWatchpointOccurred()
2608 {
2609     uint32_t register_DBGDSCR;
2610     asm("mrc p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR));
2611     if (bits(register_DBGDSCR, 5, 2) == WATCHPOINT_OCCURRED)
2612     {
2613         uint32_t mask = ~(0xF << 2);
2614         register_DBGDSCR &= mask;
2615         asm("mcr p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR));
2616     }
2617     return;
2618 }
2619 
2620 // NotifyException() calls this to double check that a watchpoint has occurred
2621 // by inspecting the bits[5:2] field of the Debug Status and Control Register
2622 // (DSCR).
2623 //
2624 // b0010 = a watchpoint occurred
2625 bool
2626 DNBArchMachARM::HasWatchpointOccurred()
2627 {
2628     uint32_t register_DBGDSCR;
2629     asm("mrc p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR));
2630     return (bits(register_DBGDSCR, 5, 2) == WATCHPOINT_OCCURRED);
2631 }
2632 
2633 bool
2634 DNBArchMachARM::IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index)
2635 {
2636     // Watchpoint Control Registers, bitfield definitions
2637     // ...
2638     // Bits    Value    Description
2639     // [0]     0        Watchpoint disabled
2640     //         1        Watchpoint enabled.
2641     return (debug_state.__wcr[hw_index] & 1u);
2642 }
2643 
2644 nub_addr_t
2645 DNBArchMachARM::GetWatchAddress(const DBG &debug_state, uint32_t hw_index)
2646 {
2647     // Watchpoint Value Registers, bitfield definitions
2648     // Bits        Description
2649     // [31:2]      Watchpoint value (word address, i.e., 4-byte aligned)
2650     // [1:0]       RAZ/SBZP
2651     return bits(debug_state.__wvr[hw_index], 31, 0);
2652 }
2653 
2654 //----------------------------------------------------------------------
2655 // Register information defintions for 32 bit ARMV6.
2656 //----------------------------------------------------------------------
2657 enum gpr_regnums
2658 {
2659     gpr_r0 = 0,
2660     gpr_r1,
2661     gpr_r2,
2662     gpr_r3,
2663     gpr_r4,
2664     gpr_r5,
2665     gpr_r6,
2666     gpr_r7,
2667     gpr_r8,
2668     gpr_r9,
2669     gpr_r10,
2670     gpr_r11,
2671     gpr_r12,
2672     gpr_sp,
2673     gpr_lr,
2674     gpr_pc,
2675     gpr_cpsr
2676 };
2677 
2678 enum
2679 {
2680     vfp_s0 = 0,
2681     vfp_s1,
2682     vfp_s2,
2683     vfp_s3,
2684     vfp_s4,
2685     vfp_s5,
2686     vfp_s6,
2687     vfp_s7,
2688     vfp_s8,
2689     vfp_s9,
2690     vfp_s10,
2691     vfp_s11,
2692     vfp_s12,
2693     vfp_s13,
2694     vfp_s14,
2695     vfp_s15,
2696     vfp_s16,
2697     vfp_s17,
2698     vfp_s18,
2699     vfp_s19,
2700     vfp_s20,
2701     vfp_s21,
2702     vfp_s22,
2703     vfp_s23,
2704     vfp_s24,
2705     vfp_s25,
2706     vfp_s26,
2707     vfp_s27,
2708     vfp_s28,
2709     vfp_s29,
2710     vfp_s30,
2711     vfp_s31,
2712     vfp_d0,
2713     vfp_d1,
2714     vfp_d2,
2715     vfp_d3,
2716     vfp_d4,
2717     vfp_d5,
2718     vfp_d6,
2719     vfp_d7,
2720     vfp_d8,
2721     vfp_d9,
2722     vfp_d10,
2723     vfp_d11,
2724     vfp_d12,
2725     vfp_d13,
2726     vfp_d14,
2727     vfp_d15,
2728     vfp_d16,
2729     vfp_d17,
2730     vfp_d18,
2731     vfp_d19,
2732     vfp_d20,
2733     vfp_d21,
2734     vfp_d22,
2735     vfp_d23,
2736     vfp_d24,
2737     vfp_d25,
2738     vfp_d26,
2739     vfp_d27,
2740     vfp_d28,
2741     vfp_d29,
2742     vfp_d30,
2743     vfp_d31,
2744     vfp_fpscr
2745 };
2746 
2747 enum
2748 {
2749     exc_exception,
2750 	exc_fsr,
2751 	exc_far,
2752 };
2753 
2754 enum
2755 {
2756     gdb_r0 = 0,
2757     gdb_r1,
2758     gdb_r2,
2759     gdb_r3,
2760     gdb_r4,
2761     gdb_r5,
2762     gdb_r6,
2763     gdb_r7,
2764     gdb_r8,
2765     gdb_r9,
2766     gdb_r10,
2767     gdb_r11,
2768     gdb_r12,
2769     gdb_sp,
2770     gdb_lr,
2771     gdb_pc,
2772     gdb_f0,
2773     gdb_f1,
2774     gdb_f2,
2775     gdb_f3,
2776     gdb_f4,
2777     gdb_f5,
2778     gdb_f6,
2779     gdb_f7,
2780     gdb_f8,
2781     gdb_cpsr,
2782     gdb_s0,
2783     gdb_s1,
2784     gdb_s2,
2785     gdb_s3,
2786     gdb_s4,
2787     gdb_s5,
2788     gdb_s6,
2789     gdb_s7,
2790     gdb_s8,
2791     gdb_s9,
2792     gdb_s10,
2793     gdb_s11,
2794     gdb_s12,
2795     gdb_s13,
2796     gdb_s14,
2797     gdb_s15,
2798     gdb_s16,
2799     gdb_s17,
2800     gdb_s18,
2801     gdb_s19,
2802     gdb_s20,
2803     gdb_s21,
2804     gdb_s22,
2805     gdb_s23,
2806     gdb_s24,
2807     gdb_s25,
2808     gdb_s26,
2809     gdb_s27,
2810     gdb_s28,
2811     gdb_s29,
2812     gdb_s30,
2813     gdb_s31,
2814     gdb_fpscr,
2815     gdb_d0,
2816     gdb_d1,
2817     gdb_d2,
2818     gdb_d3,
2819     gdb_d4,
2820     gdb_d5,
2821     gdb_d6,
2822     gdb_d7,
2823     gdb_d8,
2824     gdb_d9,
2825     gdb_d10,
2826     gdb_d11,
2827     gdb_d12,
2828     gdb_d13,
2829     gdb_d14,
2830     gdb_d15
2831 };
2832 
2833 #define GPR_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::GPR, __r[idx]))
2834 #define GPR_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::GPR, __##reg))
2835 #define VFP_S_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::FPU, __r[(idx)]) + offsetof (DNBArchMachARM::Context, vfp))
2836 #define VFP_D_OFFSET_IDX(idx) (VFP_S_OFFSET_IDX ((idx) * 2))
2837 #define VFP_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::FPU, __##reg) + offsetof (DNBArchMachARM::Context, vfp))
2838 #define EXC_OFFSET(reg)      (offsetof (DNBArchMachARM::EXC, __##reg)  + offsetof (DNBArchMachARM::Context, exc))
2839 
2840 // These macros will auto define the register name, alt name, register size,
2841 // register offset, encoding, format and native register. This ensures that
2842 // the register state structures are defined correctly and have the correct
2843 // sizes and offsets.
2844 #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, gdb_##reg }
2845 #define DEFINE_GPR_NAME(reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_NAME(reg), gcc_##reg, dwarf_##reg, gen, gdb_##reg }
2846 //#define FLOAT_FORMAT Float
2847 #define FLOAT_FORMAT Hex
2848 #define DEFINE_VFP_S_IDX(idx) { e_regSetVFP, vfp_s##idx, "s" #idx, NULL, IEEE754, FLOAT_FORMAT, 4, VFP_S_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_s##idx, INVALID_NUB_REGNUM, gdb_s##idx }
2849 //#define DEFINE_VFP_D_IDX(idx) { e_regSetVFP, vfp_d##idx, "d" #idx, NULL, IEEE754, Float, 8, VFP_D_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_d##idx, INVALID_NUB_REGNUM, gdb_d##idx }
2850 #define DEFINE_VFP_D_IDX(idx) { e_regSetVFP, vfp_d##idx, "d" #idx, NULL, IEEE754, FLOAT_FORMAT, 8, VFP_D_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_d##idx, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM }
2851 
2852 // General purpose registers
2853 const DNBRegisterInfo
2854 DNBArchMachARM::g_gpr_registers[] =
2855 {
2856     DEFINE_GPR_IDX ( 0,  r0,"arg1", GENERIC_REGNUM_ARG1  ),
2857     DEFINE_GPR_IDX ( 1,  r1,"arg2", GENERIC_REGNUM_ARG2  ),
2858     DEFINE_GPR_IDX ( 2,  r2,"arg3", GENERIC_REGNUM_ARG3  ),
2859     DEFINE_GPR_IDX ( 3,  r3,"arg4", GENERIC_REGNUM_ARG4  ),
2860     DEFINE_GPR_IDX ( 4,  r4,  NULL, INVALID_NUB_REGNUM   ),
2861     DEFINE_GPR_IDX ( 5,  r5,  NULL, INVALID_NUB_REGNUM   ),
2862     DEFINE_GPR_IDX ( 6,  r6,  NULL, INVALID_NUB_REGNUM   ),
2863     DEFINE_GPR_IDX ( 7,  r7,  "fp", GENERIC_REGNUM_FP    ),
2864     DEFINE_GPR_IDX ( 8,  r8,  NULL, INVALID_NUB_REGNUM   ),
2865     DEFINE_GPR_IDX ( 9,  r9,  NULL, INVALID_NUB_REGNUM   ),
2866     DEFINE_GPR_IDX (10, r10,  NULL, INVALID_NUB_REGNUM   ),
2867     DEFINE_GPR_IDX (11, r11,  NULL, INVALID_NUB_REGNUM   ),
2868     DEFINE_GPR_IDX (12, r12,  NULL, INVALID_NUB_REGNUM   ),
2869     DEFINE_GPR_NAME (sp, "r13", GENERIC_REGNUM_SP    ),
2870     DEFINE_GPR_NAME (lr, "r14", GENERIC_REGNUM_RA    ),
2871     DEFINE_GPR_NAME (pc, "r15", GENERIC_REGNUM_PC    ),
2872     DEFINE_GPR_NAME (cpsr, "flags", GENERIC_REGNUM_FLAGS )
2873 };
2874 
2875 // Floating point registers
2876 const DNBRegisterInfo
2877 DNBArchMachARM::g_vfp_registers[] =
2878 {
2879     DEFINE_VFP_S_IDX ( 0),
2880     DEFINE_VFP_S_IDX ( 1),
2881     DEFINE_VFP_S_IDX ( 2),
2882     DEFINE_VFP_S_IDX ( 3),
2883     DEFINE_VFP_S_IDX ( 4),
2884     DEFINE_VFP_S_IDX ( 5),
2885     DEFINE_VFP_S_IDX ( 6),
2886     DEFINE_VFP_S_IDX ( 7),
2887     DEFINE_VFP_S_IDX ( 8),
2888     DEFINE_VFP_S_IDX ( 9),
2889     DEFINE_VFP_S_IDX (10),
2890     DEFINE_VFP_S_IDX (11),
2891     DEFINE_VFP_S_IDX (12),
2892     DEFINE_VFP_S_IDX (13),
2893     DEFINE_VFP_S_IDX (14),
2894     DEFINE_VFP_S_IDX (15),
2895     DEFINE_VFP_S_IDX (16),
2896     DEFINE_VFP_S_IDX (17),
2897     DEFINE_VFP_S_IDX (18),
2898     DEFINE_VFP_S_IDX (19),
2899     DEFINE_VFP_S_IDX (20),
2900     DEFINE_VFP_S_IDX (21),
2901     DEFINE_VFP_S_IDX (22),
2902     DEFINE_VFP_S_IDX (23),
2903     DEFINE_VFP_S_IDX (24),
2904     DEFINE_VFP_S_IDX (25),
2905     DEFINE_VFP_S_IDX (26),
2906     DEFINE_VFP_S_IDX (27),
2907     DEFINE_VFP_S_IDX (28),
2908     DEFINE_VFP_S_IDX (29),
2909     DEFINE_VFP_S_IDX (30),
2910     DEFINE_VFP_S_IDX (31),
2911     DEFINE_VFP_D_IDX (0),
2912     DEFINE_VFP_D_IDX (1),
2913     DEFINE_VFP_D_IDX (2),
2914     DEFINE_VFP_D_IDX (3),
2915     DEFINE_VFP_D_IDX (4),
2916     DEFINE_VFP_D_IDX (5),
2917     DEFINE_VFP_D_IDX (6),
2918     DEFINE_VFP_D_IDX (7),
2919     DEFINE_VFP_D_IDX (8),
2920     DEFINE_VFP_D_IDX (9),
2921     DEFINE_VFP_D_IDX (10),
2922     DEFINE_VFP_D_IDX (11),
2923     DEFINE_VFP_D_IDX (12),
2924     DEFINE_VFP_D_IDX (13),
2925     DEFINE_VFP_D_IDX (14),
2926     DEFINE_VFP_D_IDX (15),
2927     DEFINE_VFP_D_IDX (16),
2928     DEFINE_VFP_D_IDX (17),
2929     DEFINE_VFP_D_IDX (18),
2930     DEFINE_VFP_D_IDX (19),
2931     DEFINE_VFP_D_IDX (20),
2932     DEFINE_VFP_D_IDX (21),
2933     DEFINE_VFP_D_IDX (22),
2934     DEFINE_VFP_D_IDX (23),
2935     DEFINE_VFP_D_IDX (24),
2936     DEFINE_VFP_D_IDX (25),
2937     DEFINE_VFP_D_IDX (26),
2938     DEFINE_VFP_D_IDX (27),
2939     DEFINE_VFP_D_IDX (28),
2940     DEFINE_VFP_D_IDX (29),
2941     DEFINE_VFP_D_IDX (30),
2942     DEFINE_VFP_D_IDX (31),
2943     { e_regSetVFP, vfp_fpscr, "fpscr", NULL, Uint, Hex, 4, VFP_OFFSET_NAME(fpscr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, gdb_fpscr }
2944 };
2945 
2946 // Exception registers
2947 
2948 const DNBRegisterInfo
2949 DNBArchMachARM::g_exc_registers[] =
2950 {
2951   { e_regSetVFP, exc_exception  , "exception"   , NULL, Uint, Hex, 4, EXC_OFFSET(exception) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM },
2952   { e_regSetVFP, exc_fsr        , "fsr"         , NULL, Uint, Hex, 4, EXC_OFFSET(fsr)       , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM },
2953   { e_regSetVFP, exc_far        , "far"         , NULL, Uint, Hex, 4, EXC_OFFSET(far)       , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM }
2954 };
2955 
2956 // Number of registers in each register set
2957 const size_t DNBArchMachARM::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo);
2958 const size_t DNBArchMachARM::k_num_vfp_registers = sizeof(g_vfp_registers)/sizeof(DNBRegisterInfo);
2959 const size_t DNBArchMachARM::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo);
2960 const size_t DNBArchMachARM::k_num_all_registers = k_num_gpr_registers + k_num_vfp_registers + k_num_exc_registers;
2961 
2962 //----------------------------------------------------------------------
2963 // Register set definitions. The first definitions at register set index
2964 // of zero is for all registers, followed by other registers sets. The
2965 // register information for the all register set need not be filled in.
2966 //----------------------------------------------------------------------
2967 const DNBRegisterSetInfo
2968 DNBArchMachARM::g_reg_sets[] =
2969 {
2970     { "ARM Registers",              NULL,               k_num_all_registers     },
2971     { "General Purpose Registers",  g_gpr_registers,    k_num_gpr_registers     },
2972     { "Floating Point Registers",   g_vfp_registers,    k_num_vfp_registers     },
2973     { "Exception State Registers",  g_exc_registers,    k_num_exc_registers     }
2974 };
2975 // Total number of register sets for this architecture
2976 const size_t DNBArchMachARM::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo);
2977 
2978 
2979 const DNBRegisterSetInfo *
2980 DNBArchMachARM::GetRegisterSetInfo(nub_size_t *num_reg_sets)
2981 {
2982     *num_reg_sets = k_num_register_sets;
2983     return g_reg_sets;
2984 }
2985 
2986 bool
2987 DNBArchMachARM::GetRegisterValue(int set, int reg, DNBRegisterValue *value)
2988 {
2989     if (set == REGISTER_SET_GENERIC)
2990     {
2991         switch (reg)
2992         {
2993         case GENERIC_REGNUM_PC:     // Program Counter
2994             set = e_regSetGPR;
2995             reg = gpr_pc;
2996             break;
2997 
2998         case GENERIC_REGNUM_SP:     // Stack Pointer
2999             set = e_regSetGPR;
3000             reg = gpr_sp;
3001             break;
3002 
3003         case GENERIC_REGNUM_FP:     // Frame Pointer
3004             set = e_regSetGPR;
3005             reg = gpr_r7;   // is this the right reg?
3006             break;
3007 
3008         case GENERIC_REGNUM_RA:     // Return Address
3009             set = e_regSetGPR;
3010             reg = gpr_lr;
3011             break;
3012 
3013         case GENERIC_REGNUM_FLAGS:  // Processor flags register
3014             set = e_regSetGPR;
3015             reg = gpr_cpsr;
3016             break;
3017 
3018         default:
3019             return false;
3020         }
3021     }
3022 
3023     if (GetRegisterState(set, false) != KERN_SUCCESS)
3024         return false;
3025 
3026     const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
3027     if (regInfo)
3028     {
3029         value->info = *regInfo;
3030         switch (set)
3031         {
3032         case e_regSetGPR:
3033             if (reg < k_num_gpr_registers)
3034             {
3035                 value->value.uint32 = m_state.context.gpr.__r[reg];
3036                 return true;
3037             }
3038             break;
3039 
3040         case e_regSetVFP:
3041             if (reg <= vfp_s31)
3042             {
3043                 value->value.uint32 = m_state.context.vfp.__r[reg];
3044                 return true;
3045             }
3046             else if (reg <= vfp_d31)
3047             {
3048                 uint32_t d_reg_idx = reg - vfp_d0;
3049                 uint32_t s_reg_idx = d_reg_idx * 2;
3050                 value->value.v_sint32[0] = m_state.context.vfp.__r[s_reg_idx + 0];
3051                 value->value.v_sint32[1] = m_state.context.vfp.__r[s_reg_idx + 1];
3052                 return true;
3053             }
3054             else if (reg == vfp_fpscr)
3055             {
3056                 value->value.uint32 = m_state.context.vfp.__fpscr;
3057                 return true;
3058             }
3059             break;
3060 
3061         case e_regSetEXC:
3062             if (reg < k_num_exc_registers)
3063             {
3064                 value->value.uint32 = (&m_state.context.exc.__exception)[reg];
3065                 return true;
3066             }
3067             break;
3068         }
3069     }
3070     return false;
3071 }
3072 
3073 bool
3074 DNBArchMachARM::SetRegisterValue(int set, int reg, const DNBRegisterValue *value)
3075 {
3076     if (set == REGISTER_SET_GENERIC)
3077     {
3078         switch (reg)
3079         {
3080         case GENERIC_REGNUM_PC:     // Program Counter
3081             set = e_regSetGPR;
3082             reg = gpr_pc;
3083             break;
3084 
3085         case GENERIC_REGNUM_SP:     // Stack Pointer
3086             set = e_regSetGPR;
3087             reg = gpr_sp;
3088             break;
3089 
3090         case GENERIC_REGNUM_FP:     // Frame Pointer
3091             set = e_regSetGPR;
3092             reg = gpr_r7;
3093             break;
3094 
3095         case GENERIC_REGNUM_RA:     // Return Address
3096             set = e_regSetGPR;
3097             reg = gpr_lr;
3098             break;
3099 
3100         case GENERIC_REGNUM_FLAGS:  // Processor flags register
3101             set = e_regSetGPR;
3102             reg = gpr_cpsr;
3103             break;
3104 
3105         default:
3106             return false;
3107         }
3108     }
3109 
3110     if (GetRegisterState(set, false) != KERN_SUCCESS)
3111         return false;
3112 
3113     bool success = false;
3114     const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
3115     if (regInfo)
3116     {
3117         switch (set)
3118         {
3119         case e_regSetGPR:
3120             if (reg < k_num_gpr_registers)
3121             {
3122                 m_state.context.gpr.__r[reg] = value->value.uint32;
3123                 success = true;
3124             }
3125             break;
3126 
3127         case e_regSetVFP:
3128             if (reg <= vfp_s31)
3129             {
3130                 m_state.context.vfp.__r[reg] = value->value.uint32;
3131                 success = true;
3132             }
3133             else if (reg <= vfp_d31)
3134             {
3135                 uint32_t d_reg_idx = reg - vfp_d0;
3136                 uint32_t s_reg_idx = d_reg_idx * 2;
3137                 m_state.context.vfp.__r[s_reg_idx + 0] = value->value.v_sint32[0];
3138                 m_state.context.vfp.__r[s_reg_idx + 1] = value->value.v_sint32[1];
3139                 success = true;
3140             }
3141             else if (reg == vfp_fpscr)
3142             {
3143                 m_state.context.vfp.__fpscr = value->value.uint32;
3144                 success = true;
3145             }
3146             break;
3147 
3148         case e_regSetEXC:
3149             if (reg < k_num_exc_registers)
3150             {
3151                 (&m_state.context.exc.__exception)[reg] = value->value.uint32;
3152                 success = true;
3153             }
3154             break;
3155         }
3156 
3157     }
3158     if (success)
3159         return SetRegisterState(set) == KERN_SUCCESS;
3160     return false;
3161 }
3162 
3163 kern_return_t
3164 DNBArchMachARM::GetRegisterState(int set, bool force)
3165 {
3166     switch (set)
3167     {
3168     case e_regSetALL:   return GetGPRState(force) |
3169                                GetVFPState(force) |
3170                                GetEXCState(force) |
3171                                GetDBGState(force);
3172     case e_regSetGPR:   return GetGPRState(force);
3173     case e_regSetVFP:   return GetVFPState(force);
3174     case e_regSetEXC:   return GetEXCState(force);
3175     case e_regSetDBG:   return GetDBGState(force);
3176     default: break;
3177     }
3178     return KERN_INVALID_ARGUMENT;
3179 }
3180 
3181 kern_return_t
3182 DNBArchMachARM::SetRegisterState(int set)
3183 {
3184     // Make sure we have a valid context to set.
3185     kern_return_t err = GetRegisterState(set, false);
3186     if (err != KERN_SUCCESS)
3187         return err;
3188 
3189     switch (set)
3190     {
3191     case e_regSetALL:   return SetGPRState() |
3192                                SetVFPState() |
3193                                SetEXCState() |
3194                                SetDBGState();
3195     case e_regSetGPR:   return SetGPRState();
3196     case e_regSetVFP:   return SetVFPState();
3197     case e_regSetEXC:   return SetEXCState();
3198     case e_regSetDBG:   return SetDBGState();
3199     default: break;
3200     }
3201     return KERN_INVALID_ARGUMENT;
3202 }
3203 
3204 bool
3205 DNBArchMachARM::RegisterSetStateIsValid (int set) const
3206 {
3207     return m_state.RegsAreValid(set);
3208 }
3209 
3210 
3211 nub_size_t
3212 DNBArchMachARM::GetRegisterContext (void *buf, nub_size_t buf_len)
3213 {
3214     nub_size_t size = sizeof (m_state.context);
3215 
3216     if (buf && buf_len)
3217     {
3218         if (size > buf_len)
3219             size = buf_len;
3220 
3221         bool force = false;
3222         if (GetGPRState(force) | GetVFPState(force) | GetEXCState(force))
3223             return 0;
3224         ::memcpy (buf, &m_state.context, size);
3225     }
3226     DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::GetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size);
3227     // Return the size of the register context even if NULL was passed in
3228     return size;
3229 }
3230 
3231 nub_size_t
3232 DNBArchMachARM::SetRegisterContext (const void *buf, nub_size_t buf_len)
3233 {
3234     nub_size_t size = sizeof (m_state.context);
3235     if (buf == NULL || buf_len == 0)
3236         size = 0;
3237 
3238     if (size)
3239     {
3240         if (size > buf_len)
3241             size = buf_len;
3242 
3243         ::memcpy (&m_state.context, buf, size);
3244         SetGPRState();
3245         SetVFPState();
3246         SetEXCState();
3247     }
3248     DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::SetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size);
3249     return size;
3250 }
3251 
3252 
3253 #endif    // #if defined (__arm__)
3254 
3255