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