blob: 160743a9f3f8a11724a632becbc9ac310d4d235f [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- ThreadPlanRunToAddress.cpp ------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Chris Lattner30fdc8d2010-06-08 16:52:24 +00006//
7//===----------------------------------------------------------------------===//
8
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +00009#include "lldb/Target/ThreadPlanRunToAddress.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010#include "lldb/Target/Process.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000011#include "lldb/Target/RegisterContext.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000012#include "lldb/Target/Target.h"
13#include "lldb/Target/Thread.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000014#include "lldb/Utility/Log.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000015#include "lldb/Utility/Stream.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016
17using namespace lldb;
18using namespace lldb_private;
19
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020// ThreadPlanRunToAddress: Continue plan
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021
Kate Stoneb9c1b512016-09-06 20:57:50 +000022ThreadPlanRunToAddress::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(m_thread.CalculateTarget().get()));
29 SetInitialBreakpoints();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000030}
31
Kate Stoneb9c1b512016-09-06 20:57:50 +000032ThreadPlanRunToAddress::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 m_thread.CalculateTarget()->GetOpcodeLoadAddress(address));
40 SetInitialBreakpoints();
Jim Ingham08b87e02010-09-14 22:03:00 +000041}
42
Kate Stoneb9c1b512016-09-06 20:57:50 +000043ThreadPlanRunToAddress::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);
Greg Claytonf3ef3d22011-05-22 22:46:53 +000055
Kate Stoneb9c1b512016-09-06 20:57:50 +000056 SetInitialBreakpoints();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000057}
58
Kate Stoneb9c1b512016-09-06 20:57:50 +000059void 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 = m_thread.CalculateTarget()
66 ->CreateBreakpoint(m_addresses[i], true, false)
67 .get();
68 if (breakpoint != nullptr) {
Jonas Devliegheree103ae92018-11-15 01:18:15 +000069 if (breakpoint->IsHardware() && !breakpoint->HasResolvedLocations())
70 m_could_not_resolve_hw_bp = true;
Kate Stoneb9c1b512016-09-06 20:57:50 +000071 m_break_ids[i] = breakpoint->GetID();
72 breakpoint->SetThreadID(m_thread.GetID());
73 breakpoint->SetBreakpointKind("run-to-address");
Chris Lattner30fdc8d2010-06-08 16:52:24 +000074 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000075 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000076}
77
Kate Stoneb9c1b512016-09-06 20:57:50 +000078ThreadPlanRunToAddress::~ThreadPlanRunToAddress() {
79 size_t num_break_ids = m_break_ids.size();
80 for (size_t i = 0; i < num_break_ids; i++) {
81 m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]);
82 }
Jonas Devliegheree103ae92018-11-15 01:18:15 +000083 m_could_not_resolve_hw_bp = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000084}
85
Kate Stoneb9c1b512016-09-06 20:57:50 +000086void ThreadPlanRunToAddress::GetDescription(Stream *s,
87 lldb::DescriptionLevel level) {
88 size_t num_addresses = m_addresses.size();
89
90 if (level == lldb::eDescriptionLevelBrief) {
91 if (num_addresses == 0) {
92 s->Printf("run to address with no addresses given.");
93 return;
94 } else if (num_addresses == 1)
95 s->Printf("run to address: ");
Chris Lattner30fdc8d2010-06-08 16:52:24 +000096 else
Kate Stoneb9c1b512016-09-06 20:57:50 +000097 s->Printf("run to addresses: ");
98
99 for (size_t i = 0; i < num_addresses; i++) {
100 s->Address(m_addresses[i], sizeof(addr_t));
101 s->Printf(" ");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000102 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000103 } else {
104 if (num_addresses == 0) {
105 s->Printf("run to address with no addresses given.");
106 return;
107 } else if (num_addresses == 1)
108 s->Printf("Run to address: ");
109 else {
110 s->Printf("Run to addresses: ");
111 }
112
113 for (size_t i = 0; i < num_addresses; i++) {
114 if (num_addresses > 1) {
115 s->Printf("\n");
116 s->Indent();
117 }
118
119 s->Address(m_addresses[i], sizeof(addr_t));
120 s->Printf(" using breakpoint: %d - ", m_break_ids[i]);
121 Breakpoint *breakpoint =
122 m_thread.CalculateTarget()->GetBreakpointByID(m_break_ids[i]).get();
123 if (breakpoint)
124 breakpoint->Dump(s);
125 else
126 s->Printf("but the breakpoint has been deleted.");
127 }
128 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000129}
130
Kate Stoneb9c1b512016-09-06 20:57:50 +0000131bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) {
Jonas Devliegheree103ae92018-11-15 01:18:15 +0000132 if (m_could_not_resolve_hw_bp) {
133 if (error)
134 error->Printf("Could not set hardware breakpoint(s)");
135 return false;
136 }
137
Adrian Prantl05097242018-04-30 16:49:04 +0000138 // If we couldn't set the breakpoint for some reason, then this won't work.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000139 bool all_bps_good = true;
140 size_t num_break_ids = m_break_ids.size();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000141 for (size_t i = 0; i < num_break_ids; i++) {
142 if (m_break_ids[i] == LLDB_INVALID_BREAK_ID) {
143 all_bps_good = false;
144 if (error) {
145 error->Printf("Could not set breakpoint for address: ");
146 error->Address(m_addresses[i], sizeof(addr_t));
147 error->Printf("\n");
148 }
149 }
150 }
151 return all_bps_good;
152}
153
154bool ThreadPlanRunToAddress::DoPlanExplainsStop(Event *event_ptr) {
155 return AtOurAddress();
156}
157
158bool ThreadPlanRunToAddress::ShouldStop(Event *event_ptr) {
159 return AtOurAddress();
160}
161
162bool ThreadPlanRunToAddress::StopOthers() { return m_stop_others; }
163
164void ThreadPlanRunToAddress::SetStopOthers(bool new_value) {
165 m_stop_others = new_value;
166}
167
168StateType ThreadPlanRunToAddress::GetPlanRunState() { return eStateRunning; }
169
170bool ThreadPlanRunToAddress::WillStop() { return true; }
171
172bool ThreadPlanRunToAddress::MischiefManaged() {
173 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
174
175 if (AtOurAddress()) {
176 // Remove the breakpoint
Jim Ingham08b87e02010-09-14 22:03:00 +0000177 size_t num_break_ids = m_break_ids.size();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000178
179 for (size_t i = 0; i < num_break_ids; i++) {
180 if (m_break_ids[i] != LLDB_INVALID_BREAK_ID) {
181 m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]);
182 m_break_ids[i] = LLDB_INVALID_BREAK_ID;
183 }
Jim Ingham08b87e02010-09-14 22:03:00 +0000184 }
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +0000185 LLDB_LOGF(log, "Completed run to address plan.");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000186 ThreadPlan::MischiefManaged();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000187 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000188 } else
189 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000190}
191
Kate Stoneb9c1b512016-09-06 20:57:50 +0000192bool ThreadPlanRunToAddress::AtOurAddress() {
193 lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
194 bool found_it = false;
195 size_t num_addresses = m_addresses.size();
196 for (size_t i = 0; i < num_addresses; i++) {
197 if (m_addresses[i] == current_address) {
198 found_it = true;
199 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000200 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000201 }
202 return found_it;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000203}