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 17 using namespace lldb; 18 using namespace lldb_private; 19 20 //---------------------------------------------------------------------- 21 // ThreadPlanRunToAddress: Continue plan 22 //---------------------------------------------------------------------- 23 24 ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, Address &address, 25 bool stop_others) 26 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread, 27 eVoteNoOpinion, eVoteNoOpinion), 28 m_stop_others(stop_others), m_addresses(), m_break_ids() { 29 m_addresses.push_back( 30 address.GetOpcodeLoadAddress(m_thread.CalculateTarget().get())); 31 SetInitialBreakpoints(); 32 } 33 34 ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, 35 lldb::addr_t address, 36 bool stop_others) 37 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread, 38 eVoteNoOpinion, eVoteNoOpinion), 39 m_stop_others(stop_others), m_addresses(), m_break_ids() { 40 m_addresses.push_back( 41 m_thread.CalculateTarget()->GetOpcodeLoadAddress(address)); 42 SetInitialBreakpoints(); 43 } 44 45 ThreadPlanRunToAddress::ThreadPlanRunToAddress( 46 Thread &thread, const std::vector<lldb::addr_t> &addresses, 47 bool stop_others) 48 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread, 49 eVoteNoOpinion, eVoteNoOpinion), 50 m_stop_others(stop_others), m_addresses(addresses), m_break_ids() { 51 // Convert all addresses into opcode addresses to make sure we set 52 // breakpoints at the correct address. 53 Target &target = thread.GetProcess()->GetTarget(); 54 std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end(); 55 for (pos = m_addresses.begin(); pos != end; ++pos) 56 *pos = target.GetOpcodeLoadAddress(*pos); 57 58 SetInitialBreakpoints(); 59 } 60 61 void ThreadPlanRunToAddress::SetInitialBreakpoints() { 62 size_t num_addresses = m_addresses.size(); 63 m_break_ids.resize(num_addresses); 64 65 for (size_t i = 0; i < num_addresses; i++) { 66 Breakpoint *breakpoint; 67 breakpoint = m_thread.CalculateTarget() 68 ->CreateBreakpoint(m_addresses[i], true, false) 69 .get(); 70 if (breakpoint != nullptr) { 71 if (breakpoint->IsHardware() && !breakpoint->HasResolvedLocations()) 72 m_could_not_resolve_hw_bp = true; 73 m_break_ids[i] = breakpoint->GetID(); 74 breakpoint->SetThreadID(m_thread.GetID()); 75 breakpoint->SetBreakpointKind("run-to-address"); 76 } 77 } 78 } 79 80 ThreadPlanRunToAddress::~ThreadPlanRunToAddress() { 81 size_t num_break_ids = m_break_ids.size(); 82 for (size_t i = 0; i < num_break_ids; i++) { 83 m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]); 84 } 85 m_could_not_resolve_hw_bp = false; 86 } 87 88 void ThreadPlanRunToAddress::GetDescription(Stream *s, 89 lldb::DescriptionLevel level) { 90 size_t num_addresses = m_addresses.size(); 91 92 if (level == lldb::eDescriptionLevelBrief) { 93 if (num_addresses == 0) { 94 s->Printf("run to address with no addresses given."); 95 return; 96 } else if (num_addresses == 1) 97 s->Printf("run to address: "); 98 else 99 s->Printf("run to addresses: "); 100 101 for (size_t i = 0; i < num_addresses; i++) { 102 s->Address(m_addresses[i], sizeof(addr_t)); 103 s->Printf(" "); 104 } 105 } else { 106 if (num_addresses == 0) { 107 s->Printf("run to address with no addresses given."); 108 return; 109 } else if (num_addresses == 1) 110 s->Printf("Run to address: "); 111 else { 112 s->Printf("Run to addresses: "); 113 } 114 115 for (size_t i = 0; i < num_addresses; i++) { 116 if (num_addresses > 1) { 117 s->Printf("\n"); 118 s->Indent(); 119 } 120 121 s->Address(m_addresses[i], sizeof(addr_t)); 122 s->Printf(" using breakpoint: %d - ", m_break_ids[i]); 123 Breakpoint *breakpoint = 124 m_thread.CalculateTarget()->GetBreakpointByID(m_break_ids[i]).get(); 125 if (breakpoint) 126 breakpoint->Dump(s); 127 else 128 s->Printf("but the breakpoint has been deleted."); 129 } 130 } 131 } 132 133 bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) { 134 if (m_could_not_resolve_hw_bp) { 135 if (error) 136 error->Printf("Could not set hardware breakpoint(s)"); 137 return false; 138 } 139 140 // If we couldn't set the breakpoint for some reason, then this won't work. 141 bool all_bps_good = true; 142 size_t num_break_ids = m_break_ids.size(); 143 for (size_t i = 0; i < num_break_ids; i++) { 144 if (m_break_ids[i] == LLDB_INVALID_BREAK_ID) { 145 all_bps_good = false; 146 if (error) { 147 error->Printf("Could not set breakpoint for address: "); 148 error->Address(m_addresses[i], sizeof(addr_t)); 149 error->Printf("\n"); 150 } 151 } 152 } 153 return all_bps_good; 154 } 155 156 bool ThreadPlanRunToAddress::DoPlanExplainsStop(Event *event_ptr) { 157 return AtOurAddress(); 158 } 159 160 bool ThreadPlanRunToAddress::ShouldStop(Event *event_ptr) { 161 return AtOurAddress(); 162 } 163 164 bool ThreadPlanRunToAddress::StopOthers() { return m_stop_others; } 165 166 void ThreadPlanRunToAddress::SetStopOthers(bool new_value) { 167 m_stop_others = new_value; 168 } 169 170 StateType ThreadPlanRunToAddress::GetPlanRunState() { return eStateRunning; } 171 172 bool ThreadPlanRunToAddress::WillStop() { return true; } 173 174 bool ThreadPlanRunToAddress::MischiefManaged() { 175 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 176 177 if (AtOurAddress()) { 178 // Remove the breakpoint 179 size_t num_break_ids = m_break_ids.size(); 180 181 for (size_t i = 0; i < num_break_ids; i++) { 182 if (m_break_ids[i] != LLDB_INVALID_BREAK_ID) { 183 m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]); 184 m_break_ids[i] = LLDB_INVALID_BREAK_ID; 185 } 186 } 187 if (log) 188 log->Printf("Completed run to address plan."); 189 ThreadPlan::MischiefManaged(); 190 return true; 191 } else 192 return false; 193 } 194 195 bool ThreadPlanRunToAddress::AtOurAddress() { 196 lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC(); 197 bool found_it = false; 198 size_t num_addresses = m_addresses.size(); 199 for (size_t i = 0; i < num_addresses; i++) { 200 if (m_addresses[i] == current_address) { 201 found_it = true; 202 break; 203 } 204 } 205 return found_it; 206 } 207