Send Breakpoint Changed events for all the relevant changes to breakpoints.
Also, provide and use accessors for the thread options on breakpoints so we
can control sending the appropriate events.


git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@150057 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/lldb/API/SBBreakpoint.h b/include/lldb/API/SBBreakpoint.h
index 8c49126..5338b0a 100644
--- a/include/lldb/API/SBBreakpoint.h
+++ b/include/lldb/API/SBBreakpoint.h
@@ -115,6 +115,9 @@
     bool
     GetDescription (lldb::SBStream &description);
 
+    static bool
+    EventIsBreakpointEvent (const lldb::SBEvent &event);
+    
     static lldb::BreakpointEventType
     GetBreakpointEventTypeFromEvent (const lldb::SBEvent& event);
 
@@ -123,6 +126,10 @@
     
     static lldb::SBBreakpointLocation
     GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx);
+    
+    static uint32_t
+    GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event_sp);
+
 
 private:
     friend class SBBreakpointLocation;
diff --git a/include/lldb/API/SBProcess.h b/include/lldb/API/SBProcess.h
index be169f0..84e9192 100644
--- a/include/lldb/API/SBProcess.h
+++ b/include/lldb/API/SBProcess.h
@@ -171,6 +171,9 @@
 
     static lldb::SBProcess
     GetProcessFromEvent (const lldb::SBEvent &event);
+    
+    static bool
+    EventIsProcessEvent (const lldb::SBEvent &event);
 
     lldb::SBBroadcaster
     GetBroadcaster () const;
diff --git a/include/lldb/Breakpoint/Breakpoint.h b/include/lldb/Breakpoint/Breakpoint.h
index 2c2174f..d6427df 100644
--- a/include/lldb/Breakpoint/Breakpoint.h
+++ b/include/lldb/Breakpoint/Breakpoint.h
@@ -106,7 +106,7 @@
         GetFlavor () const;
 
         BreakpointEventData (lldb::BreakpointEventType sub_type,
-                             lldb::BreakpointSP &new_breakpoint_sp);
+                             const lldb::BreakpointSP &new_breakpoint_sp);
 
         virtual
         ~BreakpointEventData();
@@ -116,6 +116,12 @@
 
         lldb::BreakpointSP &
         GetBreakpoint ();
+        
+        BreakpointLocationCollection &
+        GetBreakpointLocationCollection()
+        {
+            return m_locations;
+        }
 
 
         virtual void
@@ -129,10 +135,14 @@
 
         static lldb::BreakpointLocationSP
         GetBreakpointLocationAtIndexFromEvent (const lldb::EventSP &event_sp, uint32_t loc_idx);
+        
+        static uint32_t
+        GetNumBreakpointLocationsFromEvent (const lldb::EventSP &event_sp);
+
+        static const BreakpointEventData *
+        GetEventDataFromEvent (const Event *event_sp);
 
     private:
-        static BreakpointEventData *
-        GetEventDataFromEvent (const lldb::EventSP &event_sp);
 
         lldb::BreakpointEventType m_breakpoint_event;
         lldb::BreakpointSP m_new_breakpoint_sp;
@@ -343,7 +353,25 @@
     ///     The thread id for which the breakpoint hit will stop, LLDB_INVALID_THREAD_ID for all threads.
     //------------------------------------------------------------------
     lldb::tid_t
-    GetThreadID ();
+    GetThreadID () const;
+
+    void
+    SetThreadIndex (uint32_t index);
+    
+    uint32_t
+    GetThreadIndex() const;
+    
+    void
+    SetThreadName (const char *thread_name);
+    
+    const char *
+    GetThreadName () const;
+    
+    void 
+    SetQueueName (const char *queue_name);
+    
+    const char *
+    GetQueueName () const;
 
     //------------------------------------------------------------------
     /// Set the callback action invoked when the breakpoint is hit.  
@@ -531,11 +559,18 @@
     //------------------------------------------------------------------
     // For Breakpoint only
     //------------------------------------------------------------------
+    bool m_being_created;
     Target &m_target;                         // The target that holds this breakpoint.
     lldb::SearchFilterSP m_filter_sp;         // The filter that constrains the breakpoint's domain.
     lldb::BreakpointResolverSP m_resolver_sp; // The resolver that defines this breakpoint.
     BreakpointOptions m_options;              // Settable breakpoint options
     BreakpointLocationList m_locations;       // The list of locations currently found for this breakpoint.
+    
+    void
+    SendBreakpointChangedEvent (lldb::BreakpointEventType eventKind);
+    
+    void
+    SendBreakpointChangedEvent (BreakpointEventData *data);
 
     DISALLOW_COPY_AND_ASSIGN(Breakpoint);
 };
diff --git a/include/lldb/Breakpoint/BreakpointLocation.h b/include/lldb/Breakpoint/BreakpointLocation.h
index 98941cb..492e029 100644
--- a/include/lldb/Breakpoint/BreakpointLocation.h
+++ b/include/lldb/Breakpoint/BreakpointLocation.h
@@ -203,6 +203,27 @@
     //------------------------------------------------------------------
     void
     SetThreadID (lldb::tid_t thread_id);
+    
+    lldb::tid_t
+    GetThreadID ();
+
+    void
+    SetThreadIndex (uint32_t index);
+    
+    uint32_t
+    GetThreadIndex() const;
+    
+    void
+    SetThreadName (const char *thread_name);
+    
+    const char *
+    GetThreadName () const;
+    
+    void 
+    SetQueueName (const char *queue_name);
+    
+    const char *
+    GetQueueName () const;
 
     //------------------------------------------------------------------
     // The next section deals with this location's breakpoint sites.
@@ -366,11 +387,15 @@
     //------------------------------------------------------------------
     // Data members:
     //------------------------------------------------------------------
+    bool m_being_created;
     Address m_address; ///< The address defining this location.
     Breakpoint &m_owner; ///< The breakpoint that produced this object.
     std::auto_ptr<BreakpointOptions> m_options_ap; ///< Breakpoint options pointer, NULL if we're using our breakpoint's options.
     lldb::BreakpointSiteSP m_bp_site_sp; ///< Our breakpoint site (it may be shared by more than one location.)
 
+    void
+    SendBreakpointLocationChangedEvent (lldb::BreakpointEventType eventKind);
+    
     DISALLOW_COPY_AND_ASSIGN (BreakpointLocation);
 };
 
diff --git a/include/lldb/Breakpoint/BreakpointLocationList.h b/include/lldb/Breakpoint/BreakpointLocationList.h
index 3a96710..93a965b 100644
--- a/include/lldb/Breakpoint/BreakpointLocationList.h
+++ b/include/lldb/Breakpoint/BreakpointLocationList.h
@@ -223,7 +223,7 @@
     /// here because only Breakpoints are allowed to create the
     /// breakpoint location list.
     //------------------------------------------------------------------
-    BreakpointLocationList();
+    BreakpointLocationList(Breakpoint &owner);
 
     //------------------------------------------------------------------
     /// Add the breakpoint \a bp_loc_sp to the list.
@@ -236,18 +236,29 @@
     ///     Returns breakpoint location id.
     //------------------------------------------------------------------
     lldb::BreakpointLocationSP
-    Create (Breakpoint &owner, const Address &addr);
-//    Add (lldb::BreakpointLocationSP& bp_loc_sp);
+    Create (const Address &addr);
+    
+    void
+    StartRecordingNewLocations(BreakpointLocationCollection &new_locations);
+    
+    void
+    StopRecordingNewLocations();
+    
+    lldb::BreakpointLocationSP
+    AddLocation (const Address &addr,
+                 bool *new_location = NULL);
 
     typedef std::vector<lldb::BreakpointLocationSP> collection;
     typedef std::map<lldb_private::Address,
                      lldb::BreakpointLocationSP,
                      Address::ModulePointerAndOffsetLessThanFunctionObject> addr_map;
 
+    Breakpoint &m_owner;
     collection m_locations;
     addr_map m_address_to_location;
     mutable Mutex m_mutex;
     lldb::break_id_t m_next_id;
+    BreakpointLocationCollection *m_new_location_recorder;
 };
 
 } // namespace lldb_private
diff --git a/include/lldb/lldb-enumerations.h b/include/lldb/lldb-enumerations.h
index 8b901b1..798479e 100644
--- a/include/lldb/lldb-enumerations.h
+++ b/include/lldb/lldb-enumerations.h
@@ -284,9 +284,15 @@
         eBreakpointEventTypeInvalidType         = (1u << 0),
         eBreakpointEventTypeAdded               = (1u << 1),
         eBreakpointEventTypeRemoved             = (1u << 2),
-        eBreakpointEventTypeLocationsAdded      = (1u << 3),
+        eBreakpointEventTypeLocationsAdded      = (1u << 3),  // Locations added doesn't get sent when the breakpoint is created
         eBreakpointEventTypeLocationsRemoved    = (1u << 4),
-        eBreakpointEventTypeLocationsResolved   = (1u << 5)
+        eBreakpointEventTypeLocationsResolved   = (1u << 5),
+        eBreakpointEventTypeEnabled             = (1u << 6),
+        eBreakpointEventTypeDisabled            = (1u << 7),
+        eBreakpointEventTypeCommandChanged      = (1u << 8),
+        eBreakpointEventTypeConditionChanged    = (1u << 9),
+        eBreakpointEventTypeIgnoreChanged       = (1u << 10),
+        eBreakpointEventTypeThreadChanged       = (1u << 11)
     } BreakpointEventType;
 
 
diff --git a/scripts/Python/interface/SBBreakpoint.i b/scripts/Python/interface/SBBreakpoint.i
index 9e333c3..0e9a80c 100644
--- a/scripts/Python/interface/SBBreakpoint.i
+++ b/scripts/Python/interface/SBBreakpoint.i
@@ -180,6 +180,9 @@
     bool
     GetDescription (lldb::SBStream &description);
 
+    static bool
+    EventIsBreakpointEvent (const lldb::SBEvent &event);
+    
     static lldb::BreakpointEventType
     GetBreakpointEventTypeFromEvent (const lldb::SBEvent& event);
 
@@ -188,6 +191,9 @@
     
     static lldb::SBBreakpointLocation
     GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx);
+    
+    static uint32_t
+    GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event_sp);
 };
 
 } // namespace lldb
diff --git a/scripts/Python/interface/SBProcess.i b/scripts/Python/interface/SBProcess.i
index df58f16..20d782a 100644
--- a/scripts/Python/interface/SBProcess.i
+++ b/scripts/Python/interface/SBProcess.i
@@ -269,6 +269,9 @@
     static lldb::SBProcess
     GetProcessFromEvent (const lldb::SBEvent &event);
 
+    static bool
+    EventIsProcessEvent (const lldb::SBEvent &event);
+
     lldb::SBBroadcaster
     GetBroadcaster () const;
 
diff --git a/source/API/SBBreakpoint.cpp b/source/API/SBBreakpoint.cpp
index 33bdbe0..6b8ac6e 100644
--- a/source/API/SBBreakpoint.cpp
+++ b/source/API/SBBreakpoint.cpp
@@ -557,6 +557,13 @@
     return m_opaque_sp;
 }
 
+bool
+SBBreakpoint::EventIsBreakpointEvent (const lldb::SBEvent &event)
+{
+    return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) != NULL;
+
+}
+
 BreakpointEventType
 SBBreakpoint::GetBreakpointEventTypeFromEvent (const SBEvent& event)
 {
@@ -583,4 +590,13 @@
     return sb_breakpoint_loc;
 }
 
+uint32_t
+SBBreakpoint::GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event)
+{
+    uint32_t num_locations = 0;
+    if (event.IsValid())
+        num_locations = (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent (event.GetSP()));
+    return num_locations;
+}
+
 
diff --git a/source/API/SBBreakpointLocation.cpp b/source/API/SBBreakpointLocation.cpp
index 57cf5a1..d7fc1dc 100644
--- a/source/API/SBBreakpointLocation.cpp
+++ b/source/API/SBBreakpointLocation.cpp
@@ -176,9 +176,7 @@
     if (m_opaque_sp)
     {
         Mutex::Locker api_locker (m_opaque_sp->GetBreakpoint().GetTarget().GetAPIMutex());
-        const ThreadSpec *thread_spec = m_opaque_sp->GetLocationOptions()->GetThreadSpecNoCreate();
-        if (thread_spec)
-            tid = thread_spec->GetTID();
+        return m_opaque_sp->GetThreadID();
     }
     return tid;
 }
@@ -189,7 +187,7 @@
     if (m_opaque_sp)
     {
         Mutex::Locker api_locker (m_opaque_sp->GetBreakpoint().GetTarget().GetAPIMutex());
-        m_opaque_sp->GetLocationOptions()->GetThreadSpec()->SetIndex (index);
+        m_opaque_sp->SetThreadIndex (index);
     }
 }
 
@@ -200,9 +198,7 @@
     if (m_opaque_sp)
     {
         Mutex::Locker api_locker (m_opaque_sp->GetBreakpoint().GetTarget().GetAPIMutex());
-        const ThreadSpec *thread_spec = m_opaque_sp->GetOptionsNoCreate()->GetThreadSpecNoCreate();
-        if (thread_spec)
-            thread_idx = thread_spec->GetIndex();
+        return m_opaque_sp->GetThreadIndex();
     }
     return thread_idx;
 }
@@ -214,7 +210,7 @@
     if (m_opaque_sp)
     {
         Mutex::Locker api_locker (m_opaque_sp->GetBreakpoint().GetTarget().GetAPIMutex());
-        m_opaque_sp->GetLocationOptions()->GetThreadSpec()->SetName (thread_name);
+        m_opaque_sp->SetThreadName (thread_name);
     }
 }
 
@@ -224,9 +220,7 @@
     if (m_opaque_sp)
     {
         Mutex::Locker api_locker (m_opaque_sp->GetBreakpoint().GetTarget().GetAPIMutex());
-        const ThreadSpec *thread_spec = m_opaque_sp->GetOptionsNoCreate()->GetThreadSpecNoCreate();
-        if (thread_spec)
-            return thread_spec->GetName();
+        return m_opaque_sp->GetThreadName();
     }
     return NULL;
 }
@@ -237,7 +231,7 @@
     if (m_opaque_sp)
     {
         Mutex::Locker api_locker (m_opaque_sp->GetBreakpoint().GetTarget().GetAPIMutex());
-        m_opaque_sp->GetLocationOptions()->GetThreadSpec()->SetQueueName (queue_name);
+        m_opaque_sp->SetQueueName (queue_name);
     }
 }
 
@@ -247,9 +241,7 @@
     if (m_opaque_sp)
     {
         Mutex::Locker api_locker (m_opaque_sp->GetBreakpoint().GetTarget().GetAPIMutex());
-        const ThreadSpec *thread_spec = m_opaque_sp->GetOptionsNoCreate()->GetThreadSpecNoCreate();
-        if (thread_spec)
-            return thread_spec->GetQueueName();
+        m_opaque_sp->GetQueueName ();
     }
     return NULL;
 }
diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp
index 4b4e840..5fc7196 100644
--- a/source/API/SBProcess.cpp
+++ b/source/API/SBProcess.cpp
@@ -740,6 +740,11 @@
     return process;
 }
 
+bool
+SBProcess::EventIsProcessEvent (const SBEvent &event)
+{
+    return Process::ProcessEventData::GetEventDataFromEvent(event.get()) != NULL;
+}
 
 SBBroadcaster
 SBProcess::GetBroadcaster () const
diff --git a/source/Breakpoint/Breakpoint.cpp b/source/Breakpoint/Breakpoint.cpp
index aa9fab2..c680ace 100644
--- a/source/Breakpoint/Breakpoint.cpp
+++ b/source/Breakpoint/Breakpoint.cpp
@@ -45,12 +45,14 @@
 // Breakpoint constructor
 //----------------------------------------------------------------------
 Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp) :
+    m_being_created(true),
     m_target (target),
     m_filter_sp (filter_sp),
     m_resolver_sp (resolver_sp),
     m_options (),
-    m_locations ()
+    m_locations (*this)
 {
+    m_being_created = false;
 }
 
 //----------------------------------------------------------------------
@@ -83,21 +85,7 @@
 BreakpointLocationSP
 Breakpoint::AddLocation (const Address &addr, bool *new_location)
 {
-    if (new_location)
-        *new_location = false;
-    BreakpointLocationSP bp_loc_sp (m_locations.FindByAddress(addr));
-    if (!bp_loc_sp)
-	{
-		bp_loc_sp = m_locations.Create (*this, addr);
-		if (bp_loc_sp)
-		{
-	    	bp_loc_sp->ResolveBreakpointSite();
-
-		    if (new_location)
-	    	    *new_location = true;
-		}
-	}
-    return bp_loc_sp;
+    return m_locations.AddLocation (addr, new_location);
 }
 
 BreakpointLocationSP
@@ -135,11 +123,17 @@
 void
 Breakpoint::SetEnabled (bool enable)
 {
+    if (enable == m_options.IsEnabled())
+        return;
+
     m_options.SetEnabled(enable);
     if (enable)
         m_locations.ResolveAllBreakpointSites();
     else
         m_locations.ClearAllBreakpointSites();
+        
+    SendBreakpointChangedEvent (enable ? eBreakpointEventTypeEnabled : eBreakpointEventTypeDisabled);
+
 }
 
 bool
@@ -151,7 +145,11 @@
 void
 Breakpoint::SetIgnoreCount (uint32_t n)
 {
+    if (m_options.GetIgnoreCount() == n)
+        return;
+        
     m_options.SetIgnoreCount(n);
+    SendBreakpointChangedEvent (eBreakpointEventTypeIgnoreChanged);
 }
 
 uint32_t
@@ -169,22 +167,84 @@
 void
 Breakpoint::SetThreadID (lldb::tid_t thread_id)
 {
+    if (m_options.GetThreadSpec()->GetTID() == thread_id)
+        return;
+        
     m_options.GetThreadSpec()->SetTID(thread_id);
+    SendBreakpointChangedEvent (eBreakpointEventTypeThreadChanged);
 }
 
 lldb::tid_t
-Breakpoint::GetThreadID ()
+Breakpoint::GetThreadID () const
 {
-    if (m_options.GetThreadSpec() == NULL)
+    if (m_options.GetThreadSpecNoCreate() == NULL)
         return LLDB_INVALID_THREAD_ID;
     else
-        return m_options.GetThreadSpec()->GetTID();
+        return m_options.GetThreadSpecNoCreate()->GetTID();
+}
+
+void
+Breakpoint::SetThreadIndex (uint32_t index)
+{
+    if (m_options.GetThreadSpec()->GetIndex() == index)
+        return;
+        
+    m_options.GetThreadSpec()->SetIndex(index);
+    SendBreakpointChangedEvent (eBreakpointEventTypeThreadChanged);
+}
+
+uint32_t
+Breakpoint::GetThreadIndex() const
+{
+    if (m_options.GetThreadSpecNoCreate() == NULL)
+        return 0;
+    else
+        return m_options.GetThreadSpecNoCreate()->GetIndex();
+}
+
+void
+Breakpoint::SetThreadName (const char *thread_name)
+{
+    if (::strcmp (m_options.GetThreadSpec()->GetName(), thread_name) == 0)
+        return;
+        
+    m_options.GetThreadSpec()->SetName (thread_name);
+    SendBreakpointChangedEvent (eBreakpointEventTypeThreadChanged);
+}
+
+const char *
+Breakpoint::GetThreadName () const
+{
+    if (m_options.GetThreadSpecNoCreate() == NULL)
+        return NULL;
+    else
+        return m_options.GetThreadSpecNoCreate()->GetName();
+}
+
+void 
+Breakpoint::SetQueueName (const char *queue_name)
+{
+    if (::strcmp (m_options.GetThreadSpec()->GetQueueName(), queue_name) == 0)
+        return;
+        
+    m_options.GetThreadSpec()->SetQueueName (queue_name);
+    SendBreakpointChangedEvent (eBreakpointEventTypeThreadChanged);
+}
+
+const char *
+Breakpoint::GetQueueName () const
+{
+    if (m_options.GetThreadSpecNoCreate() == NULL)
+        return NULL;
+    else
+        return m_options.GetThreadSpecNoCreate()->GetQueueName();
 }
 
 void 
 Breakpoint::SetCondition (const char *condition)
 {
     m_options.SetCondition (condition);
+    SendBreakpointChangedEvent (eBreakpointEventTypeConditionChanged);
 }
 
 ThreadPlan *
@@ -206,6 +266,8 @@
     // The default "Baton" class will keep a copy of "baton" and won't free
     // or delete it when it goes goes out of scope.
     m_options.SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
+    
+    SendBreakpointChangedEvent (eBreakpointEventTypeCommandChanged);
 }
 
 // This function is used when a baton needs to be freed and therefore is 
@@ -309,9 +371,31 @@
                 new_modules.AppendIfNeeded (module_sp);
 
         }
+        
         if (new_modules.GetSize() > 0)
         {
-            ResolveBreakpointInModules(new_modules);
+            // 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);
+            
         }
     }
     else
@@ -323,6 +407,13 @@
         // the same?  Or do we need to do an equality on modules that is an
         // "equivalence"???
 
+        BreakpointEventData *removed_locations_event;
+        if (!IsInternal())
+            removed_locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsRemoved, 
+                                                               shared_from_this());
+        else
+            removed_locations_event = NULL;
+                    
         for (size_t i = 0; i < module_list.GetSize(); i++)
         {
             ModuleSP module_sp (module_list.GetModuleAtIndex (i));
@@ -340,10 +431,15 @@
                         // so we always get complete hit count and breakpoint
                         // lifetime info
                         break_loc->ClearBreakpointSite();
+                        if (removed_locations_event)
+                        {
+                            removed_locations_event->GetBreakpointLocationCollection().Add(break_loc);
+                        }
                     }
                 }
             }
         }
+        SendBreakpointChangedEvent (removed_locations_event);
     }
 }
 
@@ -429,7 +525,7 @@
 }
 
 Breakpoint::BreakpointEventData::BreakpointEventData (BreakpointEventType sub_type, 
-                                                      BreakpointSP &new_breakpoint_sp) :
+                                                      const BreakpointSP &new_breakpoint_sp) :
     EventData (),
     m_breakpoint_event (sub_type),
     m_new_breakpoint_sp (new_breakpoint_sp)
@@ -471,14 +567,14 @@
 {
 }
 
-Breakpoint::BreakpointEventData *
-Breakpoint::BreakpointEventData::GetEventDataFromEvent (const EventSP &event_sp)
+const Breakpoint::BreakpointEventData *
+Breakpoint::BreakpointEventData::GetEventDataFromEvent (const Event *event)
 {
-    if (event_sp)
+    if (event)
     {
-        EventData *event_data = event_sp->GetData();
+        const EventData *event_data = event->GetData();
         if (event_data && event_data->GetFlavor() == BreakpointEventData::GetFlavorString())
-            return static_cast <BreakpointEventData *> (event_sp->GetData());
+            return static_cast <const BreakpointEventData *> (event->GetData());
     }
     return NULL;
 }
@@ -486,7 +582,7 @@
 BreakpointEventType
 Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (const EventSP &event_sp)
 {
-    BreakpointEventData *data = GetEventDataFromEvent (event_sp);
+    const BreakpointEventData *data = GetEventDataFromEvent (event_sp.get());
 
     if (data == NULL)
         return eBreakpointEventTypeInvalidType;
@@ -499,24 +595,32 @@
 {
     BreakpointSP bp_sp;
 
-    BreakpointEventData *data = GetEventDataFromEvent (event_sp);
+    const BreakpointEventData *data = GetEventDataFromEvent (event_sp.get());
     if (data)
-        bp_sp = data->GetBreakpoint();
+        bp_sp = data->m_new_breakpoint_sp;
 
     return bp_sp;
 }
 
+uint32_t
+Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent (const EventSP &event_sp)
+{
+    const BreakpointEventData *data = GetEventDataFromEvent (event_sp.get());
+    if (data)
+        return data->m_locations.GetSize();
+
+    return 0;
+}
+
 lldb::BreakpointLocationSP
 Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (const lldb::EventSP &event_sp, uint32_t bp_loc_idx)
 {
     lldb::BreakpointLocationSP bp_loc_sp;
 
-    BreakpointEventData *data = GetEventDataFromEvent (event_sp);
+    const BreakpointEventData *data = GetEventDataFromEvent (event_sp.get());
     if (data)
     {
-        Breakpoint *bp = data->GetBreakpoint().get();
-        if (bp)
-            bp_loc_sp = bp->GetLocationAtIndex(bp_loc_idx);
+        bp_loc_sp = data->m_locations.GetByIndex(bp_loc_idx);
     }
 
     return bp_loc_sp;
@@ -556,3 +660,31 @@
 {
     m_filter_sp->GetDescription (s);
 }
+
+void
+Breakpoint::SendBreakpointChangedEvent (lldb::BreakpointEventType eventKind)
+{
+    if (!m_being_created
+        && !IsInternal() 
+        && GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
+    {
+        BreakpointEventData *data = new Breakpoint::BreakpointEventData (eventKind, shared_from_this());
+            
+        GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data);
+    }
+}
+
+void
+Breakpoint::SendBreakpointChangedEvent (BreakpointEventData *data)
+{
+
+    if (data == NULL)
+        return;
+        
+    if (!m_being_created
+        && !IsInternal() 
+        && GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
+        GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data);
+    else
+        delete data;
+}
diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp
index 358d378..c99eb46 100644
--- a/source/Breakpoint/BreakpointLocation.cpp
+++ b/source/Breakpoint/BreakpointLocation.cpp
@@ -38,12 +38,14 @@
     bool hardware
 ) :
     StoppointLocation (loc_id, addr.GetOpcodeLoadAddress(&owner.GetTarget()), hardware),
+    m_being_created(true),
     m_address (addr),
     m_owner (owner),
     m_options_ap (),
     m_bp_site_sp ()
 {
     SetThreadID (tid);
+    m_being_created = false;
 }
 
 BreakpointLocation::~BreakpointLocation()
@@ -92,6 +94,7 @@
     {
         ClearBreakpointSite();
     }
+    SendBreakpointLocationChangedEvent (enabled ? eBreakpointEventTypeEnabled : eBreakpointEventTypeDisabled);
 }
 
 void
@@ -106,6 +109,89 @@
         if (m_options_ap.get() != NULL)
             m_options_ap->SetThreadID (thread_id);
     }
+    SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
+}
+
+lldb::tid_t
+BreakpointLocation::GetThreadID ()
+{
+    if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
+        return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID();
+    else
+        return LLDB_INVALID_THREAD_ID;
+}
+
+void
+BreakpointLocation::SetThreadIndex (uint32_t index)
+{
+    if (index != 0)
+        GetLocationOptions()->GetThreadSpec()->SetIndex(index);
+    else
+    {
+        // If we're resetting this to an invalid thread id, then
+        // don't make an options pointer just to do that.
+        if (m_options_ap.get() != NULL)
+            m_options_ap->GetThreadSpec()->SetIndex(index);
+    }
+    SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
+                        
+}
+
+uint32_t
+BreakpointLocation::GetThreadIndex() const
+{
+    if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
+        return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetIndex();
+    else
+        return 0;
+}
+
+void
+BreakpointLocation::SetThreadName (const char *thread_name)
+{
+    if (thread_name != NULL)
+        GetLocationOptions()->GetThreadSpec()->SetName(thread_name);
+    else
+    {
+        // If we're resetting this to an invalid thread id, then
+        // don't make an options pointer just to do that.
+        if (m_options_ap.get() != NULL)
+            m_options_ap->GetThreadSpec()->SetName(thread_name);
+    }
+    SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
+}
+
+const char *
+BreakpointLocation::GetThreadName () const
+{
+    if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
+        return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetName();
+    else
+        return NULL;
+}
+
+void 
+BreakpointLocation::SetQueueName (const char *queue_name)
+{
+    if (queue_name != NULL)
+        GetLocationOptions()->GetThreadSpec()->SetQueueName(queue_name);
+    else
+    {
+        // If we're resetting this to an invalid thread id, then
+        // don't make an options pointer just to do that.
+        if (m_options_ap.get() != NULL)
+            m_options_ap->GetThreadSpec()->SetQueueName(queue_name);
+    }
+    SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
+}
+
+const char *
+BreakpointLocation::GetQueueName () const
+{
+    if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
+        return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetQueueName();
+    else
+        return NULL;
 }
 
 bool
@@ -124,6 +210,7 @@
     // The default "Baton" class will keep a copy of "baton" and won't free
     // or delete it when it goes goes out of scope.
     GetLocationOptions()->SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
+    SendBreakpointLocationChangedEvent (eBreakpointEventTypeCommandChanged);
 }
 
 void
@@ -131,6 +218,7 @@
                  bool is_synchronous)
 {
     GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous);
+    SendBreakpointLocationChangedEvent (eBreakpointEventTypeCommandChanged);
 }
 
 
@@ -144,6 +232,7 @@
 BreakpointLocation::SetCondition (const char *condition)
 {
     GetLocationOptions()->SetCondition (condition);
+    SendBreakpointLocationChangedEvent (eBreakpointEventTypeConditionChanged);
 }
 
 ThreadPlan *
@@ -171,6 +260,7 @@
 BreakpointLocation::SetIgnoreCount (uint32_t n)
 {
     GetLocationOptions()->SetIgnoreCount(n);
+    SendBreakpointLocationChangedEvent (eBreakpointEventTypeIgnoreChanged);
 }
 
 const BreakpointOptions *
@@ -420,3 +510,18 @@
               GetHitCount(),
               GetOptionsNoCreate()->GetIgnoreCount());
 }
+
+void
+BreakpointLocation::SendBreakpointLocationChangedEvent (lldb::BreakpointEventType eventKind)
+{
+    if (!m_being_created
+        && !m_owner.IsInternal() 
+        && m_owner.GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
+    {
+        Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData (eventKind, 
+                                                                                     m_owner.shared_from_this());
+        data->GetBreakpointLocationCollection().Add (shared_from_this());
+        m_owner.GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data);
+    }
+}
+    
diff --git a/source/Breakpoint/BreakpointLocationCollection.cpp b/source/Breakpoint/BreakpointLocationCollection.cpp
index e0ada3a..bc493b2 100644
--- a/source/Breakpoint/BreakpointLocationCollection.cpp
+++ b/source/Breakpoint/BreakpointLocationCollection.cpp
@@ -16,7 +16,6 @@
 #include "lldb/Core/ModuleList.h"
 #include "lldb/Breakpoint/Breakpoint.h"
 #include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Breakpoint/BreakpointLocationList.h"
 #include "lldb/Target/Thread.h"
 #include "lldb/Target/ThreadSpec.h"
 
diff --git a/source/Breakpoint/BreakpointLocationList.cpp b/source/Breakpoint/BreakpointLocationList.cpp
index 54824dd..ac98b9a 100644
--- a/source/Breakpoint/BreakpointLocationList.cpp
+++ b/source/Breakpoint/BreakpointLocationList.cpp
@@ -20,10 +20,12 @@
 using namespace lldb;
 using namespace lldb_private;
 
-BreakpointLocationList::BreakpointLocationList() :
+BreakpointLocationList::BreakpointLocationList(Breakpoint &owner) :
     m_locations(),
     m_address_to_location (),
-    m_mutex (Mutex::eMutexTypeRecursive)
+    m_mutex (Mutex::eMutexTypeRecursive),
+    m_new_location_recorder (NULL),
+    m_owner (owner)
 {
 }
 
@@ -32,12 +34,12 @@
 }
 
 BreakpointLocationSP
-BreakpointLocationList::Create (Breakpoint &bp, const Address &addr)
+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_locations.size() + 1;
-    BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, bp, addr));
+    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;
@@ -217,3 +219,45 @@
     }
 }
 
+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;
+}
+
+
+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;
+}
+
diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp
index 34cfc78..d3a110c 100644
--- a/source/Commands/CommandObjectBreakpoint.cpp
+++ b/source/Commands/CommandObjectBreakpoint.cpp
@@ -1516,16 +1516,16 @@
                             location->SetThreadID (m_options.m_thread_id);
                             
                         if (m_options.m_thread_index_passed)
-                            location->GetLocationOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
+                            location->SetThreadIndex(m_options.m_thread_index);
                         
                         if (m_options.m_name_passed)
-                            location->GetLocationOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str());
+                            location->SetThreadName(m_options.m_thread_name.c_str());
                         
                         if (m_options.m_queue_passed)
-                            location->GetLocationOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str());
+                            location->SetQueueName(m_options.m_queue_name.c_str());
                             
                         if (m_options.m_ignore_count != 0)
-                            location->GetLocationOptions()->SetIgnoreCount(m_options.m_ignore_count);
+                            location->SetIgnoreCount(m_options.m_ignore_count);
                             
                         if (m_options.m_enable_passed)
                             location->SetEnabled (m_options.m_enable_value);
@@ -1540,16 +1540,16 @@
                         bp->SetThreadID (m_options.m_thread_id);
                         
                     if (m_options.m_thread_index_passed)
-                        bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
+                        bp->SetThreadIndex(m_options.m_thread_index);
                     
                     if (m_options.m_name_passed)
-                        bp->GetOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str());
+                        bp->SetThreadName(m_options.m_thread_name.c_str());
                     
                     if (m_options.m_queue_passed)
-                        bp->GetOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str());
+                        bp->SetQueueName(m_options.m_queue_name.c_str());
                         
                     if (m_options.m_ignore_count != 0)
-                        bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
+                        bp->SetIgnoreCount(m_options.m_ignore_count);
                         
                     if (m_options.m_enable_passed)
                         bp->SetEnabled (m_options.m_enable_value);
diff --git a/source/Target/TargetList.cpp b/source/Target/TargetList.cpp
index b6e5d29..6ca58b8 100644
--- a/source/Target/TargetList.cpp
+++ b/source/Target/TargetList.cpp
@@ -161,6 +161,9 @@
         Mutex::Locker locker(m_target_list_mutex);
         m_selected_target_idx = m_target_list.size();
         m_target_list.push_back(target_sp);
+        
+        // Now sign the Debugger up to listen to target events for this target:
+        debugger.GetListener().StartListeningForEvents(target_sp.get(), Target::eBroadcastBitBreakpointChanged);
     }
 
     return error;
diff --git a/tools/driver/Driver.cpp b/tools/driver/Driver.cpp
index aaf5826..5808f5f 100644
--- a/tools/driver/Driver.cpp
+++ b/tools/driver/Driver.cpp
@@ -22,6 +22,7 @@
 #include <string>
 
 #include "IOChannel.h"
+#include "lldb/API/SBBreakpoint.h"
 #include "lldb/API/SBCommandInterpreter.h"
 #include "lldb/API/SBCommandReturnObject.h"
 #include "lldb/API/SBCommunication.h"
@@ -824,6 +825,46 @@
     }
 }
 
+// This function handles events that were broadcast by the process.
+void
+Driver::HandleBreakpointEvent (const SBEvent &event)
+{
+    using namespace lldb;
+    const uint32_t event_type = SBBreakpoint::GetBreakpointEventTypeFromEvent (event);
+    
+    if (event_type & eBreakpointEventTypeAdded
+        || event_type & eBreakpointEventTypeRemoved
+        || event_type & eBreakpointEventTypeEnabled
+        || event_type & eBreakpointEventTypeDisabled
+        || event_type & eBreakpointEventTypeCommandChanged
+        || event_type & eBreakpointEventTypeConditionChanged
+        || event_type & eBreakpointEventTypeIgnoreChanged
+        || event_type & eBreakpointEventTypeLocationsResolved)
+    {
+        // Don't do anything about these events, since the breakpoint commands already echo these actions.
+    }              
+    else if (event_type & eBreakpointEventTypeLocationsAdded)
+    {
+        char message[256];
+        uint32_t num_new_locations = SBBreakpoint::GetNumBreakpointLocationsFromEvent(event);
+        if (num_new_locations > 0)
+        {
+            SBBreakpoint breakpoint = SBBreakpoint::GetBreakpointFromEvent(event);
+            int message_len = ::snprintf (message, sizeof(message), "%d locations added to breakpoint %d\n", 
+                                          num_new_locations,
+                                          breakpoint.GetID());
+            m_io_channel_ap->OutWrite(message, message_len, ASYNC);
+        }
+    }
+    else if (event_type & eBreakpointEventTypeLocationsRemoved)
+    {
+       // These locations just get disabled, not sure it is worth spamming folks about this on the command line.
+    }
+    else if (event_type & eBreakpointEventTypeLocationsResolved)
+    {
+       // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy.
+    }
+}
 
 // This function handles events that were broadcast by the process.
 void
@@ -1348,10 +1389,14 @@
                             else
                                 done = HandleIOEvent (event);
                         }
-                        else if (event.BroadcasterMatchesRef (m_debugger.GetSelectedTarget().GetProcess().GetBroadcaster()))
+                        else if (SBProcess::EventIsProcessEvent (event))
                         {
                             HandleProcessEvent (event);
                         }
+                        else if (SBBreakpoint::EventIsBreakpointEvent (event))
+                        {
+                            HandleBreakpointEvent (event);
+                        }
                         else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
                         {
                             if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
diff --git a/tools/driver/Driver.h b/tools/driver/Driver.h
index eb43513..29fadfc 100644
--- a/tools/driver/Driver.h
+++ b/tools/driver/Driver.h
@@ -62,6 +62,9 @@
     void
     HandleProcessEvent (const lldb::SBEvent &event);
 
+    void
+    HandleBreakpointEvent (const lldb::SBEvent &event);
+
     lldb::SBError
     ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &do_exit);