LLDB mainline
ABIAArch64.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/lldb-types.h"
10
11#include "ABIAArch64.h"
12#include "ABIMacOSX_arm64.h"
13#include "ABISysV_arm64.h"
17#include "lldb/Target/Process.h"
18
19#include <bitset>
20#include <optional>
21
22using namespace lldb;
23using namespace lldb_private;
24
26
31
36
38 if (lldb::ProcessSP process_sp = GetProcessSP()) {
39 // b55 is the highest bit outside TBI (if it's enabled), use
40 // 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 separately
44 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
55 if (lldb::ProcessSP process_sp = GetProcessSP()) {
56 // b55 is the highest bit outside TBI (if it's enabled), use
57 // 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 separately
61 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")
74 if (name == "cpsr")
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
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
116 llvm::formatv(partial_reg_format, it.index()).str()),
118 lldb_private::ConstString("supplementary registers"),
119 partial_reg_size,
121 encoding,
122 format,
127 {*full_reg_index},
128 {}};
129 addSupplementaryRegister(regs, partial_reg);
130 }
131}
132
134 std::vector<lldb_private::DynamicRegisterInfo::Register> &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)) {
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, abort
170 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,
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,
188 addPartialRegisters(regs, v_regs, 16, "d{0}", 8, lldb::eEncodingIEEE754,
190 } else if (saw_z_regs && z_byte_size) {
191 // When SVE is enabled, some debug stubs will not describe the Neon V
192 // registers because they can be read from the bottom 128 bits of the SVE
193 // registers.
194
195 // The size used here is the one sent by the debug server. This only needs
196 // 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,
199 addPartialRegisters(regs, z_regs, *z_byte_size, "s{0}", 4,
201 addPartialRegisters(regs, z_regs, *z_byte_size, "d{0}", 8,
203 }
204}
205
207 UnwindPlan::Row row;
208
209 // Our previous Call Frame Address is the stack pointer
211
212 // Our previous PC is in the LR, all other registers are the same.
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
226 UnwindPlan::Row row;
227 const int32_t ptr_size = 8;
228
230 2 * ptr_size);
232
234 ptr_size * -2, true);
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}
static void addPartialRegisters(std::vector< lldb_private::DynamicRegisterInfo::Register > &regs, llvm::ArrayRef< std::optional< uint32_t > > full_reg_indices, uint32_t full_reg_size, const char *partial_reg_format, uint32_t partial_reg_size, lldb::Encoding encoding, lldb::Format format)
constexpr addr_t pac_sign_extension
#define LLDB_PLUGIN_DEFINE(PluginName)
static void Terminate()
lldb::UnwindPlanSP CreateDefaultUnwindPlan() override
lldb::addr_t FixDataAddress(lldb::addr_t pc) override
lldb::addr_t FixCodeAddress(lldb::addr_t pc) override
Some targets might use bits in a code address to indicate a mode switch.
uint32_t GetGenericNum(llvm::StringRef name) override
Return the generic number of the given register.
virtual lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask)
Definition ABIAArch64.h:26
void AugmentRegisterInfo(std::vector< lldb_private::DynamicRegisterInfo::Register > &regs) override
lldb::UnwindPlanSP CreateFunctionEntryUnwindPlan() override
static void Initialize()
std::pair< uint32_t, uint32_t > GetEHAndDWARFNums(llvm::StringRef name) override
Return eh_frame and dwarf numbers for the given register.
std::string GetMCName(std::string reg) override
For the given (capitalized) lldb register name, return the name of this register in the MCRegisterInf...
static void Terminate()
static void Initialize()
static void Initialize()
static void Terminate()
lldb::ProcessSP GetProcessSP() const
Request to get a Process shared pointer.
Definition ABI.h:97
A uniqued constant string class.
Definition ConstString.h:40
void SetCString(const char *cstr)
Set the C string value.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
void AugmentRegisterInfo(std::vector< DynamicRegisterInfo::Register > &regs) override
Definition ABI.cpp:271
virtual std::pair< uint32_t, uint32_t > GetEHAndDWARFNums(llvm::StringRef reg)
Return eh_frame and dwarf numbers for the given register.
Definition ABI.cpp:287
static void MapRegisterName(std::string &reg, llvm::StringRef from_prefix, llvm::StringRef to_prefix)
If the register name is of the form "<from_prefix>[<number>]" then change the name to "<to_prefix>[<n...
Definition ABI.cpp:305
void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset)
Definition UnwindPlan.h:240
bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
const FAValue & GetCFAValue() const
Definition UnwindPlan.h:365
bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num, bool can_replace)
void SetUnspecifiedRegistersAreUndefined(bool unspec_is_undef)
Definition UnwindPlan.h:408
#define LLDB_REGNUM_GENERIC_RA
#define LLDB_REGNUM_GENERIC_ARG8
#define LLDB_INVALID_ADDRESS_MASK
Address Mask Bits not used for addressing are set to 1 in the mask; all mask bits set is an invalid v...
#define LLDB_REGNUM_GENERIC_ARG6
#define LLDB_INVALID_INDEX32
#define LLDB_REGNUM_GENERIC_SP
#define LLDB_REGNUM_GENERIC_ARG4
#define LLDB_REGNUM_GENERIC_ARG3
#define LLDB_REGNUM_GENERIC_ARG1
#define LLDB_REGNUM_GENERIC_ARG7
#define LLDB_REGNUM_GENERIC_FLAGS
#define LLDB_INVALID_REGNUM
#define LLDB_REGNUM_GENERIC_ARG2
#define LLDB_REGNUM_GENERIC_PC
#define LLDB_REGNUM_GENERIC_FP
#define LLDB_REGNUM_GENERIC_ARG5
A class that represents a running process on the host machine.
void addSupplementaryRegister(std::vector< DynamicRegisterInfo::Register > &regs, DynamicRegisterInfo::Register new_reg_info)
Format
Display format definitions.
@ eFormatVectorOfUInt8
std::shared_ptr< lldb_private::Process > ProcessSP
Encoding
Register encoding definitions.
@ eEncodingIEEE754
float
@ eEncodingVector
vector registers
@ eEncodingUint
unsigned integer
std::shared_ptr< lldb_private::UnwindPlan > UnwindPlanSP
uint64_t addr_t
Definition lldb-types.h:80
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target