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 #include <optional> 13 14 #include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h" 15 #include "lldb/Core/PluginManager.h" 16 #include "lldb/Symbol/UnwindPlan.h" 17 #include "lldb/Utility/ArchSpec.h" 18 #include "lldb/Utility/ConstString.h" 19 #include "lldb/Utility/LLDBLog.h" 20 21 #define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT 22 #include "Plugins/Process/Utility/RegisterInfos_ppc64le.h" 23 24 #include "Plugins/Process/Utility/InstructionUtils.h" 25 26 using namespace lldb; 27 using namespace lldb_private; 28 29 LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionPPC64, InstructionPPC64) 30 31 EmulateInstructionPPC64::EmulateInstructionPPC64(const ArchSpec &arch) 32 : EmulateInstruction(arch) {} 33 34 void EmulateInstructionPPC64::Initialize() { 35 PluginManager::RegisterPlugin(GetPluginNameStatic(), 36 GetPluginDescriptionStatic(), CreateInstance); 37 } 38 39 void EmulateInstructionPPC64::Terminate() { 40 PluginManager::UnregisterPlugin(CreateInstance); 41 } 42 43 llvm::StringRef EmulateInstructionPPC64::GetPluginDescriptionStatic() { 44 return "Emulate instructions for the PPC64 architecture."; 45 } 46 47 EmulateInstruction * 48 EmulateInstructionPPC64::CreateInstance(const ArchSpec &arch, 49 InstructionType inst_type) { 50 if (EmulateInstructionPPC64::SupportsEmulatingInstructionsOfTypeStatic( 51 inst_type)) 52 if (arch.GetTriple().isPPC64()) 53 return new EmulateInstructionPPC64(arch); 54 55 return nullptr; 56 } 57 58 bool EmulateInstructionPPC64::SetTargetTriple(const ArchSpec &arch) { 59 return arch.GetTriple().isPPC64(); 60 } 61 62 static std::optional<RegisterInfo> LLDBTableGetRegisterInfo(uint32_t reg_num) { 63 if (reg_num >= std::size(g_register_infos_ppc64le)) 64 return {}; 65 return g_register_infos_ppc64le[reg_num]; 66 } 67 68 std::optional<RegisterInfo> 69 EmulateInstructionPPC64::GetRegisterInfo(RegisterKind reg_kind, 70 uint32_t reg_num) { 71 if (reg_kind == eRegisterKindGeneric) { 72 switch (reg_num) { 73 case LLDB_REGNUM_GENERIC_PC: 74 reg_kind = eRegisterKindLLDB; 75 reg_num = gpr_pc_ppc64le; 76 break; 77 case LLDB_REGNUM_GENERIC_SP: 78 reg_kind = eRegisterKindLLDB; 79 reg_num = gpr_r1_ppc64le; 80 break; 81 case LLDB_REGNUM_GENERIC_RA: 82 reg_kind = eRegisterKindLLDB; 83 reg_num = gpr_lr_ppc64le; 84 break; 85 case LLDB_REGNUM_GENERIC_FLAGS: 86 reg_kind = eRegisterKindLLDB; 87 reg_num = gpr_cr_ppc64le; 88 break; 89 90 default: 91 return {}; 92 } 93 } 94 95 if (reg_kind == eRegisterKindLLDB) 96 return LLDBTableGetRegisterInfo(reg_num); 97 return {}; 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 121 UnwindPlan::RowSP row(new UnwindPlan::Row); 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); 129 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); 130 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); 131 unwind_plan.SetReturnAddressRegister(gpr_lr_ppc64le); 132 return true; 133 } 134 135 EmulateInstructionPPC64::Opcode * 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 = std::size(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) { 192 EmulateInstruction::Context context; 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 std::optional<RegisterInfo> r1_info = 244 GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le); 245 if (!r1_info) 246 return false; 247 248 // restore SP 249 Context ctx; 250 ctx.type = eContextRestoreStackPointer; 251 ctx.SetRegisterToRegisterPlusOffset(*r1_info, *r1_info, 0); 252 253 WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, 0); 254 LLDB_LOG(log, "EmulateLD: success!"); 255 return true; 256 } 257 258 bool EmulateInstructionPPC64::EmulateSTD(uint32_t opcode) { 259 uint32_t rs = Bits32(opcode, 25, 21); 260 uint32_t ra = Bits32(opcode, 20, 16); 261 uint32_t ds = Bits32(opcode, 15, 2); 262 uint32_t u = Bits32(opcode, 1, 0); 263 264 // For now, tracking only stores to r1 265 if (ra != gpr_r1_ppc64le) 266 return false; 267 // ... and only stores of SP, FP and LR (moved into r0 by a previous mfspr) 268 if (rs != gpr_r1_ppc64le && rs != gpr_r31_ppc64le && rs != gpr_r30_ppc64le && 269 rs != gpr_r0_ppc64le) 270 return false; 271 272 bool success; 273 uint64_t rs_val = ReadRegisterUnsigned(eRegisterKindLLDB, rs, 0, &success); 274 if (!success) 275 return false; 276 277 int32_t ids = llvm::SignExtend32<16>(ds << 2); 278 Log *log = GetLog(LLDBLog::Unwind); 279 LLDB_LOG(log, "EmulateSTD: {0:X+8}: std{1} r{2}, {3}(r{4})", m_addr, 280 u ? "u" : "", rs, ids, ra); 281 282 // Make sure that r0 is really holding LR value (this won't catch unlikely 283 // cases, such as r0 being overwritten after mfspr) 284 uint32_t rs_num = rs; 285 if (rs == gpr_r0_ppc64le) { 286 uint64_t lr = 287 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success); 288 if (!success || lr != rs_val) 289 return false; 290 rs_num = gpr_lr_ppc64le; 291 } 292 293 // set context 294 std::optional<RegisterInfo> rs_info = 295 GetRegisterInfo(eRegisterKindLLDB, rs_num); 296 if (!rs_info) 297 return false; 298 std::optional<RegisterInfo> ra_info = GetRegisterInfo(eRegisterKindLLDB, ra); 299 if (!ra_info) 300 return false; 301 302 Context ctx; 303 ctx.type = eContextPushRegisterOnStack; 304 ctx.SetRegisterToRegisterPlusOffset(*rs_info, *ra_info, ids); 305 306 // store 307 uint64_t ra_val = ReadRegisterUnsigned(eRegisterKindLLDB, ra, 0, &success); 308 if (!success) 309 return false; 310 311 lldb::addr_t addr = ra_val + ids; 312 WriteMemory(ctx, addr, &rs_val, sizeof(rs_val)); 313 314 // update RA? 315 if (u) { 316 Context ctx; 317 // NOTE Currently, RA will always be equal to SP(r1) 318 ctx.type = eContextAdjustStackPointer; 319 WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, addr); 320 } 321 322 LLDB_LOG(log, "EmulateSTD: success!"); 323 return true; 324 } 325 326 bool EmulateInstructionPPC64::EmulateOR(uint32_t opcode) { 327 uint32_t rs = Bits32(opcode, 25, 21); 328 uint32_t ra = Bits32(opcode, 20, 16); 329 uint32_t rb = Bits32(opcode, 15, 11); 330 331 // to be safe, process only the known 'mr r31/r30, r1' prologue instructions 332 if (m_fp != LLDB_INVALID_REGNUM || rs != rb || 333 (ra != gpr_r30_ppc64le && ra != gpr_r31_ppc64le) || rb != gpr_r1_ppc64le) 334 return false; 335 336 Log *log = GetLog(LLDBLog::Unwind); 337 LLDB_LOG(log, "EmulateOR: {0:X+8}: mr r{1}, r{2}", m_addr, ra, rb); 338 339 // set context 340 std::optional<RegisterInfo> ra_info = GetRegisterInfo(eRegisterKindLLDB, ra); 341 if (!ra_info) 342 return false; 343 344 Context ctx; 345 ctx.type = eContextSetFramePointer; 346 ctx.SetRegister(*ra_info); 347 348 // move 349 bool success; 350 uint64_t rb_val = ReadRegisterUnsigned(eRegisterKindLLDB, rb, 0, &success); 351 if (!success) 352 return false; 353 WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, rb_val); 354 m_fp = ra; 355 LLDB_LOG(log, "EmulateOR: success!"); 356 return true; 357 } 358 359 bool EmulateInstructionPPC64::EmulateADDI(uint32_t opcode) { 360 uint32_t rt = Bits32(opcode, 25, 21); 361 uint32_t ra = Bits32(opcode, 20, 16); 362 uint32_t si = Bits32(opcode, 15, 0); 363 364 // handle stack adjustments only 365 // (this is a typical epilogue operation, with ra == r1. If it's 366 // something else, then we won't know the correct value of ra) 367 if (rt != gpr_r1_ppc64le || ra != gpr_r1_ppc64le) 368 return false; 369 370 int32_t si_val = llvm::SignExtend32<16>(si); 371 Log *log = GetLog(LLDBLog::Unwind); 372 LLDB_LOG(log, "EmulateADDI: {0:X+8}: addi r1, r1, {1}", m_addr, si_val); 373 374 // set context 375 std::optional<RegisterInfo> r1_info = 376 GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le); 377 if (!r1_info) 378 return false; 379 380 Context ctx; 381 ctx.type = eContextRestoreStackPointer; 382 ctx.SetRegisterToRegisterPlusOffset(*r1_info, *r1_info, 0); 383 384 // adjust SP 385 bool success; 386 uint64_t r1 = 387 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_r1_ppc64le, 0, &success); 388 if (!success) 389 return false; 390 WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, r1 + si_val); 391 LLDB_LOG(log, "EmulateADDI: success!"); 392 return true; 393 } 394