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