551 lines · cpp
1//===-- RegisterContextMinidump_ARM.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_ARM.h"10 11#include "Utility/ARM_DWARF_Registers.h"12#include "Utility/ARM_ehframe_Registers.h"13#include "lldb/Utility/RegisterValue.h"14#include "lldb/Utility/DataExtractor.h"15#include "lldb/Utility/LLDBAssert.h"16#include "lldb/lldb-enumerations.h"17 18// C includes19#include <cassert>20 21// C++ includes22 23using namespace lldb;24using namespace lldb_private;25using namespace minidump;26 27#define INV LLDB_INVALID_REGNUM28#define OFFSET(r) (offsetof(RegisterContextMinidump_ARM::Context, r))29 30#define DEF_R(i) \31 { \32 "r" #i, nullptr, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex, \33 {ehframe_r##i, dwarf_r##i, INV, INV, reg_r##i}, nullptr, nullptr, \34 nullptr, \35 }36 37#define DEF_R_ARG(i, n) \38 { \39 "r" #i, "arg" #n, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex, \40 {ehframe_r##i, dwarf_r##i, LLDB_REGNUM_GENERIC_ARG1 + i, INV, \41 reg_r##i}, \42 nullptr, nullptr, nullptr, \43 }44 45#define DEF_D(i) \46 { \47 "d" #i, nullptr, 8, OFFSET(d) + i * 8, eEncodingVector, \48 eFormatVectorOfUInt8, {dwarf_d##i, dwarf_d##i, INV, INV, reg_d##i}, \49 nullptr, nullptr, nullptr, \50 }51 52#define DEF_S(i) \53 { \54 "s" #i, nullptr, 4, OFFSET(s) + i * 4, eEncodingIEEE754, eFormatFloat, \55 {dwarf_s##i, dwarf_s##i, INV, INV, reg_s##i}, nullptr, nullptr, \56 nullptr, \57 }58 59#define DEF_Q(i) \60 { \61 "q" #i, nullptr, 16, OFFSET(q) + i * 16, eEncodingVector, \62 eFormatVectorOfUInt8, {dwarf_q##i, dwarf_q##i, INV, INV, reg_q##i}, \63 nullptr, nullptr, nullptr, \64 }65 66// Zero based LLDB register numbers for this register context67enum {68 // General Purpose Registers69 reg_r0,70 reg_r1,71 reg_r2,72 reg_r3,73 reg_r4,74 reg_r5,75 reg_r6,76 reg_r7,77 reg_r8,78 reg_r9,79 reg_r10,80 reg_r11,81 reg_r12,82 reg_sp,83 reg_lr,84 reg_pc,85 reg_cpsr,86 // Floating Point Registers87 reg_fpscr,88 reg_d0,89 reg_d1,90 reg_d2,91 reg_d3,92 reg_d4,93 reg_d5,94 reg_d6,95 reg_d7,96 reg_d8,97 reg_d9,98 reg_d10,99 reg_d11,100 reg_d12,101 reg_d13,102 reg_d14,103 reg_d15,104 reg_d16,105 reg_d17,106 reg_d18,107 reg_d19,108 reg_d20,109 reg_d21,110 reg_d22,111 reg_d23,112 reg_d24,113 reg_d25,114 reg_d26,115 reg_d27,116 reg_d28,117 reg_d29,118 reg_d30,119 reg_d31,120 reg_s0,121 reg_s1,122 reg_s2,123 reg_s3,124 reg_s4,125 reg_s5,126 reg_s6,127 reg_s7,128 reg_s8,129 reg_s9,130 reg_s10,131 reg_s11,132 reg_s12,133 reg_s13,134 reg_s14,135 reg_s15,136 reg_s16,137 reg_s17,138 reg_s18,139 reg_s19,140 reg_s20,141 reg_s21,142 reg_s22,143 reg_s23,144 reg_s24,145 reg_s25,146 reg_s26,147 reg_s27,148 reg_s28,149 reg_s29,150 reg_s30,151 reg_s31,152 reg_q0,153 reg_q1,154 reg_q2,155 reg_q3,156 reg_q4,157 reg_q5,158 reg_q6,159 reg_q7,160 reg_q8,161 reg_q9,162 reg_q10,163 reg_q11,164 reg_q12,165 reg_q13,166 reg_q14,167 reg_q15,168 k_num_regs169};170 171static RegisterInfo g_reg_info_apple_fp = {172 "fp",173 "r7",174 4,175 OFFSET(r) + 7 * 4,176 eEncodingUint,177 eFormatHex,178 {ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, INV, reg_r7},179 nullptr,180 nullptr,181 nullptr,182};183 184static RegisterInfo g_reg_info_fp = {185 "fp",186 "r11",187 4,188 OFFSET(r) + 11 * 4,189 eEncodingUint,190 eFormatHex,191 {ehframe_r11, dwarf_r11, LLDB_REGNUM_GENERIC_FP, INV, reg_r11},192 nullptr,193 nullptr,194 nullptr,195};196 197// Register info definitions for this register context198static RegisterInfo g_reg_infos[] = {199 DEF_R_ARG(0, 1),200 DEF_R_ARG(1, 2),201 DEF_R_ARG(2, 3),202 DEF_R_ARG(3, 4),203 DEF_R(4),204 DEF_R(5),205 DEF_R(6),206 DEF_R(7),207 DEF_R(8),208 DEF_R(9),209 DEF_R(10),210 DEF_R(11),211 DEF_R(12),212 {"sp",213 "r13",214 4,215 OFFSET(r) + 13 * 4,216 eEncodingUint,217 eFormatHex,218 {ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, INV, reg_sp},219 nullptr,220 nullptr,221 nullptr,222 },223 {"lr",224 "r14",225 4,226 OFFSET(r) + 14 * 4,227 eEncodingUint,228 eFormatHex,229 {ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, INV, reg_lr},230 nullptr,231 nullptr,232 nullptr,233 },234 {"pc",235 "r15",236 4,237 OFFSET(r) + 15 * 4,238 eEncodingUint,239 eFormatHex,240 {ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc},241 nullptr,242 nullptr,243 nullptr,244 },245 {"cpsr",246 "psr",247 4,248 OFFSET(cpsr),249 eEncodingUint,250 eFormatHex,251 {ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr},252 nullptr,253 nullptr,254 nullptr,255 },256 {"fpscr",257 nullptr,258 8,259 OFFSET(fpscr),260 eEncodingUint,261 eFormatHex,262 {INV, INV, INV, INV, reg_fpscr},263 nullptr,264 nullptr,265 nullptr,266 },267 DEF_D(0),268 DEF_D(1),269 DEF_D(2),270 DEF_D(3),271 DEF_D(4),272 DEF_D(5),273 DEF_D(6),274 DEF_D(7),275 DEF_D(8),276 DEF_D(9),277 DEF_D(10),278 DEF_D(11),279 DEF_D(12),280 DEF_D(13),281 DEF_D(14),282 DEF_D(15),283 DEF_D(16),284 DEF_D(17),285 DEF_D(18),286 DEF_D(19),287 DEF_D(20),288 DEF_D(21),289 DEF_D(22),290 DEF_D(23),291 DEF_D(24),292 DEF_D(25),293 DEF_D(26),294 DEF_D(27),295 DEF_D(28),296 DEF_D(29),297 DEF_D(30),298 DEF_D(31),299 DEF_S(0),300 DEF_S(1),301 DEF_S(2),302 DEF_S(3),303 DEF_S(4),304 DEF_S(5),305 DEF_S(6),306 DEF_S(7),307 DEF_S(8),308 DEF_S(9),309 DEF_S(10),310 DEF_S(11),311 DEF_S(12),312 DEF_S(13),313 DEF_S(14),314 DEF_S(15),315 DEF_S(16),316 DEF_S(17),317 DEF_S(18),318 DEF_S(19),319 DEF_S(20),320 DEF_S(21),321 DEF_S(22),322 DEF_S(23),323 DEF_S(24),324 DEF_S(25),325 DEF_S(26),326 DEF_S(27),327 DEF_S(28),328 DEF_S(29),329 DEF_S(30),330 DEF_S(31),331 DEF_Q(0),332 DEF_Q(1),333 DEF_Q(2),334 DEF_Q(3),335 DEF_Q(4),336 DEF_Q(5),337 DEF_Q(6),338 DEF_Q(7),339 DEF_Q(8),340 DEF_Q(9),341 DEF_Q(10),342 DEF_Q(11),343 DEF_Q(12),344 DEF_Q(13),345 DEF_Q(14),346 DEF_Q(15)};347 348constexpr size_t k_num_reg_infos = std::size(g_reg_infos);349 350// ARM general purpose registers.351const uint32_t g_gpr_regnums[] = {352 reg_r0,353 reg_r1,354 reg_r2,355 reg_r3,356 reg_r4,357 reg_r5,358 reg_r6,359 reg_r7,360 reg_r8,361 reg_r9,362 reg_r10,363 reg_r11,364 reg_r12,365 reg_sp,366 reg_lr,367 reg_pc,368 reg_cpsr,369 LLDB_INVALID_REGNUM // register sets need to end with this flag370};371const uint32_t g_fpu_regnums[] = {372 reg_fpscr,373 reg_d0,374 reg_d1,375 reg_d2,376 reg_d3,377 reg_d4,378 reg_d5,379 reg_d6,380 reg_d7,381 reg_d8,382 reg_d9,383 reg_d10,384 reg_d11,385 reg_d12,386 reg_d13,387 reg_d14,388 reg_d15,389 reg_d16,390 reg_d17,391 reg_d18,392 reg_d19,393 reg_d20,394 reg_d21,395 reg_d22,396 reg_d23,397 reg_d24,398 reg_d25,399 reg_d26,400 reg_d27,401 reg_d28,402 reg_d29,403 reg_d30,404 reg_d31,405 reg_s0,406 reg_s1,407 reg_s2,408 reg_s3,409 reg_s4,410 reg_s5,411 reg_s6,412 reg_s7,413 reg_s8,414 reg_s9,415 reg_s10,416 reg_s11,417 reg_s12,418 reg_s13,419 reg_s14,420 reg_s15,421 reg_s16,422 reg_s17,423 reg_s18,424 reg_s19,425 reg_s20,426 reg_s21,427 reg_s22,428 reg_s23,429 reg_s24,430 reg_s25,431 reg_s26,432 reg_s27,433 reg_s28,434 reg_s29,435 reg_s30,436 reg_s31,437 reg_q0,438 reg_q1,439 reg_q2,440 reg_q3,441 reg_q4,442 reg_q5,443 reg_q6,444 reg_q7,445 reg_q8,446 reg_q9,447 reg_q10,448 reg_q11,449 reg_q12,450 reg_q13,451 reg_q14,452 reg_q15,453 LLDB_INVALID_REGNUM // register sets need to end with this flag454};455 456// Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1457constexpr size_t k_num_gpr_regs = std::size(g_gpr_regnums) - 1;458constexpr size_t k_num_fpu_regs = std::size(g_fpu_regnums) - 1;459 460static RegisterSet g_reg_sets[] = {461 {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums},462 {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums},463};464 465constexpr size_t k_num_reg_sets = std::size(g_reg_sets);466 467RegisterContextMinidump_ARM::RegisterContextMinidump_ARM(468 lldb_private::Thread &thread, const DataExtractor &data, bool apple)469 : RegisterContext(thread, 0), m_apple(apple) {470 lldb::offset_t offset = 0;471 m_regs.context_flags = data.GetU32(&offset);472 for (unsigned i = 0; i < std::size(m_regs.r); ++i)473 m_regs.r[i] = data.GetU32(&offset);474 m_regs.cpsr = data.GetU32(&offset);475 m_regs.fpscr = data.GetU64(&offset);476 for (unsigned i = 0; i < std::size(m_regs.d); ++i)477 m_regs.d[i] = data.GetU64(&offset);478 lldbassert(k_num_regs == k_num_reg_infos);479}480 481size_t RegisterContextMinidump_ARM::GetRegisterCountStatic() {482 return k_num_regs;483}484 485// Used for unit testing so we can verify register info is filled in for486// all register flavors (DWARF, EH Frame, generic, etc).487size_t RegisterContextMinidump_ARM::GetRegisterCount() {488 return GetRegisterCountStatic();489}490 491// Used for unit testing so we can verify register info is filled in.492const RegisterInfo *493RegisterContextMinidump_ARM::GetRegisterInfoAtIndexStatic(size_t reg,494 bool apple) {495 if (reg < k_num_reg_infos) {496 if (apple) {497 if (reg == reg_r7)498 return &g_reg_info_apple_fp;499 } else {500 if (reg == reg_r11)501 return &g_reg_info_fp;502 }503 return &g_reg_infos[reg];504 }505 return nullptr;506}507 508const RegisterInfo *509RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) {510 return GetRegisterInfoAtIndexStatic(reg, m_apple);511}512 513size_t RegisterContextMinidump_ARM::GetRegisterSetCount() {514 return k_num_reg_sets;515}516 517const RegisterSet *RegisterContextMinidump_ARM::GetRegisterSet(size_t set) {518 if (set < k_num_reg_sets)519 return &g_reg_sets[set];520 return nullptr;521}522 523const char *RegisterContextMinidump_ARM::GetRegisterName(unsigned reg) {524 if (reg < k_num_reg_infos)525 return g_reg_infos[reg].name;526 return nullptr;527}528 529bool RegisterContextMinidump_ARM::ReadRegister(const RegisterInfo *reg_info,530 RegisterValue ®_value) {531 Status error;532 reg_value.SetFromMemoryData(533 *reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset,534 reg_info->byte_size, lldb::eByteOrderLittle, error);535 return error.Success();536}537 538bool RegisterContextMinidump_ARM::WriteRegister(const RegisterInfo *,539 const RegisterValue &) {540 return false;541}542 543uint32_t RegisterContextMinidump_ARM::ConvertRegisterKindToRegisterNumber(544 lldb::RegisterKind kind, uint32_t num) {545 for (size_t i = 0; i < k_num_regs; ++i) {546 if (g_reg_infos[i].kinds[kind] == num)547 return i;548 }549 return LLDB_INVALID_REGNUM;550}551