diff options
Diffstat (limited to 'source/Breakpoint/BreakpointLocationList.cpp')
-rw-r--r-- | source/Breakpoint/BreakpointLocationList.cpp | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/source/Breakpoint/BreakpointLocationList.cpp b/source/Breakpoint/BreakpointLocationList.cpp new file mode 100644 index 0000000..22a4ff0 --- /dev/null +++ b/source/Breakpoint/BreakpointLocationList.cpp @@ -0,0 +1,305 @@ +//===-- BreakpointLocationList.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Breakpoint/BreakpointLocationList.h" +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Breakpoint/Breakpoint.h" +#include "lldb/Core/Section.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; + +BreakpointLocationList::BreakpointLocationList(Breakpoint &owner) : + m_owner (owner), + m_locations(), + m_address_to_location (), + m_mutex (Mutex::eMutexTypeRecursive), + m_next_id (0), + m_new_location_recorder (NULL) +{ +} + +BreakpointLocationList::~BreakpointLocationList() +{ +} + +BreakpointLocationSP +BreakpointLocationList::Create (const Address &addr) +{ + Mutex::Locker locker (m_mutex); + // The location ID is just the size of the location list + 1 + lldb::break_id_t bp_loc_id = ++m_next_id; + BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr)); + m_locations.push_back (bp_loc_sp); + m_address_to_location[addr] = bp_loc_sp; + return bp_loc_sp; +} + +bool +BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id) +{ + BreakpointLocationSP bp = FindByID (break_id); + if (bp) + { + // Let the BreakpointLocation decide if it should stop here (could not have + // reached it's target hit count yet, or it could have a callback + // that decided it shouldn't stop (shared library loads/unloads). + return bp->ShouldStop (context); + } + // We should stop here since this BreakpointLocation isn't valid anymore or it + // doesn't exist. + return true; +} + +lldb::break_id_t +BreakpointLocationList::FindIDByAddress (const Address &addr) +{ + BreakpointLocationSP bp_loc_sp = FindByAddress (addr); + if (bp_loc_sp) + { + return bp_loc_sp->GetID(); + } + return LLDB_INVALID_BREAK_ID; +} + +BreakpointLocationSP +BreakpointLocationList::FindByID (lldb::break_id_t break_id) const +{ + BreakpointLocationSP bp_loc_sp; + Mutex::Locker locker (m_mutex); + // We never remove a breakpoint locations, so the ID can be translated into + // the location index by subtracting 1 + uint32_t idx = break_id - 1; + if (idx <= m_locations.size()) + { + bp_loc_sp = m_locations[idx]; + } + return bp_loc_sp; +} + +size_t +BreakpointLocationList::FindInModule (Module *module, + BreakpointLocationCollection& bp_loc_list) +{ + Mutex::Locker locker (m_mutex); + const size_t orig_size = bp_loc_list.GetSize(); + collection::iterator pos, end = m_locations.end(); + + for (pos = m_locations.begin(); pos != end; ++pos) + { + BreakpointLocationSP break_loc = (*pos); + SectionSP section_sp (break_loc->GetAddress().GetSection()); + if (section_sp && section_sp->GetModule().get() == module) + { + bp_loc_list.Add (break_loc); + } + } + return bp_loc_list.GetSize() - orig_size; +} + +const BreakpointLocationSP +BreakpointLocationList::FindByAddress (const Address &addr) const +{ + Mutex::Locker locker (m_mutex); + BreakpointLocationSP bp_loc_sp; + if (!m_locations.empty()) + { + Address so_addr; + + if (addr.IsSectionOffset()) + { + so_addr = addr; + } + else + { + // Try and resolve as a load address if possible. + m_owner.GetTarget().GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), so_addr); + if (!so_addr.IsValid()) + { + // The address didn't resolve, so just set to passed in addr. + so_addr = addr; + } + } + + addr_map::const_iterator pos = m_address_to_location.find (so_addr); + if (pos != m_address_to_location.end()) + bp_loc_sp = pos->second; + } + + return bp_loc_sp; +} + +void +BreakpointLocationList::Dump (Stream *s) const +{ + s->Printf("%p: ", this); + //s->Indent(); + Mutex::Locker locker (m_mutex); + s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n", (uint64_t)m_locations.size()); + s->IndentMore(); + collection::const_iterator pos, end = m_locations.end(); + for (pos = m_locations.begin(); pos != end; ++pos) + (*pos).get()->Dump(s); + s->IndentLess(); +} + + +BreakpointLocationSP +BreakpointLocationList::GetByIndex (size_t i) +{ + Mutex::Locker locker (m_mutex); + BreakpointLocationSP bp_loc_sp; + if (i < m_locations.size()) + bp_loc_sp = m_locations[i]; + + return bp_loc_sp; +} + +const BreakpointLocationSP +BreakpointLocationList::GetByIndex (size_t i) const +{ + Mutex::Locker locker (m_mutex); + BreakpointLocationSP bp_loc_sp; + if (i < m_locations.size()) + bp_loc_sp = m_locations[i]; + + return bp_loc_sp; +} + +void +BreakpointLocationList::ClearAllBreakpointSites () +{ + Mutex::Locker locker (m_mutex); + collection::iterator pos, end = m_locations.end(); + for (pos = m_locations.begin(); pos != end; ++pos) + (*pos)->ClearBreakpointSite(); +} + +void +BreakpointLocationList::ResolveAllBreakpointSites () +{ + Mutex::Locker locker (m_mutex); + collection::iterator pos, end = m_locations.end(); + + for (pos = m_locations.begin(); pos != end; ++pos) + { + if ((*pos)->IsEnabled()) + (*pos)->ResolveBreakpointSite(); + } +} + +uint32_t +BreakpointLocationList::GetHitCount () const +{ + uint32_t hit_count = 0; + Mutex::Locker locker (m_mutex); + collection::const_iterator pos, end = m_locations.end(); + for (pos = m_locations.begin(); pos != end; ++pos) + hit_count += (*pos)->GetHitCount(); + return hit_count; +} + +size_t +BreakpointLocationList::GetNumResolvedLocations() const +{ + Mutex::Locker locker (m_mutex); + size_t resolve_count = 0; + collection::const_iterator pos, end = m_locations.end(); + for (pos = m_locations.begin(); pos != end; ++pos) + { + if ((*pos)->IsResolved()) + ++resolve_count; + } + return resolve_count; +} + +void +BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level) +{ + Mutex::Locker locker (m_mutex); + collection::iterator pos, end = m_locations.end(); + + for (pos = m_locations.begin(); pos != end; ++pos) + { + s->Printf(" "); + (*pos)->GetDescription(s, level); + } +} + +BreakpointLocationSP +BreakpointLocationList::AddLocation (const Address &addr, bool *new_location) +{ + Mutex::Locker locker (m_mutex); + + if (new_location) + *new_location = false; + BreakpointLocationSP bp_loc_sp (FindByAddress(addr)); + if (!bp_loc_sp) + { + bp_loc_sp = Create (addr); + if (bp_loc_sp) + { + bp_loc_sp->ResolveBreakpointSite(); + + if (new_location) + *new_location = true; + if(m_new_location_recorder) + { + m_new_location_recorder->Add(bp_loc_sp); + } + } + } + return bp_loc_sp; +} + +bool +BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp) +{ + if (bp_loc_sp) + { + Mutex::Locker locker (m_mutex); + + m_address_to_location.erase (bp_loc_sp->GetAddress()); + + collection::iterator pos, end = m_locations.end(); + for (pos = m_locations.begin(); pos != end; ++pos) + { + if ((*pos).get() == bp_loc_sp.get()) + { + m_locations.erase (pos); + return true; + } + } + } + return false; +} + + + +void +BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations) +{ + Mutex::Locker locker (m_mutex); + assert (m_new_location_recorder == NULL); + m_new_location_recorder = &new_locations; +} + +void +BreakpointLocationList::StopRecordingNewLocations () +{ + Mutex::Locker locker (m_mutex); + m_new_location_recorder = NULL; +} + |