1 //===-- SBBreakpoint.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/API/SBBreakpoint.h" 11 #include "lldb/API/SBBreakpointLocation.h" 12 #include "lldb/API/SBDebugger.h" 13 #include "lldb/API/SBEvent.h" 14 #include "lldb/API/SBProcess.h" 15 #include "lldb/API/SBStream.h" 16 #include "lldb/API/SBThread.h" 17 18 #include "lldb/Breakpoint/Breakpoint.h" 19 #include "lldb/Breakpoint/BreakpointLocation.h" 20 #include "lldb/Breakpoint/StoppointCallbackContext.h" 21 #include "lldb/Core/Address.h" 22 #include "lldb/Core/Stream.h" 23 #include "lldb/Core/StreamFile.h" 24 #include "lldb/Target/Process.h" 25 #include "lldb/Target/Target.h" 26 #include "lldb/Target/Thread.h" 27 #include "lldb/Target/ThreadSpec.h" 28 29 30 #include "lldb/lldb-enumerations.h" 31 32 using namespace lldb; 33 using namespace lldb_private; 34 35 struct CallbackData 36 { 37 SBBreakpoint::BreakpointHitCallback callback; 38 void *callback_baton; 39 }; 40 41 class SBBreakpointCallbackBaton : public Baton 42 { 43 public: 44 45 SBBreakpointCallbackBaton (SBBreakpoint::BreakpointHitCallback callback, void *baton) : 46 Baton (new CallbackData) 47 { 48 CallbackData *data = (CallbackData *)m_data; 49 data->callback = callback; 50 data->callback_baton = baton; 51 } 52 53 virtual ~SBBreakpointCallbackBaton() 54 { 55 CallbackData *data = (CallbackData *)m_data; 56 57 if (data) 58 { 59 delete data; 60 m_data = NULL; 61 } 62 } 63 }; 64 65 66 SBBreakpoint::SBBreakpoint () : 67 m_opaque_sp () 68 { 69 } 70 71 SBBreakpoint::SBBreakpoint (const SBBreakpoint& rhs) : 72 m_opaque_sp (rhs.m_opaque_sp) 73 { 74 } 75 76 77 SBBreakpoint::SBBreakpoint (const lldb::BreakpointSP &bp_sp) : 78 m_opaque_sp (bp_sp) 79 { 80 } 81 82 SBBreakpoint::~SBBreakpoint() 83 { 84 } 85 86 const SBBreakpoint & 87 SBBreakpoint::operator = (const SBBreakpoint& rhs) 88 { 89 if (this != &rhs) 90 { 91 m_opaque_sp = rhs.m_opaque_sp; 92 } 93 return *this; 94 } 95 96 break_id_t 97 SBBreakpoint::GetID () const 98 { 99 if (m_opaque_sp) 100 return m_opaque_sp->GetID(); 101 return LLDB_INVALID_BREAK_ID; 102 } 103 104 105 bool 106 SBBreakpoint::IsValid() const 107 { 108 return m_opaque_sp; 109 } 110 111 void 112 SBBreakpoint::ClearAllBreakpointSites () 113 { 114 if (m_opaque_sp) 115 m_opaque_sp->ClearAllBreakpointSites (); 116 } 117 118 SBBreakpointLocation 119 SBBreakpoint::FindLocationByAddress (addr_t vm_addr) 120 { 121 SBBreakpointLocation sb_bp_location; 122 123 if (m_opaque_sp) 124 { 125 if (vm_addr != LLDB_INVALID_ADDRESS) 126 { 127 Address address; 128 Target &target = m_opaque_sp->GetTarget(); 129 if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false) 130 { 131 address.SetSection (NULL); 132 address.SetOffset (vm_addr); 133 } 134 sb_bp_location.SetLocation (m_opaque_sp->FindLocationByAddress (address)); 135 } 136 } 137 return sb_bp_location; 138 } 139 140 break_id_t 141 SBBreakpoint::FindLocationIDByAddress (addr_t vm_addr) 142 { 143 break_id_t lldb_id = (break_id_t) 0; 144 145 if (m_opaque_sp) 146 { 147 if (vm_addr != LLDB_INVALID_ADDRESS) 148 { 149 Address address; 150 Target &target = m_opaque_sp->GetTarget(); 151 if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false) 152 { 153 address.SetSection (NULL); 154 address.SetOffset (vm_addr); 155 } 156 lldb_id = m_opaque_sp->FindLocationIDByAddress (address); 157 } 158 } 159 160 return lldb_id; 161 } 162 163 SBBreakpointLocation 164 SBBreakpoint::FindLocationByID (break_id_t bp_loc_id) 165 { 166 SBBreakpointLocation sb_bp_location; 167 168 if (m_opaque_sp) 169 sb_bp_location.SetLocation (m_opaque_sp->FindLocationByID (bp_loc_id)); 170 171 return sb_bp_location; 172 } 173 174 SBBreakpointLocation 175 SBBreakpoint::GetLocationAtIndex (uint32_t index) 176 { 177 SBBreakpointLocation sb_bp_location; 178 179 if (m_opaque_sp) 180 sb_bp_location.SetLocation (m_opaque_sp->GetLocationAtIndex (index)); 181 182 return sb_bp_location; 183 } 184 185 void 186 SBBreakpoint::SetEnabled (bool enable) 187 { 188 if (m_opaque_sp) 189 m_opaque_sp->SetEnabled (enable); 190 } 191 192 bool 193 SBBreakpoint::IsEnabled () 194 { 195 if (m_opaque_sp) 196 return m_opaque_sp->IsEnabled(); 197 else 198 return false; 199 } 200 201 void 202 SBBreakpoint::SetIgnoreCount (uint32_t count) 203 { 204 if (m_opaque_sp) 205 m_opaque_sp->SetIgnoreCount (count); 206 } 207 208 uint32_t 209 SBBreakpoint::GetHitCount () const 210 { 211 if (m_opaque_sp) 212 return m_opaque_sp->GetHitCount(); 213 else 214 return 0; 215 } 216 217 uint32_t 218 SBBreakpoint::GetIgnoreCount () const 219 { 220 if (m_opaque_sp) 221 return m_opaque_sp->GetIgnoreCount(); 222 else 223 return 0; 224 } 225 226 void 227 SBBreakpoint::SetThreadID (tid_t sb_thread_id) 228 { 229 if (m_opaque_sp) 230 m_opaque_sp->SetThreadID (sb_thread_id); 231 } 232 233 tid_t 234 SBBreakpoint::GetThreadID () 235 { 236 tid_t lldb_thread_id = LLDB_INVALID_THREAD_ID; 237 if (m_opaque_sp) 238 lldb_thread_id = m_opaque_sp->GetThreadID(); 239 240 return lldb_thread_id; 241 } 242 243 void 244 SBBreakpoint::SetThreadIndex (uint32_t index) 245 { 246 if (m_opaque_sp) 247 m_opaque_sp->GetOptions()->GetThreadSpec()->SetIndex (index); 248 } 249 250 uint32_t 251 SBBreakpoint::GetThreadIndex() const 252 { 253 if (m_opaque_sp) 254 { 255 const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpec(); 256 if (thread_spec == NULL) 257 return 0; 258 else 259 return thread_spec->GetIndex(); 260 } 261 return 0; 262 } 263 264 265 void 266 SBBreakpoint::SetThreadName (const char *thread_name) 267 { 268 if (m_opaque_sp) 269 m_opaque_sp->GetOptions()->GetThreadSpec()->SetName (thread_name); 270 } 271 272 const char * 273 SBBreakpoint::GetThreadName () const 274 { 275 if (m_opaque_sp) 276 { 277 const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpec(); 278 if (thread_spec == NULL) 279 return NULL; 280 else 281 return thread_spec->GetName(); 282 } 283 return NULL; 284 } 285 286 void 287 SBBreakpoint::SetQueueName (const char *queue_name) 288 { 289 if (m_opaque_sp) 290 m_opaque_sp->GetOptions()->GetThreadSpec()->SetQueueName (queue_name); 291 } 292 293 const char * 294 SBBreakpoint::GetQueueName () const 295 { 296 if (m_opaque_sp) 297 { 298 const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpec(); 299 if (thread_spec == NULL) 300 return NULL; 301 else 302 return thread_spec->GetQueueName(); 303 } 304 return NULL; 305 } 306 307 size_t 308 SBBreakpoint::GetNumResolvedLocations() const 309 { 310 if (m_opaque_sp) 311 return m_opaque_sp->GetNumResolvedLocations(); 312 else 313 return 0; 314 } 315 316 size_t 317 SBBreakpoint::GetNumLocations() const 318 { 319 if (m_opaque_sp) 320 return m_opaque_sp->GetNumLocations(); 321 else 322 return 0; 323 } 324 325 bool 326 SBBreakpoint::GetDescription (SBStream &s) 327 { 328 if (m_opaque_sp) 329 { 330 s.Printf("SBBreakpoint: id = %i, ", m_opaque_sp->GetID()); 331 m_opaque_sp->GetResolverDescription (s.get()); 332 m_opaque_sp->GetFilterDescription (s.get()); 333 const size_t num_locations = m_opaque_sp->GetNumLocations (); 334 s.Printf(", locations = %zu", num_locations); 335 return true; 336 } 337 s.Printf ("No value"); 338 return false; 339 } 340 341 bool 342 SBBreakpoint::PrivateBreakpointHitCallback 343 ( 344 void *baton, 345 StoppointCallbackContext *ctx, 346 lldb::user_id_t break_id, 347 lldb::user_id_t break_loc_id 348 ) 349 { 350 BreakpointSP bp_sp(ctx->exe_ctx.target->GetBreakpointList().FindBreakpointByID(break_id)); 351 if (baton && bp_sp) 352 { 353 CallbackData *data = (CallbackData *)baton; 354 lldb_private::Breakpoint *bp = bp_sp.get(); 355 if (bp && data->callback) 356 { 357 if (ctx->exe_ctx.process) 358 { 359 SBProcess sb_process (ctx->exe_ctx.process->GetSP()); 360 SBThread sb_thread; 361 SBBreakpointLocation sb_location; 362 assert (bp_sp); 363 sb_location.SetLocation (bp_sp->FindLocationByID (break_loc_id)); 364 if (ctx->exe_ctx.thread) 365 sb_thread.SetThread(ctx->exe_ctx.thread->GetSP()); 366 367 return data->callback (data->callback_baton, 368 sb_process, 369 sb_thread, 370 sb_location); 371 } 372 } 373 } 374 return true; // Return true if we should stop at this breakpoint 375 } 376 377 void 378 SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton) 379 { 380 if (m_opaque_sp.get()) 381 { 382 BatonSP baton_sp(new SBBreakpointCallbackBaton (callback, baton)); 383 m_opaque_sp->SetCallback (SBBreakpoint::PrivateBreakpointHitCallback, baton_sp, false); 384 } 385 } 386 387 388 lldb_private::Breakpoint * 389 SBBreakpoint::operator->() const 390 { 391 return m_opaque_sp.get(); 392 } 393 394 lldb_private::Breakpoint * 395 SBBreakpoint::get() const 396 { 397 return m_opaque_sp.get(); 398 } 399 400 lldb::BreakpointSP & 401 SBBreakpoint::operator *() 402 { 403 return m_opaque_sp; 404 } 405 406 const lldb::BreakpointSP & 407 SBBreakpoint::operator *() const 408 { 409 return m_opaque_sp; 410 } 411 412 BreakpointEventType 413 SBBreakpoint::GetBreakpointEventTypeFromEvent (const SBEvent& event) 414 { 415 if (event.IsValid()) 416 return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event.GetSP()); 417 return eBreakpointEventTypeInvalidType; 418 } 419 420 SBBreakpoint 421 SBBreakpoint::GetBreakpointFromEvent (const lldb::SBEvent& event) 422 { 423 SBBreakpoint sb_breakpoint; 424 if (event.IsValid()) 425 sb_breakpoint.m_opaque_sp = Breakpoint::BreakpointEventData::GetBreakpointFromEvent (event.GetSP()); 426 return sb_breakpoint; 427 } 428 429 SBBreakpointLocation 430 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx) 431 { 432 SBBreakpointLocation sb_breakpoint_loc; 433 if (event.IsValid()) 434 sb_breakpoint_loc.SetLocation (Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (event.GetSP(), loc_idx)); 435 return sb_breakpoint_loc; 436 } 437 438 439