blob: 44de724b608c3f71bd116abe9499098c15b8ff1e [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
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
11// C++ Includes
12// Other libraries and framework includes
13// Project includes
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +000014#include "lldb/Target/ThreadPlanRunToAddress.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000015#include "lldb/Target/Process.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016#include "lldb/Target/RegisterContext.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000017#include "lldb/Target/Target.h"
18#include "lldb/Target/Thread.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000019#include "lldb/Utility/Log.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000020#include "lldb/Utility/Stream.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021
22using namespace lldb;
23using namespace lldb_private;
24
25//----------------------------------------------------------------------
26// ThreadPlanRunToAddress: Continue plan
27//----------------------------------------------------------------------
28
Kate Stoneb9c1b512016-09-06 20:57:50 +000029ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, Address &address,
30 bool stop_others)
31 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
32 eVoteNoOpinion, eVoteNoOpinion),
33 m_stop_others(stop_others), m_addresses(), m_break_ids() {
34 m_addresses.push_back(
35 address.GetOpcodeLoadAddress(m_thread.CalculateTarget().get()));
36 SetInitialBreakpoints();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037}
38
Kate Stoneb9c1b512016-09-06 20:57:50 +000039ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread,
40 lldb::addr_t address,
41 bool stop_others)
42 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
43 eVoteNoOpinion, eVoteNoOpinion),
44 m_stop_others(stop_others), m_addresses(), m_break_ids() {
45 m_addresses.push_back(
46 m_thread.CalculateTarget()->GetOpcodeLoadAddress(address));
47 SetInitialBreakpoints();
Jim Ingham08b87e02010-09-14 22:03:00 +000048}
49
Kate Stoneb9c1b512016-09-06 20:57:50 +000050ThreadPlanRunToAddress::ThreadPlanRunToAddress(
51 Thread &thread, const std::vector<lldb::addr_t> &addresses,
52 bool stop_others)
53 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
54 eVoteNoOpinion, eVoteNoOpinion),
55 m_stop_others(stop_others), m_addresses(addresses), m_break_ids() {
56 // Convert all addresses into opcode addresses to make sure we set
57 // breakpoints at the correct address.
58 Target &target = thread.GetProcess()->GetTarget();
59 std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();
60 for (pos = m_addresses.begin(); pos != end; ++pos)
61 *pos = target.GetOpcodeLoadAddress(*pos);
Greg Claytonf3ef3d22011-05-22 22:46:53 +000062
Kate Stoneb9c1b512016-09-06 20:57:50 +000063 SetInitialBreakpoints();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000064}
65
Kate Stoneb9c1b512016-09-06 20:57:50 +000066void ThreadPlanRunToAddress::SetInitialBreakpoints() {
67 size_t num_addresses = m_addresses.size();
68 m_break_ids.resize(num_addresses);
69
70 for (size_t i = 0; i < num_addresses; i++) {
71 Breakpoint *breakpoint;
72 breakpoint = m_thread.CalculateTarget()
73 ->CreateBreakpoint(m_addresses[i], true, false)
74 .get();
75 if (breakpoint != nullptr) {
76 m_break_ids[i] = breakpoint->GetID();
77 breakpoint->SetThreadID(m_thread.GetID());
78 breakpoint->SetBreakpointKind("run-to-address");
Chris Lattner30fdc8d2010-06-08 16:52:24 +000079 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000080 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000081}
82
Kate Stoneb9c1b512016-09-06 20:57:50 +000083ThreadPlanRunToAddress::~ThreadPlanRunToAddress() {
84 size_t num_break_ids = m_break_ids.size();
85 for (size_t i = 0; i < num_break_ids; i++) {
86 m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]);
87 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000088}
89
Kate Stoneb9c1b512016-09-06 20:57:50 +000090void ThreadPlanRunToAddress::GetDescription(Stream *s,
91 lldb::DescriptionLevel level) {
92 size_t num_addresses = m_addresses.size();
93
94 if (level == lldb::eDescriptionLevelBrief) {
95 if (num_addresses == 0) {
96 s->Printf("run to address with no addresses given.");
97 return;
98 } else if (num_addresses == 1)
99 s->Printf("run to address: ");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000100 else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000101 s->Printf("run to addresses: ");
102
103 for (size_t i = 0; i < num_addresses; i++) {
104 s->Address(m_addresses[i], sizeof(addr_t));
105 s->Printf(" ");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000106 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000107 } else {
108 if (num_addresses == 0) {
109 s->Printf("run to address with no addresses given.");
110 return;
111 } else if (num_addresses == 1)
112 s->Printf("Run to address: ");
113 else {
114 s->Printf("Run to addresses: ");
115 }
116
117 for (size_t i = 0; i < num_addresses; i++) {
118 if (num_addresses > 1) {
119 s->Printf("\n");
120 s->Indent();
121 }
122
123 s->Address(m_addresses[i], sizeof(addr_t));
124 s->Printf(" using breakpoint: %d - ", m_break_ids[i]);
125 Breakpoint *breakpoint =
126 m_thread.CalculateTarget()->GetBreakpointByID(m_break_ids[i]).get();
127 if (breakpoint)
128 breakpoint->Dump(s);
129 else
130 s->Printf("but the breakpoint has been deleted.");
131 }
132 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000133}
134
Kate Stoneb9c1b512016-09-06 20:57:50 +0000135bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) {
136 // If we couldn't set the breakpoint for some reason, then this won't
137 // work.
138 bool all_bps_good = true;
139 size_t num_break_ids = m_break_ids.size();
140
141 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 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000185 if (log)
186 log->Printf("Completed run to address plan.");
187 ThreadPlan::MischiefManaged();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000188 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000189 } else
190 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000191}
192
Kate Stoneb9c1b512016-09-06 20:57:50 +0000193bool ThreadPlanRunToAddress::AtOurAddress() {
194 lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
195 bool found_it = false;
196 size_t num_addresses = m_addresses.size();
197 for (size_t i = 0; i < num_addresses; i++) {
198 if (m_addresses[i] == current_address) {
199 found_it = true;
200 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000201 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000202 }
203 return found_it;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000204}