1 //===-- RegisterContextMinidump_ARM64.cpp -----------------------*- C++ -*-===// 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 <assert.h> 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, nullptr, 0 \ 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, nullptr, 0 \ 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, nullptr, 0 \ 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, nullptr, 0 \ 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, nullptr, 0 \ 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, nullptr, 0 \ 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, nullptr, 0 \ 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 nullptr, 320 0}, 321 {"lr", 322 "x30", 323 8, 324 OFFSET(x) + 30 * 8, 325 eEncodingUint, 326 eFormatHex, 327 {arm64_dwarf::x30, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, INV, reg_lr}, 328 nullptr, 329 nullptr, 330 nullptr, 331 0}, 332 {"sp", 333 "x31", 334 8, 335 OFFSET(x) + 31 * 8, 336 eEncodingUint, 337 eFormatHex, 338 {arm64_dwarf::x31, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, INV, reg_sp}, 339 nullptr, 340 nullptr, 341 nullptr, 342 0}, 343 {"pc", 344 nullptr, 345 8, 346 OFFSET(pc), 347 eEncodingUint, 348 eFormatHex, 349 {arm64_dwarf::pc, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc}, 350 nullptr, 351 nullptr, 352 nullptr, 353 0}, 354 // w0 - w31 355 DEF_W(0), 356 DEF_W(1), 357 DEF_W(2), 358 DEF_W(3), 359 DEF_W(4), 360 DEF_W(5), 361 DEF_W(6), 362 DEF_W(7), 363 DEF_W(8), 364 DEF_W(9), 365 DEF_W(10), 366 DEF_W(11), 367 DEF_W(12), 368 DEF_W(13), 369 DEF_W(14), 370 DEF_W(15), 371 DEF_W(16), 372 DEF_W(17), 373 DEF_W(18), 374 DEF_W(19), 375 DEF_W(20), 376 DEF_W(21), 377 DEF_W(22), 378 DEF_W(23), 379 DEF_W(24), 380 DEF_W(25), 381 DEF_W(26), 382 DEF_W(27), 383 DEF_W(28), 384 DEF_W(29), 385 DEF_W(30), 386 DEF_W(31), 387 {"cpsr", 388 "psr", 389 4, 390 OFFSET(cpsr), 391 eEncodingUint, 392 eFormatHex, 393 {INV, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr}, 394 nullptr, 395 nullptr, 396 nullptr, 397 0}, 398 {"fpsr", 399 nullptr, 400 4, 401 OFFSET(fpsr), 402 eEncodingUint, 403 eFormatHex, 404 {INV, INV, INV, INV, reg_fpsr}, 405 nullptr, 406 nullptr, 407 nullptr, 408 0}, 409 {"fpcr", 410 nullptr, 411 4, 412 OFFSET(fpcr), 413 eEncodingUint, 414 eFormatHex, 415 {INV, INV, INV, INV, reg_fpcr}, 416 nullptr, 417 nullptr, 418 nullptr, 419 0}, 420 // v0 - v31 421 DEF_V(0), 422 DEF_V(1), 423 DEF_V(2), 424 DEF_V(3), 425 DEF_V(4), 426 DEF_V(5), 427 DEF_V(6), 428 DEF_V(7), 429 DEF_V(8), 430 DEF_V(9), 431 DEF_V(10), 432 DEF_V(11), 433 DEF_V(12), 434 DEF_V(13), 435 DEF_V(14), 436 DEF_V(15), 437 DEF_V(16), 438 DEF_V(17), 439 DEF_V(18), 440 DEF_V(19), 441 DEF_V(20), 442 DEF_V(21), 443 DEF_V(22), 444 DEF_V(23), 445 DEF_V(24), 446 DEF_V(25), 447 DEF_V(26), 448 DEF_V(27), 449 DEF_V(28), 450 DEF_V(29), 451 DEF_V(30), 452 DEF_V(31), 453 // d0 - d31 454 DEF_D(0), 455 DEF_D(1), 456 DEF_D(2), 457 DEF_D(3), 458 DEF_D(4), 459 DEF_D(5), 460 DEF_D(6), 461 DEF_D(7), 462 DEF_D(8), 463 DEF_D(9), 464 DEF_D(10), 465 DEF_D(11), 466 DEF_D(12), 467 DEF_D(13), 468 DEF_D(14), 469 DEF_D(15), 470 DEF_D(16), 471 DEF_D(17), 472 DEF_D(18), 473 DEF_D(19), 474 DEF_D(20), 475 DEF_D(21), 476 DEF_D(22), 477 DEF_D(23), 478 DEF_D(24), 479 DEF_D(25), 480 DEF_D(26), 481 DEF_D(27), 482 DEF_D(28), 483 DEF_D(29), 484 DEF_D(30), 485 DEF_D(31), 486 // s0 - s31 487 DEF_S(0), 488 DEF_S(1), 489 DEF_S(2), 490 DEF_S(3), 491 DEF_S(4), 492 DEF_S(5), 493 DEF_S(6), 494 DEF_S(7), 495 DEF_S(8), 496 DEF_S(9), 497 DEF_S(10), 498 DEF_S(11), 499 DEF_S(12), 500 DEF_S(13), 501 DEF_S(14), 502 DEF_S(15), 503 DEF_S(16), 504 DEF_S(17), 505 DEF_S(18), 506 DEF_S(19), 507 DEF_S(20), 508 DEF_S(21), 509 DEF_S(22), 510 DEF_S(23), 511 DEF_S(24), 512 DEF_S(25), 513 DEF_S(26), 514 DEF_S(27), 515 DEF_S(28), 516 DEF_S(29), 517 DEF_S(30), 518 DEF_S(31), 519 // h0 - h31 520 DEF_H(0), 521 DEF_H(1), 522 DEF_H(2), 523 DEF_H(3), 524 DEF_H(4), 525 DEF_H(5), 526 DEF_H(6), 527 DEF_H(7), 528 DEF_H(8), 529 DEF_H(9), 530 DEF_H(10), 531 DEF_H(11), 532 DEF_H(12), 533 DEF_H(13), 534 DEF_H(14), 535 DEF_H(15), 536 DEF_H(16), 537 DEF_H(17), 538 DEF_H(18), 539 DEF_H(19), 540 DEF_H(20), 541 DEF_H(21), 542 DEF_H(22), 543 DEF_H(23), 544 DEF_H(24), 545 DEF_H(25), 546 DEF_H(26), 547 DEF_H(27), 548 DEF_H(28), 549 DEF_H(29), 550 DEF_H(30), 551 DEF_H(31), 552 }; 553 554 constexpr size_t k_num_reg_infos = llvm::array_lengthof(g_reg_infos); 555 556 // ARM64 general purpose registers. 557 const uint32_t g_gpr_regnums[] = { 558 reg_x0, 559 reg_x1, 560 reg_x2, 561 reg_x3, 562 reg_x4, 563 reg_x5, 564 reg_x6, 565 reg_x7, 566 reg_x8, 567 reg_x9, 568 reg_x10, 569 reg_x11, 570 reg_x12, 571 reg_x13, 572 reg_x14, 573 reg_x15, 574 reg_x16, 575 reg_x17, 576 reg_x18, 577 reg_x19, 578 reg_x20, 579 reg_x21, 580 reg_x22, 581 reg_x23, 582 reg_x24, 583 reg_x25, 584 reg_x26, 585 reg_x27, 586 reg_x28, 587 reg_fp, 588 reg_lr, 589 reg_sp, 590 reg_w0, 591 reg_w1, 592 reg_w2, 593 reg_w3, 594 reg_w4, 595 reg_w5, 596 reg_w6, 597 reg_w7, 598 reg_w8, 599 reg_w9, 600 reg_w10, 601 reg_w11, 602 reg_w12, 603 reg_w13, 604 reg_w14, 605 reg_w15, 606 reg_w16, 607 reg_w17, 608 reg_w18, 609 reg_w19, 610 reg_w20, 611 reg_w21, 612 reg_w22, 613 reg_w23, 614 reg_w24, 615 reg_w25, 616 reg_w26, 617 reg_w27, 618 reg_w28, 619 reg_w29, 620 reg_w30, 621 reg_w31, 622 reg_pc, 623 reg_cpsr, 624 LLDB_INVALID_REGNUM // register sets need to end with this flag 625 }; 626 const uint32_t g_fpu_regnums[] = { 627 reg_v0, 628 reg_v1, 629 reg_v2, 630 reg_v3, 631 reg_v4, 632 reg_v5, 633 reg_v6, 634 reg_v7, 635 reg_v8, 636 reg_v9, 637 reg_v10, 638 reg_v11, 639 reg_v12, 640 reg_v13, 641 reg_v14, 642 reg_v15, 643 reg_v16, 644 reg_v17, 645 reg_v18, 646 reg_v19, 647 reg_v20, 648 reg_v21, 649 reg_v22, 650 reg_v23, 651 reg_v24, 652 reg_v25, 653 reg_v26, 654 reg_v27, 655 reg_v28, 656 reg_v29, 657 reg_v30, 658 reg_v31, 659 reg_d0, 660 reg_d1, 661 reg_d2, 662 reg_d3, 663 reg_d4, 664 reg_d5, 665 reg_d6, 666 reg_d7, 667 reg_d8, 668 reg_d9, 669 reg_d10, 670 reg_d11, 671 reg_d12, 672 reg_d13, 673 reg_d14, 674 reg_d15, 675 reg_d16, 676 reg_d17, 677 reg_d18, 678 reg_d19, 679 reg_d20, 680 reg_d21, 681 reg_d22, 682 reg_d23, 683 reg_d24, 684 reg_d25, 685 reg_d26, 686 reg_d27, 687 reg_d28, 688 reg_d29, 689 reg_d30, 690 reg_d31, 691 reg_s0, 692 reg_s1, 693 reg_s2, 694 reg_s3, 695 reg_s4, 696 reg_s5, 697 reg_s6, 698 reg_s7, 699 reg_s8, 700 reg_s9, 701 reg_s10, 702 reg_s11, 703 reg_s12, 704 reg_s13, 705 reg_s14, 706 reg_s15, 707 reg_s16, 708 reg_s17, 709 reg_s18, 710 reg_s19, 711 reg_s20, 712 reg_s21, 713 reg_s22, 714 reg_s23, 715 reg_s24, 716 reg_s25, 717 reg_s26, 718 reg_s27, 719 reg_s28, 720 reg_s29, 721 reg_s30, 722 reg_s31, 723 reg_h0, 724 reg_h1, 725 reg_h2, 726 reg_h3, 727 reg_h4, 728 reg_h5, 729 reg_h6, 730 reg_h7, 731 reg_h8, 732 reg_h9, 733 reg_h10, 734 reg_h11, 735 reg_h12, 736 reg_h13, 737 reg_h14, 738 reg_h15, 739 reg_h16, 740 reg_h17, 741 reg_h18, 742 reg_h19, 743 reg_h20, 744 reg_h21, 745 reg_h22, 746 reg_h23, 747 reg_h24, 748 reg_h25, 749 reg_h26, 750 reg_h27, 751 reg_h28, 752 reg_h29, 753 reg_h30, 754 reg_h31, 755 reg_fpsr, 756 reg_fpcr, 757 LLDB_INVALID_REGNUM // register sets need to end with this flag 758 }; 759 760 // Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1 761 constexpr size_t k_num_gpr_regs = llvm::array_lengthof(g_gpr_regnums) - 1; 762 constexpr size_t k_num_fpu_regs = llvm::array_lengthof(g_fpu_regnums) - 1; 763 764 static RegisterSet g_reg_sets[] = { 765 {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums}, 766 {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums}, 767 }; 768 769 constexpr size_t k_num_reg_sets = llvm::array_lengthof(g_reg_sets); 770 771 RegisterContextMinidump_ARM64::RegisterContextMinidump_ARM64( 772 lldb_private::Thread &thread, const DataExtractor &data) 773 : RegisterContext(thread, 0) { 774 lldb::offset_t offset = 0; 775 m_regs.context_flags = data.GetU64(&offset); 776 for (unsigned i = 0; i < 32; ++i) 777 m_regs.x[i] = data.GetU64(&offset); 778 m_regs.pc = data.GetU64(&offset); 779 m_regs.cpsr = data.GetU32(&offset); 780 m_regs.fpsr = data.GetU32(&offset); 781 m_regs.fpcr = data.GetU32(&offset); 782 auto regs_data = data.GetData(&offset, sizeof(m_regs.v)); 783 if (regs_data) 784 memcpy(m_regs.v, regs_data, sizeof(m_regs.v)); 785 static_assert(k_num_regs == k_num_reg_infos, ""); 786 } 787 size_t RegisterContextMinidump_ARM64::GetRegisterCount() { return k_num_regs; } 788 789 const RegisterInfo * 790 RegisterContextMinidump_ARM64::GetRegisterInfoAtIndex(size_t reg) { 791 if (reg < k_num_reg_infos) 792 return &g_reg_infos[reg]; 793 return nullptr; 794 } 795 796 size_t RegisterContextMinidump_ARM64::GetRegisterSetCount() { 797 return k_num_reg_sets; 798 } 799 800 const RegisterSet *RegisterContextMinidump_ARM64::GetRegisterSet(size_t set) { 801 if (set < k_num_reg_sets) 802 return &g_reg_sets[set]; 803 return nullptr; 804 } 805 806 const char *RegisterContextMinidump_ARM64::GetRegisterName(unsigned reg) { 807 if (reg < k_num_reg_infos) 808 return g_reg_infos[reg].name; 809 return nullptr; 810 } 811 812 bool RegisterContextMinidump_ARM64::ReadRegister(const RegisterInfo *reg_info, 813 RegisterValue ®_value) { 814 Status error; 815 reg_value.SetFromMemoryData( 816 reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset, 817 reg_info->byte_size, lldb::eByteOrderLittle, error); 818 return error.Success(); 819 } 820 821 bool RegisterContextMinidump_ARM64::WriteRegister(const RegisterInfo *, 822 const RegisterValue &) { 823 return false; 824 } 825 826 uint32_t RegisterContextMinidump_ARM64::ConvertRegisterKindToRegisterNumber( 827 lldb::RegisterKind kind, uint32_t num) { 828 for (size_t i = 0; i < k_num_regs; ++i) { 829 if (g_reg_infos[i].kinds[kind] == num) 830 return i; 831 } 832 return LLDB_INVALID_REGNUM; 833 } 834