Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp
39648 views
1
//===-- EmulateInstructionPPC64.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 "EmulateInstructionPPC64.h"
10
11
#include <cstdlib>
12
#include <optional>
13
14
#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h"
15
#include "lldb/Core/PluginManager.h"
16
#include "lldb/Symbol/UnwindPlan.h"
17
#include "lldb/Utility/ArchSpec.h"
18
#include "lldb/Utility/ConstString.h"
19
#include "lldb/Utility/LLDBLog.h"
20
21
#define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT
22
#include "Plugins/Process/Utility/RegisterInfos_ppc64le.h"
23
24
#include "Plugins/Process/Utility/InstructionUtils.h"
25
26
using namespace lldb;
27
using namespace lldb_private;
28
29
LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionPPC64, InstructionPPC64)
30
31
EmulateInstructionPPC64::EmulateInstructionPPC64(const ArchSpec &arch)
32
: EmulateInstruction(arch) {}
33
34
void EmulateInstructionPPC64::Initialize() {
35
PluginManager::RegisterPlugin(GetPluginNameStatic(),
36
GetPluginDescriptionStatic(), CreateInstance);
37
}
38
39
void EmulateInstructionPPC64::Terminate() {
40
PluginManager::UnregisterPlugin(CreateInstance);
41
}
42
43
llvm::StringRef EmulateInstructionPPC64::GetPluginDescriptionStatic() {
44
return "Emulate instructions for the PPC64 architecture.";
45
}
46
47
EmulateInstruction *
48
EmulateInstructionPPC64::CreateInstance(const ArchSpec &arch,
49
InstructionType inst_type) {
50
if (EmulateInstructionPPC64::SupportsEmulatingInstructionsOfTypeStatic(
51
inst_type))
52
if (arch.GetTriple().isPPC64())
53
return new EmulateInstructionPPC64(arch);
54
55
return nullptr;
56
}
57
58
bool EmulateInstructionPPC64::SetTargetTriple(const ArchSpec &arch) {
59
return arch.GetTriple().isPPC64();
60
}
61
62
static std::optional<RegisterInfo> LLDBTableGetRegisterInfo(uint32_t reg_num) {
63
if (reg_num >= std::size(g_register_infos_ppc64le))
64
return {};
65
return g_register_infos_ppc64le[reg_num];
66
}
67
68
std::optional<RegisterInfo>
69
EmulateInstructionPPC64::GetRegisterInfo(RegisterKind reg_kind,
70
uint32_t reg_num) {
71
if (reg_kind == eRegisterKindGeneric) {
72
switch (reg_num) {
73
case LLDB_REGNUM_GENERIC_PC:
74
reg_kind = eRegisterKindLLDB;
75
reg_num = gpr_pc_ppc64le;
76
break;
77
case LLDB_REGNUM_GENERIC_SP:
78
reg_kind = eRegisterKindLLDB;
79
reg_num = gpr_r1_ppc64le;
80
break;
81
case LLDB_REGNUM_GENERIC_RA:
82
reg_kind = eRegisterKindLLDB;
83
reg_num = gpr_lr_ppc64le;
84
break;
85
case LLDB_REGNUM_GENERIC_FLAGS:
86
reg_kind = eRegisterKindLLDB;
87
reg_num = gpr_cr_ppc64le;
88
break;
89
90
default:
91
return {};
92
}
93
}
94
95
if (reg_kind == eRegisterKindLLDB)
96
return LLDBTableGetRegisterInfo(reg_num);
97
return {};
98
}
99
100
bool EmulateInstructionPPC64::ReadInstruction() {
101
bool success = false;
102
m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
103
LLDB_INVALID_ADDRESS, &success);
104
if (success) {
105
Context ctx;
106
ctx.type = eContextReadOpcode;
107
ctx.SetNoArgs();
108
m_opcode.SetOpcode32(ReadMemoryUnsigned(ctx, m_addr, 4, 0, &success),
109
GetByteOrder());
110
}
111
if (!success)
112
m_addr = LLDB_INVALID_ADDRESS;
113
return success;
114
}
115
116
bool EmulateInstructionPPC64::CreateFunctionEntryUnwind(
117
UnwindPlan &unwind_plan) {
118
unwind_plan.Clear();
119
unwind_plan.SetRegisterKind(eRegisterKindLLDB);
120
121
UnwindPlan::RowSP row(new UnwindPlan::Row);
122
123
// Our previous Call Frame Address is the stack pointer
124
row->GetCFAValue().SetIsRegisterPlusOffset(gpr_r1_ppc64le, 0);
125
126
unwind_plan.AppendRow(row);
127
unwind_plan.SetSourceName("EmulateInstructionPPC64");
128
unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
129
unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
130
unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
131
unwind_plan.SetReturnAddressRegister(gpr_lr_ppc64le);
132
return true;
133
}
134
135
EmulateInstructionPPC64::Opcode *
136
EmulateInstructionPPC64::GetOpcodeForInstruction(uint32_t opcode) {
137
static EmulateInstructionPPC64::Opcode g_opcodes[] = {
138
{0xfc0007ff, 0x7c0002a6, &EmulateInstructionPPC64::EmulateMFSPR,
139
"mfspr RT, SPR"},
140
{0xfc000003, 0xf8000000, &EmulateInstructionPPC64::EmulateSTD,
141
"std RS, DS(RA)"},
142
{0xfc000003, 0xf8000001, &EmulateInstructionPPC64::EmulateSTD,
143
"stdu RS, DS(RA)"},
144
{0xfc0007fe, 0x7c000378, &EmulateInstructionPPC64::EmulateOR,
145
"or RA, RS, RB"},
146
{0xfc000000, 0x38000000, &EmulateInstructionPPC64::EmulateADDI,
147
"addi RT, RA, SI"},
148
{0xfc000003, 0xe8000000, &EmulateInstructionPPC64::EmulateLD,
149
"ld RT, DS(RA)"}};
150
static const size_t k_num_ppc_opcodes = std::size(g_opcodes);
151
152
for (size_t i = 0; i < k_num_ppc_opcodes; ++i) {
153
if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value)
154
return &g_opcodes[i];
155
}
156
return nullptr;
157
}
158
159
bool EmulateInstructionPPC64::EvaluateInstruction(uint32_t evaluate_options) {
160
const uint32_t opcode = m_opcode.GetOpcode32();
161
// LLDB_LOG(log, "PPC64::EvaluateInstruction: opcode={0:X+8}", opcode);
162
Opcode *opcode_data = GetOpcodeForInstruction(opcode);
163
if (!opcode_data)
164
return false;
165
166
// LLDB_LOG(log, "PPC64::EvaluateInstruction: {0}", opcode_data->name);
167
const bool auto_advance_pc =
168
evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
169
170
bool success = false;
171
172
uint32_t orig_pc_value = 0;
173
if (auto_advance_pc) {
174
orig_pc_value =
175
ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success);
176
if (!success)
177
return false;
178
}
179
180
// Call the Emulate... function.
181
success = (this->*opcode_data->callback)(opcode);
182
if (!success)
183
return false;
184
185
if (auto_advance_pc) {
186
uint32_t new_pc_value =
187
ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success);
188
if (!success)
189
return false;
190
191
if (new_pc_value == orig_pc_value) {
192
EmulateInstruction::Context context;
193
context.type = eContextAdvancePC;
194
context.SetNoArgs();
195
if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_pc_ppc64le,
196
orig_pc_value + 4))
197
return false;
198
}
199
}
200
return true;
201
}
202
203
bool EmulateInstructionPPC64::EmulateMFSPR(uint32_t opcode) {
204
uint32_t rt = Bits32(opcode, 25, 21);
205
uint32_t spr = Bits32(opcode, 20, 11);
206
207
enum { SPR_LR = 0x100 };
208
209
// For now, we're only insterested in 'mfspr r0, lr'
210
if (rt != gpr_r0_ppc64le || spr != SPR_LR)
211
return false;
212
213
Log *log = GetLog(LLDBLog::Unwind);
214
LLDB_LOG(log, "EmulateMFSPR: {0:X+8}: mfspr r0, lr", m_addr);
215
216
bool success;
217
uint64_t lr =
218
ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success);
219
if (!success)
220
return false;
221
Context context;
222
context.type = eContextWriteRegisterRandomBits;
223
WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_r0_ppc64le, lr);
224
LLDB_LOG(log, "EmulateMFSPR: success!");
225
return true;
226
}
227
228
bool EmulateInstructionPPC64::EmulateLD(uint32_t opcode) {
229
uint32_t rt = Bits32(opcode, 25, 21);
230
uint32_t ra = Bits32(opcode, 20, 16);
231
uint32_t ds = Bits32(opcode, 15, 2);
232
233
int32_t ids = llvm::SignExtend32<16>(ds << 2);
234
235
// For now, tracking only loads from 0(r1) to r1 (0(r1) is the ABI defined
236
// location to save previous SP)
237
if (ra != gpr_r1_ppc64le || rt != gpr_r1_ppc64le || ids != 0)
238
return false;
239
240
Log *log = GetLog(LLDBLog::Unwind);
241
LLDB_LOG(log, "EmulateLD: {0:X+8}: ld r{1}, {2}(r{3})", m_addr, rt, ids, ra);
242
243
std::optional<RegisterInfo> r1_info =
244
GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le);
245
if (!r1_info)
246
return false;
247
248
// restore SP
249
Context ctx;
250
ctx.type = eContextRestoreStackPointer;
251
ctx.SetRegisterToRegisterPlusOffset(*r1_info, *r1_info, 0);
252
253
WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, 0);
254
LLDB_LOG(log, "EmulateLD: success!");
255
return true;
256
}
257
258
bool EmulateInstructionPPC64::EmulateSTD(uint32_t opcode) {
259
uint32_t rs = Bits32(opcode, 25, 21);
260
uint32_t ra = Bits32(opcode, 20, 16);
261
uint32_t ds = Bits32(opcode, 15, 2);
262
uint32_t u = Bits32(opcode, 1, 0);
263
264
// For now, tracking only stores to r1
265
if (ra != gpr_r1_ppc64le)
266
return false;
267
// ... and only stores of SP, FP and LR (moved into r0 by a previous mfspr)
268
if (rs != gpr_r1_ppc64le && rs != gpr_r31_ppc64le && rs != gpr_r30_ppc64le &&
269
rs != gpr_r0_ppc64le)
270
return false;
271
272
bool success;
273
uint64_t rs_val = ReadRegisterUnsigned(eRegisterKindLLDB, rs, 0, &success);
274
if (!success)
275
return false;
276
277
int32_t ids = llvm::SignExtend32<16>(ds << 2);
278
Log *log = GetLog(LLDBLog::Unwind);
279
LLDB_LOG(log, "EmulateSTD: {0:X+8}: std{1} r{2}, {3}(r{4})", m_addr,
280
u ? "u" : "", rs, ids, ra);
281
282
// Make sure that r0 is really holding LR value (this won't catch unlikely
283
// cases, such as r0 being overwritten after mfspr)
284
uint32_t rs_num = rs;
285
if (rs == gpr_r0_ppc64le) {
286
uint64_t lr =
287
ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success);
288
if (!success || lr != rs_val)
289
return false;
290
rs_num = gpr_lr_ppc64le;
291
}
292
293
// set context
294
std::optional<RegisterInfo> rs_info =
295
GetRegisterInfo(eRegisterKindLLDB, rs_num);
296
if (!rs_info)
297
return false;
298
std::optional<RegisterInfo> ra_info = GetRegisterInfo(eRegisterKindLLDB, ra);
299
if (!ra_info)
300
return false;
301
302
Context ctx;
303
ctx.type = eContextPushRegisterOnStack;
304
ctx.SetRegisterToRegisterPlusOffset(*rs_info, *ra_info, ids);
305
306
// store
307
uint64_t ra_val = ReadRegisterUnsigned(eRegisterKindLLDB, ra, 0, &success);
308
if (!success)
309
return false;
310
311
lldb::addr_t addr = ra_val + ids;
312
WriteMemory(ctx, addr, &rs_val, sizeof(rs_val));
313
314
// update RA?
315
if (u) {
316
Context ctx;
317
// NOTE Currently, RA will always be equal to SP(r1)
318
ctx.type = eContextAdjustStackPointer;
319
WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, addr);
320
}
321
322
LLDB_LOG(log, "EmulateSTD: success!");
323
return true;
324
}
325
326
bool EmulateInstructionPPC64::EmulateOR(uint32_t opcode) {
327
uint32_t rs = Bits32(opcode, 25, 21);
328
uint32_t ra = Bits32(opcode, 20, 16);
329
uint32_t rb = Bits32(opcode, 15, 11);
330
331
// to be safe, process only the known 'mr r31/r30, r1' prologue instructions
332
if (m_fp != LLDB_INVALID_REGNUM || rs != rb ||
333
(ra != gpr_r30_ppc64le && ra != gpr_r31_ppc64le) || rb != gpr_r1_ppc64le)
334
return false;
335
336
Log *log = GetLog(LLDBLog::Unwind);
337
LLDB_LOG(log, "EmulateOR: {0:X+8}: mr r{1}, r{2}", m_addr, ra, rb);
338
339
// set context
340
std::optional<RegisterInfo> ra_info = GetRegisterInfo(eRegisterKindLLDB, ra);
341
if (!ra_info)
342
return false;
343
344
Context ctx;
345
ctx.type = eContextSetFramePointer;
346
ctx.SetRegister(*ra_info);
347
348
// move
349
bool success;
350
uint64_t rb_val = ReadRegisterUnsigned(eRegisterKindLLDB, rb, 0, &success);
351
if (!success)
352
return false;
353
WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, rb_val);
354
m_fp = ra;
355
LLDB_LOG(log, "EmulateOR: success!");
356
return true;
357
}
358
359
bool EmulateInstructionPPC64::EmulateADDI(uint32_t opcode) {
360
uint32_t rt = Bits32(opcode, 25, 21);
361
uint32_t ra = Bits32(opcode, 20, 16);
362
uint32_t si = Bits32(opcode, 15, 0);
363
364
// handle stack adjustments only
365
// (this is a typical epilogue operation, with ra == r1. If it's
366
// something else, then we won't know the correct value of ra)
367
if (rt != gpr_r1_ppc64le || ra != gpr_r1_ppc64le)
368
return false;
369
370
int32_t si_val = llvm::SignExtend32<16>(si);
371
Log *log = GetLog(LLDBLog::Unwind);
372
LLDB_LOG(log, "EmulateADDI: {0:X+8}: addi r1, r1, {1}", m_addr, si_val);
373
374
// set context
375
std::optional<RegisterInfo> r1_info =
376
GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le);
377
if (!r1_info)
378
return false;
379
380
Context ctx;
381
ctx.type = eContextRestoreStackPointer;
382
ctx.SetRegisterToRegisterPlusOffset(*r1_info, *r1_info, 0);
383
384
// adjust SP
385
bool success;
386
uint64_t r1 =
387
ReadRegisterUnsigned(eRegisterKindLLDB, gpr_r1_ppc64le, 0, &success);
388
if (!success)
389
return false;
390
WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, r1 + si_val);
391
LLDB_LOG(log, "EmulateADDI: success!");
392
return true;
393
}
394
395