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 <cstdlib>
12 
15 #include "lldb/Symbol/UnwindPlan.h"
16 #include "lldb/Utility/ArchSpec.h"
18 #include "lldb/Utility/LLDBLog.h"
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 llvm::StringRef EmulateInstructionPPC64::GetPluginDescriptionStatic() {
43  return "Emulate instructions for the PPC64 architecture.";
44 }
45 
47 EmulateInstructionPPC64::CreateInstance(const ArchSpec &arch,
48  InstructionType inst_type) {
49  if (EmulateInstructionPPC64::SupportsEmulatingInstructionsOfTypeStatic(
50  inst_type))
51  if (arch.GetTriple().isPPC64())
52  return new EmulateInstructionPPC64(arch);
53 
54  return nullptr;
55 }
56 
57 bool EmulateInstructionPPC64::SetTargetTriple(const ArchSpec &arch) {
58  return arch.GetTriple().isPPC64();
59 }
60 
61 static bool LLDBTableGetRegisterInfo(uint32_t reg_num, RegisterInfo &reg_info) {
62  if (reg_num >= llvm::array_lengthof(g_register_infos_ppc64le))
63  return false;
64  reg_info = g_register_infos_ppc64le[reg_num];
65  return true;
66 }
67 
68 bool EmulateInstructionPPC64::GetRegisterInfo(RegisterKind reg_kind,
69  uint32_t reg_num,
70  RegisterInfo &reg_info) {
71  if (reg_kind == eRegisterKindGeneric) {
72  switch (reg_num) {
74  reg_kind = eRegisterKindLLDB;
75  reg_num = gpr_pc_ppc64le;
76  break;
78  reg_kind = eRegisterKindLLDB;
79  reg_num = gpr_r1_ppc64le;
80  break;
82  reg_kind = eRegisterKindLLDB;
83  reg_num = gpr_lr_ppc64le;
84  break;
86  reg_kind = eRegisterKindLLDB;
87  reg_num = gpr_cr_ppc64le;
88  break;
89 
90  default:
91  return false;
92  }
93  }
94 
95  if (reg_kind == eRegisterKindLLDB)
96  return LLDBTableGetRegisterInfo(reg_num, reg_info);
97  return false;
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 
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);
132  return true;
133 }
134 
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 = llvm::array_lengthof(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) {
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  RegisterInfo r1_info;
244  if (!GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le, r1_info))
245  return false;
246 
247  // restore SP
248  Context ctx;
249  ctx.type = eContextRestoreStackPointer;
250  ctx.SetRegisterToRegisterPlusOffset(r1_info, r1_info, 0);
251 
252  WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, 0);
253  LLDB_LOG(log, "EmulateLD: success!");
254  return true;
255 }
256 
257 bool EmulateInstructionPPC64::EmulateSTD(uint32_t opcode) {
258  uint32_t rs = Bits32(opcode, 25, 21);
259  uint32_t ra = Bits32(opcode, 20, 16);
260  uint32_t ds = Bits32(opcode, 15, 2);
261  uint32_t u = Bits32(opcode, 1, 0);
262 
263  // For now, tracking only stores to r1
264  if (ra != gpr_r1_ppc64le)
265  return false;
266  // ... and only stores of SP, FP and LR (moved into r0 by a previous mfspr)
267  if (rs != gpr_r1_ppc64le && rs != gpr_r31_ppc64le && rs != gpr_r30_ppc64le &&
268  rs != gpr_r0_ppc64le)
269  return false;
270 
271  bool success;
272  uint64_t rs_val = ReadRegisterUnsigned(eRegisterKindLLDB, rs, 0, &success);
273  if (!success)
274  return false;
275 
276  int32_t ids = llvm::SignExtend32<16>(ds << 2);
277  Log *log = GetLog(LLDBLog::Unwind);
278  LLDB_LOG(log, "EmulateSTD: {0:X+8}: std{1} r{2}, {3}(r{4})", m_addr,
279  u ? "u" : "", rs, ids, ra);
280 
281  // Make sure that r0 is really holding LR value (this won't catch unlikely
282  // cases, such as r0 being overwritten after mfspr)
283  uint32_t rs_num = rs;
284  if (rs == gpr_r0_ppc64le) {
285  uint64_t lr =
286  ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success);
287  if (!success || lr != rs_val)
288  return false;
289  rs_num = gpr_lr_ppc64le;
290  }
291 
292  // set context
293  RegisterInfo rs_info;
294  if (!GetRegisterInfo(eRegisterKindLLDB, rs_num, rs_info))
295  return false;
296  RegisterInfo ra_info;
297  if (!GetRegisterInfo(eRegisterKindLLDB, ra, ra_info))
298  return false;
299 
300  Context ctx;
301  ctx.type = eContextPushRegisterOnStack;
302  ctx.SetRegisterToRegisterPlusOffset(rs_info, ra_info, ids);
303 
304  // store
305  uint64_t ra_val = ReadRegisterUnsigned(eRegisterKindLLDB, ra, 0, &success);
306  if (!success)
307  return false;
308 
309  lldb::addr_t addr = ra_val + ids;
310  WriteMemory(ctx, addr, &rs_val, sizeof(rs_val));
311 
312  // update RA?
313  if (u) {
314  Context ctx;
315  // NOTE Currently, RA will always be equal to SP(r1)
316  ctx.type = eContextAdjustStackPointer;
317  WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, addr);
318  }
319 
320  LLDB_LOG(log, "EmulateSTD: success!");
321  return true;
322 }
323 
324 bool EmulateInstructionPPC64::EmulateOR(uint32_t opcode) {
325  uint32_t rs = Bits32(opcode, 25, 21);
326  uint32_t ra = Bits32(opcode, 20, 16);
327  uint32_t rb = Bits32(opcode, 15, 11);
328 
329  // to be safe, process only the known 'mr r31/r30, r1' prologue instructions
330  if (m_fp != LLDB_INVALID_REGNUM || rs != rb ||
331  (ra != gpr_r30_ppc64le && ra != gpr_r31_ppc64le) || rb != gpr_r1_ppc64le)
332  return false;
333 
334  Log *log = GetLog(LLDBLog::Unwind);
335  LLDB_LOG(log, "EmulateOR: {0:X+8}: mr r{1}, r{2}", m_addr, ra, rb);
336 
337  // set context
338  RegisterInfo ra_info;
339  if (!GetRegisterInfo(eRegisterKindLLDB, ra, ra_info))
340  return false;
341 
342  Context ctx;
343  ctx.type = eContextSetFramePointer;
344  ctx.SetRegister(ra_info);
345 
346  // move
347  bool success;
348  uint64_t rb_val = ReadRegisterUnsigned(eRegisterKindLLDB, rb, 0, &success);
349  if (!success)
350  return false;
351  WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, rb_val);
352  m_fp = ra;
353  LLDB_LOG(log, "EmulateOR: success!");
354  return true;
355 }
356 
357 bool EmulateInstructionPPC64::EmulateADDI(uint32_t opcode) {
358  uint32_t rt = Bits32(opcode, 25, 21);
359  uint32_t ra = Bits32(opcode, 20, 16);
360  uint32_t si = Bits32(opcode, 15, 0);
361 
362  // handle stack adjustments only
363  // (this is a typical epilogue operation, with ra == r1. If it's
364  // something else, then we won't know the correct value of ra)
365  if (rt != gpr_r1_ppc64le || ra != gpr_r1_ppc64le)
366  return false;
367 
368  int32_t si_val = llvm::SignExtend32<16>(si);
369  Log *log = GetLog(LLDBLog::Unwind);
370  LLDB_LOG(log, "EmulateADDI: {0:X+8}: addi r1, r1, {1}", m_addr, si_val);
371 
372  // set context
373  RegisterInfo r1_info;
374  if (!GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le, r1_info))
375  return false;
376 
377  Context ctx;
378  ctx.type = eContextRestoreStackPointer;
379  ctx.SetRegisterToRegisterPlusOffset(r1_info, r1_info, 0);
380 
381  // adjust SP
382  bool success;
383  uint64_t r1 =
384  ReadRegisterUnsigned(eRegisterKindLLDB, gpr_r1_ppc64le, 0, &success);
385  if (!success)
386  return false;
387  WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, r1 + si_val);
388  LLDB_LOG(log, "EmulateADDI: success!");
389  return true;
390 }
lldb_private::EmulateInstructionPPC64::Opcode::callback
bool(EmulateInstructionPPC64::* callback)(uint32_t opcode)
Definition: EmulateInstructionPPC64.h:73
lldb_private::UnwindPlan::AppendRow
void AppendRow(const RowSP &row_sp)
Definition: UnwindPlan.cpp:362
lldb_private::ArchSpec
Definition: ArchSpec.h:33
LLDB_INVALID_REGNUM
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:79
lldb_private::UnwindPlan::SetRegisterKind
void SetRegisterKind(lldb::RegisterKind kind)
Definition: UnwindPlan.h:437
lldb::eRegisterKindGeneric
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target
Definition: lldb-enumerations.h:230
EmulateInstructionPPC64.h
lldb_private::EmulateInstructionPPC64::Opcode
Definition: EmulateInstructionPPC64.h:70
lldb_private::UnwindPlan::SetUnwindPlanValidAtAllInstructions
void SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)
Definition: UnwindPlan.h:490
lldb_private::eLazyBoolYes
@ eLazyBoolYes
Definition: lldb-private-enumerations.h:115
lldb_private::EmulateInstruction::Context
Definition: EmulateInstruction.h:184
arm64_dwarf::lr
@ lr
Definition: ARM64_DWARF_Registers.h:49
lldb_private::EmulateInstructionPPC64
Definition: EmulateInstructionPPC64.h:18
lldb_private::UnwindPlan::SetUnwindPlanForSignalTrap
void SetUnwindPlanForSignalTrap(lldb_private::LazyBool is_for_signal_trap)
Definition: UnwindPlan.h:502
ra
@ ra
Definition: CompactUnwindInfo.cpp:1249
lldb_private::ArchSpec::GetTriple
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:455
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
lldb_private::UnwindPlan::SetSourceName
void SetSourceName(const char *)
Definition: UnwindPlan.cpp:564
LLDB_PLUGIN_DEFINE_ADV
LLDB_PLUGIN_DEFINE_ADV(ObjectContainerUniversalMachO, ObjectContainerMachOArchive) void ObjectContainerUniversalMachO
Definition: ObjectContainerUniversalMachO.cpp:23
LLDB_REGNUM_GENERIC_FLAGS
#define LLDB_REGNUM_GENERIC_FLAGS
Definition: lldb-defines.h:55
lldb_private::EmulateInstruction::Context::SetRegister
void SetRegister(RegisterInfo reg)
Definition: EmulateInstruction.h:285
lldb::eRegisterKindLLDB
@ eRegisterKindLLDB
lldb's internal register numbers
Definition: lldb-enumerations.h:234
gpr_r30_ppc64le
@ gpr_r30_ppc64le
Definition: lldb-ppc64le-register-enums.h:47
lldb_private::UnwindPlan::SetReturnAddressRegister
void SetReturnAddressRegister(uint32_t regnum)
Definition: UnwindPlan.h:439
lldb_private::EmulateInstruction::Context::type
ContextType type
Definition: EmulateInstruction.h:185
lldb_private::UnwindPlan::SetSourcedFromCompiler
void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)
Definition: UnwindPlan.h:478
LLDBTableGetRegisterInfo
static bool LLDBTableGetRegisterInfo(uint32_t reg_num, RegisterInfo &reg_info)
Definition: EmulateInstructionPPC64.cpp:61
lldb_private::EmulateInstruction::Context::SetRegisterToRegisterPlusOffset
void SetRegisterToRegisterPlusOffset(RegisterInfo data_reg, RegisterInfo base_reg, int64_t offset)
Definition: EmulateInstruction.h:255
gpr_r31_ppc64le
@ gpr_r31_ppc64le
Definition: lldb-ppc64le-register-enums.h:48
gpr_r0_ppc64le
@ gpr_r0_ppc64le
Definition: lldb-ppc64le-register-enums.h:17
UnwindPlan.h
InstructionUtils.h
lldb::RegisterKind
RegisterKind
Register numbering types.
Definition: lldb-enumerations.h:227
lldb_private::UnwindPlan::RowSP
std::shared_ptr< Row > RowSP
Definition: UnwindPlan.h:395
lldb-ppc64le-register-enums.h
gpr_cr_ppc64le
@ gpr_cr_ppc64le
Definition: lldb-ppc64le-register-enums.h:55
lldb_private::UnwindPlan::Clear
void Clear()
Definition: UnwindPlan.h:508
lldb_private::EmulateInstruction::Context::SetNoArgs
void SetNoArgs()
Definition: EmulateInstruction.h:321
lldb_private::UnwindPlan::Row
Definition: UnwindPlan.h:55
uint32_t
lldb_private::eLazyBoolNo
@ eLazyBoolNo
Definition: lldb-private-enumerations.h:115
lldb_private::EmulateInstruction
Definition: EmulateInstruction.h:93
LLDB_REGNUM_GENERIC_SP
#define LLDB_REGNUM_GENERIC_SP
Definition: lldb-defines.h:52
ArchSpec.h
gpr_pc_ppc64le
@ gpr_pc_ppc64le
Definition: lldb-ppc64le-register-enums.h:49
gpr_lr_ppc64le
@ gpr_lr_ppc64le
Definition: lldb-ppc64le-register-enums.h:53
PluginManager.h
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:74
LLDB_LOG
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:336
lldb_private::InstructionType
InstructionType
Instruction types.
Definition: lldb-private-enumerations.h:118
gpr_r1_ppc64le
@ gpr_r1_ppc64le
Definition: lldb-ppc64le-register-enums.h:18
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
LLDB_REGNUM_GENERIC_PC
#define LLDB_REGNUM_GENERIC_PC
Definition: lldb-defines.h:51
RegisterInfos_ppc64le.h
ConstString.h
lldb_private::Log
Definition: Log.h:115
lldb_private::GetLog
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:308
lldb_private::UnwindPlan
Definition: UnwindPlan.h:53
lldb
Definition: SBAddress.h:15
LLDBLog.h
lldb_private::Bits32
static uint32_t Bits32(const uint32_t bits, const uint32_t msbit, const uint32_t lsbit)
Definition: InstructionUtils.h:29
LLDB_REGNUM_GENERIC_RA
#define LLDB_REGNUM_GENERIC_RA
Definition: lldb-defines.h:54