1 //===-- GDBRemoteRegisterContext.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 #include "GDBRemoteRegisterContext.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 #include "lldb/Core/DataBufferHeap.h"
16 #include "lldb/Core/DataExtractor.h"
17 #include "lldb/Core/RegisterValue.h"
18 #include "lldb/Core/Scalar.h"
19 #include "lldb/Core/StreamString.h"
20 #include "lldb/Target/ExecutionContext.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Utility/Utils.h"
23 // Project includes
24 #include "Utility/StringExtractorGDBRemote.h"
25 #include "ProcessGDBRemote.h"
26 #include "ProcessGDBRemoteLog.h"
27 #include "ThreadGDBRemote.h"
28 #include "Utility/ARM_DWARF_Registers.h"
29 #include "Utility/ARM_ehframe_Registers.h"
30 
31 using namespace lldb;
32 using namespace lldb_private;
33 using namespace lldb_private::process_gdb_remote;
34 
35 //----------------------------------------------------------------------
36 // GDBRemoteRegisterContext constructor
37 //----------------------------------------------------------------------
38 GDBRemoteRegisterContext::GDBRemoteRegisterContext
39 (
40     ThreadGDBRemote &thread,
41     uint32_t concrete_frame_idx,
42     GDBRemoteDynamicRegisterInfo &reg_info,
43     bool read_all_at_once
44 ) :
45     RegisterContext (thread, concrete_frame_idx),
46     m_reg_info (reg_info),
47     m_reg_valid (),
48     m_reg_data (),
49     m_read_all_at_once (read_all_at_once)
50 {
51     // Resize our vector of bools to contain one bool for every register.
52     // We will use these boolean values to know when a register value
53     // is valid in m_reg_data.
54     m_reg_valid.resize (reg_info.GetNumRegisters());
55 
56     // Make a heap based buffer that is big enough to store all registers
57     DataBufferSP reg_data_sp(new DataBufferHeap (reg_info.GetRegisterDataByteSize(), 0));
58     m_reg_data.SetData (reg_data_sp);
59     m_reg_data.SetByteOrder(thread.GetProcess()->GetByteOrder());
60 }
61 
62 //----------------------------------------------------------------------
63 // Destructor
64 //----------------------------------------------------------------------
65 GDBRemoteRegisterContext::~GDBRemoteRegisterContext()
66 {
67 }
68 
69 void
70 GDBRemoteRegisterContext::InvalidateAllRegisters ()
71 {
72     SetAllRegisterValid (false);
73 }
74 
75 void
76 GDBRemoteRegisterContext::SetAllRegisterValid (bool b)
77 {
78     std::vector<bool>::iterator pos, end = m_reg_valid.end();
79     for (pos = m_reg_valid.begin(); pos != end; ++pos)
80         *pos = b;
81 }
82 
83 size_t
84 GDBRemoteRegisterContext::GetRegisterCount ()
85 {
86     return m_reg_info.GetNumRegisters ();
87 }
88 
89 const RegisterInfo *
90 GDBRemoteRegisterContext::GetRegisterInfoAtIndex (size_t reg)
91 {
92     RegisterInfo* reg_info = m_reg_info.GetRegisterInfoAtIndex (reg);
93 
94     if (reg_info && reg_info->dynamic_size_dwarf_expr_bytes)
95     {
96         const ArchSpec &arch = m_thread.GetProcess ()->GetTarget ().GetArchitecture ();
97         uint8_t reg_size = UpdateDynamicRegisterSize (arch, reg_info);
98         reg_info->byte_size = reg_size;
99     }
100     return reg_info;
101 }
102 
103 size_t
104 GDBRemoteRegisterContext::GetRegisterSetCount ()
105 {
106     return m_reg_info.GetNumRegisterSets ();
107 }
108 
109 
110 
111 const RegisterSet *
112 GDBRemoteRegisterContext::GetRegisterSet (size_t reg_set)
113 {
114     return m_reg_info.GetRegisterSet (reg_set);
115 }
116 
117 
118 
119 bool
120 GDBRemoteRegisterContext::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value)
121 {
122     // Read the register
123     if (ReadRegisterBytes (reg_info, m_reg_data))
124     {
125         const bool partial_data_ok = false;
126         Error error (value.SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok));
127         return error.Success();
128     }
129     return false;
130 }
131 
132 bool
133 GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, StringExtractor &response)
134 {
135     const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
136     if (reg_info == NULL)
137         return false;
138 
139     // Invalidate if needed
140     InvalidateIfNeeded(false);
141 
142     const uint32_t reg_byte_size = reg_info->byte_size;
143     const size_t bytes_copied = response.GetHexBytes (const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_byte_size)), reg_byte_size, '\xcc');
144     bool success = bytes_copied == reg_byte_size;
145     if (success)
146     {
147         SetRegisterIsValid(reg, true);
148     }
149     else if (bytes_copied > 0)
150     {
151         // Only set register is valid to false if we copied some bytes, else
152         // leave it as it was.
153         SetRegisterIsValid(reg, false);
154     }
155     return success;
156 }
157 
158 bool
159 GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, uint64_t new_reg_val)
160 {
161     const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
162     if (reg_info == NULL)
163         return false;
164 
165     // Early in process startup, we can get a thread that has an invalid byte order
166     // because the process hasn't been completely set up yet (see the ctor where the
167     // byte order is setfrom the process).  If that's the case, we can't set the
168     // value here.
169     if (m_reg_data.GetByteOrder() == eByteOrderInvalid)
170     {
171         return false;
172     }
173 
174     // Invalidate if needed
175     InvalidateIfNeeded (false);
176 
177     DataBufferSP buffer_sp (new DataBufferHeap (&new_reg_val, sizeof (new_reg_val)));
178     DataExtractor data (buffer_sp, endian::InlHostByteOrder(), sizeof (void*));
179 
180     // If our register context and our register info disagree, which should never happen, don't
181     // overwrite past the end of the buffer.
182     if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
183         return false;
184 
185     // Grab a pointer to where we are going to put this register
186     uint8_t *dst = const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
187 
188     if (dst == NULL)
189         return false;
190 
191 
192     if (data.CopyByteOrderedData (0,                            // src offset
193                                   reg_info->byte_size,          // src length
194                                   dst,                          // dst
195                                   reg_info->byte_size,          // dst length
196                                   m_reg_data.GetByteOrder()))   // dst byte order
197     {
198         SetRegisterIsValid (reg, true);
199         return true;
200     }
201     return false;
202 }
203 
204 // Helper function for GDBRemoteRegisterContext::ReadRegisterBytes().
205 bool
206 GDBRemoteRegisterContext::GetPrimordialRegister(const RegisterInfo *reg_info,
207                                                 GDBRemoteCommunicationClient &gdb_comm)
208 {
209     const uint32_t lldb_reg = reg_info->kinds[eRegisterKindLLDB];
210     const uint32_t remote_reg = reg_info->kinds[eRegisterKindProcessPlugin];
211     StringExtractorGDBRemote response;
212     if (gdb_comm.ReadRegister(m_thread.GetProtocolID(), remote_reg, response))
213         return PrivateSetRegisterValue (lldb_reg, response);
214     return false;
215 }
216 
217 bool
218 GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataExtractor &data)
219 {
220     ExecutionContext exe_ctx (CalculateThread());
221 
222     Process *process = exe_ctx.GetProcessPtr();
223     Thread *thread = exe_ctx.GetThreadPtr();
224     if (process == NULL || thread == NULL)
225         return false;
226 
227     GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
228 
229     InvalidateIfNeeded(false);
230 
231     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
232 
233     if (!GetRegisterIsValid(reg))
234     {
235         if (m_read_all_at_once)
236         {
237             StringExtractorGDBRemote response;
238             if (!gdb_comm.ReadAllRegisters(m_thread.GetProtocolID(), response))
239                 return false;
240             if (response.IsNormalResponse())
241                 if (response.GetHexBytes(const_cast<void *>(reinterpret_cast<const void *>(m_reg_data.GetDataStart())),
242                                          m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize())
243                     SetAllRegisterValid (true);
244         }
245         else if (reg_info->value_regs)
246         {
247             // Process this composite register request by delegating to the constituent
248             // primordial registers.
249 
250             // Index of the primordial register.
251             bool success = true;
252             for (uint32_t idx = 0; success; ++idx)
253             {
254                 const uint32_t prim_reg = reg_info->value_regs[idx];
255                 if (prim_reg == LLDB_INVALID_REGNUM)
256                     break;
257                 // We have a valid primordial register as our constituent.
258                 // Grab the corresponding register info.
259                 const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg);
260                 if (prim_reg_info == NULL)
261                     success = false;
262                 else
263                 {
264                     // Read the containing register if it hasn't already been read
265                     if (!GetRegisterIsValid(prim_reg))
266                         success = GetPrimordialRegister(prim_reg_info, gdb_comm);
267                 }
268             }
269 
270             if (success)
271             {
272                 // If we reach this point, all primordial register requests have succeeded.
273                 // Validate this composite register.
274                 SetRegisterIsValid (reg_info, true);
275             }
276         }
277         else
278         {
279             // Get each register individually
280             GetPrimordialRegister(reg_info, gdb_comm);
281         }
282 
283         // Make sure we got a valid register value after reading it
284         if (!GetRegisterIsValid(reg))
285             return false;
286     }
287 
288     if (&data != &m_reg_data)
289     {
290 #if defined (LLDB_CONFIGURATION_DEBUG)
291         assert (m_reg_data.GetByteSize() >= reg_info->byte_offset + reg_info->byte_size);
292 #endif
293         // If our register context and our register info disagree, which should never happen, don't
294         // read past the end of the buffer.
295         if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
296             return false;
297 
298         // If we aren't extracting into our own buffer (which
299         // only happens when this function is called from
300         // ReadRegisterValue(uint32_t, Scalar&)) then
301         // we transfer bytes from our buffer into the data
302         // buffer that was passed in
303 
304         data.SetByteOrder (m_reg_data.GetByteOrder());
305         data.SetData (m_reg_data, reg_info->byte_offset, reg_info->byte_size);
306     }
307     return true;
308 }
309 
310 bool
311 GDBRemoteRegisterContext::WriteRegister (const RegisterInfo *reg_info,
312                                          const RegisterValue &value)
313 {
314     DataExtractor data;
315     if (value.GetData (data))
316         return WriteRegisterBytes (reg_info, data, 0);
317     return false;
318 }
319 
320 // Helper function for GDBRemoteRegisterContext::WriteRegisterBytes().
321 bool
322 GDBRemoteRegisterContext::SetPrimordialRegister(const RegisterInfo *reg_info,
323                                                 GDBRemoteCommunicationClient &gdb_comm)
324 {
325     StreamString packet;
326     StringExtractorGDBRemote response;
327     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
328     packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]);
329     packet.PutBytesAsRawHex8 (m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size),
330                               reg_info->byte_size,
331                               endian::InlHostByteOrder(),
332                               endian::InlHostByteOrder());
333 
334     if (gdb_comm.GetThreadSuffixSupported())
335         packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
336 
337     // Invalidate just this register
338     SetRegisterIsValid(reg, false);
339     if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
340                                               packet.GetString().size(),
341                                               response,
342                                               false) == GDBRemoteCommunication::PacketResult::Success)
343     {
344         if (response.IsOKResponse())
345             return true;
346     }
347     return false;
348 }
349 
350 void
351 GDBRemoteRegisterContext::SyncThreadState(Process *process)
352 {
353     // NB.  We assume our caller has locked the sequence mutex.
354 
355     GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *) process)->GetGDBRemote());
356     if (!gdb_comm.GetSyncThreadStateSupported())
357         return;
358 
359     StreamString packet;
360     StringExtractorGDBRemote response;
361     packet.Printf ("QSyncThreadState:%4.4" PRIx64 ";", m_thread.GetProtocolID());
362     if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
363                                               packet.GetString().size(),
364                                               response,
365                                               false) == GDBRemoteCommunication::PacketResult::Success)
366     {
367         if (response.IsOKResponse())
368             InvalidateAllRegisters();
369     }
370 }
371 
372 bool
373 GDBRemoteRegisterContext::WriteRegisterBytes (const RegisterInfo *reg_info, DataExtractor &data, uint32_t data_offset)
374 {
375     ExecutionContext exe_ctx (CalculateThread());
376 
377     Process *process = exe_ctx.GetProcessPtr();
378     Thread *thread = exe_ctx.GetThreadPtr();
379     if (process == NULL || thread == NULL)
380         return false;
381 
382     GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
383 // FIXME: This check isn't right because IsRunning checks the Public state, but this
384 // is work you need to do - for instance in ShouldStop & friends - before the public
385 // state has been changed.
386 //    if (gdb_comm.IsRunning())
387 //        return false;
388 
389 
390 #if defined (LLDB_CONFIGURATION_DEBUG)
391     assert (m_reg_data.GetByteSize() >= reg_info->byte_offset + reg_info->byte_size);
392 #endif
393 
394     // If our register context and our register info disagree, which should never happen, don't
395     // overwrite past the end of the buffer.
396     if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
397         return false;
398 
399     // Grab a pointer to where we are going to put this register
400     uint8_t *dst = const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
401 
402     if (dst == NULL)
403         return false;
404 
405 
406     if (data.CopyByteOrderedData (data_offset,                  // src offset
407                                   reg_info->byte_size,          // src length
408                                   dst,                          // dst
409                                   reg_info->byte_size,          // dst length
410                                   m_reg_data.GetByteOrder()))   // dst byte order
411     {
412         std::unique_lock<std::recursive_mutex> lock;
413         if (gdb_comm.GetSequenceMutex(lock, "Didn't get sequence mutex for write register."))
414         {
415             const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
416             ProcessSP process_sp (m_thread.GetProcess());
417             if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
418             {
419                 StreamString packet;
420                 StringExtractorGDBRemote response;
421 
422                 if (m_read_all_at_once)
423                 {
424                     // Set all registers in one packet
425                     packet.PutChar ('G');
426                     packet.PutBytesAsRawHex8 (m_reg_data.GetDataStart(),
427                                               m_reg_data.GetByteSize(),
428                                               endian::InlHostByteOrder(),
429                                               endian::InlHostByteOrder());
430 
431                     if (thread_suffix_supported)
432                         packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
433 
434                     // Invalidate all register values
435                     InvalidateIfNeeded (true);
436 
437                     if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
438                                                               packet.GetString().size(),
439                                                               response,
440                                                               false) == GDBRemoteCommunication::PacketResult::Success)
441                     {
442                         SetAllRegisterValid (false);
443                         if (response.IsOKResponse())
444                         {
445                             return true;
446                         }
447                     }
448                 }
449                 else
450                 {
451                     bool success = true;
452 
453                     if (reg_info->value_regs)
454                     {
455                         // This register is part of another register. In this case we read the actual
456                         // register data for any "value_regs", and once all that data is read, we will
457                         // have enough data in our register context bytes for the value of this register
458 
459                         // Invalidate this composite register first.
460 
461                         for (uint32_t idx = 0; success; ++idx)
462                         {
463                             const uint32_t reg = reg_info->value_regs[idx];
464                             if (reg == LLDB_INVALID_REGNUM)
465                                 break;
466                             // We have a valid primordial register as our constituent.
467                             // Grab the corresponding register info.
468                             const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg);
469                             if (value_reg_info == NULL)
470                                 success = false;
471                             else
472                                 success = SetPrimordialRegister(value_reg_info, gdb_comm);
473                         }
474                     }
475                     else
476                     {
477                         // This is an actual register, write it
478                         success = SetPrimordialRegister(reg_info, gdb_comm);
479                     }
480 
481                     // Check if writing this register will invalidate any other register values?
482                     // If so, invalidate them
483                     if (reg_info->invalidate_regs)
484                     {
485                         for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0];
486                              reg != LLDB_INVALID_REGNUM;
487                              reg = reg_info->invalidate_regs[++idx])
488                         {
489                             SetRegisterIsValid(reg, false);
490                         }
491                     }
492 
493                     return success;
494                 }
495             }
496         }
497         else
498         {
499             Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
500             if (log)
501             {
502                 if (log->GetVerbose())
503                 {
504                     StreamString strm;
505                     gdb_comm.DumpHistory(strm);
506                     log->Printf("error: failed to get packet sequence mutex, not sending write register for \"%s\":\n%s", reg_info->name, strm.GetData());
507                 }
508                 else
509                     log->Printf("error: failed to get packet sequence mutex, not sending write register for \"%s\"", reg_info->name);
510             }
511         }
512     }
513     return false;
514 }
515 
516 bool
517 GDBRemoteRegisterContext::ReadAllRegisterValues (RegisterCheckpoint &reg_checkpoint)
518 {
519     ExecutionContext exe_ctx (CalculateThread());
520 
521     Process *process = exe_ctx.GetProcessPtr();
522     Thread *thread = exe_ctx.GetThreadPtr();
523     if (process == NULL || thread == NULL)
524         return false;
525 
526     GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
527 
528     uint32_t save_id = 0;
529     if (gdb_comm.SaveRegisterState(thread->GetProtocolID(), save_id))
530     {
531         reg_checkpoint.SetID(save_id);
532         reg_checkpoint.GetData().reset();
533         return true;
534     }
535     else
536     {
537         reg_checkpoint.SetID(0); // Invalid save ID is zero
538         return ReadAllRegisterValues(reg_checkpoint.GetData());
539     }
540 }
541 
542 bool
543 GDBRemoteRegisterContext::WriteAllRegisterValues (const RegisterCheckpoint &reg_checkpoint)
544 {
545     uint32_t save_id = reg_checkpoint.GetID();
546     if (save_id != 0)
547     {
548         ExecutionContext exe_ctx (CalculateThread());
549 
550         Process *process = exe_ctx.GetProcessPtr();
551         Thread *thread = exe_ctx.GetThreadPtr();
552         if (process == NULL || thread == NULL)
553             return false;
554 
555         GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
556 
557         return gdb_comm.RestoreRegisterState(m_thread.GetProtocolID(), save_id);
558     }
559     else
560     {
561         return WriteAllRegisterValues(reg_checkpoint.GetData());
562     }
563 }
564 
565 bool
566 GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
567 {
568     ExecutionContext exe_ctx (CalculateThread());
569 
570     Process *process = exe_ctx.GetProcessPtr();
571     Thread *thread = exe_ctx.GetThreadPtr();
572     if (process == NULL || thread == NULL)
573         return false;
574 
575     GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
576 
577     StringExtractorGDBRemote response;
578 
579     const bool use_g_packet = gdb_comm.AvoidGPackets ((ProcessGDBRemote *)process) == false;
580 
581     std::unique_lock<std::recursive_mutex> lock;
582     if (gdb_comm.GetSequenceMutex(lock, "Didn't get sequence mutex for read all registers."))
583     {
584         SyncThreadState(process);
585 
586         char packet[32];
587         const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
588         ProcessSP process_sp (m_thread.GetProcess());
589         if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
590         {
591             int packet_len = 0;
592             if (thread_suffix_supported)
593                 packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64, m_thread.GetProtocolID());
594             else
595                 packet_len = ::snprintf (packet, sizeof(packet), "g");
596             assert (packet_len < ((int)sizeof(packet) - 1));
597 
598             if (use_g_packet && gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false) == GDBRemoteCommunication::PacketResult::Success)
599             {
600                 int packet_len = 0;
601                 if (thread_suffix_supported)
602                     packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64, m_thread.GetProtocolID());
603                 else
604                     packet_len = ::snprintf (packet, sizeof(packet), "g");
605                 assert (packet_len < ((int)sizeof(packet) - 1));
606 
607                 if (gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false) == GDBRemoteCommunication::PacketResult::Success)
608                 {
609                     if (response.IsErrorResponse())
610                         return false;
611 
612                     std::string &response_str = response.GetStringRef();
613                     if (isxdigit(response_str[0]))
614                     {
615                         response_str.insert(0, 1, 'G');
616                         if (thread_suffix_supported)
617                         {
618                             char thread_id_cstr[64];
619                             ::snprintf (thread_id_cstr, sizeof(thread_id_cstr), ";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
620                             response_str.append (thread_id_cstr);
621                         }
622                         data_sp.reset (new DataBufferHeap (response_str.c_str(), response_str.size()));
623                         return true;
624                     }
625                 }
626             }
627             else
628             {
629                 // For the use_g_packet == false case, we're going to read each register
630                 // individually and store them as binary data in a buffer instead of as ascii
631                 // characters.
632                 const RegisterInfo *reg_info;
633 
634                 // data_sp will take ownership of this DataBufferHeap pointer soon.
635                 DataBufferSP reg_ctx(new DataBufferHeap(m_reg_info.GetRegisterDataByteSize(), 0));
636 
637                 for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex (i)) != NULL; i++)
638                 {
639                     if (reg_info->value_regs) // skip registers that are slices of real registers
640                         continue;
641                     ReadRegisterBytes (reg_info, m_reg_data);
642                     // ReadRegisterBytes saves the contents of the register in to the m_reg_data buffer
643                 }
644                 memcpy (reg_ctx->GetBytes(), m_reg_data.GetDataStart(), m_reg_info.GetRegisterDataByteSize());
645 
646                 data_sp = reg_ctx;
647                 return true;
648             }
649         }
650     }
651     else
652     {
653 
654         Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
655         if (log)
656         {
657             if (log->GetVerbose())
658             {
659                 StreamString strm;
660                 gdb_comm.DumpHistory(strm);
661                 log->Printf("error: failed to get packet sequence mutex, not sending read all registers:\n%s", strm.GetData());
662             }
663             else
664                 log->Printf("error: failed to get packet sequence mutex, not sending read all registers");
665         }
666     }
667 
668     data_sp.reset();
669     return false;
670 }
671 
672 bool
673 GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
674 {
675     if (!data_sp || data_sp->GetBytes() == NULL || data_sp->GetByteSize() == 0)
676         return false;
677 
678     ExecutionContext exe_ctx (CalculateThread());
679 
680     Process *process = exe_ctx.GetProcessPtr();
681     Thread *thread = exe_ctx.GetThreadPtr();
682     if (process == NULL || thread == NULL)
683         return false;
684 
685     GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
686 
687     const bool use_g_packet = gdb_comm.AvoidGPackets ((ProcessGDBRemote *)process) == false;
688 
689     StringExtractorGDBRemote response;
690     std::unique_lock<std::recursive_mutex> lock;
691     if (gdb_comm.GetSequenceMutex(lock, "Didn't get sequence mutex for write all registers."))
692     {
693         const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
694         ProcessSP process_sp (m_thread.GetProcess());
695         if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
696         {
697             // The data_sp contains the entire G response packet including the
698             // G, and if the thread suffix is supported, it has the thread suffix
699             // as well.
700             const char *G_packet = (const char *)data_sp->GetBytes();
701             size_t G_packet_len = data_sp->GetByteSize();
702             if (use_g_packet
703                 && gdb_comm.SendPacketAndWaitForResponse (G_packet,
704                                                           G_packet_len,
705                                                           response,
706                                                           false) == GDBRemoteCommunication::PacketResult::Success)
707             {
708                 // The data_sp contains the entire G response packet including the
709                 // G, and if the thread suffix is supported, it has the thread suffix
710                 // as well.
711                 const char *G_packet = (const char *)data_sp->GetBytes();
712                 size_t G_packet_len = data_sp->GetByteSize();
713                 if (gdb_comm.SendPacketAndWaitForResponse (G_packet,
714                                                            G_packet_len,
715                                                            response,
716                                                            false) == GDBRemoteCommunication::PacketResult::Success)
717                 {
718                     if (response.IsOKResponse())
719                         return true;
720                     else if (response.IsErrorResponse())
721                     {
722                         uint32_t num_restored = 0;
723                         // We need to manually go through all of the registers and
724                         // restore them manually
725 
726                         response.GetStringRef().assign (G_packet, G_packet_len);
727                         response.SetFilePos(1); // Skip the leading 'G'
728 
729                         // G_packet_len is hex-ascii characters plus prefix 'G' plus suffix thread specifier.
730                         // This means buffer will be a little more than 2x larger than necessary but we resize
731                         // it down once we've extracted all hex ascii chars from the packet.
732                         DataBufferHeap buffer (G_packet_len, 0);
733 
734                         const uint32_t bytes_extracted = response.GetHexBytes (buffer.GetBytes(),
735                                                                                buffer.GetByteSize(),
736                                                                                '\xcc');
737 
738                         DataExtractor restore_data (buffer.GetBytes(),
739                                                     buffer.GetByteSize(),
740                                                     m_reg_data.GetByteOrder(),
741                                                     m_reg_data.GetAddressByteSize());
742 
743                         if (bytes_extracted < restore_data.GetByteSize())
744                             restore_data.SetData(restore_data.GetDataStart(), bytes_extracted, m_reg_data.GetByteOrder());
745 
746                         const RegisterInfo *reg_info;
747 
748                         // The g packet contents may either include the slice registers (registers defined in
749                         // terms of other registers, e.g. eax is a subset of rax) or not.  The slice registers
750                         // should NOT be in the g packet, but some implementations may incorrectly include them.
751                         //
752                         // If the slice registers are included in the packet, we must step over the slice registers
753                         // when parsing the packet -- relying on the RegisterInfo byte_offset field would be incorrect.
754                         // If the slice registers are not included, then using the byte_offset values into the
755                         // data buffer is the best way to find individual register values.
756 
757                         uint64_t size_including_slice_registers = 0;
758                         uint64_t size_not_including_slice_registers = 0;
759                         uint64_t size_by_highest_offset = 0;
760 
761                         for (uint32_t reg_idx=0; (reg_info = GetRegisterInfoAtIndex (reg_idx)) != NULL; ++reg_idx)
762                         {
763                             size_including_slice_registers += reg_info->byte_size;
764                             if (reg_info->value_regs == NULL)
765                                 size_not_including_slice_registers += reg_info->byte_size;
766                             if (reg_info->byte_offset >= size_by_highest_offset)
767                                 size_by_highest_offset = reg_info->byte_offset + reg_info->byte_size;
768                         }
769 
770                         bool use_byte_offset_into_buffer;
771                         if (size_by_highest_offset == restore_data.GetByteSize())
772                         {
773                             // The size of the packet agrees with the highest offset: + size in the register file
774                             use_byte_offset_into_buffer = true;
775                         }
776                         else if (size_not_including_slice_registers == restore_data.GetByteSize())
777                         {
778                             // The size of the packet is the same as concatenating all of the registers sequentially,
779                             // skipping the slice registers
780                             use_byte_offset_into_buffer = true;
781                         }
782                         else if (size_including_slice_registers == restore_data.GetByteSize())
783                         {
784                             // The slice registers are present in the packet (when they shouldn't be).
785                             // Don't try to use the RegisterInfo byte_offset into the restore_data, it will
786                             // point to the wrong place.
787                             use_byte_offset_into_buffer = false;
788                         }
789                         else {
790                             // None of our expected sizes match the actual g packet data we're looking at.
791                             // The most conservative approach here is to use the running total byte offset.
792                             use_byte_offset_into_buffer = false;
793                         }
794 
795                         // In case our register definitions don't include the correct offsets,
796                         // keep track of the size of each reg & compute offset based on that.
797                         uint32_t running_byte_offset = 0;
798                         for (uint32_t reg_idx=0; (reg_info = GetRegisterInfoAtIndex (reg_idx)) != NULL; ++reg_idx, running_byte_offset += reg_info->byte_size)
799                         {
800                             // Skip composite aka slice registers (e.g. eax is a slice of rax).
801                             if (reg_info->value_regs)
802                                 continue;
803 
804                             const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
805 
806                             uint32_t register_offset;
807                             if (use_byte_offset_into_buffer)
808                             {
809                                 register_offset = reg_info->byte_offset;
810                             }
811                             else
812                             {
813                                 register_offset = running_byte_offset;
814                             }
815 
816                             // Only write down the registers that need to be written
817                             // if we are going to be doing registers individually.
818                             bool write_reg = true;
819                             const uint32_t reg_byte_size = reg_info->byte_size;
820 
821                             const char *restore_src = (const char *)restore_data.PeekData(register_offset, reg_byte_size);
822                             if (restore_src)
823                             {
824                                 StreamString packet;
825                                 packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]);
826                                 packet.PutBytesAsRawHex8 (restore_src,
827                                                           reg_byte_size,
828                                                           endian::InlHostByteOrder(),
829                                                           endian::InlHostByteOrder());
830 
831                                 if (thread_suffix_supported)
832                                     packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
833 
834                                 SetRegisterIsValid(reg, false);
835                                 if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
836                                                                           packet.GetString().size(),
837                                                                           response,
838                                                                           false) == GDBRemoteCommunication::PacketResult::Success)
839                                 {
840                                     const char *current_src = (const char *)m_reg_data.PeekData(register_offset, reg_byte_size);
841                                     if (current_src)
842                                         write_reg = memcmp (current_src, restore_src, reg_byte_size) != 0;
843                                 }
844 
845                                 if (write_reg)
846                                 {
847                                     StreamString packet;
848                                     packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]);
849                                     packet.PutBytesAsRawHex8 (restore_src,
850                                                               reg_byte_size,
851                                                               endian::InlHostByteOrder(),
852                                                               endian::InlHostByteOrder());
853 
854                                     if (thread_suffix_supported)
855                                         packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
856 
857                                     SetRegisterIsValid(reg, false);
858                                     if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
859                                                                               packet.GetString().size(),
860                                                                               response,
861                                                                               false) == GDBRemoteCommunication::PacketResult::Success)
862                                     {
863                                         if (response.IsOKResponse())
864                                             ++num_restored;
865                                     }
866                                 }
867                             }
868                         }
869                         return num_restored > 0;
870                     }
871                 }
872             }
873             else
874             {
875                 // For the use_g_packet == false case, we're going to write each register
876                 // individually.  The data buffer is binary data in this case, instead of
877                 // ascii characters.
878 
879                 bool arm64_debugserver = false;
880                 if (m_thread.GetProcess().get())
881                 {
882                     const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture();
883                     if (arch.IsValid()
884                         && arch.GetMachine() == llvm::Triple::aarch64
885                         && arch.GetTriple().getVendor() == llvm::Triple::Apple
886                         && arch.GetTriple().getOS() == llvm::Triple::IOS)
887                     {
888                         arm64_debugserver = true;
889                     }
890                 }
891                 uint32_t num_restored = 0;
892                 const RegisterInfo *reg_info;
893                 for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex (i)) != NULL; i++)
894                 {
895                     if (reg_info->value_regs) // skip registers that are slices of real registers
896                         continue;
897                     // Skip the fpsr and fpcr floating point status/control register writing to
898                     // work around a bug in an older version of debugserver that would lead to
899                     // register context corruption when writing fpsr/fpcr.
900                     if (arm64_debugserver &&
901                         (strcmp (reg_info->name, "fpsr") == 0 || strcmp (reg_info->name, "fpcr") == 0))
902                     {
903                         continue;
904                     }
905                     StreamString packet;
906                     packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]);
907                     packet.PutBytesAsRawHex8 (data_sp->GetBytes() + reg_info->byte_offset, reg_info->byte_size, endian::InlHostByteOrder(), endian::InlHostByteOrder());
908                     if (thread_suffix_supported)
909                         packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
910 
911                     SetRegisterIsValid(reg_info, false);
912                     if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
913                                                               packet.GetString().size(),
914                                                               response,
915                                                               false) == GDBRemoteCommunication::PacketResult::Success)
916                     {
917                         if (response.IsOKResponse())
918                             ++num_restored;
919                     }
920                 }
921                 return num_restored > 0;
922             }
923         }
924     }
925     else
926     {
927         Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
928         if (log)
929         {
930             if (log->GetVerbose())
931             {
932                 StreamString strm;
933                 gdb_comm.DumpHistory(strm);
934                 log->Printf("error: failed to get packet sequence mutex, not sending write all registers:\n%s", strm.GetData());
935             }
936             else
937                 log->Printf("error: failed to get packet sequence mutex, not sending write all registers");
938         }
939     }
940     return false;
941 }
942 
943 
944 uint32_t
945 GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num)
946 {
947     return m_reg_info.ConvertRegisterKindToRegisterNumber (kind, num);
948 }
949 
950 
951 void
952 GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch)
953 {
954     // For Advanced SIMD and VFP register mapping.
955     static uint32_t g_d0_regs[] =  { 26, 27, LLDB_INVALID_REGNUM }; // (s0, s1)
956     static uint32_t g_d1_regs[] =  { 28, 29, LLDB_INVALID_REGNUM }; // (s2, s3)
957     static uint32_t g_d2_regs[] =  { 30, 31, LLDB_INVALID_REGNUM }; // (s4, s5)
958     static uint32_t g_d3_regs[] =  { 32, 33, LLDB_INVALID_REGNUM }; // (s6, s7)
959     static uint32_t g_d4_regs[] =  { 34, 35, LLDB_INVALID_REGNUM }; // (s8, s9)
960     static uint32_t g_d5_regs[] =  { 36, 37, LLDB_INVALID_REGNUM }; // (s10, s11)
961     static uint32_t g_d6_regs[] =  { 38, 39, LLDB_INVALID_REGNUM }; // (s12, s13)
962     static uint32_t g_d7_regs[] =  { 40, 41, LLDB_INVALID_REGNUM }; // (s14, s15)
963     static uint32_t g_d8_regs[] =  { 42, 43, LLDB_INVALID_REGNUM }; // (s16, s17)
964     static uint32_t g_d9_regs[] =  { 44, 45, LLDB_INVALID_REGNUM }; // (s18, s19)
965     static uint32_t g_d10_regs[] = { 46, 47, LLDB_INVALID_REGNUM }; // (s20, s21)
966     static uint32_t g_d11_regs[] = { 48, 49, LLDB_INVALID_REGNUM }; // (s22, s23)
967     static uint32_t g_d12_regs[] = { 50, 51, LLDB_INVALID_REGNUM }; // (s24, s25)
968     static uint32_t g_d13_regs[] = { 52, 53, LLDB_INVALID_REGNUM }; // (s26, s27)
969     static uint32_t g_d14_regs[] = { 54, 55, LLDB_INVALID_REGNUM }; // (s28, s29)
970     static uint32_t g_d15_regs[] = { 56, 57, LLDB_INVALID_REGNUM }; // (s30, s31)
971     static uint32_t g_q0_regs[] =  { 26, 27, 28, 29, LLDB_INVALID_REGNUM }; // (d0, d1) -> (s0, s1, s2, s3)
972     static uint32_t g_q1_regs[] =  { 30, 31, 32, 33, LLDB_INVALID_REGNUM }; // (d2, d3) -> (s4, s5, s6, s7)
973     static uint32_t g_q2_regs[] =  { 34, 35, 36, 37, LLDB_INVALID_REGNUM }; // (d4, d5) -> (s8, s9, s10, s11)
974     static uint32_t g_q3_regs[] =  { 38, 39, 40, 41, LLDB_INVALID_REGNUM }; // (d6, d7) -> (s12, s13, s14, s15)
975     static uint32_t g_q4_regs[] =  { 42, 43, 44, 45, LLDB_INVALID_REGNUM }; // (d8, d9) -> (s16, s17, s18, s19)
976     static uint32_t g_q5_regs[] =  { 46, 47, 48, 49, LLDB_INVALID_REGNUM }; // (d10, d11) -> (s20, s21, s22, s23)
977     static uint32_t g_q6_regs[] =  { 50, 51, 52, 53, LLDB_INVALID_REGNUM }; // (d12, d13) -> (s24, s25, s26, s27)
978     static uint32_t g_q7_regs[] =  { 54, 55, 56, 57, LLDB_INVALID_REGNUM }; // (d14, d15) -> (s28, s29, s30, s31)
979     static uint32_t g_q8_regs[] =  { 59, 60, LLDB_INVALID_REGNUM }; // (d16, d17)
980     static uint32_t g_q9_regs[] =  { 61, 62, LLDB_INVALID_REGNUM }; // (d18, d19)
981     static uint32_t g_q10_regs[] = { 63, 64, LLDB_INVALID_REGNUM }; // (d20, d21)
982     static uint32_t g_q11_regs[] = { 65, 66, LLDB_INVALID_REGNUM }; // (d22, d23)
983     static uint32_t g_q12_regs[] = { 67, 68, LLDB_INVALID_REGNUM }; // (d24, d25)
984     static uint32_t g_q13_regs[] = { 69, 70, LLDB_INVALID_REGNUM }; // (d26, d27)
985     static uint32_t g_q14_regs[] = { 71, 72, LLDB_INVALID_REGNUM }; // (d28, d29)
986     static uint32_t g_q15_regs[] = { 73, 74, LLDB_INVALID_REGNUM }; // (d30, d31)
987 
988     // This is our array of composite registers, with each element coming from the above register mappings.
989     static uint32_t *g_composites[] = {
990         g_d0_regs, g_d1_regs,  g_d2_regs,  g_d3_regs,  g_d4_regs,  g_d5_regs,  g_d6_regs,  g_d7_regs,
991         g_d8_regs, g_d9_regs, g_d10_regs, g_d11_regs, g_d12_regs, g_d13_regs, g_d14_regs, g_d15_regs,
992         g_q0_regs, g_q1_regs,  g_q2_regs,  g_q3_regs,  g_q4_regs,  g_q5_regs,  g_q6_regs,  g_q7_regs,
993         g_q8_regs, g_q9_regs, g_q10_regs, g_q11_regs, g_q12_regs, g_q13_regs, g_q14_regs, g_q15_regs
994     };
995 
996     static RegisterInfo g_register_infos[] = {
997 //   NAME    ALT    SZ  OFF  ENCODING          FORMAT          EH_FRAME             DWARF                GENERIC                 PROCESS PLUGIN  LLDB      VALUE REGS    INVALIDATE REGS
998 //   ======  ====== === ===  =============     ============    ===================  ===================  ======================  =============   ====      ==========    ===============
999     { "r0", "arg1",   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r0,          dwarf_r0,            LLDB_REGNUM_GENERIC_ARG1,0,               0 },        NULL,              NULL},
1000     { "r1", "arg2",   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r1,          dwarf_r1,            LLDB_REGNUM_GENERIC_ARG2,1,               1 },        NULL,              NULL},
1001     { "r2", "arg3",   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r2,          dwarf_r2,            LLDB_REGNUM_GENERIC_ARG3,2,               2 },        NULL,              NULL},
1002     { "r3", "arg4",   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r3,          dwarf_r3,            LLDB_REGNUM_GENERIC_ARG4,3,               3 },        NULL,              NULL},
1003     { "r4",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r4,          dwarf_r4,            LLDB_INVALID_REGNUM,     4,               4 },        NULL,              NULL},
1004     { "r5",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r5,          dwarf_r5,            LLDB_INVALID_REGNUM,     5,               5 },        NULL,              NULL},
1005     { "r6",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r6,          dwarf_r6,            LLDB_INVALID_REGNUM,     6,               6 },        NULL,              NULL},
1006     { "r7",   "fp",   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r7,          dwarf_r7,            LLDB_REGNUM_GENERIC_FP,  7,               7 },        NULL,              NULL},
1007     { "r8",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r8,          dwarf_r8,            LLDB_INVALID_REGNUM,     8,               8 },        NULL,              NULL},
1008     { "r9",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r9,          dwarf_r9,            LLDB_INVALID_REGNUM,     9,               9 },        NULL,              NULL},
1009     { "r10",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r10,         dwarf_r10,           LLDB_INVALID_REGNUM,    10,              10 },        NULL,              NULL},
1010     { "r11",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r11,         dwarf_r11,           LLDB_INVALID_REGNUM,    11,              11 },        NULL,              NULL},
1011     { "r12",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r12,         dwarf_r12,           LLDB_INVALID_REGNUM,    12,              12 },        NULL,              NULL},
1012     { "sp",   "r13",  4,   0, eEncodingUint,    eFormatHex,   { ehframe_sp,          dwarf_sp,            LLDB_REGNUM_GENERIC_SP, 13,              13 },        NULL,              NULL},
1013     { "lr",   "r14",  4,   0, eEncodingUint,    eFormatHex,   { ehframe_lr,          dwarf_lr,            LLDB_REGNUM_GENERIC_RA, 14,              14 },        NULL,              NULL},
1014     { "pc",   "r15",  4,   0, eEncodingUint,    eFormatHex,   { ehframe_pc,          dwarf_pc,            LLDB_REGNUM_GENERIC_PC, 15,              15 },        NULL,              NULL},
1015     { "f0",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    16,              16 },        NULL,              NULL},
1016     { "f1",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    17,              17 },        NULL,              NULL},
1017     { "f2",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    18,              18 },        NULL,              NULL},
1018     { "f3",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    19,              19 },        NULL,              NULL},
1019     { "f4",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    20,              20 },        NULL,              NULL},
1020     { "f5",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    21,              21 },        NULL,              NULL},
1021     { "f6",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    22,              22 },        NULL,              NULL},
1022     { "f7",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    23,              23 },        NULL,              NULL},
1023     { "fps",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    24,              24 },        NULL,              NULL},
1024     { "cpsr","flags", 4,   0, eEncodingUint,    eFormatHex,   { ehframe_cpsr,        dwarf_cpsr,          LLDB_INVALID_REGNUM,    25,              25 },        NULL,              NULL},
1025     { "s0",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0,            LLDB_INVALID_REGNUM,    26,              26 },        NULL,              NULL},
1026     { "s1",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1,            LLDB_INVALID_REGNUM,    27,              27 },        NULL,              NULL},
1027     { "s2",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2,            LLDB_INVALID_REGNUM,    28,              28 },        NULL,              NULL},
1028     { "s3",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3,            LLDB_INVALID_REGNUM,    29,              29 },        NULL,              NULL},
1029     { "s4",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4,            LLDB_INVALID_REGNUM,    30,              30 },        NULL,              NULL},
1030     { "s5",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5,            LLDB_INVALID_REGNUM,    31,              31 },        NULL,              NULL},
1031     { "s6",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6,            LLDB_INVALID_REGNUM,    32,              32 },        NULL,              NULL},
1032     { "s7",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7,            LLDB_INVALID_REGNUM,    33,              33 },        NULL,              NULL},
1033     { "s8",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8,            LLDB_INVALID_REGNUM,    34,              34 },        NULL,              NULL},
1034     { "s9",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9,            LLDB_INVALID_REGNUM,    35,              35 },        NULL,              NULL},
1035     { "s10",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10,           LLDB_INVALID_REGNUM,    36,              36 },        NULL,              NULL},
1036     { "s11",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11,           LLDB_INVALID_REGNUM,    37,              37 },        NULL,              NULL},
1037     { "s12",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12,           LLDB_INVALID_REGNUM,    38,              38 },        NULL,              NULL},
1038     { "s13",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13,           LLDB_INVALID_REGNUM,    39,              39 },        NULL,              NULL},
1039     { "s14",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14,           LLDB_INVALID_REGNUM,    40,              40 },        NULL,              NULL},
1040     { "s15",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15,           LLDB_INVALID_REGNUM,    41,              41 },        NULL,              NULL},
1041     { "s16",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16,           LLDB_INVALID_REGNUM,    42,              42 },        NULL,              NULL},
1042     { "s17",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17,           LLDB_INVALID_REGNUM,    43,              43 },        NULL,              NULL},
1043     { "s18",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18,           LLDB_INVALID_REGNUM,    44,              44 },        NULL,              NULL},
1044     { "s19",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19,           LLDB_INVALID_REGNUM,    45,              45 },        NULL,              NULL},
1045     { "s20",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20,           LLDB_INVALID_REGNUM,    46,              46 },        NULL,              NULL},
1046     { "s21",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21,           LLDB_INVALID_REGNUM,    47,              47 },        NULL,              NULL},
1047     { "s22",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22,           LLDB_INVALID_REGNUM,    48,              48 },        NULL,              NULL},
1048     { "s23",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23,           LLDB_INVALID_REGNUM,    49,              49 },        NULL,              NULL},
1049     { "s24",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24,           LLDB_INVALID_REGNUM,    50,              50 },        NULL,              NULL},
1050     { "s25",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25,           LLDB_INVALID_REGNUM,    51,              51 },        NULL,              NULL},
1051     { "s26",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26,           LLDB_INVALID_REGNUM,    52,              52 },        NULL,              NULL},
1052     { "s27",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27,           LLDB_INVALID_REGNUM,    53,              53 },        NULL,              NULL},
1053     { "s28",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28,           LLDB_INVALID_REGNUM,    54,              54 },        NULL,              NULL},
1054     { "s29",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29,           LLDB_INVALID_REGNUM,    55,              55 },        NULL,              NULL},
1055     { "s30",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30,           LLDB_INVALID_REGNUM,    56,              56 },        NULL,              NULL},
1056     { "s31",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31,           LLDB_INVALID_REGNUM,    57,              57 },        NULL,              NULL},
1057     { "fpscr",NULL,   4,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    58,              58 },        NULL,              NULL},
1058     { "d16",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16,           LLDB_INVALID_REGNUM,    59,              59 },        NULL,              NULL},
1059     { "d17",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17,           LLDB_INVALID_REGNUM,    60,              60 },        NULL,              NULL},
1060     { "d18",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18,           LLDB_INVALID_REGNUM,    61,              61 },        NULL,              NULL},
1061     { "d19",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19,           LLDB_INVALID_REGNUM,    62,              62 },        NULL,              NULL},
1062     { "d20",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20,           LLDB_INVALID_REGNUM,    63,              63 },        NULL,              NULL},
1063     { "d21",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21,           LLDB_INVALID_REGNUM,    64,              64 },        NULL,              NULL},
1064     { "d22",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22,           LLDB_INVALID_REGNUM,    65,              65 },        NULL,              NULL},
1065     { "d23",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23,           LLDB_INVALID_REGNUM,    66,              66 },        NULL,              NULL},
1066     { "d24",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24,           LLDB_INVALID_REGNUM,    67,              67 },        NULL,              NULL},
1067     { "d25",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25,           LLDB_INVALID_REGNUM,    68,              68 },        NULL,              NULL},
1068     { "d26",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26,           LLDB_INVALID_REGNUM,    69,              69 },        NULL,              NULL},
1069     { "d27",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27,           LLDB_INVALID_REGNUM,    70,              70 },        NULL,              NULL},
1070     { "d28",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28,           LLDB_INVALID_REGNUM,    71,              71 },        NULL,              NULL},
1071     { "d29",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29,           LLDB_INVALID_REGNUM,    72,              72 },        NULL,              NULL},
1072     { "d30",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30,           LLDB_INVALID_REGNUM,    73,              73 },        NULL,              NULL},
1073     { "d31",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31,           LLDB_INVALID_REGNUM,    74,              74 },        NULL,              NULL},
1074     { "d0",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0,            LLDB_INVALID_REGNUM,    75,              75 },   g_d0_regs,              NULL},
1075     { "d1",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1,            LLDB_INVALID_REGNUM,    76,              76 },   g_d1_regs,              NULL},
1076     { "d2",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2,            LLDB_INVALID_REGNUM,    77,              77 },   g_d2_regs,              NULL},
1077     { "d3",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3,            LLDB_INVALID_REGNUM,    78,              78 },   g_d3_regs,              NULL},
1078     { "d4",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4,            LLDB_INVALID_REGNUM,    79,              79 },   g_d4_regs,              NULL},
1079     { "d5",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5,            LLDB_INVALID_REGNUM,    80,              80 },   g_d5_regs,              NULL},
1080     { "d6",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6,            LLDB_INVALID_REGNUM,    81,              81 },   g_d6_regs,              NULL},
1081     { "d7",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7,            LLDB_INVALID_REGNUM,    82,              82 },   g_d7_regs,              NULL},
1082     { "d8",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8,            LLDB_INVALID_REGNUM,    83,              83 },   g_d8_regs,              NULL},
1083     { "d9",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9,            LLDB_INVALID_REGNUM,    84,              84 },   g_d9_regs,              NULL},
1084     { "d10",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10,           LLDB_INVALID_REGNUM,    85,              85 },  g_d10_regs,              NULL},
1085     { "d11",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11,           LLDB_INVALID_REGNUM,    86,              86 },  g_d11_regs,              NULL},
1086     { "d12",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12,           LLDB_INVALID_REGNUM,    87,              87 },  g_d12_regs,              NULL},
1087     { "d13",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13,           LLDB_INVALID_REGNUM,    88,              88 },  g_d13_regs,              NULL},
1088     { "d14",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14,           LLDB_INVALID_REGNUM,    89,              89 },  g_d14_regs,              NULL},
1089     { "d15",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15,           LLDB_INVALID_REGNUM,    90,              90 },  g_d15_regs,              NULL},
1090     { "q0",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0,    LLDB_INVALID_REGNUM,    91,              91 },   g_q0_regs,              NULL},
1091     { "q1",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1,    LLDB_INVALID_REGNUM,    92,              92 },   g_q1_regs,              NULL},
1092     { "q2",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2,    LLDB_INVALID_REGNUM,    93,              93 },   g_q2_regs,              NULL},
1093     { "q3",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3,    LLDB_INVALID_REGNUM,    94,              94 },   g_q3_regs,              NULL},
1094     { "q4",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4,    LLDB_INVALID_REGNUM,    95,              95 },   g_q4_regs,              NULL},
1095     { "q5",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5,    LLDB_INVALID_REGNUM,    96,              96 },   g_q5_regs,              NULL},
1096     { "q6",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6,    LLDB_INVALID_REGNUM,    97,              97 },   g_q6_regs,              NULL},
1097     { "q7",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7,    LLDB_INVALID_REGNUM,    98,              98 },   g_q7_regs,              NULL},
1098     { "q8",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8,    LLDB_INVALID_REGNUM,    99,              99 },   g_q8_regs,              NULL},
1099     { "q9",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9,    LLDB_INVALID_REGNUM,   100,             100 },   g_q9_regs,              NULL},
1100     { "q10",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10,   LLDB_INVALID_REGNUM,   101,             101 },  g_q10_regs,              NULL},
1101     { "q11",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11,   LLDB_INVALID_REGNUM,   102,             102 },  g_q11_regs,              NULL},
1102     { "q12",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12,   LLDB_INVALID_REGNUM,   103,             103 },  g_q12_regs,              NULL},
1103     { "q13",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13,   LLDB_INVALID_REGNUM,   104,             104 },  g_q13_regs,              NULL},
1104     { "q14",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14,   LLDB_INVALID_REGNUM,   105,             105 },  g_q14_regs,              NULL},
1105     { "q15",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15,   LLDB_INVALID_REGNUM,   106,             106 },  g_q15_regs,              NULL}
1106     };
1107 
1108     static const uint32_t num_registers = llvm::array_lengthof(g_register_infos);
1109     static ConstString gpr_reg_set ("General Purpose Registers");
1110     static ConstString sfp_reg_set ("Software Floating Point Registers");
1111     static ConstString vfp_reg_set ("Floating Point Registers");
1112     size_t i;
1113     if (from_scratch)
1114     {
1115         // Calculate the offsets of the registers
1116         // Note that the layout of the "composite" registers (d0-d15 and q0-q15) which comes after the
1117         // "primordial" registers is important.  This enables us to calculate the offset of the composite
1118         // register by using the offset of its first primordial register.  For example, to calculate the
1119         // offset of q0, use s0's offset.
1120         if (g_register_infos[2].byte_offset == 0)
1121         {
1122             uint32_t byte_offset = 0;
1123             for (i=0; i<num_registers; ++i)
1124             {
1125                 // For primordial registers, increment the byte_offset by the byte_size to arrive at the
1126                 // byte_offset for the next register.  Otherwise, we have a composite register whose
1127                 // offset can be calculated by consulting the offset of its first primordial register.
1128                 if (!g_register_infos[i].value_regs)
1129                 {
1130                     g_register_infos[i].byte_offset = byte_offset;
1131                     byte_offset += g_register_infos[i].byte_size;
1132                 }
1133                 else
1134                 {
1135                     const uint32_t first_primordial_reg = g_register_infos[i].value_regs[0];
1136                     g_register_infos[i].byte_offset = g_register_infos[first_primordial_reg].byte_offset;
1137                 }
1138             }
1139         }
1140         for (i=0; i<num_registers; ++i)
1141         {
1142             ConstString name;
1143             ConstString alt_name;
1144             if (g_register_infos[i].name && g_register_infos[i].name[0])
1145                 name.SetCString(g_register_infos[i].name);
1146             if (g_register_infos[i].alt_name && g_register_infos[i].alt_name[0])
1147                 alt_name.SetCString(g_register_infos[i].alt_name);
1148 
1149             if (i <= 15 || i == 25)
1150                 AddRegister (g_register_infos[i], name, alt_name, gpr_reg_set);
1151             else if (i <= 24)
1152                 AddRegister (g_register_infos[i], name, alt_name, sfp_reg_set);
1153             else
1154                 AddRegister (g_register_infos[i], name, alt_name, vfp_reg_set);
1155         }
1156     }
1157     else
1158     {
1159         // Add composite registers to our primordial registers, then.
1160         const size_t num_composites = llvm::array_lengthof(g_composites);
1161         const size_t num_dynamic_regs = GetNumRegisters();
1162         const size_t num_common_regs = num_registers - num_composites;
1163         RegisterInfo *g_comp_register_infos = g_register_infos + num_common_regs;
1164 
1165         // First we need to validate that all registers that we already have match the non composite regs.
1166         // If so, then we can add the registers, else we need to bail
1167         bool match = true;
1168         if (num_dynamic_regs == num_common_regs)
1169         {
1170             for (i=0; match && i<num_dynamic_regs; ++i)
1171             {
1172                 // Make sure all register names match
1173                 if (m_regs[i].name && g_register_infos[i].name)
1174                 {
1175                     if (strcmp(m_regs[i].name, g_register_infos[i].name))
1176                     {
1177                         match = false;
1178                         break;
1179                     }
1180                 }
1181 
1182                 // Make sure all register byte sizes match
1183                 if (m_regs[i].byte_size != g_register_infos[i].byte_size)
1184                 {
1185                     match = false;
1186                     break;
1187                 }
1188             }
1189         }
1190         else
1191         {
1192             // Wrong number of registers.
1193             match = false;
1194         }
1195         // If "match" is true, then we can add extra registers.
1196         if (match)
1197         {
1198             for (i=0; i<num_composites; ++i)
1199             {
1200                 ConstString name;
1201                 ConstString alt_name;
1202                 const uint32_t first_primordial_reg = g_comp_register_infos[i].value_regs[0];
1203                 const char *reg_name = g_register_infos[first_primordial_reg].name;
1204                 if (reg_name && reg_name[0])
1205                 {
1206                     for (uint32_t j = 0; j < num_dynamic_regs; ++j)
1207                     {
1208                         const RegisterInfo *reg_info = GetRegisterInfoAtIndex(j);
1209                         // Find a matching primordial register info entry.
1210                         if (reg_info && reg_info->name && ::strcasecmp(reg_info->name, reg_name) == 0)
1211                         {
1212                             // The name matches the existing primordial entry.
1213                             // Find and assign the offset, and then add this composite register entry.
1214                             g_comp_register_infos[i].byte_offset = reg_info->byte_offset;
1215                             name.SetCString(g_comp_register_infos[i].name);
1216                             AddRegister(g_comp_register_infos[i], name, alt_name, vfp_reg_set);
1217                         }
1218                     }
1219                 }
1220             }
1221         }
1222     }
1223 }
1224