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 //===----------------------------------------------------------------------===// 8 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" 17 18 using namespace lldb; 19 using namespace lldb_private; 20 21 // ThreadPlanRunToAddress: Continue plan 22 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(); 31 } 32 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(); 42 } 43 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); 56 57 SetInitialBreakpoints(); 58 } 59 60 void ThreadPlanRunToAddress::SetInitialBreakpoints() { 61 size_t num_addresses = m_addresses.size(); 62 m_break_ids.resize(num_addresses); 63 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"); 74 } 75 } 76 } 77 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]); 82 } 83 m_could_not_resolve_hw_bp = false; 84 } 85 86 void ThreadPlanRunToAddress::GetDescription(Stream *s, 87 lldb::DescriptionLevel level) { 88 size_t num_addresses = m_addresses.size(); 89 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: "); 98 99 for (size_t i = 0; i < num_addresses; i++) { 100 DumpAddress(s->AsRawOstream(), m_addresses[i], sizeof(addr_t)); 101 s->Printf(" "); 102 } 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: "); 111 } 112 113 for (size_t i = 0; i < num_addresses; i++) { 114 if (num_addresses > 1) { 115 s->Printf("\n"); 116 s->Indent(); 117 } 118 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."); 127 } 128 } 129 } 130 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; 136 } 137 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"); 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 = GetLog(LLDBLog::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 GetTarget().RemoveBreakpointByID(m_break_ids[i]); 182 m_break_ids[i] = LLDB_INVALID_BREAK_ID; 183 } 184 } 185 LLDB_LOGF(log, "Completed run to address plan."); 186 ThreadPlan::MischiefManaged(); 187 return true; 188 } else 189 return false; 190 } 191 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; 200 } 201 } 202 return found_it; 203 } 204