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/Scalar.h"
18 #include "lldb/Core/StreamString.h"
19 // Project includes
20 #include "Utility/StringExtractorGDBRemote.h"
21 #include "ProcessGDBRemote.h"
22 #include "ThreadGDBRemote.h"
23 #include "Utility/ARM_GCC_Registers.h"
24 #include "Utility/ARM_DWARF_Registers.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 //----------------------------------------------------------------------
30 // GDBRemoteRegisterContext constructor
31 //----------------------------------------------------------------------
32 GDBRemoteRegisterContext::GDBRemoteRegisterContext
33 (
34     ThreadGDBRemote &thread,
35     uint32_t concrete_frame_idx,
36     GDBRemoteDynamicRegisterInfo &reg_info,
37     bool read_all_at_once
38 ) :
39     RegisterContext (thread, concrete_frame_idx),
40     m_reg_info (reg_info),
41     m_reg_valid (),
42     m_reg_data (),
43     m_read_all_at_once (read_all_at_once)
44 {
45     // Resize our vector of bools to contain one bool for every register.
46     // We will use these boolean values to know when a register value
47     // is valid in m_reg_data.
48     m_reg_valid.resize (reg_info.GetNumRegisters());
49 
50     // Make a heap based buffer that is big enough to store all registers
51     DataBufferSP reg_data_sp(new DataBufferHeap (reg_info.GetRegisterDataByteSize(), 0));
52     m_reg_data.SetData (reg_data_sp);
53 
54 }
55 
56 //----------------------------------------------------------------------
57 // Destructor
58 //----------------------------------------------------------------------
59 GDBRemoteRegisterContext::~GDBRemoteRegisterContext()
60 {
61 }
62 
63 ProcessGDBRemote &
64 GDBRemoteRegisterContext::GetGDBProcess()
65 {
66     return static_cast<ProcessGDBRemote &>(m_thread.GetProcess());
67 }
68 
69 ThreadGDBRemote &
70 GDBRemoteRegisterContext::GetGDBThread()
71 {
72     return static_cast<ThreadGDBRemote &>(m_thread);
73 }
74 
75 void
76 GDBRemoteRegisterContext::InvalidateAllRegisters ()
77 {
78     SetAllRegisterValid (false);
79 }
80 
81 void
82 GDBRemoteRegisterContext::SetAllRegisterValid (bool b)
83 {
84     std::vector<bool>::iterator pos, end = m_reg_valid.end();
85     for (pos = m_reg_valid.begin(); pos != end; ++pos)
86         *pos = b;
87 }
88 
89 size_t
90 GDBRemoteRegisterContext::GetRegisterCount ()
91 {
92     return m_reg_info.GetNumRegisters ();
93 }
94 
95 const RegisterInfo *
96 GDBRemoteRegisterContext::GetRegisterInfoAtIndex (uint32_t reg)
97 {
98     return m_reg_info.GetRegisterInfoAtIndex (reg);
99 }
100 
101 size_t
102 GDBRemoteRegisterContext::GetRegisterSetCount ()
103 {
104     return m_reg_info.GetNumRegisterSets ();
105 }
106 
107 
108 
109 const RegisterSet *
110 GDBRemoteRegisterContext::GetRegisterSet (uint32_t reg_set)
111 {
112     return m_reg_info.GetRegisterSet (reg_set);
113 }
114 
115 
116 
117 bool
118 GDBRemoteRegisterContext::ReadRegisterValue (uint32_t reg, Scalar &value)
119 {
120     // Read the register
121     if (ReadRegisterBytes (reg, m_reg_data))
122     {
123         const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
124         uint32_t offset = reg_info->byte_offset;
125         switch (reg_info->encoding)
126         {
127         case eEncodingUint:
128             switch (reg_info->byte_size)
129             {
130             case 1:
131             case 2:
132             case 4:
133                 value = m_reg_data.GetMaxU32 (&offset, reg_info->byte_size);
134                 return true;
135 
136             case 8:
137                 value = m_reg_data.GetMaxU64 (&offset, reg_info->byte_size);
138                 return true;
139             }
140             break;
141 
142         case eEncodingSint:
143             switch (reg_info->byte_size)
144             {
145             case 1:
146             case 2:
147             case 4:
148                 value = (int32_t)m_reg_data.GetMaxU32 (&offset, reg_info->byte_size);
149                 return true;
150 
151             case 8:
152                 value = m_reg_data.GetMaxS64 (&offset, reg_info->byte_size);
153                 return true;
154             }
155             break;
156 
157         case eEncodingIEEE754:
158             switch (reg_info->byte_size)
159             {
160             case sizeof (float):
161                 value = m_reg_data.GetFloat (&offset);
162                 return true;
163 
164             case sizeof (double):
165                 value = m_reg_data.GetDouble (&offset);
166                 return true;
167 
168             case sizeof (long double):
169                 value = m_reg_data.GetLongDouble (&offset);
170                 return true;
171             }
172             break;
173 
174         default:
175             break;
176         }
177     }
178     return false;
179 }
180 
181 bool
182 GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, StringExtractor &response)
183 {
184     const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
185     if (reg_info == NULL)
186         return false;
187 
188     // Invalidate if needed
189     InvalidateIfNeeded(false);
190 
191     const uint32_t reg_byte_size = reg_info->byte_size;
192     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');
193     bool success = bytes_copied == reg_byte_size;
194     if (success)
195     {
196         m_reg_valid[reg] = true;
197     }
198     else if (bytes_copied > 0)
199     {
200         // Only set register is valid to false if we copied some bytes, else
201         // leave it as it was.
202         m_reg_valid[reg] = false;
203     }
204     return success;
205 }
206 
207 
208 bool
209 GDBRemoteRegisterContext::ReadRegisterBytes (uint32_t reg, DataExtractor &data)
210 {
211     GDBRemoteCommunicationClient &gdb_comm (GetGDBProcess().GetGDBRemote());
212 
213     InvalidateIfNeeded(false);
214 
215     const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
216     assert (reg_info);
217     if (!m_reg_valid[reg])
218     {
219         Mutex::Locker locker;
220         if (gdb_comm.GetSequenceMutex (locker))
221         {
222             const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
223             if (thread_suffix_supported || GetGDBProcess().GetGDBRemote().SetCurrentThread(m_thread.GetID()))
224             {
225                 char packet[64];
226                 StringExtractorGDBRemote response;
227                 int packet_len = 0;
228                 if (m_read_all_at_once)
229                 {
230                     // Get all registers in one packet
231                     if (thread_suffix_supported)
232                         packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4x;", m_thread.GetID());
233                     else
234                         packet_len = ::snprintf (packet, sizeof(packet), "g");
235                     assert (packet_len < (sizeof(packet) - 1));
236                     if (gdb_comm.SendPacketAndWaitForResponse(packet, response, false))
237                     {
238                         if (response.IsNormalResponse())
239                             if (response.GetHexBytes ((void *)m_reg_data.GetDataStart(), m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize())
240                                 SetAllRegisterValid (true);
241                     }
242                 }
243                 else
244                 {
245                     // Get each register individually
246                     if (thread_suffix_supported)
247                         packet_len = ::snprintf (packet, sizeof(packet), "p%x;thread:%4.4x;", reg, m_thread.GetID());
248                     else
249                         packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
250                     assert (packet_len < (sizeof(packet) - 1));
251                     if (gdb_comm.SendPacketAndWaitForResponse(packet, response, false))
252                         PrivateSetRegisterValue (reg, response);
253                 }
254             }
255         }
256 
257         // Make sure we got a valid register value after reading it
258         if (!m_reg_valid[reg])
259             return false;
260     }
261 
262     if (&data != &m_reg_data)
263     {
264         // If we aren't extracting into our own buffer (which
265         // only happens when this function is called from
266         // ReadRegisterValue(uint32_t, Scalar&)) then
267         // we transfer bytes from our buffer into the data
268         // buffer that was passed in
269         data.SetByteOrder (m_reg_data.GetByteOrder());
270         data.SetData (m_reg_data, reg_info->byte_offset, reg_info->byte_size);
271     }
272     return true;
273 }
274 
275 
276 bool
277 GDBRemoteRegisterContext::WriteRegisterValue (uint32_t reg, const Scalar &value)
278 {
279     const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
280     if (reg_info)
281     {
282         DataExtractor data;
283         if (value.GetData (data, reg_info->byte_size))
284             return WriteRegisterBytes (reg, data, 0);
285     }
286     return false;
287 }
288 
289 
290 bool
291 GDBRemoteRegisterContext::WriteRegisterBytes (uint32_t reg, DataExtractor &data, uint32_t data_offset)
292 {
293     GDBRemoteCommunicationClient &gdb_comm (GetGDBProcess().GetGDBRemote());
294 // FIXME: This check isn't right because IsRunning checks the Public state, but this
295 // is work you need to do - for instance in ShouldStop & friends - before the public
296 // state has been changed.
297 //    if (gdb_comm.IsRunning())
298 //        return false;
299 
300     const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
301 
302     if (reg_info)
303     {
304         // Grab a pointer to where we are going to put this register
305         uint8_t *dst = const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
306 
307         if (dst == NULL)
308             return false;
309 
310         // Grab a pointer to where we are going to grab the new value from
311         const uint8_t *src = data.PeekData(0, reg_info->byte_size);
312 
313         if (src == NULL)
314             return false;
315 
316         if (data.GetByteOrder() == m_reg_data.GetByteOrder())
317         {
318             // No swapping, just copy the bytes
319             ::memcpy (dst, src, reg_info->byte_size);
320         }
321         else
322         {
323             // Swap the bytes
324             for (uint32_t i=0; i<reg_info->byte_size; ++i)
325                 dst[i] = src[reg_info->byte_size - 1 - i];
326         }
327 
328         Mutex::Locker locker;
329         if (gdb_comm.GetSequenceMutex (locker))
330         {
331             const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
332             if (thread_suffix_supported || GetGDBProcess().GetGDBRemote().SetCurrentThread(m_thread.GetID()))
333             {
334                 uint32_t offset, end_offset;
335                 StreamString packet;
336                 StringExtractorGDBRemote response;
337                 if (m_read_all_at_once)
338                 {
339                     // Get all registers in one packet
340                     packet.PutChar ('G');
341                     offset = 0;
342                     end_offset = m_reg_data.GetByteSize();
343 
344                     packet.PutBytesAsRawHex8 (m_reg_data.GetDataStart(),
345                                               m_reg_data.GetByteSize(),
346                                               lldb::endian::InlHostByteOrder(),
347                                               lldb::endian::InlHostByteOrder());
348 
349                     if (thread_suffix_supported)
350                         packet.Printf (";thread:%4.4x;", m_thread.GetID());
351 
352                     // Invalidate all register values
353                     InvalidateIfNeeded (true);
354 
355                     if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
356                                                               packet.GetString().size(),
357                                                               response,
358                                                               false))
359                     {
360                         SetAllRegisterValid (false);
361                         if (response.IsOKResponse())
362                         {
363                             return true;
364                         }
365                     }
366                 }
367                 else
368                 {
369                     // Get each register individually
370                     packet.Printf ("P%x=", reg);
371                     packet.PutBytesAsRawHex8 (m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size),
372                                               reg_info->byte_size,
373                                               lldb::endian::InlHostByteOrder(),
374                                               lldb::endian::InlHostByteOrder());
375 
376                     if (thread_suffix_supported)
377                         packet.Printf (";thread:%4.4x;", m_thread.GetID());
378 
379                     // Invalidate just this register
380                     m_reg_valid[reg] = false;
381                     if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
382                                                               packet.GetString().size(),
383                                                               response,
384                                                               false))
385                     {
386                         if (response.IsOKResponse())
387                         {
388                             return true;
389                         }
390                     }
391                 }
392             }
393         }
394     }
395     return false;
396 }
397 
398 
399 bool
400 GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
401 {
402     GDBRemoteCommunicationClient &gdb_comm (GetGDBProcess().GetGDBRemote());
403     StringExtractorGDBRemote response;
404 
405     Mutex::Locker locker;
406     if (gdb_comm.GetSequenceMutex (locker))
407     {
408         char packet[32];
409         const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
410         if (thread_suffix_supported || GetGDBProcess().GetGDBRemote().SetCurrentThread(m_thread.GetID()))
411         {
412             int packet_len = 0;
413             if (thread_suffix_supported)
414                 packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4x", m_thread.GetID());
415             else
416                 packet_len = ::snprintf (packet, sizeof(packet), "g");
417             assert (packet_len < (sizeof(packet) - 1));
418 
419             if (gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false))
420             {
421                 if (response.IsErrorResponse())
422                     return false;
423 
424                 response.GetStringRef().insert(0, 1, 'G');
425                 if (thread_suffix_supported)
426                 {
427                     char thread_id_cstr[64];
428                     ::snprintf (thread_id_cstr, sizeof(thread_id_cstr), ";thread:%4.4x;", m_thread.GetID());
429                     response.GetStringRef().append (thread_id_cstr);
430                 }
431                 data_sp.reset (new DataBufferHeap (response.GetStringRef().c_str(),
432                                                    response.GetStringRef().size()));
433                 return true;
434             }
435         }
436     }
437     return false;
438 }
439 
440 bool
441 GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
442 {
443     if (!data_sp || data_sp->GetBytes() == NULL || data_sp->GetByteSize() == 0)
444         return false;
445 
446     GDBRemoteCommunicationClient &gdb_comm (GetGDBProcess().GetGDBRemote());
447     StringExtractorGDBRemote response;
448     Mutex::Locker locker;
449     if (gdb_comm.GetSequenceMutex (locker))
450     {
451         const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
452         if (thread_suffix_supported || GetGDBProcess().GetGDBRemote().SetCurrentThread(m_thread.GetID()))
453         {
454             if (gdb_comm.SendPacketAndWaitForResponse((const char *)data_sp->GetBytes(),
455                                                       data_sp->GetByteSize(),
456                                                       response,
457                                                       false))
458             {
459                 if (response.IsOKResponse())
460                     return true;
461             }
462         }
463     }
464     return false;
465 }
466 
467 
468 uint32_t
469 GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
470 {
471     return m_reg_info.ConvertRegisterKindToRegisterNumber (kind, num);
472 }
473 
474 void
475 GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters()
476 {
477     static RegisterInfo g_register_infos[] = {
478 //   NAME    ALT    SZ  OFF  ENCODING          FORMAT          COMPILER             DWARF                GENERIC                 GDB    LLDB
479 //   ======  ====== === ===  =============     ============    ===================  ===================  ======================  ===    ====
480     { "r0",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r0,              dwarf_r0,            LLDB_INVALID_REGNUM,     0,      0 }},
481     { "r1",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r1,              dwarf_r1,            LLDB_INVALID_REGNUM,     1,      1 }},
482     { "r2",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r2,              dwarf_r2,            LLDB_INVALID_REGNUM,     2,      2 }},
483     { "r3",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r3,              dwarf_r3,            LLDB_INVALID_REGNUM,     3,      3 }},
484     { "r4",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r4,              dwarf_r4,            LLDB_INVALID_REGNUM,     4,      4 }},
485     { "r5",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r5,              dwarf_r5,            LLDB_INVALID_REGNUM,     5,      5 }},
486     { "r6",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r6,              dwarf_r6,            LLDB_INVALID_REGNUM,     6,      6 }},
487     { "r7",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r7,              dwarf_r7,            LLDB_REGNUM_GENERIC_FP,  7,      7 }},
488     { "r8",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r8,              dwarf_r8,            LLDB_INVALID_REGNUM,     8,      8 }},
489     { "r9",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r9,              dwarf_r9,            LLDB_INVALID_REGNUM,     9,      9 }},
490     { "r10",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r10,             dwarf_r10,           LLDB_INVALID_REGNUM,    10,     10 }},
491     { "r11",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r11,             dwarf_r11,           LLDB_INVALID_REGNUM,    11,     11 }},
492     { "r12",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r12,             dwarf_r12,           LLDB_INVALID_REGNUM,    12,     12 }},
493     { "sp",   "r13",  4,   0, eEncodingUint,    eFormatHex,   { gcc_sp,              dwarf_sp,            LLDB_REGNUM_GENERIC_SP, 13,     13 }},
494     { "lr",   "r14",  4,   0, eEncodingUint,    eFormatHex,   { gcc_lr,              dwarf_lr,            LLDB_REGNUM_GENERIC_RA, 14,     14 }},
495     { "pc",   "r15",  4,   0, eEncodingUint,    eFormatHex,   { gcc_pc,              dwarf_pc,            LLDB_REGNUM_GENERIC_PC, 15,     15 }},
496     { "f0",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    16,     16 }},
497     { "f1",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    17,     17 }},
498     { "f2",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    18,     18 }},
499     { "f3",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    19,     19 }},
500     { "f4",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    20,     20 }},
501     { "f5",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    21,     21 }},
502     { "f6",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    22,     22 }},
503     { "f7",   NULL,  12,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    23,     23 }},
504     { "fps",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    24,     24 }},
505     { "cpsr", "psr",  4,   0, eEncodingUint,    eFormatHex,   { gcc_cpsr,            dwarf_cpsr,          LLDB_INVALID_REGNUM,    25,     25 }},
506     { "s0",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s0,            LLDB_INVALID_REGNUM,    26,     26 }},
507     { "s1",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s1,            LLDB_INVALID_REGNUM,    27,     27 }},
508     { "s2",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s2,            LLDB_INVALID_REGNUM,    28,     28 }},
509     { "s3",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s3,            LLDB_INVALID_REGNUM,    29,     29 }},
510     { "s4",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s4,            LLDB_INVALID_REGNUM,    30,     30 }},
511     { "s5",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s5,            LLDB_INVALID_REGNUM,    31,     31 }},
512     { "s6",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s6,            LLDB_INVALID_REGNUM,    32,     32 }},
513     { "s7",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s7,            LLDB_INVALID_REGNUM,    33,     33 }},
514     { "s8",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s8,            LLDB_INVALID_REGNUM,    34,     34 }},
515     { "s9",   NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s9,            LLDB_INVALID_REGNUM,    35,     35 }},
516     { "s10",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s10,           LLDB_INVALID_REGNUM,    36,     36 }},
517     { "s11",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s11,           LLDB_INVALID_REGNUM,    37,     37 }},
518     { "s12",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s12,           LLDB_INVALID_REGNUM,    38,     38 }},
519     { "s13",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s13,           LLDB_INVALID_REGNUM,    39,     39 }},
520     { "s14",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s14,           LLDB_INVALID_REGNUM,    40,     40 }},
521     { "s15",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s15,           LLDB_INVALID_REGNUM,    41,     41 }},
522     { "s16",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s16,           LLDB_INVALID_REGNUM,    42,     42 }},
523     { "s17",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s17,           LLDB_INVALID_REGNUM,    43,     43 }},
524     { "s18",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s18,           LLDB_INVALID_REGNUM,    44,     44 }},
525     { "s19",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s19,           LLDB_INVALID_REGNUM,    45,     45 }},
526     { "s20",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s20,           LLDB_INVALID_REGNUM,    46,     46 }},
527     { "s21",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s21,           LLDB_INVALID_REGNUM,    47,     47 }},
528     { "s22",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s22,           LLDB_INVALID_REGNUM,    48,     48 }},
529     { "s23",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s23,           LLDB_INVALID_REGNUM,    49,     49 }},
530     { "s24",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s24,           LLDB_INVALID_REGNUM,    50,     50 }},
531     { "s25",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s25,           LLDB_INVALID_REGNUM,    51,     51 }},
532     { "s26",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s26,           LLDB_INVALID_REGNUM,    52,     52 }},
533     { "s27",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s27,           LLDB_INVALID_REGNUM,    53,     53 }},
534     { "s28",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s28,           LLDB_INVALID_REGNUM,    54,     54 }},
535     { "s29",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s29,           LLDB_INVALID_REGNUM,    55,     55 }},
536     { "s30",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s30,           LLDB_INVALID_REGNUM,    56,     56 }},
537     { "s31",  NULL,   4,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_s31,           LLDB_INVALID_REGNUM,    57,     57 }},
538     { "fpscr",NULL,   4,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    58,     58 }},
539     { "d16",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d16,           LLDB_INVALID_REGNUM,    59,     59 }},
540     { "d17",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d17,           LLDB_INVALID_REGNUM,    60,     60 }},
541     { "d18",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d18,           LLDB_INVALID_REGNUM,    61,     61 }},
542     { "d19",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d19,           LLDB_INVALID_REGNUM,    62,     62 }},
543     { "d20",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d20,           LLDB_INVALID_REGNUM,    63,     63 }},
544     { "d21",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d21,           LLDB_INVALID_REGNUM,    64,     64 }},
545     { "d22",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d22,           LLDB_INVALID_REGNUM,    65,     65 }},
546     { "d23",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d23,           LLDB_INVALID_REGNUM,    66,     66 }},
547     { "d24",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d24,           LLDB_INVALID_REGNUM,    67,     67 }},
548     { "d25",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d25,           LLDB_INVALID_REGNUM,    68,     68 }},
549     { "d26",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d26,           LLDB_INVALID_REGNUM,    69,     69 }},
550     { "d27",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d27,           LLDB_INVALID_REGNUM,    70,     70 }},
551     { "d28",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d28,           LLDB_INVALID_REGNUM,    71,     71 }},
552     { "d29",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d29,           LLDB_INVALID_REGNUM,    72,     72 }},
553     { "d30",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d30,           LLDB_INVALID_REGNUM,    73,     73 }},
554     { "d31",  NULL,   8,   0, eEncodingIEEE754, eFormatHex,   { LLDB_INVALID_REGNUM, dwarf_d31,           LLDB_INVALID_REGNUM,    74,     74 }},
555     };
556 
557     static const uint32_t num_registers = sizeof (g_register_infos)/sizeof (RegisterInfo);
558     static ConstString gpr_reg_set ("General Purpose Registers");
559     static ConstString sfp_reg_set ("Software Floating Point Registers");
560     static ConstString vfp_reg_set ("Floating Point Registers");
561     uint32_t i;
562     // Calculate the offsets of the registers
563     if (g_register_infos[2].byte_offset == 0)
564     {
565         uint32_t byte_offset = 0;
566         for (i=0; i<num_registers; ++i)
567         {
568             g_register_infos[i].byte_offset = byte_offset;
569             byte_offset += g_register_infos[i].byte_size;
570         }
571     }
572     for (i=0; i<num_registers; ++i)
573     {
574         ConstString name;
575         ConstString alt_name;
576         if (g_register_infos[i].name && g_register_infos[i].name[0])
577             name.SetCString(g_register_infos[i].name);
578         if (g_register_infos[i].alt_name && g_register_infos[i].alt_name[0])
579             alt_name.SetCString(g_register_infos[i].alt_name);
580 
581         if (i <= 15 || i == 25)
582             AddRegister (g_register_infos[i], name, alt_name, gpr_reg_set);
583         else if (i <= 24)
584             AddRegister (g_register_infos[i], name, alt_name, sfp_reg_set);
585         else
586             AddRegister (g_register_infos[i], name, alt_name, vfp_reg_set);
587     }
588 }
589 
590