Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / source / Target / ThreadPlanRunToAddress.cpp
bloba2ac8c3d09668278aeeb2a1e048cf5ad59968c3d
1 //===-- ThreadPlanRunToAddress.cpp ----------------------------------------===//
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 //===----------------------------------------------------------------------===//
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/LLDBLog.h"
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/Stream.h"
18 using namespace lldb;
19 using namespace lldb_private;
21 // ThreadPlanRunToAddress: Continue plan
23 ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, Address &address,
24 bool stop_others)
25 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
26 eVoteNoOpinion, eVoteNoOpinion),
27 m_stop_others(stop_others), m_addresses(), m_break_ids() {
28 m_addresses.push_back(
29 address.GetOpcodeLoadAddress(thread.CalculateTarget().get()));
30 SetInitialBreakpoints();
33 ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread,
34 lldb::addr_t address,
35 bool stop_others)
36 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
37 eVoteNoOpinion, eVoteNoOpinion),
38 m_stop_others(stop_others), m_addresses(), m_break_ids() {
39 m_addresses.push_back(
40 thread.CalculateTarget()->GetOpcodeLoadAddress(address));
41 SetInitialBreakpoints();
44 ThreadPlanRunToAddress::ThreadPlanRunToAddress(
45 Thread &thread, const std::vector<lldb::addr_t> &addresses,
46 bool stop_others)
47 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
48 eVoteNoOpinion, eVoteNoOpinion),
49 m_stop_others(stop_others), m_addresses(addresses), m_break_ids() {
50 // Convert all addresses into opcode addresses to make sure we set
51 // breakpoints at the correct address.
52 Target &target = thread.GetProcess()->GetTarget();
53 std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();
54 for (pos = m_addresses.begin(); pos != end; ++pos)
55 *pos = target.GetOpcodeLoadAddress(*pos);
57 SetInitialBreakpoints();
60 void ThreadPlanRunToAddress::SetInitialBreakpoints() {
61 size_t num_addresses = m_addresses.size();
62 m_break_ids.resize(num_addresses);
64 for (size_t i = 0; i < num_addresses; i++) {
65 Breakpoint *breakpoint;
66 breakpoint =
67 GetTarget().CreateBreakpoint(m_addresses[i], true, false).get();
68 if (breakpoint != nullptr) {
69 if (breakpoint->IsHardware() && !breakpoint->HasResolvedLocations())
70 m_could_not_resolve_hw_bp = true;
71 m_break_ids[i] = breakpoint->GetID();
72 breakpoint->SetThreadID(m_tid);
73 breakpoint->SetBreakpointKind("run-to-address");
78 ThreadPlanRunToAddress::~ThreadPlanRunToAddress() {
79 size_t num_break_ids = m_break_ids.size();
80 for (size_t i = 0; i < num_break_ids; i++) {
81 GetTarget().RemoveBreakpointByID(m_break_ids[i]);
83 m_could_not_resolve_hw_bp = false;
86 void ThreadPlanRunToAddress::GetDescription(Stream *s,
87 lldb::DescriptionLevel level) {
88 size_t num_addresses = m_addresses.size();
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: ");
99 for (size_t i = 0; i < num_addresses; i++) {
100 DumpAddress(s->AsRawOstream(), m_addresses[i], sizeof(addr_t));
101 s->Printf(" ");
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: ");
113 for (size_t i = 0; i < num_addresses; i++) {
114 if (num_addresses > 1) {
115 s->Printf("\n");
116 s->Indent();
119 DumpAddress(s->AsRawOstream(), m_addresses[i], sizeof(addr_t));
120 s->Printf(" using breakpoint: %d - ", m_break_ids[i]);
121 Breakpoint *breakpoint =
122 GetTarget().GetBreakpointByID(m_break_ids[i]).get();
123 if (breakpoint)
124 breakpoint->Dump(s);
125 else
126 s->Printf("but the breakpoint has been deleted.");
131 bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) {
132 if (m_could_not_resolve_hw_bp) {
133 if (error)
134 error->Printf("Could not set hardware breakpoint(s)");
135 return false;
138 // If we couldn't set the breakpoint for some reason, then this won't work.
139 bool all_bps_good = true;
140 size_t num_break_ids = m_break_ids.size();
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 DumpAddress(error->AsRawOstream(), m_addresses[i], sizeof(addr_t));
147 error->Printf("\n");
151 return all_bps_good;
154 bool ThreadPlanRunToAddress::DoPlanExplainsStop(Event *event_ptr) {
155 return AtOurAddress();
158 bool ThreadPlanRunToAddress::ShouldStop(Event *event_ptr) {
159 return AtOurAddress();
162 bool ThreadPlanRunToAddress::StopOthers() { return m_stop_others; }
164 void ThreadPlanRunToAddress::SetStopOthers(bool new_value) {
165 m_stop_others = new_value;
168 StateType ThreadPlanRunToAddress::GetPlanRunState() { return eStateRunning; }
170 bool ThreadPlanRunToAddress::WillStop() { return true; }
172 bool ThreadPlanRunToAddress::MischiefManaged() {
173 Log *log = GetLog(LLDBLog::Step);
175 if (AtOurAddress()) {
176 // Remove the breakpoint
177 size_t num_break_ids = m_break_ids.size();
179 for (size_t i = 0; i < num_break_ids; i++) {
180 if (m_break_ids[i] != LLDB_INVALID_BREAK_ID) {
181 GetTarget().RemoveBreakpointByID(m_break_ids[i]);
182 m_break_ids[i] = LLDB_INVALID_BREAK_ID;
185 LLDB_LOGF(log, "Completed run to address plan.");
186 ThreadPlan::MischiefManaged();
187 return true;
188 } else
189 return false;
192 bool ThreadPlanRunToAddress::AtOurAddress() {
193 lldb::addr_t current_address = GetThread().GetRegisterContext()->GetPC();
194 bool found_it = false;
195 size_t num_addresses = m_addresses.size();
196 for (size_t i = 0; i < num_addresses; i++) {
197 if (m_addresses[i] == current_address) {
198 found_it = true;
199 break;
202 return found_it;