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/Log.h"
15 #include "lldb/Utility/Stream.h"
18 using namespace lldb_private
;
20 // ThreadPlanRunToAddress: Continue plan
22 ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread
&thread
, Address
&address
,
24 : ThreadPlan(ThreadPlan::eKindRunToAddress
, "Run to address plan", thread
,
25 eVoteNoOpinion
, eVoteNoOpinion
),
26 m_stop_others(stop_others
), m_addresses(), m_break_ids() {
27 m_addresses
.push_back(
28 address
.GetOpcodeLoadAddress(thread
.CalculateTarget().get()));
29 SetInitialBreakpoints();
32 ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread
&thread
,
35 : ThreadPlan(ThreadPlan::eKindRunToAddress
, "Run to address plan", thread
,
36 eVoteNoOpinion
, eVoteNoOpinion
),
37 m_stop_others(stop_others
), m_addresses(), m_break_ids() {
38 m_addresses
.push_back(
39 thread
.CalculateTarget()->GetOpcodeLoadAddress(address
));
40 SetInitialBreakpoints();
43 ThreadPlanRunToAddress::ThreadPlanRunToAddress(
44 Thread
&thread
, const std::vector
<lldb::addr_t
> &addresses
,
46 : ThreadPlan(ThreadPlan::eKindRunToAddress
, "Run to address plan", thread
,
47 eVoteNoOpinion
, eVoteNoOpinion
),
48 m_stop_others(stop_others
), m_addresses(addresses
), m_break_ids() {
49 // Convert all addresses into opcode addresses to make sure we set
50 // breakpoints at the correct address.
51 Target
&target
= thread
.GetProcess()->GetTarget();
52 std::vector
<lldb::addr_t
>::iterator pos
, end
= m_addresses
.end();
53 for (pos
= m_addresses
.begin(); pos
!= end
; ++pos
)
54 *pos
= target
.GetOpcodeLoadAddress(*pos
);
56 SetInitialBreakpoints();
59 void ThreadPlanRunToAddress::SetInitialBreakpoints() {
60 size_t num_addresses
= m_addresses
.size();
61 m_break_ids
.resize(num_addresses
);
63 for (size_t i
= 0; i
< num_addresses
; i
++) {
64 Breakpoint
*breakpoint
;
66 GetTarget().CreateBreakpoint(m_addresses
[i
], true, false).get();
67 if (breakpoint
!= nullptr) {
68 if (breakpoint
->IsHardware() && !breakpoint
->HasResolvedLocations())
69 m_could_not_resolve_hw_bp
= true;
70 m_break_ids
[i
] = breakpoint
->GetID();
71 breakpoint
->SetThreadID(m_tid
);
72 breakpoint
->SetBreakpointKind("run-to-address");
77 ThreadPlanRunToAddress::~ThreadPlanRunToAddress() {
78 size_t num_break_ids
= m_break_ids
.size();
79 for (size_t i
= 0; i
< num_break_ids
; i
++) {
80 GetTarget().RemoveBreakpointByID(m_break_ids
[i
]);
82 m_could_not_resolve_hw_bp
= false;
85 void ThreadPlanRunToAddress::GetDescription(Stream
*s
,
86 lldb::DescriptionLevel level
) {
87 size_t num_addresses
= m_addresses
.size();
89 if (level
== lldb::eDescriptionLevelBrief
) {
90 if (num_addresses
== 0) {
91 s
->Printf("run to address with no addresses given.");
93 } else if (num_addresses
== 1)
94 s
->Printf("run to address: ");
96 s
->Printf("run to addresses: ");
98 for (size_t i
= 0; i
< num_addresses
; i
++) {
99 DumpAddress(s
->AsRawOstream(), m_addresses
[i
], sizeof(addr_t
));
103 if (num_addresses
== 0) {
104 s
->Printf("run to address with no addresses given.");
106 } else if (num_addresses
== 1)
107 s
->Printf("Run to address: ");
109 s
->Printf("Run to addresses: ");
112 for (size_t i
= 0; i
< num_addresses
; i
++) {
113 if (num_addresses
> 1) {
118 DumpAddress(s
->AsRawOstream(), m_addresses
[i
], sizeof(addr_t
));
119 s
->Printf(" using breakpoint: %d - ", m_break_ids
[i
]);
120 Breakpoint
*breakpoint
=
121 GetTarget().GetBreakpointByID(m_break_ids
[i
]).get();
125 s
->Printf("but the breakpoint has been deleted.");
130 bool ThreadPlanRunToAddress::ValidatePlan(Stream
*error
) {
131 if (m_could_not_resolve_hw_bp
) {
133 error
->Printf("Could not set hardware breakpoint(s)");
137 // If we couldn't set the breakpoint for some reason, then this won't work.
138 bool all_bps_good
= true;
139 size_t num_break_ids
= m_break_ids
.size();
140 for (size_t i
= 0; i
< num_break_ids
; i
++) {
141 if (m_break_ids
[i
] == LLDB_INVALID_BREAK_ID
) {
142 all_bps_good
= false;
144 error
->Printf("Could not set breakpoint for address: ");
145 DumpAddress(error
->AsRawOstream(), m_addresses
[i
], sizeof(addr_t
));
153 bool ThreadPlanRunToAddress::DoPlanExplainsStop(Event
*event_ptr
) {
154 return AtOurAddress();
157 bool ThreadPlanRunToAddress::ShouldStop(Event
*event_ptr
) {
158 return AtOurAddress();
161 bool ThreadPlanRunToAddress::StopOthers() { return m_stop_others
; }
163 void ThreadPlanRunToAddress::SetStopOthers(bool new_value
) {
164 m_stop_others
= new_value
;
167 StateType
ThreadPlanRunToAddress::GetPlanRunState() { return eStateRunning
; }
169 bool ThreadPlanRunToAddress::WillStop() { return true; }
171 bool ThreadPlanRunToAddress::MischiefManaged() {
172 Log
*log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP
));
174 if (AtOurAddress()) {
175 // Remove the breakpoint
176 size_t num_break_ids
= m_break_ids
.size();
178 for (size_t i
= 0; i
< num_break_ids
; i
++) {
179 if (m_break_ids
[i
] != LLDB_INVALID_BREAK_ID
) {
180 GetTarget().RemoveBreakpointByID(m_break_ids
[i
]);
181 m_break_ids
[i
] = LLDB_INVALID_BREAK_ID
;
184 LLDB_LOGF(log
, "Completed run to address plan.");
185 ThreadPlan::MischiefManaged();
191 bool ThreadPlanRunToAddress::AtOurAddress() {
192 lldb::addr_t current_address
= GetThread().GetRegisterContext()->GetPC();
193 bool found_it
= false;
194 size_t num_addresses
= m_addresses
.size();
195 for (size_t i
= 0; i
< num_addresses
; i
++) {
196 if (m_addresses
[i
] == current_address
) {