//===-- SBBreakpoint.cpp ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/API/SBBreakpoint.h" #include "lldb/API/SBBreakpointLocation.h" #include "lldb/API/SBDebugger.h" #include "lldb/API/SBProcess.h" #include "lldb/API/SBThread.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Address.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadSpec.h" #include "lldb/lldb-enumerations.h" using namespace lldb; using namespace lldb_private; struct CallbackData { SBBreakpoint::BreakpointHitCallback callback; void *callback_baton; }; class SBBreakpointCallbackBaton : public Baton { public: SBBreakpointCallbackBaton (SBBreakpoint::BreakpointHitCallback callback, void *baton) : Baton (new CallbackData) { CallbackData *data = (CallbackData *)m_data; data->callback = callback; data->callback_baton = baton; } virtual ~SBBreakpointCallbackBaton() { CallbackData *data = (CallbackData *)m_data; if (data) { delete data; m_data = NULL; } } }; SBBreakpoint::SBBreakpoint () : m_opaque_sp () { } SBBreakpoint::SBBreakpoint (const SBBreakpoint& rhs) : m_opaque_sp (rhs.m_opaque_sp) { } SBBreakpoint::SBBreakpoint (const lldb::BreakpointSP &bp_sp) : m_opaque_sp (bp_sp) { } SBBreakpoint::~SBBreakpoint() { } const SBBreakpoint & SBBreakpoint::operator = (const SBBreakpoint& rhs) { if (this != &rhs) { m_opaque_sp = rhs.m_opaque_sp; } return *this; } break_id_t SBBreakpoint::GetID () const { if (m_opaque_sp) return m_opaque_sp->GetID(); return LLDB_INVALID_BREAK_ID; } bool SBBreakpoint::IsValid() const { return m_opaque_sp; } void SBBreakpoint::Dump (FILE *f) { if (m_opaque_sp && f) { lldb_private::StreamFile str (f); m_opaque_sp->Dump (&str); } } void SBBreakpoint::ClearAllBreakpointSites () { if (m_opaque_sp) m_opaque_sp->ClearAllBreakpointSites (); } SBBreakpointLocation SBBreakpoint::FindLocationByAddress (addr_t vm_addr) { SBBreakpointLocation sb_bp_location; if (m_opaque_sp) { if (vm_addr != LLDB_INVALID_ADDRESS) { Address address; Process *sb_process = m_opaque_sp->GetTarget().GetProcessSP().get(); if (sb_process == NULL || sb_process->ResolveLoadAddress (vm_addr, address) == false) { address.SetSection (NULL); address.SetOffset (vm_addr); } sb_bp_location.SetLocation (m_opaque_sp->FindLocationByAddress (address)); } } return sb_bp_location; } break_id_t SBBreakpoint::FindLocationIDByAddress (addr_t vm_addr) { break_id_t lldb_id = (break_id_t) 0; if (m_opaque_sp) { if (vm_addr != LLDB_INVALID_ADDRESS) { Address address; Process *sb_process = m_opaque_sp->GetTarget().GetProcessSP().get(); if (sb_process == NULL || sb_process->ResolveLoadAddress (vm_addr, address) == false) { address.SetSection (NULL); address.SetOffset (vm_addr); } lldb_id = m_opaque_sp->FindLocationIDByAddress (address); } } return lldb_id; } SBBreakpointLocation SBBreakpoint::FindLocationByID (break_id_t bp_loc_id) { SBBreakpointLocation sb_bp_location; if (m_opaque_sp) sb_bp_location.SetLocation (m_opaque_sp->FindLocationByID (bp_loc_id)); return sb_bp_location; } SBBreakpointLocation SBBreakpoint::GetLocationAtIndex (uint32_t index) { SBBreakpointLocation sb_bp_location; if (m_opaque_sp) sb_bp_location.SetLocation (m_opaque_sp->GetLocationAtIndex (index)); return sb_bp_location; } void SBBreakpoint::ListLocations (FILE* f, const char *description_level) { if (m_opaque_sp && f) { DescriptionLevel level; if (strcmp (description_level, "brief") == 0) level = eDescriptionLevelBrief; else if (strcmp (description_level, "full") == 0) level = eDescriptionLevelFull; else if (strcmp (description_level, "verbose") == 0) level = eDescriptionLevelVerbose; else level = eDescriptionLevelBrief; StreamFile str (f); str.IndentMore(); int num_locs = m_opaque_sp->GetNumLocations(); for (int i = 0; i < num_locs; ++i) { BreakpointLocation *loc = m_opaque_sp->GetLocationAtIndex (i).get(); loc->GetDescription (&str, level); str.EOL(); } } } void SBBreakpoint::SetEnabled (bool enable) { if (m_opaque_sp) m_opaque_sp->SetEnabled (enable); } bool SBBreakpoint::IsEnabled () { if (m_opaque_sp) return m_opaque_sp->IsEnabled(); else return false; } void SBBreakpoint::SetIgnoreCount (int32_t count) { if (m_opaque_sp) m_opaque_sp->SetIgnoreCount (count); } int32_t SBBreakpoint::GetIgnoreCount () const { if (m_opaque_sp) return m_opaque_sp->GetIgnoreCount(); else return 0; } void SBBreakpoint::SetThreadID (tid_t sb_thread_id) { if (m_opaque_sp) m_opaque_sp->SetThreadID (sb_thread_id); } tid_t SBBreakpoint::GetThreadID () { tid_t lldb_thread_id = LLDB_INVALID_THREAD_ID; if (m_opaque_sp) lldb_thread_id = m_opaque_sp->GetThreadID(); return lldb_thread_id; } void SBBreakpoint::SetThreadIndex (uint32_t index) { if (m_opaque_sp) m_opaque_sp->GetOptions()->GetThreadSpec()->SetIndex (index); } uint32_t SBBreakpoint::GetThreadIndex() const { if (m_opaque_sp) { const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpec(); if (thread_spec == NULL) return 0; else return thread_spec->GetIndex(); } return 0; } void SBBreakpoint::SetThreadName (const char *thread_name) { if (m_opaque_sp) m_opaque_sp->GetOptions()->GetThreadSpec()->SetName (thread_name); } const char * SBBreakpoint::GetThreadName () const { if (m_opaque_sp) { const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpec(); if (thread_spec == NULL) return NULL; else return thread_spec->GetName(); } return NULL; } void SBBreakpoint::SetQueueName (const char *queue_name) { if (m_opaque_sp) m_opaque_sp->GetOptions()->GetThreadSpec()->SetQueueName (queue_name); } const char * SBBreakpoint::GetQueueName () const { if (m_opaque_sp) { const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpec(); if (thread_spec == NULL) return NULL; else return thread_spec->GetQueueName(); } return NULL; } size_t SBBreakpoint::GetNumResolvedLocations() const { if (m_opaque_sp) return m_opaque_sp->GetNumResolvedLocations(); else return 0; } size_t SBBreakpoint::GetNumLocations() const { if (m_opaque_sp) return m_opaque_sp->GetNumLocations(); else return 0; } void SBBreakpoint::GetDescription (FILE *f, const char *description_level, bool describe_locations) { if (f == NULL) return; if (m_opaque_sp) { DescriptionLevel level; if (strcmp (description_level, "brief") == 0) level = eDescriptionLevelBrief; else if (strcmp (description_level, "full") == 0) level = eDescriptionLevelFull; else if (strcmp (description_level, "verbose") == 0) level = eDescriptionLevelVerbose; else level = eDescriptionLevelBrief; StreamFile str (f); m_opaque_sp->GetDescription (&str, level); str.EOL(); if (describe_locations) { //str.IndentMore(); // int num_locs = m_opaque_sp->GetNumLocations(); // for (int i = 0; i < num_locs; ++i) // { // BreakpointLocation *loc = m_opaque_sp->FindLocationByIndex (i); // loc->GetDescription (&str, level); // str.EOL(); // } ListLocations (f, description_level); } } } bool SBBreakpoint::PrivateBreakpointHitCallback ( void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id, lldb::user_id_t break_loc_id ) { BreakpointSP bp_sp(ctx->exe_ctx.target->GetBreakpointList().FindBreakpointByID(break_id)); if (baton && bp_sp) { CallbackData *data = (CallbackData *)baton; lldb_private::Breakpoint *bp = bp_sp.get(); if (bp && data->callback) { if (ctx->exe_ctx.process) { SBProcess sb_process (ctx->exe_ctx.process->GetSP()); SBThread sb_thread; SBBreakpointLocation sb_location; assert (bp_sp); sb_location.SetLocation (bp_sp->FindLocationByID (break_loc_id)); if (ctx->exe_ctx.thread) sb_thread.SetThread(ctx->exe_ctx.thread->GetSP()); return data->callback (data->callback_baton, sb_process, sb_thread, sb_location); } } } return true; // Return true if we should stop at this breakpoint } void SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton) { if (m_opaque_sp.get()) { BatonSP baton_sp(new SBBreakpointCallbackBaton (callback, baton)); m_opaque_sp->SetCallback (SBBreakpoint::PrivateBreakpointHitCallback, baton_sp, false); } } lldb_private::Breakpoint * SBBreakpoint::operator->() const { return m_opaque_sp.get(); } lldb_private::Breakpoint * SBBreakpoint::get() const { return m_opaque_sp.get(); } lldb::BreakpointSP & SBBreakpoint::operator *() { return m_opaque_sp; } const lldb::BreakpointSP & SBBreakpoint::operator *() const { return m_opaque_sp; }