Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.cpp
39645 views
1
//===-- ArchitectureAArch64.cpp -------------------------------------------===//
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 "Plugins/Architecture/AArch64/ArchitectureAArch64.h"
10
#include "lldb/Core/PluginManager.h"
11
#include "lldb/Target/RegisterContext.h"
12
#include "lldb/Utility/ArchSpec.h"
13
#include "lldb/Utility/DataBufferHeap.h"
14
#include "lldb/Utility/DataExtractor.h"
15
16
using namespace lldb_private;
17
using namespace lldb;
18
19
LLDB_PLUGIN_DEFINE(ArchitectureAArch64)
20
21
void ArchitectureAArch64::Initialize() {
22
PluginManager::RegisterPlugin(GetPluginNameStatic(),
23
"AArch64-specific algorithms",
24
&ArchitectureAArch64::Create);
25
}
26
27
void ArchitectureAArch64::Terminate() {
28
PluginManager::UnregisterPlugin(&ArchitectureAArch64::Create);
29
}
30
31
std::unique_ptr<Architecture>
32
ArchitectureAArch64::Create(const ArchSpec &arch) {
33
auto machine = arch.GetMachine();
34
if (machine != llvm::Triple::aarch64 && machine != llvm::Triple::aarch64_be &&
35
machine != llvm::Triple::aarch64_32) {
36
return nullptr;
37
}
38
return std::unique_ptr<Architecture>(new ArchitectureAArch64());
39
}
40
41
static void
42
UpdateARM64SVERegistersInfos(DynamicRegisterInfo::reg_collection_range regs,
43
uint64_t vg) {
44
// SVE Z register size is vg x 8 bytes.
45
uint32_t z_reg_byte_size = vg * 8;
46
47
// SVE vector length has changed, accordingly set size of Z, P and FFR
48
// registers. Also invalidate register offsets it will be recalculated
49
// after SVE register size update.
50
for (auto &reg : regs) {
51
if (reg.value_regs == nullptr) {
52
if (reg.name[0] == 'z' && isdigit(reg.name[1]))
53
reg.byte_size = z_reg_byte_size;
54
else if (reg.name[0] == 'p' && isdigit(reg.name[1]))
55
reg.byte_size = vg;
56
else if (strcmp(reg.name, "ffr") == 0)
57
reg.byte_size = vg;
58
}
59
reg.byte_offset = LLDB_INVALID_INDEX32;
60
}
61
}
62
63
static void
64
UpdateARM64SMERegistersInfos(DynamicRegisterInfo::reg_collection_range regs,
65
uint64_t svg) {
66
for (auto &reg : regs) {
67
if (strcmp(reg.name, "za") == 0) {
68
// ZA is a register with size (svg*8) * (svg*8). A square essentially.
69
reg.byte_size = (svg * 8) * (svg * 8);
70
}
71
reg.byte_offset = LLDB_INVALID_INDEX32;
72
}
73
}
74
75
bool ArchitectureAArch64::ReconfigureRegisterInfo(DynamicRegisterInfo &reg_info,
76
DataExtractor &reg_data,
77
RegisterContext &reg_context
78
79
) const {
80
// Once we start to reconfigure registers, we cannot read any of them.
81
// So we must read VG and SVG up front.
82
83
const uint64_t fail_value = LLDB_INVALID_ADDRESS;
84
std::optional<uint64_t> vg_reg_value;
85
const RegisterInfo *vg_reg_info = reg_info.GetRegisterInfo("vg");
86
if (vg_reg_info) {
87
uint32_t vg_reg_num = vg_reg_info->kinds[eRegisterKindLLDB];
88
uint64_t reg_value =
89
reg_context.ReadRegisterAsUnsigned(vg_reg_num, fail_value);
90
if (reg_value != fail_value && reg_value <= 32)
91
vg_reg_value = reg_value;
92
}
93
94
std::optional<uint64_t> svg_reg_value;
95
const RegisterInfo *svg_reg_info = reg_info.GetRegisterInfo("svg");
96
if (svg_reg_info) {
97
uint32_t svg_reg_num = svg_reg_info->kinds[eRegisterKindLLDB];
98
uint64_t reg_value =
99
reg_context.ReadRegisterAsUnsigned(svg_reg_num, fail_value);
100
if (reg_value != fail_value && reg_value <= 32)
101
svg_reg_value = reg_value;
102
}
103
104
if (!vg_reg_value && !svg_reg_value)
105
return false;
106
107
auto regs = reg_info.registers<DynamicRegisterInfo::reg_collection_range>();
108
if (vg_reg_value)
109
UpdateARM64SVERegistersInfos(regs, *vg_reg_value);
110
if (svg_reg_value)
111
UpdateARM64SMERegistersInfos(regs, *svg_reg_value);
112
113
// At this point if we have updated any registers, their offsets will all be
114
// invalid. If we did, we need to update them all.
115
reg_info.ConfigureOffsets();
116
// From here we are able to read registers again.
117
118
// Make a heap based buffer that is big enough to store all registers
119
reg_data.SetData(
120
std::make_shared<DataBufferHeap>(reg_info.GetRegisterDataByteSize(), 0));
121
reg_data.SetByteOrder(reg_context.GetByteOrder());
122
123
return true;
124
}
125
126