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