1 //===-- ThreadPlanRunToAddress.cpp ------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // C Includes 11 // C++ Includes 12 // Other libraries and framework includes 13 // Project includes 14 #include "lldb/Target/ThreadPlanRunToAddress.h" 15 #include "lldb/Core/Log.h" 16 #include "lldb/Core/Stream.h" 17 #include "lldb/Target/Process.h" 18 #include "lldb/Target/RegisterContext.h" 19 #include "lldb/Target/Target.h" 20 #include "lldb/Target/Thread.h" 21 22 using namespace lldb; 23 using namespace lldb_private; 24 25 //---------------------------------------------------------------------- 26 // ThreadPlanRunToAddress: Continue plan 27 //---------------------------------------------------------------------- 28 29 ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, Address &address, 30 bool stop_others) 31 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread, 32 eVoteNoOpinion, eVoteNoOpinion), 33 m_stop_others(stop_others), m_addresses(), m_break_ids() { 34 m_addresses.push_back( 35 address.GetOpcodeLoadAddress(m_thread.CalculateTarget().get())); 36 SetInitialBreakpoints(); 37 } 38 39 ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, 40 lldb::addr_t address, 41 bool stop_others) 42 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread, 43 eVoteNoOpinion, eVoteNoOpinion), 44 m_stop_others(stop_others), m_addresses(), m_break_ids() { 45 m_addresses.push_back( 46 m_thread.CalculateTarget()->GetOpcodeLoadAddress(address)); 47 SetInitialBreakpoints(); 48 } 49 50 ThreadPlanRunToAddress::ThreadPlanRunToAddress( 51 Thread &thread, const std::vector<lldb::addr_t> &addresses, 52 bool stop_others) 53 : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread, 54 eVoteNoOpinion, eVoteNoOpinion), 55 m_stop_others(stop_others), m_addresses(addresses), m_break_ids() { 56 // Convert all addresses into opcode addresses to make sure we set 57 // breakpoints at the correct address. 58 Target &target = thread.GetProcess()->GetTarget(); 59 std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end(); 60 for (pos = m_addresses.begin(); pos != end; ++pos) 61 *pos = target.GetOpcodeLoadAddress(*pos); 62 63 SetInitialBreakpoints(); 64 } 65 66 void ThreadPlanRunToAddress::SetInitialBreakpoints() { 67 size_t num_addresses = m_addresses.size(); 68 m_break_ids.resize(num_addresses); 69 70 for (size_t i = 0; i < num_addresses; i++) { 71 Breakpoint *breakpoint; 72 breakpoint = m_thread.CalculateTarget() 73 ->CreateBreakpoint(m_addresses[i], true, false) 74 .get(); 75 if (breakpoint != nullptr) { 76 m_break_ids[i] = breakpoint->GetID(); 77 breakpoint->SetThreadID(m_thread.GetID()); 78 breakpoint->SetBreakpointKind("run-to-address"); 79 } 80 } 81 } 82 83 ThreadPlanRunToAddress::~ThreadPlanRunToAddress() { 84 size_t num_break_ids = m_break_ids.size(); 85 for (size_t i = 0; i < num_break_ids; i++) { 86 m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]); 87 } 88 } 89 90 void ThreadPlanRunToAddress::GetDescription(Stream *s, 91 lldb::DescriptionLevel level) { 92 size_t num_addresses = m_addresses.size(); 93 94 if (level == lldb::eDescriptionLevelBrief) { 95 if (num_addresses == 0) { 96 s->Printf("run to address with no addresses given."); 97 return; 98 } else if (num_addresses == 1) 99 s->Printf("run to address: "); 100 else 101 s->Printf("run to addresses: "); 102 103 for (size_t i = 0; i < num_addresses; i++) { 104 s->Address(m_addresses[i], sizeof(addr_t)); 105 s->Printf(" "); 106 } 107 } else { 108 if (num_addresses == 0) { 109 s->Printf("run to address with no addresses given."); 110 return; 111 } else if (num_addresses == 1) 112 s->Printf("Run to address: "); 113 else { 114 s->Printf("Run to addresses: "); 115 } 116 117 for (size_t i = 0; i < num_addresses; i++) { 118 if (num_addresses > 1) { 119 s->Printf("\n"); 120 s->Indent(); 121 } 122 123 s->Address(m_addresses[i], sizeof(addr_t)); 124 s->Printf(" using breakpoint: %d - ", m_break_ids[i]); 125 Breakpoint *breakpoint = 126 m_thread.CalculateTarget()->GetBreakpointByID(m_break_ids[i]).get(); 127 if (breakpoint) 128 breakpoint->Dump(s); 129 else 130 s->Printf("but the breakpoint has been deleted."); 131 } 132 } 133 } 134 135 bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) { 136 // If we couldn't set the breakpoint for some reason, then this won't 137 // work. 138 bool all_bps_good = true; 139 size_t num_break_ids = m_break_ids.size(); 140 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 error->Address(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(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 if (log) 186 log->Printf("Completed run to address plan."); 187 ThreadPlan::MischiefManaged(); 188 return true; 189 } else 190 return false; 191 } 192 193 bool ThreadPlanRunToAddress::AtOurAddress() { 194 lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC(); 195 bool found_it = false; 196 size_t num_addresses = m_addresses.size(); 197 for (size_t i = 0; i < num_addresses; i++) { 198 if (m_addresses[i] == current_address) { 199 found_it = true; 200 break; 201 } 202 } 203 return found_it; 204 } 205