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