1 //===-- DNBArchMachARM64.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__) || defined (__arm64__) || defined (__aarch64__)
15 
16 #include "MacOSX/arm64/DNBArchImplARM64.h"
17 
18 #if defined (ARM_THREAD_STATE64_COUNT)
19 
20 #include "MacOSX/MachProcess.h"
21 #include "MacOSX/MachThread.h"
22 #include "DNBBreakpoint.h"
23 #include "DNBLog.h"
24 #include "DNBRegisterInfo.h"
25 #include "DNB.h"
26 
27 #include <inttypes.h>
28 #include <sys/sysctl.h>
29 
30 // Break only in privileged or user mode
31 // (PAC bits in the DBGWVRn_EL1 watchpoint control register)
32 #define S_USER                  ((uint32_t)(2u << 1))
33 
34 #define BCR_ENABLE              ((uint32_t)(1u))
35 #define WCR_ENABLE              ((uint32_t)(1u))
36 
37 // Watchpoint load/store
38 // (LSC bits in the DBGWVRn_EL1 watchpoint control register)
39 #define WCR_LOAD                ((uint32_t)(1u << 3))
40 #define WCR_STORE               ((uint32_t)(1u << 4))
41 
42 // Enable breakpoint, watchpoint, and vector catch debug exceptions.
43 // (MDE bit in the MDSCR_EL1 register.  Equivalent to the MDBGen bit in DBGDSCRext in Aarch32)
44 #define MDE_ENABLE ((uint32_t)(1u << 15))
45 
46 // Single instruction step
47 // (SS bit in the MDSCR_EL1 register)
48 #define SS_ENABLE ((uint32_t)(1u))
49 
50 static const uint8_t g_arm64_breakpoint_opcode[] = { 0x00, 0x00, 0x20, 0xD4 }; // "brk #0", 0xd4200000 in BE byte order
51 static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 };   // this armv7 insn also works in arm64
52 
53 // If we need to set one logical watchpoint by using
54 // two hardware watchpoint registers, the watchpoint
55 // will be split into a "high" and "low" watchpoint.
56 // Record both of them in the LoHi array.
57 
58 // It's safe to initialize to all 0's since
59 // hi > lo and therefore LoHi[i] cannot be 0.
60 static uint32_t LoHi[16] = { 0 };
61 
62 
63 void
64 DNBArchMachARM64::Initialize()
65 {
66     DNBArchPluginInfo arch_plugin_info =
67     {
68         CPU_TYPE_ARM64,
69         DNBArchMachARM64::Create,
70         DNBArchMachARM64::GetRegisterSetInfo,
71         DNBArchMachARM64::SoftwareBreakpointOpcode
72     };
73 
74     // Register this arch plug-in with the main protocol class
75     DNBArchProtocol::RegisterArchPlugin (arch_plugin_info);
76 }
77 
78 
79 DNBArchProtocol *
80 DNBArchMachARM64::Create (MachThread *thread)
81 {
82     DNBArchMachARM64 *obj = new DNBArchMachARM64 (thread);
83 
84     return obj;
85 }
86 
87 const uint8_t *
88 DNBArchMachARM64::SoftwareBreakpointOpcode (nub_size_t byte_size)
89 {
90     return g_arm_breakpoint_opcode;
91 }
92 
93 uint32_t
94 DNBArchMachARM64::GetCPUType()
95 {
96     return CPU_TYPE_ARM64;
97 }
98 
99 uint64_t
100 DNBArchMachARM64::GetPC(uint64_t failValue)
101 {
102     // Get program counter
103     if (GetGPRState(false) == KERN_SUCCESS)
104         return m_state.context.gpr.__pc;
105     return failValue;
106 }
107 
108 kern_return_t
109 DNBArchMachARM64::SetPC(uint64_t value)
110 {
111     // Get program counter
112     kern_return_t err = GetGPRState(false);
113     if (err == KERN_SUCCESS)
114     {
115         m_state.context.gpr.__pc = value;
116         err = SetGPRState();
117     }
118     return err == KERN_SUCCESS;
119 }
120 
121 uint64_t
122 DNBArchMachARM64::GetSP(uint64_t failValue)
123 {
124     // Get stack pointer
125     if (GetGPRState(false) == KERN_SUCCESS)
126         return m_state.context.gpr.__sp;
127     return failValue;
128 }
129 
130 kern_return_t
131 DNBArchMachARM64::GetGPRState(bool force)
132 {
133     int set = e_regSetGPR;
134     // Check if we have valid cached registers
135     if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
136         return KERN_SUCCESS;
137 
138     // Read the registers from our thread
139     mach_msg_type_number_t count = e_regSetGPRCount;
140     kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_THREAD_STATE64, (thread_state_t)&m_state.context.gpr, &count);
141     if (DNBLogEnabledForAny (LOG_THREAD))
142     {
143         uint64_t *x = &m_state.context.gpr.__x[0];
144         DNBLogThreaded("thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count = %u) regs"
145                        "\n   x0=%16.16llx"
146                        "\n   x1=%16.16llx"
147                        "\n   x2=%16.16llx"
148                        "\n   x3=%16.16llx"
149                        "\n   x4=%16.16llx"
150                        "\n   x5=%16.16llx"
151                        "\n   x6=%16.16llx"
152                        "\n   x7=%16.16llx"
153                        "\n   x8=%16.16llx"
154                        "\n   x9=%16.16llx"
155                        "\n  x10=%16.16llx"
156                        "\n  x11=%16.16llx"
157                        "\n  x12=%16.16llx"
158                        "\n  x13=%16.16llx"
159                        "\n  x14=%16.16llx"
160                        "\n  x15=%16.16llx"
161                        "\n  x16=%16.16llx"
162                        "\n  x17=%16.16llx"
163                        "\n  x18=%16.16llx"
164                        "\n  x19=%16.16llx"
165                        "\n  x20=%16.16llx"
166                        "\n  x21=%16.16llx"
167                        "\n  x22=%16.16llx"
168                        "\n  x23=%16.16llx"
169                        "\n  x24=%16.16llx"
170                        "\n  x25=%16.16llx"
171                        "\n  x26=%16.16llx"
172                        "\n  x27=%16.16llx"
173                        "\n  x28=%16.16llx"
174                        "\n   fp=%16.16llx"
175                        "\n   lr=%16.16llx"
176                        "\n   sp=%16.16llx"
177                        "\n   pc=%16.16llx"
178                        "\n cpsr=%8.8x",
179                        m_thread->MachPortNumber(),
180                        e_regSetGPR,
181                        e_regSetGPRCount,
182                        kret,
183                        count,
184                        x[0],
185                        x[1],
186                        x[2],
187                        x[3],
188                        x[4],
189                        x[5],
190                        x[6],
191                        x[7],
192                        x[8],
193                        x[9],
194                        x[0],
195                        x[11],
196                        x[12],
197                        x[13],
198                        x[14],
199                        x[15],
200                        x[16],
201                        x[17],
202                        x[18],
203                        x[19],
204                        x[20],
205                        x[21],
206                        x[22],
207                        x[23],
208                        x[24],
209                        x[25],
210                        x[26],
211                        x[27],
212                        x[28],
213                        m_state.context.gpr.__fp,
214                        m_state.context.gpr.__lr,
215                        m_state.context.gpr.__sp,
216                        m_state.context.gpr.__pc,
217                        m_state.context.gpr.__cpsr);
218     }
219     m_state.SetError(set, Read, kret);
220     return kret;
221 }
222 
223 kern_return_t
224 DNBArchMachARM64::GetVFPState(bool force)
225 {
226     int set = e_regSetVFP;
227     // Check if we have valid cached registers
228     if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
229         return KERN_SUCCESS;
230 
231     // Read the registers from our thread
232     mach_msg_type_number_t count = e_regSetVFPCount;
233     kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_NEON_STATE64, (thread_state_t)&m_state.context.vfp, &count);
234     if (DNBLogEnabledForAny (LOG_THREAD))
235     {
236 #if defined (__arm64__) || defined (__aarch64__)
237         DNBLogThreaded("thread_get_state(0x%4.4x, %u, &vfp, %u) => 0x%8.8x (count = %u) regs"
238                        "\n   q0  = 0x%16.16llx%16.16llx"
239                        "\n   q1  = 0x%16.16llx%16.16llx"
240                        "\n   q2  = 0x%16.16llx%16.16llx"
241                        "\n   q3  = 0x%16.16llx%16.16llx"
242                        "\n   q4  = 0x%16.16llx%16.16llx"
243                        "\n   q5  = 0x%16.16llx%16.16llx"
244                        "\n   q6  = 0x%16.16llx%16.16llx"
245                        "\n   q7  = 0x%16.16llx%16.16llx"
246                        "\n   q8  = 0x%16.16llx%16.16llx"
247                        "\n   q9  = 0x%16.16llx%16.16llx"
248                        "\n   q10 = 0x%16.16llx%16.16llx"
249                        "\n   q11 = 0x%16.16llx%16.16llx"
250                        "\n   q12 = 0x%16.16llx%16.16llx"
251                        "\n   q13 = 0x%16.16llx%16.16llx"
252                        "\n   q14 = 0x%16.16llx%16.16llx"
253                        "\n   q15 = 0x%16.16llx%16.16llx"
254                        "\n   q16 = 0x%16.16llx%16.16llx"
255                        "\n   q17 = 0x%16.16llx%16.16llx"
256                        "\n   q18 = 0x%16.16llx%16.16llx"
257                        "\n   q19 = 0x%16.16llx%16.16llx"
258                        "\n   q20 = 0x%16.16llx%16.16llx"
259                        "\n   q21 = 0x%16.16llx%16.16llx"
260                        "\n   q22 = 0x%16.16llx%16.16llx"
261                        "\n   q23 = 0x%16.16llx%16.16llx"
262                        "\n   q24 = 0x%16.16llx%16.16llx"
263                        "\n   q25 = 0x%16.16llx%16.16llx"
264                        "\n   q26 = 0x%16.16llx%16.16llx"
265                        "\n   q27 = 0x%16.16llx%16.16llx"
266                        "\n   q28 = 0x%16.16llx%16.16llx"
267                        "\n   q29 = 0x%16.16llx%16.16llx"
268                        "\n   q30 = 0x%16.16llx%16.16llx"
269                        "\n   q31 = 0x%16.16llx%16.16llx"
270                        "\n  fpsr = 0x%8.8x"
271                        "\n  fpcr = 0x%8.8x\n\n",
272                        m_thread->MachPortNumber(),
273                        e_regSetVFP,
274                        e_regSetVFPCount,
275                        kret,
276                        count,
277                        ((uint64_t *)&m_state.context.vfp.__v[0])[0] , ((uint64_t *)&m_state.context.vfp.__v[0])[1],
278                        ((uint64_t *)&m_state.context.vfp.__v[1])[0] , ((uint64_t *)&m_state.context.vfp.__v[1])[1],
279                        ((uint64_t *)&m_state.context.vfp.__v[2])[0] , ((uint64_t *)&m_state.context.vfp.__v[2])[1],
280                        ((uint64_t *)&m_state.context.vfp.__v[3])[0] , ((uint64_t *)&m_state.context.vfp.__v[3])[1],
281                        ((uint64_t *)&m_state.context.vfp.__v[4])[0] , ((uint64_t *)&m_state.context.vfp.__v[4])[1],
282                        ((uint64_t *)&m_state.context.vfp.__v[5])[0] , ((uint64_t *)&m_state.context.vfp.__v[5])[1],
283                        ((uint64_t *)&m_state.context.vfp.__v[6])[0] , ((uint64_t *)&m_state.context.vfp.__v[6])[1],
284                        ((uint64_t *)&m_state.context.vfp.__v[7])[0] , ((uint64_t *)&m_state.context.vfp.__v[7])[1],
285                        ((uint64_t *)&m_state.context.vfp.__v[8])[0] , ((uint64_t *)&m_state.context.vfp.__v[8])[1],
286                        ((uint64_t *)&m_state.context.vfp.__v[9])[0] , ((uint64_t *)&m_state.context.vfp.__v[9])[1],
287                        ((uint64_t *)&m_state.context.vfp.__v[10])[0], ((uint64_t *)&m_state.context.vfp.__v[10])[1],
288                        ((uint64_t *)&m_state.context.vfp.__v[11])[0], ((uint64_t *)&m_state.context.vfp.__v[11])[1],
289                        ((uint64_t *)&m_state.context.vfp.__v[12])[0], ((uint64_t *)&m_state.context.vfp.__v[12])[1],
290                        ((uint64_t *)&m_state.context.vfp.__v[13])[0], ((uint64_t *)&m_state.context.vfp.__v[13])[1],
291                        ((uint64_t *)&m_state.context.vfp.__v[14])[0], ((uint64_t *)&m_state.context.vfp.__v[14])[1],
292                        ((uint64_t *)&m_state.context.vfp.__v[15])[0], ((uint64_t *)&m_state.context.vfp.__v[15])[1],
293                        ((uint64_t *)&m_state.context.vfp.__v[16])[0], ((uint64_t *)&m_state.context.vfp.__v[16])[1],
294                        ((uint64_t *)&m_state.context.vfp.__v[17])[0], ((uint64_t *)&m_state.context.vfp.__v[17])[1],
295                        ((uint64_t *)&m_state.context.vfp.__v[18])[0], ((uint64_t *)&m_state.context.vfp.__v[18])[1],
296                        ((uint64_t *)&m_state.context.vfp.__v[19])[0], ((uint64_t *)&m_state.context.vfp.__v[19])[1],
297                        ((uint64_t *)&m_state.context.vfp.__v[20])[0], ((uint64_t *)&m_state.context.vfp.__v[20])[1],
298                        ((uint64_t *)&m_state.context.vfp.__v[21])[0], ((uint64_t *)&m_state.context.vfp.__v[21])[1],
299                        ((uint64_t *)&m_state.context.vfp.__v[22])[0], ((uint64_t *)&m_state.context.vfp.__v[22])[1],
300                        ((uint64_t *)&m_state.context.vfp.__v[23])[0], ((uint64_t *)&m_state.context.vfp.__v[23])[1],
301                        ((uint64_t *)&m_state.context.vfp.__v[24])[0], ((uint64_t *)&m_state.context.vfp.__v[24])[1],
302                        ((uint64_t *)&m_state.context.vfp.__v[25])[0], ((uint64_t *)&m_state.context.vfp.__v[25])[1],
303                        ((uint64_t *)&m_state.context.vfp.__v[26])[0], ((uint64_t *)&m_state.context.vfp.__v[26])[1],
304                        ((uint64_t *)&m_state.context.vfp.__v[27])[0], ((uint64_t *)&m_state.context.vfp.__v[27])[1],
305                        ((uint64_t *)&m_state.context.vfp.__v[28])[0], ((uint64_t *)&m_state.context.vfp.__v[28])[1],
306                        ((uint64_t *)&m_state.context.vfp.__v[29])[0], ((uint64_t *)&m_state.context.vfp.__v[29])[1],
307                        ((uint64_t *)&m_state.context.vfp.__v[30])[0], ((uint64_t *)&m_state.context.vfp.__v[30])[1],
308                        ((uint64_t *)&m_state.context.vfp.__v[31])[0], ((uint64_t *)&m_state.context.vfp.__v[31])[1],
309                        m_state.context.vfp.__fpsr,
310                        m_state.context.vfp.__fpcr);
311 #endif
312     }
313     m_state.SetError(set, Read, kret);
314     return kret;
315 }
316 
317 kern_return_t
318 DNBArchMachARM64::GetEXCState(bool force)
319 {
320     int set = e_regSetEXC;
321     // Check if we have valid cached registers
322     if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
323         return KERN_SUCCESS;
324 
325     // Read the registers from our thread
326     mach_msg_type_number_t count = e_regSetEXCCount;
327     kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_EXCEPTION_STATE64, (thread_state_t)&m_state.context.exc, &count);
328     m_state.SetError(set, Read, kret);
329     return kret;
330 }
331 
332 static void
333 DumpDBGState(const arm_debug_state_t& dbg)
334 {
335     uint32_t i = 0;
336     for (i=0; i<16; i++)
337         DNBLogThreadedIf(LOG_STEP, "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }",
338             i, i, dbg.__bvr[i], dbg.__bcr[i],
339             i, i, dbg.__wvr[i], dbg.__wcr[i]);
340 }
341 
342 kern_return_t
343 DNBArchMachARM64::GetDBGState(bool force)
344 {
345     int set = e_regSetDBG;
346 
347     // Check if we have valid cached registers
348     if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
349         return KERN_SUCCESS;
350 
351     // Read the registers from our thread
352     mach_msg_type_number_t count = e_regSetDBGCount;
353     kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE64, (thread_state_t)&m_state.dbg, &count);
354     m_state.SetError(set, Read, kret);
355 
356     return kret;
357 }
358 
359 kern_return_t
360 DNBArchMachARM64::SetGPRState()
361 {
362     int set = e_regSetGPR;
363     kern_return_t kret = ::thread_set_state(m_thread->MachPortNumber(), ARM_THREAD_STATE64, (thread_state_t)&m_state.context.gpr, e_regSetGPRCount);
364     m_state.SetError(set, Write, kret);         // Set the current write error for this register set
365     m_state.InvalidateRegisterSetState(set);    // Invalidate the current register state in case registers are read back differently
366     return kret;                                // Return the error code
367 }
368 
369 kern_return_t
370 DNBArchMachARM64::SetVFPState()
371 {
372     int set = e_regSetVFP;
373     kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_NEON_STATE64, (thread_state_t)&m_state.context.vfp, e_regSetVFPCount);
374     m_state.SetError(set, Write, kret);         // Set the current write error for this register set
375     m_state.InvalidateRegisterSetState(set);    // Invalidate the current register state in case registers are read back differently
376     return kret;                                // Return the error code
377 }
378 
379 kern_return_t
380 DNBArchMachARM64::SetEXCState()
381 {
382     int set = e_regSetEXC;
383     kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_EXCEPTION_STATE64, (thread_state_t)&m_state.context.exc, e_regSetEXCCount);
384     m_state.SetError(set, Write, kret);         // Set the current write error for this register set
385     m_state.InvalidateRegisterSetState(set);    // Invalidate the current register state in case registers are read back differently
386     return kret;                                // Return the error code
387 }
388 
389 kern_return_t
390 DNBArchMachARM64::SetDBGState(bool also_set_on_task)
391 {
392     int set = e_regSetDBG;
393     kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_DEBUG_STATE64, (thread_state_t)&m_state.dbg, e_regSetDBGCount);
394     if (also_set_on_task)
395     {
396         kern_return_t task_kret = task_set_state (m_thread->Process()->Task().TaskPort(), ARM_DEBUG_STATE64, (thread_state_t)&m_state.dbg, e_regSetDBGCount);
397         if (task_kret != KERN_SUCCESS)
398              DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::SetDBGState failed to set debug control register state: 0x%8.8x.", task_kret);
399     }
400     m_state.SetError(set, Write, kret);         // Set the current write error for this register set
401     m_state.InvalidateRegisterSetState(set);    // Invalidate the current register state in case registers are read back differently
402 
403     return kret;                                // Return the error code
404 }
405 
406 void
407 DNBArchMachARM64::ThreadWillResume()
408 {
409     // Do we need to step this thread? If so, let the mach thread tell us so.
410     if (m_thread->IsStepping())
411     {
412         EnableHardwareSingleStep(true);
413     }
414 
415     // Disable the triggered watchpoint temporarily before we resume.
416     // Plus, we try to enable hardware single step to execute past the instruction which triggered our watchpoint.
417     if (m_watchpoint_did_occur)
418     {
419         if (m_watchpoint_hw_index >= 0)
420         {
421             kern_return_t kret = GetDBGState(false);
422             if (kret == KERN_SUCCESS && !IsWatchpointEnabled(m_state.dbg, m_watchpoint_hw_index)) {
423                 // The watchpoint might have been disabled by the user.  We don't need to do anything at all
424                 // to enable hardware single stepping.
425                 m_watchpoint_did_occur = false;
426                 m_watchpoint_hw_index = -1;
427                 return;
428             }
429 
430             DisableHardwareWatchpoint(m_watchpoint_hw_index, false);
431             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() DisableHardwareWatchpoint(%d) called",
432                              m_watchpoint_hw_index);
433 
434             // Enable hardware single step to move past the watchpoint-triggering instruction.
435             m_watchpoint_resume_single_step_enabled = (EnableHardwareSingleStep(true) == KERN_SUCCESS);
436 
437             // If we are not able to enable single step to move past the watchpoint-triggering instruction,
438             // at least we should reset the two watchpoint member variables so that the next time around
439             // this callback function is invoked, the enclosing logical branch is skipped.
440             if (!m_watchpoint_resume_single_step_enabled) {
441                 // Reset the two watchpoint member variables.
442                 m_watchpoint_did_occur = false;
443                 m_watchpoint_hw_index = -1;
444                 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() failed to enable single step");
445             }
446             else
447                 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() succeeded to enable single step");
448         }
449     }
450 }
451 
452 bool
453 DNBArchMachARM64::NotifyException(MachException::Data& exc)
454 {
455 
456     switch (exc.exc_type)
457     {
458         default:
459             break;
460         case EXC_BREAKPOINT:
461             if (exc.exc_data.size() == 2 && exc.exc_data[0] == EXC_ARM_DA_DEBUG)
462             {
463                 // The data break address is passed as exc_data[1].
464                 nub_addr_t addr = exc.exc_data[1];
465                 // Find the hardware index with the side effect of possibly massaging the
466                 // addr to return the starting address as seen from the debugger side.
467                 uint32_t hw_index = GetHardwareWatchpointHit(addr);
468 
469                 // One logical watchpoint was split into two watchpoint locations because
470                 // it was too big.  If the watchpoint exception is indicating the 2nd half
471                 // of the two-parter, find the address of the 1st half and report that --
472                 // that's what lldb is going to expect to see.
473                 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::NotifyException watchpoint %d was hit on address 0x%llx", hw_index, (uint64_t) addr);
474                 const int num_watchpoints = NumSupportedHardwareWatchpoints ();
475                 for (int i = 0; i < num_watchpoints; i++)
476                 {
477                    if (LoHi[i] != 0
478                        && LoHi[i] == hw_index
479                        && LoHi[i] != i
480                        && GetWatchpointAddressByIndex (i) != INVALID_NUB_ADDRESS)
481                    {
482                        addr = GetWatchpointAddressByIndex (i);
483                        DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::NotifyException It is a linked watchpoint; rewritten to index %d addr 0x%llx", LoHi[i], (uint64_t) addr);
484                     }
485                 }
486 
487                 if (hw_index != INVALID_NUB_HW_INDEX)
488                 {
489                     m_watchpoint_did_occur = true;
490                     m_watchpoint_hw_index = hw_index;
491                     exc.exc_data[1] = addr;
492                     // Piggyback the hw_index in the exc.data.
493                     exc.exc_data.push_back(hw_index);
494                 }
495 
496                 return true;
497             }
498             break;
499     }
500     return false;
501 }
502 
503 bool
504 DNBArchMachARM64::ThreadDidStop()
505 {
506     bool success = true;
507 
508     m_state.InvalidateAllRegisterStates();
509 
510     if (m_watchpoint_resume_single_step_enabled)
511     {
512         // Great!  We now disable the hardware single step as well as re-enable the hardware watchpoint.
513         // See also ThreadWillResume().
514         if (EnableHardwareSingleStep(false) == KERN_SUCCESS)
515         {
516             if (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0)
517             {
518                 ReenableHardwareWatchpoint(m_watchpoint_hw_index);
519                 m_watchpoint_resume_single_step_enabled = false;
520                 m_watchpoint_did_occur = false;
521                 m_watchpoint_hw_index = -1;
522             }
523             else
524             {
525                 DNBLogError("internal error detected: m_watchpoint_resume_step_enabled is true but (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0) does not hold!");
526             }
527         }
528         else
529         {
530             DNBLogError("internal error detected: m_watchpoint_resume_step_enabled is true but unable to disable single step!");
531         }
532     }
533 
534     // Are we stepping a single instruction?
535     if (GetGPRState(true) == KERN_SUCCESS)
536     {
537         // We are single stepping, was this the primary thread?
538         if (m_thread->IsStepping())
539         {
540             // This was the primary thread, we need to clear the trace
541             // bit if so.
542             success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
543         }
544         else
545         {
546             // The MachThread will automatically restore the suspend count
547             // in ThreadDidStop(), so we don't need to do anything here if
548             // we weren't the primary thread the last time
549         }
550     }
551     return success;
552 }
553 
554 // Set the single step bit in the processor status register.
555 kern_return_t
556 DNBArchMachARM64::EnableHardwareSingleStep (bool enable)
557 {
558     DNBError err;
559     DNBLogThreadedIf(LOG_STEP, "%s( enable = %d )", __FUNCTION__, enable);
560 
561     err = GetGPRState(false);
562 
563     if (err.Fail())
564     {
565         err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__);
566         return err.Error();
567     }
568 
569     err = GetDBGState(false);
570 
571     if (err.Fail())
572     {
573         err.LogThreaded("%s: failed to read the DBG registers", __FUNCTION__);
574         return err.Error();
575     }
576 
577     if (enable)
578     {
579         DNBLogThreadedIf(LOG_STEP, "%s: Setting MDSCR_EL1 Single Step bit at pc 0x%llx", __FUNCTION__, (uint64_t) m_state.context.gpr.__pc);
580         m_state.dbg.__mdscr_el1 |= SS_ENABLE;
581     }
582     else
583     {
584         DNBLogThreadedIf(LOG_STEP, "%s: Clearing MDSCR_EL1 Single Step bit at pc 0x%llx", __FUNCTION__, (uint64_t) m_state.context.gpr.__pc);
585         m_state.dbg.__mdscr_el1 &= ~(SS_ENABLE);
586     }
587 
588     return SetDBGState(false);
589 }
590 
591 // return 1 if bit "BIT" is set in "value"
592 static inline uint32_t bit(uint32_t value, uint32_t bit)
593 {
594     return (value >> bit) & 1u;
595 }
596 
597 // return the bitfield "value[msbit:lsbit]".
598 static inline uint64_t bits(uint64_t value, uint32_t msbit, uint32_t lsbit)
599 {
600     assert(msbit >= lsbit);
601     uint64_t shift_left = sizeof(value) * 8 - 1 - msbit;
602     value <<= shift_left;           // shift anything above the msbit off of the unsigned edge
603     value >>= shift_left + lsbit;   // shift it back again down to the lsbit (including undoing any shift from above)
604     return value;                   // return our result
605 }
606 
607 uint32_t
608 DNBArchMachARM64::NumSupportedHardwareWatchpoints()
609 {
610     // Set the init value to something that will let us know that we need to
611     // autodetect how many watchpoints are supported dynamically...
612     static uint32_t g_num_supported_hw_watchpoints = UINT_MAX;
613     if (g_num_supported_hw_watchpoints == UINT_MAX)
614     {
615         // Set this to zero in case we can't tell if there are any HW breakpoints
616         g_num_supported_hw_watchpoints = 0;
617 
618 
619         size_t len;
620         uint32_t n = 0;
621         len = sizeof (n);
622         if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0)
623         {
624             g_num_supported_hw_watchpoints = n;
625             DNBLogThreadedIf(LOG_THREAD, "hw.optional.watchpoint=%u", n);
626         }
627         else
628         {
629             // For AArch64 we would need to look at ID_AA64DFR0_EL1 but debugserver runs in EL0 so it can't
630             // access that reg.  The kernel should have filled in the sysctls based on it though.
631 #if defined (__arm__)
632             uint32_t register_DBGDIDR;
633 
634             asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR));
635             uint32_t numWRPs = bits(register_DBGDIDR, 31, 28);
636             // Zero is reserved for the WRP count, so don't increment it if it is zero
637             if (numWRPs > 0)
638                 numWRPs++;
639             g_num_supported_hw_watchpoints = numWRPs;
640             DNBLogThreadedIf(LOG_THREAD, "Number of supported hw watchpoints via asm():  %d", g_num_supported_hw_watchpoints);
641 #endif
642         }
643     }
644     return g_num_supported_hw_watchpoints;
645 }
646 
647 uint32_t
648 DNBArchMachARM64::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task)
649 {
650     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::EnableHardwareWatchpoint(addr = 0x%8.8llx, size = %zu, read = %u, write = %u)", (uint64_t)addr, size, read, write);
651 
652     const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
653 
654     // Can't watch zero bytes
655     if (size == 0)
656         return INVALID_NUB_HW_INDEX;
657 
658     // We must watch for either read or write
659     if (read == false && write == false)
660         return INVALID_NUB_HW_INDEX;
661 
662     // Otherwise, can't watch more than 8 bytes per WVR/WCR pair
663     if (size > 8)
664         return INVALID_NUB_HW_INDEX;
665 
666     // arm64 watchpoints really have an 8-byte alignment requirement.  You can put a watchpoint on a 4-byte
667     // offset address but you can only watch 4 bytes with that watchpoint.
668 
669     // arm64 watchpoints on an 8-byte (double word) aligned addr can watch any bytes in that
670     // 8-byte long region of memory.  They can watch the 1st byte, the 2nd byte, 3rd byte, etc, or any
671     // combination therein by setting the bits in the BAS [12:5] (Byte Address Select) field of
672     // the DBGWCRn_EL1 reg for the watchpoint.
673 
674     // If the MASK [28:24] bits in the DBGWCRn_EL1 allow a single watchpoint to monitor a larger region
675     // of memory (16 bytes, 32 bytes, or 2GB) but the Byte Address Select bitfield then selects a larger
676     // range of bytes, instead of individual bytes.  See the ARMv8 Debug Architecture manual for details.
677     // This implementation does not currently use the MASK bits; the largest single region watched by a single
678     // watchpoint right now is 8-bytes.
679 
680     nub_addr_t aligned_wp_address = addr & ~0x7;
681     uint32_t addr_dword_offset = addr & 0x7;
682 
683     // Do we need to split up this logical watchpoint into two hardware watchpoint
684     // registers?
685     // e.g. a watchpoint of length 4 on address 6.  We need do this with
686     //   one watchpoint on address 0 with bytes 6 & 7 being monitored
687     //   one watchpoint on address 8 with bytes 0, 1, 2, 3 being monitored
688 
689     if (addr_dword_offset + size > 8)
690     {
691         DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::EnableHardwareWatchpoint(addr = 0x%8.8llx, size = %zu) needs two hardware watchpoints slots to monitor", (uint64_t)addr, size);
692         int low_watchpoint_size = 8 - addr_dword_offset;
693         int high_watchpoint_size = addr_dword_offset + size - 8;
694 
695         uint32_t lo = EnableHardwareWatchpoint(addr, low_watchpoint_size, read, write, also_set_on_task);
696         if (lo == INVALID_NUB_HW_INDEX)
697             return INVALID_NUB_HW_INDEX;
698         uint32_t hi = EnableHardwareWatchpoint (aligned_wp_address + 8, high_watchpoint_size, read, write, also_set_on_task);
699         if (hi == INVALID_NUB_HW_INDEX)
700         {
701             DisableHardwareWatchpoint (lo, also_set_on_task);
702             return INVALID_NUB_HW_INDEX;
703         }
704         // Tag this lo->hi mapping in our database.
705         LoHi[lo] = hi;
706         return lo;
707     }
708 
709     // At this point
710     //  1 aligned_wp_address is the requested address rounded down to 8-byte alignment
711     //  2 addr_dword_offset is the offset into that double word (8-byte) region that we are watching
712     //  3 size is the number of bytes within that 8-byte region that we are watching
713 
714     // Set the Byte Address Selects bits DBGWCRn_EL1 bits [12:5] based on the above.
715     // The bit shift and negation operation will give us 0b11 for 2, 0b1111 for 4, etc, up to 0b11111111 for 8.
716     // then we shift those bits left by the offset into this dword that we are interested in.
717     // e.g. if we are watching bytes 4,5,6,7 in a dword we want a BAS of 0b11110000.
718     uint32_t byte_address_select = ((1 << size) - 1) << addr_dword_offset;
719 
720     // Read the debug state
721     kern_return_t kret = GetDBGState(false);
722 
723     if (kret == KERN_SUCCESS)
724     {
725         // Check to make sure we have the needed hardware support
726         uint32_t i = 0;
727 
728         for (i=0; i<num_hw_watchpoints; ++i)
729         {
730             if ((m_state.dbg.__wcr[i] & WCR_ENABLE) == 0)
731                 break; // We found an available hw watchpoint slot (in i)
732         }
733 
734         // See if we found an available hw watchpoint slot above
735         if (i < num_hw_watchpoints)
736         {
737             //DumpDBGState(m_state.dbg);
738 
739             // Clear any previous LoHi joined-watchpoint that may have been in use
740             LoHi[i] = 0;
741 
742             // shift our Byte Address Select bits up to the correct bit range for the DBGWCRn_EL1
743             byte_address_select = byte_address_select << 5;
744 
745             // Make sure bits 1:0 are clear in our address
746             m_state.dbg.__wvr[i] = aligned_wp_address;          // DVA (Data Virtual Address)
747             m_state.dbg.__wcr[i] =  byte_address_select |       // Which bytes that follow the DVA that we will watch
748                                     S_USER |                    // Stop only in user mode
749                                     (read ? WCR_LOAD : 0) |     // Stop on read access?
750                                     (write ? WCR_STORE : 0) |   // Stop on write access?
751                                     WCR_ENABLE;                 // Enable this watchpoint;
752 
753             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::EnableHardwareWatchpoint() adding watchpoint on address 0x%llx with control register value 0x%x", (uint64_t) m_state.dbg.__wvr[i], (uint32_t) m_state.dbg.__wcr[i]);
754 
755             // The kernel will set the MDE_ENABLE bit in the MDSCR_EL1 for us automatically, don't need to do it here.
756 
757             kret = SetDBGState(also_set_on_task);
758             //DumpDBGState(m_state.dbg);
759 
760             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret);
761 
762             if (kret == KERN_SUCCESS)
763                 return i;
764         }
765         else
766         {
767             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints);
768         }
769     }
770     return INVALID_NUB_HW_INDEX;
771 }
772 
773 bool
774 DNBArchMachARM64::ReenableHardwareWatchpoint (uint32_t hw_index)
775 {
776     // If this logical watchpoint # is actually implemented using
777     // two hardware watchpoint registers, re-enable both of them.
778 
779     if (hw_index < NumSupportedHardwareWatchpoints() && LoHi[hw_index])
780     {
781         return ReenableHardwareWatchpoint_helper (hw_index) && ReenableHardwareWatchpoint_helper (LoHi[hw_index]);
782     }
783     else
784     {
785         return ReenableHardwareWatchpoint_helper (hw_index);
786     }
787 }
788 
789 bool
790 DNBArchMachARM64::ReenableHardwareWatchpoint_helper (uint32_t hw_index)
791 {
792     kern_return_t kret = GetDBGState(false);
793     if (kret != KERN_SUCCESS)
794         return false;
795 
796     const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
797     if (hw_index >= num_hw_points)
798         return false;
799 
800     m_state.dbg.__wvr[hw_index] = m_disabled_watchpoints[hw_index].addr;
801     m_state.dbg.__wcr[hw_index] = m_disabled_watchpoints[hw_index].control;
802 
803     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::EnableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8llx  WCR%u = 0x%8.8llx",
804                      hw_index,
805                      hw_index,
806                      (uint64_t) m_state.dbg.__wvr[hw_index],
807                      hw_index,
808                      (uint64_t) m_state.dbg.__wcr[hw_index]);
809 
810    // The kernel will set the MDE_ENABLE bit in the MDSCR_EL1 for us automatically, don't need to do it here.
811 
812     kret = SetDBGState(false);
813 
814     return (kret == KERN_SUCCESS);
815 }
816 
817 bool
818 DNBArchMachARM64::DisableHardwareWatchpoint (uint32_t hw_index, bool also_set_on_task)
819 {
820     if (hw_index < NumSupportedHardwareWatchpoints() && LoHi[hw_index])
821     {
822         return DisableHardwareWatchpoint_helper (hw_index, also_set_on_task) && DisableHardwareWatchpoint_helper (LoHi[hw_index], also_set_on_task);
823     }
824     else
825     {
826         return DisableHardwareWatchpoint_helper (hw_index, also_set_on_task);
827     }
828 }
829 
830 bool
831 DNBArchMachARM64::DisableHardwareWatchpoint_helper (uint32_t hw_index, bool also_set_on_task)
832 {
833     kern_return_t kret = GetDBGState(false);
834     if (kret != KERN_SUCCESS)
835         return false;
836 
837     const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
838     if (hw_index >= num_hw_points)
839         return false;
840 
841     m_disabled_watchpoints[hw_index].addr = m_state.dbg.__wvr[hw_index];
842     m_disabled_watchpoints[hw_index].control = m_state.dbg.__wcr[hw_index];
843 
844     m_state.dbg.__wcr[hw_index] &= ~((nub_addr_t)WCR_ENABLE);
845     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::DisableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8llx  WCR%u = 0x%8.8llx",
846                      hw_index,
847                      hw_index,
848                      (uint64_t) m_state.dbg.__wvr[hw_index],
849                      hw_index,
850                      (uint64_t) m_state.dbg.__wcr[hw_index]);
851 
852     kret = SetDBGState(also_set_on_task);
853 
854     return (kret == KERN_SUCCESS);
855 }
856 
857 // This is for checking the Byte Address Select bits in the DBRWCRn_EL1 control register.
858 // Returns -1 if the trailing bit patterns are not one of:
859 // { 0b???????1, 0b??????10, 0b?????100, 0b????1000, 0b???10000, 0b??100000, 0b?1000000, 0b10000000 }.
860 static inline
861 int32_t
862 LowestBitSet(uint32_t val)
863 {
864     for (unsigned i = 0; i < 8; ++i) {
865         if (bit(val, i))
866             return i;
867     }
868     return -1;
869 }
870 
871 // Iterate through the debug registers; return the index of the first watchpoint whose address matches.
872 // As a side effect, the starting address as understood by the debugger is returned which could be
873 // different from 'addr' passed as an in/out argument.
874 uint32_t
875 DNBArchMachARM64::GetHardwareWatchpointHit(nub_addr_t &addr)
876 {
877     // Read the debug state
878     kern_return_t kret = GetDBGState(true);
879     //DumpDBGState(m_state.dbg);
880     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret);
881     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::GetHardwareWatchpointHit() addr = 0x%llx", (uint64_t)addr);
882 
883     // This is the watchpoint value to match against, i.e., word address.
884     nub_addr_t wp_val = addr & ~((nub_addr_t)3);
885     if (kret == KERN_SUCCESS)
886     {
887         DBG &debug_state = m_state.dbg;
888         uint32_t i, num = NumSupportedHardwareWatchpoints();
889         for (i = 0; i < num; ++i)
890         {
891             nub_addr_t wp_addr = GetWatchAddress(debug_state, i);
892             DNBLogThreadedIf(LOG_WATCHPOINTS,
893                              "DNBArchMachARM64::GetHardwareWatchpointHit() slot: %u (addr = 0x%llx).",
894                              i, (uint64_t)wp_addr);
895             if (wp_val == wp_addr) {
896                 uint32_t byte_mask = bits(debug_state.__wcr[i], 12, 5);
897 
898                 // Sanity check the byte_mask, first.
899                 if (LowestBitSet(byte_mask) < 0)
900                     continue;
901 
902                 // Check that the watchpoint is enabled.
903                 if (!IsWatchpointEnabled(debug_state, i))
904                     continue;
905 
906                 // Compute the starting address (from the point of view of the debugger).
907                 addr = wp_addr + LowestBitSet(byte_mask);
908                 return i;
909             }
910         }
911     }
912     return INVALID_NUB_HW_INDEX;
913 }
914 
915 nub_addr_t
916 DNBArchMachARM64::GetWatchpointAddressByIndex (uint32_t hw_index)
917 {
918     kern_return_t kret = GetDBGState(true);
919     if (kret != KERN_SUCCESS)
920         return INVALID_NUB_ADDRESS;
921     const uint32_t num = NumSupportedHardwareWatchpoints();
922     if (hw_index >= num)
923         return INVALID_NUB_ADDRESS;
924     if (IsWatchpointEnabled (m_state.dbg, hw_index))
925         return GetWatchAddress (m_state.dbg, hw_index);
926     return INVALID_NUB_ADDRESS;
927 }
928 
929 bool
930 DNBArchMachARM64::IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index)
931 {
932     // Watchpoint Control Registers, bitfield definitions
933     // ...
934     // Bits    Value    Description
935     // [0]     0        Watchpoint disabled
936     //         1        Watchpoint enabled.
937     return (debug_state.__wcr[hw_index] & 1u);
938 }
939 
940 nub_addr_t
941 DNBArchMachARM64::GetWatchAddress(const DBG &debug_state, uint32_t hw_index)
942 {
943     // Watchpoint Value Registers, bitfield definitions
944     // Bits        Description
945     // [31:2]      Watchpoint value (word address, i.e., 4-byte aligned)
946     // [1:0]       RAZ/SBZP
947     return bits(debug_state.__wvr[hw_index], 63, 0);
948 }
949 
950 //----------------------------------------------------------------------
951 // Register information definitions for 64 bit ARMv8.
952 //----------------------------------------------------------------------
953 enum gpr_regnums
954 {
955     gpr_x0 = 0,
956     gpr_x1,
957     gpr_x2,
958     gpr_x3,
959     gpr_x4,
960     gpr_x5,
961     gpr_x6,
962     gpr_x7,
963     gpr_x8,
964     gpr_x9,
965     gpr_x10,
966     gpr_x11,
967     gpr_x12,
968     gpr_x13,
969     gpr_x14,
970     gpr_x15,
971     gpr_x16,
972     gpr_x17,
973     gpr_x18,
974     gpr_x19,
975     gpr_x20,
976     gpr_x21,
977     gpr_x22,
978     gpr_x23,
979     gpr_x24,
980     gpr_x25,
981     gpr_x26,
982     gpr_x27,
983     gpr_x28,
984     gpr_fp, gpr_x29 = gpr_fp,
985     gpr_lr,	gpr_x30 = gpr_lr,
986     gpr_sp,	gpr_x31 = gpr_sp,
987     gpr_pc,
988     gpr_cpsr,
989     gpr_w0,
990     gpr_w1,
991     gpr_w2,
992     gpr_w3,
993     gpr_w4,
994     gpr_w5,
995     gpr_w6,
996     gpr_w7,
997     gpr_w8,
998     gpr_w9,
999     gpr_w10,
1000     gpr_w11,
1001     gpr_w12,
1002     gpr_w13,
1003     gpr_w14,
1004     gpr_w15,
1005     gpr_w16,
1006     gpr_w17,
1007     gpr_w18,
1008     gpr_w19,
1009     gpr_w20,
1010     gpr_w21,
1011     gpr_w22,
1012     gpr_w23,
1013     gpr_w24,
1014     gpr_w25,
1015     gpr_w26,
1016     gpr_w27,
1017     gpr_w28
1018 
1019 };
1020 
1021 enum
1022 {
1023     vfp_v0 = 0,
1024     vfp_v1,
1025     vfp_v2,
1026     vfp_v3,
1027     vfp_v4,
1028     vfp_v5,
1029     vfp_v6,
1030     vfp_v7,
1031     vfp_v8,
1032     vfp_v9,
1033     vfp_v10,
1034     vfp_v11,
1035     vfp_v12,
1036     vfp_v13,
1037     vfp_v14,
1038     vfp_v15,
1039     vfp_v16,
1040     vfp_v17,
1041     vfp_v18,
1042     vfp_v19,
1043     vfp_v20,
1044     vfp_v21,
1045     vfp_v22,
1046     vfp_v23,
1047     vfp_v24,
1048     vfp_v25,
1049     vfp_v26,
1050     vfp_v27,
1051     vfp_v28,
1052     vfp_v29,
1053     vfp_v30,
1054     vfp_v31,
1055     vfp_fpsr,
1056     vfp_fpcr,
1057 
1058     // lower 32 bits of the corresponding vfp_v<n> reg.
1059     vfp_s0,
1060     vfp_s1,
1061     vfp_s2,
1062     vfp_s3,
1063     vfp_s4,
1064     vfp_s5,
1065     vfp_s6,
1066     vfp_s7,
1067     vfp_s8,
1068     vfp_s9,
1069     vfp_s10,
1070     vfp_s11,
1071     vfp_s12,
1072     vfp_s13,
1073     vfp_s14,
1074     vfp_s15,
1075     vfp_s16,
1076     vfp_s17,
1077     vfp_s18,
1078     vfp_s19,
1079     vfp_s20,
1080     vfp_s21,
1081     vfp_s22,
1082     vfp_s23,
1083     vfp_s24,
1084     vfp_s25,
1085     vfp_s26,
1086     vfp_s27,
1087     vfp_s28,
1088     vfp_s29,
1089     vfp_s30,
1090     vfp_s31,
1091 
1092     // lower 64 bits of the corresponding vfp_v<n> reg.
1093     vfp_d0,
1094     vfp_d1,
1095     vfp_d2,
1096     vfp_d3,
1097     vfp_d4,
1098     vfp_d5,
1099     vfp_d6,
1100     vfp_d7,
1101     vfp_d8,
1102     vfp_d9,
1103     vfp_d10,
1104     vfp_d11,
1105     vfp_d12,
1106     vfp_d13,
1107     vfp_d14,
1108     vfp_d15,
1109     vfp_d16,
1110     vfp_d17,
1111     vfp_d18,
1112     vfp_d19,
1113     vfp_d20,
1114     vfp_d21,
1115     vfp_d22,
1116     vfp_d23,
1117     vfp_d24,
1118     vfp_d25,
1119     vfp_d26,
1120     vfp_d27,
1121     vfp_d28,
1122     vfp_d29,
1123     vfp_d30,
1124     vfp_d31
1125 };
1126 
1127 enum
1128 {
1129     exc_far = 0,
1130     exc_esr,
1131     exc_exception
1132 };
1133 
1134 // These numbers from the "DWARF for the ARM 64-bit Architecture (AArch64)" document.
1135 
1136 enum
1137 {
1138     dwarf_x0 = 0,
1139     dwarf_x1,
1140     dwarf_x2,
1141     dwarf_x3,
1142     dwarf_x4,
1143     dwarf_x5,
1144     dwarf_x6,
1145     dwarf_x7,
1146     dwarf_x8,
1147     dwarf_x9,
1148     dwarf_x10,
1149     dwarf_x11,
1150     dwarf_x12,
1151     dwarf_x13,
1152     dwarf_x14,
1153     dwarf_x15,
1154     dwarf_x16,
1155     dwarf_x17,
1156     dwarf_x18,
1157     dwarf_x19,
1158     dwarf_x20,
1159     dwarf_x21,
1160     dwarf_x22,
1161     dwarf_x23,
1162     dwarf_x24,
1163     dwarf_x25,
1164     dwarf_x26,
1165     dwarf_x27,
1166     dwarf_x28,
1167     dwarf_x29,
1168     dwarf_x30,
1169     dwarf_x31,
1170     dwarf_pc        = 32,
1171     dwarf_elr_mode  = 33,
1172     dwarf_fp = dwarf_x29,
1173     dwarf_lr = dwarf_x30,
1174     dwarf_sp = dwarf_x31,
1175     // 34-63 reserved
1176 
1177     // V0-V31 (128 bit vector registers)
1178     dwarf_v0        = 64,
1179     dwarf_v1,
1180     dwarf_v2,
1181     dwarf_v3,
1182     dwarf_v4,
1183     dwarf_v5,
1184     dwarf_v6,
1185     dwarf_v7,
1186     dwarf_v8,
1187     dwarf_v9,
1188     dwarf_v10,
1189     dwarf_v11,
1190     dwarf_v12,
1191     dwarf_v13,
1192     dwarf_v14,
1193     dwarf_v15,
1194     dwarf_v16,
1195     dwarf_v17,
1196     dwarf_v18,
1197     dwarf_v19,
1198     dwarf_v20,
1199     dwarf_v21,
1200     dwarf_v22,
1201     dwarf_v23,
1202     dwarf_v24,
1203     dwarf_v25,
1204     dwarf_v26,
1205     dwarf_v27,
1206     dwarf_v28,
1207     dwarf_v29,
1208     dwarf_v30,
1209     dwarf_v31
1210 
1211     // 96-127 reserved
1212 };
1213 
1214 enum
1215 {
1216     gdb_gpr_x0 = 0,
1217     gdb_gpr_x1,
1218     gdb_gpr_x2,
1219     gdb_gpr_x3,
1220     gdb_gpr_x4,
1221     gdb_gpr_x5,
1222     gdb_gpr_x6,
1223     gdb_gpr_x7,
1224     gdb_gpr_x8,
1225     gdb_gpr_x9,
1226     gdb_gpr_x10,
1227     gdb_gpr_x11,
1228     gdb_gpr_x12,
1229     gdb_gpr_x13,
1230     gdb_gpr_x14,
1231     gdb_gpr_x15,
1232     gdb_gpr_x16,
1233     gdb_gpr_x17,
1234     gdb_gpr_x18,
1235     gdb_gpr_x19,
1236     gdb_gpr_x20,
1237     gdb_gpr_x21,
1238     gdb_gpr_x22,
1239     gdb_gpr_x23,
1240     gdb_gpr_x24,
1241     gdb_gpr_x25,
1242     gdb_gpr_x26,
1243     gdb_gpr_x27,
1244     gdb_gpr_x28,
1245     gdb_gpr_fp,    // x29
1246     gdb_gpr_lr,    // x30
1247     gdb_gpr_sp,    // sp aka xsp
1248     gdb_gpr_pc,
1249     gdb_gpr_cpsr,
1250     gdb_vfp_v0,
1251     gdb_vfp_v1,
1252     gdb_vfp_v2,
1253     gdb_vfp_v3,
1254     gdb_vfp_v4,
1255     gdb_vfp_v5,
1256     gdb_vfp_v6,
1257     gdb_vfp_v7,
1258     gdb_vfp_v8,
1259     gdb_vfp_v9,
1260     gdb_vfp_v10,
1261     gdb_vfp_v11,
1262     gdb_vfp_v12,
1263     gdb_vfp_v13,
1264     gdb_vfp_v14,
1265     gdb_vfp_v15,
1266     gdb_vfp_v16,
1267     gdb_vfp_v17,
1268     gdb_vfp_v18,
1269     gdb_vfp_v19,
1270     gdb_vfp_v20,
1271     gdb_vfp_v21,
1272     gdb_vfp_v22,
1273     gdb_vfp_v23,
1274     gdb_vfp_v24,
1275     gdb_vfp_v25,
1276     gdb_vfp_v26,
1277     gdb_vfp_v27,
1278     gdb_vfp_v28,
1279     gdb_vfp_v29,
1280     gdb_vfp_v30,
1281     gdb_vfp_v31,
1282     gdb_vfp_fpsr,
1283     gdb_vfp_fpcr
1284 };
1285 
1286 const char *g_contained_x0[] {"x0", NULL };
1287 const char *g_contained_x1[] {"x1", NULL };
1288 const char *g_contained_x2[] {"x2", NULL };
1289 const char *g_contained_x3[] {"x3", NULL };
1290 const char *g_contained_x4[] {"x4", NULL };
1291 const char *g_contained_x5[] {"x5", NULL };
1292 const char *g_contained_x6[] {"x6", NULL };
1293 const char *g_contained_x7[] {"x7", NULL };
1294 const char *g_contained_x8[] {"x8", NULL };
1295 const char *g_contained_x9[] {"x9", NULL };
1296 const char *g_contained_x10[] {"x10", NULL };
1297 const char *g_contained_x11[] {"x11", NULL };
1298 const char *g_contained_x12[] {"x12", NULL };
1299 const char *g_contained_x13[] {"x13", NULL };
1300 const char *g_contained_x14[] {"x14", NULL };
1301 const char *g_contained_x15[] {"x15", NULL };
1302 const char *g_contained_x16[] {"x16", NULL };
1303 const char *g_contained_x17[] {"x17", NULL };
1304 const char *g_contained_x18[] {"x18", NULL };
1305 const char *g_contained_x19[] {"x19", NULL };
1306 const char *g_contained_x20[] {"x20", NULL };
1307 const char *g_contained_x21[] {"x21", NULL };
1308 const char *g_contained_x22[] {"x22", NULL };
1309 const char *g_contained_x23[] {"x23", NULL };
1310 const char *g_contained_x24[] {"x24", NULL };
1311 const char *g_contained_x25[] {"x25", NULL };
1312 const char *g_contained_x26[] {"x26", NULL };
1313 const char *g_contained_x27[] {"x27", NULL };
1314 const char *g_contained_x28[] {"x28", NULL };
1315 
1316 const char *g_invalidate_x0[] {"x0", "w0", NULL };
1317 const char *g_invalidate_x1[] {"x1", "w1", NULL };
1318 const char *g_invalidate_x2[] {"x2", "w2", NULL };
1319 const char *g_invalidate_x3[] {"x3", "w3", NULL };
1320 const char *g_invalidate_x4[] {"x4", "w4", NULL };
1321 const char *g_invalidate_x5[] {"x5", "w5", NULL };
1322 const char *g_invalidate_x6[] {"x6", "w6", NULL };
1323 const char *g_invalidate_x7[] {"x7", "w7", NULL };
1324 const char *g_invalidate_x8[] {"x8", "w8", NULL };
1325 const char *g_invalidate_x9[] {"x9", "w9", NULL };
1326 const char *g_invalidate_x10[] {"x10", "w10", NULL };
1327 const char *g_invalidate_x11[] {"x11", "w11", NULL };
1328 const char *g_invalidate_x12[] {"x12", "w12", NULL };
1329 const char *g_invalidate_x13[] {"x13", "w13", NULL };
1330 const char *g_invalidate_x14[] {"x14", "w14", NULL };
1331 const char *g_invalidate_x15[] {"x15", "w15", NULL };
1332 const char *g_invalidate_x16[] {"x16", "w16", NULL };
1333 const char *g_invalidate_x17[] {"x17", "w17", NULL };
1334 const char *g_invalidate_x18[] {"x18", "w18", NULL };
1335 const char *g_invalidate_x19[] {"x19", "w19", NULL };
1336 const char *g_invalidate_x20[] {"x20", "w20", NULL };
1337 const char *g_invalidate_x21[] {"x21", "w21", NULL };
1338 const char *g_invalidate_x22[] {"x22", "w22", NULL };
1339 const char *g_invalidate_x23[] {"x23", "w23", NULL };
1340 const char *g_invalidate_x24[] {"x24", "w24", NULL };
1341 const char *g_invalidate_x25[] {"x25", "w25", NULL };
1342 const char *g_invalidate_x26[] {"x26", "w26", NULL };
1343 const char *g_invalidate_x27[] {"x27", "w27", NULL };
1344 const char *g_invalidate_x28[] {"x28", "w28", NULL };
1345 
1346 #define GPR_OFFSET_IDX(idx) (offsetof (DNBArchMachARM64::GPR, __x[idx]))
1347 
1348 #define GPR_OFFSET_NAME(reg) (offsetof (DNBArchMachARM64::GPR , __##reg))
1349 
1350 // These macros will auto define the register name, alt name, register size,
1351 // register offset, encoding, format and native register. This ensures that
1352 // the register state structures are defined correctly and have the correct
1353 // sizes and offsets.
1354 #define DEFINE_GPR_IDX(idx, reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 8, GPR_OFFSET_IDX(idx) , dwarf_##reg, dwarf_##reg, gen, gdb_gpr_##reg, NULL, g_invalidate_x##idx }
1355 #define DEFINE_GPR_NAME(reg, alt, gen)     { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 8, GPR_OFFSET_NAME(reg), dwarf_##reg, dwarf_##reg, gen, gdb_gpr_##reg, NULL, NULL }
1356 #define DEFINE_PSEUDO_GPR_IDX(idx, reg)    { e_regSetGPR, gpr_##reg, #reg, NULL, Uint, Hex, 4, 0, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_x##idx, g_invalidate_x##idx }
1357 
1358 //_STRUCT_ARM_THREAD_STATE64
1359 //{
1360 //	uint64_t    x[29];	/* General purpose registers x0-x28 */
1361 //	uint64_t    fp;		/* Frame pointer x29 */
1362 //	uint64_t    lr;		/* Link register x30 */
1363 //	uint64_t    sp;		/* Stack pointer x31 */
1364 //	uint64_t    pc;		/* Program counter */
1365 //	uint32_t    cpsr;	/* Current program status register */
1366 //};
1367 
1368 
1369 // General purpose registers
1370 const DNBRegisterInfo
1371 DNBArchMachARM64::g_gpr_registers[] =
1372 {
1373     DEFINE_GPR_IDX ( 0,  x0, "arg1", GENERIC_REGNUM_ARG1  ),
1374     DEFINE_GPR_IDX ( 1,  x1, "arg2", GENERIC_REGNUM_ARG2  ),
1375     DEFINE_GPR_IDX ( 2,  x2, "arg3", GENERIC_REGNUM_ARG3  ),
1376     DEFINE_GPR_IDX ( 3,  x3, "arg4", GENERIC_REGNUM_ARG4  ),
1377     DEFINE_GPR_IDX ( 4,  x4, "arg5", GENERIC_REGNUM_ARG5  ),
1378     DEFINE_GPR_IDX ( 5,  x5, "arg6", GENERIC_REGNUM_ARG6  ),
1379     DEFINE_GPR_IDX ( 6,  x6, "arg7", GENERIC_REGNUM_ARG7  ),
1380     DEFINE_GPR_IDX ( 7,  x7, "arg8", GENERIC_REGNUM_ARG8  ),
1381     DEFINE_GPR_IDX ( 8,  x8,   NULL, INVALID_NUB_REGNUM   ),
1382     DEFINE_GPR_IDX ( 9,  x9,   NULL, INVALID_NUB_REGNUM   ),
1383     DEFINE_GPR_IDX (10, x10,   NULL, INVALID_NUB_REGNUM   ),
1384     DEFINE_GPR_IDX (11, x11,   NULL, INVALID_NUB_REGNUM   ),
1385     DEFINE_GPR_IDX (12, x12,   NULL, INVALID_NUB_REGNUM   ),
1386     DEFINE_GPR_IDX (13, x13,   NULL, INVALID_NUB_REGNUM   ),
1387     DEFINE_GPR_IDX (14, x14,   NULL, INVALID_NUB_REGNUM   ),
1388     DEFINE_GPR_IDX (15, x15,   NULL, INVALID_NUB_REGNUM   ),
1389     DEFINE_GPR_IDX (16, x16,   NULL, INVALID_NUB_REGNUM   ),
1390     DEFINE_GPR_IDX (17, x17,   NULL, INVALID_NUB_REGNUM   ),
1391     DEFINE_GPR_IDX (18, x18,   NULL, INVALID_NUB_REGNUM   ),
1392     DEFINE_GPR_IDX (19, x19,   NULL, INVALID_NUB_REGNUM   ),
1393     DEFINE_GPR_IDX (20, x20,   NULL, INVALID_NUB_REGNUM   ),
1394     DEFINE_GPR_IDX (21, x21,   NULL, INVALID_NUB_REGNUM   ),
1395     DEFINE_GPR_IDX (22, x22,   NULL, INVALID_NUB_REGNUM   ),
1396     DEFINE_GPR_IDX (23, x23,   NULL, INVALID_NUB_REGNUM   ),
1397     DEFINE_GPR_IDX (24, x24,   NULL, INVALID_NUB_REGNUM   ),
1398     DEFINE_GPR_IDX (25, x25,   NULL, INVALID_NUB_REGNUM   ),
1399     DEFINE_GPR_IDX (26, x26,   NULL, INVALID_NUB_REGNUM   ),
1400     DEFINE_GPR_IDX (27, x27,   NULL, INVALID_NUB_REGNUM   ),
1401     DEFINE_GPR_IDX (28, x28,   NULL, INVALID_NUB_REGNUM   ),
1402     DEFINE_GPR_NAME (fp, "x29", GENERIC_REGNUM_FP),
1403     DEFINE_GPR_NAME (lr, "x30", GENERIC_REGNUM_RA),
1404     DEFINE_GPR_NAME (sp, "xsp",  GENERIC_REGNUM_SP),
1405     DEFINE_GPR_NAME (pc,  NULL, GENERIC_REGNUM_PC),
1406 
1407     // in armv7 we specify that writing to the CPSR should invalidate r8-12, sp, lr.
1408     // this should be specified for arm64 too even though debugserver is only used for
1409     // userland debugging.
1410     { e_regSetGPR, gpr_cpsr, "cpsr", "flags", Uint, Hex, 4, GPR_OFFSET_NAME(cpsr), dwarf_elr_mode, dwarf_elr_mode, INVALID_NUB_REGNUM, gdb_gpr_cpsr, NULL, NULL },
1411 
1412     DEFINE_PSEUDO_GPR_IDX ( 0,  w0),
1413     DEFINE_PSEUDO_GPR_IDX ( 1,  w1),
1414     DEFINE_PSEUDO_GPR_IDX ( 2,  w2),
1415     DEFINE_PSEUDO_GPR_IDX ( 3,  w3),
1416     DEFINE_PSEUDO_GPR_IDX ( 4,  w4),
1417     DEFINE_PSEUDO_GPR_IDX ( 5,  w5),
1418     DEFINE_PSEUDO_GPR_IDX ( 6,  w6),
1419     DEFINE_PSEUDO_GPR_IDX ( 7,  w7),
1420     DEFINE_PSEUDO_GPR_IDX ( 8,  w8),
1421     DEFINE_PSEUDO_GPR_IDX ( 9,  w9),
1422     DEFINE_PSEUDO_GPR_IDX (10, w10),
1423     DEFINE_PSEUDO_GPR_IDX (11, w11),
1424     DEFINE_PSEUDO_GPR_IDX (12, w12),
1425     DEFINE_PSEUDO_GPR_IDX (13, w13),
1426     DEFINE_PSEUDO_GPR_IDX (14, w14),
1427     DEFINE_PSEUDO_GPR_IDX (15, w15),
1428     DEFINE_PSEUDO_GPR_IDX (16, w16),
1429     DEFINE_PSEUDO_GPR_IDX (17, w17),
1430     DEFINE_PSEUDO_GPR_IDX (18, w18),
1431     DEFINE_PSEUDO_GPR_IDX (19, w19),
1432     DEFINE_PSEUDO_GPR_IDX (20, w20),
1433     DEFINE_PSEUDO_GPR_IDX (21, w21),
1434     DEFINE_PSEUDO_GPR_IDX (22, w22),
1435     DEFINE_PSEUDO_GPR_IDX (23, w23),
1436     DEFINE_PSEUDO_GPR_IDX (24, w24),
1437     DEFINE_PSEUDO_GPR_IDX (25, w25),
1438     DEFINE_PSEUDO_GPR_IDX (26, w26),
1439     DEFINE_PSEUDO_GPR_IDX (27, w27),
1440     DEFINE_PSEUDO_GPR_IDX (28, w28)
1441 };
1442 
1443 const char *g_contained_v0[] {"v0", NULL };
1444 const char *g_contained_v1[] {"v1", NULL };
1445 const char *g_contained_v2[] {"v2", NULL };
1446 const char *g_contained_v3[] {"v3", NULL };
1447 const char *g_contained_v4[] {"v4", NULL };
1448 const char *g_contained_v5[] {"v5", NULL };
1449 const char *g_contained_v6[] {"v6", NULL };
1450 const char *g_contained_v7[] {"v7", NULL };
1451 const char *g_contained_v8[] {"v8", NULL };
1452 const char *g_contained_v9[] {"v9", NULL };
1453 const char *g_contained_v10[] {"v10", NULL };
1454 const char *g_contained_v11[] {"v11", NULL };
1455 const char *g_contained_v12[] {"v12", NULL };
1456 const char *g_contained_v13[] {"v13", NULL };
1457 const char *g_contained_v14[] {"v14", NULL };
1458 const char *g_contained_v15[] {"v15", NULL };
1459 const char *g_contained_v16[] {"v16", NULL };
1460 const char *g_contained_v17[] {"v17", NULL };
1461 const char *g_contained_v18[] {"v18", NULL };
1462 const char *g_contained_v19[] {"v19", NULL };
1463 const char *g_contained_v20[] {"v20", NULL };
1464 const char *g_contained_v21[] {"v21", NULL };
1465 const char *g_contained_v22[] {"v22", NULL };
1466 const char *g_contained_v23[] {"v23", NULL };
1467 const char *g_contained_v24[] {"v24", NULL };
1468 const char *g_contained_v25[] {"v25", NULL };
1469 const char *g_contained_v26[] {"v26", NULL };
1470 const char *g_contained_v27[] {"v27", NULL };
1471 const char *g_contained_v28[] {"v28", NULL };
1472 const char *g_contained_v29[] {"v29", NULL };
1473 const char *g_contained_v30[] {"v30", NULL };
1474 const char *g_contained_v31[] {"v31", NULL };
1475 
1476 const char *g_invalidate_v0[] {"v0", "d0", "s0", NULL };
1477 const char *g_invalidate_v1[] {"v1", "d1", "s1", NULL };
1478 const char *g_invalidate_v2[] {"v2", "d2", "s2", NULL };
1479 const char *g_invalidate_v3[] {"v3", "d3", "s3", NULL };
1480 const char *g_invalidate_v4[] {"v4", "d4", "s4", NULL };
1481 const char *g_invalidate_v5[] {"v5", "d5", "s5", NULL };
1482 const char *g_invalidate_v6[] {"v6", "d6", "s6", NULL };
1483 const char *g_invalidate_v7[] {"v7", "d7", "s7", NULL };
1484 const char *g_invalidate_v8[] {"v8", "d8", "s8", NULL };
1485 const char *g_invalidate_v9[] {"v9", "d9", "s9", NULL };
1486 const char *g_invalidate_v10[] {"v10", "d10", "s10", NULL };
1487 const char *g_invalidate_v11[] {"v11", "d11", "s11", NULL };
1488 const char *g_invalidate_v12[] {"v12", "d12", "s12", NULL };
1489 const char *g_invalidate_v13[] {"v13", "d13", "s13", NULL };
1490 const char *g_invalidate_v14[] {"v14", "d14", "s14", NULL };
1491 const char *g_invalidate_v15[] {"v15", "d15", "s15", NULL };
1492 const char *g_invalidate_v16[] {"v16", "d16", "s16", NULL };
1493 const char *g_invalidate_v17[] {"v17", "d17", "s17", NULL };
1494 const char *g_invalidate_v18[] {"v18", "d18", "s18", NULL };
1495 const char *g_invalidate_v19[] {"v19", "d19", "s19", NULL };
1496 const char *g_invalidate_v20[] {"v20", "d20", "s20", NULL };
1497 const char *g_invalidate_v21[] {"v21", "d21", "s21", NULL };
1498 const char *g_invalidate_v22[] {"v22", "d22", "s22", NULL };
1499 const char *g_invalidate_v23[] {"v23", "d23", "s23", NULL };
1500 const char *g_invalidate_v24[] {"v24", "d24", "s24", NULL };
1501 const char *g_invalidate_v25[] {"v25", "d25", "s25", NULL };
1502 const char *g_invalidate_v26[] {"v26", "d26", "s26", NULL };
1503 const char *g_invalidate_v27[] {"v27", "d27", "s27", NULL };
1504 const char *g_invalidate_v28[] {"v28", "d28", "s28", NULL };
1505 const char *g_invalidate_v29[] {"v29", "d29", "s29", NULL };
1506 const char *g_invalidate_v30[] {"v30", "d30", "s30", NULL };
1507 const char *g_invalidate_v31[] {"v31", "d31", "s31", NULL };
1508 
1509 #if defined (__arm64__) || defined (__aarch64__)
1510 #define VFP_V_OFFSET_IDX(idx) (offsetof (DNBArchMachARM64::FPU, __v) + (idx * 16) + offsetof (DNBArchMachARM64::Context, vfp))
1511 #else
1512 #define VFP_V_OFFSET_IDX(idx) (offsetof (DNBArchMachARM64::FPU, opaque) + (idx * 16) + offsetof (DNBArchMachARM64::Context, vfp))
1513 #endif
1514 #define VFP_OFFSET_NAME(reg) (offsetof (DNBArchMachARM64::FPU, reg) + offsetof (DNBArchMachARM64::Context, vfp))
1515 #define EXC_OFFSET(reg)      (offsetof (DNBArchMachARM64::EXC, reg)  + offsetof (DNBArchMachARM64::Context, exc))
1516 
1517 //#define FLOAT_FORMAT Float
1518 #define DEFINE_VFP_V_IDX(idx) { e_regSetVFP, vfp_v##idx, "v" #idx, "q" #idx, Vector, VectorOfUInt8, 16, VFP_V_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_v##idx, INVALID_NUB_REGNUM, gdb_vfp_v##idx, NULL, g_invalidate_v##idx }
1519 #define DEFINE_PSEUDO_VFP_S_IDX(idx) { e_regSetVFP, vfp_s##idx, "s" #idx, NULL, IEEE754, Float, 4, 0, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_v##idx, g_invalidate_v##idx }
1520 #define DEFINE_PSEUDO_VFP_D_IDX(idx) { e_regSetVFP, vfp_d##idx, "d" #idx, NULL, IEEE754, Float, 8, 0, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_v##idx, g_invalidate_v##idx }
1521 
1522 // Floating point registers
1523 const DNBRegisterInfo
1524 DNBArchMachARM64::g_vfp_registers[] =
1525 {
1526     DEFINE_VFP_V_IDX ( 0),
1527     DEFINE_VFP_V_IDX ( 1),
1528     DEFINE_VFP_V_IDX ( 2),
1529     DEFINE_VFP_V_IDX ( 3),
1530     DEFINE_VFP_V_IDX ( 4),
1531     DEFINE_VFP_V_IDX ( 5),
1532     DEFINE_VFP_V_IDX ( 6),
1533     DEFINE_VFP_V_IDX ( 7),
1534     DEFINE_VFP_V_IDX ( 8),
1535     DEFINE_VFP_V_IDX ( 9),
1536     DEFINE_VFP_V_IDX (10),
1537     DEFINE_VFP_V_IDX (11),
1538     DEFINE_VFP_V_IDX (12),
1539     DEFINE_VFP_V_IDX (13),
1540     DEFINE_VFP_V_IDX (14),
1541     DEFINE_VFP_V_IDX (15),
1542     DEFINE_VFP_V_IDX (16),
1543     DEFINE_VFP_V_IDX (17),
1544     DEFINE_VFP_V_IDX (18),
1545     DEFINE_VFP_V_IDX (19),
1546     DEFINE_VFP_V_IDX (20),
1547     DEFINE_VFP_V_IDX (21),
1548     DEFINE_VFP_V_IDX (22),
1549     DEFINE_VFP_V_IDX (23),
1550     DEFINE_VFP_V_IDX (24),
1551     DEFINE_VFP_V_IDX (25),
1552     DEFINE_VFP_V_IDX (26),
1553     DEFINE_VFP_V_IDX (27),
1554     DEFINE_VFP_V_IDX (28),
1555     DEFINE_VFP_V_IDX (29),
1556     DEFINE_VFP_V_IDX (30),
1557     DEFINE_VFP_V_IDX (31),
1558     { e_regSetVFP, vfp_fpsr, "fpsr", NULL, Uint, Hex, 4, VFP_V_OFFSET_IDX (32) + 0, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1559     { e_regSetVFP, vfp_fpcr, "fpcr", NULL, Uint, Hex, 4, VFP_V_OFFSET_IDX (32) + 4, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1560 
1561     DEFINE_PSEUDO_VFP_S_IDX (0),
1562     DEFINE_PSEUDO_VFP_S_IDX (1),
1563     DEFINE_PSEUDO_VFP_S_IDX (2),
1564     DEFINE_PSEUDO_VFP_S_IDX (3),
1565     DEFINE_PSEUDO_VFP_S_IDX (4),
1566     DEFINE_PSEUDO_VFP_S_IDX (5),
1567     DEFINE_PSEUDO_VFP_S_IDX (6),
1568     DEFINE_PSEUDO_VFP_S_IDX (7),
1569     DEFINE_PSEUDO_VFP_S_IDX (8),
1570     DEFINE_PSEUDO_VFP_S_IDX (9),
1571     DEFINE_PSEUDO_VFP_S_IDX (10),
1572     DEFINE_PSEUDO_VFP_S_IDX (11),
1573     DEFINE_PSEUDO_VFP_S_IDX (12),
1574     DEFINE_PSEUDO_VFP_S_IDX (13),
1575     DEFINE_PSEUDO_VFP_S_IDX (14),
1576     DEFINE_PSEUDO_VFP_S_IDX (15),
1577     DEFINE_PSEUDO_VFP_S_IDX (16),
1578     DEFINE_PSEUDO_VFP_S_IDX (17),
1579     DEFINE_PSEUDO_VFP_S_IDX (18),
1580     DEFINE_PSEUDO_VFP_S_IDX (19),
1581     DEFINE_PSEUDO_VFP_S_IDX (20),
1582     DEFINE_PSEUDO_VFP_S_IDX (21),
1583     DEFINE_PSEUDO_VFP_S_IDX (22),
1584     DEFINE_PSEUDO_VFP_S_IDX (23),
1585     DEFINE_PSEUDO_VFP_S_IDX (24),
1586     DEFINE_PSEUDO_VFP_S_IDX (25),
1587     DEFINE_PSEUDO_VFP_S_IDX (26),
1588     DEFINE_PSEUDO_VFP_S_IDX (27),
1589     DEFINE_PSEUDO_VFP_S_IDX (28),
1590     DEFINE_PSEUDO_VFP_S_IDX (29),
1591     DEFINE_PSEUDO_VFP_S_IDX (30),
1592     DEFINE_PSEUDO_VFP_S_IDX (31),
1593 
1594     DEFINE_PSEUDO_VFP_D_IDX (0),
1595     DEFINE_PSEUDO_VFP_D_IDX (1),
1596     DEFINE_PSEUDO_VFP_D_IDX (2),
1597     DEFINE_PSEUDO_VFP_D_IDX (3),
1598     DEFINE_PSEUDO_VFP_D_IDX (4),
1599     DEFINE_PSEUDO_VFP_D_IDX (5),
1600     DEFINE_PSEUDO_VFP_D_IDX (6),
1601     DEFINE_PSEUDO_VFP_D_IDX (7),
1602     DEFINE_PSEUDO_VFP_D_IDX (8),
1603     DEFINE_PSEUDO_VFP_D_IDX (9),
1604     DEFINE_PSEUDO_VFP_D_IDX (10),
1605     DEFINE_PSEUDO_VFP_D_IDX (11),
1606     DEFINE_PSEUDO_VFP_D_IDX (12),
1607     DEFINE_PSEUDO_VFP_D_IDX (13),
1608     DEFINE_PSEUDO_VFP_D_IDX (14),
1609     DEFINE_PSEUDO_VFP_D_IDX (15),
1610     DEFINE_PSEUDO_VFP_D_IDX (16),
1611     DEFINE_PSEUDO_VFP_D_IDX (17),
1612     DEFINE_PSEUDO_VFP_D_IDX (18),
1613     DEFINE_PSEUDO_VFP_D_IDX (19),
1614     DEFINE_PSEUDO_VFP_D_IDX (20),
1615     DEFINE_PSEUDO_VFP_D_IDX (21),
1616     DEFINE_PSEUDO_VFP_D_IDX (22),
1617     DEFINE_PSEUDO_VFP_D_IDX (23),
1618     DEFINE_PSEUDO_VFP_D_IDX (24),
1619     DEFINE_PSEUDO_VFP_D_IDX (25),
1620     DEFINE_PSEUDO_VFP_D_IDX (26),
1621     DEFINE_PSEUDO_VFP_D_IDX (27),
1622     DEFINE_PSEUDO_VFP_D_IDX (28),
1623     DEFINE_PSEUDO_VFP_D_IDX (29),
1624     DEFINE_PSEUDO_VFP_D_IDX (30),
1625     DEFINE_PSEUDO_VFP_D_IDX (31)
1626 
1627 };
1628 
1629 
1630 //_STRUCT_ARM_EXCEPTION_STATE64
1631 //{
1632 //	uint64_t	far; /* Virtual Fault Address */
1633 //	uint32_t	esr; /* Exception syndrome */
1634 //	uint32_t	exception; /* number of arm exception taken */
1635 //};
1636 
1637 // Exception registers
1638 const DNBRegisterInfo
1639 DNBArchMachARM64::g_exc_registers[] =
1640 {
1641     { e_regSetEXC, exc_far        , "far"         , NULL, Uint, Hex, 8, EXC_OFFSET(__far)       , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1642     { e_regSetEXC, exc_esr        , "esr"         , NULL, Uint, Hex, 4, EXC_OFFSET(__esr)       , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1643     { e_regSetEXC, exc_exception  , "exception"   , NULL, Uint, Hex, 4, EXC_OFFSET(__exception) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }
1644 };
1645 
1646 // Number of registers in each register set
1647 const size_t DNBArchMachARM64::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo);
1648 const size_t DNBArchMachARM64::k_num_vfp_registers = sizeof(g_vfp_registers)/sizeof(DNBRegisterInfo);
1649 const size_t DNBArchMachARM64::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo);
1650 const size_t DNBArchMachARM64::k_num_all_registers = k_num_gpr_registers + k_num_vfp_registers + k_num_exc_registers;
1651 
1652 //----------------------------------------------------------------------
1653 // Register set definitions. The first definitions at register set index
1654 // of zero is for all registers, followed by other registers sets. The
1655 // register information for the all register set need not be filled in.
1656 //----------------------------------------------------------------------
1657 const DNBRegisterSetInfo
1658 DNBArchMachARM64::g_reg_sets[] =
1659 {
1660     { "ARM64 Registers",            NULL,               k_num_all_registers     },
1661     { "General Purpose Registers",  g_gpr_registers,    k_num_gpr_registers     },
1662     { "Floating Point Registers",   g_vfp_registers,    k_num_vfp_registers     },
1663     { "Exception State Registers",  g_exc_registers,    k_num_exc_registers     }
1664 };
1665 // Total number of register sets for this architecture
1666 const size_t DNBArchMachARM64::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo);
1667 
1668 
1669 const DNBRegisterSetInfo *
1670 DNBArchMachARM64::GetRegisterSetInfo(nub_size_t *num_reg_sets)
1671 {
1672     *num_reg_sets = k_num_register_sets;
1673     return g_reg_sets;
1674 }
1675 
1676 bool
1677 DNBArchMachARM64::FixGenericRegisterNumber (uint32_t &set, uint32_t &reg)
1678 {
1679     if (set == REGISTER_SET_GENERIC)
1680     {
1681         switch (reg)
1682         {
1683             case GENERIC_REGNUM_PC:     // Program Counter
1684                 set = e_regSetGPR;
1685                 reg = gpr_pc;
1686                 break;
1687 
1688             case GENERIC_REGNUM_SP:     // Stack Pointer
1689                 set = e_regSetGPR;
1690                 reg = gpr_sp;
1691                 break;
1692 
1693             case GENERIC_REGNUM_FP:     // Frame Pointer
1694                 set = e_regSetGPR;
1695                 reg = gpr_fp;
1696                 break;
1697 
1698             case GENERIC_REGNUM_RA:     // Return Address
1699                 set = e_regSetGPR;
1700                 reg = gpr_lr;
1701                 break;
1702 
1703             case GENERIC_REGNUM_FLAGS:  // Processor flags register
1704                 set = e_regSetGPR;
1705                 reg = gpr_cpsr;
1706                 break;
1707 
1708             case GENERIC_REGNUM_ARG1:
1709             case GENERIC_REGNUM_ARG2:
1710             case GENERIC_REGNUM_ARG3:
1711             case GENERIC_REGNUM_ARG4:
1712             case GENERIC_REGNUM_ARG5:
1713             case GENERIC_REGNUM_ARG6:
1714                 set = e_regSetGPR;
1715                 reg = gpr_x0 + reg - GENERIC_REGNUM_ARG1;
1716                 break;
1717 
1718             default:
1719                 return false;
1720         }
1721     }
1722     return true;
1723 }
1724 bool
1725 DNBArchMachARM64::GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value)
1726 {
1727     if (!FixGenericRegisterNumber (set, reg))
1728         return false;
1729 
1730     if (GetRegisterState(set, false) != KERN_SUCCESS)
1731         return false;
1732 
1733     const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
1734     if (regInfo)
1735     {
1736         value->info = *regInfo;
1737         switch (set)
1738         {
1739         case e_regSetGPR:
1740             if (reg <= gpr_pc)
1741             {
1742                 value->value.uint64 = m_state.context.gpr.__x[reg];
1743                 return true;
1744             }
1745             else if (reg == gpr_cpsr)
1746             {
1747                 value->value.uint32 = m_state.context.gpr.__cpsr;
1748                 return true;
1749             }
1750             break;
1751 
1752         case e_regSetVFP:
1753 
1754             if (reg >= vfp_v0 && reg <= vfp_v31)
1755             {
1756 #if defined (__arm64__) || defined (__aarch64__)
1757                 memcpy (&value->value.v_uint8, &m_state.context.vfp.__v[reg - vfp_v0], 16);
1758 #else
1759                 memcpy (&value->value.v_uint8, ((uint8_t *) &m_state.context.vfp.opaque) + ((reg - vfp_v0) * 16), 16);
1760 #endif
1761                 return true;
1762             }
1763             else if (reg == vfp_fpsr)
1764             {
1765 #if defined (__arm64__) || defined (__aarch64__)
1766                 memcpy (&value->value.uint32, &m_state.context.vfp.__fpsr, 4);
1767 #else
1768                 memcpy (&value->value.uint32, ((uint8_t *) &m_state.context.vfp.opaque) + (32 * 16) + 0, 4);
1769 #endif
1770                 return true;
1771             }
1772             else if (reg == vfp_fpcr)
1773             {
1774 #if defined (__arm64__) || defined (__aarch64__)
1775                 memcpy (&value->value.uint32, &m_state.context.vfp.__fpcr, 4);
1776 #else
1777                 memcpy (&value->value.uint32, ((uint8_t *) &m_state.context.vfp.opaque) + (32 * 16) + 4, 4);
1778 #endif
1779                 return true;
1780             }
1781             else if (reg >= vfp_s0 && reg <= vfp_s31)
1782             {
1783 #if defined (__arm64__) || defined (__aarch64__)
1784                 memcpy (&value->value.v_uint8, &m_state.context.vfp.__v[reg - vfp_s0], 4);
1785 #else
1786                 memcpy (&value->value.v_uint8, ((uint8_t *) &m_state.context.vfp.opaque) + ((reg - vfp_s0) * 16), 4);
1787 #endif
1788                 return true;
1789             }
1790             else if (reg >= vfp_d0 && reg <= vfp_d31)
1791             {
1792 #if defined (__arm64__) || defined (__aarch64__)
1793                 memcpy (&value->value.v_uint8, &m_state.context.vfp.__v[reg - vfp_d0], 8);
1794 #else
1795                 memcpy (&value->value.v_uint8, ((uint8_t *) &m_state.context.vfp.opaque) + ((reg - vfp_d0) * 16), 8);
1796 #endif
1797                 return true;
1798             }
1799             break;
1800 
1801         case e_regSetEXC:
1802             if (reg == exc_far)
1803             {
1804                 value->value.uint64 = m_state.context.exc.__far;
1805                 return true;
1806             }
1807             else if (reg == exc_esr)
1808             {
1809                 value->value.uint32 = m_state.context.exc.__esr;
1810                 return true;
1811             }
1812             else if (reg == exc_exception)
1813             {
1814                 value->value.uint32 = m_state.context.exc.__exception;
1815                 return true;
1816             }
1817             break;
1818         }
1819     }
1820     return false;
1821 }
1822 
1823 bool
1824 DNBArchMachARM64::SetRegisterValue(uint32_t set, uint32_t reg, const DNBRegisterValue *value)
1825 {
1826     if (!FixGenericRegisterNumber (set, reg))
1827         return false;
1828 
1829     if (GetRegisterState(set, false) != KERN_SUCCESS)
1830         return false;
1831 
1832     bool success = false;
1833     const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
1834     if (regInfo)
1835     {
1836         switch (set)
1837         {
1838         case e_regSetGPR:
1839             if (reg <= gpr_pc)
1840             {
1841                 m_state.context.gpr.__x[reg] = value->value.uint64;
1842                 success = true;
1843             }
1844             else if (reg == gpr_cpsr)
1845             {
1846                 m_state.context.gpr.__cpsr = value->value.uint32;
1847                 success = true;
1848             }
1849             break;
1850 
1851         case e_regSetVFP:
1852             if (reg >= vfp_v0 && reg <= vfp_v31)
1853             {
1854 #if defined (__arm64__) || defined (__aarch64__)
1855                 memcpy (&m_state.context.vfp.__v[reg - vfp_v0], &value->value.v_uint8, 16);
1856 #else
1857                 memcpy (((uint8_t *) &m_state.context.vfp.opaque) + ((reg - vfp_v0) * 16), &value->value.v_uint8, 16);
1858 #endif
1859                 success = true;
1860             }
1861             else if (reg == vfp_fpsr)
1862             {
1863 #if defined (__arm64__) || defined (__aarch64__)
1864                 memcpy (&m_state.context.vfp.__fpsr, &value->value.uint32, 4);
1865 #else
1866                 memcpy (((uint8_t *) &m_state.context.vfp.opaque) + (32 * 16) + 0, &value->value.uint32, 4);
1867 #endif
1868                 success = true;
1869             }
1870             else if (reg == vfp_fpcr)
1871             {
1872 #if defined (__arm64__) || defined (__aarch64__)
1873                 memcpy (&m_state.context.vfp.__fpcr, &value->value.uint32, 4);
1874 #else
1875                 memcpy (((uint8_t *) m_state.context.vfp.opaque) + (32 * 16) + 4, &value->value.uint32, 4);
1876 #endif
1877                 success = true;
1878             }
1879             else if (reg >= vfp_s0 && reg <= vfp_s31)
1880             {
1881 #if defined (__arm64__) || defined (__aarch64__)
1882                 memcpy (&m_state.context.vfp.__v[reg - vfp_s0], &value->value.v_uint8, 4);
1883 #else
1884                 memcpy (((uint8_t *) &m_state.context.vfp.opaque) + ((reg - vfp_s0) * 16), &value->value.v_uint8, 4);
1885 #endif
1886                 success = true;
1887             }
1888             else if (reg >= vfp_d0 && reg <= vfp_d31)
1889             {
1890 #if defined (__arm64__) || defined (__aarch64__)
1891                 memcpy (&m_state.context.vfp.__v[reg - vfp_d0], &value->value.v_uint8, 8);
1892 #else
1893                 memcpy (((uint8_t *) &m_state.context.vfp.opaque) + ((reg - vfp_d0) * 16), &value->value.v_uint8, 8);
1894 #endif
1895                 success = true;
1896             }
1897             break;
1898 
1899         case e_regSetEXC:
1900             if (reg == exc_far)
1901             {
1902                 m_state.context.exc.__far = value->value.uint64;
1903                 success = true;
1904             }
1905             else if (reg == exc_esr)
1906             {
1907                 m_state.context.exc.__esr = value->value.uint32;
1908                 success = true;
1909             }
1910             else if (reg == exc_exception)
1911             {
1912                 m_state.context.exc.__exception = value->value.uint32;
1913                 success = true;
1914             }
1915             break;
1916         }
1917 
1918     }
1919     if (success)
1920         return SetRegisterState(set) == KERN_SUCCESS;
1921     return false;
1922 }
1923 
1924 kern_return_t
1925 DNBArchMachARM64::GetRegisterState(int set, bool force)
1926 {
1927     switch (set)
1928     {
1929     case e_regSetALL:   return GetGPRState(force) |
1930                                GetVFPState(force) |
1931                                GetEXCState(force) |
1932                                GetDBGState(force);
1933     case e_regSetGPR:   return GetGPRState(force);
1934     case e_regSetVFP:   return GetVFPState(force);
1935     case e_regSetEXC:   return GetEXCState(force);
1936     case e_regSetDBG:   return GetDBGState(force);
1937     default: break;
1938     }
1939     return KERN_INVALID_ARGUMENT;
1940 }
1941 
1942 kern_return_t
1943 DNBArchMachARM64::SetRegisterState(int set)
1944 {
1945     // Make sure we have a valid context to set.
1946     kern_return_t err = GetRegisterState(set, false);
1947     if (err != KERN_SUCCESS)
1948         return err;
1949 
1950     switch (set)
1951     {
1952     case e_regSetALL:   return SetGPRState() |
1953                                SetVFPState() |
1954                                SetEXCState() |
1955                                SetDBGState(false);
1956     case e_regSetGPR:   return SetGPRState();
1957     case e_regSetVFP:   return SetVFPState();
1958     case e_regSetEXC:   return SetEXCState();
1959     case e_regSetDBG:   return SetDBGState(false);
1960     default: break;
1961     }
1962     return KERN_INVALID_ARGUMENT;
1963 }
1964 
1965 bool
1966 DNBArchMachARM64::RegisterSetStateIsValid (int set) const
1967 {
1968     return m_state.RegsAreValid(set);
1969 }
1970 
1971 
1972 nub_size_t
1973 DNBArchMachARM64::GetRegisterContext (void *buf, nub_size_t buf_len)
1974 {
1975     nub_size_t size = sizeof (m_state.context.gpr) +
1976                       sizeof (m_state.context.vfp) +
1977                       sizeof (m_state.context.exc);
1978 
1979     if (buf && buf_len)
1980     {
1981         if (size > buf_len)
1982             size = buf_len;
1983 
1984         bool force = false;
1985         if (GetGPRState(force) | GetVFPState(force) | GetEXCState(force))
1986             return 0;
1987 
1988         // Copy each struct individually to avoid any padding that might be between the structs in m_state.context
1989         uint8_t *p = (uint8_t *)buf;
1990         ::memcpy (p, &m_state.context.gpr, sizeof(m_state.context.gpr));
1991         p += sizeof(m_state.context.gpr);
1992         ::memcpy (p, &m_state.context.vfp, sizeof(m_state.context.vfp));
1993         p += sizeof(m_state.context.vfp);
1994         ::memcpy (p, &m_state.context.exc, sizeof(m_state.context.exc));
1995         p += sizeof(m_state.context.exc);
1996 
1997         size_t bytes_written = p - (uint8_t *)buf;
1998         UNUSED_IF_ASSERT_DISABLED(bytes_written);
1999         assert (bytes_written == size);
2000     }
2001     DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM64::GetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size);
2002     // Return the size of the register context even if NULL was passed in
2003     return size;
2004 }
2005 
2006 nub_size_t
2007 DNBArchMachARM64::SetRegisterContext (const void *buf, nub_size_t buf_len)
2008 {
2009     nub_size_t size = sizeof (m_state.context.gpr) +
2010                       sizeof (m_state.context.vfp) +
2011                       sizeof (m_state.context.exc);
2012 
2013     if (buf == NULL || buf_len == 0)
2014         size = 0;
2015 
2016     if (size)
2017     {
2018         if (size > buf_len)
2019             size = buf_len;
2020 
2021         // Copy each struct individually to avoid any padding that might be between the structs in m_state.context
2022         uint8_t *p = (uint8_t *)buf;
2023         ::memcpy (&m_state.context.gpr, p, sizeof(m_state.context.gpr));
2024         p += sizeof(m_state.context.gpr);
2025         ::memcpy (&m_state.context.vfp, p, sizeof(m_state.context.vfp));
2026         p += sizeof(m_state.context.vfp);
2027         ::memcpy (&m_state.context.exc, p, sizeof(m_state.context.exc));
2028         p += sizeof(m_state.context.exc);
2029 
2030         size_t bytes_written = p - (uint8_t *)buf;
2031         UNUSED_IF_ASSERT_DISABLED(bytes_written);
2032         assert (bytes_written == size);
2033         SetGPRState();
2034         SetVFPState();
2035         SetEXCState();
2036     }
2037     DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM64::SetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size);
2038     return size;
2039 }
2040 
2041 uint32_t
2042 DNBArchMachARM64::SaveRegisterState ()
2043 {
2044     kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber());
2045     DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount());
2046 
2047     // Always re-read the registers because above we call thread_abort_safely();
2048     bool force = true;
2049 
2050     if ((kret = GetGPRState(force)) != KERN_SUCCESS)
2051     {
2052         DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM64::SaveRegisterState () error: GPR regs failed to read: %u ", kret);
2053     }
2054     else if ((kret = GetVFPState(force)) != KERN_SUCCESS)
2055     {
2056         DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM64::SaveRegisterState () error: %s regs failed to read: %u", "VFP", kret);
2057     }
2058     else
2059     {
2060         const uint32_t save_id = GetNextRegisterStateSaveID ();
2061         m_saved_register_states[save_id] = m_state.context;
2062         return save_id;
2063     }
2064     return UINT32_MAX;
2065 }
2066 
2067 bool
2068 DNBArchMachARM64::RestoreRegisterState (uint32_t save_id)
2069 {
2070     SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id);
2071     if (pos != m_saved_register_states.end())
2072     {
2073         m_state.context.gpr = pos->second.gpr;
2074         m_state.context.vfp = pos->second.vfp;
2075         kern_return_t kret;
2076         bool success = true;
2077         if ((kret = SetGPRState()) != KERN_SUCCESS)
2078         {
2079             DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM64::RestoreRegisterState (save_id = %u) error: GPR regs failed to write: %u", save_id, kret);
2080             success = false;
2081         }
2082         else if ((kret = SetVFPState()) != KERN_SUCCESS)
2083         {
2084             DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM64::RestoreRegisterState (save_id = %u) error: %s regs failed to write: %u", save_id, "VFP", kret);
2085             success = false;
2086         }
2087         m_saved_register_states.erase(pos);
2088         return success;
2089     }
2090     return false;
2091 }
2092 
2093 
2094 #endif  // #if defined (ARM_THREAD_STATE64_COUNT)
2095 #endif  // #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
2096