834 lines · cpp
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-exception6//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 includes17#include <cassert>18 19// C++ includes20 21using namespace lldb;22using namespace lldb_private;23using namespace minidump;24 25#define INV LLDB_INVALID_REGNUM26#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, \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, \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, \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, \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, \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, \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, \74 }75 76// Zero based LLDB register numbers for this register context77enum {78 // General Purpose Registers79 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 Registers146 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_regs277};278 279// Register info definitions for this register context280static 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 },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 },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 },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 },354 // w0 - w31355 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 },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 },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 },420 // v0 - v31421 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 - d31454 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 - s31487 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 - h31520 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 554constexpr size_t k_num_reg_infos = std::size(g_reg_infos);555 556// ARM64 general purpose registers.557const 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 flag625};626const 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 flag758};759 760// Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1761constexpr size_t k_num_gpr_regs = std::size(g_gpr_regnums) - 1;762constexpr size_t k_num_fpu_regs = std::size(g_fpu_regnums) - 1;763 764static 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 769constexpr size_t k_num_reg_sets = std::size(g_reg_sets);770 771RegisterContextMinidump_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}787size_t RegisterContextMinidump_ARM64::GetRegisterCount() { return k_num_regs; }788 789const RegisterInfo *790RegisterContextMinidump_ARM64::GetRegisterInfoAtIndex(size_t reg) {791 if (reg < k_num_reg_infos)792 return &g_reg_infos[reg];793 return nullptr;794}795 796size_t RegisterContextMinidump_ARM64::GetRegisterSetCount() {797 return k_num_reg_sets;798}799 800const 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 806const 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 812bool 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 821bool RegisterContextMinidump_ARM64::WriteRegister(const RegisterInfo *,822 const RegisterValue &) {823 return false;824}825 826uint32_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