1cfca06d7SDimitry Andric //===-- ThreadPlanRunToAddress.cpp ----------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
9e81d9d49SDimitry Andric #include "lldb/Target/ThreadPlanRunToAddress.h"
10f034231aSEd Maste #include "lldb/Target/Process.h"
11f034231aSEd Maste #include "lldb/Target/RegisterContext.h"
1214f1b3e8SDimitry Andric #include "lldb/Target/Target.h"
1314f1b3e8SDimitry Andric #include "lldb/Target/Thread.h"
14145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
1574a628f7SDimitry Andric #include "lldb/Utility/Log.h"
1674a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
17f034231aSEd Maste
18f034231aSEd Maste using namespace lldb;
19f034231aSEd Maste using namespace lldb_private;
20f034231aSEd Maste
21f034231aSEd Maste // ThreadPlanRunToAddress: Continue plan
22f034231aSEd Maste
ThreadPlanRunToAddress(Thread & thread,Address & address,bool stop_others)2314f1b3e8SDimitry Andric ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, Address &address,
2414f1b3e8SDimitry Andric bool stop_others)
2514f1b3e8SDimitry Andric : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
2614f1b3e8SDimitry Andric eVoteNoOpinion, eVoteNoOpinion),
2714f1b3e8SDimitry Andric m_stop_others(stop_others), m_addresses(), m_break_ids() {
2814f1b3e8SDimitry Andric m_addresses.push_back(
29cfca06d7SDimitry Andric address.GetOpcodeLoadAddress(thread.CalculateTarget().get()));
30f034231aSEd Maste SetInitialBreakpoints();
31f034231aSEd Maste }
32f034231aSEd Maste
ThreadPlanRunToAddress(Thread & thread,lldb::addr_t address,bool stop_others)3314f1b3e8SDimitry Andric ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread,
34f034231aSEd Maste lldb::addr_t address,
3514f1b3e8SDimitry Andric bool stop_others)
3614f1b3e8SDimitry Andric : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
3714f1b3e8SDimitry Andric eVoteNoOpinion, eVoteNoOpinion),
3814f1b3e8SDimitry Andric m_stop_others(stop_others), m_addresses(), m_break_ids() {
3914f1b3e8SDimitry Andric m_addresses.push_back(
40cfca06d7SDimitry Andric thread.CalculateTarget()->GetOpcodeLoadAddress(address));
41f034231aSEd Maste SetInitialBreakpoints();
42f034231aSEd Maste }
43f034231aSEd Maste
ThreadPlanRunToAddress(Thread & thread,const std::vector<lldb::addr_t> & addresses,bool stop_others)4414f1b3e8SDimitry Andric ThreadPlanRunToAddress::ThreadPlanRunToAddress(
4514f1b3e8SDimitry Andric Thread &thread, const std::vector<lldb::addr_t> &addresses,
4614f1b3e8SDimitry Andric bool stop_others)
4714f1b3e8SDimitry Andric : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
4814f1b3e8SDimitry Andric eVoteNoOpinion, eVoteNoOpinion),
4914f1b3e8SDimitry Andric m_stop_others(stop_others), m_addresses(addresses), m_break_ids() {
500cac4ca3SEd Maste // Convert all addresses into opcode addresses to make sure we set
51f034231aSEd Maste // breakpoints at the correct address.
52f034231aSEd Maste Target &target = thread.GetProcess()->GetTarget();
53f034231aSEd Maste std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();
54f034231aSEd Maste for (pos = m_addresses.begin(); pos != end; ++pos)
55f034231aSEd Maste *pos = target.GetOpcodeLoadAddress(*pos);
56f034231aSEd Maste
57f034231aSEd Maste SetInitialBreakpoints();
58f034231aSEd Maste }
59f034231aSEd Maste
SetInitialBreakpoints()6014f1b3e8SDimitry Andric void ThreadPlanRunToAddress::SetInitialBreakpoints() {
61f034231aSEd Maste size_t num_addresses = m_addresses.size();
62f034231aSEd Maste m_break_ids.resize(num_addresses);
63f034231aSEd Maste
6414f1b3e8SDimitry Andric for (size_t i = 0; i < num_addresses; i++) {
65f034231aSEd Maste Breakpoint *breakpoint;
66cfca06d7SDimitry Andric breakpoint =
67cfca06d7SDimitry Andric GetTarget().CreateBreakpoint(m_addresses[i], true, false).get();
6814f1b3e8SDimitry Andric if (breakpoint != nullptr) {
6994994d37SDimitry Andric if (breakpoint->IsHardware() && !breakpoint->HasResolvedLocations())
7094994d37SDimitry Andric m_could_not_resolve_hw_bp = true;
71f034231aSEd Maste m_break_ids[i] = breakpoint->GetID();
72cfca06d7SDimitry Andric breakpoint->SetThreadID(m_tid);
73f034231aSEd Maste breakpoint->SetBreakpointKind("run-to-address");
74f034231aSEd Maste }
75f034231aSEd Maste }
76f034231aSEd Maste }
77f034231aSEd Maste
~ThreadPlanRunToAddress()7814f1b3e8SDimitry Andric ThreadPlanRunToAddress::~ThreadPlanRunToAddress() {
79f034231aSEd Maste size_t num_break_ids = m_break_ids.size();
8014f1b3e8SDimitry Andric for (size_t i = 0; i < num_break_ids; i++) {
81cfca06d7SDimitry Andric GetTarget().RemoveBreakpointByID(m_break_ids[i]);
82f034231aSEd Maste }
8394994d37SDimitry Andric m_could_not_resolve_hw_bp = false;
84f034231aSEd Maste }
85f034231aSEd Maste
GetDescription(Stream * s,lldb::DescriptionLevel level)8614f1b3e8SDimitry Andric void ThreadPlanRunToAddress::GetDescription(Stream *s,
8714f1b3e8SDimitry Andric lldb::DescriptionLevel level) {
88f034231aSEd Maste size_t num_addresses = m_addresses.size();
89f034231aSEd Maste
9014f1b3e8SDimitry Andric if (level == lldb::eDescriptionLevelBrief) {
9114f1b3e8SDimitry Andric if (num_addresses == 0) {
92f034231aSEd Maste s->Printf("run to address with no addresses given.");
93f034231aSEd Maste return;
9414f1b3e8SDimitry Andric } else if (num_addresses == 1)
95f034231aSEd Maste s->Printf("run to address: ");
96f034231aSEd Maste else
97f034231aSEd Maste s->Printf("run to addresses: ");
98f034231aSEd Maste
9914f1b3e8SDimitry Andric for (size_t i = 0; i < num_addresses; i++) {
100706b4fc4SDimitry Andric DumpAddress(s->AsRawOstream(), m_addresses[i], sizeof(addr_t));
101f034231aSEd Maste s->Printf(" ");
102f034231aSEd Maste }
10314f1b3e8SDimitry Andric } else {
10414f1b3e8SDimitry Andric if (num_addresses == 0) {
105f034231aSEd Maste s->Printf("run to address with no addresses given.");
106f034231aSEd Maste return;
10714f1b3e8SDimitry Andric } else if (num_addresses == 1)
108f034231aSEd Maste s->Printf("Run to address: ");
10914f1b3e8SDimitry Andric else {
110f034231aSEd Maste s->Printf("Run to addresses: ");
111f034231aSEd Maste }
112f034231aSEd Maste
11314f1b3e8SDimitry Andric for (size_t i = 0; i < num_addresses; i++) {
11414f1b3e8SDimitry Andric if (num_addresses > 1) {
115f034231aSEd Maste s->Printf("\n");
116f034231aSEd Maste s->Indent();
117f034231aSEd Maste }
118f034231aSEd Maste
119706b4fc4SDimitry Andric DumpAddress(s->AsRawOstream(), m_addresses[i], sizeof(addr_t));
120f034231aSEd Maste s->Printf(" using breakpoint: %d - ", m_break_ids[i]);
12114f1b3e8SDimitry Andric Breakpoint *breakpoint =
122cfca06d7SDimitry Andric GetTarget().GetBreakpointByID(m_break_ids[i]).get();
123f034231aSEd Maste if (breakpoint)
124f034231aSEd Maste breakpoint->Dump(s);
125f034231aSEd Maste else
126f034231aSEd Maste s->Printf("but the breakpoint has been deleted.");
127f034231aSEd Maste }
128f034231aSEd Maste }
129f034231aSEd Maste }
130f034231aSEd Maste
ValidatePlan(Stream * error)13114f1b3e8SDimitry Andric bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) {
13294994d37SDimitry Andric if (m_could_not_resolve_hw_bp) {
13394994d37SDimitry Andric if (error)
13494994d37SDimitry Andric error->Printf("Could not set hardware breakpoint(s)");
13594994d37SDimitry Andric return false;
13694994d37SDimitry Andric }
13794994d37SDimitry Andric
138f73363f1SDimitry Andric // If we couldn't set the breakpoint for some reason, then this won't work.
139f034231aSEd Maste bool all_bps_good = true;
140f034231aSEd Maste size_t num_break_ids = m_break_ids.size();
14114f1b3e8SDimitry Andric for (size_t i = 0; i < num_break_ids; i++) {
14214f1b3e8SDimitry Andric if (m_break_ids[i] == LLDB_INVALID_BREAK_ID) {
143f034231aSEd Maste all_bps_good = false;
14414f1b3e8SDimitry Andric if (error) {
145f034231aSEd Maste error->Printf("Could not set breakpoint for address: ");
146706b4fc4SDimitry Andric DumpAddress(error->AsRawOstream(), m_addresses[i], sizeof(addr_t));
147f034231aSEd Maste error->Printf("\n");
148f034231aSEd Maste }
149f034231aSEd Maste }
150f034231aSEd Maste }
151f034231aSEd Maste return all_bps_good;
152f034231aSEd Maste }
153f034231aSEd Maste
DoPlanExplainsStop(Event * event_ptr)15414f1b3e8SDimitry Andric bool ThreadPlanRunToAddress::DoPlanExplainsStop(Event *event_ptr) {
155f034231aSEd Maste return AtOurAddress();
156f034231aSEd Maste }
157f034231aSEd Maste
ShouldStop(Event * event_ptr)15814f1b3e8SDimitry Andric bool ThreadPlanRunToAddress::ShouldStop(Event *event_ptr) {
159e81d9d49SDimitry Andric return AtOurAddress();
160f034231aSEd Maste }
161f034231aSEd Maste
StopOthers()16214f1b3e8SDimitry Andric bool ThreadPlanRunToAddress::StopOthers() { return m_stop_others; }
163f034231aSEd Maste
SetStopOthers(bool new_value)16414f1b3e8SDimitry Andric void ThreadPlanRunToAddress::SetStopOthers(bool new_value) {
165f034231aSEd Maste m_stop_others = new_value;
166f034231aSEd Maste }
167f034231aSEd Maste
GetPlanRunState()16814f1b3e8SDimitry Andric StateType ThreadPlanRunToAddress::GetPlanRunState() { return eStateRunning; }
169f034231aSEd Maste
WillStop()17014f1b3e8SDimitry Andric bool ThreadPlanRunToAddress::WillStop() { return true; }
171f034231aSEd Maste
MischiefManaged()17214f1b3e8SDimitry Andric bool ThreadPlanRunToAddress::MischiefManaged() {
173145449b1SDimitry Andric Log *log = GetLog(LLDBLog::Step);
174f034231aSEd Maste
17514f1b3e8SDimitry Andric if (AtOurAddress()) {
176f034231aSEd Maste // Remove the breakpoint
177f034231aSEd Maste size_t num_break_ids = m_break_ids.size();
178f034231aSEd Maste
17914f1b3e8SDimitry Andric for (size_t i = 0; i < num_break_ids; i++) {
18014f1b3e8SDimitry Andric if (m_break_ids[i] != LLDB_INVALID_BREAK_ID) {
181cfca06d7SDimitry Andric GetTarget().RemoveBreakpointByID(m_break_ids[i]);
182f034231aSEd Maste m_break_ids[i] = LLDB_INVALID_BREAK_ID;
183f034231aSEd Maste }
184f034231aSEd Maste }
185ead24645SDimitry Andric LLDB_LOGF(log, "Completed run to address plan.");
186f034231aSEd Maste ThreadPlan::MischiefManaged();
187f034231aSEd Maste return true;
18814f1b3e8SDimitry Andric } else
189f034231aSEd Maste return false;
190f034231aSEd Maste }
191f034231aSEd Maste
AtOurAddress()19214f1b3e8SDimitry Andric bool ThreadPlanRunToAddress::AtOurAddress() {
193cfca06d7SDimitry Andric lldb::addr_t current_address = GetThread().GetRegisterContext()->GetPC();
194f034231aSEd Maste bool found_it = false;
195f034231aSEd Maste size_t num_addresses = m_addresses.size();
19614f1b3e8SDimitry Andric for (size_t i = 0; i < num_addresses; i++) {
19714f1b3e8SDimitry Andric if (m_addresses[i] == current_address) {
198f034231aSEd Maste found_it = true;
199f034231aSEd Maste break;
200f034231aSEd Maste }
201f034231aSEd Maste }
202f034231aSEd Maste return found_it;
203f034231aSEd Maste }
204