Coverage Report

Created: 2022-01-15 10:30

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