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/Log.h" 23 #include "lldb/Core/Stream.h" 24 #include "lldb/Core/StreamFile.h" 25 #include "lldb/Target/Process.h" 26 #include "lldb/Target/Target.h" 27 #include "lldb/Target/Thread.h" 28 #include "lldb/Target/ThreadSpec.h" 29 30 31 #include "lldb/lldb-enumerations.h" 32 33 using namespace lldb; 34 using namespace lldb_private; 35 36 struct CallbackData 37 { 38 SBBreakpoint::BreakpointHitCallback callback; 39 void *callback_baton; 40 }; 41 42 class SBBreakpointCallbackBaton : public Baton 43 { 44 public: 45 46 SBBreakpointCallbackBaton (SBBreakpoint::BreakpointHitCallback callback, void *baton) : 47 Baton (new CallbackData) 48 { 49 CallbackData *data = (CallbackData *)m_data; 50 data->callback = callback; 51 data->callback_baton = baton; 52 } 53 54 virtual ~SBBreakpointCallbackBaton() 55 { 56 CallbackData *data = (CallbackData *)m_data; 57 58 if (data) 59 { 60 delete data; 61 m_data = NULL; 62 } 63 } 64 }; 65 66 67 SBBreakpoint::SBBreakpoint () : 68 m_opaque_sp () 69 { 70 } 71 72 SBBreakpoint::SBBreakpoint (const SBBreakpoint& rhs) : 73 m_opaque_sp (rhs.m_opaque_sp) 74 { 75 } 76 77 78 SBBreakpoint::SBBreakpoint (const lldb::BreakpointSP &bp_sp) : 79 m_opaque_sp (bp_sp) 80 { 81 } 82 83 SBBreakpoint::~SBBreakpoint() 84 { 85 } 86 87 const SBBreakpoint & 88 SBBreakpoint::operator = (const SBBreakpoint& rhs) 89 { 90 if (this != &rhs) 91 m_opaque_sp = rhs.m_opaque_sp; 92 return *this; 93 } 94 95 bool 96 SBBreakpoint::operator == (const lldb::SBBreakpoint& rhs) 97 { 98 if (m_opaque_sp && rhs.m_opaque_sp) 99 return m_opaque_sp.get() == rhs.m_opaque_sp.get(); 100 return false; 101 } 102 103 break_id_t 104 SBBreakpoint::GetID () const 105 { 106 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 107 108 break_id_t break_id = LLDB_INVALID_BREAK_ID; 109 if (m_opaque_sp) 110 break_id = m_opaque_sp->GetID(); 111 112 if (log) 113 { 114 if (break_id == LLDB_INVALID_BREAK_ID) 115 log->Printf ("SBBreakpoint(%p)::GetID () => LLDB_INVALID_BREAK_ID", m_opaque_sp.get()); 116 else 117 log->Printf ("SBBreakpoint(%p)::GetID () => %u", m_opaque_sp.get(), break_id); 118 } 119 120 return break_id; 121 } 122 123 124 bool 125 SBBreakpoint::IsValid() const 126 { 127 return m_opaque_sp; 128 } 129 130 void 131 SBBreakpoint::ClearAllBreakpointSites () 132 { 133 if (m_opaque_sp) 134 { 135 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 136 m_opaque_sp->ClearAllBreakpointSites (); 137 } 138 } 139 140 SBBreakpointLocation 141 SBBreakpoint::FindLocationByAddress (addr_t vm_addr) 142 { 143 SBBreakpointLocation sb_bp_location; 144 145 if (m_opaque_sp) 146 { 147 if (vm_addr != LLDB_INVALID_ADDRESS) 148 { 149 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 150 Address address; 151 Target &target = m_opaque_sp->GetTarget(); 152 if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false) 153 { 154 address.SetSection (NULL); 155 address.SetOffset (vm_addr); 156 } 157 sb_bp_location.SetLocation (m_opaque_sp->FindLocationByAddress (address)); 158 } 159 } 160 return sb_bp_location; 161 } 162 163 break_id_t 164 SBBreakpoint::FindLocationIDByAddress (addr_t vm_addr) 165 { 166 break_id_t break_id = LLDB_INVALID_BREAK_ID; 167 168 if (m_opaque_sp && vm_addr != LLDB_INVALID_ADDRESS) 169 { 170 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 171 Address address; 172 Target &target = m_opaque_sp->GetTarget(); 173 if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false) 174 { 175 address.SetSection (NULL); 176 address.SetOffset (vm_addr); 177 } 178 break_id = m_opaque_sp->FindLocationIDByAddress (address); 179 } 180 181 return break_id; 182 } 183 184 SBBreakpointLocation 185 SBBreakpoint::FindLocationByID (break_id_t bp_loc_id) 186 { 187 SBBreakpointLocation sb_bp_location; 188 189 if (m_opaque_sp) 190 { 191 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 192 sb_bp_location.SetLocation (m_opaque_sp->FindLocationByID (bp_loc_id)); 193 } 194 195 return sb_bp_location; 196 } 197 198 SBBreakpointLocation 199 SBBreakpoint::GetLocationAtIndex (uint32_t index) 200 { 201 SBBreakpointLocation sb_bp_location; 202 203 if (m_opaque_sp) 204 { 205 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 206 sb_bp_location.SetLocation (m_opaque_sp->GetLocationAtIndex (index)); 207 } 208 209 return sb_bp_location; 210 } 211 212 void 213 SBBreakpoint::SetEnabled (bool enable) 214 { 215 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 216 217 if (log) 218 log->Printf ("SBBreakpoint(%p)::SetEnabled (enabled=%i)", m_opaque_sp.get(), enable); 219 220 if (m_opaque_sp) 221 { 222 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 223 m_opaque_sp->SetEnabled (enable); 224 } 225 } 226 227 bool 228 SBBreakpoint::IsEnabled () 229 { 230 if (m_opaque_sp) 231 { 232 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 233 return m_opaque_sp->IsEnabled(); 234 } 235 else 236 return false; 237 } 238 239 void 240 SBBreakpoint::SetIgnoreCount (uint32_t count) 241 { 242 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 243 244 if (log) 245 log->Printf ("SBBreakpoint(%p)::SetIgnoreCount (count=%u)", m_opaque_sp.get(), count); 246 247 if (m_opaque_sp) 248 { 249 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 250 m_opaque_sp->SetIgnoreCount (count); 251 } 252 } 253 254 void 255 SBBreakpoint::SetCondition (const char *condition) 256 { 257 if (m_opaque_sp) 258 { 259 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 260 m_opaque_sp->SetCondition (condition); 261 } 262 } 263 264 const char * 265 SBBreakpoint::GetCondition () 266 { 267 if (m_opaque_sp) 268 { 269 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 270 return m_opaque_sp->GetConditionText (); 271 } 272 return NULL; 273 } 274 275 uint32_t 276 SBBreakpoint::GetHitCount () const 277 { 278 uint32_t count = 0; 279 if (m_opaque_sp) 280 { 281 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 282 count = m_opaque_sp->GetHitCount(); 283 } 284 285 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 286 if (log) 287 log->Printf ("SBBreakpoint(%p)::GetHitCount () => %u", m_opaque_sp.get(), count); 288 289 return count; 290 } 291 292 uint32_t 293 SBBreakpoint::GetIgnoreCount () const 294 { 295 uint32_t count = 0; 296 if (m_opaque_sp) 297 { 298 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 299 count = m_opaque_sp->GetIgnoreCount(); 300 } 301 302 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 303 if (log) 304 log->Printf ("SBBreakpoint(%p)::GetIgnoreCount () => %u", m_opaque_sp.get(), count); 305 306 return count; 307 } 308 309 void 310 SBBreakpoint::SetThreadID (tid_t tid) 311 { 312 if (m_opaque_sp) 313 { 314 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 315 m_opaque_sp->SetThreadID (tid); 316 } 317 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 318 if (log) 319 log->Printf ("SBBreakpoint(%p)::SetThreadID (tid=0x%4.4x)", m_opaque_sp.get(), tid); 320 321 } 322 323 tid_t 324 SBBreakpoint::GetThreadID () 325 { 326 tid_t tid = LLDB_INVALID_THREAD_ID; 327 if (m_opaque_sp) 328 { 329 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 330 tid = m_opaque_sp->GetThreadID(); 331 } 332 333 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 334 if (log) 335 log->Printf ("SBBreakpoint(%p)::GetThreadID () => 0x%4.4x", m_opaque_sp.get(), tid); 336 return tid; 337 } 338 339 void 340 SBBreakpoint::SetThreadIndex (uint32_t index) 341 { 342 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 343 if (log) 344 log->Printf ("SBBreakpoint(%p)::SetThreadIndex (%u)", m_opaque_sp.get(), index); 345 if (m_opaque_sp) 346 { 347 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 348 m_opaque_sp->GetOptions()->GetThreadSpec()->SetIndex (index); 349 } 350 } 351 352 uint32_t 353 SBBreakpoint::GetThreadIndex() const 354 { 355 uint32_t thread_idx = UINT32_MAX; 356 if (m_opaque_sp) 357 { 358 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 359 const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate(); 360 if (thread_spec != NULL) 361 thread_idx = thread_spec->GetIndex(); 362 } 363 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 364 if (log) 365 log->Printf ("SBBreakpoint(%p)::GetThreadIndex () => %u", m_opaque_sp.get(), thread_idx); 366 367 return thread_idx; 368 } 369 370 371 void 372 SBBreakpoint::SetThreadName (const char *thread_name) 373 { 374 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 375 if (log) 376 log->Printf ("SBBreakpoint(%p)::SetThreadName (%s)", m_opaque_sp.get(), thread_name); 377 378 if (m_opaque_sp) 379 { 380 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 381 m_opaque_sp->GetOptions()->GetThreadSpec()->SetName (thread_name); 382 } 383 } 384 385 const char * 386 SBBreakpoint::GetThreadName () const 387 { 388 const char *name = NULL; 389 if (m_opaque_sp) 390 { 391 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 392 const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate(); 393 if (thread_spec != NULL) 394 name = thread_spec->GetName(); 395 } 396 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 397 if (log) 398 log->Printf ("SBBreakpoint(%p)::GetThreadName () => %s", m_opaque_sp.get(), name); 399 400 return name; 401 } 402 403 void 404 SBBreakpoint::SetQueueName (const char *queue_name) 405 { 406 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 407 if (log) 408 log->Printf ("SBBreakpoint(%p)::SetQueueName (%s)", m_opaque_sp.get(), queue_name); 409 if (m_opaque_sp) 410 { 411 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 412 m_opaque_sp->GetOptions()->GetThreadSpec()->SetQueueName (queue_name); 413 } 414 } 415 416 const char * 417 SBBreakpoint::GetQueueName () const 418 { 419 const char *name = NULL; 420 if (m_opaque_sp) 421 { 422 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 423 const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate(); 424 if (thread_spec) 425 name = thread_spec->GetQueueName(); 426 } 427 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 428 if (log) 429 log->Printf ("SBBreakpoint(%p)::GetQueueName () => %s", m_opaque_sp.get(), name); 430 431 return name; 432 } 433 434 size_t 435 SBBreakpoint::GetNumResolvedLocations() const 436 { 437 size_t num_resolved = 0; 438 if (m_opaque_sp) 439 { 440 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 441 num_resolved = m_opaque_sp->GetNumResolvedLocations(); 442 } 443 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 444 if (log) 445 log->Printf ("SBBreakpoint(%p)::GetNumResolvedLocations () => %zu", m_opaque_sp.get(), num_resolved); 446 return num_resolved; 447 } 448 449 size_t 450 SBBreakpoint::GetNumLocations() const 451 { 452 size_t num_locs = 0; 453 if (m_opaque_sp) 454 { 455 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 456 num_locs = m_opaque_sp->GetNumLocations(); 457 } 458 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 459 if (log) 460 log->Printf ("SBBreakpoint(%p)::GetNumLocations () => %zu", m_opaque_sp.get(), num_locs); 461 return num_locs; 462 } 463 464 bool 465 SBBreakpoint::GetDescription (SBStream &s) 466 { 467 if (m_opaque_sp) 468 { 469 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 470 s.Printf("SBBreakpoint: id = %i, ", m_opaque_sp->GetID()); 471 m_opaque_sp->GetResolverDescription (s.get()); 472 m_opaque_sp->GetFilterDescription (s.get()); 473 const size_t num_locations = m_opaque_sp->GetNumLocations (); 474 s.Printf(", locations = %zu", num_locations); 475 return true; 476 } 477 s.Printf ("No value"); 478 return false; 479 } 480 481 bool 482 SBBreakpoint::PrivateBreakpointHitCallback 483 ( 484 void *baton, 485 StoppointCallbackContext *ctx, 486 lldb::user_id_t break_id, 487 lldb::user_id_t break_loc_id 488 ) 489 { 490 BreakpointSP bp_sp(ctx->exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id)); 491 if (baton && bp_sp) 492 { 493 CallbackData *data = (CallbackData *)baton; 494 lldb_private::Breakpoint *bp = bp_sp.get(); 495 if (bp && data->callback) 496 { 497 Process *process = ctx->exe_ctx.GetProcessPtr(); 498 if (process) 499 { 500 SBProcess sb_process (process->GetSP()); 501 SBThread sb_thread; 502 SBBreakpointLocation sb_location; 503 assert (bp_sp); 504 sb_location.SetLocation (bp_sp->FindLocationByID (break_loc_id)); 505 Thread *thread = ctx->exe_ctx.GetThreadPtr(); 506 if (thread) 507 sb_thread.SetThread(thread->GetSP()); 508 509 return data->callback (data->callback_baton, 510 sb_process, 511 sb_thread, 512 sb_location); 513 } 514 } 515 } 516 return true; // Return true if we should stop at this breakpoint 517 } 518 519 void 520 SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton) 521 { 522 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 523 524 if (log) 525 log->Printf ("SBBreakpoint(%p)::SetCallback (callback=%p, baton=%p)", m_opaque_sp.get(), callback, baton); 526 527 if (m_opaque_sp) 528 { 529 Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); 530 BatonSP baton_sp(new SBBreakpointCallbackBaton (callback, baton)); 531 m_opaque_sp->SetCallback (SBBreakpoint::PrivateBreakpointHitCallback, baton_sp, false); 532 } 533 } 534 535 536 lldb_private::Breakpoint * 537 SBBreakpoint::operator->() const 538 { 539 return m_opaque_sp.get(); 540 } 541 542 lldb_private::Breakpoint * 543 SBBreakpoint::get() const 544 { 545 return m_opaque_sp.get(); 546 } 547 548 lldb::BreakpointSP & 549 SBBreakpoint::operator *() 550 { 551 return m_opaque_sp; 552 } 553 554 const lldb::BreakpointSP & 555 SBBreakpoint::operator *() const 556 { 557 return m_opaque_sp; 558 } 559 560 BreakpointEventType 561 SBBreakpoint::GetBreakpointEventTypeFromEvent (const SBEvent& event) 562 { 563 if (event.IsValid()) 564 return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event.GetSP()); 565 return eBreakpointEventTypeInvalidType; 566 } 567 568 SBBreakpoint 569 SBBreakpoint::GetBreakpointFromEvent (const lldb::SBEvent& event) 570 { 571 SBBreakpoint sb_breakpoint; 572 if (event.IsValid()) 573 sb_breakpoint.m_opaque_sp = Breakpoint::BreakpointEventData::GetBreakpointFromEvent (event.GetSP()); 574 return sb_breakpoint; 575 } 576 577 SBBreakpointLocation 578 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx) 579 { 580 SBBreakpointLocation sb_breakpoint_loc; 581 if (event.IsValid()) 582 sb_breakpoint_loc.SetLocation (Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (event.GetSP(), loc_idx)); 583 return sb_breakpoint_loc; 584 } 585 586 587