1//===-- ThreadPlanRunToAddress.cpp ------------------------------*- C++ -*-===// 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/Log.h" 15#include "lldb/Utility/Stream.h" 16 17using namespace lldb; 18using namespace lldb_private; 19 20// ThreadPlanRunToAddress: Continue plan 21 22ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, Address &address, 23 bool stop_others) 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(m_thread.CalculateTarget().get())); 29 SetInitialBreakpoints(); 30} 31 32ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, 33 lldb::addr_t address, 34 bool stop_others) 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 m_thread.CalculateTarget()->GetOpcodeLoadAddress(address)); 40 SetInitialBreakpoints(); 41} 42 43ThreadPlanRunToAddress::ThreadPlanRunToAddress( 44 Thread &thread, const std::vector<lldb::addr_t> &addresses, 45 bool stop_others) 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); 55 56 SetInitialBreakpoints(); 57} 58 59void ThreadPlanRunToAddress::SetInitialBreakpoints() { 60 size_t num_addresses = m_addresses.size(); 61 m_break_ids.resize(num_addresses); 62 63 for (size_t i = 0; i < num_addresses; i++) { 64 Breakpoint *breakpoint; 65 breakpoint = m_thread.CalculateTarget() 66 ->CreateBreakpoint(m_addresses[i], true, false) 67 .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_thread.GetID()); 73 breakpoint->SetBreakpointKind("run-to-address"); 74 } 75 } 76} 77 78ThreadPlanRunToAddress::~ThreadPlanRunToAddress() { 79 size_t num_break_ids = m_break_ids.size(); 80 for (size_t i = 0; i < num_break_ids; i++) { 81 m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]); 82 } 83 m_could_not_resolve_hw_bp = false; 84} 85 86void 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 m_thread.CalculateTarget()->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 131bool 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 154bool ThreadPlanRunToAddress::DoPlanExplainsStop(Event *event_ptr) { 155 return AtOurAddress(); 156} 157 158bool ThreadPlanRunToAddress::ShouldStop(Event *event_ptr) { 159 return AtOurAddress(); 160} 161 162bool ThreadPlanRunToAddress::StopOthers() { return m_stop_others; } 163 164void ThreadPlanRunToAddress::SetStopOthers(bool new_value) { 165 m_stop_others = new_value; 166} 167 168StateType ThreadPlanRunToAddress::GetPlanRunState() { return eStateRunning; } 169 170bool ThreadPlanRunToAddress::WillStop() { return true; } 171 172bool ThreadPlanRunToAddress::MischiefManaged() { 173 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_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 m_thread.CalculateTarget()->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 192bool ThreadPlanRunToAddress::AtOurAddress() { 193 lldb::addr_t current_address = m_thread.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