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