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