]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Target/ThreadPlanRunToAddress.cpp
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / source / Target / ThreadPlanRunToAddress.cpp
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 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/Target/ThreadPlanRunToAddress.h"
15 #include "lldb/Core/Log.h"
16 #include "lldb/Core/Stream.h"
17 #include "lldb/Target/Process.h"
18 #include "lldb/Target/RegisterContext.h"
19 #include "lldb/Target/Target.h"
20 #include "lldb/Target/Thread.h"
21
22 using namespace lldb;
23 using namespace lldb_private;
24
25 //----------------------------------------------------------------------
26 // ThreadPlanRunToAddress: Continue plan
27 //----------------------------------------------------------------------
28
29 ThreadPlanRunToAddress::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();
37 }
38
39 ThreadPlanRunToAddress::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();
48 }
49
50 ThreadPlanRunToAddress::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);
62
63   SetInitialBreakpoints();
64 }
65
66 void 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");
79     }
80   }
81 }
82
83 ThreadPlanRunToAddress::~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   }
88 }
89
90 void 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: ");
100     else
101       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(" ");
106     }
107   } 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   }
133 }
134
135 bool 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
154 bool ThreadPlanRunToAddress::DoPlanExplainsStop(Event *event_ptr) {
155   return AtOurAddress();
156 }
157
158 bool ThreadPlanRunToAddress::ShouldStop(Event *event_ptr) {
159   return AtOurAddress();
160 }
161
162 bool ThreadPlanRunToAddress::StopOthers() { return m_stop_others; }
163
164 void ThreadPlanRunToAddress::SetStopOthers(bool new_value) {
165   m_stop_others = new_value;
166 }
167
168 StateType ThreadPlanRunToAddress::GetPlanRunState() { return eStateRunning; }
169
170 bool ThreadPlanRunToAddress::WillStop() { return true; }
171
172 bool ThreadPlanRunToAddress::MischiefManaged() {
173   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
174
175   if (AtOurAddress()) {
176     // Remove the breakpoint
177     size_t num_break_ids = m_break_ids.size();
178
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       }
184     }
185     if (log)
186       log->Printf("Completed run to address plan.");
187     ThreadPlan::MischiefManaged();
188     return true;
189   } else
190     return false;
191 }
192
193 bool 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;
201     }
202   }
203   return found_it;
204 }