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 ®_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