blob: 8091b8a1ab7fbc28e29d9ff0be217962387a2be2 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- ThreadPlanRunToAddress.cpp ------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +000010#include "lldb/Target/ThreadPlanRunToAddress.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000011#include "lldb/Target/Process.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000012#include "lldb/Target/RegisterContext.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000013#include "lldb/Target/Target.h"
14#include "lldb/Target/Thread.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000015#include "lldb/Utility/Log.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000016#include "lldb/Utility/Stream.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017
18using namespace lldb;
19using namespace lldb_private;
20
21//----------------------------------------------------------------------
22// ThreadPlanRunToAddress: Continue plan
23//----------------------------------------------------------------------
24
Kate Stoneb9c1b512016-09-06 20:57:50 +000025ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, Address &address,
26 bool stop_others)
27 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
28 eVoteNoOpinion, eVoteNoOpinion),
29 m_stop_others(stop_others), m_addresses(), m_break_ids() {
30 m_addresses.push_back(
31 address.GetOpcodeLoadAddress(m_thread.CalculateTarget().get()));
32 SetInitialBreakpoints();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033}
34
Kate Stoneb9c1b512016-09-06 20:57:50 +000035ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread,
36 lldb::addr_t address,
37 bool stop_others)
38 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
39 eVoteNoOpinion, eVoteNoOpinion),
40 m_stop_others(stop_others), m_addresses(), m_break_ids() {
41 m_addresses.push_back(
42 m_thread.CalculateTarget()->GetOpcodeLoadAddress(address));
43 SetInitialBreakpoints();
Jim Ingham08b87e02010-09-14 22:03:00 +000044}
45
Kate Stoneb9c1b512016-09-06 20:57:50 +000046ThreadPlanRunToAddress::ThreadPlanRunToAddress(
47 Thread &thread, const std::vector<lldb::addr_t> &addresses,
48 bool stop_others)
49 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
50 eVoteNoOpinion, eVoteNoOpinion),
51 m_stop_others(stop_others), m_addresses(addresses), m_break_ids() {
52 // Convert all addresses into opcode addresses to make sure we set
53 // breakpoints at the correct address.
54 Target &target = thread.GetProcess()->GetTarget();
55 std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();
56 for (pos = m_addresses.begin(); pos != end; ++pos)
57 *pos = target.GetOpcodeLoadAddress(*pos);
Greg Claytonf3ef3d22011-05-22 22:46:53 +000058
Kate Stoneb9c1b512016-09-06 20:57:50 +000059 SetInitialBreakpoints();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000060}
61
Kate Stoneb9c1b512016-09-06 20:57:50 +000062void ThreadPlanRunToAddress::SetInitialBreakpoints() {
63 size_t num_addresses = m_addresses.size();
64 m_break_ids.resize(num_addresses);
65
66 for (size_t i = 0; i < num_addresses; i++) {
67 Breakpoint *breakpoint;
68 breakpoint = m_thread.CalculateTarget()
69 ->CreateBreakpoint(m_addresses[i], true, false)
70 .get();
71 if (breakpoint != nullptr) {
72 m_break_ids[i] = breakpoint->GetID();
73 breakpoint->SetThreadID(m_thread.GetID());
74 breakpoint->SetBreakpointKind("run-to-address");
Chris Lattner30fdc8d2010-06-08 16:52:24 +000075 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000076 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000077}
78
Kate Stoneb9c1b512016-09-06 20:57:50 +000079ThreadPlanRunToAddress::~ThreadPlanRunToAddress() {
80 size_t num_break_ids = m_break_ids.size();
81 for (size_t i = 0; i < num_break_ids; i++) {
82 m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]);
83 }
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) {
Adrian Prantl05097242018-04-30 16:49:04 +0000132 // If we couldn't set the breakpoint for some reason, then this won't work.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000133 bool all_bps_good = true;
134 size_t num_break_ids = m_break_ids.size();
135
136 for (size_t i = 0; i < num_break_ids; i++) {
137 if (m_break_ids[i] == LLDB_INVALID_BREAK_ID) {
138 all_bps_good = false;
139 if (error) {
140 error->Printf("Could not set breakpoint for address: ");
141 error->Address(m_addresses[i], sizeof(addr_t));
142 error->Printf("\n");
143 }
144 }
145 }
146 return all_bps_good;
147}
148
149bool ThreadPlanRunToAddress::DoPlanExplainsStop(Event *event_ptr) {
150 return AtOurAddress();
151}
152
153bool ThreadPlanRunToAddress::ShouldStop(Event *event_ptr) {
154 return AtOurAddress();
155}
156
157bool ThreadPlanRunToAddress::StopOthers() { return m_stop_others; }
158
159void ThreadPlanRunToAddress::SetStopOthers(bool new_value) {
160 m_stop_others = new_value;
161}
162
163StateType ThreadPlanRunToAddress::GetPlanRunState() { return eStateRunning; }
164
165bool ThreadPlanRunToAddress::WillStop() { return true; }
166
167bool ThreadPlanRunToAddress::MischiefManaged() {
168 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
169
170 if (AtOurAddress()) {
171 // Remove the breakpoint
Jim Ingham08b87e02010-09-14 22:03:00 +0000172 size_t num_break_ids = m_break_ids.size();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000173
174 for (size_t i = 0; i < num_break_ids; i++) {
175 if (m_break_ids[i] != LLDB_INVALID_BREAK_ID) {
176 m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]);
177 m_break_ids[i] = LLDB_INVALID_BREAK_ID;
178 }
Jim Ingham08b87e02010-09-14 22:03:00 +0000179 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000180 if (log)
181 log->Printf("Completed run to address plan.");
182 ThreadPlan::MischiefManaged();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000183 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000184 } else
185 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000186}
187
Kate Stoneb9c1b512016-09-06 20:57:50 +0000188bool ThreadPlanRunToAddress::AtOurAddress() {
189 lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
190 bool found_it = false;
191 size_t num_addresses = m_addresses.size();
192 for (size_t i = 0; i < num_addresses; i++) {
193 if (m_addresses[i] == current_address) {
194 found_it = true;
195 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000196 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000197 }
198 return found_it;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000199}