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