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