1*d409305fSDimitry Andric //===-- NativeProcessSoftwareSingleStep.cpp -------------------------------===// 2*d409305fSDimitry Andric // 3*d409305fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*d409305fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*d409305fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*d409305fSDimitry Andric // 7*d409305fSDimitry Andric //===----------------------------------------------------------------------===// 8*d409305fSDimitry Andric 9*d409305fSDimitry Andric #include "NativeProcessSoftwareSingleStep.h" 10*d409305fSDimitry Andric 11*d409305fSDimitry Andric #include "lldb/Core/EmulateInstruction.h" 12*d409305fSDimitry Andric #include "lldb/Host/common/NativeRegisterContext.h" 13*d409305fSDimitry Andric #include "lldb/Utility/RegisterValue.h" 14*d409305fSDimitry Andric 15*d409305fSDimitry Andric #include <unordered_map> 16*d409305fSDimitry Andric 17*d409305fSDimitry Andric using namespace lldb; 18*d409305fSDimitry Andric using namespace lldb_private; 19*d409305fSDimitry Andric 20*d409305fSDimitry Andric namespace { 21*d409305fSDimitry Andric 22*d409305fSDimitry Andric struct EmulatorBaton { 23*d409305fSDimitry Andric NativeProcessProtocol &m_process; 24*d409305fSDimitry Andric NativeRegisterContext &m_reg_context; 25*d409305fSDimitry Andric 26*d409305fSDimitry Andric // eRegisterKindDWARF -> RegsiterValue 27*d409305fSDimitry Andric std::unordered_map<uint32_t, RegisterValue> m_register_values; 28*d409305fSDimitry Andric 29*d409305fSDimitry Andric EmulatorBaton(NativeProcessProtocol &process, 30*d409305fSDimitry Andric NativeRegisterContext ®_context) 31*d409305fSDimitry Andric : m_process(process), m_reg_context(reg_context) {} 32*d409305fSDimitry Andric }; 33*d409305fSDimitry Andric 34*d409305fSDimitry Andric } // anonymous namespace 35*d409305fSDimitry Andric 36*d409305fSDimitry Andric static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton, 37*d409305fSDimitry Andric const EmulateInstruction::Context &context, 38*d409305fSDimitry Andric lldb::addr_t addr, void *dst, size_t length) { 39*d409305fSDimitry Andric EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); 40*d409305fSDimitry Andric 41*d409305fSDimitry Andric size_t bytes_read; 42*d409305fSDimitry Andric emulator_baton->m_process.ReadMemory(addr, dst, length, bytes_read); 43*d409305fSDimitry Andric return bytes_read; 44*d409305fSDimitry Andric } 45*d409305fSDimitry Andric 46*d409305fSDimitry Andric static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton, 47*d409305fSDimitry Andric const RegisterInfo *reg_info, 48*d409305fSDimitry Andric RegisterValue ®_value) { 49*d409305fSDimitry Andric EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); 50*d409305fSDimitry Andric 51*d409305fSDimitry Andric auto it = emulator_baton->m_register_values.find( 52*d409305fSDimitry Andric reg_info->kinds[eRegisterKindDWARF]); 53*d409305fSDimitry Andric if (it != emulator_baton->m_register_values.end()) { 54*d409305fSDimitry Andric reg_value = it->second; 55*d409305fSDimitry Andric return true; 56*d409305fSDimitry Andric } 57*d409305fSDimitry Andric 58*d409305fSDimitry Andric // The emulator only fill in the dwarf regsiter numbers (and in some case the 59*d409305fSDimitry Andric // generic register numbers). Get the full register info from the register 60*d409305fSDimitry Andric // context based on the dwarf register numbers. 61*d409305fSDimitry Andric const RegisterInfo *full_reg_info = 62*d409305fSDimitry Andric emulator_baton->m_reg_context.GetRegisterInfo( 63*d409305fSDimitry Andric eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]); 64*d409305fSDimitry Andric 65*d409305fSDimitry Andric Status error = 66*d409305fSDimitry Andric emulator_baton->m_reg_context.ReadRegister(full_reg_info, reg_value); 67*d409305fSDimitry Andric if (error.Success()) 68*d409305fSDimitry Andric return true; 69*d409305fSDimitry Andric 70*d409305fSDimitry Andric return false; 71*d409305fSDimitry Andric } 72*d409305fSDimitry Andric 73*d409305fSDimitry Andric static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton, 74*d409305fSDimitry Andric const EmulateInstruction::Context &context, 75*d409305fSDimitry Andric const RegisterInfo *reg_info, 76*d409305fSDimitry Andric const RegisterValue ®_value) { 77*d409305fSDimitry Andric EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); 78*d409305fSDimitry Andric emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] = 79*d409305fSDimitry Andric reg_value; 80*d409305fSDimitry Andric return true; 81*d409305fSDimitry Andric } 82*d409305fSDimitry Andric 83*d409305fSDimitry Andric static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton, 84*d409305fSDimitry Andric const EmulateInstruction::Context &context, 85*d409305fSDimitry Andric lldb::addr_t addr, const void *dst, 86*d409305fSDimitry Andric size_t length) { 87*d409305fSDimitry Andric return length; 88*d409305fSDimitry Andric } 89*d409305fSDimitry Andric 90*d409305fSDimitry Andric static lldb::addr_t ReadFlags(NativeRegisterContext ®siter_context) { 91*d409305fSDimitry Andric const RegisterInfo *flags_info = regsiter_context.GetRegisterInfo( 92*d409305fSDimitry Andric eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); 93*d409305fSDimitry Andric return regsiter_context.ReadRegisterAsUnsigned(flags_info, 94*d409305fSDimitry Andric LLDB_INVALID_ADDRESS); 95*d409305fSDimitry Andric } 96*d409305fSDimitry Andric 97*d409305fSDimitry Andric Status NativeProcessSoftwareSingleStep::SetupSoftwareSingleStepping( 98*d409305fSDimitry Andric NativeThreadProtocol &thread) { 99*d409305fSDimitry Andric Status error; 100*d409305fSDimitry Andric NativeProcessProtocol &process = thread.GetProcess(); 101*d409305fSDimitry Andric NativeRegisterContext ®ister_context = thread.GetRegisterContext(); 102*d409305fSDimitry Andric const ArchSpec &arch = process.GetArchitecture(); 103*d409305fSDimitry Andric 104*d409305fSDimitry Andric std::unique_ptr<EmulateInstruction> emulator_up( 105*d409305fSDimitry Andric EmulateInstruction::FindPlugin(arch, eInstructionTypePCModifying, 106*d409305fSDimitry Andric nullptr)); 107*d409305fSDimitry Andric 108*d409305fSDimitry Andric if (emulator_up == nullptr) 109*d409305fSDimitry Andric return Status("Instruction emulator not found!"); 110*d409305fSDimitry Andric 111*d409305fSDimitry Andric EmulatorBaton baton(process, register_context); 112*d409305fSDimitry Andric emulator_up->SetBaton(&baton); 113*d409305fSDimitry Andric emulator_up->SetReadMemCallback(&ReadMemoryCallback); 114*d409305fSDimitry Andric emulator_up->SetReadRegCallback(&ReadRegisterCallback); 115*d409305fSDimitry Andric emulator_up->SetWriteMemCallback(&WriteMemoryCallback); 116*d409305fSDimitry Andric emulator_up->SetWriteRegCallback(&WriteRegisterCallback); 117*d409305fSDimitry Andric 118*d409305fSDimitry Andric if (!emulator_up->ReadInstruction()) 119*d409305fSDimitry Andric return Status("Read instruction failed!"); 120*d409305fSDimitry Andric 121*d409305fSDimitry Andric bool emulation_result = 122*d409305fSDimitry Andric emulator_up->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC); 123*d409305fSDimitry Andric 124*d409305fSDimitry Andric const RegisterInfo *reg_info_pc = register_context.GetRegisterInfo( 125*d409305fSDimitry Andric eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 126*d409305fSDimitry Andric const RegisterInfo *reg_info_flags = register_context.GetRegisterInfo( 127*d409305fSDimitry Andric eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); 128*d409305fSDimitry Andric 129*d409305fSDimitry Andric auto pc_it = 130*d409305fSDimitry Andric baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]); 131*d409305fSDimitry Andric auto flags_it = 132*d409305fSDimitry Andric baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]); 133*d409305fSDimitry Andric 134*d409305fSDimitry Andric lldb::addr_t next_pc; 135*d409305fSDimitry Andric lldb::addr_t next_flags; 136*d409305fSDimitry Andric if (emulation_result) { 137*d409305fSDimitry Andric assert(pc_it != baton.m_register_values.end() && 138*d409305fSDimitry Andric "Emulation was successfull but PC wasn't updated"); 139*d409305fSDimitry Andric next_pc = pc_it->second.GetAsUInt64(); 140*d409305fSDimitry Andric 141*d409305fSDimitry Andric if (flags_it != baton.m_register_values.end()) 142*d409305fSDimitry Andric next_flags = flags_it->second.GetAsUInt64(); 143*d409305fSDimitry Andric else 144*d409305fSDimitry Andric next_flags = ReadFlags(register_context); 145*d409305fSDimitry Andric } else if (pc_it == baton.m_register_values.end()) { 146*d409305fSDimitry Andric // Emulate instruction failed and it haven't changed PC. Advance PC with 147*d409305fSDimitry Andric // the size of the current opcode because the emulation of all 148*d409305fSDimitry Andric // PC modifying instruction should be successful. The failure most 149*d409305fSDimitry Andric // likely caused by a not supported instruction which don't modify PC. 150*d409305fSDimitry Andric next_pc = register_context.GetPC() + emulator_up->GetOpcode().GetByteSize(); 151*d409305fSDimitry Andric next_flags = ReadFlags(register_context); 152*d409305fSDimitry Andric } else { 153*d409305fSDimitry Andric // The instruction emulation failed after it modified the PC. It is an 154*d409305fSDimitry Andric // unknown error where we can't continue because the next instruction is 155*d409305fSDimitry Andric // modifying the PC but we don't know how. 156*d409305fSDimitry Andric return Status("Instruction emulation failed unexpectedly."); 157*d409305fSDimitry Andric } 158*d409305fSDimitry Andric 159*d409305fSDimitry Andric int size_hint = 0; 160*d409305fSDimitry Andric if (arch.GetMachine() == llvm::Triple::arm) { 161*d409305fSDimitry Andric if (next_flags & 0x20) { 162*d409305fSDimitry Andric // Thumb mode 163*d409305fSDimitry Andric size_hint = 2; 164*d409305fSDimitry Andric } else { 165*d409305fSDimitry Andric // Arm mode 166*d409305fSDimitry Andric size_hint = 4; 167*d409305fSDimitry Andric } 168*d409305fSDimitry Andric } else if (arch.IsMIPS() || arch.GetTriple().isPPC64()) 169*d409305fSDimitry Andric size_hint = 4; 170*d409305fSDimitry Andric error = process.SetBreakpoint(next_pc, size_hint, /*hardware=*/false); 171*d409305fSDimitry Andric 172*d409305fSDimitry Andric // If setting the breakpoint fails because next_pc is out of the address 173*d409305fSDimitry Andric // space, ignore it and let the debugee segfault. 174*d409305fSDimitry Andric if (error.GetError() == EIO || error.GetError() == EFAULT) { 175*d409305fSDimitry Andric return Status(); 176*d409305fSDimitry Andric } else if (error.Fail()) 177*d409305fSDimitry Andric return error; 178*d409305fSDimitry Andric 179*d409305fSDimitry Andric m_threads_stepping_with_breakpoint.insert({thread.GetID(), next_pc}); 180*d409305fSDimitry Andric 181*d409305fSDimitry Andric return Status(); 182*d409305fSDimitry Andric } 183