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/Log.h" 15 #include "lldb/Utility/Stream.h" 16 17 using namespace lldb; 18 using namespace lldb_private; 19 20 // ThreadPlanRunToAddress: Continue plan 21 22 ThreadPlanRunToAddress::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(thread.CalculateTarget().get())); 29 SetInitialBreakpoints(); 30 } 31 32 ThreadPlanRunToAddress::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 thread.CalculateTarget()->GetOpcodeLoadAddress(address)); 40 SetInitialBreakpoints(); 41 } 42 43 ThreadPlanRunToAddress::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 59 void 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 = 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"); 73 } 74 } 75 } 76 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]); 81 } 82 m_could_not_resolve_hw_bp = false; 83 } 84 85 void ThreadPlanRunToAddress::GetDescription(Stream *s, 86 lldb::DescriptionLevel level) { 87 size_t num_addresses = m_addresses.size(); 88 89 if (level == lldb::eDescriptionLevelBrief) { 90 if (num_addresses == 0) { 91 s->Printf("run to address with no addresses given."); 92 return; 93 } else if (num_addresses == 1) 94 s->Printf("run to address: "); 95 else 96 s->Printf("run to addresses: "); 97 98 for (size_t i = 0; i < num_addresses; i++) { 99 DumpAddress(s->AsRawOstream(), m_addresses[i], sizeof(addr_t)); 100 s->Printf(" "); 101 } 102 } else { 103 if (num_addresses == 0) { 104 s->Printf("run to address with no addresses given."); 105 return; 106 } else if (num_addresses == 1) 107 s->Printf("Run to address: "); 108 else { 109 s->Printf("Run to addresses: "); 110 } 111 112 for (size_t i = 0; i < num_addresses; i++) { 113 if (num_addresses > 1) { 114 s->Printf("\n"); 115 s->Indent(); 116 } 117 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(); 122 if (breakpoint) 123 breakpoint->Dump(s); 124 else 125 s->Printf("but the breakpoint has been deleted."); 126 } 127 } 128 } 129 130 bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) { 131 if (m_could_not_resolve_hw_bp) { 132 if (error) 133 error->Printf("Could not set hardware breakpoint(s)"); 134 return false; 135 } 136 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; 143 if (error) { 144 error->Printf("Could not set breakpoint for address: "); 145 DumpAddress(error->AsRawOstream(), m_addresses[i], sizeof(addr_t)); 146 error->Printf("\n"); 147 } 148 } 149 } 150 return all_bps_good; 151 } 152 153 bool ThreadPlanRunToAddress::DoPlanExplainsStop(Event *event_ptr) { 154 return AtOurAddress(); 155 } 156 157 bool ThreadPlanRunToAddress::ShouldStop(Event *event_ptr) { 158 return AtOurAddress(); 159 } 160 161 bool ThreadPlanRunToAddress::StopOthers() { return m_stop_others; } 162 163 void ThreadPlanRunToAddress::SetStopOthers(bool new_value) { 164 m_stop_others = new_value; 165 } 166 167 StateType ThreadPlanRunToAddress::GetPlanRunState() { return eStateRunning; } 168 169 bool ThreadPlanRunToAddress::WillStop() { return true; } 170 171 bool ThreadPlanRunToAddress::MischiefManaged() { 172 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 173 174 if (AtOurAddress()) { 175 // Remove the breakpoint 176 size_t num_break_ids = m_break_ids.size(); 177 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; 182 } 183 } 184 LLDB_LOGF(log, "Completed run to address plan."); 185 ThreadPlan::MischiefManaged(); 186 return true; 187 } else 188 return false; 189 } 190 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) { 197 found_it = true; 198 break; 199 } 200 } 201 return found_it; 202 } 203