brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.0 KiB · 8bfb432 Raw
246 lines · cpp
1//===-- AArch66.h ---------------------------------------------------------===//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 "lldb/lldb-types.h"10 11#include "ABIAArch64.h"12#include "ABIMacOSX_arm64.h"13#include "ABISysV_arm64.h"14#include "Utility/ARM64_DWARF_Registers.h"15#include "Utility/ARM64_ehframe_Registers.h"16#include "lldb/Core/PluginManager.h"17#include "lldb/Target/Process.h"18 19#include <bitset>20#include <optional>21 22using namespace lldb;23using namespace lldb_private;24 25LLDB_PLUGIN_DEFINE(ABIAArch64)26 27void ABIAArch64::Initialize() {28  ABISysV_arm64::Initialize();29  ABIMacOSX_arm64::Initialize();30}31 32void ABIAArch64::Terminate() {33  ABISysV_arm64::Terminate();34  ABIMacOSX_arm64::Terminate();35}36 37lldb::addr_t ABIAArch64::FixCodeAddress(lldb::addr_t pc) {38  if (lldb::ProcessSP process_sp = GetProcessSP()) {39    // b55 is the highest bit outside TBI (if it's enabled), use40    // it to determine if the high bits are set to 0 or 1.41    const addr_t pac_sign_extension = 0x0080000000000000ULL;42    addr_t mask = process_sp->GetCodeAddressMask();43    // Test if the high memory mask has been overriden separately44    if (pc & pac_sign_extension &&45        process_sp->GetHighmemCodeAddressMask() != LLDB_INVALID_ADDRESS_MASK)46      mask = process_sp->GetHighmemCodeAddressMask();47 48    if (mask != LLDB_INVALID_ADDRESS_MASK)49      return FixAddress(pc, mask);50  }51  return pc;52}53 54lldb::addr_t ABIAArch64::FixDataAddress(lldb::addr_t pc) {55  if (lldb::ProcessSP process_sp = GetProcessSP()) {56    // b55 is the highest bit outside TBI (if it's enabled), use57    // it to determine if the high bits are set to 0 or 1.58    const addr_t pac_sign_extension = 0x0080000000000000ULL;59    addr_t mask = process_sp->GetDataAddressMask();60    // Test if the high memory mask has been overriden separately61    if (pc & pac_sign_extension &&62        process_sp->GetHighmemDataAddressMask() != LLDB_INVALID_ADDRESS_MASK)63      mask = process_sp->GetHighmemDataAddressMask();64    if (mask != LLDB_INVALID_ADDRESS_MASK)65      return FixAddress(pc, mask);66  }67  return pc;68}69 70std::pair<uint32_t, uint32_t>71ABIAArch64::GetEHAndDWARFNums(llvm::StringRef name) {72  if (name == "pc")73    return {arm64_ehframe::pc, arm64_dwarf::pc};74  if (name == "cpsr")75    return {arm64_ehframe::cpsr, arm64_dwarf::cpsr};76  return MCBasedABI::GetEHAndDWARFNums(name);77}78 79std::string ABIAArch64::GetMCName(std::string reg) {80  MapRegisterName(reg, "v", "q");81  MapRegisterName(reg, "x29", "fp");82  MapRegisterName(reg, "x30", "lr");83  return reg;84}85 86uint32_t ABIAArch64::GetGenericNum(llvm::StringRef name) {87  return llvm::StringSwitch<uint32_t>(name)88      .Case("pc", LLDB_REGNUM_GENERIC_PC)89      .Cases({"lr", "x30"}, LLDB_REGNUM_GENERIC_RA)90      .Cases({"sp", "x31"}, LLDB_REGNUM_GENERIC_SP)91      .Cases({"fp", "x29"}, LLDB_REGNUM_GENERIC_FP)92      .Case("cpsr", LLDB_REGNUM_GENERIC_FLAGS)93      .Case("x0", LLDB_REGNUM_GENERIC_ARG1)94      .Case("x1", LLDB_REGNUM_GENERIC_ARG2)95      .Case("x2", LLDB_REGNUM_GENERIC_ARG3)96      .Case("x3", LLDB_REGNUM_GENERIC_ARG4)97      .Case("x4", LLDB_REGNUM_GENERIC_ARG5)98      .Case("x5", LLDB_REGNUM_GENERIC_ARG6)99      .Case("x6", LLDB_REGNUM_GENERIC_ARG7)100      .Case("x7", LLDB_REGNUM_GENERIC_ARG8)101      .Default(LLDB_INVALID_REGNUM);102}103 104static void addPartialRegisters(105    std::vector<lldb_private::DynamicRegisterInfo::Register> &regs,106    llvm::ArrayRef<std::optional<uint32_t>> full_reg_indices,107    uint32_t full_reg_size, const char *partial_reg_format,108    uint32_t partial_reg_size, lldb::Encoding encoding, lldb::Format format) {109  for (auto it : llvm::enumerate(full_reg_indices)) {110    std::optional<uint32_t> full_reg_index = it.value();111    if (!full_reg_index || regs[*full_reg_index].byte_size != full_reg_size)112      return;113 114    lldb_private::DynamicRegisterInfo::Register partial_reg{115        lldb_private::ConstString(116            llvm::formatv(partial_reg_format, it.index()).str()),117        lldb_private::ConstString(),118        lldb_private::ConstString("supplementary registers"),119        partial_reg_size,120        LLDB_INVALID_INDEX32,121        encoding,122        format,123        LLDB_INVALID_REGNUM,124        LLDB_INVALID_REGNUM,125        LLDB_INVALID_REGNUM,126        LLDB_INVALID_REGNUM,127        {*full_reg_index},128        {}};129    addSupplementaryRegister(regs, partial_reg);130  }131}132 133void ABIAArch64::AugmentRegisterInfo(134    std::vector<lldb_private::DynamicRegisterInfo::Register> &regs) {135  lldb_private::MCBasedABI::AugmentRegisterInfo(regs);136 137  lldb_private::ConstString sp_string{"sp"};138 139  std::array<std::optional<uint32_t>, 32> x_regs;140  std::array<std::optional<uint32_t>, 32> v_regs;141  std::array<std::optional<uint32_t>, 32> z_regs;142  std::optional<uint32_t> z_byte_size;143 144  for (auto it : llvm::enumerate(regs)) {145    lldb_private::DynamicRegisterInfo::Register &info = it.value();146    // GDB sends x31 as "sp".  Add the "x31" alt_name for convenience.147    if (info.name == sp_string && !info.alt_name)148      info.alt_name.SetCString("x31");149 150    unsigned int reg_num;151    auto get_reg = [&info, &reg_num](const char *prefix) {152      llvm::StringRef reg_name = info.name.GetStringRef();153      llvm::StringRef alt_name = info.alt_name.GetStringRef();154      return (reg_name.consume_front(prefix) &&155              llvm::to_integer(reg_name, reg_num, 10) && reg_num < 32) ||156             (alt_name.consume_front(prefix) &&157              llvm::to_integer(alt_name, reg_num, 10) && reg_num < 32);158    };159 160    if (get_reg("x"))161      x_regs[reg_num] = it.index();162    else if (get_reg("v"))163      v_regs[reg_num] = it.index();164    else if (get_reg("z")) {165      z_regs[reg_num] = it.index();166      if (!z_byte_size)167        z_byte_size = info.byte_size;168    }169    // if we have at least one subregister, abort170    else if (get_reg("w") || get_reg("s") || get_reg("d"))171      return;172  }173 174  // Create aliases for partial registers.175 176  // Wn for Xn.177  addPartialRegisters(regs, x_regs, 8, "w{0}", 4, lldb::eEncodingUint,178                      lldb::eFormatHex);179 180  auto bool_predicate = [](const auto &reg_num) { return bool(reg_num); };181  bool saw_v_regs = llvm::any_of(v_regs, bool_predicate);182  bool saw_z_regs = llvm::any_of(z_regs, bool_predicate);183 184  // Sn/Dn for Vn.185  if (saw_v_regs) {186    addPartialRegisters(regs, v_regs, 16, "s{0}", 4, lldb::eEncodingIEEE754,187                        lldb::eFormatFloat);188    addPartialRegisters(regs, v_regs, 16, "d{0}", 8, lldb::eEncodingIEEE754,189                        lldb::eFormatFloat);190  } else if (saw_z_regs && z_byte_size) {191    // When SVE is enabled, some debug stubs will not describe the Neon V192    // registers because they can be read from the bottom 128 bits of the SVE193    // registers.194 195    // The size used here is the one sent by the debug server. This only needs196    // to be correct right now. Later we will rely on the value of vg instead.197    addPartialRegisters(regs, z_regs, *z_byte_size, "v{0}", 16,198                        lldb::eEncodingVector, lldb::eFormatVectorOfUInt8);199    addPartialRegisters(regs, z_regs, *z_byte_size, "s{0}", 4,200                        lldb::eEncodingIEEE754, lldb::eFormatFloat);201    addPartialRegisters(regs, z_regs, *z_byte_size, "d{0}", 8,202                        lldb::eEncodingIEEE754, lldb::eFormatFloat);203  }204}205 206UnwindPlanSP ABIAArch64::CreateFunctionEntryUnwindPlan() {207  UnwindPlan::Row row;208 209  // Our previous Call Frame Address is the stack pointer210  row.GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_SP, 0);211 212  // Our previous PC is in the LR, all other registers are the same.213  row.SetRegisterLocationToRegister(LLDB_REGNUM_GENERIC_PC,214                                    LLDB_REGNUM_GENERIC_RA, true);215 216  auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindGeneric);217  plan_sp->AppendRow(std::move(row));218  plan_sp->SetSourceName("arm64 at-func-entry default");219  plan_sp->SetSourcedFromCompiler(eLazyBoolNo);220  plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);221  plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);222  return plan_sp;223}224 225UnwindPlanSP ABIAArch64::CreateDefaultUnwindPlan() {226  UnwindPlan::Row row;227  const int32_t ptr_size = 8;228 229  row.GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_FP,230                                            2 * ptr_size);231  row.SetUnspecifiedRegistersAreUndefined(true);232 233  row.SetRegisterLocationToAtCFAPlusOffset(LLDB_REGNUM_GENERIC_FP,234                                           ptr_size * -2, true);235  row.SetRegisterLocationToAtCFAPlusOffset(LLDB_REGNUM_GENERIC_PC,236                                           ptr_size * -1, true);237 238  auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindGeneric);239  plan_sp->AppendRow(std::move(row));240  plan_sp->SetSourceName("arm64 default unwind plan");241  plan_sp->SetSourcedFromCompiler(eLazyBoolNo);242  plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);243  plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);244  return plan_sp;245}246