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