Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp
39653 views
//===-- AArch66.h ---------------------------------------------------------===//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 "lldb/lldb-types.h"910#include "ABIAArch64.h"11#ifdef LLDB_ENABLE_ALL12#include "ABIMacOSX_arm64.h"13#endif // LLDB_ENABLE_ALL14#include "ABISysV_arm64.h"15#include "Utility/ARM64_DWARF_Registers.h"16#include "lldb/Core/PluginManager.h"17#include "lldb/Target/Process.h"1819#include <bitset>20#include <optional>2122using namespace lldb;2324LLDB_PLUGIN_DEFINE(ABIAArch64)2526void ABIAArch64::Initialize() {27ABISysV_arm64::Initialize();28#ifdef LLDB_ENABLE_ALL29ABIMacOSX_arm64::Initialize();30#endif // LLDB_ENABLE_ALL31}3233void ABIAArch64::Terminate() {34ABISysV_arm64::Terminate();35#ifdef LLDB_ENABLE_ALL36ABIMacOSX_arm64::Terminate();37#endif // LLDB_ENABLE_ALL38}3940lldb::addr_t ABIAArch64::FixCodeAddress(lldb::addr_t pc) {41if (lldb::ProcessSP process_sp = GetProcessSP()) {42// b55 is the highest bit outside TBI (if it's enabled), use43// it to determine if the high bits are set to 0 or 1.44const addr_t pac_sign_extension = 0x0080000000000000ULL;45addr_t mask = process_sp->GetCodeAddressMask();46// Test if the high memory mask has been overriden separately47if (pc & pac_sign_extension &&48process_sp->GetHighmemCodeAddressMask() != LLDB_INVALID_ADDRESS_MASK)49mask = process_sp->GetHighmemCodeAddressMask();5051if (mask != LLDB_INVALID_ADDRESS_MASK)52return FixAddress(pc, mask);53}54return pc;55}5657lldb::addr_t ABIAArch64::FixDataAddress(lldb::addr_t pc) {58if (lldb::ProcessSP process_sp = GetProcessSP()) {59// b55 is the highest bit outside TBI (if it's enabled), use60// it to determine if the high bits are set to 0 or 1.61const addr_t pac_sign_extension = 0x0080000000000000ULL;62addr_t mask = process_sp->GetDataAddressMask();63// Test if the high memory mask has been overriden separately64if (pc & pac_sign_extension &&65process_sp->GetHighmemDataAddressMask() != LLDB_INVALID_ADDRESS_MASK)66mask = process_sp->GetHighmemDataAddressMask();67if (mask != LLDB_INVALID_ADDRESS_MASK)68return FixAddress(pc, mask);69}70return pc;71}7273std::pair<uint32_t, uint32_t>74ABIAArch64::GetEHAndDWARFNums(llvm::StringRef name) {75if (name == "pc")76return {LLDB_INVALID_REGNUM, arm64_dwarf::pc};77if (name == "cpsr")78return {LLDB_INVALID_REGNUM, arm64_dwarf::cpsr};79return MCBasedABI::GetEHAndDWARFNums(name);80}8182std::string ABIAArch64::GetMCName(std::string reg) {83MapRegisterName(reg, "v", "q");84MapRegisterName(reg, "x29", "fp");85MapRegisterName(reg, "x30", "lr");86return reg;87}8889uint32_t ABIAArch64::GetGenericNum(llvm::StringRef name) {90return llvm::StringSwitch<uint32_t>(name)91.Case("pc", LLDB_REGNUM_GENERIC_PC)92.Cases("lr", "x30", LLDB_REGNUM_GENERIC_RA)93.Cases("sp", "x31", LLDB_REGNUM_GENERIC_SP)94.Cases("fp", "x29", LLDB_REGNUM_GENERIC_FP)95.Case("cpsr", LLDB_REGNUM_GENERIC_FLAGS)96.Case("x0", LLDB_REGNUM_GENERIC_ARG1)97.Case("x1", LLDB_REGNUM_GENERIC_ARG2)98.Case("x2", LLDB_REGNUM_GENERIC_ARG3)99.Case("x3", LLDB_REGNUM_GENERIC_ARG4)100.Case("x4", LLDB_REGNUM_GENERIC_ARG5)101.Case("x5", LLDB_REGNUM_GENERIC_ARG6)102.Case("x6", LLDB_REGNUM_GENERIC_ARG7)103.Case("x7", LLDB_REGNUM_GENERIC_ARG8)104.Default(LLDB_INVALID_REGNUM);105}106107static void addPartialRegisters(108std::vector<lldb_private::DynamicRegisterInfo::Register> ®s,109llvm::ArrayRef<std::optional<uint32_t>> full_reg_indices,110uint32_t full_reg_size, const char *partial_reg_format,111uint32_t partial_reg_size, lldb::Encoding encoding, lldb::Format format) {112for (auto it : llvm::enumerate(full_reg_indices)) {113std::optional<uint32_t> full_reg_index = it.value();114if (!full_reg_index || regs[*full_reg_index].byte_size != full_reg_size)115return;116117lldb_private::DynamicRegisterInfo::Register partial_reg{118lldb_private::ConstString(119llvm::formatv(partial_reg_format, it.index()).str()),120lldb_private::ConstString(),121lldb_private::ConstString("supplementary registers"),122partial_reg_size,123LLDB_INVALID_INDEX32,124encoding,125format,126LLDB_INVALID_REGNUM,127LLDB_INVALID_REGNUM,128LLDB_INVALID_REGNUM,129LLDB_INVALID_REGNUM,130{*full_reg_index},131{}};132addSupplementaryRegister(regs, partial_reg);133}134}135136void ABIAArch64::AugmentRegisterInfo(137std::vector<lldb_private::DynamicRegisterInfo::Register> ®s) {138lldb_private::MCBasedABI::AugmentRegisterInfo(regs);139140lldb_private::ConstString sp_string{"sp"};141142std::array<std::optional<uint32_t>, 32> x_regs;143std::array<std::optional<uint32_t>, 32> v_regs;144145for (auto it : llvm::enumerate(regs)) {146lldb_private::DynamicRegisterInfo::Register &info = it.value();147// GDB sends x31 as "sp". Add the "x31" alt_name for convenience.148if (info.name == sp_string && !info.alt_name)149info.alt_name.SetCString("x31");150151unsigned int reg_num;152auto get_reg = [&info, ®_num](const char *prefix) {153llvm::StringRef reg_name = info.name.GetStringRef();154llvm::StringRef alt_name = info.alt_name.GetStringRef();155return (reg_name.consume_front(prefix) &&156llvm::to_integer(reg_name, reg_num, 10) && reg_num < 32) ||157(alt_name.consume_front(prefix) &&158llvm::to_integer(alt_name, reg_num, 10) && reg_num < 32);159};160161if (get_reg("x"))162x_regs[reg_num] = it.index();163else if (get_reg("v"))164v_regs[reg_num] = it.index();165// if we have at least one subregister, abort166else if (get_reg("w") || get_reg("s") || get_reg("d"))167return;168}169170// Create aliases for partial registers: wN for xN, and sN/dN for vN.171addPartialRegisters(regs, x_regs, 8, "w{0}", 4, lldb::eEncodingUint,172lldb::eFormatHex);173addPartialRegisters(regs, v_regs, 16, "s{0}", 4, lldb::eEncodingIEEE754,174lldb::eFormatFloat);175addPartialRegisters(regs, v_regs, 16, "d{0}", 8, lldb::eEncodingIEEE754,176lldb::eFormatFloat);177}178179180