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
91 NativeThreadProtocol &thread) {
92 NativeProcessProtocol &process = thread.GetProcess();
93 NativeRegisterContext &register_context = thread.GetRegisterContext();
94 const ArchSpec &arch = process.GetArchitecture();
95
96 std::unique_ptr<EmulateInstruction> emulator_up(
98 nullptr));
99 if (emulator_up == nullptr)
100 return Status::FromErrorString("Instruction emulator not found!");
101
102 EmulatorBaton baton(process, register_context);
103 emulator_up->SetBaton(&baton);
104 emulator_up->SetReadMemCallback(&ReadMemoryCallback);
105 emulator_up->SetReadRegCallback(&ReadRegisterCallback);
106 emulator_up->SetWriteMemCallback(&WriteMemoryCallback);
107 emulator_up->SetWriteRegCallback(&WriteRegisterCallback);
108
109 auto bp_locations_predictor =
111 std::move(emulator_up));
112
113 llvm::Expected<BreakpointLocations> candidates =
114 bp_locations_predictor->GetBreakpointLocations();
115 if (!candidates)
116 return Status::FromError(candidates.takeError());
117
118 for (addr_t bp_addr : *candidates) {
119 if (process.HasSoftwareBreakpoint(bp_addr))
120 continue;
121 llvm::Expected<unsigned> bp_size =
122 bp_locations_predictor->GetBreakpointSize(bp_addr);
123 if (auto err = bp_size.takeError())
124 return Status::FromError(std::move(err));
125
126 Status error = process.SetBreakpoint(bp_addr, *bp_size, /*hardware=*/false);
127
128 // If setting the breakpoint fails because pc is out of the address
129 // space, ignore it and let the debugee segfault.
130 if (error.GetError() == EIO || error.GetError() == EFAULT)
131 continue;
132 if (error.Fail())
133 return error;
134
135 m_step_breakpoints.emplace(bp_addr);
136 }
137
138 m_threads_stepping_with_breakpoint.emplace(thread.GetID(),
139 std::move(*candidates));
140 return Status();
141}
static llvm::raw_ostream & error(Stream &strm)
static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton, const RegisterInfo *reg_info, RegisterValue &reg_value)
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 bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton, const EmulateInstruction::Context &context, const RegisterInfo *reg_info, const RegisterValue &reg_value)
An architecture specification class.
Definition ArchSpec.h:32
"lldb/Core/EmulateInstruction.h" A class that allows emulation of CPU opcodes.
static std::unique_ptr< SingleStepBreakpointLocationsPredictor > CreateBreakpointLocationPredictor(std::unique_ptr< EmulateInstruction > emulator_up)
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
virtual Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read)=0
std::map< lldb::tid_t, std::vector< lldb::addr_t > > m_threads_stepping_with_breakpoint
Status SetupSoftwareSingleStepping(NativeThreadProtocol &thread)
const RegisterInfo * GetRegisterInfo(uint32_t reg_kind, uint32_t reg_num)
virtual Status ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)=0
An error handling class.
Definition Status.h:118
static Status FromErrorString(const char *str)
Definition Status.h:141
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
Definition Status.cpp:136
A class that represents a running process on the host machine.
uint64_t addr_t
Definition lldb-types.h:80
@ 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.