1 //===-- 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 
10 #include "lldb/Target/ThreadPlanRunToAddress.h"
11 #include "lldb/Target/Process.h"
12 #include "lldb/Target/RegisterContext.h"
13 #include "lldb/Target/Target.h"
14 #include "lldb/Target/Thread.h"
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/Stream.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 //----------------------------------------------------------------------
22 // ThreadPlanRunToAddress: Continue plan
23 //----------------------------------------------------------------------
24 
25 ThreadPlanRunToAddress::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();
33 }
34 
35 ThreadPlanRunToAddress::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();
44 }
45 
46 ThreadPlanRunToAddress::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);
58 
59   SetInitialBreakpoints();
60 }
61 
62 void 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");
75     }
76   }
77 }
78 
79 ThreadPlanRunToAddress::~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   }
84 }
85 
86 void 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: ");
96     else
97       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(" ");
102     }
103   } 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   }
129 }
130 
131 bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) {
132   // If we couldn't set the breakpoint for some reason, then this won't work.
133   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 
149 bool ThreadPlanRunToAddress::DoPlanExplainsStop(Event *event_ptr) {
150   return AtOurAddress();
151 }
152 
153 bool ThreadPlanRunToAddress::ShouldStop(Event *event_ptr) {
154   return AtOurAddress();
155 }
156 
157 bool ThreadPlanRunToAddress::StopOthers() { return m_stop_others; }
158 
159 void ThreadPlanRunToAddress::SetStopOthers(bool new_value) {
160   m_stop_others = new_value;
161 }
162 
163 StateType ThreadPlanRunToAddress::GetPlanRunState() { return eStateRunning; }
164 
165 bool ThreadPlanRunToAddress::WillStop() { return true; }
166 
167 bool ThreadPlanRunToAddress::MischiefManaged() {
168   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
169 
170   if (AtOurAddress()) {
171     // Remove the breakpoint
172     size_t num_break_ids = m_break_ids.size();
173 
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       }
179     }
180     if (log)
181       log->Printf("Completed run to address plan.");
182     ThreadPlan::MischiefManaged();
183     return true;
184   } else
185     return false;
186 }
187 
188 bool 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;
196     }
197   }
198   return found_it;
199 }
200