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("x0", LLDB_REGNUM_GENERIC_ARG1)
92 .Case("x1", LLDB_REGNUM_GENERIC_ARG2)
93 .Case("x2", LLDB_REGNUM_GENERIC_ARG3)
94 .Case("x3", LLDB_REGNUM_GENERIC_ARG4)
95 .Case("x4", LLDB_REGNUM_GENERIC_ARG5)
96 .Case("x5", LLDB_REGNUM_GENERIC_ARG6)
97 .Case("x6", LLDB_REGNUM_GENERIC_ARG7)
98 .Case("x7", LLDB_REGNUM_GENERIC_ARG8)
99 .Default(LLDB_INVALID_REGNUM);
100}
101
103 std::vector<lldb_private::DynamicRegisterInfo::Register> &regs,
104 llvm::ArrayRef<std::optional<uint32_t>> full_reg_indices,
105 uint32_t full_reg_size, const char *partial_reg_format,
106 uint32_t partial_reg_size, lldb::Encoding encoding, lldb::Format format) {
107 for (auto it : llvm::enumerate(full_reg_indices)) {
108 std::optional<uint32_t> full_reg_index = it.value();
109 if (!full_reg_index || regs[*full_reg_index].byte_size != full_reg_size)
110 return;
111
114 llvm::formatv(partial_reg_format, it.index()).str()),
116 lldb_private::ConstString("supplementary registers"),
117 partial_reg_size,
119 encoding,
120 format,
125 {*full_reg_index},
126 {}};
127 addSupplementaryRegister(regs, partial_reg);
128 }
129}
130
132 std::vector<lldb_private::DynamicRegisterInfo::Register> &regs) {
134
135 lldb_private::ConstString sp_string{"sp"};
136
137 std::array<std::optional<uint32_t>, 32> x_regs;
138 std::array<std::optional<uint32_t>, 32> v_regs;
139 std::array<std::optional<uint32_t>, 32> z_regs;
140 std::optional<uint32_t> z_byte_size;
141
142 for (auto it : llvm::enumerate(regs)) {
144 // GDB sends x31 as "sp". Add the "x31" alt_name for convenience.
145 if (info.name == sp_string && !info.alt_name)
146 info.alt_name.SetCString("x31");
147
148 unsigned int reg_num;
149 auto get_reg = [&info, &reg_num](const char *prefix) {
150 llvm::StringRef reg_name = info.name.GetStringRef();
151 llvm::StringRef alt_name = info.alt_name.GetStringRef();
152 return (reg_name.consume_front(prefix) &&
153 llvm::to_integer(reg_name, reg_num, 10) && reg_num < 32) ||
154 (alt_name.consume_front(prefix) &&
155 llvm::to_integer(alt_name, reg_num, 10) && reg_num < 32);
156 };
157
158 if (get_reg("x"))
159 x_regs[reg_num] = it.index();
160 else if (get_reg("v"))
161 v_regs[reg_num] = it.index();
162 else if (get_reg("z")) {
163 z_regs[reg_num] = it.index();
164 if (!z_byte_size)
165 z_byte_size = info.byte_size;
166 }
167 // if we have at least one subregister, abort
168 else if (get_reg("w") || get_reg("s") || get_reg("d"))
169 return;
170 }
171
172 // Create aliases for partial registers.
173
174 // Wn for Xn.
175 addPartialRegisters(regs, x_regs, 8, "w{0}", 4, lldb::eEncodingUint,
177
178 auto bool_predicate = [](const auto &reg_num) { return bool(reg_num); };
179 bool saw_v_regs = llvm::any_of(v_regs, bool_predicate);
180 bool saw_z_regs = llvm::any_of(z_regs, bool_predicate);
181
182 // Sn/Dn for Vn.
183 if (saw_v_regs) {
184 addPartialRegisters(regs, v_regs, 16, "s{0}", 4, lldb::eEncodingIEEE754,
186 addPartialRegisters(regs, v_regs, 16, "d{0}", 8, lldb::eEncodingIEEE754,
188 } else if (saw_z_regs && z_byte_size) {
189 // When SVE is enabled, some debug stubs will not describe the Neon V
190 // registers because they can be read from the bottom 128 bits of the SVE
191 // registers.
192
193 // The size used here is the one sent by the debug server. This only needs
194 // to be correct right now. Later we will rely on the value of vg instead.
195 addPartialRegisters(regs, z_regs, *z_byte_size, "v{0}", 16,
197 addPartialRegisters(regs, z_regs, *z_byte_size, "s{0}", 4,
199 addPartialRegisters(regs, z_regs, *z_byte_size, "d{0}", 8,
201 }
202}
203
205 UnwindPlan::Row row;
206
207 // Our previous Call Frame Address is the stack pointer
209
210 // Our previous PC is in the LR, all other registers are the same.
213
214 auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindGeneric);
215 plan_sp->AppendRow(std::move(row));
216 plan_sp->SetSourceName("arm64 at-func-entry default");
217 plan_sp->SetSourcedFromCompiler(eLazyBoolNo);
218 plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
219 plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);
220 return plan_sp;
221}
222
224 UnwindPlan::Row row;
225 const int32_t ptr_size = 8;
226
228 2 * ptr_size);
230
232 ptr_size * -2, true);
234 ptr_size * -1, true);
235
236 auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindGeneric);
237 plan_sp->AppendRow(std::move(row));
238 plan_sp->SetSourceName("arm64 default unwind plan");
239 plan_sp->SetSourcedFromCompiler(eLazyBoolNo);
240 plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
241 plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);
242 return plan_sp;
243}
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: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