]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Target/ThreadPlanRunToAddress.cpp
Merge llvm, clang, compiler-rt, libc++, lld, and lldb release_80 branch
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / 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 #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       if (breakpoint->IsHardware() && !breakpoint->HasResolvedLocations())
73         m_could_not_resolve_hw_bp = true;
74       m_break_ids[i] = breakpoint->GetID();
75       breakpoint->SetThreadID(m_thread.GetID());
76       breakpoint->SetBreakpointKind("run-to-address");
77     }
78   }
79 }
80
81 ThreadPlanRunToAddress::~ThreadPlanRunToAddress() {
82   size_t num_break_ids = m_break_ids.size();
83   for (size_t i = 0; i < num_break_ids; i++) {
84     m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]);
85   }
86   m_could_not_resolve_hw_bp = false;
87 }
88
89 void ThreadPlanRunToAddress::GetDescription(Stream *s,
90                                             lldb::DescriptionLevel level) {
91   size_t num_addresses = m_addresses.size();
92
93   if (level == lldb::eDescriptionLevelBrief) {
94     if (num_addresses == 0) {
95       s->Printf("run to address with no addresses given.");
96       return;
97     } else if (num_addresses == 1)
98       s->Printf("run to address: ");
99     else
100       s->Printf("run to addresses: ");
101
102     for (size_t i = 0; i < num_addresses; i++) {
103       s->Address(m_addresses[i], sizeof(addr_t));
104       s->Printf(" ");
105     }
106   } else {
107     if (num_addresses == 0) {
108       s->Printf("run to address with no addresses given.");
109       return;
110     } else if (num_addresses == 1)
111       s->Printf("Run to address: ");
112     else {
113       s->Printf("Run to addresses: ");
114     }
115
116     for (size_t i = 0; i < num_addresses; i++) {
117       if (num_addresses > 1) {
118         s->Printf("\n");
119         s->Indent();
120       }
121
122       s->Address(m_addresses[i], sizeof(addr_t));
123       s->Printf(" using breakpoint: %d - ", m_break_ids[i]);
124       Breakpoint *breakpoint =
125           m_thread.CalculateTarget()->GetBreakpointByID(m_break_ids[i]).get();
126       if (breakpoint)
127         breakpoint->Dump(s);
128       else
129         s->Printf("but the breakpoint has been deleted.");
130     }
131   }
132 }
133
134 bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) {
135   if (m_could_not_resolve_hw_bp) {
136     if (error)
137       error->Printf("Could not set hardware breakpoint(s)");
138     return false;
139   }
140
141   // If we couldn't set the breakpoint for some reason, then this won't work.
142   bool all_bps_good = true;
143   size_t num_break_ids = m_break_ids.size();
144   for (size_t i = 0; i < num_break_ids; i++) {
145     if (m_break_ids[i] == LLDB_INVALID_BREAK_ID) {
146       all_bps_good = false;
147       if (error) {
148         error->Printf("Could not set breakpoint for address: ");
149         error->Address(m_addresses[i], sizeof(addr_t));
150         error->Printf("\n");
151       }
152     }
153   }
154   return all_bps_good;
155 }
156
157 bool ThreadPlanRunToAddress::DoPlanExplainsStop(Event *event_ptr) {
158   return AtOurAddress();
159 }
160
161 bool ThreadPlanRunToAddress::ShouldStop(Event *event_ptr) {
162   return AtOurAddress();
163 }
164
165 bool ThreadPlanRunToAddress::StopOthers() { return m_stop_others; }
166
167 void ThreadPlanRunToAddress::SetStopOthers(bool new_value) {
168   m_stop_others = new_value;
169 }
170
171 StateType ThreadPlanRunToAddress::GetPlanRunState() { return eStateRunning; }
172
173 bool ThreadPlanRunToAddress::WillStop() { return true; }
174
175 bool ThreadPlanRunToAddress::MischiefManaged() {
176   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
177
178   if (AtOurAddress()) {
179     // Remove the breakpoint
180     size_t num_break_ids = m_break_ids.size();
181
182     for (size_t i = 0; i < num_break_ids; i++) {
183       if (m_break_ids[i] != LLDB_INVALID_BREAK_ID) {
184         m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]);
185         m_break_ids[i] = LLDB_INVALID_BREAK_ID;
186       }
187     }
188     if (log)
189       log->Printf("Completed run to address plan.");
190     ThreadPlan::MischiefManaged();
191     return true;
192   } else
193     return false;
194 }
195
196 bool ThreadPlanRunToAddress::AtOurAddress() {
197   lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
198   bool found_it = false;
199   size_t num_addresses = m_addresses.size();
200   for (size_t i = 0; i < num_addresses; i++) {
201     if (m_addresses[i] == current_address) {
202       found_it = true;
203       break;
204     }
205   }
206   return found_it;
207 }