| //===-- 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), |
| m_next_id (0) |
| { |
| } |
| |
| BreakpointLocationList::~BreakpointLocationList() |
| { |
| } |
| |
| lldb::break_id_t |
| BreakpointLocationList::Add (BreakpointLocationSP &bp_loc_sp) |
| { |
| if (bp_loc_sp) |
| { |
| Mutex::Locker locker (m_mutex); |
| m_locations.push_back (bp_loc_sp); |
| m_address_to_location[bp_loc_sp->GetAddress()] = bp_loc_sp; |
| return bp_loc_sp->GetID(); |
| } |
| return LLDB_INVALID_BREAK_ID; |
| } |
| |
| 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 (Address &addr) |
| { |
| BreakpointLocationSP bp_loc_sp = FindByAddress (addr); |
| if (bp_loc_sp) |
| { |
| return bp_loc_sp->GetID(); |
| } |
| return LLDB_INVALID_BREAK_ID; |
| } |
| |
| bool |
| BreakpointLocationList::Remove (lldb::break_id_t break_id) |
| { |
| Mutex::Locker locker (m_mutex); |
| collection::iterator pos = GetIDIterator(break_id); // Predicate |
| if (pos != m_locations.end()) |
| { |
| m_address_to_location.erase ((*pos)->GetAddress()); |
| m_locations.erase(pos); |
| return true; |
| } |
| return false; |
| } |
| |
| |
| class BreakpointLocationIDMatches |
| { |
| public: |
| BreakpointLocationIDMatches (lldb::break_id_t break_id) : |
| m_break_id(break_id) |
| { |
| } |
| |
| bool operator() (const BreakpointLocationSP &bp_loc_sp) const |
| { |
| return m_break_id == bp_loc_sp->GetID(); |
| } |
| |
| private: |
| const lldb::break_id_t m_break_id; |
| }; |
| |
| class BreakpointLocationAddressMatches |
| { |
| public: |
| BreakpointLocationAddressMatches (Address& addr) : |
| m_addr(addr) |
| { |
| } |
| |
| bool operator() (const BreakpointLocationSP& bp_loc_sp) const |
| { |
| return Address::CompareFileAddress(m_addr, bp_loc_sp->GetAddress()) == 0; |
| } |
| |
| private: |
| const Address &m_addr; |
| }; |
| |
| BreakpointLocationList::collection::iterator |
| BreakpointLocationList::GetIDIterator (lldb::break_id_t break_id) |
| { |
| Mutex::Locker locker (m_mutex); |
| return std::find_if (m_locations.begin(), |
| m_locations.end(), |
| BreakpointLocationIDMatches(break_id)); |
| } |
| |
| BreakpointLocationList::collection::const_iterator |
| BreakpointLocationList::GetIDConstIterator (lldb::break_id_t break_id) const |
| { |
| Mutex::Locker locker (m_mutex); |
| return std::find_if (m_locations.begin(), |
| m_locations.end(), |
| BreakpointLocationIDMatches(break_id)); |
| } |
| |
| BreakpointLocationSP |
| BreakpointLocationList::FindByID (lldb::break_id_t break_id) |
| { |
| Mutex::Locker locker (m_mutex); |
| BreakpointLocationSP stop_sp; |
| collection::iterator pos = GetIDIterator(break_id); |
| if (pos != m_locations.end()) |
| stop_sp = *pos; |
| |
| return stop_sp; |
| } |
| |
| const BreakpointLocationSP |
| BreakpointLocationList::FindByID (lldb::break_id_t break_id) const |
| { |
| Mutex::Locker locker (m_mutex); |
| BreakpointLocationSP stop_sp; |
| collection::const_iterator pos = GetIDConstIterator(break_id); |
| if (pos != m_locations.end()) |
| stop_sp = *pos; |
| |
| return stop_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 (Address &addr) const |
| { |
| Mutex::Locker locker (m_mutex); |
| BreakpointLocationSP stop_sp; |
| if (!m_locations.empty()) |
| { |
| addr_map::const_iterator pos = m_address_to_location.find (addr); |
| if (pos != m_address_to_location.end()) |
| stop_sp = pos->second; |
| } |
| |
| return stop_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 stop_sp; |
| if (i < m_locations.size()) |
| stop_sp = m_locations[i]; |
| |
| return stop_sp; |
| } |
| |
| const BreakpointLocationSP |
| BreakpointLocationList::GetByIndex (uint32_t i) const |
| { |
| Mutex::Locker locker (m_mutex); |
| BreakpointLocationSP stop_sp; |
| if (i < m_locations.size()) |
| stop_sp = m_locations[i]; |
| |
| return stop_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) |
| (*pos)->ResolveBreakpointSite(); |
| } |
| |
| 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; |
| } |
| |
| break_id_t |
| BreakpointLocationList::GetNextID() |
| { |
| return ++m_next_id; |
| } |
| |
| 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); |
| } |
| } |
| |