1 //===-- ThreadPlanRunToAddress.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 "lldb/Target/ThreadPlanRunToAddress.h"
10 #include "lldb/Target/Process.h"
11 #include "lldb/Target/RegisterContext.h"
12 #include "lldb/Target/Target.h"
13 #include "lldb/Target/Thread.h"
14 #include "lldb/Utility/Log.h"
15 #include "lldb/Utility/Stream.h"
16
17 using namespace lldb;
18 using namespace lldb_private;
19
20 // ThreadPlanRunToAddress: Continue plan
21
ThreadPlanRunToAddress(Thread & thread,Address & address,bool stop_others)22 ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, Address &address,
23 bool stop_others)
24 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
25 eVoteNoOpinion, eVoteNoOpinion),
26 m_stop_others(stop_others), m_addresses(), m_break_ids() {
27 m_addresses.push_back(
28 address.GetOpcodeLoadAddress(thread.CalculateTarget().get()));
29 SetInitialBreakpoints();
30 }
31
ThreadPlanRunToAddress(Thread & thread,lldb::addr_t address,bool stop_others)32 ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread,
33 lldb::addr_t address,
34 bool stop_others)
35 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
36 eVoteNoOpinion, eVoteNoOpinion),
37 m_stop_others(stop_others), m_addresses(), m_break_ids() {
38 m_addresses.push_back(
39 thread.CalculateTarget()->GetOpcodeLoadAddress(address));
40 SetInitialBreakpoints();
41 }
42
ThreadPlanRunToAddress(Thread & thread,const std::vector<lldb::addr_t> & addresses,bool stop_others)43 ThreadPlanRunToAddress::ThreadPlanRunToAddress(
44 Thread &thread, const std::vector<lldb::addr_t> &addresses,
45 bool stop_others)
46 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
47 eVoteNoOpinion, eVoteNoOpinion),
48 m_stop_others(stop_others), m_addresses(addresses), m_break_ids() {
49 // Convert all addresses into opcode addresses to make sure we set
50 // breakpoints at the correct address.
51 Target &target = thread.GetProcess()->GetTarget();
52 std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();
53 for (pos = m_addresses.begin(); pos != end; ++pos)
54 *pos = target.GetOpcodeLoadAddress(*pos);
55
56 SetInitialBreakpoints();
57 }
58
SetInitialBreakpoints()59 void ThreadPlanRunToAddress::SetInitialBreakpoints() {
60 size_t num_addresses = m_addresses.size();
61 m_break_ids.resize(num_addresses);
62
63 for (size_t i = 0; i < num_addresses; i++) {
64 Breakpoint *breakpoint;
65 breakpoint =
66 GetTarget().CreateBreakpoint(m_addresses[i], true, false).get();
67 if (breakpoint != nullptr) {
68 if (breakpoint->IsHardware() && !breakpoint->HasResolvedLocations())
69 m_could_not_resolve_hw_bp = true;
70 m_break_ids[i] = breakpoint->GetID();
71 breakpoint->SetThreadID(m_tid);
72 breakpoint->SetBreakpointKind("run-to-address");
73 }
74 }
75 }
76
~ThreadPlanRunToAddress()77 ThreadPlanRunToAddress::~ThreadPlanRunToAddress() {
78 size_t num_break_ids = m_break_ids.size();
79 for (size_t i = 0; i < num_break_ids; i++) {
80 GetTarget().RemoveBreakpointByID(m_break_ids[i]);
81 }
82 m_could_not_resolve_hw_bp = false;
83 }
84
GetDescription(Stream * s,lldb::DescriptionLevel level)85 void ThreadPlanRunToAddress::GetDescription(Stream *s,
86 lldb::DescriptionLevel level) {
87 size_t num_addresses = m_addresses.size();
88
89 if (level == lldb::eDescriptionLevelBrief) {
90 if (num_addresses == 0) {
91 s->Printf("run to address with no addresses given.");
92 return;
93 } else if (num_addresses == 1)
94 s->Printf("run to address: ");
95 else
96 s->Printf("run to addresses: ");
97
98 for (size_t i = 0; i < num_addresses; i++) {
99 DumpAddress(s->AsRawOstream(), m_addresses[i], sizeof(addr_t));
100 s->Printf(" ");
101 }
102 } else {
103 if (num_addresses == 0) {
104 s->Printf("run to address with no addresses given.");
105 return;
106 } else if (num_addresses == 1)
107 s->Printf("Run to address: ");
108 else {
109 s->Printf("Run to addresses: ");
110 }
111
112 for (size_t i = 0; i < num_addresses; i++) {
113 if (num_addresses > 1) {
114 s->Printf("\n");
115 s->Indent();
116 }
117
118 DumpAddress(s->AsRawOstream(), m_addresses[i], sizeof(addr_t));
119 s->Printf(" using breakpoint: %d - ", m_break_ids[i]);
120 Breakpoint *breakpoint =
121 GetTarget().GetBreakpointByID(m_break_ids[i]).get();
122 if (breakpoint)
123 breakpoint->Dump(s);
124 else
125 s->Printf("but the breakpoint has been deleted.");
126 }
127 }
128 }
129
ValidatePlan(Stream * error)130 bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) {
131 if (m_could_not_resolve_hw_bp) {
132 if (error)
133 error->Printf("Could not set hardware breakpoint(s)");
134 return false;
135 }
136
137 // If we couldn't set the breakpoint for some reason, then this won't work.
138 bool all_bps_good = true;
139 size_t num_break_ids = m_break_ids.size();
140 for (size_t i = 0; i < num_break_ids; i++) {
141 if (m_break_ids[i] == LLDB_INVALID_BREAK_ID) {
142 all_bps_good = false;
143 if (error) {
144 error->Printf("Could not set breakpoint for address: ");
145 DumpAddress(error->AsRawOstream(), m_addresses[i], sizeof(addr_t));
146 error->Printf("\n");
147 }
148 }
149 }
150 return all_bps_good;
151 }
152
DoPlanExplainsStop(Event * event_ptr)153 bool ThreadPlanRunToAddress::DoPlanExplainsStop(Event *event_ptr) {
154 return AtOurAddress();
155 }
156
ShouldStop(Event * event_ptr)157 bool ThreadPlanRunToAddress::ShouldStop(Event *event_ptr) {
158 return AtOurAddress();
159 }
160
StopOthers()161 bool ThreadPlanRunToAddress::StopOthers() { return m_stop_others; }
162
SetStopOthers(bool new_value)163 void ThreadPlanRunToAddress::SetStopOthers(bool new_value) {
164 m_stop_others = new_value;
165 }
166
GetPlanRunState()167 StateType ThreadPlanRunToAddress::GetPlanRunState() { return eStateRunning; }
168
WillStop()169 bool ThreadPlanRunToAddress::WillStop() { return true; }
170
MischiefManaged()171 bool ThreadPlanRunToAddress::MischiefManaged() {
172 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
173
174 if (AtOurAddress()) {
175 // Remove the breakpoint
176 size_t num_break_ids = m_break_ids.size();
177
178 for (size_t i = 0; i < num_break_ids; i++) {
179 if (m_break_ids[i] != LLDB_INVALID_BREAK_ID) {
180 GetTarget().RemoveBreakpointByID(m_break_ids[i]);
181 m_break_ids[i] = LLDB_INVALID_BREAK_ID;
182 }
183 }
184 LLDB_LOGF(log, "Completed run to address plan.");
185 ThreadPlan::MischiefManaged();
186 return true;
187 } else
188 return false;
189 }
190
AtOurAddress()191 bool ThreadPlanRunToAddress::AtOurAddress() {
192 lldb::addr_t current_address = GetThread().GetRegisterContext()->GetPC();
193 bool found_it = false;
194 size_t num_addresses = m_addresses.size();
195 for (size_t i = 0; i < num_addresses; i++) {
196 if (m_addresses[i] == current_address) {
197 found_it = true;
198 break;
199 }
200 }
201 return found_it;
202 }
203