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