Home | History | Annotate | Download | only in Breakpoint
      1 //===-- BreakpointLocationList.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 
     11 // C Includes
     12 // C++ Includes
     13 // Other libraries and framework includes
     14 // Project includes
     15 #include "lldb/Breakpoint/BreakpointLocationList.h"
     16 #include "lldb/Breakpoint/BreakpointLocation.h"
     17 #include "lldb/Breakpoint/Breakpoint.h"
     18 #include "lldb/Core/Section.h"
     19 #include "lldb/Target/Target.h"
     20 
     21 using namespace lldb;
     22 using namespace lldb_private;
     23 
     24 BreakpointLocationList::BreakpointLocationList(Breakpoint &owner) :
     25     m_owner (owner),
     26     m_locations(),
     27     m_address_to_location (),
     28     m_mutex (Mutex::eMutexTypeRecursive),
     29     m_next_id (0),
     30     m_new_location_recorder (NULL)
     31 {
     32 }
     33 
     34 BreakpointLocationList::~BreakpointLocationList()
     35 {
     36 }
     37 
     38 BreakpointLocationSP
     39 BreakpointLocationList::Create (const Address &addr)
     40 {
     41     Mutex::Locker locker (m_mutex);
     42     // The location ID is just the size of the location list + 1
     43     lldb::break_id_t bp_loc_id = ++m_next_id;
     44     BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr));
     45     m_locations.push_back (bp_loc_sp);
     46     m_address_to_location[addr] = bp_loc_sp;
     47     return bp_loc_sp;
     48 }
     49 
     50 bool
     51 BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id)
     52 {
     53     BreakpointLocationSP bp = FindByID (break_id);
     54     if (bp)
     55     {
     56         // Let the BreakpointLocation decide if it should stop here (could not have
     57         // reached it's target hit count yet, or it could have a callback
     58         // that decided it shouldn't stop (shared library loads/unloads).
     59         return bp->ShouldStop (context);
     60     }
     61     // We should stop here since this BreakpointLocation isn't valid anymore or it
     62     // doesn't exist.
     63     return true;
     64 }
     65 
     66 lldb::break_id_t
     67 BreakpointLocationList::FindIDByAddress (const Address &addr)
     68 {
     69     BreakpointLocationSP bp_loc_sp = FindByAddress (addr);
     70     if (bp_loc_sp)
     71     {
     72         return bp_loc_sp->GetID();
     73     }
     74     return LLDB_INVALID_BREAK_ID;
     75 }
     76 
     77 BreakpointLocationSP
     78 BreakpointLocationList::FindByID (lldb::break_id_t break_id) const
     79 {
     80     BreakpointLocationSP bp_loc_sp;
     81     Mutex::Locker locker (m_mutex);
     82     // We never remove a breakpoint locations, so the ID can be translated into
     83     // the location index by subtracting 1
     84     uint32_t idx = break_id - 1;
     85     if (idx <= m_locations.size())
     86     {
     87         bp_loc_sp = m_locations[idx];
     88     }
     89     return bp_loc_sp;
     90 }
     91 
     92 size_t
     93 BreakpointLocationList::FindInModule (Module *module,
     94                                       BreakpointLocationCollection& bp_loc_list)
     95 {
     96     Mutex::Locker locker (m_mutex);
     97     const size_t orig_size = bp_loc_list.GetSize();
     98     collection::iterator pos, end = m_locations.end();
     99 
    100     for (pos = m_locations.begin(); pos != end; ++pos)
    101     {
    102         BreakpointLocationSP break_loc = (*pos);
    103         SectionSP section_sp (break_loc->GetAddress().GetSection());
    104         if (section_sp && section_sp->GetModule().get() == module)
    105         {
    106             bp_loc_list.Add (break_loc);
    107         }
    108     }
    109     return bp_loc_list.GetSize() - orig_size;
    110 }
    111 
    112 const BreakpointLocationSP
    113 BreakpointLocationList::FindByAddress (const Address &addr) const
    114 {
    115     Mutex::Locker locker (m_mutex);
    116     BreakpointLocationSP bp_loc_sp;
    117     if (!m_locations.empty())
    118     {
    119         Address so_addr;
    120 
    121         if (addr.IsSectionOffset())
    122         {
    123             so_addr = addr;
    124         }
    125         else
    126         {
    127             // Try and resolve as a load address if possible.
    128             m_owner.GetTarget().GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), so_addr);
    129             if (!so_addr.IsValid())
    130             {
    131                 // The address didn't resolve, so just set to passed in addr.
    132                 so_addr = addr;
    133             }
    134         }
    135 
    136         addr_map::const_iterator pos = m_address_to_location.find (so_addr);
    137         if (pos != m_address_to_location.end())
    138             bp_loc_sp = pos->second;
    139     }
    140 
    141     return bp_loc_sp;
    142 }
    143 
    144 void
    145 BreakpointLocationList::Dump (Stream *s) const
    146 {
    147     s->Printf("%p: ", this);
    148     //s->Indent();
    149     Mutex::Locker locker (m_mutex);
    150     s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n", (uint64_t)m_locations.size());
    151     s->IndentMore();
    152     collection::const_iterator pos, end = m_locations.end();
    153     for (pos = m_locations.begin(); pos != end; ++pos)
    154         (*pos).get()->Dump(s);
    155     s->IndentLess();
    156 }
    157 
    158 
    159 BreakpointLocationSP
    160 BreakpointLocationList::GetByIndex (size_t i)
    161 {
    162     Mutex::Locker locker (m_mutex);
    163     BreakpointLocationSP bp_loc_sp;
    164     if (i < m_locations.size())
    165         bp_loc_sp = m_locations[i];
    166 
    167     return bp_loc_sp;
    168 }
    169 
    170 const BreakpointLocationSP
    171 BreakpointLocationList::GetByIndex (size_t i) const
    172 {
    173     Mutex::Locker locker (m_mutex);
    174     BreakpointLocationSP bp_loc_sp;
    175     if (i < m_locations.size())
    176         bp_loc_sp = m_locations[i];
    177 
    178     return bp_loc_sp;
    179 }
    180 
    181 void
    182 BreakpointLocationList::ClearAllBreakpointSites ()
    183 {
    184     Mutex::Locker locker (m_mutex);
    185     collection::iterator pos, end = m_locations.end();
    186     for (pos = m_locations.begin(); pos != end; ++pos)
    187         (*pos)->ClearBreakpointSite();
    188 }
    189 
    190 void
    191 BreakpointLocationList::ResolveAllBreakpointSites ()
    192 {
    193     Mutex::Locker locker (m_mutex);
    194     collection::iterator pos, end = m_locations.end();
    195 
    196     for (pos = m_locations.begin(); pos != end; ++pos)
    197     {
    198         if ((*pos)->IsEnabled())
    199             (*pos)->ResolveBreakpointSite();
    200     }
    201 }
    202 
    203 uint32_t
    204 BreakpointLocationList::GetHitCount () const
    205 {
    206     uint32_t hit_count = 0;
    207     Mutex::Locker locker (m_mutex);
    208     collection::const_iterator pos, end = m_locations.end();
    209     for (pos = m_locations.begin(); pos != end; ++pos)
    210         hit_count += (*pos)->GetHitCount();
    211     return hit_count;
    212 }
    213 
    214 size_t
    215 BreakpointLocationList::GetNumResolvedLocations() const
    216 {
    217     Mutex::Locker locker (m_mutex);
    218     size_t resolve_count = 0;
    219     collection::const_iterator pos, end = m_locations.end();
    220     for (pos = m_locations.begin(); pos != end; ++pos)
    221     {
    222         if ((*pos)->IsResolved())
    223             ++resolve_count;
    224     }
    225     return resolve_count;
    226 }
    227 
    228 void
    229 BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level)
    230 {
    231     Mutex::Locker locker (m_mutex);
    232     collection::iterator pos, end = m_locations.end();
    233 
    234     for (pos = m_locations.begin(); pos != end; ++pos)
    235     {
    236         s->Printf(" ");
    237         (*pos)->GetDescription(s, level);
    238     }
    239 }
    240 
    241 BreakpointLocationSP
    242 BreakpointLocationList::AddLocation (const Address &addr, bool *new_location)
    243 {
    244     Mutex::Locker locker (m_mutex);
    245 
    246     if (new_location)
    247         *new_location = false;
    248     BreakpointLocationSP bp_loc_sp (FindByAddress(addr));
    249     if (!bp_loc_sp)
    250 	{
    251 		bp_loc_sp = Create (addr);
    252 		if (bp_loc_sp)
    253 		{
    254 	    	bp_loc_sp->ResolveBreakpointSite();
    255 
    256 		    if (new_location)
    257 	    	    *new_location = true;
    258             if(m_new_location_recorder)
    259             {
    260                 m_new_location_recorder->Add(bp_loc_sp);
    261             }
    262 		}
    263 	}
    264     return bp_loc_sp;
    265 }
    266 
    267 bool
    268 BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp)
    269 {
    270     if (bp_loc_sp)
    271     {
    272         Mutex::Locker locker (m_mutex);
    273 
    274         m_address_to_location.erase (bp_loc_sp->GetAddress());
    275 
    276         collection::iterator pos, end = m_locations.end();
    277         for (pos = m_locations.begin(); pos != end; ++pos)
    278         {
    279             if ((*pos).get() == bp_loc_sp.get())
    280             {
    281                 m_locations.erase (pos);
    282                 return true;
    283             }
    284         }
    285 	}
    286     return false;
    287 }
    288 
    289 
    290 
    291 void
    292 BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations)
    293 {
    294     Mutex::Locker locker (m_mutex);
    295     assert (m_new_location_recorder == NULL);
    296     m_new_location_recorder = &new_locations;
    297 }
    298 
    299 void
    300 BreakpointLocationList::StopRecordingNewLocations ()
    301 {
    302     Mutex::Locker locker (m_mutex);
    303     m_new_location_recorder = NULL;
    304 }
    305 
    306