[Lldb-commits] [lldb] r217551 - Rework how resetting breakpoints in changed modules works. Try to match up old

Jim Ingham jingham at apple.com
Wed Sep 10 14:40:48 PDT 2014


Author: jingham
Date: Wed Sep 10 16:40:47 2014
New Revision: 217551

URL: http://llvm.org/viewvc/llvm-project?rev=217551&view=rev
Log:
Rework how resetting breakpoints in changed modules works.  Try to match up old
locations with new ones if possible.

Next up some test cases...

Modified:
    lldb/trunk/include/lldb/Breakpoint/Breakpoint.h
    lldb/trunk/include/lldb/Breakpoint/BreakpointLocation.h
    lldb/trunk/include/lldb/Breakpoint/BreakpointLocationCollection.h
    lldb/trunk/include/lldb/Breakpoint/BreakpointLocationList.h
    lldb/trunk/include/lldb/Core/ModuleList.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/Breakpoint/Breakpoint.cpp
    lldb/trunk/source/Breakpoint/BreakpointLocation.cpp
    lldb/trunk/source/Breakpoint/BreakpointLocationList.cpp

Modified: lldb/trunk/include/lldb/Breakpoint/Breakpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/Breakpoint.h?rev=217551&r1=217550&r2=217551&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/Breakpoint.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/Breakpoint.h Wed Sep 10 16:40:47 2014
@@ -203,14 +203,29 @@ public:
     /// Tell this breakpoint to scan a given module list and resolve any
     /// new locations that match the breakpoint's specifications.
     ///
-    /// @param[in] changed_modules
+    /// @param[in] module_list
     ///    The list of modules to look in for new locations.
+    ///
+    /// @param[in]  send_event
+    ///     If \b true, send a breakpoint location added event for non-internal breakpoints.
     //------------------------------------------------------------------
     void
-    ResolveBreakpointInModules (ModuleList &changed_modules);
-
+    ResolveBreakpointInModules (ModuleList &module_list, bool send_event = true);
 
     //------------------------------------------------------------------
+    /// Tell this breakpoint to scan a given module list and resolve any
+    /// new locations that match the breakpoint's specifications.
+    ///
+    /// @param[in] changed_modules
+    ///    The list of modules to look in for new locations.
+    ///
+    /// @param[in]  new_locations
+    ///     Fills new_locations with the new locations that were made.
+    //------------------------------------------------------------------
+    void
+    ResolveBreakpointInModules (ModuleList &module_list, BreakpointLocationCollection &new_locations);
+    
+    //------------------------------------------------------------------
     /// Like ResolveBreakpointInModules, but allows for "unload" events, in
     /// which case we will remove any locations that are in modules that got
     /// unloaded.

Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointLocation.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointLocation.h?rev=217551&r1=217550&r2=217551&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/BreakpointLocation.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/BreakpointLocation.h Wed Sep 10 16:40:47 2014
@@ -52,6 +52,7 @@ class BreakpointLocation :
     public StoppointLocation
 {
 public:
+    friend class BreakpointLocationList;
 
     ~BreakpointLocation ();
 
@@ -374,6 +375,19 @@ public:
         m_is_reexported = is_reexported;
     }
     
+    //------------------------------------------------------------------
+    /// Returns whether the two breakpoint locations might represent "equivalent locations".
+    /// This is used when modules changed to determine if a Location in the old module might
+    /// be the "same as" the input location.
+    ///
+    /// @param[in] location
+    ///    The location to compare against.
+    ///
+    /// @return
+    ///     \b true or \b false as given in the description above.
+    //------------------------------------------------------------------
+    bool EquivalentToLocation(BreakpointLocation &location);
+    
 protected:
     friend class BreakpointLocationList;
     friend class Process;
@@ -396,8 +410,11 @@ protected:
 
     bool
     IgnoreCountShouldStop();
-
+    
 private:
+    void
+    SwapLocation (lldb::BreakpointLocationSP swap_from);
+
 
     //------------------------------------------------------------------
     // Constructors and Destructors

Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointLocationCollection.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointLocationCollection.h?rev=217551&r1=217550&r2=217551&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/BreakpointLocationCollection.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/BreakpointLocationCollection.h Wed Sep 10 16:40:47 2014
@@ -16,6 +16,7 @@
 // Other libraries and framework includes
 // Project includes
 #include "lldb/lldb-private.h"
+#include "lldb/Utility/Iterable.h"
 
 namespace lldb_private {
 
@@ -202,6 +203,14 @@ private:
 
     collection m_break_loc_collection;
 
+public:
+    typedef AdaptedIterable<collection, lldb::BreakpointLocationSP, vector_adapter> BreakpointLocationCollectionIterable;
+    BreakpointLocationCollectionIterable
+    BreakpointLocations()
+    {
+        return BreakpointLocationCollectionIterable(m_break_loc_collection);
+    }
+
 };
 
 } // namespace lldb_private

Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointLocationList.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointLocationList.h?rev=217551&r1=217550&r2=217551&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/BreakpointLocationList.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/BreakpointLocationList.h Wed Sep 10 16:40:47 2014
@@ -19,6 +19,7 @@
 #include "lldb/lldb-private.h"
 #include "lldb/Core/Address.h"
 #include "lldb/Host/Mutex.h"
+#include "lldb/Utility/Iterable.h"
 
 namespace lldb_private {
 
@@ -248,12 +249,18 @@ protected:
     AddLocation (const Address &addr,
                  bool resolve_indirect_symbols,
                  bool *new_location = NULL);
+    
+    void
+    SwapLocation (lldb::BreakpointLocationSP to_location_sp, lldb::BreakpointLocationSP from_location_sp);
 
     bool
     RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp);
     
     void
     RemoveInvalidLocations (const ArchSpec &arch);
+    
+    void
+    Compact();
 
     typedef std::vector<lldb::BreakpointLocationSP> collection;
     typedef std::map<lldb_private::Address,
@@ -266,6 +273,14 @@ protected:
     mutable Mutex m_mutex;
     lldb::break_id_t m_next_id;
     BreakpointLocationCollection *m_new_location_recorder;
+public:
+    typedef AdaptedIterable<collection, lldb::BreakpointLocationSP, vector_adapter> BreakpointLocationIterable;
+    BreakpointLocationIterable
+    BreakpointLocations()
+    {
+        return BreakpointLocationIterable(m_locations);
+    }
+
 };
 
 } // namespace lldb_private

Modified: lldb/trunk/include/lldb/Core/ModuleList.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ModuleList.h?rev=217551&r1=217550&r2=217551&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ModuleList.h (original)
+++ lldb/trunk/include/lldb/Core/ModuleList.h Wed Sep 10 16:40:47 2014
@@ -586,6 +586,13 @@ public:
         return ModuleIterable(m_modules, GetMutex());
     }
     
+    typedef AdaptedIterable<collection, lldb::ModuleSP, vector_adapter> ModuleIterableNoLocking;
+    ModuleIterableNoLocking
+    ModulesNoLocking ()
+    {
+        return ModuleIterableNoLocking(m_modules);
+    }
+    
 };
 
 } // namespace lldb_private

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=217551&r1=217550&r2=217551&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Wed Sep 10 16:40:47 2014
@@ -613,6 +613,7 @@
 		4C3ADCD61810D88B00357218 /* BreakpointResolverFileRegex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CAA56141422D986001FFA01 /* BreakpointResolverFileRegex.cpp */; };
 		4C6649A014EEE7F100B0316F /* StreamCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C66499F14EEE7F100B0316F /* StreamCallback.h */; };
 		4C6649A314EEE81000B0316F /* StreamCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6649A214EEE81000B0316F /* StreamCallback.cpp */; };
+		4C73152219B7D71700F865A4 /* Iterable.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C73152119B7D71700F865A4 /* Iterable.h */; };
 		4CABA9E0134A8BCD00539BDD /* ValueObjectMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CABA9DF134A8BCD00539BDD /* ValueObjectMemory.cpp */; };
 		4CCA644D13B40B82003BDF98 /* ItaniumABILanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA643D13B40B82003BDF98 /* ItaniumABILanguageRuntime.cpp */; };
 		4CCA645013B40B82003BDF98 /* AppleObjCRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644213B40B82003BDF98 /* AppleObjCRuntime.cpp */; };
@@ -1892,6 +1893,7 @@
 		4C626533130F1B0A00C889F6 /* StreamTee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StreamTee.h; path = include/lldb/Core/StreamTee.h; sourceTree = "<group>"; };
 		4C66499F14EEE7F100B0316F /* StreamCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StreamCallback.h; path = include/lldb/Core/StreamCallback.h; sourceTree = "<group>"; };
 		4C6649A214EEE81000B0316F /* StreamCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StreamCallback.cpp; path = source/Core/StreamCallback.cpp; sourceTree = "<group>"; };
+		4C73152119B7D71700F865A4 /* Iterable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Iterable.h; path = include/lldb/Utility/Iterable.h; sourceTree = "<group>"; };
 		4C7CF7E31295E10E00B4FBB5 /* ThreadPlanCallUserExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanCallUserExpression.h; path = include/lldb/Target/ThreadPlanCallUserExpression.h; sourceTree = "<group>"; };
 		4C7CF7E51295E12B00B4FBB5 /* ThreadPlanCallUserExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanCallUserExpression.cpp; path = source/Target/ThreadPlanCallUserExpression.cpp; sourceTree = "<group>"; };
 		4C98D3DA118FB96F00E575D0 /* ClangFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangFunction.cpp; path = source/Expression/ClangFunction.cpp; sourceTree = "<group>"; };
@@ -2952,6 +2954,7 @@
 				264A12FE137252C700875C42 /* ARM64_DWARF_Registers.cpp */,
 				26F996A8119B79C300412154 /* ARM_GCC_Registers.h */,
 				264723A511FA076E00DE380C /* CleanUp.h */,
+				4C73152119B7D71700F865A4 /* Iterable.h */,
 				26D1804416CEE12500EDFB5B /* KQueue.h */,
 				26D1803C16CEBFD300EDFB5B /* KQueue.cpp */,
 				94031A9F13CF5B3D00DCFF3C /* PriorityPointerPair.h */,
@@ -4483,6 +4486,7 @@
 				2697A39515E404BA003E682C /* OptionValueArch.h in Headers */,
 				26474CBF18D0CB2D0073DEBA /* RegisterContextMach_i386.h in Headers */,
 				26474CC118D0CB2D0073DEBA /* RegisterContextMach_x86_64.h in Headers */,
+				4C73152219B7D71700F865A4 /* Iterable.h in Headers */,
 				2698699D15E6CBD0002415FF /* OperatingSystemPython.h in Headers */,
 				232CB618191E00CD00EF39FC /* NativeBreakpointList.h in Headers */,
 				260D9B2715EC369500960137 /* ModuleSpec.h in Headers */,

Modified: lldb/trunk/source/Breakpoint/Breakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/Breakpoint.cpp?rev=217551&r1=217550&r2=217551&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/Breakpoint.cpp (original)
+++ lldb/trunk/source/Breakpoint/Breakpoint.cpp Wed Sep 10 16:40:47 2014
@@ -20,11 +20,14 @@
 #include "lldb/Breakpoint/BreakpointResolver.h"
 #include "lldb/Breakpoint/BreakpointResolverFileLine.h"
 #include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleList.h"
 #include "lldb/Core/SearchFilter.h"
 #include "lldb/Core/Section.h"
 #include "lldb/Core/Stream.h"
 #include "lldb/Core/StreamString.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Target/ThreadSpec.h"
@@ -349,10 +352,41 @@ Breakpoint::ResolveBreakpoint ()
 }
 
 void
-Breakpoint::ResolveBreakpointInModules (ModuleList &module_list)
+Breakpoint::ResolveBreakpointInModules (ModuleList &module_list, BreakpointLocationCollection &new_locations)
+{
+    m_locations.StartRecordingNewLocations(new_locations);
+    
+    m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
+
+    m_locations.StopRecordingNewLocations();
+}
+
+void
+Breakpoint::ResolveBreakpointInModules (ModuleList &module_list, bool send_event)
 {
     if (m_resolver_sp)
-        m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
+    {
+        // If this is not an internal breakpoint, set up to record the new locations, then dispatch
+        // an event with the new locations.
+        if (!IsInternal() && send_event)
+        {
+            BreakpointEventData *new_locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsAdded, 
+                                                                                shared_from_this());
+            
+            ResolveBreakpointInModules (module_list, new_locations_event->GetBreakpointLocationCollection());
+
+            if (new_locations_event->GetBreakpointLocationCollection().GetSize() != 0)
+            {
+                SendBreakpointChangedEvent (new_locations_event);
+            }
+            else
+                delete new_locations_event;
+        }
+        else
+        {
+            m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
+        }
+    }
 }
 
 void
@@ -368,6 +402,11 @@ Breakpoint::ClearAllBreakpointSites ()
 void
 Breakpoint::ModulesChanged (ModuleList &module_list, bool load, bool delete_locations)
 {
+    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+    if (log)
+        log->Printf ("Breakpoint::ModulesChanged: num_modules: %zu load: %i delete_locations: %i\n",
+                     module_list.GetSize(), load, delete_locations);
+    
     Mutex::Locker modules_mutex(module_list.GetMutex());
     if (load)
     {
@@ -383,32 +422,27 @@ Breakpoint::ModulesChanged (ModuleList &
                                  // them after the locations pass.  Have to do it this way because
                                  // resolving breakpoints will add new locations potentially.
 
-        const size_t num_locs = m_locations.GetSize();
-        size_t num_modules = module_list.GetSize();
-        for (size_t i = 0; i < num_modules; i++)
+        for (ModuleSP module_sp : module_list.ModulesNoLocking())
         {
             bool seen = false;
-            ModuleSP module_sp (module_list.GetModuleAtIndexUnlocked (i));
             if (!m_filter_sp->ModulePasses (module_sp))
                 continue;
 
-            for (size_t loc_idx = 0; loc_idx < num_locs; loc_idx++)
+            for (BreakpointLocationSP break_loc_sp : m_locations.BreakpointLocations())
             {
-                BreakpointLocationSP break_loc = m_locations.GetByIndex(loc_idx);
-                if (!break_loc->IsEnabled())
+                if (!break_loc_sp->IsEnabled())
                     continue;
-                SectionSP section_sp (break_loc->GetAddress().GetSection());
+                SectionSP section_sp (break_loc_sp->GetAddress().GetSection());
                 if (!section_sp || section_sp->GetModule() == module_sp)
                 {
                     if (!seen)
                         seen = true;
 
-                    if (!break_loc->ResolveBreakpointSite())
+                    if (!break_loc_sp->ResolveBreakpointSite())
                     {
-                        Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
                         if (log)
                             log->Printf ("Warning: could not set breakpoint site for breakpoint location %d of breakpoint %d.\n",
-                                         break_loc->GetID(), GetID());
+                                         break_loc_sp->GetID(), GetID());
                     }
                 }
             }
@@ -420,28 +454,7 @@ Breakpoint::ModulesChanged (ModuleList &
         
         if (new_modules.GetSize() > 0)
         {
-            // If this is not an internal breakpoint, set up to record the new locations, then dispatch
-            // an event with the new locations.
-            if (!IsInternal())
-            {
-                BreakpointEventData *new_locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsAdded, 
-                                                                                    shared_from_this());
-                
-                m_locations.StartRecordingNewLocations(new_locations_event->GetBreakpointLocationCollection());
-                
-                ResolveBreakpointInModules(new_modules);
-
-                m_locations.StopRecordingNewLocations();
-                if (new_locations_event->GetBreakpointLocationCollection().GetSize() != 0)
-                {
-                    SendBreakpointChangedEvent (new_locations_event);
-                }
-                else
-                    delete new_locations_event;
-            }
-            else
-                ResolveBreakpointInModules(new_modules);
-            
+            ResolveBreakpointInModules(new_modules);
         }
     }
     else
@@ -498,21 +511,251 @@ Breakpoint::ModulesChanged (ModuleList &
     }
 }
 
+namespace
+{
+static bool
+SymbolContextsMightBeEquivalent(SymbolContext &old_sc, SymbolContext &new_sc)
+{
+    bool equivalent_scs = false;
+    
+    if (old_sc.module_sp.get() == new_sc.module_sp.get())
+    {
+        // If these come from the same module, we can directly compare the pointers:
+        if (old_sc.comp_unit && new_sc.comp_unit
+            && (old_sc.comp_unit == new_sc.comp_unit))
+        {
+            if (old_sc.function && new_sc.function
+                && (old_sc.function == new_sc.function))
+            {
+                equivalent_scs = true;
+            }
+        }
+        else if (old_sc.symbol && new_sc.symbol
+                && (old_sc.symbol == new_sc.symbol))
+        {
+            equivalent_scs = true;
+        }
+    }
+    else
+    {
+        // Otherwise we will compare by name...
+        if (old_sc.comp_unit && new_sc.comp_unit)
+        {
+            if (FileSpec::Equal(*old_sc.comp_unit, *new_sc.comp_unit, true))
+            {
+                // Now check the functions:
+                if (old_sc.function && new_sc.function
+                    && (old_sc.function->GetName() == new_sc.function->GetName()))
+                {
+                    equivalent_scs = true;
+                }
+            }
+        }
+        else if (old_sc.symbol && new_sc.symbol)
+        {
+            if (Mangled::Compare(old_sc.symbol->GetMangled(), new_sc.symbol->GetMangled()) == 0)
+            {
+                equivalent_scs = true;
+            }
+        }
+    }
+    return equivalent_scs;
+}
+}
+
 void
 Breakpoint::ModuleReplaced (ModuleSP old_module_sp, ModuleSP new_module_sp)
 {
-    ModuleList temp_list;
-    temp_list.Append (new_module_sp);
-    ModulesChanged (temp_list, true);
-
-    // TO DO: For now I'm just adding locations for the new module and removing the
-    // breakpoint locations that were in the old module.
-    // We should really go find the ones that are in the new module & if we can determine that they are "equivalent"
-    // carry over the options from the old location to the new.
-
-    temp_list.Clear();
-    temp_list.Append (old_module_sp);
-    ModulesChanged (temp_list, false, true);
+    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+    if (log)
+        log->Printf ("Breakpoint::ModulesReplaced for %s\n",
+                     old_module_sp->GetSpecificationDescription().c_str());
+    // First find all the locations that are in the old module
+    
+    BreakpointLocationCollection old_break_locs;
+    for (BreakpointLocationSP break_loc_sp : m_locations.BreakpointLocations())
+    {
+        SectionSP section_sp = break_loc_sp->GetAddress().GetSection();
+        if (section_sp && section_sp->GetModule() == old_module_sp)
+        {
+            old_break_locs.Add(break_loc_sp);
+        }
+    }
+    
+    size_t num_old_locations = old_break_locs.GetSize();
+    
+    if (num_old_locations == 0)
+    {
+        // There were no locations in the old module, so we just need to check if there were any in the new module.
+        ModuleList temp_list;
+        temp_list.Append (new_module_sp);
+        ResolveBreakpointInModules(temp_list);
+    }
+    else
+    {
+        // First search the new module for locations.
+        // Then compare this with the old list, copy over locations that "look the same"
+        // Then delete the old locations.
+        // Finally remember to post the creation event.
+        //
+        // Two locations are the same if they have the same comp unit & function (by name) and there are the same number
+        // of locations in the old function as in the new one.
+        
+        ModuleList temp_list;
+        temp_list.Append (new_module_sp);
+        BreakpointLocationCollection new_break_locs;
+        ResolveBreakpointInModules(temp_list, new_break_locs);
+        BreakpointLocationCollection locations_to_remove;
+        BreakpointLocationCollection locations_to_announce;
+        
+        size_t num_new_locations = new_break_locs.GetSize();
+        
+        if (num_new_locations > 0)
+        {
+            // Break out the case of one location -> one location since that's the most common one, and there's no need
+            // to build up the structures needed for the merge in that case.
+            if (num_new_locations == 1 && num_old_locations == 1)
+            {
+                bool equivalent_locations = false;
+                SymbolContext old_sc, new_sc;
+                // The only way the old and new location can be equivalent is if they have the same amount of information:
+                BreakpointLocationSP old_loc_sp = old_break_locs.GetByIndex(0);
+                BreakpointLocationSP new_loc_sp = new_break_locs.GetByIndex(0);
+                
+                if (old_loc_sp->GetAddress().CalculateSymbolContext(&old_sc)
+                    == new_loc_sp->GetAddress().CalculateSymbolContext(&new_sc))
+                {
+                    equivalent_locations = SymbolContextsMightBeEquivalent(old_sc, new_sc);
+                }
+                
+                if (equivalent_locations)
+                {
+                    m_locations.SwapLocation (old_loc_sp, new_loc_sp);
+                }
+                else
+                {
+                    locations_to_remove.Add(old_loc_sp);
+                    locations_to_announce.Add(new_loc_sp);
+                }
+            }
+            else
+            {
+                //We don't want to have to keep computing the SymbolContexts for these addresses over and over,
+                // so lets get them up front:
+                
+                typedef std::map<lldb::break_id_t, SymbolContext> IDToSCMap;
+                IDToSCMap old_sc_map;
+                for (size_t idx = 0; idx < num_old_locations; idx++)
+                {
+                    SymbolContext sc;
+                    BreakpointLocationSP bp_loc_sp = old_break_locs.GetByIndex(idx);
+                    lldb::break_id_t loc_id = bp_loc_sp->GetID();
+                    bp_loc_sp->GetAddress().CalculateSymbolContext(&old_sc_map[loc_id]);
+                }
+                
+                std::map<lldb::break_id_t, SymbolContext> new_sc_map;
+                for (size_t idx = 0; idx < num_new_locations; idx++)
+                {
+                    SymbolContext sc;
+                    BreakpointLocationSP bp_loc_sp = new_break_locs.GetByIndex(idx);
+                    lldb::break_id_t loc_id = bp_loc_sp->GetID();
+                    bp_loc_sp->GetAddress().CalculateSymbolContext(&new_sc_map[loc_id]);
+                }
+                // Take an element from the old Symbol Contexts
+                while (old_sc_map.size() > 0)
+                {
+                    lldb::break_id_t old_id = old_sc_map.begin()->first;
+                    SymbolContext &old_sc = old_sc_map.begin()->second;
+                    
+                    // Count the number of entries equivalent to this SC for the old list:
+                    std::vector<lldb::break_id_t> old_id_vec;
+                    old_id_vec.push_back(old_id);
+                    
+                    IDToSCMap::iterator tmp_iter;
+                    for (tmp_iter = ++old_sc_map.begin(); tmp_iter != old_sc_map.end(); tmp_iter++)
+                    {
+                        if (SymbolContextsMightBeEquivalent (old_sc, tmp_iter->second))
+                            old_id_vec.push_back (tmp_iter->first);
+                    }
+                    
+                    // Now find all the equivalent locations in the new list.
+                    std::vector<lldb::break_id_t> new_id_vec;
+                    for (tmp_iter = new_sc_map.begin(); tmp_iter != new_sc_map.end(); tmp_iter++)
+                    {
+                        if (SymbolContextsMightBeEquivalent (old_sc, tmp_iter->second))
+                            new_id_vec.push_back(tmp_iter->first);
+                    }
+                    
+                    // Alright, if we have the same number of potentially equivalent locations in the old
+                    // and new modules, we'll just map them one to one in ascending ID order (assuming the
+                    // resolver's order would match the equivalent ones.
+                    // Otherwise, we'll dump all the old ones, and just take the new ones, erasing the elements
+                    // from both maps as we go.
+                    
+                    if (old_id_vec.size() == new_id_vec.size())
+                    {
+                        sort(old_id_vec.begin(), old_id_vec.end());
+                        sort(new_id_vec.begin(), new_id_vec.end());
+                        size_t num_elements = old_id_vec.size();
+                        for (size_t idx = 0; idx < num_elements; idx++)
+                        {
+                            BreakpointLocationSP old_loc_sp = old_break_locs.FindByIDPair(GetID(), old_id_vec[idx]);
+                            BreakpointLocationSP new_loc_sp = new_break_locs.FindByIDPair(GetID(), new_id_vec[idx]);
+                            m_locations.SwapLocation(old_loc_sp, new_loc_sp);
+                            old_sc_map.erase(old_id_vec[idx]);
+                            new_sc_map.erase(new_id_vec[idx]);
+                        }
+                    }
+                    else
+                    {
+                        for (lldb::break_id_t old_id : old_id_vec)
+                        {
+                            locations_to_remove.Add(old_break_locs.FindByIDPair(GetID(), old_id));
+                            old_sc_map.erase(old_id);
+                        }
+                        for (lldb::break_id_t new_id : new_id_vec)
+                        {
+                            locations_to_announce.Add(new_break_locs.FindByIDPair(GetID(), new_id));
+                            new_sc_map.erase(new_id);
+                        }
+                    }
+                }
+            }
+        }
+        
+        // Now remove the remaining old locations, and cons up a removed locations event.
+        // Note, we don't put the new locations that were swapped with an old location on the locations_to_remove
+        // list, so we don't need to worry about telling the world about removing a location we didn't tell them
+        // about adding.
+        
+        BreakpointEventData *locations_event;
+        if (!IsInternal())
+            locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsRemoved,
+                                                               shared_from_this());
+        else
+            locations_event = NULL;
+
+        for (BreakpointLocationSP loc_sp : locations_to_remove.BreakpointLocations())
+        {
+            m_locations.RemoveLocation(loc_sp);
+            if (locations_event)
+                locations_event->GetBreakpointLocationCollection().Add(loc_sp);
+        }
+        SendBreakpointChangedEvent (locations_event);
+
+        // And announce the new ones.
+        
+        if (!IsInternal())
+        {
+            locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsAdded,
+                                                               shared_from_this());
+            for (BreakpointLocationSP loc_sp : locations_to_announce.BreakpointLocations())
+                    locations_event->GetBreakpointLocationCollection().Add(loc_sp);
+
+            SendBreakpointChangedEvent (locations_event);
+        }
+        m_locations.Compact();
+    }
 }
 
 void

Modified: lldb/trunk/source/Breakpoint/BreakpointLocation.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointLocation.cpp?rev=217551&r1=217550&r2=217551&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointLocation.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointLocation.cpp Wed Sep 10 16:40:47 2014
@@ -717,4 +717,13 @@ BreakpointLocation::SendBreakpointLocati
         m_owner.GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data);
     }
 }
-    
+
+void
+BreakpointLocation::SwapLocation (BreakpointLocationSP swap_from)
+{
+    m_address = swap_from->m_address;
+    m_should_resolve_indirect_functions = swap_from->m_should_resolve_indirect_functions;
+    m_is_reexported = swap_from->m_is_reexported;
+    m_is_indirect = swap_from->m_is_indirect;
+    m_user_expression_sp.reset();
+}

Modified: lldb/trunk/source/Breakpoint/BreakpointLocationList.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointLocationList.cpp?rev=217551&r1=217550&r2=217551&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointLocationList.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointLocationList.cpp Wed Sep 10 16:40:47 2014
@@ -272,6 +272,20 @@ BreakpointLocationList::AddLocation (con
     return bp_loc_sp;
 }
 
+void
+BreakpointLocationList::SwapLocation (BreakpointLocationSP to_location_sp, BreakpointLocationSP from_location_sp)
+{
+    if (!from_location_sp || !to_location_sp)
+        return;
+    
+    m_address_to_location.erase(to_location_sp->GetAddress());
+    to_location_sp->SwapLocation(from_location_sp);
+    RemoveLocation(from_location_sp);
+    m_address_to_location[to_location_sp->GetAddress()] = to_location_sp;
+    to_location_sp->ResolveBreakpointSite();
+}
+
+
 bool
 BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp)
 {
@@ -345,3 +359,16 @@ BreakpointLocationList::StopRecordingNew
     m_new_location_recorder = NULL;
 }
 
+void
+BreakpointLocationList::Compact()
+{
+    lldb::break_id_t highest_id = 0;
+    
+    for (BreakpointLocationSP loc_sp : m_locations)
+    {
+        lldb::break_id_t cur_id = loc_sp->GetID();
+        if (cur_id > highest_id)
+            highest_id = cur_id;
+    }
+    m_next_id = highest_id;
+}





More information about the lldb-commits mailing list