Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp
96380 views
1
//===-- NativeRegisterContextFreeBSD_powerpc.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
#if defined(__powerpc__)
10
11
#include "NativeRegisterContextFreeBSD_powerpc.h"
12
13
#include "lldb/Host/HostInfo.h"
14
#include "lldb/Utility/DataBufferHeap.h"
15
#include "lldb/Utility/RegisterValue.h"
16
#include "lldb/Utility/Status.h"
17
18
#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
19
// for register enum definitions
20
#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
21
22
// clang-format off
23
#include <sys/param.h>
24
#include <sys/ptrace.h>
25
#include <sys/types.h>
26
// clang-format on
27
#include <optional>
28
29
using namespace lldb;
30
using namespace lldb_private;
31
using namespace lldb_private::process_freebsd;
32
33
static const uint32_t g_gpr_regnums[] = {
34
gpr_r0_powerpc, gpr_r1_powerpc, gpr_r2_powerpc, gpr_r3_powerpc,
35
gpr_r4_powerpc, gpr_r5_powerpc, gpr_r6_powerpc, gpr_r7_powerpc,
36
gpr_r8_powerpc, gpr_r9_powerpc, gpr_r10_powerpc, gpr_r11_powerpc,
37
gpr_r12_powerpc, gpr_r13_powerpc, gpr_r14_powerpc, gpr_r15_powerpc,
38
gpr_r16_powerpc, gpr_r17_powerpc, gpr_r18_powerpc, gpr_r19_powerpc,
39
gpr_r20_powerpc, gpr_r21_powerpc, gpr_r22_powerpc, gpr_r23_powerpc,
40
gpr_r24_powerpc, gpr_r25_powerpc, gpr_r26_powerpc, gpr_r27_powerpc,
41
gpr_r28_powerpc, gpr_r29_powerpc, gpr_r30_powerpc, gpr_r31_powerpc,
42
gpr_lr_powerpc, gpr_cr_powerpc, gpr_xer_powerpc, gpr_ctr_powerpc,
43
gpr_pc_powerpc,
44
};
45
46
static const uint32_t g_fpr_regnums[] = {
47
fpr_f0_powerpc, fpr_f1_powerpc, fpr_f2_powerpc, fpr_f3_powerpc,
48
fpr_f4_powerpc, fpr_f5_powerpc, fpr_f6_powerpc, fpr_f7_powerpc,
49
fpr_f8_powerpc, fpr_f9_powerpc, fpr_f10_powerpc, fpr_f11_powerpc,
50
fpr_f12_powerpc, fpr_f13_powerpc, fpr_f14_powerpc, fpr_f15_powerpc,
51
fpr_f16_powerpc, fpr_f17_powerpc, fpr_f18_powerpc, fpr_f19_powerpc,
52
fpr_f20_powerpc, fpr_f21_powerpc, fpr_f22_powerpc, fpr_f23_powerpc,
53
fpr_f24_powerpc, fpr_f25_powerpc, fpr_f26_powerpc, fpr_f27_powerpc,
54
fpr_f28_powerpc, fpr_f29_powerpc, fpr_f30_powerpc, fpr_f31_powerpc,
55
fpr_fpscr_powerpc,
56
};
57
58
// Number of register sets provided by this context.
59
enum { k_num_register_sets = 2 };
60
61
static const RegisterSet g_reg_sets_powerpc[k_num_register_sets] = {
62
{"General Purpose Registers", "gpr", k_num_gpr_registers_powerpc,
63
g_gpr_regnums},
64
{"Floating Point Registers", "fpr", k_num_fpr_registers_powerpc,
65
g_fpr_regnums},
66
};
67
68
NativeRegisterContextFreeBSD *
69
NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
70
const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) {
71
return new NativeRegisterContextFreeBSD_powerpc(target_arch, native_thread);
72
}
73
74
static RegisterInfoInterface *
75
CreateRegisterInfoInterface(const ArchSpec &target_arch) {
76
if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
77
return new RegisterContextFreeBSD_powerpc32(target_arch);
78
} else {
79
assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
80
"Register setting path assumes this is a 64-bit host");
81
return new RegisterContextFreeBSD_powerpc64(target_arch);
82
}
83
}
84
85
NativeRegisterContextFreeBSD_powerpc::NativeRegisterContextFreeBSD_powerpc(
86
const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread)
87
: NativeRegisterContextRegisterInfo(
88
native_thread, CreateRegisterInfoInterface(target_arch)) {}
89
90
RegisterContextFreeBSD_powerpc &
91
NativeRegisterContextFreeBSD_powerpc::GetRegisterInfo() const {
92
return static_cast<RegisterContextFreeBSD_powerpc &>(
93
*m_register_info_interface_up);
94
}
95
96
uint32_t NativeRegisterContextFreeBSD_powerpc::GetRegisterSetCount() const {
97
return k_num_register_sets;
98
}
99
100
const RegisterSet *
101
NativeRegisterContextFreeBSD_powerpc::GetRegisterSet(uint32_t set_index) const {
102
switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
103
case llvm::Triple::ppc:
104
return &g_reg_sets_powerpc[set_index];
105
default:
106
llvm_unreachable("Unhandled target architecture.");
107
}
108
}
109
110
std::optional<NativeRegisterContextFreeBSD_powerpc::RegSetKind>
111
NativeRegisterContextFreeBSD_powerpc::GetSetForNativeRegNum(
112
uint32_t reg_num) const {
113
switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
114
case llvm::Triple::ppc:
115
if (reg_num >= k_first_gpr_powerpc && reg_num <= k_last_gpr_powerpc)
116
return GPRegSet;
117
if (reg_num >= k_first_fpr && reg_num <= k_last_fpr)
118
return FPRegSet;
119
break;
120
default:
121
llvm_unreachable("Unhandled target architecture.");
122
}
123
124
llvm_unreachable("Register does not belong to any register set");
125
}
126
127
uint32_t NativeRegisterContextFreeBSD_powerpc::GetUserRegisterCount() const {
128
uint32_t count = 0;
129
for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
130
count += GetRegisterSet(set_index)->num_registers;
131
return count;
132
}
133
134
Status NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet(RegSetKind set) {
135
switch (set) {
136
case GPRegSet:
137
return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(),
138
m_reg_data.data());
139
case FPRegSet:
140
return NativeProcessFreeBSD::PtraceWrapper(PT_GETFPREGS, m_thread.GetID(),
141
m_reg_data.data() + sizeof(reg));
142
}
143
llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet");
144
}
145
146
Status NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet(RegSetKind set) {
147
switch (set) {
148
case GPRegSet:
149
return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(),
150
m_reg_data.data());
151
case FPRegSet:
152
return NativeProcessFreeBSD::PtraceWrapper(PT_SETFPREGS, m_thread.GetID(),
153
m_reg_data.data() + sizeof(reg));
154
}
155
llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet");
156
}
157
158
Status
159
NativeRegisterContextFreeBSD_powerpc::ReadRegister(const RegisterInfo *reg_info,
160
RegisterValue &reg_value) {
161
Status error;
162
163
if (!reg_info) {
164
error.SetErrorString("reg_info NULL");
165
return error;
166
}
167
168
const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
169
170
if (reg == LLDB_INVALID_REGNUM)
171
return Status("no lldb regnum for %s", reg_info && reg_info->name
172
? reg_info->name
173
: "<unknown register>");
174
175
std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
176
if (!opt_set) {
177
// This is likely an internal register for lldb use only and should not be
178
// directly queried.
179
error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
180
reg_info->name);
181
return error;
182
}
183
184
RegSetKind set = *opt_set;
185
error = ReadRegisterSet(set);
186
if (error.Fail())
187
return error;
188
189
assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
190
reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset,
191
reg_info->byte_size, endian::InlHostByteOrder());
192
return error;
193
}
194
195
Status NativeRegisterContextFreeBSD_powerpc::WriteRegister(
196
const RegisterInfo *reg_info, const RegisterValue &reg_value) {
197
Status error;
198
199
if (!reg_info)
200
return Status("reg_info NULL");
201
202
const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
203
204
if (reg == LLDB_INVALID_REGNUM)
205
return Status("no lldb regnum for %s", reg_info && reg_info->name
206
? reg_info->name
207
: "<unknown register>");
208
209
std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
210
if (!opt_set) {
211
// This is likely an internal register for lldb use only and should not be
212
// directly queried.
213
error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
214
reg_info->name);
215
return error;
216
}
217
218
RegSetKind set = *opt_set;
219
error = ReadRegisterSet(set);
220
if (error.Fail())
221
return error;
222
223
assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
224
::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(),
225
reg_info->byte_size);
226
227
return WriteRegisterSet(set);
228
}
229
230
Status NativeRegisterContextFreeBSD_powerpc::ReadAllRegisterValues(
231
lldb::WritableDataBufferSP &data_sp) {
232
Status error;
233
234
error = ReadRegisterSet(GPRegSet);
235
if (error.Fail())
236
return error;
237
238
error = ReadRegisterSet(FPRegSet);
239
if (error.Fail())
240
return error;
241
242
data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0));
243
uint8_t *dst = data_sp->GetBytes();
244
::memcpy(dst, m_reg_data.data(), m_reg_data.size());
245
246
return error;
247
}
248
249
Status NativeRegisterContextFreeBSD_powerpc::WriteAllRegisterValues(
250
const lldb::DataBufferSP &data_sp) {
251
Status error;
252
253
if (!data_sp) {
254
error.SetErrorStringWithFormat(
255
"NativeRegisterContextFreeBSD_powerpc::%s invalid data_sp provided",
256
__FUNCTION__);
257
return error;
258
}
259
260
if (data_sp->GetByteSize() != m_reg_data.size()) {
261
error.SetErrorStringWithFormat(
262
"NativeRegisterContextFreeBSD_powerpc::%s data_sp contained mismatched "
263
"data size, expected %zu, actual %" PRIu64,
264
__FUNCTION__, m_reg_data.size(), data_sp->GetByteSize());
265
return error;
266
}
267
268
const uint8_t *src = data_sp->GetBytes();
269
if (src == nullptr) {
270
error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_powerpc::%s "
271
"DataBuffer::GetBytes() returned a null "
272
"pointer",
273
__FUNCTION__);
274
return error;
275
}
276
::memcpy(m_reg_data.data(), src, m_reg_data.size());
277
278
error = WriteRegisterSet(GPRegSet);
279
if (error.Fail())
280
return error;
281
282
return WriteRegisterSet(FPRegSet);
283
}
284
285
llvm::Error NativeRegisterContextFreeBSD_powerpc::CopyHardwareWatchpointsFrom(
286
NativeRegisterContextFreeBSD &source) {
287
return llvm::Error::success();
288
}
289
290
#endif // defined (__powerpc__)
291
292