LLDB mainline
NativeProcessSoftwareSingleStep.cpp
Go to the documentation of this file.
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
10
14
15#include <unordered_map>
16
17using namespace lldb;
18using namespace lldb_private;
19
20namespace {
21
22struct 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 &reg_context)
31 : m_process(process), m_reg_context(reg_context) {}
32};
33
34} // anonymous namespace
35
36static 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
46static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton,
47 const RegisterInfo *reg_info,
48 RegisterValue &reg_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(
64
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
73static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton,
74 const EmulateInstruction::Context &context,
75 const RegisterInfo *reg_info,
76 const RegisterValue &reg_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
83static 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
90static lldb::addr_t ReadFlags(NativeRegisterContext &regsiter_context) {
91 const RegisterInfo *flags_info = regsiter_context.GetRegisterInfo(
93 return regsiter_context.ReadRegisterAsUnsigned(flags_info,
95}
96
97static int GetSoftwareBreakpointSize(const ArchSpec &arch,
98 lldb::addr_t next_flags) {
99 if (arch.GetMachine() == llvm::Triple::arm) {
100 if (next_flags & 0x20)
101 // Thumb mode
102 return 2;
103 // Arm mode
104 return 4;
105 }
106 if (arch.IsMIPS() || arch.GetTriple().isPPC64() ||
107 arch.GetTriple().isRISCV() || arch.GetTriple().isLoongArch())
108 return 4;
109 return 0;
110}
111
113 lldb::addr_t next_flags,
114 NativeProcessProtocol &process) {
115 int size_hint = GetSoftwareBreakpointSize(arch, next_flags);
117 error = process.SetBreakpoint(pc, size_hint, /*hardware=*/false);
118
119 // If setting the breakpoint fails because pc is out of the address
120 // space, ignore it and let the debugee segfault.
121 if (error.GetError() == EIO || error.GetError() == EFAULT)
122 return Status();
123 if (error.Fail())
124 return error;
125
126 return Status();
127}
128
130 NativeThreadProtocol &thread) {
132 NativeProcessProtocol &process = thread.GetProcess();
133 NativeRegisterContext &register_context = thread.GetRegisterContext();
134 const ArchSpec &arch = process.GetArchitecture();
135
136 std::unique_ptr<EmulateInstruction> emulator_up(
138 nullptr));
139
140 if (emulator_up == nullptr)
141 return Status("Instruction emulator not found!");
142
143 EmulatorBaton baton(process, register_context);
144 emulator_up->SetBaton(&baton);
145 emulator_up->SetReadMemCallback(&ReadMemoryCallback);
146 emulator_up->SetReadRegCallback(&ReadRegisterCallback);
147 emulator_up->SetWriteMemCallback(&WriteMemoryCallback);
148 emulator_up->SetWriteRegCallback(&WriteRegisterCallback);
149
150 if (!emulator_up->ReadInstruction()) {
151 // try to get at least the size of next instruction to set breakpoint.
152 auto instr_size = emulator_up->GetLastInstrSize();
153 if (!instr_size)
154 return Status("Read instruction failed!");
155 bool success = false;
156 auto pc = emulator_up->ReadRegisterUnsigned(eRegisterKindGeneric,
158 LLDB_INVALID_ADDRESS, &success);
159 if (!success)
160 return Status("Reading pc failed!");
161 lldb::addr_t next_pc = pc + *instr_size;
162 auto result =
163 SetSoftwareBreakpointOnPC(arch, next_pc, /* next_flags */ 0x0, process);
164 m_threads_stepping_with_breakpoint.insert({thread.GetID(), next_pc});
165 return result;
166 }
167
168 bool emulation_result =
169 emulator_up->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
170
171 const RegisterInfo *reg_info_pc = register_context.GetRegisterInfo(
173 const RegisterInfo *reg_info_flags = register_context.GetRegisterInfo(
175
176 auto pc_it =
177 baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]);
178 auto flags_it = reg_info_flags == nullptr
179 ? baton.m_register_values.end()
180 : baton.m_register_values.find(
181 reg_info_flags->kinds[eRegisterKindDWARF]);
182
183 lldb::addr_t next_pc;
184 lldb::addr_t next_flags;
185 if (emulation_result) {
186 assert(pc_it != baton.m_register_values.end() &&
187 "Emulation was successfull but PC wasn't updated");
188 next_pc = pc_it->second.GetAsUInt64();
189
190 if (flags_it != baton.m_register_values.end())
191 next_flags = flags_it->second.GetAsUInt64();
192 else
193 next_flags = ReadFlags(register_context);
194 } else if (pc_it == baton.m_register_values.end()) {
195 // Emulate instruction failed and it haven't changed PC. Advance PC with
196 // the size of the current opcode because the emulation of all
197 // PC modifying instruction should be successful. The failure most
198 // likely caused by a not supported instruction which don't modify PC.
199 next_pc = register_context.GetPC() + emulator_up->GetOpcode().GetByteSize();
200 next_flags = ReadFlags(register_context);
201 } else {
202 // The instruction emulation failed after it modified the PC. It is an
203 // unknown error where we can't continue because the next instruction is
204 // modifying the PC but we don't know how.
205 return Status("Instruction emulation failed unexpectedly.");
206 }
207 auto result = SetSoftwareBreakpointOnPC(arch, next_pc, next_flags, process);
208 m_threads_stepping_with_breakpoint.insert({thread.GetID(), next_pc});
209 return result;
210}
static llvm::raw_ostream & error(Stream &strm)
static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton, const RegisterInfo *reg_info, RegisterValue &reg_value)
static int GetSoftwareBreakpointSize(const ArchSpec &arch, lldb::addr_t next_flags)
static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton, const EmulateInstruction::Context &context, lldb::addr_t addr, const void *dst, size_t length)
static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton, const EmulateInstruction::Context &context, lldb::addr_t addr, void *dst, size_t length)
static Status SetSoftwareBreakpointOnPC(const ArchSpec &arch, lldb::addr_t pc, lldb::addr_t next_flags, NativeProcessProtocol &process)
static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton, const EmulateInstruction::Context &context, const RegisterInfo *reg_info, const RegisterValue &reg_value)
static lldb::addr_t ReadFlags(NativeRegisterContext &regsiter_context)
An architecture specification class.
Definition: ArchSpec.h:31
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:450
bool IsMIPS() const
if MIPS architecture return true.
Definition: ArchSpec.cpp:559
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:683
"lldb/Core/EmulateInstruction.h" A class that allows emulation of CPU opcodes.
static EmulateInstruction * FindPlugin(const ArchSpec &arch, InstructionType supported_inst_type, const char *plugin_name)
virtual Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware)=0
virtual const ArchSpec & GetArchitecture() const =0
Status SetupSoftwareSingleStepping(NativeThreadProtocol &thread)
std::map< lldb::tid_t, lldb::addr_t > m_threads_stepping_with_breakpoint
lldb::addr_t ReadRegisterAsUnsigned(uint32_t reg, lldb::addr_t fail_value)
const RegisterInfo * GetRegisterInfo(uint32_t reg_kind, uint32_t reg_num)
lldb::addr_t GetPC(lldb::addr_t fail_value=LLDB_INVALID_ADDRESS)
NativeProcessProtocol & GetProcess()
virtual NativeRegisterContext & GetRegisterContext()=0
An error handling class.
Definition: Status.h:44
#define LLDB_REGNUM_GENERIC_FLAGS
Definition: lldb-defines.h:60
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:82
#define LLDB_REGNUM_GENERIC_PC
Definition: lldb-defines.h:56
A class that represents a running process on the host machine.
Definition: SBAddress.h:15
uint64_t addr_t
Definition: lldb-types.h:80
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target
@ eRegisterKindDWARF
the register numbers seen DWARF
Every register is described in detail including its name, alternate name (optional),...
uint32_t kinds[lldb::kNumRegisterKinds]
Holds all of the various register numbers for all register kinds.