1 //===-- ThreadPlanRunToAddress.cpp ----------------------------------------===//
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
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"
19 using namespace lldb_private
;
21 // ThreadPlanRunToAddress: Continue plan
23 ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread
&thread
, Address
&address
,
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
,
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
,
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
;
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.");
94 } else if (num_addresses
== 1)
95 s
->Printf("run to address: ");
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
));
104 if (num_addresses
== 0) {
105 s
->Printf("run to address with no addresses given.");
107 } else if (num_addresses
== 1)
108 s
->Printf("Run to address: ");
110 s
->Printf("Run to addresses: ");
113 for (size_t i
= 0; i
< num_addresses
; i
++) {
114 if (num_addresses
> 1) {
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();
126 s
->Printf("but the breakpoint has been deleted.");
131 bool ThreadPlanRunToAddress::ValidatePlan(Stream
*error
) {
132 if (m_could_not_resolve_hw_bp
) {
134 error
->Printf("Could not set hardware breakpoint(s)");
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;
145 error
->Printf("Could not set breakpoint for address: ");
146 DumpAddress(error
->AsRawOstream(), m_addresses
[i
], sizeof(addr_t
));
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();
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
) {