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