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