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