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