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