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 #include "lldb/Target/ThreadPlanRunToAddress.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/lldb-private-log.h" 17 #include "lldb/Core/Log.h" 18 #include "lldb/Core/Stream.h" 19 #include "lldb/Target/Target.h" 20 #include "lldb/Target/Process.h" 21 #include "lldb/Target/Thread.h" 22 #include "lldb/Target/RegisterContext.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 //---------------------------------------------------------------------- 28 // ThreadPlanRunToAddress: Continue plan 29 //---------------------------------------------------------------------- 30 31 ThreadPlanRunToAddress::ThreadPlanRunToAddress 32 ( 33 Thread &thread, 34 Address &address, 35 bool stop_others 36 ) : 37 ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion), 38 m_stop_others (stop_others), 39 m_addresses (), 40 m_break_ids () 41 { 42 m_addresses.push_back (address.GetLoadAddress(&m_thread.GetProcess().GetTarget())); 43 SetInitialBreakpoints(); 44 } 45 46 ThreadPlanRunToAddress::ThreadPlanRunToAddress 47 ( 48 Thread &thread, 49 lldb::addr_t address, 50 bool stop_others 51 ) : 52 ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion), 53 m_stop_others (stop_others), 54 m_addresses (), 55 m_break_ids () 56 { 57 m_addresses.push_back(address); 58 SetInitialBreakpoints(); 59 } 60 61 ThreadPlanRunToAddress::ThreadPlanRunToAddress 62 ( 63 Thread &thread, 64 std::vector<lldb::addr_t> &addresses, 65 bool stop_others 66 ) : 67 ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion), 68 m_stop_others (stop_others), 69 m_addresses (addresses), 70 m_break_ids () 71 { 72 SetInitialBreakpoints(); 73 } 74 75 void 76 ThreadPlanRunToAddress::SetInitialBreakpoints () 77 { 78 size_t num_addresses = m_addresses.size(); 79 m_break_ids.resize(num_addresses); 80 81 for (size_t i = 0; i < num_addresses; i++) 82 { 83 Breakpoint *breakpoint; 84 breakpoint = m_thread.GetProcess().GetTarget().CreateBreakpoint (m_addresses[i], true).get(); 85 if (breakpoint != NULL) 86 { 87 m_break_ids[i] = breakpoint->GetID(); 88 breakpoint->SetThreadID(m_thread.GetID()); 89 } 90 } 91 } 92 93 ThreadPlanRunToAddress::~ThreadPlanRunToAddress () 94 { 95 size_t num_break_ids = m_break_ids.size(); 96 for (size_t i = 0; i < num_break_ids; i++) 97 { 98 m_thread.GetProcess().GetTarget().RemoveBreakpointByID (m_break_ids[i]); 99 } 100 } 101 102 void 103 ThreadPlanRunToAddress::GetDescription (Stream *s, lldb::DescriptionLevel level) 104 { 105 size_t num_addresses = m_addresses.size(); 106 107 if (level == lldb::eDescriptionLevelBrief) 108 { 109 if (num_addresses == 0) 110 { 111 s->Printf ("run to address with no addresses given."); 112 return; 113 } 114 else if (num_addresses == 1) 115 s->Printf ("run to address: "); 116 else 117 s->Printf ("run to addresses: "); 118 119 for (size_t i = 0; i < num_addresses; i++) 120 { 121 s->Address (m_addresses[i], sizeof (addr_t)); 122 s->Printf(" "); 123 } 124 } 125 else 126 { 127 if (num_addresses == 0) 128 { 129 s->Printf ("run to address with no addresses given."); 130 return; 131 } 132 else if (num_addresses == 1) 133 s->Printf ("Run to address: "); 134 else 135 { 136 s->Printf ("Run to addresses: "); 137 } 138 139 for (size_t i = 0; i < num_addresses; i++) 140 { 141 if (num_addresses > 1) 142 { 143 s->Printf("\n"); 144 s->Indent(); 145 } 146 147 s->Address(m_addresses[i], sizeof (addr_t)); 148 s->Printf (" using breakpoint: %d - ", m_break_ids[i]); 149 Breakpoint *breakpoint = m_thread.GetProcess().GetTarget().GetBreakpointByID (m_break_ids[i]).get(); 150 if (breakpoint) 151 breakpoint->Dump (s); 152 else 153 s->Printf ("but the breakpoint has been deleted."); 154 } 155 } 156 } 157 158 bool 159 ThreadPlanRunToAddress::ValidatePlan (Stream *error) 160 { 161 // If we couldn't set the breakpoint for some reason, then this won't 162 // work. 163 bool all_bps_good = true; 164 size_t num_break_ids = m_break_ids.size(); 165 166 for (size_t i = 0; i < num_break_ids; i++) 167 { 168 if (m_break_ids[i] == LLDB_INVALID_BREAK_ID) 169 { 170 all_bps_good = false; 171 if (error) 172 { 173 error->Printf ("Could not set breakpoint for address: "); 174 error->Address (m_addresses[i], sizeof (addr_t)); 175 error->Printf ("\n"); 176 } 177 } 178 } 179 return all_bps_good; 180 } 181 182 bool 183 ThreadPlanRunToAddress::PlanExplainsStop () 184 { 185 return AtOurAddress(); 186 } 187 188 bool 189 ThreadPlanRunToAddress::ShouldStop (Event *event_ptr) 190 { 191 return false; 192 } 193 194 bool 195 ThreadPlanRunToAddress::StopOthers () 196 { 197 return m_stop_others; 198 } 199 200 void 201 ThreadPlanRunToAddress::SetStopOthers (bool new_value) 202 { 203 m_stop_others = new_value; 204 } 205 206 StateType 207 ThreadPlanRunToAddress::GetPlanRunState () 208 { 209 return eStateRunning; 210 } 211 212 bool 213 ThreadPlanRunToAddress::WillStop () 214 { 215 return true; 216 } 217 218 bool 219 ThreadPlanRunToAddress::MischiefManaged () 220 { 221 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 222 223 if (AtOurAddress()) 224 { 225 // Remove the breakpoint 226 size_t num_break_ids = m_break_ids.size(); 227 228 for (size_t i = 0; i < num_break_ids; i++) 229 { 230 if (m_break_ids[i] != LLDB_INVALID_BREAK_ID) 231 { 232 m_thread.GetProcess().GetTarget().RemoveBreakpointByID (m_break_ids[i]); 233 m_break_ids[i] = LLDB_INVALID_BREAK_ID; 234 } 235 } 236 if (log) 237 log->Printf("Completed run to address plan."); 238 ThreadPlan::MischiefManaged (); 239 return true; 240 } 241 else 242 return false; 243 } 244 245 bool 246 ThreadPlanRunToAddress::AtOurAddress () 247 { 248 lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC(); 249 bool found_it = false; 250 size_t num_addresses = m_addresses.size(); 251 for (size_t i = 0; i < num_addresses; i++) 252 { 253 if (m_addresses[i] == current_address) 254 { 255 found_it = true; 256 break; 257 } 258 } 259 return found_it; 260 } 261