1 //===-- RegisterContextMinidump_ARM64.cpp ---------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "RegisterContextMinidump_ARM64.h" 10 11 #include "Utility/ARM64_DWARF_Registers.h" 12 #include "lldb/Utility/RegisterValue.h" 13 #include "lldb/Utility/DataExtractor.h" 14 #include "lldb/lldb-enumerations.h" 15 16 // C includes 17 #include <cassert> 18 19 // C++ includes 20 21 using namespace lldb; 22 using namespace lldb_private; 23 using namespace minidump; 24 25 #define INV LLDB_INVALID_REGNUM 26 #define OFFSET(r) (offsetof(RegisterContextMinidump_ARM64::Context, r)) 27 28 #define DEF_X(i) \ 29 { \ 30 "x" #i, nullptr, 8, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \ 31 {arm64_dwarf::x##i, arm64_dwarf::x##i, INV, INV, reg_x##i}, \ 32 nullptr, nullptr, \ 33 } 34 35 #define DEF_W(i) \ 36 { \ 37 "w" #i, nullptr, 4, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \ 38 {INV, INV, INV, INV, reg_w##i}, nullptr, nullptr, \ 39 } 40 41 #define DEF_X_ARG(i, n) \ 42 { \ 43 "x" #i, "arg" #n, 8, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \ 44 {arm64_dwarf::x##i, arm64_dwarf::x##i, LLDB_REGNUM_GENERIC_ARG1 + i, \ 45 INV, reg_x##i}, nullptr, nullptr, \ 46 } 47 48 #define DEF_V(i) \ 49 { \ 50 "v" #i, nullptr, 16, OFFSET(v) + i * 16, eEncodingVector, \ 51 eFormatVectorOfUInt8, {arm64_dwarf::v##i, arm64_dwarf::v##i, INV, INV, \ 52 reg_v##i}, nullptr, nullptr, \ 53 } 54 55 #define DEF_D(i) \ 56 { \ 57 "d" #i, nullptr, 8, OFFSET(v) + i * 16, eEncodingVector, \ 58 eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_d##i}, nullptr, \ 59 nullptr, \ 60 } 61 62 #define DEF_S(i) \ 63 { \ 64 "s" #i, nullptr, 4, OFFSET(v) + i * 16, eEncodingVector, \ 65 eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_s##i}, nullptr, \ 66 nullptr, \ 67 } 68 69 #define DEF_H(i) \ 70 { \ 71 "h" #i, nullptr, 2, OFFSET(v) + i * 16, eEncodingVector, \ 72 eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_h##i}, nullptr, \ 73 nullptr, \ 74 } 75 76 // Zero based LLDB register numbers for this register context 77 enum { 78 // General Purpose Registers 79 reg_x0 = 0, 80 reg_x1, 81 reg_x2, 82 reg_x3, 83 reg_x4, 84 reg_x5, 85 reg_x6, 86 reg_x7, 87 reg_x8, 88 reg_x9, 89 reg_x10, 90 reg_x11, 91 reg_x12, 92 reg_x13, 93 reg_x14, 94 reg_x15, 95 reg_x16, 96 reg_x17, 97 reg_x18, 98 reg_x19, 99 reg_x20, 100 reg_x21, 101 reg_x22, 102 reg_x23, 103 reg_x24, 104 reg_x25, 105 reg_x26, 106 reg_x27, 107 reg_x28, 108 reg_fp, 109 reg_lr, 110 reg_sp, 111 reg_pc, 112 reg_w0, 113 reg_w1, 114 reg_w2, 115 reg_w3, 116 reg_w4, 117 reg_w5, 118 reg_w6, 119 reg_w7, 120 reg_w8, 121 reg_w9, 122 reg_w10, 123 reg_w11, 124 reg_w12, 125 reg_w13, 126 reg_w14, 127 reg_w15, 128 reg_w16, 129 reg_w17, 130 reg_w18, 131 reg_w19, 132 reg_w20, 133 reg_w21, 134 reg_w22, 135 reg_w23, 136 reg_w24, 137 reg_w25, 138 reg_w26, 139 reg_w27, 140 reg_w28, 141 reg_w29, 142 reg_w30, 143 reg_w31, 144 reg_cpsr, 145 // Floating Point Registers 146 reg_fpsr, 147 reg_fpcr, 148 reg_v0, 149 reg_v1, 150 reg_v2, 151 reg_v3, 152 reg_v4, 153 reg_v5, 154 reg_v6, 155 reg_v7, 156 reg_v8, 157 reg_v9, 158 reg_v10, 159 reg_v11, 160 reg_v12, 161 reg_v13, 162 reg_v14, 163 reg_v15, 164 reg_v16, 165 reg_v17, 166 reg_v18, 167 reg_v19, 168 reg_v20, 169 reg_v21, 170 reg_v22, 171 reg_v23, 172 reg_v24, 173 reg_v25, 174 reg_v26, 175 reg_v27, 176 reg_v28, 177 reg_v29, 178 reg_v30, 179 reg_v31, 180 reg_d0, 181 reg_d1, 182 reg_d2, 183 reg_d3, 184 reg_d4, 185 reg_d5, 186 reg_d6, 187 reg_d7, 188 reg_d8, 189 reg_d9, 190 reg_d10, 191 reg_d11, 192 reg_d12, 193 reg_d13, 194 reg_d14, 195 reg_d15, 196 reg_d16, 197 reg_d17, 198 reg_d18, 199 reg_d19, 200 reg_d20, 201 reg_d21, 202 reg_d22, 203 reg_d23, 204 reg_d24, 205 reg_d25, 206 reg_d26, 207 reg_d27, 208 reg_d28, 209 reg_d29, 210 reg_d30, 211 reg_d31, 212 reg_s0, 213 reg_s1, 214 reg_s2, 215 reg_s3, 216 reg_s4, 217 reg_s5, 218 reg_s6, 219 reg_s7, 220 reg_s8, 221 reg_s9, 222 reg_s10, 223 reg_s11, 224 reg_s12, 225 reg_s13, 226 reg_s14, 227 reg_s15, 228 reg_s16, 229 reg_s17, 230 reg_s18, 231 reg_s19, 232 reg_s20, 233 reg_s21, 234 reg_s22, 235 reg_s23, 236 reg_s24, 237 reg_s25, 238 reg_s26, 239 reg_s27, 240 reg_s28, 241 reg_s29, 242 reg_s30, 243 reg_s31, 244 reg_h0, 245 reg_h1, 246 reg_h2, 247 reg_h3, 248 reg_h4, 249 reg_h5, 250 reg_h6, 251 reg_h7, 252 reg_h8, 253 reg_h9, 254 reg_h10, 255 reg_h11, 256 reg_h12, 257 reg_h13, 258 reg_h14, 259 reg_h15, 260 reg_h16, 261 reg_h17, 262 reg_h18, 263 reg_h19, 264 reg_h20, 265 reg_h21, 266 reg_h22, 267 reg_h23, 268 reg_h24, 269 reg_h25, 270 reg_h26, 271 reg_h27, 272 reg_h28, 273 reg_h29, 274 reg_h30, 275 reg_h31, 276 k_num_regs 277 }; 278 279 // Register info definitions for this register context 280 static RegisterInfo g_reg_infos[] = { 281 DEF_X_ARG(0, 1), 282 DEF_X_ARG(1, 2), 283 DEF_X_ARG(2, 3), 284 DEF_X_ARG(3, 4), 285 DEF_X_ARG(4, 5), 286 DEF_X_ARG(5, 6), 287 DEF_X_ARG(6, 7), 288 DEF_X_ARG(7, 8), 289 DEF_X(8), 290 DEF_X(9), 291 DEF_X(10), 292 DEF_X(11), 293 DEF_X(12), 294 DEF_X(13), 295 DEF_X(14), 296 DEF_X(15), 297 DEF_X(16), 298 DEF_X(17), 299 DEF_X(18), 300 DEF_X(19), 301 DEF_X(20), 302 DEF_X(21), 303 DEF_X(22), 304 DEF_X(23), 305 DEF_X(24), 306 DEF_X(25), 307 DEF_X(26), 308 DEF_X(27), 309 DEF_X(28), 310 {"fp", 311 "x29", 312 8, 313 OFFSET(x) + 29 * 8, 314 eEncodingUint, 315 eFormatHex, 316 {arm64_dwarf::x29, arm64_dwarf::x29, LLDB_REGNUM_GENERIC_FP, INV, reg_fp}, 317 nullptr, 318 nullptr, 319 }, 320 {"lr", 321 "x30", 322 8, 323 OFFSET(x) + 30 * 8, 324 eEncodingUint, 325 eFormatHex, 326 {arm64_dwarf::x30, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, INV, reg_lr}, 327 nullptr, 328 nullptr, 329 }, 330 {"sp", 331 "x31", 332 8, 333 OFFSET(x) + 31 * 8, 334 eEncodingUint, 335 eFormatHex, 336 {arm64_dwarf::x31, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, INV, reg_sp}, 337 nullptr, 338 nullptr, 339 }, 340 {"pc", 341 nullptr, 342 8, 343 OFFSET(pc), 344 eEncodingUint, 345 eFormatHex, 346 {arm64_dwarf::pc, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc}, 347 nullptr, 348 nullptr, 349 }, 350 // w0 - w31 351 DEF_W(0), 352 DEF_W(1), 353 DEF_W(2), 354 DEF_W(3), 355 DEF_W(4), 356 DEF_W(5), 357 DEF_W(6), 358 DEF_W(7), 359 DEF_W(8), 360 DEF_W(9), 361 DEF_W(10), 362 DEF_W(11), 363 DEF_W(12), 364 DEF_W(13), 365 DEF_W(14), 366 DEF_W(15), 367 DEF_W(16), 368 DEF_W(17), 369 DEF_W(18), 370 DEF_W(19), 371 DEF_W(20), 372 DEF_W(21), 373 DEF_W(22), 374 DEF_W(23), 375 DEF_W(24), 376 DEF_W(25), 377 DEF_W(26), 378 DEF_W(27), 379 DEF_W(28), 380 DEF_W(29), 381 DEF_W(30), 382 DEF_W(31), 383 {"cpsr", 384 "psr", 385 4, 386 OFFSET(cpsr), 387 eEncodingUint, 388 eFormatHex, 389 {INV, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr}, 390 nullptr, 391 nullptr, 392 }, 393 {"fpsr", 394 nullptr, 395 4, 396 OFFSET(fpsr), 397 eEncodingUint, 398 eFormatHex, 399 {INV, INV, INV, INV, reg_fpsr}, 400 nullptr, 401 nullptr, 402 }, 403 {"fpcr", 404 nullptr, 405 4, 406 OFFSET(fpcr), 407 eEncodingUint, 408 eFormatHex, 409 {INV, INV, INV, INV, reg_fpcr}, 410 nullptr, 411 nullptr, 412 }, 413 // v0 - v31 414 DEF_V(0), 415 DEF_V(1), 416 DEF_V(2), 417 DEF_V(3), 418 DEF_V(4), 419 DEF_V(5), 420 DEF_V(6), 421 DEF_V(7), 422 DEF_V(8), 423 DEF_V(9), 424 DEF_V(10), 425 DEF_V(11), 426 DEF_V(12), 427 DEF_V(13), 428 DEF_V(14), 429 DEF_V(15), 430 DEF_V(16), 431 DEF_V(17), 432 DEF_V(18), 433 DEF_V(19), 434 DEF_V(20), 435 DEF_V(21), 436 DEF_V(22), 437 DEF_V(23), 438 DEF_V(24), 439 DEF_V(25), 440 DEF_V(26), 441 DEF_V(27), 442 DEF_V(28), 443 DEF_V(29), 444 DEF_V(30), 445 DEF_V(31), 446 // d0 - d31 447 DEF_D(0), 448 DEF_D(1), 449 DEF_D(2), 450 DEF_D(3), 451 DEF_D(4), 452 DEF_D(5), 453 DEF_D(6), 454 DEF_D(7), 455 DEF_D(8), 456 DEF_D(9), 457 DEF_D(10), 458 DEF_D(11), 459 DEF_D(12), 460 DEF_D(13), 461 DEF_D(14), 462 DEF_D(15), 463 DEF_D(16), 464 DEF_D(17), 465 DEF_D(18), 466 DEF_D(19), 467 DEF_D(20), 468 DEF_D(21), 469 DEF_D(22), 470 DEF_D(23), 471 DEF_D(24), 472 DEF_D(25), 473 DEF_D(26), 474 DEF_D(27), 475 DEF_D(28), 476 DEF_D(29), 477 DEF_D(30), 478 DEF_D(31), 479 // s0 - s31 480 DEF_S(0), 481 DEF_S(1), 482 DEF_S(2), 483 DEF_S(3), 484 DEF_S(4), 485 DEF_S(5), 486 DEF_S(6), 487 DEF_S(7), 488 DEF_S(8), 489 DEF_S(9), 490 DEF_S(10), 491 DEF_S(11), 492 DEF_S(12), 493 DEF_S(13), 494 DEF_S(14), 495 DEF_S(15), 496 DEF_S(16), 497 DEF_S(17), 498 DEF_S(18), 499 DEF_S(19), 500 DEF_S(20), 501 DEF_S(21), 502 DEF_S(22), 503 DEF_S(23), 504 DEF_S(24), 505 DEF_S(25), 506 DEF_S(26), 507 DEF_S(27), 508 DEF_S(28), 509 DEF_S(29), 510 DEF_S(30), 511 DEF_S(31), 512 // h0 - h31 513 DEF_H(0), 514 DEF_H(1), 515 DEF_H(2), 516 DEF_H(3), 517 DEF_H(4), 518 DEF_H(5), 519 DEF_H(6), 520 DEF_H(7), 521 DEF_H(8), 522 DEF_H(9), 523 DEF_H(10), 524 DEF_H(11), 525 DEF_H(12), 526 DEF_H(13), 527 DEF_H(14), 528 DEF_H(15), 529 DEF_H(16), 530 DEF_H(17), 531 DEF_H(18), 532 DEF_H(19), 533 DEF_H(20), 534 DEF_H(21), 535 DEF_H(22), 536 DEF_H(23), 537 DEF_H(24), 538 DEF_H(25), 539 DEF_H(26), 540 DEF_H(27), 541 DEF_H(28), 542 DEF_H(29), 543 DEF_H(30), 544 DEF_H(31), 545 }; 546 547 constexpr size_t k_num_reg_infos = llvm::array_lengthof(g_reg_infos); 548 549 // ARM64 general purpose registers. 550 const uint32_t g_gpr_regnums[] = { 551 reg_x0, 552 reg_x1, 553 reg_x2, 554 reg_x3, 555 reg_x4, 556 reg_x5, 557 reg_x6, 558 reg_x7, 559 reg_x8, 560 reg_x9, 561 reg_x10, 562 reg_x11, 563 reg_x12, 564 reg_x13, 565 reg_x14, 566 reg_x15, 567 reg_x16, 568 reg_x17, 569 reg_x18, 570 reg_x19, 571 reg_x20, 572 reg_x21, 573 reg_x22, 574 reg_x23, 575 reg_x24, 576 reg_x25, 577 reg_x26, 578 reg_x27, 579 reg_x28, 580 reg_fp, 581 reg_lr, 582 reg_sp, 583 reg_w0, 584 reg_w1, 585 reg_w2, 586 reg_w3, 587 reg_w4, 588 reg_w5, 589 reg_w6, 590 reg_w7, 591 reg_w8, 592 reg_w9, 593 reg_w10, 594 reg_w11, 595 reg_w12, 596 reg_w13, 597 reg_w14, 598 reg_w15, 599 reg_w16, 600 reg_w17, 601 reg_w18, 602 reg_w19, 603 reg_w20, 604 reg_w21, 605 reg_w22, 606 reg_w23, 607 reg_w24, 608 reg_w25, 609 reg_w26, 610 reg_w27, 611 reg_w28, 612 reg_w29, 613 reg_w30, 614 reg_w31, 615 reg_pc, 616 reg_cpsr, 617 LLDB_INVALID_REGNUM // register sets need to end with this flag 618 }; 619 const uint32_t g_fpu_regnums[] = { 620 reg_v0, 621 reg_v1, 622 reg_v2, 623 reg_v3, 624 reg_v4, 625 reg_v5, 626 reg_v6, 627 reg_v7, 628 reg_v8, 629 reg_v9, 630 reg_v10, 631 reg_v11, 632 reg_v12, 633 reg_v13, 634 reg_v14, 635 reg_v15, 636 reg_v16, 637 reg_v17, 638 reg_v18, 639 reg_v19, 640 reg_v20, 641 reg_v21, 642 reg_v22, 643 reg_v23, 644 reg_v24, 645 reg_v25, 646 reg_v26, 647 reg_v27, 648 reg_v28, 649 reg_v29, 650 reg_v30, 651 reg_v31, 652 reg_d0, 653 reg_d1, 654 reg_d2, 655 reg_d3, 656 reg_d4, 657 reg_d5, 658 reg_d6, 659 reg_d7, 660 reg_d8, 661 reg_d9, 662 reg_d10, 663 reg_d11, 664 reg_d12, 665 reg_d13, 666 reg_d14, 667 reg_d15, 668 reg_d16, 669 reg_d17, 670 reg_d18, 671 reg_d19, 672 reg_d20, 673 reg_d21, 674 reg_d22, 675 reg_d23, 676 reg_d24, 677 reg_d25, 678 reg_d26, 679 reg_d27, 680 reg_d28, 681 reg_d29, 682 reg_d30, 683 reg_d31, 684 reg_s0, 685 reg_s1, 686 reg_s2, 687 reg_s3, 688 reg_s4, 689 reg_s5, 690 reg_s6, 691 reg_s7, 692 reg_s8, 693 reg_s9, 694 reg_s10, 695 reg_s11, 696 reg_s12, 697 reg_s13, 698 reg_s14, 699 reg_s15, 700 reg_s16, 701 reg_s17, 702 reg_s18, 703 reg_s19, 704 reg_s20, 705 reg_s21, 706 reg_s22, 707 reg_s23, 708 reg_s24, 709 reg_s25, 710 reg_s26, 711 reg_s27, 712 reg_s28, 713 reg_s29, 714 reg_s30, 715 reg_s31, 716 reg_h0, 717 reg_h1, 718 reg_h2, 719 reg_h3, 720 reg_h4, 721 reg_h5, 722 reg_h6, 723 reg_h7, 724 reg_h8, 725 reg_h9, 726 reg_h10, 727 reg_h11, 728 reg_h12, 729 reg_h13, 730 reg_h14, 731 reg_h15, 732 reg_h16, 733 reg_h17, 734 reg_h18, 735 reg_h19, 736 reg_h20, 737 reg_h21, 738 reg_h22, 739 reg_h23, 740 reg_h24, 741 reg_h25, 742 reg_h26, 743 reg_h27, 744 reg_h28, 745 reg_h29, 746 reg_h30, 747 reg_h31, 748 reg_fpsr, 749 reg_fpcr, 750 LLDB_INVALID_REGNUM // register sets need to end with this flag 751 }; 752 753 // Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1 754 constexpr size_t k_num_gpr_regs = llvm::array_lengthof(g_gpr_regnums) - 1; 755 constexpr size_t k_num_fpu_regs = llvm::array_lengthof(g_fpu_regnums) - 1; 756 757 static RegisterSet g_reg_sets[] = { 758 {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums}, 759 {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums}, 760 }; 761 762 constexpr size_t k_num_reg_sets = llvm::array_lengthof(g_reg_sets); 763 764 RegisterContextMinidump_ARM64::RegisterContextMinidump_ARM64( 765 lldb_private::Thread &thread, const DataExtractor &data) 766 : RegisterContext(thread, 0) { 767 lldb::offset_t offset = 0; 768 m_regs.context_flags = data.GetU64(&offset); 769 for (unsigned i = 0; i < 32; ++i) 770 m_regs.x[i] = data.GetU64(&offset); 771 m_regs.pc = data.GetU64(&offset); 772 m_regs.cpsr = data.GetU32(&offset); 773 m_regs.fpsr = data.GetU32(&offset); 774 m_regs.fpcr = data.GetU32(&offset); 775 auto regs_data = data.GetData(&offset, sizeof(m_regs.v)); 776 if (regs_data) 777 memcpy(m_regs.v, regs_data, sizeof(m_regs.v)); 778 static_assert(k_num_regs == k_num_reg_infos, ""); 779 } 780 size_t RegisterContextMinidump_ARM64::GetRegisterCount() { return k_num_regs; } 781 782 const RegisterInfo * 783 RegisterContextMinidump_ARM64::GetRegisterInfoAtIndex(size_t reg) { 784 if (reg < k_num_reg_infos) 785 return &g_reg_infos[reg]; 786 return nullptr; 787 } 788 789 size_t RegisterContextMinidump_ARM64::GetRegisterSetCount() { 790 return k_num_reg_sets; 791 } 792 793 const RegisterSet *RegisterContextMinidump_ARM64::GetRegisterSet(size_t set) { 794 if (set < k_num_reg_sets) 795 return &g_reg_sets[set]; 796 return nullptr; 797 } 798 799 const char *RegisterContextMinidump_ARM64::GetRegisterName(unsigned reg) { 800 if (reg < k_num_reg_infos) 801 return g_reg_infos[reg].name; 802 return nullptr; 803 } 804 805 bool RegisterContextMinidump_ARM64::ReadRegister(const RegisterInfo *reg_info, 806 RegisterValue ®_value) { 807 Status error; 808 reg_value.SetFromMemoryData( 809 reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset, 810 reg_info->byte_size, lldb::eByteOrderLittle, error); 811 return error.Success(); 812 } 813 814 bool RegisterContextMinidump_ARM64::WriteRegister(const RegisterInfo *, 815 const RegisterValue &) { 816 return false; 817 } 818 819 uint32_t RegisterContextMinidump_ARM64::ConvertRegisterKindToRegisterNumber( 820 lldb::RegisterKind kind, uint32_t num) { 821 for (size_t i = 0; i < k_num_regs; ++i) { 822 if (g_reg_infos[i].kinds[kind] == num) 823 return i; 824 } 825 return LLDB_INVALID_REGNUM; 826 } 827