| //===-- 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/Core/ModuleList.h" |
| #include "lldb/Target/Target.h" |
| |
| using namespace lldb; |
| using namespace lldb_private; |
| |
| BreakpointLocationList::BreakpointLocationList() : |
| m_locations(), |
| m_address_to_location (), |
| m_mutex (Mutex::eMutexTypeRecursive) |
| { |
| } |
| |
| BreakpointLocationList::~BreakpointLocationList() |
| { |
| } |
| |
| BreakpointLocationSP |
| BreakpointLocationList::Create (Breakpoint &bp, 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_locations.size() + 1; |
| BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, bp, 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) |
| { |
| bool seen = false; |
| BreakpointLocationSP break_loc = (*pos); |
| const Section *section = break_loc->GetAddress().GetSection(); |
| if (section) |
| { |
| if (section->GetModule() == module) |
| { |
| if (!seen) |
| { |
| seen = true; |
| 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()) |
| { |
| addr_map::const_iterator pos = m_address_to_location.find (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: ", (int)sizeof(void*) * 2, this); |
| //s->Indent(); |
| Mutex::Locker locker (m_mutex); |
| s->Printf("BreakpointLocationList with %zu BreakpointLocations:\n", 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 (uint32_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 (uint32_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); |
| } |
| } |
| |