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")
75}
76
77std::string ABIAArch64::GetMCName(std::string reg) {
78 MapRegisterName(reg, "v", "q");
79 MapRegisterName(reg, "x29", "fp");
80 MapRegisterName(reg, "x30", "lr");
81 return reg;
82}
83
84uint32_t ABIAArch64::GetGenericNum(llvm::StringRef name) {
85 return llvm::StringSwitch<uint32_t>(name)
86 .Case("pc", LLDB_REGNUM_GENERIC_PC)
87 .Cases({"lr", "x30"}, LLDB_REGNUM_GENERIC_RA)
88 .Cases({"sp", "x31"}, LLDB_REGNUM_GENERIC_SP)
89 .Cases({"fp", "x29"}, LLDB_REGNUM_GENERIC_FP)
90 .Case("cpsr", LLDB_REGNUM_GENERIC_FLAGS)
91 .Case("tpidr", LLDB_REGNUM_GENERIC_TP)
92 .Case("x0", LLDB_REGNUM_GENERIC_ARG1)
93 .Case("x1", LLDB_REGNUM_GENERIC_ARG2)
94 .Case("x2", LLDB_REGNUM_GENERIC_ARG3)
95 .Case("x3", LLDB_REGNUM_GENERIC_ARG4)
96 .Case("x4", LLDB_REGNUM_GENERIC_ARG5)
97 .Case("x5", LLDB_REGNUM_GENERIC_ARG6)
98 .Case("x6", LLDB_REGNUM_GENERIC_ARG7)
99 .Case("x7", LLDB_REGNUM_GENERIC_ARG8)
100 .Default(LLDB_INVALID_REGNUM);
101}
102
104 std::vector<lldb_private::DynamicRegisterInfo::Register> &regs,
105 llvm::ArrayRef<std::optional<uint32_t>> full_reg_indices,
106 uint32_t full_reg_size, const char *partial_reg_format,
107 uint32_t partial_reg_size, lldb::Encoding encoding, lldb::Format format) {
108 for (auto it : llvm::enumerate(full_reg_indices)) {
109 std::optional<uint32_t> full_reg_index = it.value();
110 if (!full_reg_index || regs[*full_reg_index].byte_size != full_reg_size)
111 return;
112
115 llvm::formatv(partial_reg_format, it.index()).str()),
117 lldb_private::ConstString("supplementary registers"),
118 partial_reg_size,
120 encoding,
121 format,
126 {*full_reg_index},
127 {}};
128 addSupplementaryRegister(regs, partial_reg);
129 }
130}
131
133 std::vector<lldb_private::DynamicRegisterInfo::Register> &regs) {
135
136 lldb_private::ConstString sp_string{"sp"};
137
138 std::array<std::optional<uint32_t>, 32> x_regs;
139 std::array<std::optional<uint32_t>, 32> v_regs;
140 std::array<std::optional<uint32_t>, 32> z_regs;
141 std::optional<uint32_t> z_byte_size;
142
143 for (auto it : llvm::enumerate(regs)) {
145 // GDB sends x31 as "sp". Add the "x31" alt_name for convenience.
146 if (info.name == sp_string && !info.alt_name)
147 info.alt_name.SetCString("x31");
148
149 unsigned int reg_num;
150 auto get_reg = [&info, &reg_num](const char *prefix) {
151 llvm::StringRef reg_name = info.name.GetStringRef();
152 llvm::StringRef alt_name = info.alt_name.GetStringRef();
153 return (reg_name.consume_front(prefix) &&
154 llvm::to_integer(reg_name, reg_num, 10) && reg_num < 32) ||
155 (alt_name.consume_front(prefix) &&
156 llvm::to_integer(alt_name, reg_num, 10) && reg_num < 32);
157 };
158
159 if (get_reg("x"))
160 x_regs[reg_num] = it.index();
161 else if (get_reg("v"))
162 v_regs[reg_num] = it.index();
163 else if (get_reg("z")) {
164 z_regs[reg_num] = it.index();
165 if (!z_byte_size)
166 z_byte_size = info.byte_size;
167 }
168 // if we have at least one subregister, abort
169 else if (get_reg("w") || get_reg("s") || get_reg("d"))
170 return;
171 }
172
173 // Create aliases for partial registers.
174
175 // Wn for Xn.
176 addPartialRegisters(regs, x_regs, 8, "w{0}", 4, lldb::eEncodingUint,
178
179 auto bool_predicate = [](const auto &reg_num) { return bool(reg_num); };
180 bool saw_v_regs = llvm::any_of(v_regs, bool_predicate);
181 bool saw_z_regs = llvm::any_of(z_regs, bool_predicate);
182
183 // Sn/Dn for Vn.
184 if (saw_v_regs) {
185 addPartialRegisters(regs, v_regs, 16, "s{0}", 4, lldb::eEncodingIEEE754,
187 addPartialRegisters(regs, v_regs, 16, "d{0}", 8, lldb::eEncodingIEEE754,
189 } else if (saw_z_regs && z_byte_size) {
190 // When SVE is enabled, some debug stubs will not describe the Neon V
191 // registers because they can be read from the bottom 128 bits of the SVE
192 // registers.
193
194 // The size used here is the one sent by the debug server. This only needs
195 // to be correct right now. Later we will rely on the value of vg instead.
196 addPartialRegisters(regs, z_regs, *z_byte_size, "v{0}", 16,
198 addPartialRegisters(regs, z_regs, *z_byte_size, "s{0}", 4,
200 addPartialRegisters(regs, z_regs, *z_byte_size, "d{0}", 8,
202 }
203}
204
206 UnwindPlan::Row row;
207
208 // Our previous Call Frame Address is the stack pointer
210
211 // Our previous PC is in the LR, all other registers are the same.
214
215 auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindGeneric);
216 plan_sp->AppendRow(std::move(row));
217 plan_sp->SetSourceName("arm64 at-func-entry default");
218 plan_sp->SetSourcedFromCompiler(eLazyBoolNo);
219 plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
220 plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);
221 return plan_sp;
222}
223
225 UnwindPlan::Row row;
226 const int32_t ptr_size = 8;
227
229 2 * ptr_size);
231
233 ptr_size * -2, true);
235 ptr_size * -1, true);
236
237 auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindGeneric);
238 plan_sp->AppendRow(std::move(row));
239 plan_sp->SetSourceName("arm64 default unwind plan");
240 plan_sp->SetSourcedFromCompiler(eLazyBoolNo);
241 plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
242 plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);
243 return plan_sp;
244}
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:262
virtual std::pair< uint32_t, uint32_t > GetEHAndDWARFNums(llvm::StringRef reg)
Return eh_frame and dwarf numbers for the given register.
Definition ABI.cpp:278
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:296
void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset)
Definition UnwindPlan.h:241
bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
const FAValue & GetCFAValue() const
Definition UnwindPlan.h:366
bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num, bool can_replace)
void SetUnspecifiedRegistersAreUndefined(bool unspec_is_undef)
Definition UnwindPlan.h:409
#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_TP
#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