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