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 "Plugins/Process/Utility/lldb-ppc64le-register-enums.h" 14 #include "lldb/Core/PluginManager.h" 15 #include "lldb/Symbol/UnwindPlan.h" 16 #include "lldb/Utility/ArchSpec.h" 17 #include "lldb/Utility/ConstString.h" 18 #include "lldb/Utility/LLDBLog.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 : 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 46 EmulateInstruction * 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 ®_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 ®_info) { 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 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 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 = 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) { 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 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 } 391