Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp
39653 views
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
#ifdef LLDB_ENABLE_ALL
13
#include "ABIMacOSX_arm64.h"
14
#endif // LLDB_ENABLE_ALL
15
#include "ABISysV_arm64.h"
16
#include "Utility/ARM64_DWARF_Registers.h"
17
#include "lldb/Core/PluginManager.h"
18
#include "lldb/Target/Process.h"
19
20
#include <bitset>
21
#include <optional>
22
23
using namespace lldb;
24
25
LLDB_PLUGIN_DEFINE(ABIAArch64)
26
27
void ABIAArch64::Initialize() {
28
ABISysV_arm64::Initialize();
29
#ifdef LLDB_ENABLE_ALL
30
ABIMacOSX_arm64::Initialize();
31
#endif // LLDB_ENABLE_ALL
32
}
33
34
void ABIAArch64::Terminate() {
35
ABISysV_arm64::Terminate();
36
#ifdef LLDB_ENABLE_ALL
37
ABIMacOSX_arm64::Terminate();
38
#endif // LLDB_ENABLE_ALL
39
}
40
41
lldb::addr_t ABIAArch64::FixCodeAddress(lldb::addr_t pc) {
42
if (lldb::ProcessSP process_sp = GetProcessSP()) {
43
// b55 is the highest bit outside TBI (if it's enabled), use
44
// it to determine if the high bits are set to 0 or 1.
45
const addr_t pac_sign_extension = 0x0080000000000000ULL;
46
addr_t mask = process_sp->GetCodeAddressMask();
47
// Test if the high memory mask has been overriden separately
48
if (pc & pac_sign_extension &&
49
process_sp->GetHighmemCodeAddressMask() != LLDB_INVALID_ADDRESS_MASK)
50
mask = process_sp->GetHighmemCodeAddressMask();
51
52
if (mask != LLDB_INVALID_ADDRESS_MASK)
53
return FixAddress(pc, mask);
54
}
55
return pc;
56
}
57
58
lldb::addr_t ABIAArch64::FixDataAddress(lldb::addr_t pc) {
59
if (lldb::ProcessSP process_sp = GetProcessSP()) {
60
// b55 is the highest bit outside TBI (if it's enabled), use
61
// it to determine if the high bits are set to 0 or 1.
62
const addr_t pac_sign_extension = 0x0080000000000000ULL;
63
addr_t mask = process_sp->GetDataAddressMask();
64
// Test if the high memory mask has been overriden separately
65
if (pc & pac_sign_extension &&
66
process_sp->GetHighmemDataAddressMask() != LLDB_INVALID_ADDRESS_MASK)
67
mask = process_sp->GetHighmemDataAddressMask();
68
if (mask != LLDB_INVALID_ADDRESS_MASK)
69
return FixAddress(pc, mask);
70
}
71
return pc;
72
}
73
74
std::pair<uint32_t, uint32_t>
75
ABIAArch64::GetEHAndDWARFNums(llvm::StringRef name) {
76
if (name == "pc")
77
return {LLDB_INVALID_REGNUM, arm64_dwarf::pc};
78
if (name == "cpsr")
79
return {LLDB_INVALID_REGNUM, arm64_dwarf::cpsr};
80
return MCBasedABI::GetEHAndDWARFNums(name);
81
}
82
83
std::string ABIAArch64::GetMCName(std::string reg) {
84
MapRegisterName(reg, "v", "q");
85
MapRegisterName(reg, "x29", "fp");
86
MapRegisterName(reg, "x30", "lr");
87
return reg;
88
}
89
90
uint32_t ABIAArch64::GetGenericNum(llvm::StringRef name) {
91
return llvm::StringSwitch<uint32_t>(name)
92
.Case("pc", LLDB_REGNUM_GENERIC_PC)
93
.Cases("lr", "x30", LLDB_REGNUM_GENERIC_RA)
94
.Cases("sp", "x31", LLDB_REGNUM_GENERIC_SP)
95
.Cases("fp", "x29", LLDB_REGNUM_GENERIC_FP)
96
.Case("cpsr", LLDB_REGNUM_GENERIC_FLAGS)
97
.Case("x0", LLDB_REGNUM_GENERIC_ARG1)
98
.Case("x1", LLDB_REGNUM_GENERIC_ARG2)
99
.Case("x2", LLDB_REGNUM_GENERIC_ARG3)
100
.Case("x3", LLDB_REGNUM_GENERIC_ARG4)
101
.Case("x4", LLDB_REGNUM_GENERIC_ARG5)
102
.Case("x5", LLDB_REGNUM_GENERIC_ARG6)
103
.Case("x6", LLDB_REGNUM_GENERIC_ARG7)
104
.Case("x7", LLDB_REGNUM_GENERIC_ARG8)
105
.Default(LLDB_INVALID_REGNUM);
106
}
107
108
static void addPartialRegisters(
109
std::vector<lldb_private::DynamicRegisterInfo::Register> &regs,
110
llvm::ArrayRef<std::optional<uint32_t>> full_reg_indices,
111
uint32_t full_reg_size, const char *partial_reg_format,
112
uint32_t partial_reg_size, lldb::Encoding encoding, lldb::Format format) {
113
for (auto it : llvm::enumerate(full_reg_indices)) {
114
std::optional<uint32_t> full_reg_index = it.value();
115
if (!full_reg_index || regs[*full_reg_index].byte_size != full_reg_size)
116
return;
117
118
lldb_private::DynamicRegisterInfo::Register partial_reg{
119
lldb_private::ConstString(
120
llvm::formatv(partial_reg_format, it.index()).str()),
121
lldb_private::ConstString(),
122
lldb_private::ConstString("supplementary registers"),
123
partial_reg_size,
124
LLDB_INVALID_INDEX32,
125
encoding,
126
format,
127
LLDB_INVALID_REGNUM,
128
LLDB_INVALID_REGNUM,
129
LLDB_INVALID_REGNUM,
130
LLDB_INVALID_REGNUM,
131
{*full_reg_index},
132
{}};
133
addSupplementaryRegister(regs, partial_reg);
134
}
135
}
136
137
void ABIAArch64::AugmentRegisterInfo(
138
std::vector<lldb_private::DynamicRegisterInfo::Register> &regs) {
139
lldb_private::MCBasedABI::AugmentRegisterInfo(regs);
140
141
lldb_private::ConstString sp_string{"sp"};
142
143
std::array<std::optional<uint32_t>, 32> x_regs;
144
std::array<std::optional<uint32_t>, 32> v_regs;
145
146
for (auto it : llvm::enumerate(regs)) {
147
lldb_private::DynamicRegisterInfo::Register &info = it.value();
148
// GDB sends x31 as "sp". Add the "x31" alt_name for convenience.
149
if (info.name == sp_string && !info.alt_name)
150
info.alt_name.SetCString("x31");
151
152
unsigned int reg_num;
153
auto get_reg = [&info, &reg_num](const char *prefix) {
154
llvm::StringRef reg_name = info.name.GetStringRef();
155
llvm::StringRef alt_name = info.alt_name.GetStringRef();
156
return (reg_name.consume_front(prefix) &&
157
llvm::to_integer(reg_name, reg_num, 10) && reg_num < 32) ||
158
(alt_name.consume_front(prefix) &&
159
llvm::to_integer(alt_name, reg_num, 10) && reg_num < 32);
160
};
161
162
if (get_reg("x"))
163
x_regs[reg_num] = it.index();
164
else if (get_reg("v"))
165
v_regs[reg_num] = it.index();
166
// if we have at least one subregister, abort
167
else if (get_reg("w") || get_reg("s") || get_reg("d"))
168
return;
169
}
170
171
// Create aliases for partial registers: wN for xN, and sN/dN for vN.
172
addPartialRegisters(regs, x_regs, 8, "w{0}", 4, lldb::eEncodingUint,
173
lldb::eFormatHex);
174
addPartialRegisters(regs, v_regs, 16, "s{0}", 4, lldb::eEncodingIEEE754,
175
lldb::eFormatFloat);
176
addPartialRegisters(regs, v_regs, 16, "d{0}", 8, lldb::eEncodingIEEE754,
177
lldb::eFormatFloat);
178
}
179
180