summaryrefslogtreecommitdiffstats
path: root/lldb/source/Breakpoint
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Breakpoint')
-rw-r--r--lldb/source/Breakpoint/Breakpoint.cpp516
-rw-r--r--lldb/source/Breakpoint/BreakpointID.cpp120
-rw-r--r--lldb/source/Breakpoint/BreakpointIDList.cpp348
-rw-r--r--lldb/source/Breakpoint/BreakpointList.cpp198
-rw-r--r--lldb/source/Breakpoint/BreakpointLocation.cpp389
-rw-r--r--lldb/source/Breakpoint/BreakpointLocationCollection.cpp161
-rw-r--r--lldb/source/Breakpoint/BreakpointLocationList.cpp305
-rw-r--r--lldb/source/Breakpoint/BreakpointOptions.cpp180
-rw-r--r--lldb/source/Breakpoint/BreakpointResolver.cpp60
-rw-r--r--lldb/source/Breakpoint/BreakpointResolverAddress.cpp111
-rw-r--r--lldb/source/Breakpoint/BreakpointResolverFileLine.cpp122
-rw-r--r--lldb/source/Breakpoint/BreakpointResolverName.cpp252
-rw-r--r--lldb/source/Breakpoint/BreakpointSite.cpp221
-rw-r--r--lldb/source/Breakpoint/BreakpointSiteList.cpp229
-rw-r--r--lldb/source/Breakpoint/Stoppoint.cpp46
-rw-r--r--lldb/source/Breakpoint/StoppointCallbackContext.cpp38
-rw-r--r--lldb/source/Breakpoint/StoppointLocation.cpp120
-rw-r--r--lldb/source/Breakpoint/WatchpointLocation.cpp137
18 files changed, 3553 insertions, 0 deletions
diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp
new file mode 100644
index 00000000000..c475cf0f0d7
--- /dev/null
+++ b/lldb/source/Breakpoint/Breakpoint.cpp
@@ -0,0 +1,516 @@
+//===-- Breakpoint.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/Core/Address.h"
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointResolver.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/SearchFilter.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/lldb-private-log.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+const ConstString &
+Breakpoint::GetEventIdentifier ()
+{
+ static ConstString g_identifier("event-identifier.breakpoint.changed");
+ return g_identifier;
+}
+
+//----------------------------------------------------------------------
+// Breakpoint constructor
+//----------------------------------------------------------------------
+Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp) :
+ m_target (target),
+ m_filter_sp (filter_sp),
+ m_resolver_sp (resolver_sp),
+ m_options (),
+ m_locations ()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Breakpoint::~Breakpoint()
+{
+}
+
+bool
+Breakpoint::IsInternal () const
+{
+ return LLDB_BREAK_ID_IS_INTERNAL(m_bid);
+}
+
+
+
+Target&
+Breakpoint::GetTarget ()
+{
+ return m_target;
+}
+
+const Target&
+Breakpoint::GetTarget () const
+{
+ return m_target;
+}
+
+BreakpointLocationSP
+Breakpoint::AddLocation (Address &addr, bool *new_location)
+{
+ BreakpointLocationSP bp_loc_sp (m_locations.FindByAddress(addr));
+ if (bp_loc_sp)
+ {
+ if (new_location)
+ *new_location = false;
+ return bp_loc_sp;
+ }
+
+ bp_loc_sp.reset (new BreakpointLocation (m_locations.GetNextID(), *this, addr));
+ m_locations.Add (bp_loc_sp);
+ bp_loc_sp->ResolveBreakpointSite();
+
+ if (new_location)
+ *new_location = true;
+ return bp_loc_sp;
+}
+
+BreakpointLocationSP
+Breakpoint::FindLocationByAddress (Address &addr)
+{
+ return m_locations.FindByAddress(addr);
+}
+
+break_id_t
+Breakpoint::FindLocationIDByAddress (Address &addr)
+{
+ return m_locations.FindIDByAddress(addr);
+}
+
+BreakpointLocationSP
+Breakpoint::FindLocationByID (break_id_t bp_loc_id)
+{
+ return m_locations.FindByID(bp_loc_id);
+}
+
+BreakpointLocationSP
+Breakpoint::GetLocationAtIndex (uint32_t index)
+{
+ return m_locations.GetByIndex(index);
+}
+
+BreakpointLocationSP
+Breakpoint::GetLocationSP (BreakpointLocation *bp_loc_ptr)
+{
+ assert (bp_loc_ptr->GetBreakpoint().GetID() == GetID());
+ return m_locations.FindByID(bp_loc_ptr->GetID());
+}
+
+
+// For each of the overall options we need to decide how they propagate to
+// the location options. This will determine the precedence of options on
+// the breakpoint vrs. its locations.
+
+// Disable at the breakpoint level should override the location settings.
+// That way you can conveniently turn off a whole breakpoint without messing
+// up the individual settings.
+
+void
+Breakpoint::SetEnabled (bool enable)
+{
+ m_options.SetEnabled(enable);
+ if (enable)
+ m_locations.ResolveAllBreakpointSites();
+ else
+ m_locations.ClearAllBreakpointSites();
+}
+
+bool
+Breakpoint::IsEnabled ()
+{
+ return m_options.IsEnabled();
+}
+
+void
+Breakpoint::SetIgnoreCount (int32_t n)
+{
+ m_options.SetIgnoreCount(n);
+}
+
+int32_t
+Breakpoint::GetIgnoreCount () const
+{
+ return m_options.GetIgnoreCount();
+}
+
+void
+Breakpoint::SetThreadID (lldb::tid_t thread_id)
+{
+ m_options.SetThreadID(thread_id);
+}
+
+lldb::tid_t
+Breakpoint::GetThreadID ()
+{
+ return m_options.GetThreadID();
+}
+
+// This function is used when "baton" doesn't need to be freed
+void
+Breakpoint::SetCallback (BreakpointHitCallback callback, void *baton, bool is_synchronous)
+{
+ // 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);
+}
+
+// This function is used when a baton needs to be freed and therefore is
+// contained in a "Baton" subclass.
+void
+Breakpoint::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous)
+{
+ m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
+}
+
+void
+Breakpoint::ClearCallback ()
+{
+ m_options.ClearCallback ();
+}
+
+bool
+Breakpoint::InvokeCallback (StoppointCallbackContext *context, break_id_t bp_loc_id)
+{
+ return m_options.InvokeCallback (context, GetID(), bp_loc_id);
+}
+
+BreakpointOptions *
+Breakpoint::GetOptions ()
+{
+ return &m_options;
+}
+
+void
+Breakpoint::ResolveBreakpoint ()
+{
+ if (m_resolver_sp)
+ m_resolver_sp->ResolveBreakpoint(*m_filter_sp);
+}
+
+void
+Breakpoint::ResolveBreakpointInModules (ModuleList &module_list)
+{
+ if (m_resolver_sp)
+ m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
+}
+
+void
+Breakpoint::ClearAllBreakpointSites ()
+{
+ m_locations.ClearAllBreakpointSites();
+}
+
+//----------------------------------------------------------------------
+// ModulesChanged: Pass in a list of new modules, and
+//----------------------------------------------------------------------
+
+void
+Breakpoint::ModulesChanged (ModuleList &module_list, bool load)
+{
+ if (load)
+ {
+ // The logic for handling new modules is:
+ // 1) If the filter rejects this module, then skip it.
+ // 2) Run through the current location list and if there are any locations
+ // for that module, we mark the module as "seen" and we don't try to re-resolve
+ // breakpoint locations for that module.
+ // However, we do add breakpoint sites to these locations if needed.
+ // 3) If we don't see this module in our breakpoint location list, call ResolveInModules.
+
+ ModuleList new_modules; // We'll stuff the "unseen" modules in this list, and then resolve
+ // them after the locations pass. Have to do it this way because
+ // resolving breakpoints will add new locations potentially.
+
+ for (int i = 0; i < module_list.GetSize(); i++)
+ {
+ bool seen = false;
+ ModuleSP module_sp (module_list.GetModuleAtIndex (i));
+ Module *module = module_sp.get();
+ if (!m_filter_sp->ModulePasses (module_sp))
+ continue;
+
+ for (int i = 0; i < m_locations.GetSize(); i++)
+ {
+ BreakpointLocationSP break_loc = m_locations.GetByIndex(i);
+ const Section *section = break_loc->GetAddress().GetSection();
+ if (section == NULL || section->GetModule() == module)
+ {
+ if (!seen)
+ seen = true;
+
+ if (!break_loc->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());
+ }
+ }
+ }
+
+ if (!seen)
+ new_modules.AppendInNeeded (module_sp);
+
+ }
+ if (new_modules.GetSize() > 0)
+ {
+ ResolveBreakpointInModules(new_modules);
+ }
+ }
+ else
+ {
+ // Go through the currently set locations and if any have breakpoints in
+ // the module list, then remove their breakpoint sites.
+ // FIXME: Think about this... Maybe it's better to delete the locations?
+ // Are we sure that on load-unload-reload the module pointer will remain
+ // the same? Or do we need to do an equality on modules that is an
+ // "equivalence"???
+
+ for (int i = 0; i < module_list.GetSize(); i++)
+ {
+ ModuleSP module_sp (module_list.GetModuleAtIndex (i));
+ if (!m_filter_sp->ModulePasses (module_sp))
+ continue;
+
+ for (int i = 0; i < m_locations.GetSize(); i++)
+ {
+ BreakpointLocationSP break_loc = m_locations.GetByIndex(i);
+ const Section *section = break_loc->GetAddress().GetSection();
+ if (section)
+ {
+ if (section->GetModule() == module_sp.get())
+ break_loc->ClearBreakpointSite();
+ }
+// else
+// {
+// Address temp_addr;
+// if (module->ResolveLoadAddress(break_loc->GetLoadAddress(), m_target->GetProcess(), temp_addr))
+// break_loc->ClearBreakpointSite();
+// }
+ }
+ }
+ }
+}
+
+void
+Breakpoint::Dump (Stream *)
+{
+}
+
+size_t
+Breakpoint::GetNumResolvedLocations() const
+{
+ // Return the number of breakpoints that are actually resolved and set
+ // down in the inferior process.
+ return m_locations.GetNumResolvedLocations();
+}
+
+size_t
+Breakpoint::GetNumLocations() const
+{
+ return m_locations.GetSize();
+}
+
+void
+Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_locations)
+{
+ assert (s != NULL);
+ StreamString filter_strm;
+
+
+ s->Printf("%i ", GetID());
+ GetResolverDescription (s);
+ GetFilterDescription (&filter_strm);
+ if (filter_strm.GetString().compare ("No Filter") != 0)
+ {
+ s->Printf (", ");
+ GetFilterDescription (s);
+ }
+
+ const uint32_t num_locations = GetNumLocations ();
+ const uint32_t num_resolved_locations = GetNumResolvedLocations ();
+
+ switch (level)
+ {
+ case lldb::eDescriptionLevelBrief:
+ case lldb::eDescriptionLevelFull:
+ if (num_locations > 0)
+ {
+ s->Printf(" with %u location%s", num_locations, num_locations > 1 ? "s" : "");
+ if (num_resolved_locations > 0)
+ s->Printf(" (%u resolved)", num_resolved_locations);
+ s->PutChar(';');
+ }
+ else
+ {
+ s->Printf(" with 0 locations (Pending Breakpoint).");
+ }
+
+ if (level == lldb::eDescriptionLevelFull)
+ {
+ Baton *baton = GetOptions()->GetBaton();
+ if (baton)
+ {
+ s->EOL ();
+ s->Indent();
+ baton->GetDescription(s, level);
+ }
+ }
+ break;
+
+ case lldb::eDescriptionLevelVerbose:
+ // Verbose mode does a debug dump of the breakpoint
+ Dump (s);
+ Baton *baton = GetOptions()->GetBaton();
+ if (baton)
+ {
+ s->EOL ();
+ s->Indent();
+ baton->GetDescription(s, level);
+ }
+ break;
+ }
+
+ if (show_locations)
+ {
+ s->EOL();
+ s->IndentMore();
+ for (int i = 0; i < GetNumLocations(); ++i)
+ {
+ BreakpointLocation *loc = GetLocationAtIndex(i).get();
+ loc->GetDescription(s, level);
+ s->EOL();
+ }
+ s->IndentLess();
+
+ }
+}
+
+Breakpoint::BreakpointEventData::BreakpointEventData (Breakpoint::BreakpointEventData::EventSubType sub_type, BreakpointSP &new_breakpoint_sp) :
+ EventData (),
+ m_sub_type (sub_type),
+ m_new_breakpoint_sp (new_breakpoint_sp)
+{
+}
+
+Breakpoint::BreakpointEventData::~BreakpointEventData ()
+{
+}
+
+const ConstString &
+Breakpoint::BreakpointEventData::GetFlavorString ()
+{
+ static ConstString g_flavor ("Breakpoint::BreakpointEventData");
+ return g_flavor;
+}
+
+const ConstString &
+Breakpoint::BreakpointEventData::GetFlavor () const
+{
+ return BreakpointEventData::GetFlavorString ();
+}
+
+
+BreakpointSP &
+Breakpoint::BreakpointEventData::GetBreakpoint ()
+{
+ return m_new_breakpoint_sp;
+}
+
+Breakpoint::BreakpointEventData::EventSubType
+Breakpoint::BreakpointEventData::GetSubType () const
+{
+ return m_sub_type;
+}
+
+void
+Breakpoint::BreakpointEventData::Dump (Stream *s) const
+{
+}
+
+Breakpoint::BreakpointEventData *
+Breakpoint::BreakpointEventData::GetEventDataFromEvent (const EventSP &event_sp)
+{
+ if (event_sp)
+ {
+ EventData *event_data = event_sp->GetData();
+ if (event_data && event_data->GetFlavor() == BreakpointEventData::GetFlavorString())
+ return static_cast <BreakpointEventData *> (event_sp->GetData());
+ }
+ return NULL;
+}
+
+Breakpoint::BreakpointEventData::EventSubType
+Breakpoint::BreakpointEventData::GetSubTypeFromEvent (const EventSP &event_sp)
+{
+ BreakpointEventData *data = GetEventDataFromEvent (event_sp);
+
+ if (data == NULL)
+ return eBreakpointInvalidType;
+ else
+ return data->GetSubType();
+}
+
+BreakpointSP
+Breakpoint::BreakpointEventData::GetBreakpointFromEvent (const EventSP &event_sp)
+{
+ BreakpointEventData *data = GetEventDataFromEvent (event_sp);
+
+ if (data == NULL)
+ {
+ BreakpointSP ret_val;
+ return ret_val;
+ }
+ else
+ return data->GetBreakpoint();
+}
+
+
+void
+Breakpoint::GetResolverDescription (Stream *s)
+{
+ if (m_resolver_sp)
+ m_resolver_sp->GetDescription (s);
+}
+
+void
+Breakpoint::GetFilterDescription (Stream *s)
+{
+ m_filter_sp->GetDescription (s);
+}
+
+const BreakpointSP
+Breakpoint::GetSP ()
+{
+ return m_target.GetBreakpointList().FindBreakpointByID (GetID());
+}
diff --git a/lldb/source/Breakpoint/BreakpointID.cpp b/lldb/source/Breakpoint/BreakpointID.cpp
new file mode 100644
index 00000000000..691e5c07523
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointID.cpp
@@ -0,0 +1,120 @@
+//===-- BreakpointID.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/BreakpointID.h"
+#include "lldb/Breakpoint/Breakpoint.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+BreakpointID::BreakpointID (break_id_t bp_id, break_id_t loc_id) :
+ m_break_id (bp_id),
+ m_location_id (loc_id)
+{
+}
+
+BreakpointID::~BreakpointID ()
+{
+}
+
+const char *BreakpointID::g_range_specifiers[] = { "-", "to", "To", "TO", NULL };
+
+// Tells whether or not STR is valid to use between two strings representing breakpoint IDs, to
+// indicate a range of breakpoint IDs. This is broken out into a separate function so that we can
+// easily change or add to the format for specifying ID ranges at a later date.
+
+bool
+BreakpointID::IsRangeIdentifier (const char *str)
+{
+ int specifier_count = 0;
+ for (int i = 0; g_range_specifiers[i] != NULL; ++i)
+ ++specifier_count;
+
+ for (int i = 0; i < specifier_count; ++i)
+ {
+ if (strcmp (g_range_specifiers[i], str) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+bool
+BreakpointID::IsValidIDExpression (const char *str)
+{
+ break_id_t bp_id;
+ break_id_t loc_id;
+ BreakpointID::ParseCanonicalReference (str, &bp_id, &loc_id);
+
+ if (bp_id == LLDB_INVALID_BREAK_ID)
+ return false;
+ else
+ return true;
+}
+
+void
+BreakpointID::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+ if (level == eDescriptionLevelVerbose)
+ s->Printf("%p BreakpointID:", this);
+
+ if (m_break_id == LLDB_INVALID_BREAK_ID)
+ s->PutCString ("<invalid>");
+ else if (m_location_id == LLDB_INVALID_BREAK_ID)
+ s->Printf("%i", m_break_id);
+ else
+ s->Printf("%i.%i", m_break_id, m_location_id);
+}
+
+void
+BreakpointID::GetCanonicalReference (Stream *s, break_id_t bp_id, break_id_t loc_id)
+{
+ if (bp_id == LLDB_INVALID_BREAK_ID)
+ s->PutCString ("<invalid>");
+ else if (loc_id == LLDB_INVALID_BREAK_ID)
+ s->Printf("%i", bp_id);
+ else
+ s->Printf("%i.%i", bp_id, loc_id);
+}
+
+bool
+BreakpointID::ParseCanonicalReference (const char *input, break_id_t *break_id_ptr, break_id_t *break_loc_id_ptr)
+{
+ *break_id_ptr = LLDB_INVALID_BREAK_ID;
+ *break_loc_id_ptr = LLDB_INVALID_BREAK_ID;
+
+ if (input == NULL || *input == '\0')
+ return false;
+
+ const char *format = "%i%n.%i%n";
+ int chars_consumed_1 = 0;
+ int chars_consumed_2 = 0;
+ int n_items_parsed = ::sscanf (input,
+ format,
+ break_id_ptr, // %i parse the breakpoint ID
+ &chars_consumed_1, // %n gets the number of characters parsed so far
+ break_loc_id_ptr, // %i parse the breakpoint location ID
+ &chars_consumed_2); // %n gets the number of characters parsed so far
+
+ if ((n_items_parsed == 1 && input[chars_consumed_1] == '\0') ||
+ (n_items_parsed == 2 && input[chars_consumed_2] == '\0'))
+ return true;
+
+ // Badly formatted canonical reference.
+ *break_id_ptr = LLDB_INVALID_BREAK_ID;
+ *break_loc_id_ptr = LLDB_INVALID_BREAK_ID;
+ return false;
+}
+
diff --git a/lldb/source/Breakpoint/BreakpointIDList.cpp b/lldb/source/Breakpoint/BreakpointIDList.cpp
new file mode 100644
index 00000000000..895f1b1e3f4
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointIDList.cpp
@@ -0,0 +1,348 @@
+//===-- BreakpointIDList.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointIDList.h"
+
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Core/Args.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// class BreakpointIDList
+//----------------------------------------------------------------------
+
+BreakpointIDList::BreakpointIDList () :
+m_invalid_id (LLDB_INVALID_BREAK_ID, LLDB_INVALID_BREAK_ID)
+{
+}
+
+BreakpointIDList::~BreakpointIDList ()
+{
+}
+
+int
+BreakpointIDList::Size()
+{
+ return m_breakpoint_ids.size();
+}
+
+BreakpointID &
+BreakpointIDList::GetBreakpointIDAtIndex (int index)
+{
+ if (index < m_breakpoint_ids.size())
+ return m_breakpoint_ids[index];
+ else
+ return m_invalid_id;
+}
+
+bool
+BreakpointIDList::RemoveBreakpointIDAtIndex (int index)
+{
+ bool success = false;
+ if (index < m_breakpoint_ids.size())
+ {
+ BreakpointIDArray::iterator pos;
+ int i;
+
+ for (pos = m_breakpoint_ids.begin(), i = 0; i != index && pos != m_breakpoint_ids.end(); ++pos, ++i);
+ assert (i == index);
+ if (pos != m_breakpoint_ids.end())
+ {
+ m_breakpoint_ids.erase (pos);
+ success = true;
+ }
+ }
+ return success;
+}
+
+void
+BreakpointIDList::Clear()
+{
+ m_breakpoint_ids.clear ();
+}
+
+bool
+BreakpointIDList::AddBreakpointID (BreakpointID bp_id)
+{
+ m_breakpoint_ids.push_back (bp_id);
+
+ return true; // We don't do any verification in this function, so always return true.
+}
+
+bool
+BreakpointIDList::AddBreakpointID (const char *bp_id_str)
+{
+ BreakpointID temp_bp_id;
+ break_id_t bp_id;
+ break_id_t loc_id;
+
+ bool success = BreakpointID::ParseCanonicalReference (bp_id_str, &bp_id, &loc_id);
+
+ if (success)
+ {
+ temp_bp_id.SetID (bp_id, loc_id);
+ m_breakpoint_ids.push_back (temp_bp_id);
+ }
+
+ return success;
+}
+
+bool
+BreakpointIDList::FindBreakpointID (BreakpointID &bp_id, int *position)
+{
+ bool success = false;
+ BreakpointIDArray::iterator tmp_pos;
+
+ for (int i = 0; i < m_breakpoint_ids.size(); ++i)
+ {
+ BreakpointID tmp_id = m_breakpoint_ids[i];
+ if (tmp_id.GetBreakpointID() == bp_id.GetBreakpointID()
+ && tmp_id.GetLocationID() == bp_id.GetLocationID())
+ {
+ success = true;
+ *position = i;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool
+BreakpointIDList::FindBreakpointID (const char *bp_id_str, int *position)
+{
+ BreakpointID temp_bp_id;
+ break_id_t bp_id;
+ break_id_t loc_id;
+
+ if (BreakpointID::ParseCanonicalReference (bp_id_str, &bp_id, &loc_id))
+ {
+ temp_bp_id.SetID (bp_id, loc_id);
+ return FindBreakpointID (temp_bp_id, position);
+ }
+ else
+ return false;
+}
+
+void
+BreakpointIDList::InsertStringArray (const char **string_array, int array_size, CommandReturnObject &result)
+{
+ if (string_array == NULL)
+ return;
+
+ for (int i = 0; i < array_size; ++i)
+ {
+ break_id_t bp_id;
+ break_id_t loc_id;
+
+ if (BreakpointID::ParseCanonicalReference (string_array[i], &bp_id, &loc_id))
+ {
+ if (bp_id != LLDB_INVALID_BREAK_ID)
+ {
+ BreakpointID temp_bp_id(bp_id, loc_id);
+ m_breakpoint_ids.push_back (temp_bp_id);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", string_array[i]);
+ result.SetStatus (eReturnStatusFailed);
+ return;
+ }
+ }
+ }
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+}
+
+
+// This function takes OLD_ARGS, which is usually the result of breaking the command string arguments into
+// an array of space-separated strings, and searches through the arguments for any breakpoint ID range specifiers.
+// Any string in the array that is not part of an ID range specifier is copied directly into NEW_ARGS. If any
+// ID range specifiers are found, the range is interpreted and a list of canonical breakpoint IDs corresponding to
+// all the current breakpoints and locations in the range are added to NEW_ARGS. When this function is done,
+// NEW_ARGS should be a copy of OLD_ARGS, with and ID range specifiers replaced by the members of the range.
+
+void
+BreakpointIDList::FindAndReplaceIDRanges (Args &old_args, Target *target, CommandReturnObject &result,
+ Args &new_args)
+{
+ char *range_start;
+ const char *range_end;
+ const char *current_arg;
+ int num_old_args = old_args.GetArgumentCount();
+
+ for (int i = 0; i < num_old_args; ++i)
+ {
+ bool is_range = false;
+ current_arg = old_args.GetArgumentAtIndex (i);
+
+ int range_start_len = 0;
+ int range_end_pos = 0;
+ if (BreakpointIDList::StringContainsIDRangeExpression (current_arg, &range_start_len, &range_end_pos))
+ {
+ is_range = true;
+ range_start = (char *) malloc (range_start_len + 1);
+ strncpy (range_start, current_arg, range_start_len);
+ range_start[range_start_len] = '\0';
+ range_end = current_arg + range_end_pos;
+ }
+ else if ((i + 2 < num_old_args)
+ && BreakpointID::IsRangeIdentifier (old_args.GetArgumentAtIndex (i+1))
+ && BreakpointID::IsValidIDExpression (current_arg)
+ && BreakpointID::IsValidIDExpression (old_args.GetArgumentAtIndex (i+2)))
+ {
+ range_start = (char *) current_arg;
+ range_end = old_args.GetArgumentAtIndex (i+2);
+ is_range = true;
+ i = i+2;
+ }
+
+ if (is_range)
+ {
+ break_id_t start_bp_id;
+ break_id_t end_bp_id;
+ break_id_t start_loc_id;
+ break_id_t end_loc_id;
+
+ BreakpointID::ParseCanonicalReference (range_start, &start_bp_id, &start_loc_id);
+ BreakpointID::ParseCanonicalReference (range_end, &end_bp_id, &end_loc_id);
+
+ if ((start_bp_id == LLDB_INVALID_BREAK_ID)
+ || (! target->GetBreakpointByID (start_bp_id)))
+ {
+ new_args.Clear();
+ result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_start);
+ result.SetStatus (eReturnStatusFailed);
+ return;
+ }
+
+ if ((end_bp_id == LLDB_INVALID_BREAK_ID)
+ || (! target->GetBreakpointByID (end_bp_id)))
+ {
+ new_args.Clear();
+ result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_end);
+ result.SetStatus (eReturnStatusFailed);
+ return;
+ }
+
+ // We have valid range starting & ending breakpoint IDs. Go through all the breakpoints in the
+ // target and find all the breakpoints that fit into this range, and add them to new_args.
+
+ const BreakpointList& breakpoints = target->GetBreakpointList();
+ size_t num_breakpoints = breakpoints.GetSize();
+ for (int j = 0; j < num_breakpoints; ++j)
+ {
+ Breakpoint *breakpoint = breakpoints.GetBreakpointByIndex (j).get();
+ break_id_t cur_bp_id = breakpoint->GetID();
+
+ if ((cur_bp_id < start_bp_id) || (cur_bp_id > end_bp_id))
+ continue;
+
+ size_t num_locations = breakpoint->GetNumLocations();
+
+ if ((cur_bp_id == start_bp_id) && (start_loc_id != LLDB_INVALID_BREAK_ID))
+ {
+ for (int k = 0; k < num_locations; ++k)
+ {
+ BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get();
+ if (bp_loc->GetID() >= start_loc_id)
+ {
+ StreamString canonical_id_str;
+ BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID());
+ new_args.AppendArgument (canonical_id_str.GetData());
+ }
+ }
+ }
+ else if ((cur_bp_id == end_bp_id) && (end_loc_id != LLDB_INVALID_BREAK_ID))
+ {
+ for (int k = 0; k < num_locations; ++k)
+ {
+ BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get();
+ if (bp_loc->GetID() <= end_loc_id)
+ {
+ StreamString canonical_id_str;
+ BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID());
+ new_args.AppendArgument (canonical_id_str.GetData());
+ }
+ }
+ }
+ else
+ {
+ StreamString canonical_id_str;
+ BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, LLDB_INVALID_BREAK_ID);
+ new_args.AppendArgument (canonical_id_str.GetData());
+ }
+ }
+ }
+ else // else is_range was false
+ {
+ new_args.AppendArgument (current_arg);
+ }
+ }
+
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ return;
+}
+
+//bool
+//BreakpointIDList::StringContainsIDRangeExpression (const char *in_string, const char **range_start,
+// const **range_end)
+bool
+BreakpointIDList::StringContainsIDRangeExpression (const char *in_string, int *range_start_len, int *range_end_pos)
+{
+ bool is_range_expression = false;
+ std::string arg_str = in_string;
+ std::string::size_type idx;
+ std::string::size_type start_pos = 0;
+
+ //*range_start = NULL;
+ //*range_end = NULL;
+ *range_start_len = 0;
+ *range_end_pos = 0;
+
+ int specifiers_size = 0;
+ for (int i = 0; BreakpointID::g_range_specifiers[i] != NULL; ++i)
+ ++specifiers_size;
+
+ for (int i = 0; i < specifiers_size && !is_range_expression; ++i)
+ {
+ const char *specifier_str = BreakpointID::g_range_specifiers[i];
+ int len = strlen (specifier_str);
+ idx = arg_str.find (BreakpointID::g_range_specifiers[i]);
+ if (idx != std::string::npos)
+ {
+ *range_start_len = idx - start_pos;
+ std::string start_str = arg_str.substr (start_pos, *range_start_len);
+ if (idx + len < arg_str.length())
+ {
+ *range_end_pos = idx + len;
+ std::string end_str = arg_str.substr (*range_end_pos);
+ if (BreakpointID::IsValidIDExpression (start_str.c_str())
+ && BreakpointID::IsValidIDExpression (end_str.c_str()))
+ {
+ is_range_expression = true;
+ //*range_start = start_str;
+ //*range_end = end_str;
+ }
+ }
+ }
+ }
+
+ if (!is_range_expression)
+ {
+ *range_start_len = 0;
+ *range_end_pos = 0;
+ }
+
+ return is_range_expression;
+}
diff --git a/lldb/source/Breakpoint/BreakpointList.cpp b/lldb/source/Breakpoint/BreakpointList.cpp
new file mode 100644
index 00000000000..c10aa770b82
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointList.cpp
@@ -0,0 +1,198 @@
+//===-- BreakpointList.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointList.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb;
+using namespace lldb_private;
+
+BreakpointList::BreakpointList (bool is_internal) :
+ m_mutex (Mutex::eMutexTypeRecursive),
+ m_breakpoints(),
+ m_next_break_id (0),
+ m_is_internal (is_internal)
+{
+}
+
+BreakpointList::~BreakpointList()
+{
+}
+
+
+break_id_t
+BreakpointList::Add (BreakpointSP &bp)
+{
+ Mutex::Locker locker(m_mutex);
+ // Internal breakpoint IDs are negative, normal ones are positive
+ bp->SetID (m_is_internal ? --m_next_break_id : ++m_next_break_id);
+ m_breakpoints.push_back(bp);
+ return bp->GetID();
+}
+
+bool
+BreakpointList::Remove (break_id_t break_id)
+{
+ Mutex::Locker locker(m_mutex);
+ bp_collection::iterator pos = GetBreakpointIDIterator(break_id); // Predicate
+ if (pos != m_breakpoints.end())
+ {
+ m_breakpoints.erase(pos);
+ return true;
+ }
+ return false;
+}
+
+void
+BreakpointList::SetEnabledAll (bool enabled)
+{
+ Mutex::Locker locker(m_mutex);
+ bp_collection::iterator pos, end = m_breakpoints.end();
+ for (pos = m_breakpoints.begin(); pos != end; ++pos)
+ (*pos)->SetEnabled (enabled);
+}
+
+
+void
+BreakpointList::RemoveAll ()
+{
+ Mutex::Locker locker(m_mutex);
+ ClearAllBreakpointSites ();
+
+ m_breakpoints.erase (m_breakpoints.begin(), m_breakpoints.end());
+}
+
+class BreakpointIDMatches
+{
+public:
+ BreakpointIDMatches (break_id_t break_id) :
+ m_break_id(break_id)
+ {
+ }
+
+ bool operator() (const BreakpointSP &bp) const
+ {
+ return m_break_id == bp->GetID();
+ }
+
+private:
+ const break_id_t m_break_id;
+};
+
+BreakpointList::bp_collection::iterator
+BreakpointList::GetBreakpointIDIterator (break_id_t break_id)
+{
+ return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range
+ BreakpointIDMatches(break_id)); // Predicate
+}
+
+BreakpointList::bp_collection::const_iterator
+BreakpointList::GetBreakpointIDConstIterator (break_id_t break_id) const
+{
+ return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range
+ BreakpointIDMatches(break_id)); // Predicate
+}
+
+BreakpointSP
+BreakpointList::FindBreakpointByID (break_id_t break_id)
+{
+ Mutex::Locker locker(m_mutex);
+ BreakpointSP stop_sp;
+ bp_collection::iterator pos = GetBreakpointIDIterator(break_id);
+ if (pos != m_breakpoints.end())
+ stop_sp = *pos;
+
+ return stop_sp;
+}
+
+const BreakpointSP
+BreakpointList::FindBreakpointByID (break_id_t break_id) const
+{
+ Mutex::Locker locker(m_mutex);
+ BreakpointSP stop_sp;
+ bp_collection::const_iterator pos = GetBreakpointIDConstIterator(break_id);
+ if (pos != m_breakpoints.end())
+ stop_sp = *pos;
+
+ return stop_sp;
+}
+
+void
+BreakpointList::Dump (Stream *s) const
+{
+ Mutex::Locker locker(m_mutex);
+ s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+ s->Indent();
+ s->Printf("BreakpointList with %u Breakpoints:\n", (uint32_t)m_breakpoints.size());
+ s->IndentMore();
+ bp_collection::const_iterator pos;
+ bp_collection::const_iterator end = m_breakpoints.end();
+ for (pos = m_breakpoints.begin(); pos != end; ++pos)
+ (*pos)->Dump(s);
+ s->IndentLess();
+}
+
+
+BreakpointSP
+BreakpointList::GetBreakpointByIndex (uint32_t i)
+{
+ Mutex::Locker locker(m_mutex);
+ BreakpointSP stop_sp;
+ bp_collection::iterator end = m_breakpoints.end();
+ bp_collection::iterator pos;
+ uint32_t curr_i = 0;
+ for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
+ {
+ if (curr_i == i)
+ stop_sp = *pos;
+ }
+ return stop_sp;
+}
+
+const BreakpointSP
+BreakpointList::GetBreakpointByIndex (uint32_t i) const
+{
+ Mutex::Locker locker(m_mutex);
+ BreakpointSP stop_sp;
+ bp_collection::const_iterator end = m_breakpoints.end();
+ bp_collection::const_iterator pos;
+ uint32_t curr_i = 0;
+ for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
+ {
+ if (curr_i == i)
+ stop_sp = *pos;
+ }
+ return stop_sp;
+}
+
+void
+BreakpointList::UpdateBreakpoints (ModuleList& module_list, bool added)
+{
+ Mutex::Locker locker(m_mutex);
+ bp_collection::iterator end = m_breakpoints.end();
+ bp_collection::iterator pos;
+ for (pos = m_breakpoints.begin(); pos != end; ++pos)
+ (*pos)->ModulesChanged (module_list, added);
+
+}
+
+void
+BreakpointList::ClearAllBreakpointSites ()
+{
+ Mutex::Locker locker(m_mutex);
+ bp_collection::iterator end = m_breakpoints.end();
+ bp_collection::iterator pos;
+ for (pos = m_breakpoints.begin(); pos != end; ++pos)
+ (*pos)->ClearAllBreakpointSites ();
+
+}
diff --git a/lldb/source/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp
new file mode 100644
index 00000000000..5c0e81df381
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointLocation.cpp
@@ -0,0 +1,389 @@
+//===-- BreakpointLocation.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
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointID.h"
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/lldb-private-log.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+BreakpointLocation::BreakpointLocation
+(
+ break_id_t loc_id,
+ Breakpoint &owner,
+ Address &addr,
+ lldb::tid_t tid,
+ bool hardware
+) :
+ StoppointLocation (loc_id, addr.GetLoadAddress(owner.GetTarget().GetProcessSP().get()), tid, hardware),
+ m_address (addr),
+ m_owner (owner),
+ m_options_ap (),
+ m_bp_site_sp ()
+{
+}
+
+BreakpointLocation::~BreakpointLocation()
+{
+ ClearBreakpointSite();
+}
+
+lldb::addr_t
+BreakpointLocation::GetLoadAddress ()
+{
+ return m_address.GetLoadAddress(m_owner.GetTarget().GetProcessSP().get());
+}
+
+Address &
+BreakpointLocation::GetAddress ()
+{
+ return m_address;
+}
+
+Breakpoint &
+BreakpointLocation::GetBreakpoint ()
+{
+ return m_owner;
+}
+
+bool
+BreakpointLocation::IsEnabled ()
+{
+ if (!m_owner.IsEnabled())
+ return false;
+ else if (m_options_ap.get() != NULL)
+ return m_options_ap->IsEnabled();
+ else
+ return true;
+}
+
+void
+BreakpointLocation::SetEnabled (bool enabled)
+{
+ GetLocationOptions()->SetEnabled(enabled);
+ if (enabled)
+ {
+ ResolveBreakpointSite();
+ }
+ else
+ {
+ ClearBreakpointSite();
+ }
+}
+
+void
+BreakpointLocation::SetThreadID (lldb::tid_t thread_id)
+{
+ GetLocationOptions()->SetThreadID(thread_id);
+}
+
+lldb::tid_t
+BreakpointLocation::GetThreadID ()
+{
+ return GetOptionsNoCopy()->GetThreadID();
+}
+
+bool
+BreakpointLocation::InvokeCallback (StoppointCallbackContext *context)
+{
+ bool owner_result;
+
+ owner_result = m_owner.InvokeCallback (context, GetID());
+ if (owner_result == false)
+ return false;
+ else if (m_options_ap.get() != NULL)
+ return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID());
+ else
+ return true;
+}
+
+void
+BreakpointLocation::SetCallback (BreakpointHitCallback callback, void *baton,
+ bool is_synchronous)
+{
+ // 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);
+}
+
+void
+BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &baton_sp,
+ bool is_synchronous)
+{
+ GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous);
+}
+
+void
+BreakpointLocation::ClearCallback ()
+{
+ GetLocationOptions()->ClearCallback();
+}
+
+int32_t
+BreakpointLocation::GetIgnoreCount ()
+{
+ return GetOptionsNoCopy()->GetIgnoreCount();
+}
+
+void
+BreakpointLocation::SetIgnoreCount (int32_t n)
+{
+ GetLocationOptions()->SetIgnoreCount(n);
+}
+
+BreakpointOptions *
+BreakpointLocation::GetOptionsNoCopy ()
+{
+ if (m_options_ap.get() != NULL)
+ return m_options_ap.get();
+ else
+ return m_owner.GetOptions ();
+}
+
+BreakpointOptions *
+BreakpointLocation::GetLocationOptions ()
+{
+ if (m_options_ap.get() == NULL)
+ m_options_ap.reset(new BreakpointOptions (*m_owner.GetOptions ()));
+
+ return m_options_ap.get();
+}
+
+// RETURNS - true if we should stop at this breakpoint, false if we
+// should continue.
+
+bool
+BreakpointLocation::ShouldStop (StoppointCallbackContext *context)
+{
+ bool should_stop = true;
+
+ m_hit_count++;
+
+ if (!IsEnabled())
+ return false;
+
+ if (GetThreadID() != LLDB_INVALID_THREAD_ID
+ && context->context.thread->GetID() != GetThreadID())
+ return false;
+
+ if (m_hit_count <= GetIgnoreCount())
+ return false;
+
+ // Tell if the callback is synchronous here.
+ context->is_synchronous = true;
+ should_stop = InvokeCallback (context);
+
+ if (should_stop)
+ {
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+ if (log)
+ {
+ StreamString s;
+ GetDescription (&s, lldb::eDescriptionLevelVerbose);
+ log->Printf ("Hit breakpoint location: %s\n", s.GetData());
+ }
+ }
+ return should_stop;
+}
+
+bool
+BreakpointLocation::IsResolved () const
+{
+ return m_bp_site_sp.get() != NULL;
+}
+
+bool
+BreakpointLocation::ResolveBreakpointSite ()
+{
+ if (m_bp_site_sp)
+ return true;
+
+ Process* process = m_owner.GetTarget().GetProcessSP().get();
+ if (process == NULL)
+ return false;
+
+ BreakpointLocationSP myself_sp(m_owner.GetLocationSP (this));
+
+ lldb::user_id_t new_id = process->CreateBreakpointSite (myself_sp, false);
+
+ if (new_id == LLDB_INVALID_UID)
+ {
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+ if (log)
+ log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n",
+ m_address.GetLoadAddress(process));
+ return false;
+ }
+
+ return true;
+}
+
+bool
+BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp)
+{
+ m_bp_site_sp = bp_site_sp;
+ return true;
+}
+
+bool
+BreakpointLocation::ClearBreakpointSite ()
+{
+ if (m_bp_site_sp.get())
+ {
+ m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(), GetID(), m_bp_site_sp);
+ m_bp_site_sp.reset();
+ return true;
+ }
+ return false;
+}
+
+void
+BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+ SymbolContext sc;
+ s->Indent();
+ BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
+
+ if (level == lldb::eDescriptionLevelBrief)
+ return;
+
+ s->PutCString(": ");
+
+ if (level == lldb::eDescriptionLevelVerbose)
+ s->IndentMore();
+
+ if (m_address.IsSectionOffset())
+ {
+ m_address.CalculateSymbolContext(&sc);
+
+ if (level == lldb::eDescriptionLevelFull)
+ {
+ s->PutCString("where = ");
+ sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address);
+ }
+ else
+ {
+ if (sc.module_sp)
+ {
+ s->EOL();
+ s->Indent("module = ");
+ sc.module_sp->GetFileSpec().Dump (s);
+ }
+
+ if (sc.comp_unit != NULL)
+ {
+ s->EOL();
+ s->Indent("compile unit = ");
+ dynamic_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
+
+ if (sc.function != NULL)
+ {
+ s->EOL();
+ s->Indent("function = ");
+ s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>"));
+ }
+
+ if (sc.line_entry.line > 0)
+ {
+ s->EOL();
+ s->Indent("location = ");
+ sc.line_entry.DumpStopContext (s);
+ }
+
+ }
+ else
+ {
+ // If we don't have a comp unit, see if we have a symbol we can print.
+ if (sc.symbol)
+ {
+ s->EOL();
+ s->Indent("symbol = ");
+ s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
+ }
+ }
+ }
+ }
+
+ if (level == lldb::eDescriptionLevelVerbose)
+ {
+ s->EOL();
+ s->Indent();
+ }
+ s->Printf ("%saddress = ", (level == lldb::eDescriptionLevelFull && m_address.IsSectionOffset()) ? ", " : "");
+ ExecutionContextScope *exe_scope = NULL;
+ Target *target = &m_owner.GetTarget();
+ if (target)
+ exe_scope = target->GetProcessSP().get();
+ if (exe_scope == NULL)
+ exe_scope = target;
+
+ m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
+
+ if (level == lldb::eDescriptionLevelVerbose)
+ {
+ s->EOL();
+ s->Indent();
+ s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
+
+ s->Indent();
+ s->Printf("enabled = %s\n", IsEnabled() ? "true" : "false");
+
+ s->Indent();
+ s->Printf ("hit count = %-4u\n", GetHitCount());
+
+ if (m_options_ap.get())
+ {
+ Baton *baton = m_options_ap->GetBaton();
+ if (baton)
+ {
+ s->Indent();
+ baton->GetDescription (s, level);
+ s->EOL();
+ }
+ }
+ s->IndentLess();
+ }
+ else
+ {
+ s->Printf(", %sresolved, %s, hit count = %u",
+ (IsResolved() ? "" : "un"),
+ (IsEnabled() ? "enabled" : "disabled"),
+ GetHitCount());
+ }
+}
+
+void
+BreakpointLocation::Dump(Stream *s) const
+{
+ if (s == NULL)
+ return;
+
+ s->Printf("BreakpointLocation %u: tid = %4.4x load addr = 0x%8.8llx state = %s type = %s breakpoint hw_index = %i hit_count = %-4u ignore_count = %-4u",
+ GetID(),
+ m_tid,
+ (uint64_t) m_address.GetLoadAddress(m_owner.GetTarget().GetProcessSP().get()),
+ (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled",
+ IsHardware() ? "hardware" : "software",
+ GetHardwareIndex(),
+ GetHitCount(),
+ m_options_ap.get() ? m_options_ap->GetIgnoreCount() : m_owner.GetIgnoreCount());
+}
diff --git a/lldb/source/Breakpoint/BreakpointLocationCollection.cpp b/lldb/source/Breakpoint/BreakpointLocationCollection.cpp
new file mode 100644
index 00000000000..7b574263003
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointLocationCollection.cpp
@@ -0,0 +1,161 @@
+//===-- BreakpointLocationCollection.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/BreakpointLocationCollection.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointLocationList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// BreakpointLocationCollection constructor
+//----------------------------------------------------------------------
+BreakpointLocationCollection::BreakpointLocationCollection() :
+ m_break_loc_collection()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+BreakpointLocationCollection::~BreakpointLocationCollection()
+{
+}
+
+void
+BreakpointLocationCollection::Add(const BreakpointLocationSP &bp_loc)
+{
+ BreakpointLocationSP old_bp_loc = FindByIDPair (bp_loc->GetBreakpoint().GetID(), bp_loc->GetID());
+ if (!old_bp_loc.get())
+ m_break_loc_collection.push_back(bp_loc);
+}
+
+bool
+BreakpointLocationCollection::Remove (lldb::user_id_t bp_id, lldb::user_id_t bp_loc_id)
+{
+ collection::iterator pos = GetIDPairIterator(bp_id, bp_loc_id); // Predicate
+ if (pos != m_break_loc_collection.end())
+ {
+ m_break_loc_collection.erase(pos);
+ return true;
+ }
+ return false;
+
+}
+
+class BreakpointIDPairMatches
+{
+public:
+ BreakpointIDPairMatches (lldb::user_id_t break_id, lldb::user_id_t break_loc_id) :
+ m_break_id(break_id),
+ m_break_loc_id (break_loc_id)
+ {
+ }
+
+ bool operator() (const BreakpointLocationSP &bp_loc) const
+ {
+ return m_break_id == bp_loc->GetBreakpoint().GetID()
+ && m_break_loc_id == bp_loc->GetID();
+ }
+
+private:
+ const lldb::user_id_t m_break_id;
+ const lldb::user_id_t m_break_loc_id;
+};
+
+BreakpointLocationCollection::collection::iterator
+BreakpointLocationCollection::GetIDPairIterator (lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
+{
+ return std::find_if(m_break_loc_collection.begin(), m_break_loc_collection.end(), // Search full range
+ BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate
+}
+
+BreakpointLocationCollection::collection::const_iterator
+BreakpointLocationCollection::GetIDPairConstIterator (lldb::user_id_t break_id, lldb::user_id_t break_loc_id) const
+{
+ return std::find_if(m_break_loc_collection.begin(), m_break_loc_collection.end(), // Search full range
+ BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate
+}
+
+BreakpointLocationSP
+BreakpointLocationCollection::FindByIDPair (lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
+{
+ BreakpointLocationSP stop_sp;
+ collection::iterator pos = GetIDPairIterator(break_id, break_loc_id);
+ if (pos != m_break_loc_collection.end())
+ stop_sp = *pos;
+
+ return stop_sp;
+}
+
+const BreakpointLocationSP
+BreakpointLocationCollection::FindByIDPair (lldb::user_id_t break_id, lldb::user_id_t break_loc_id) const
+{
+ BreakpointLocationSP stop_sp;
+ collection::const_iterator pos = GetIDPairConstIterator(break_id, break_loc_id);
+ if (pos != m_break_loc_collection.end())
+ stop_sp = *pos;
+
+ return stop_sp;
+}
+
+BreakpointLocationSP
+BreakpointLocationCollection::GetByIndex (uint32_t i)
+{
+ BreakpointLocationSP stop_sp;
+ if (i >= 0 && i < m_break_loc_collection.size())
+ stop_sp = m_break_loc_collection[i];
+
+ return stop_sp;
+}
+
+const BreakpointLocationSP
+BreakpointLocationCollection::GetByIndex (uint32_t i) const
+{
+ BreakpointLocationSP stop_sp;
+ if (i >= 0 && i < m_break_loc_collection.size())
+ stop_sp = m_break_loc_collection[i];
+
+ return stop_sp;
+}
+
+bool
+BreakpointLocationCollection::ShouldStop (StoppointCallbackContext *context)
+{
+ bool shouldStop = false;
+
+ for (int i = 0; i < GetSize(); i++) {
+ bool one_result = GetByIndex(i)->ShouldStop(context);
+ if (one_result)
+ shouldStop = true;
+ }
+ return shouldStop;
+}
+
+void
+BreakpointLocationCollection::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+ collection::iterator pos,
+ begin = m_break_loc_collection.begin(),
+ end = m_break_loc_collection.end();
+
+ for (pos = begin; pos != end; ++pos)
+ {
+ if (pos != begin)
+ s->PutChar(' ');
+ (*pos)->GetDescription(s, level);
+ }
+}
diff --git a/lldb/source/Breakpoint/BreakpointLocationList.cpp b/lldb/source/Breakpoint/BreakpointLocationList.cpp
new file mode 100644
index 00000000000..d86a8cf4c47
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointLocationList.cpp
@@ -0,0 +1,305 @@
+//===-- 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::user_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::user_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::user_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::user_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::user_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::user_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::user_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::user_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::user_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::user_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;
+}
+
+
+static int
+FindLocationByAddress (Address *addr_ptr, const BreakpointLocationSP *bp_loc_sp_ptr)
+{
+ return Address::CompareModulePointerAndOffset(*addr_ptr, (*bp_loc_sp_ptr)->GetAddress());
+}
+
+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 >= 0 && 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 >= 0 && 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);
+ }
+}
+
diff --git a/lldb/source/Breakpoint/BreakpointOptions.cpp b/lldb/source/Breakpoint/BreakpointOptions.cpp
new file mode 100644
index 00000000000..4f664c4692f
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointOptions.cpp
@@ -0,0 +1,180 @@
+//===-- BreakpointOptions.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointOptions.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+bool
+BreakpointOptions::NullCallback (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
+{
+ return true;
+}
+
+//----------------------------------------------------------------------
+// BreakpointOptions constructor
+//----------------------------------------------------------------------
+BreakpointOptions::BreakpointOptions() :
+ m_callback (BreakpointOptions::NullCallback),
+ m_callback_is_synchronous (false),
+ m_callback_baton_sp (),
+ m_enabled (true),
+ m_ignore_count (0),
+ m_thread_id (LLDB_INVALID_THREAD_ID)
+{
+}
+
+//----------------------------------------------------------------------
+// BreakpointOptions copy constructor
+//----------------------------------------------------------------------
+BreakpointOptions::BreakpointOptions(const BreakpointOptions& rhs) :
+ m_callback (rhs.m_callback),
+ m_callback_baton_sp (rhs.m_callback_baton_sp),
+ m_callback_is_synchronous (rhs.m_callback_is_synchronous),
+ m_enabled (rhs.m_enabled),
+ m_ignore_count (rhs.m_ignore_count),
+ m_thread_id (rhs.m_thread_id)
+{
+}
+
+//----------------------------------------------------------------------
+// BreakpointOptions assignment operator
+//----------------------------------------------------------------------
+const BreakpointOptions&
+BreakpointOptions::operator=(const BreakpointOptions& rhs)
+{
+ m_callback = rhs.m_callback;
+ m_callback_baton_sp = rhs.m_callback_baton_sp;
+ m_callback_is_synchronous = rhs.m_callback_is_synchronous;
+ m_enabled = rhs.m_enabled;
+ m_ignore_count = rhs.m_ignore_count;
+ m_thread_id = rhs.m_thread_id;
+ return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+BreakpointOptions::~BreakpointOptions()
+{
+}
+
+//------------------------------------------------------------------
+// Callbacks
+//------------------------------------------------------------------
+void
+BreakpointOptions::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool callback_is_synchronous)
+{
+ m_callback_is_synchronous = callback_is_synchronous;
+ m_callback = callback;
+ m_callback_baton_sp = callback_baton_sp;
+}
+
+void
+BreakpointOptions::ClearCallback ()
+{
+ m_callback = NULL;
+ m_callback_baton_sp.reset();
+}
+
+Baton *
+BreakpointOptions::GetBaton ()
+{
+ return m_callback_baton_sp.get();
+}
+
+bool
+BreakpointOptions::InvokeCallback (StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id)
+{
+ if (m_callback && context->is_synchronous == IsCallbackSynchronous())
+ {
+ return m_callback (m_callback_baton_sp ? m_callback_baton_sp->m_data : NULL,
+ context,
+ break_id,
+ break_loc_id);
+ }
+ else
+ return true;
+}
+
+//------------------------------------------------------------------
+// Enabled/Ignore Count
+//------------------------------------------------------------------
+bool
+BreakpointOptions::IsEnabled () const
+{
+ return m_enabled;
+}
+
+void
+BreakpointOptions::SetEnabled (bool enabled)
+{
+ m_enabled = enabled;
+}
+
+int32_t
+BreakpointOptions::GetIgnoreCount () const
+{
+ return m_ignore_count;
+}
+
+void
+BreakpointOptions::SetIgnoreCount (int32_t n)
+{
+ m_ignore_count = n;
+}
+
+void
+BreakpointOptions::SetThreadID (lldb::tid_t thread_id)
+{
+ m_thread_id = thread_id;
+}
+
+lldb::tid_t
+BreakpointOptions::GetThreadID () const
+{
+ return m_thread_id;
+}
+
+
+
+void
+BreakpointOptions::CommandBaton::GetDescription (Stream *s, lldb::DescriptionLevel level) const
+{
+ s->Indent("Breakpoint commands:\n");
+ CommandData *data = (CommandData *)m_data;
+
+ s->IndentMore ();
+ if (data && data->user_source.GetSize() > 0)
+ {
+ const size_t num_strings = data->user_source.GetSize();
+ for (size_t i = 0; i < num_strings; ++i)
+ {
+ s->Indent(data->user_source.GetStringAtIndex(i));
+ s->EOL();
+ }
+ }
+ else
+ {
+ s->PutCString ("No commands.\n");
+ }
+ s->IndentLess ();
+}
+
diff --git a/lldb/source/Breakpoint/BreakpointResolver.cpp b/lldb/source/Breakpoint/BreakpointResolver.cpp
new file mode 100644
index 00000000000..e0fbfde7932
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointResolver.cpp
@@ -0,0 +1,60 @@
+//===-- BreakpointResolver.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointResolver.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Address.h"
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/SearchFilter.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/lldb-private-log.h"
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// BreakpointResolver:
+//----------------------------------------------------------------------
+BreakpointResolver::BreakpointResolver (Breakpoint *bkpt) :
+ m_breakpoint (bkpt)
+{
+}
+
+BreakpointResolver::~BreakpointResolver ()
+{
+
+}
+
+void
+BreakpointResolver::SetBreakpoint (Breakpoint *bkpt)
+{
+ m_breakpoint = bkpt;
+}
+
+void
+BreakpointResolver::ResolveBreakpointInModules (SearchFilter &filter, ModuleList &modules)
+{
+ filter.SearchInModuleList(*this, modules);
+}
+
+void
+BreakpointResolver::ResolveBreakpoint (SearchFilter &filter)
+{
+ filter.Search (*this);
+}
+
diff --git a/lldb/source/Breakpoint/BreakpointResolverAddress.cpp b/lldb/source/Breakpoint/BreakpointResolverAddress.cpp
new file mode 100644
index 00000000000..034ef601dc4
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointResolverAddress.cpp
@@ -0,0 +1,111 @@
+//===-- BreakpointResolverAddress.cpp ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointResolverAddress.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private-log.h"
+
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// BreakpointResolverAddress:
+//----------------------------------------------------------------------
+BreakpointResolverAddress::BreakpointResolverAddress
+(
+ Breakpoint *bkpt,
+ const Address &addr
+) :
+ BreakpointResolver (bkpt),
+ m_addr (addr)
+{
+}
+
+BreakpointResolverAddress::~BreakpointResolverAddress ()
+{
+
+}
+
+void
+BreakpointResolverAddress::ResolveBreakpoint (SearchFilter &filter)
+{
+ // The address breakpoint only takes once, so if we've already set it we're done.
+ if (m_breakpoint->GetNumLocations() > 0)
+ return;
+ else
+ BreakpointResolver::ResolveBreakpoint(filter);
+}
+
+void
+BreakpointResolverAddress::ResolveBreakpointInModules
+(
+ SearchFilter &filter,
+ ModuleList &modules
+)
+{
+ // The address breakpoint only takes once, so if we've already set it we're done.
+ if (m_breakpoint->GetNumLocations() > 0)
+ return;
+ else
+ BreakpointResolver::ResolveBreakpointInModules (filter, modules);
+}
+
+Searcher::CallbackReturn
+BreakpointResolverAddress::SearchCallback
+(
+ SearchFilter &filter,
+ SymbolContext &context,
+ Address *addr,
+ bool containing
+)
+{
+ assert (m_breakpoint != NULL);
+
+ if (filter.AddressPasses (m_addr))
+ {
+ BreakpointLocationSP bp_loc_sp(m_breakpoint->AddLocation(m_addr));
+ if (bp_loc_sp && !m_breakpoint->IsInternal())
+ {
+ StreamString s;
+ bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+ if (log)
+ log->Printf ("Added location: %s\n", s.GetData());
+ }
+ }
+ return Searcher::eCallbackReturnStop;
+}
+
+Searcher::Depth
+BreakpointResolverAddress::GetDepth()
+{
+ return Searcher::eDepthTarget;
+}
+
+void
+BreakpointResolverAddress::GetDescription (Stream *s)
+{
+ s->PutCString ("Address breakpoint: ");
+ m_addr.Dump(s, m_breakpoint->GetTarget().GetProcessSP().get(), Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
+}
+
+void
+BreakpointResolverAddress::Dump (Stream *s) const
+{
+
+}
diff --git a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp
new file mode 100644
index 00000000000..86e05964485
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp
@@ -0,0 +1,122 @@
+//===-- BreakpointResolverFileLine.cpp --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/lldb-private-log.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// BreakpointResolverFileLine:
+//----------------------------------------------------------------------
+BreakpointResolverFileLine::BreakpointResolverFileLine
+(
+ Breakpoint *bkpt,
+ const FileSpec &file_spec,
+ uint32_t line_no,
+ bool check_inlines
+) :
+ BreakpointResolver (bkpt),
+ m_file_spec (file_spec),
+ m_line_number (line_no),
+ m_inlines (check_inlines)
+{
+}
+
+BreakpointResolverFileLine::~BreakpointResolverFileLine ()
+{
+}
+
+Searcher::CallbackReturn
+BreakpointResolverFileLine::SearchCallback
+(
+ SearchFilter &filter,
+ SymbolContext &context,
+ Address *addr,
+ bool containing
+)
+{
+ SymbolContextList sc_list;
+ uint32_t sc_list_size;
+ CompileUnit *cu = context.comp_unit;
+
+ assert (m_breakpoint != NULL);
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+
+ sc_list_size = cu->ResolveSymbolContext (m_file_spec, m_line_number, m_inlines, false, eSymbolContextEverything, sc_list);
+ for (int i = 0; i < sc_list_size; i++)
+ {
+ SymbolContext sc;
+ if (sc_list.GetContextAtIndex(i, sc))
+ {
+ Address line_start = sc.line_entry.range.GetBaseAddress();
+ if (line_start.IsValid())
+ {
+ BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
+ if (log && bp_loc_sp && !m_breakpoint->IsInternal())
+ {
+ StreamString s;
+ bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
+ log->Printf ("Added location: %s\n", s.GetData());
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("error: Unable to set breakpoint at file address 0x%llx for %s:%d\n",
+ line_start.GetFileAddress(),
+ m_file_spec.GetFilename().AsCString("<Unknown>"),
+ m_line_number);
+ }
+ }
+ else
+ {
+#if 0
+ s << "error: Breakpoint at '" << pos->c_str() << "' isn't resolved yet: \n";
+ if (sc.line_entry.address.Dump(&s, Address::DumpStyleSectionNameOffset))
+ s.EOL();
+ if (sc.line_entry.address.Dump(&s, Address::DumpStyleSectionPointerOffset))
+ s.EOL();
+ if (sc.line_entry.address.Dump(&s, Address::DumpStyleFileAddress))
+ s.EOL();
+ if (sc.line_entry.address.Dump(&s, Address::DumpStyleLoadAddress))
+ s.EOL();
+#endif
+ }
+ }
+ return Searcher::eCallbackReturnContinue;
+}
+
+Searcher::Depth
+BreakpointResolverFileLine::GetDepth()
+{
+ return Searcher::eDepthCompUnit;
+}
+
+void
+BreakpointResolverFileLine::GetDescription (Stream *s)
+{
+ s->Printf ("File and line breakpoint - file: \"%s\" line: %u", m_file_spec.GetFilename().AsCString(), m_line_number);
+}
+
+void
+BreakpointResolverFileLine::Dump (Stream *s) const
+{
+
+}
+
diff --git a/lldb/source/Breakpoint/BreakpointResolverName.cpp b/lldb/source/Breakpoint/BreakpointResolverName.cpp
new file mode 100644
index 00000000000..b04bb8aef48
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointResolverName.cpp
@@ -0,0 +1,252 @@
+//===-- BreakpointResolverName.cpp ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointResolverName.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/lldb-private-log.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+BreakpointResolverName::BreakpointResolverName
+(
+ Breakpoint *bkpt,
+ const char *func_name,
+ Breakpoint::MatchType type
+) :
+ BreakpointResolver (bkpt),
+ m_func_name (func_name),
+ m_class_name (NULL),
+ m_regex (),
+ m_match_type (type)
+{
+ if (m_match_type == Breakpoint::Regexp)
+ {
+ if (!m_regex.Compile (m_func_name.AsCString()))
+ {
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+
+ if (log)
+ log->Warning ("function name regexp: \"%s\" did not compile.", m_func_name.AsCString());
+ }
+ }
+}
+
+BreakpointResolverName::BreakpointResolverName
+(
+ Breakpoint *bkpt,
+ RegularExpression &func_regex
+) :
+ BreakpointResolver (bkpt),
+ m_func_name (NULL),
+ m_class_name (NULL),
+ m_regex (func_regex),
+ m_match_type (Breakpoint::Regexp)
+{
+
+}
+
+BreakpointResolverName::BreakpointResolverName
+(
+ Breakpoint *bkpt,
+ const char *class_name,
+ const char *method,
+ Breakpoint::MatchType type
+) :
+ BreakpointResolver (bkpt),
+ m_func_name (method),
+ m_class_name (class_name),
+ m_regex (),
+ m_match_type (type)
+{
+
+}
+
+BreakpointResolverName::~BreakpointResolverName ()
+{
+}
+
+// FIXME: Right now we look at the module level, and call the module's "FindFunctions".
+// Greg says he will add function tables, maybe at the CompileUnit level to accelerate function
+// lookup. At that point, we should switch the depth to CompileUnit, and look in these tables.
+
+Searcher::CallbackReturn
+BreakpointResolverName::SearchCallback
+(
+ SearchFilter &filter,
+ SymbolContext &context,
+ Address *addr,
+ bool containing
+)
+{
+ SymbolContextList func_list;
+ SymbolContextList sym_list;
+
+ bool skip_prologue = true;
+ uint32_t i;
+ bool new_location;
+ SymbolContext sc;
+ Address break_addr;
+ assert (m_breakpoint != NULL);
+
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+
+ if (m_class_name)
+ {
+ if (log)
+ log->Warning ("Class/method function specification not supported yet.\n");
+ return Searcher::eCallbackReturnStop;
+ }
+
+ switch (m_match_type)
+ {
+ case Breakpoint::Exact:
+ if (context.module_sp)
+ {
+ context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list);
+ context.module_sp->FindFunctions (m_func_name, false, func_list);
+ }
+ break;
+ case Breakpoint::Regexp:
+ if (context.module_sp)
+ {
+ context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list);
+ context.module_sp->FindFunctions (m_regex, true, func_list);
+ }
+ break;
+ case Breakpoint::Glob:
+ if (log)
+ log->Warning ("glob is not supported yet.");
+ break;
+ }
+
+ // Remove any duplicates between the funcion list and the symbol list
+ if (func_list.GetSize())
+ {
+ for (i = 0; i < func_list.GetSize(); i++)
+ {
+ if (func_list.GetContextAtIndex(i, sc) == false)
+ continue;
+
+ if (sc.function == NULL)
+ continue;
+ uint32_t j = 0;
+ while (j < sym_list.GetSize())
+ {
+ SymbolContext symbol_sc;
+ if (sym_list.GetContextAtIndex(j, symbol_sc))
+ {
+ if (symbol_sc.symbol && symbol_sc.symbol->GetAddressRangePtr())
+ {
+ if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRangePtr()->GetBaseAddress())
+ {
+ sym_list.RemoveContextAtIndex(j);
+ continue; // Don't increment j
+ }
+ }
+ }
+
+ j++;
+ }
+ }
+
+ for (i = 0; i < func_list.GetSize(); i++)
+ {
+ if (func_list.GetContextAtIndex(i, sc))
+ {
+ if (sc.function)
+ {
+ break_addr = sc.function->GetAddressRange().GetBaseAddress();
+ if (skip_prologue)
+ {
+ const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
+ if (prologue_byte_size)
+ break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
+ }
+
+ if (filter.AddressPasses(break_addr))
+ {
+ BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
+ if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
+ {
+ if (log)
+ {
+ StreamString s;
+ bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
+ log->Printf ("Added location: %s\n", s.GetData());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < sym_list.GetSize(); i++)
+ {
+ if (sym_list.GetContextAtIndex(i, sc))
+ {
+ if (sc.symbol && sc.symbol->GetAddressRangePtr())
+ {
+ break_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress();
+
+ if (skip_prologue)
+ {
+ const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
+ if (prologue_byte_size)
+ break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
+ }
+
+ if (filter.AddressPasses(break_addr))
+ {
+ BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
+ if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
+ {
+ StreamString s;
+ bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
+ if (log)
+ log->Printf ("Added location: %s\n", s.GetData());
+ }
+ }
+ }
+ }
+ }
+ return Searcher::eCallbackReturnContinue;
+}
+
+Searcher::Depth
+BreakpointResolverName::GetDepth()
+{
+ return Searcher::eDepthModule;
+}
+
+void
+BreakpointResolverName::GetDescription (Stream *s)
+{
+ s->PutCString("Breakpoint by name: ");
+
+ if (m_match_type == Breakpoint::Regexp)
+ s->Printf("'%s' (regular expression)", m_regex.GetText());
+ else
+ s->Printf("'%s'", m_func_name.AsCString());
+}
+
+void
+BreakpointResolverName::Dump (Stream *s) const
+{
+
+}
+
diff --git a/lldb/source/Breakpoint/BreakpointSite.cpp b/lldb/source/Breakpoint/BreakpointSite.cpp
new file mode 100644
index 00000000000..cd0920d07c7
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointSite.cpp
@@ -0,0 +1,221 @@
+//===-- BreakpointSite.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointSite.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointSiteList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+BreakpointSite::BreakpointSite
+(
+ BreakpointSiteList *list,
+ BreakpointLocationSP& owner,
+ lldb::addr_t addr,
+ lldb::tid_t tid,
+ bool use_hardware
+) :
+ StoppointLocation(GetNextID(), addr, tid, use_hardware),
+ m_type (eSoftware), // Process subclasses need to set this correctly using SetType()
+ m_saved_opcode(),
+ m_trap_opcode(),
+ m_enabled(false), // Need to create it disabled, so the first enable turns it on.
+ m_owners()
+{
+ m_owners.Add(owner);
+}
+
+BreakpointSite::~BreakpointSite()
+{
+ BreakpointLocationSP bp_loc_sp;
+ for (int i = 0; i < m_owners.GetSize(); i++)
+ {
+ m_owners.GetByIndex(i)->ClearBreakpointSite();
+ }
+}
+
+break_id_t
+BreakpointSite::GetNextID()
+{
+ static break_id_t g_next_id = 0;
+ return ++g_next_id;
+}
+
+// RETURNS - true if we should stop at this breakpoint, false if we
+// should continue.
+
+bool
+BreakpointSite::ShouldStop (StoppointCallbackContext *context)
+{
+ m_hit_count++;
+ return m_owners.ShouldStop (context);
+}
+
+bool
+BreakpointSite::IsBreakpointAtThisSite (lldb::break_id_t bp_id)
+{
+ for (int i = 0; i < m_owners.GetSize(); i++)
+ {
+ if (m_owners.GetByIndex(i)->GetBreakpoint().GetID() == bp_id)
+ return true;
+ }
+ return false;
+}
+
+void
+BreakpointSite::Dump(Stream *s) const
+{
+ if (s == NULL)
+ return;
+
+ s->Printf("BreakpointSite %u: tid = %4.4x addr = 0x%8.8llx type = %s breakpoint hw_index = %i hit_count = %-4u",
+ GetID(),
+ m_tid,
+ (uint64_t)m_addr,
+ IsHardware() ? "hardware" : "software",
+ GetHardwareIndex(),
+ GetHitCount());
+}
+
+void
+BreakpointSite::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+ if (level != lldb::eDescriptionLevelBrief)
+ s->Printf ("breakpoint site: %d ", GetID());
+ m_owners.GetDescription (s, level);
+}
+
+uint8_t *
+BreakpointSite::GetTrapOpcodeBytes()
+{
+ return &m_trap_opcode[0];
+}
+
+const uint8_t *
+BreakpointSite::GetTrapOpcodeBytes() const
+{
+ return &m_trap_opcode[0];
+}
+
+size_t
+BreakpointSite::GetTrapOpcodeMaxByteSize() const
+{
+ return sizeof(m_trap_opcode);
+}
+
+bool
+BreakpointSite::SetTrapOpcode (const uint8_t *trap_opcode, size_t trap_opcode_size)
+{
+ if (trap_opcode_size > 0 && trap_opcode_size <= sizeof(m_trap_opcode))
+ {
+ m_byte_size = trap_opcode_size;
+ ::memcpy (m_trap_opcode, trap_opcode, trap_opcode_size);
+ return true;
+ }
+ m_byte_size = 0;
+ return false;
+}
+
+uint8_t *
+BreakpointSite::GetSavedOpcodeBytes()
+{
+ return &m_saved_opcode[0];
+}
+
+const uint8_t *
+BreakpointSite::GetSavedOpcodeBytes() const
+{
+ return &m_saved_opcode[0];
+}
+
+bool
+BreakpointSite::IsEnabled () const
+{
+ return m_enabled;
+}
+
+void
+BreakpointSite::SetEnabled (bool enabled)
+{
+ m_enabled = enabled;
+}
+
+void
+BreakpointSite::AddOwner (BreakpointLocationSP &owner)
+{
+ m_owners.Add(owner);
+}
+
+uint32_t
+BreakpointSite::RemoveOwner (lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
+{
+ m_owners.Remove(break_id, break_loc_id);
+ return m_owners.GetSize();
+}
+
+uint32_t
+BreakpointSite::GetNumberOfOwners ()
+{
+ return m_owners.GetSize();
+}
+
+BreakpointLocationSP
+BreakpointSite::GetOwnerAtIndex (uint32_t index)
+{
+ return m_owners.GetByIndex (index);
+}
+
+bool
+BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, lldb::addr_t *intersect_addr, size_t *intersect_size, size_t *opcode_offset) const
+{
+ // We only use software traps for software breakpoints
+ if (!IsHardware())
+ {
+ if (m_byte_size > 0)
+ {
+ const lldb::addr_t bp_end_addr = m_addr + m_byte_size;
+ const lldb::addr_t end_addr = addr + size;
+ // Is the breakpoint end address before the passed in start address?
+ if (bp_end_addr <= addr)
+ return false;
+ // Is the breakpoint start address after passed in end address?
+ if (end_addr <= m_addr)
+ return false;
+ if (intersect_addr || intersect_size || opcode_offset)
+ {
+ if (m_addr < addr)
+ {
+ if (intersect_addr)
+ *intersect_addr = addr;
+ if (intersect_size)
+ *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - addr;
+ if (opcode_offset)
+ *opcode_offset = addr - m_addr;
+ }
+ else
+ {
+ if (intersect_addr)
+ *intersect_addr = m_addr;
+ if (intersect_size)
+ *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - m_addr;
+ if (opcode_offset)
+ *opcode_offset = 0;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/lldb/source/Breakpoint/BreakpointSiteList.cpp b/lldb/source/Breakpoint/BreakpointSiteList.cpp
new file mode 100644
index 00000000000..19e18bb749a
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointSiteList.cpp
@@ -0,0 +1,229 @@
+//===-- BreakpointSiteList.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointSiteList.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+BreakpointSiteList::BreakpointSiteList() :
+ m_bp_site_list()
+{
+}
+
+BreakpointSiteList::~BreakpointSiteList()
+{
+}
+
+// Add breakpoint site to the list. However, if the element already exists in the
+// list, then we don't add it, and return LLDB_INVALID_BREAK_ID.
+
+lldb::user_id_t
+BreakpointSiteList::Add(const BreakpointSiteSP &bp)
+{
+ lldb::addr_t bp_site_load_addr = bp->GetLoadAddress();
+ collection::iterator iter = m_bp_site_list.find (bp_site_load_addr);
+
+ if (iter == m_bp_site_list.end())
+ {
+ m_bp_site_list.insert (iter, collection::value_type (bp_site_load_addr, bp));
+ return bp->GetID();
+ }
+ else
+ {
+ return LLDB_INVALID_BREAK_ID;
+ }
+}
+
+bool
+BreakpointSiteList::ShouldStop (StoppointCallbackContext *context, lldb::user_id_t break_id)
+{
+ BreakpointSiteSP bp = FindByID (break_id);
+ if (bp)
+ {
+ // Let the BreakpointSite 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 BreakpointSite isn't valid anymore or it
+ // doesn't exist.
+ return true;
+}
+lldb::user_id_t
+BreakpointSiteList::FindIDByAddress (lldb::addr_t addr)
+{
+ BreakpointSiteSP bp = FindByAddress (addr);
+ if (bp)
+ {
+ //DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8llx ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID());
+ return bp.get()->GetID();
+ }
+ //DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8llx ) => NONE", __FUNCTION__, (uint64_t)addr);
+ return LLDB_INVALID_BREAK_ID;
+}
+
+bool
+BreakpointSiteList::Remove (lldb::user_id_t break_id)
+{
+ collection::iterator pos = GetIDIterator(break_id); // Predicate
+ if (pos != m_bp_site_list.end())
+ {
+ m_bp_site_list.erase(pos);
+ return true;
+ }
+ return false;
+}
+
+bool
+BreakpointSiteList::RemoveByAddress (lldb::addr_t address)
+{
+ collection::iterator pos = m_bp_site_list.find(address);
+ if (pos != m_bp_site_list.end())
+ {
+ m_bp_site_list.erase(pos);
+ return true;
+ }
+ return false;
+}
+
+class BreakpointSiteIDMatches
+{
+public:
+ BreakpointSiteIDMatches (lldb::user_id_t break_id) :
+ m_break_id(break_id)
+ {
+ }
+
+ bool operator() (std::pair <lldb::addr_t, BreakpointSiteSP> val_pair) const
+ {
+ return m_break_id == val_pair.second.get()->GetID();
+ }
+
+private:
+ const lldb::user_id_t m_break_id;
+};
+
+BreakpointSiteList::collection::iterator
+BreakpointSiteList::GetIDIterator (lldb::user_id_t break_id)
+{
+ return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(), // Search full range
+ BreakpointSiteIDMatches(break_id)); // Predicate
+}
+
+BreakpointSiteList::collection::const_iterator
+BreakpointSiteList::GetIDConstIterator (lldb::user_id_t break_id) const
+{
+ return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(), // Search full range
+ BreakpointSiteIDMatches(break_id)); // Predicate
+}
+
+BreakpointSiteSP
+BreakpointSiteList::FindByID (lldb::user_id_t break_id)
+{
+ BreakpointSiteSP stop_sp;
+ collection::iterator pos = GetIDIterator(break_id);
+ if (pos != m_bp_site_list.end())
+ stop_sp = pos->second;
+
+ return stop_sp;
+}
+
+const BreakpointSiteSP
+BreakpointSiteList::FindByID (lldb::user_id_t break_id) const
+{
+ BreakpointSiteSP stop_sp;
+ collection::const_iterator pos = GetIDConstIterator(break_id);
+ if (pos != m_bp_site_list.end())
+ stop_sp = pos->second;
+
+ return stop_sp;
+}
+
+BreakpointSiteSP
+BreakpointSiteList::FindByAddress (lldb::addr_t addr)
+{
+ BreakpointSiteSP found_sp;
+
+ collection::iterator iter = m_bp_site_list.find(addr);
+ if (iter != m_bp_site_list.end())
+ found_sp = iter->second;
+ return found_sp;
+}
+
+void
+BreakpointSiteList::Dump (Stream *s) const
+{
+ s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+ s->Indent();
+ s->Printf("BreakpointSiteList with %u BreakpointSites:\n", (uint32_t)m_bp_site_list.size());
+ s->IndentMore();
+ collection::const_iterator pos;
+ collection::const_iterator end = m_bp_site_list.end();
+ for (pos = m_bp_site_list.begin(); pos != end; ++pos)
+ pos->second.get()->Dump(s);
+ s->IndentLess();
+}
+
+
+BreakpointSiteSP
+BreakpointSiteList::GetByIndex (uint32_t i)
+{
+ BreakpointSiteSP stop_sp;
+ collection::iterator end = m_bp_site_list.end();
+ collection::iterator pos;
+ uint32_t curr_i = 0;
+ for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
+ {
+ if (curr_i == i)
+ stop_sp = pos->second;
+ }
+ return stop_sp;
+}
+
+const BreakpointSiteSP
+BreakpointSiteList::GetByIndex (uint32_t i) const
+{
+ BreakpointSiteSP stop_sp;
+ collection::const_iterator end = m_bp_site_list.end();
+ collection::const_iterator pos;
+ uint32_t curr_i = 0;
+ for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
+ {
+ if (curr_i == i)
+ stop_sp = pos->second;
+ }
+ return stop_sp;
+}
+
+void
+BreakpointSiteList::SetEnabledForAll (const bool enabled, const lldb::user_id_t except_id)
+{
+ collection::iterator end = m_bp_site_list.end();
+ collection::iterator pos;
+ for (pos = m_bp_site_list.begin(); pos != end; ++pos)
+ {
+ if (except_id != LLDB_INVALID_BREAK_ID && except_id != pos->second->GetID())
+ pos->second->SetEnabled (enabled);
+ else
+ pos->second->SetEnabled (!enabled);
+ }
+}
+
+const BreakpointSiteList::collection *
+BreakpointSiteList::GetMap ()
+{
+ return &m_bp_site_list;
+}
diff --git a/lldb/source/Breakpoint/Stoppoint.cpp b/lldb/source/Breakpoint/Stoppoint.cpp
new file mode 100644
index 00000000000..583ab47005f
--- /dev/null
+++ b/lldb/source/Breakpoint/Stoppoint.cpp
@@ -0,0 +1,46 @@
+//===-- Stoppoint.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+#include "lldb/Breakpoint/Stoppoint.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Stoppoint constructor
+//----------------------------------------------------------------------
+Stoppoint::Stoppoint() :
+ m_bid (LLDB_INVALID_BREAK_ID)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Stoppoint::~Stoppoint()
+{
+}
+
+break_id_t
+Stoppoint::GetID () const
+{
+ return m_bid;
+}
+
+void
+Stoppoint::SetID (break_id_t bid)
+{
+ m_bid = bid;
+}
diff --git a/lldb/source/Breakpoint/StoppointCallbackContext.cpp b/lldb/source/Breakpoint/StoppointCallbackContext.cpp
new file mode 100644
index 00000000000..86620621c76
--- /dev/null
+++ b/lldb/source/Breakpoint/StoppointCallbackContext.cpp
@@ -0,0 +1,38 @@
+//===-- StoppointCallbackContext.cpp ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb_private;
+
+StoppointCallbackContext::StoppointCallbackContext() :
+ event (NULL),
+ context()
+{
+}
+
+StoppointCallbackContext::StoppointCallbackContext(Event *e, Process* p, Thread *t, StackFrame *f, bool synchronously) :
+ event (e),
+ context (p, t, f),
+ is_synchronous(synchronously)
+{
+}
+
+void
+StoppointCallbackContext::Clear()
+{
+ event = NULL;
+ context.Clear();
+ is_synchronous = false;
+}
diff --git a/lldb/source/Breakpoint/StoppointLocation.cpp b/lldb/source/Breakpoint/StoppointLocation.cpp
new file mode 100644
index 00000000000..999ad536ab8
--- /dev/null
+++ b/lldb/source/Breakpoint/StoppointLocation.cpp
@@ -0,0 +1,120 @@
+//===-- StoppointLocation.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/StoppointLocation.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// StoppointLocation constructor
+//----------------------------------------------------------------------
+StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, tid_t tid, bool hardware) :
+ m_loc_id(bid),
+ m_tid(tid),
+ m_byte_size(0),
+ m_addr(addr),
+ m_hit_count(0),
+ m_hw_preferred(hardware),
+ m_hw_index(LLDB_INVALID_INDEX32)
+{
+}
+
+StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, tid_t tid, size_t size, bool hardware) :
+ m_loc_id(bid),
+ m_tid(tid),
+ m_byte_size(size),
+ m_addr(addr),
+ m_hit_count(0),
+ m_hw_preferred(hardware),
+ m_hw_index(LLDB_INVALID_INDEX32)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+StoppointLocation::~StoppointLocation()
+{
+}
+
+
+size_t
+StoppointLocation::GetByteSize () const
+{
+ return m_byte_size;
+}
+
+addr_t
+StoppointLocation::GetLoadAddress() const
+{
+ return m_addr;
+}
+
+tid_t
+StoppointLocation::GetThreadID() const
+{
+ return m_tid;
+}
+
+uint32_t
+StoppointLocation::GetHitCount () const
+{
+ return m_hit_count;
+}
+
+bool
+StoppointLocation::HardwarePreferred () const
+{
+ return m_hw_preferred;
+}
+
+bool
+StoppointLocation::IsHardware () const
+{
+ return m_hw_index != LLDB_INVALID_INDEX32;
+}
+
+uint32_t
+StoppointLocation::GetHardwareIndex () const
+{
+ return m_hw_index;
+}
+
+void
+StoppointLocation::SetHardwareIndex (uint32_t hw_index)
+{
+ m_hw_index = hw_index;
+}
+
+// RETURNS - true if we should stop at this breakpoint, false if we
+// should continue.
+
+bool
+StoppointLocation::ShouldStop (StoppointCallbackContext *context)
+{
+ return true;
+}
+
+break_id_t
+StoppointLocation::GetID() const
+{
+ return m_loc_id;
+}
+
+void
+StoppointLocation::Dump (Stream *stream) const
+{
+
+}
diff --git a/lldb/source/Breakpoint/WatchpointLocation.cpp b/lldb/source/Breakpoint/WatchpointLocation.cpp
new file mode 100644
index 00000000000..f765ef43202
--- /dev/null
+++ b/lldb/source/Breakpoint/WatchpointLocation.cpp
@@ -0,0 +1,137 @@
+//===-- WatchpointLocation.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/WatchpointLocation.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+WatchpointLocation::WatchpointLocation (lldb::addr_t addr, lldb::tid_t tid, bool hardware) :
+ StoppointLocation (GetNextID(), addr, tid, hardware),
+ m_enabled(0),
+ m_watch_read(0),
+ m_watch_write(0),
+ m_watch_was_read(0),
+ m_watch_was_written(0),
+ m_ignore_count(0),
+ m_callback(NULL),
+ m_callback_baton(NULL)
+{
+}
+
+WatchpointLocation::~WatchpointLocation()
+{
+}
+
+break_id_t
+WatchpointLocation::GetNextID()
+{
+ static break_id_t g_next_ID = 0;
+ return ++g_next_ID;
+}
+
+bool
+WatchpointLocation::SetCallback (WatchpointHitCallback callback, void *callback_baton)
+{
+ m_callback = callback;
+ m_callback_baton = callback_baton;
+ return true;
+}
+
+
+// RETURNS - true if we should stop at this breakpoint, false if we
+// should continue.
+
+bool
+WatchpointLocation::BreakpointWasHit (StoppointCallbackContext *context)
+{
+ m_hit_count++;
+
+ if (m_hit_count > m_ignore_count)
+ {
+ uint32_t access = 0;
+ if (m_watch_was_read)
+ access |= LLDB_WATCH_TYPE_READ;
+ if (m_watch_was_written)
+ access |= LLDB_WATCH_TYPE_WRITE;
+ return m_callback(m_callback_baton, context, GetID(), access);
+ }
+ return false;
+}
+
+void
+WatchpointLocation::Dump(Stream *s) const
+{
+ if (s == NULL)
+ return;
+
+ s->Printf("WatchpointLocation %u: tid = %4.4x addr = 0x%8.8llx size = %zu state = %s type = %s watchpoint (%s%s) hw_index = %i hit_count = %-4u ignore_count = %-4u callback = %8p baton = %8p",
+ GetID(),
+ m_tid,
+ (uint64_t)m_addr,
+ m_byte_size,
+ m_enabled ? "enabled " : "disabled",
+ IsHardware() ? "hardware" : "software",
+ m_watch_read ? "r" : "",
+ m_watch_write ? "w" : "",
+ GetHardwareIndex(),
+ GetHitCount(),
+ GetIgnoreCount(),
+ m_callback,
+ m_callback_baton);
+}
+
+bool
+WatchpointLocation::IsEnabled() const
+{
+ return m_enabled;
+}
+
+void
+WatchpointLocation::SetEnabled(uint32_t enabled)
+{
+ if (!enabled)
+ SetHardwareIndex(LLDB_INVALID_INDEX32);
+ m_enabled = enabled;
+}
+
+void
+WatchpointLocation::SetWatchpointType (uint32_t type)
+{
+ m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0;
+ m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0;
+}
+
+bool
+WatchpointLocation::WatchpointRead () const
+{
+ return m_watch_read != 0;
+}
+bool
+WatchpointLocation::WatchpointWrite () const
+{
+ return m_watch_write != 0;
+}
+int32_t
+WatchpointLocation::GetIgnoreCount () const
+{
+ return m_ignore_count;
+}
+
+void
+WatchpointLocation::SetIgnoreCount (int32_t n)
+{
+ m_ignore_count = n;
+}
OpenPOWER on IntegriCloud