1 //===-- DynamicRegisterInfo.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 "lldb/lldb-python.h" 11 12 #include "DynamicRegisterInfo.h" 13 14 // C Includes 15 // C++ Includes 16 // Other libraries and framework includes 17 // Project includes 18 #include "lldb/Interpreter/Args.h" 19 #include "lldb/Core/RegularExpression.h" 20 #include "lldb/Core/StreamFile.h" 21 #include "lldb/DataFormatters/FormatManager.h" 22 23 #ifndef LLDB_DISABLE_PYTHON 24 #include "lldb/Interpreter/PythonDataObjects.h" 25 #endif 26 27 using namespace lldb; 28 using namespace lldb_private; 29 30 DynamicRegisterInfo::DynamicRegisterInfo () : 31 m_regs (), 32 m_sets (), 33 m_set_reg_nums (), 34 m_set_names (), 35 m_value_regs_map (), 36 m_invalidate_regs_map (), 37 m_reg_data_byte_size (0), 38 m_finalized (false) 39 { 40 } 41 42 DynamicRegisterInfo::DynamicRegisterInfo (const lldb_private::PythonDictionary &dict, ByteOrder byte_order) : 43 m_regs (), 44 m_sets (), 45 m_set_reg_nums (), 46 m_set_names (), 47 m_value_regs_map (), 48 m_invalidate_regs_map (), 49 m_reg_data_byte_size (0), 50 m_finalized (false) 51 { 52 SetRegisterInfo (dict, byte_order); 53 } 54 55 DynamicRegisterInfo::~DynamicRegisterInfo () 56 { 57 } 58 59 60 size_t 61 DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict, 62 ByteOrder byte_order) 63 { 64 assert(!m_finalized); 65 #ifndef LLDB_DISABLE_PYTHON 66 PythonList sets (dict.GetItemForKey("sets")); 67 if (sets) 68 { 69 const uint32_t num_sets = sets.GetSize(); 70 for (uint32_t i=0; i<num_sets; ++i) 71 { 72 PythonString py_set_name(sets.GetItemAtIndex(i)); 73 ConstString set_name; 74 if (py_set_name) 75 set_name.SetCString(py_set_name.GetString()); 76 if (set_name) 77 { 78 RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL }; 79 m_sets.push_back (new_set); 80 } 81 else 82 { 83 Clear(); 84 return 0; 85 } 86 } 87 m_set_reg_nums.resize(m_sets.size()); 88 } 89 PythonList regs (dict.GetItemForKey("registers")); 90 if (regs) 91 { 92 const uint32_t num_regs = regs.GetSize(); 93 PythonString name_pystr("name"); 94 PythonString altname_pystr("alt-name"); 95 PythonString bitsize_pystr("bitsize"); 96 PythonString offset_pystr("offset"); 97 PythonString encoding_pystr("encoding"); 98 PythonString format_pystr("format"); 99 PythonString set_pystr("set"); 100 PythonString gcc_pystr("gcc"); 101 PythonString dwarf_pystr("dwarf"); 102 PythonString generic_pystr("generic"); 103 PythonString slice_pystr("slice"); 104 PythonString composite_pystr("composite"); 105 PythonString invalidate_regs_pystr("invalidate-regs"); 106 107 // typedef std::map<std::string, std::vector<std::string> > InvalidateNameMap; 108 // InvalidateNameMap invalidate_map; 109 for (uint32_t i=0; i<num_regs; ++i) 110 { 111 PythonDictionary reg_info_dict(regs.GetItemAtIndex(i)); 112 if (reg_info_dict) 113 { 114 // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 2, 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', }, 115 RegisterInfo reg_info; 116 std::vector<uint32_t> value_regs; 117 std::vector<uint32_t> invalidate_regs; 118 bzero (®_info, sizeof(reg_info)); 119 120 reg_info.name = ConstString (reg_info_dict.GetItemForKeyAsString(name_pystr)).GetCString(); 121 if (reg_info.name == NULL) 122 { 123 Clear(); 124 return 0; 125 } 126 127 reg_info.alt_name = ConstString (reg_info_dict.GetItemForKeyAsString(altname_pystr)).GetCString(); 128 129 reg_info.byte_offset = reg_info_dict.GetItemForKeyAsInteger(offset_pystr, UINT32_MAX); 130 131 if (reg_info.byte_offset == UINT32_MAX) 132 { 133 // No offset for this register, see if the register has a value expression 134 // which indicates this register is part of another register. Value expressions 135 // are things like "rax[31:0]" which state that the current register's value 136 // is in a concrete register "rax" in bits 31:0. If there is a value expression 137 // we can calculate the offset 138 bool success = false; 139 const char *slice_cstr = reg_info_dict.GetItemForKeyAsString(slice_pystr); 140 if (slice_cstr) 141 { 142 // Slices use the following format: 143 // REGNAME[MSBIT:LSBIT] 144 // REGNAME - name of the register to grab a slice of 145 // MSBIT - the most significant bit at which the current register value starts at 146 // LSBIT - the least significant bit at which the current register value ends at 147 static RegularExpression g_bitfield_regex("([A-Za-z_][A-Za-z0-9_]*)\\[([0-9]+):([0-9]+)\\]"); 148 RegularExpression::Match regex_match(3); 149 if (g_bitfield_regex.Execute(slice_cstr, ®ex_match)) 150 { 151 llvm::StringRef reg_name_str; 152 std::string msbit_str; 153 std::string lsbit_str; 154 if (regex_match.GetMatchAtIndex(slice_cstr, 1, reg_name_str) && 155 regex_match.GetMatchAtIndex(slice_cstr, 2, msbit_str) && 156 regex_match.GetMatchAtIndex(slice_cstr, 3, lsbit_str)) 157 { 158 const uint32_t msbit = Args::StringToUInt32(msbit_str.c_str(), UINT32_MAX); 159 const uint32_t lsbit = Args::StringToUInt32(lsbit_str.c_str(), UINT32_MAX); 160 if (msbit != UINT32_MAX && lsbit != UINT32_MAX) 161 { 162 if (msbit > lsbit) 163 { 164 const uint32_t msbyte = msbit / 8; 165 const uint32_t lsbyte = lsbit / 8; 166 167 ConstString containing_reg_name(reg_name_str); 168 169 RegisterInfo *containing_reg_info = GetRegisterInfo (containing_reg_name); 170 if (containing_reg_info) 171 { 172 const uint32_t max_bit = containing_reg_info->byte_size * 8; 173 if (msbit < max_bit && lsbit < max_bit) 174 { 175 m_invalidate_regs_map[containing_reg_info->kinds[eRegisterKindLLDB]].push_back(i); 176 m_value_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]); 177 m_invalidate_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]); 178 179 if (byte_order == eByteOrderLittle) 180 { 181 success = true; 182 reg_info.byte_offset = containing_reg_info->byte_offset + lsbyte; 183 } 184 else if (byte_order == eByteOrderBig) 185 { 186 success = true; 187 reg_info.byte_offset = containing_reg_info->byte_offset + msbyte; 188 } 189 else 190 { 191 assert(!"Invalid byte order"); 192 } 193 } 194 else 195 { 196 if (msbit > max_bit) 197 printf("error: msbit (%u) must be less than the bitsize of the register (%u)\n", msbit, max_bit); 198 else 199 printf("error: lsbit (%u) must be less than the bitsize of the register (%u)\n", lsbit, max_bit); 200 } 201 } 202 else 203 { 204 printf("error: invalid concrete register \"%s\"\n", containing_reg_name.GetCString()); 205 } 206 } 207 else 208 { 209 printf("error: msbit (%u) must be greater than lsbit (%u)\n", msbit, lsbit); 210 } 211 } 212 else 213 { 214 printf("error: msbit (%u) and lsbit (%u) must be valid\n", msbit, lsbit); 215 } 216 } 217 else 218 { 219 // TODO: print error invalid slice string that doesn't follow the format 220 printf("error: failed to extract regex matches for parsing the register bitfield regex\n"); 221 222 } 223 } 224 else 225 { 226 // TODO: print error invalid slice string that doesn't follow the format 227 printf("error: failed to match against register bitfield regex\n"); 228 } 229 } 230 else 231 { 232 PythonList composite_reg_list (reg_info_dict.GetItemForKey(composite_pystr)); 233 if (composite_reg_list) 234 { 235 const size_t num_composite_regs = composite_reg_list.GetSize(); 236 if (num_composite_regs > 0) 237 { 238 uint32_t composite_offset = UINT32_MAX; 239 for (uint32_t composite_idx=0; composite_idx<num_composite_regs; ++composite_idx) 240 { 241 PythonString composite_reg_name_pystr(composite_reg_list.GetItemAtIndex(composite_idx)); 242 if (composite_reg_name_pystr) 243 { 244 ConstString composite_reg_name(composite_reg_name_pystr.GetString()); 245 if (composite_reg_name) 246 { 247 RegisterInfo *composite_reg_info = GetRegisterInfo (composite_reg_name); 248 if (composite_reg_info) 249 { 250 if (composite_offset > composite_reg_info->byte_offset) 251 composite_offset = composite_reg_info->byte_offset; 252 m_value_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]); 253 m_invalidate_regs_map[composite_reg_info->kinds[eRegisterKindLLDB]].push_back(i); 254 m_invalidate_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]); 255 } 256 else 257 { 258 // TODO: print error invalid slice string that doesn't follow the format 259 printf("error: failed to find composite register by name: \"%s\"\n", composite_reg_name.GetCString()); 260 } 261 } 262 else 263 { 264 printf("error: 'composite' key contained an empty string\n"); 265 } 266 } 267 else 268 { 269 printf("error: 'composite' list value wasn't a python string\n"); 270 } 271 } 272 if (composite_offset != UINT32_MAX) 273 { 274 reg_info.byte_offset = composite_offset; 275 success = m_value_regs_map.find(i) != m_value_regs_map.end(); 276 } 277 else 278 { 279 printf("error: 'composite' registers must specify at least one real register\n"); 280 } 281 } 282 else 283 { 284 printf("error: 'composite' list was empty\n"); 285 } 286 } 287 } 288 289 290 if (!success) 291 { 292 Clear(); 293 return 0; 294 } 295 } 296 const int64_t bitsize = reg_info_dict.GetItemForKeyAsInteger(bitsize_pystr, 0); 297 if (bitsize == 0) 298 { 299 Clear(); 300 return 0; 301 } 302 303 reg_info.byte_size = bitsize / 8; 304 305 const char *format_cstr = reg_info_dict.GetItemForKeyAsString(format_pystr); 306 if (format_cstr) 307 { 308 if (Args::StringToFormat(format_cstr, reg_info.format, NULL).Fail()) 309 { 310 Clear(); 311 return 0; 312 } 313 } 314 else 315 { 316 reg_info.format = (Format)reg_info_dict.GetItemForKeyAsInteger (format_pystr, eFormatHex); 317 } 318 319 const char *encoding_cstr = reg_info_dict.GetItemForKeyAsString(encoding_pystr); 320 if (encoding_cstr) 321 reg_info.encoding = Args::StringToEncoding (encoding_cstr, eEncodingUint); 322 else 323 reg_info.encoding = (Encoding)reg_info_dict.GetItemForKeyAsInteger (encoding_pystr, eEncodingUint); 324 325 const int64_t set = reg_info_dict.GetItemForKeyAsInteger(set_pystr, -1); 326 if (set >= m_sets.size()) 327 { 328 Clear(); 329 return 0; 330 } 331 332 // Fill in the register numbers 333 reg_info.kinds[lldb::eRegisterKindLLDB] = i; 334 reg_info.kinds[lldb::eRegisterKindGDB] = i; 335 reg_info.kinds[lldb::eRegisterKindGCC] = reg_info_dict.GetItemForKeyAsInteger(gcc_pystr, LLDB_INVALID_REGNUM); 336 reg_info.kinds[lldb::eRegisterKindDWARF] = reg_info_dict.GetItemForKeyAsInteger(dwarf_pystr, LLDB_INVALID_REGNUM); 337 const char *generic_cstr = reg_info_dict.GetItemForKeyAsString(generic_pystr); 338 if (generic_cstr) 339 reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister (generic_cstr); 340 else 341 reg_info.kinds[lldb::eRegisterKindGeneric] = reg_info_dict.GetItemForKeyAsInteger(generic_pystr, LLDB_INVALID_REGNUM); 342 343 // Check if this register invalidates any other register values when it is modified 344 PythonList invalidate_reg_list (reg_info_dict.GetItemForKey(invalidate_regs_pystr)); 345 if (invalidate_reg_list) 346 { 347 const size_t num_regs = invalidate_reg_list.GetSize(); 348 if (num_regs > 0) 349 { 350 for (uint32_t idx=0; idx<num_regs; ++idx) 351 { 352 PythonObject invalidate_reg_object (invalidate_reg_list.GetItemAtIndex(idx)); 353 PythonString invalidate_reg_name_pystr(invalidate_reg_object); 354 if (invalidate_reg_name_pystr) 355 { 356 ConstString invalidate_reg_name(invalidate_reg_name_pystr.GetString()); 357 if (invalidate_reg_name) 358 { 359 RegisterInfo *invalidate_reg_info = GetRegisterInfo (invalidate_reg_name); 360 if (invalidate_reg_info) 361 { 362 m_invalidate_regs_map[i].push_back(invalidate_reg_info->kinds[eRegisterKindLLDB]); 363 } 364 else 365 { 366 // TODO: print error invalid slice string that doesn't follow the format 367 printf("error: failed to find a 'invalidate-regs' register for \"%s\" while parsing register \"%s\"\n", invalidate_reg_name.GetCString(), reg_info.name); 368 } 369 } 370 else 371 { 372 printf("error: 'invalidate-regs' list value was an empty string\n"); 373 } 374 } 375 else 376 { 377 PythonInteger invalidate_reg_num(invalidate_reg_object); 378 379 if (invalidate_reg_num) 380 { 381 const int64_t r = invalidate_reg_num.GetInteger(); 382 if (r != UINT64_MAX) 383 m_invalidate_regs_map[i].push_back(r); 384 else 385 printf("error: 'invalidate-regs' list value wasn't a valid integer\n"); 386 } 387 else 388 { 389 printf("error: 'invalidate-regs' list value wasn't a python string or integer\n"); 390 } 391 } 392 } 393 } 394 else 395 { 396 printf("error: 'invalidate-regs' contained an empty list\n"); 397 } 398 } 399 400 // Calculate the register offset 401 const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size; 402 if (m_reg_data_byte_size < end_reg_offset) 403 m_reg_data_byte_size = end_reg_offset; 404 405 m_regs.push_back (reg_info); 406 m_set_reg_nums[set].push_back(i); 407 408 } 409 else 410 { 411 Clear(); 412 return 0; 413 } 414 } 415 Finalize (); 416 } 417 #endif 418 return m_regs.size(); 419 } 420 421 422 void 423 DynamicRegisterInfo::AddRegister (RegisterInfo ®_info, 424 ConstString ®_name, 425 ConstString ®_alt_name, 426 ConstString &set_name) 427 { 428 assert(!m_finalized); 429 const uint32_t reg_num = m_regs.size(); 430 reg_info.name = reg_name.AsCString(); 431 assert (reg_info.name); 432 reg_info.alt_name = reg_alt_name.AsCString(NULL); 433 uint32_t i; 434 if (reg_info.value_regs) 435 { 436 for (i=0; reg_info.value_regs[i] != LLDB_INVALID_REGNUM; ++i) 437 m_value_regs_map[reg_num].push_back(reg_info.value_regs[i]); 438 } 439 if (reg_info.invalidate_regs) 440 { 441 for (i=0; reg_info.invalidate_regs[i] != LLDB_INVALID_REGNUM; ++i) 442 m_invalidate_regs_map[reg_num].push_back(reg_info.invalidate_regs[i]); 443 } 444 m_regs.push_back (reg_info); 445 uint32_t set = GetRegisterSetIndexByName (set_name, true); 446 assert (set < m_sets.size()); 447 assert (set < m_set_reg_nums.size()); 448 assert (set < m_set_names.size()); 449 m_set_reg_nums[set].push_back(reg_num); 450 size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size; 451 if (m_reg_data_byte_size < end_reg_offset) 452 m_reg_data_byte_size = end_reg_offset; 453 } 454 455 void 456 DynamicRegisterInfo::Finalize () 457 { 458 if (m_finalized) 459 return; 460 461 m_finalized = true; 462 const size_t num_sets = m_sets.size(); 463 for (size_t set = 0; set < num_sets; ++set) 464 { 465 assert (m_sets.size() == m_set_reg_nums.size()); 466 m_sets[set].num_registers = m_set_reg_nums[set].size(); 467 m_sets[set].registers = &m_set_reg_nums[set][0]; 468 } 469 470 // sort and unique all value registers and make sure each is terminated with 471 // LLDB_INVALID_REGNUM 472 473 for (reg_to_regs_map::iterator pos = m_value_regs_map.begin(), end = m_value_regs_map.end(); 474 pos != end; 475 ++pos) 476 { 477 if (pos->second.size() > 1) 478 { 479 std::sort (pos->second.begin(), pos->second.end()); 480 reg_num_collection::iterator unique_end = std::unique (pos->second.begin(), pos->second.end()); 481 if (unique_end != pos->second.end()) 482 pos->second.erase(unique_end, pos->second.end()); 483 } 484 assert (!pos->second.empty()); 485 if (pos->second.back() != LLDB_INVALID_REGNUM) 486 pos->second.push_back(LLDB_INVALID_REGNUM); 487 } 488 489 // Now update all value_regs with each register info as needed 490 const size_t num_regs = m_regs.size(); 491 for (size_t i=0; i<num_regs; ++i) 492 { 493 if (m_value_regs_map.find(i) != m_value_regs_map.end()) 494 m_regs[i].value_regs = m_value_regs_map[i].data(); 495 else 496 m_regs[i].value_regs = NULL; 497 } 498 499 // Expand all invalidation dependencies 500 for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), end = m_invalidate_regs_map.end(); 501 pos != end; 502 ++pos) 503 { 504 const uint32_t reg_num = pos->first; 505 506 if (m_regs[reg_num].value_regs) 507 { 508 reg_num_collection extra_invalid_regs; 509 for (const uint32_t invalidate_reg_num : pos->second) 510 { 511 reg_to_regs_map::iterator invalidate_pos = m_invalidate_regs_map.find(invalidate_reg_num); 512 if (invalidate_pos != m_invalidate_regs_map.end()) 513 { 514 for (const uint32_t concrete_invalidate_reg_num : invalidate_pos->second) 515 { 516 if (concrete_invalidate_reg_num != reg_num) 517 extra_invalid_regs.push_back(concrete_invalidate_reg_num); 518 } 519 } 520 } 521 pos->second.insert(pos->second.end(), extra_invalid_regs.begin(), extra_invalid_regs.end()); 522 } 523 } 524 525 // sort and unique all invalidate registers and make sure each is terminated with 526 // LLDB_INVALID_REGNUM 527 for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), end = m_invalidate_regs_map.end(); 528 pos != end; 529 ++pos) 530 { 531 if (pos->second.size() > 1) 532 { 533 std::sort (pos->second.begin(), pos->second.end()); 534 reg_num_collection::iterator unique_end = std::unique (pos->second.begin(), pos->second.end()); 535 if (unique_end != pos->second.end()) 536 pos->second.erase(unique_end, pos->second.end()); 537 } 538 assert (!pos->second.empty()); 539 if (pos->second.back() != LLDB_INVALID_REGNUM) 540 pos->second.push_back(LLDB_INVALID_REGNUM); 541 } 542 543 // Now update all invalidate_regs with each register info as needed 544 for (size_t i=0; i<num_regs; ++i) 545 { 546 if (m_invalidate_regs_map.find(i) != m_invalidate_regs_map.end()) 547 m_regs[i].invalidate_regs = m_invalidate_regs_map[i].data(); 548 else 549 m_regs[i].invalidate_regs = NULL; 550 } 551 } 552 553 size_t 554 DynamicRegisterInfo::GetNumRegisters() const 555 { 556 return m_regs.size(); 557 } 558 559 size_t 560 DynamicRegisterInfo::GetNumRegisterSets() const 561 { 562 return m_sets.size(); 563 } 564 565 size_t 566 DynamicRegisterInfo::GetRegisterDataByteSize() const 567 { 568 return m_reg_data_byte_size; 569 } 570 571 const RegisterInfo * 572 DynamicRegisterInfo::GetRegisterInfoAtIndex (uint32_t i) const 573 { 574 if (i < m_regs.size()) 575 return &m_regs[i]; 576 return NULL; 577 } 578 579 const RegisterSet * 580 DynamicRegisterInfo::GetRegisterSet (uint32_t i) const 581 { 582 if (i < m_sets.size()) 583 return &m_sets[i]; 584 return NULL; 585 } 586 587 uint32_t 588 DynamicRegisterInfo::GetRegisterSetIndexByName (ConstString &set_name, bool can_create) 589 { 590 name_collection::iterator pos, end = m_set_names.end(); 591 for (pos = m_set_names.begin(); pos != end; ++pos) 592 { 593 if (*pos == set_name) 594 return std::distance (m_set_names.begin(), pos); 595 } 596 597 m_set_names.push_back(set_name); 598 m_set_reg_nums.resize(m_set_reg_nums.size()+1); 599 RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL }; 600 m_sets.push_back (new_set); 601 return m_sets.size() - 1; 602 } 603 604 uint32_t 605 DynamicRegisterInfo::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const 606 { 607 reg_collection::const_iterator pos, end = m_regs.end(); 608 for (pos = m_regs.begin(); pos != end; ++pos) 609 { 610 if (pos->kinds[kind] == num) 611 return std::distance (m_regs.begin(), pos); 612 } 613 614 return LLDB_INVALID_REGNUM; 615 } 616 617 void 618 DynamicRegisterInfo::Clear() 619 { 620 m_regs.clear(); 621 m_sets.clear(); 622 m_set_reg_nums.clear(); 623 m_set_names.clear(); 624 m_value_regs_map.clear(); 625 m_invalidate_regs_map.clear(); 626 m_reg_data_byte_size = 0; 627 m_finalized = false; 628 } 629 630 void 631 DynamicRegisterInfo::Dump () const 632 { 633 StreamFile s(stdout, false); 634 const size_t num_regs = m_regs.size(); 635 s.Printf("%p: DynamicRegisterInfo contains %zu registers:\n", this, num_regs); 636 for (size_t i=0; i<num_regs; ++i) 637 { 638 s.Printf("[%3zu] name = %-10s", i, m_regs[i].name); 639 s.Printf(", size = %2u, offset = %4u, encoding = %u, format = %-10s", 640 m_regs[i].byte_size, 641 m_regs[i].byte_offset, 642 m_regs[i].encoding, 643 FormatManager::GetFormatAsCString (m_regs[i].format)); 644 if (m_regs[i].kinds[eRegisterKindGDB] != LLDB_INVALID_REGNUM) 645 s.Printf(", gdb = %3u", m_regs[i].kinds[eRegisterKindGDB]); 646 if (m_regs[i].kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) 647 s.Printf(", dwarf = %3u", m_regs[i].kinds[eRegisterKindDWARF]); 648 if (m_regs[i].kinds[eRegisterKindGCC] != LLDB_INVALID_REGNUM) 649 s.Printf(", gcc = %3u", m_regs[i].kinds[eRegisterKindGCC]); 650 if (m_regs[i].kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) 651 s.Printf(", generic = %3u", m_regs[i].kinds[eRegisterKindGeneric]); 652 if (m_regs[i].alt_name) 653 s.Printf(", alt-name = %s", m_regs[i].alt_name); 654 if (m_regs[i].value_regs) 655 { 656 s.Printf(", value_regs = [ "); 657 for (size_t j=0; m_regs[i].value_regs[j] != LLDB_INVALID_REGNUM; ++j) 658 { 659 s.Printf("%s ", m_regs[m_regs[i].value_regs[j]].name); 660 } 661 s.Printf("]"); 662 } 663 if (m_regs[i].invalidate_regs) 664 { 665 s.Printf(", invalidate_regs = [ "); 666 for (size_t j=0; m_regs[i].invalidate_regs[j] != LLDB_INVALID_REGNUM; ++j) 667 { 668 s.Printf("%s ", m_regs[m_regs[i].invalidate_regs[j]].name); 669 } 670 s.Printf("]"); 671 } 672 s.EOL(); 673 } 674 675 const size_t num_sets = m_sets.size(); 676 s.Printf("%p: DynamicRegisterInfo contains %zu register sets:\n", this, num_sets); 677 for (size_t i=0; i<num_sets; ++i) 678 { 679 s.Printf("set[%zu] name = %s, regs = [", i, m_sets[i].name); 680 for (size_t idx=0; idx<m_sets[i].num_registers; ++idx) 681 { 682 s.Printf("%s ", m_regs[m_sets[i].registers[idx]].name); 683 } 684 s.Printf("]\n"); 685 } 686 } 687 688 689 690 lldb_private::RegisterInfo * 691 DynamicRegisterInfo::GetRegisterInfo (const lldb_private::ConstString ®_name) 692 { 693 for (auto ®_info : m_regs) 694 { 695 // We can use pointer comparison since we used a ConstString to set 696 // the "name" member in AddRegister() 697 if (reg_info.name == reg_name.GetCString()) 698 { 699 return ®_info; 700 } 701 } 702 return NULL; 703 } 704