1ac7ddfbfSEd Maste //===-- ThreadPlanRunToAddress.cpp ------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
109f2f44ceSEd Maste #include "lldb/Target/ThreadPlanRunToAddress.h"
11ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
12ac7ddfbfSEd Maste #include "lldb/Target/RegisterContext.h"
13435933ddSDimitry Andric #include "lldb/Target/Target.h"
14435933ddSDimitry Andric #include "lldb/Target/Thread.h"
15f678e45dSDimitry Andric #include "lldb/Utility/Log.h"
16f678e45dSDimitry Andric #include "lldb/Utility/Stream.h"
17ac7ddfbfSEd Maste 
18ac7ddfbfSEd Maste using namespace lldb;
19ac7ddfbfSEd Maste using namespace lldb_private;
20ac7ddfbfSEd Maste 
21ac7ddfbfSEd Maste //----------------------------------------------------------------------
22ac7ddfbfSEd Maste // ThreadPlanRunToAddress: Continue plan
23ac7ddfbfSEd Maste //----------------------------------------------------------------------
24ac7ddfbfSEd Maste 
ThreadPlanRunToAddress(Thread & thread,Address & address,bool stop_others)25435933ddSDimitry Andric ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, Address &address,
26435933ddSDimitry Andric                                                bool stop_others)
27435933ddSDimitry Andric     : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
28435933ddSDimitry Andric                  eVoteNoOpinion, eVoteNoOpinion),
29435933ddSDimitry Andric       m_stop_others(stop_others), m_addresses(), m_break_ids() {
30435933ddSDimitry Andric   m_addresses.push_back(
31435933ddSDimitry Andric       address.GetOpcodeLoadAddress(m_thread.CalculateTarget().get()));
32ac7ddfbfSEd Maste   SetInitialBreakpoints();
33ac7ddfbfSEd Maste }
34ac7ddfbfSEd Maste 
ThreadPlanRunToAddress(Thread & thread,lldb::addr_t address,bool stop_others)35435933ddSDimitry Andric ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread,
36ac7ddfbfSEd Maste                                                lldb::addr_t address,
37435933ddSDimitry Andric                                                bool stop_others)
38435933ddSDimitry Andric     : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
39435933ddSDimitry Andric                  eVoteNoOpinion, eVoteNoOpinion),
40435933ddSDimitry Andric       m_stop_others(stop_others), m_addresses(), m_break_ids() {
41435933ddSDimitry Andric   m_addresses.push_back(
42435933ddSDimitry Andric       m_thread.CalculateTarget()->GetOpcodeLoadAddress(address));
43ac7ddfbfSEd Maste   SetInitialBreakpoints();
44ac7ddfbfSEd Maste }
45ac7ddfbfSEd Maste 
ThreadPlanRunToAddress(Thread & thread,const std::vector<lldb::addr_t> & addresses,bool stop_others)46435933ddSDimitry Andric ThreadPlanRunToAddress::ThreadPlanRunToAddress(
47435933ddSDimitry Andric     Thread &thread, const std::vector<lldb::addr_t> &addresses,
48435933ddSDimitry Andric     bool stop_others)
49435933ddSDimitry Andric     : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
50435933ddSDimitry Andric                  eVoteNoOpinion, eVoteNoOpinion),
51435933ddSDimitry Andric       m_stop_others(stop_others), m_addresses(addresses), m_break_ids() {
520127ef0fSEd Maste   // Convert all addresses into opcode addresses to make sure we set
53ac7ddfbfSEd Maste   // breakpoints at the correct address.
54ac7ddfbfSEd Maste   Target &target = thread.GetProcess()->GetTarget();
55ac7ddfbfSEd Maste   std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();
56ac7ddfbfSEd Maste   for (pos = m_addresses.begin(); pos != end; ++pos)
57ac7ddfbfSEd Maste     *pos = target.GetOpcodeLoadAddress(*pos);
58ac7ddfbfSEd Maste 
59ac7ddfbfSEd Maste   SetInitialBreakpoints();
60ac7ddfbfSEd Maste }
61ac7ddfbfSEd Maste 
SetInitialBreakpoints()62435933ddSDimitry Andric void ThreadPlanRunToAddress::SetInitialBreakpoints() {
63ac7ddfbfSEd Maste   size_t num_addresses = m_addresses.size();
64ac7ddfbfSEd Maste   m_break_ids.resize(num_addresses);
65ac7ddfbfSEd Maste 
66435933ddSDimitry Andric   for (size_t i = 0; i < num_addresses; i++) {
67ac7ddfbfSEd Maste     Breakpoint *breakpoint;
68435933ddSDimitry Andric     breakpoint = m_thread.CalculateTarget()
69435933ddSDimitry Andric                      ->CreateBreakpoint(m_addresses[i], true, false)
70435933ddSDimitry Andric                      .get();
71435933ddSDimitry Andric     if (breakpoint != nullptr) {
72*b5893f02SDimitry Andric       if (breakpoint->IsHardware() && !breakpoint->HasResolvedLocations())
73*b5893f02SDimitry Andric         m_could_not_resolve_hw_bp = true;
74ac7ddfbfSEd Maste       m_break_ids[i] = breakpoint->GetID();
75ac7ddfbfSEd Maste       breakpoint->SetThreadID(m_thread.GetID());
76ac7ddfbfSEd Maste       breakpoint->SetBreakpointKind("run-to-address");
77ac7ddfbfSEd Maste     }
78ac7ddfbfSEd Maste   }
79ac7ddfbfSEd Maste }
80ac7ddfbfSEd Maste 
~ThreadPlanRunToAddress()81435933ddSDimitry Andric ThreadPlanRunToAddress::~ThreadPlanRunToAddress() {
82ac7ddfbfSEd Maste   size_t num_break_ids = m_break_ids.size();
83435933ddSDimitry Andric   for (size_t i = 0; i < num_break_ids; i++) {
84ac7ddfbfSEd Maste     m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]);
85ac7ddfbfSEd Maste   }
86*b5893f02SDimitry Andric   m_could_not_resolve_hw_bp = false;
87ac7ddfbfSEd Maste }
88ac7ddfbfSEd Maste 
GetDescription(Stream * s,lldb::DescriptionLevel level)89435933ddSDimitry Andric void ThreadPlanRunToAddress::GetDescription(Stream *s,
90435933ddSDimitry Andric                                             lldb::DescriptionLevel level) {
91ac7ddfbfSEd Maste   size_t num_addresses = m_addresses.size();
92ac7ddfbfSEd Maste 
93435933ddSDimitry Andric   if (level == lldb::eDescriptionLevelBrief) {
94435933ddSDimitry Andric     if (num_addresses == 0) {
95ac7ddfbfSEd Maste       s->Printf("run to address with no addresses given.");
96ac7ddfbfSEd Maste       return;
97435933ddSDimitry Andric     } else if (num_addresses == 1)
98ac7ddfbfSEd Maste       s->Printf("run to address: ");
99ac7ddfbfSEd Maste     else
100ac7ddfbfSEd Maste       s->Printf("run to addresses: ");
101ac7ddfbfSEd Maste 
102435933ddSDimitry Andric     for (size_t i = 0; i < num_addresses; i++) {
103ac7ddfbfSEd Maste       s->Address(m_addresses[i], sizeof(addr_t));
104ac7ddfbfSEd Maste       s->Printf(" ");
105ac7ddfbfSEd Maste     }
106435933ddSDimitry Andric   } else {
107435933ddSDimitry Andric     if (num_addresses == 0) {
108ac7ddfbfSEd Maste       s->Printf("run to address with no addresses given.");
109ac7ddfbfSEd Maste       return;
110435933ddSDimitry Andric     } else if (num_addresses == 1)
111ac7ddfbfSEd Maste       s->Printf("Run to address: ");
112435933ddSDimitry Andric     else {
113ac7ddfbfSEd Maste       s->Printf("Run to addresses: ");
114ac7ddfbfSEd Maste     }
115ac7ddfbfSEd Maste 
116435933ddSDimitry Andric     for (size_t i = 0; i < num_addresses; i++) {
117435933ddSDimitry Andric       if (num_addresses > 1) {
118ac7ddfbfSEd Maste         s->Printf("\n");
119ac7ddfbfSEd Maste         s->Indent();
120ac7ddfbfSEd Maste       }
121ac7ddfbfSEd Maste 
122ac7ddfbfSEd Maste       s->Address(m_addresses[i], sizeof(addr_t));
123ac7ddfbfSEd Maste       s->Printf(" using breakpoint: %d - ", m_break_ids[i]);
124435933ddSDimitry Andric       Breakpoint *breakpoint =
125435933ddSDimitry Andric           m_thread.CalculateTarget()->GetBreakpointByID(m_break_ids[i]).get();
126ac7ddfbfSEd Maste       if (breakpoint)
127ac7ddfbfSEd Maste         breakpoint->Dump(s);
128ac7ddfbfSEd Maste       else
129ac7ddfbfSEd Maste         s->Printf("but the breakpoint has been deleted.");
130ac7ddfbfSEd Maste     }
131ac7ddfbfSEd Maste   }
132ac7ddfbfSEd Maste }
133ac7ddfbfSEd Maste 
ValidatePlan(Stream * error)134435933ddSDimitry Andric bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) {
135*b5893f02SDimitry Andric   if (m_could_not_resolve_hw_bp) {
136*b5893f02SDimitry Andric     if (error)
137*b5893f02SDimitry Andric       error->Printf("Could not set hardware breakpoint(s)");
138*b5893f02SDimitry Andric     return false;
139*b5893f02SDimitry Andric   }
140*b5893f02SDimitry Andric 
1414ba319b5SDimitry Andric   // If we couldn't set the breakpoint for some reason, then this won't work.
142ac7ddfbfSEd Maste   bool all_bps_good = true;
143ac7ddfbfSEd Maste   size_t num_break_ids = m_break_ids.size();
144435933ddSDimitry Andric   for (size_t i = 0; i < num_break_ids; i++) {
145435933ddSDimitry Andric     if (m_break_ids[i] == LLDB_INVALID_BREAK_ID) {
146ac7ddfbfSEd Maste       all_bps_good = false;
147435933ddSDimitry Andric       if (error) {
148ac7ddfbfSEd Maste         error->Printf("Could not set breakpoint for address: ");
149ac7ddfbfSEd Maste         error->Address(m_addresses[i], sizeof(addr_t));
150ac7ddfbfSEd Maste         error->Printf("\n");
151ac7ddfbfSEd Maste       }
152ac7ddfbfSEd Maste     }
153ac7ddfbfSEd Maste   }
154ac7ddfbfSEd Maste   return all_bps_good;
155ac7ddfbfSEd Maste }
156ac7ddfbfSEd Maste 
DoPlanExplainsStop(Event * event_ptr)157435933ddSDimitry Andric bool ThreadPlanRunToAddress::DoPlanExplainsStop(Event *event_ptr) {
158ac7ddfbfSEd Maste   return AtOurAddress();
159ac7ddfbfSEd Maste }
160ac7ddfbfSEd Maste 
ShouldStop(Event * event_ptr)161435933ddSDimitry Andric bool ThreadPlanRunToAddress::ShouldStop(Event *event_ptr) {
1629f2f44ceSEd Maste   return AtOurAddress();
163ac7ddfbfSEd Maste }
164ac7ddfbfSEd Maste 
StopOthers()165435933ddSDimitry Andric bool ThreadPlanRunToAddress::StopOthers() { return m_stop_others; }
166ac7ddfbfSEd Maste 
SetStopOthers(bool new_value)167435933ddSDimitry Andric void ThreadPlanRunToAddress::SetStopOthers(bool new_value) {
168ac7ddfbfSEd Maste   m_stop_others = new_value;
169ac7ddfbfSEd Maste }
170ac7ddfbfSEd Maste 
GetPlanRunState()171435933ddSDimitry Andric StateType ThreadPlanRunToAddress::GetPlanRunState() { return eStateRunning; }
172ac7ddfbfSEd Maste 
WillStop()173435933ddSDimitry Andric bool ThreadPlanRunToAddress::WillStop() { return true; }
174ac7ddfbfSEd Maste 
MischiefManaged()175435933ddSDimitry Andric bool ThreadPlanRunToAddress::MischiefManaged() {
176ac7ddfbfSEd Maste   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
177ac7ddfbfSEd Maste 
178435933ddSDimitry Andric   if (AtOurAddress()) {
179ac7ddfbfSEd Maste     // Remove the breakpoint
180ac7ddfbfSEd Maste     size_t num_break_ids = m_break_ids.size();
181ac7ddfbfSEd Maste 
182435933ddSDimitry Andric     for (size_t i = 0; i < num_break_ids; i++) {
183435933ddSDimitry Andric       if (m_break_ids[i] != LLDB_INVALID_BREAK_ID) {
184ac7ddfbfSEd Maste         m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]);
185ac7ddfbfSEd Maste         m_break_ids[i] = LLDB_INVALID_BREAK_ID;
186ac7ddfbfSEd Maste       }
187ac7ddfbfSEd Maste     }
188ac7ddfbfSEd Maste     if (log)
189ac7ddfbfSEd Maste       log->Printf("Completed run to address plan.");
190ac7ddfbfSEd Maste     ThreadPlan::MischiefManaged();
191ac7ddfbfSEd Maste     return true;
192435933ddSDimitry Andric   } else
193ac7ddfbfSEd Maste     return false;
194ac7ddfbfSEd Maste }
195ac7ddfbfSEd Maste 
AtOurAddress()196435933ddSDimitry Andric bool ThreadPlanRunToAddress::AtOurAddress() {
197ac7ddfbfSEd Maste   lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
198ac7ddfbfSEd Maste   bool found_it = false;
199ac7ddfbfSEd Maste   size_t num_addresses = m_addresses.size();
200435933ddSDimitry Andric   for (size_t i = 0; i < num_addresses; i++) {
201435933ddSDimitry Andric     if (m_addresses[i] == current_address) {
202ac7ddfbfSEd Maste       found_it = true;
203ac7ddfbfSEd Maste       break;
204ac7ddfbfSEd Maste     }
205ac7ddfbfSEd Maste   }
206ac7ddfbfSEd Maste   return found_it;
207ac7ddfbfSEd Maste }
208