diff --git a/lldb/include/lldb/Breakpoint/BreakpointList.h b/lldb/include/lldb/Breakpoint/BreakpointList.h index 225bb3ba498c..84ccf935230f 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointList.h +++ b/lldb/include/lldb/Breakpoint/BreakpointList.h @@ -153,6 +153,15 @@ public: void ClearAllBreakpointSites (); + + //------------------------------------------------------------------ + /// Sets the passed in Locker to hold the Breakpoint List mutex. + /// + /// @param[in] locker + /// The locker object that is set. + //------------------------------------------------------------------ + void + GetListMutex (lldb_private::Mutex::Locker &locker); protected: typedef std::list bp_collection; diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocation.h b/lldb/include/lldb/Breakpoint/BreakpointLocation.h index 1324ced54312..7aed5589ec19 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointLocation.h +++ b/lldb/include/lldb/Breakpoint/BreakpointLocation.h @@ -178,16 +178,6 @@ public: void SetThreadID (lldb::tid_t thread_id); - //------------------------------------------------------------------ - /// Return the current stop thread value. - /// - /// @return - /// The thread id for which the breakpoint hit will stop, - /// LLDB_INVALID_THREAD_ID for all threads. - //------------------------------------------------------------------ - lldb::tid_t - GetThreadID (); - //------------------------------------------------------------------ // The next section deals with this location's breakpoint sites. //------------------------------------------------------------------ @@ -267,8 +257,11 @@ public: /// A pointer to the containing breakpoint's options if this /// location doesn't have its own copy. //------------------------------------------------------------------ - BreakpointOptions * - GetOptionsNoCopy (); + const BreakpointOptions * + GetOptionsNoCopy () const; + + bool + ValidForThisThread (Thread *thread); protected: friend class Breakpoint; diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h b/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h index 9e04a2c42779..9f0dd0fb2e07 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h +++ b/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h @@ -156,6 +156,20 @@ public: /// @see lldb::DescriptionLevel //------------------------------------------------------------------ void GetDescription (Stream *s, lldb::DescriptionLevel level); + + //------------------------------------------------------------------ + /// Check whether this collection of breakpoint locations have any + /// thread specifiers, and if yes, is \a thread_id contained in any + /// of these specifiers. + /// + /// @param[in] thread + /// The thread against which to test. + /// + /// return + /// \b true if the collection contains at least one location that + /// would be valid for this thread, false otherwise. + //------------------------------------------------------------------ + bool ValidForThisThread (Thread *thread); diff --git a/lldb/include/lldb/Breakpoint/BreakpointOptions.h b/lldb/include/lldb/Breakpoint/BreakpointOptions.h index e7a3e3bf1d22..c0c3eeb57785 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointOptions.h +++ b/lldb/include/lldb/Breakpoint/BreakpointOptions.h @@ -12,6 +12,7 @@ // C Includes // C++ Includes +#include // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" @@ -84,6 +85,7 @@ public: return m_callback_is_synchronous; }; Baton *GetBaton (); + const Baton *GetBaton () const; void ClearCallback (); //------------------------------------------------------------------ @@ -122,21 +124,24 @@ public: //------------------------------------------------------------------ //------------------------------------------------------------------ - /// Return the current stop thread value. + /// Return the current thread spec. This is used to pass to Thread::MatchesSpec. /// @return - /// The thread id for which the breakpoint hit will stop, - /// LLDB_INVALID_THREAD_ID for all threads. + /// The thread specification pointer for this option, or NULL if none has + /// been set yet. //------------------------------------------------------------------ - lldb::tid_t - GetThreadID () const; + const ThreadSpec * + GetThreadSpec () const; //------------------------------------------------------------------ - /// Set the valid thread to be checked when the breakpoint is hit. - /// @param[in] thread_id - /// If this thread hits the breakpoint, we stop, otherwise not. + /// Returns a pointer to the ThreadSpec for this option, creating it. + /// if it hasn't been created already. This API is used for setting the + /// ThreadSpec items for this option. //------------------------------------------------------------------ + ThreadSpec * + GetThreadSpec (); + void - SetThreadID (lldb::tid_t thread_id); + SetThreadID(lldb::tid_t thread_id); //------------------------------------------------------------------ /// This is the default empty callback. @@ -201,7 +206,7 @@ private: bool m_callback_is_synchronous; bool m_enabled; int32_t m_ignore_count; // Number of times to ignore this breakpoint - lldb::tid_t m_thread_id; // Thread for which this breakpoint will take + std::auto_ptr m_thread_spec_ap; // Thread for which this breakpoint will take }; diff --git a/lldb/include/lldb/Breakpoint/BreakpointSite.h b/lldb/include/lldb/Breakpoint/BreakpointSite.h index aeb385ba18eb..50d8fe501374 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointSite.h +++ b/lldb/include/lldb/Breakpoint/BreakpointSite.h @@ -182,6 +182,22 @@ public: //------------------------------------------------------------------ lldb::BreakpointLocationSP GetOwnerAtIndex (uint32_t index); + + //------------------------------------------------------------------ + /// Check whether the owners of this breakpoint site have any + /// thread specifiers, and if yes, is \a thread contained in any + /// of these specifiers. + /// + /// @param[in] thread + /// The thread against which to test. + /// + /// return + /// \b true if the collection contains at least one location that + /// would be valid for this thread, false otherwise. + //------------------------------------------------------------------ + bool + ValidForThisThread (Thread *thread); + //------------------------------------------------------------------ /// Print a description of this breakpoint site to the stream \a s. diff --git a/lldb/include/lldb/Breakpoint/StoppointLocation.h b/lldb/include/lldb/Breakpoint/StoppointLocation.h index b52551005a6d..2978fd5ecc65 100644 --- a/lldb/include/lldb/Breakpoint/StoppointLocation.h +++ b/lldb/include/lldb/Breakpoint/StoppointLocation.h @@ -28,12 +28,10 @@ public: //------------------------------------------------------------------ StoppointLocation (lldb::break_id_t bid, lldb::addr_t m_addr, - lldb::tid_t tid, bool hardware); StoppointLocation (lldb::break_id_t bid, lldb::addr_t m_addr, - lldb::tid_t tid, size_t size, bool hardware); @@ -62,9 +60,6 @@ public: uint32_t GetHardwareIndex () const; - lldb::tid_t - GetThreadID() const; - bool HardwarePreferred () const; @@ -88,7 +83,6 @@ protected: // Classes that inherit from StoppointLocation can see and modify these //------------------------------------------------------------------ lldb::break_id_t m_loc_id; // Break ID - lldb::tid_t m_tid; // The thread ID if this stoppoint location is thread specific, or LLDB_INVALID_THREAD_ID if not thread specific. lldb::addr_t m_addr; // The load address of this stop point. The base Stoppoint doesn't // store a full Address since that's not needed for the breakpoint sites. bool m_hw_preferred; // 1 if this point has been requested to be set using hardware (which may fail due to lack of resources) diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index e7b0ce4f73d9..bd8bdf069baa 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -262,6 +262,9 @@ public: lldb::Vote ShouldReportRun (Event *event_ptr); + + virtual bool + MatchesSpec (const ThreadSpec *spec); bool GetStopInfo (StopInfo *stop_info); diff --git a/lldb/include/lldb/Target/ThreadSpec.h b/lldb/include/lldb/Target/ThreadSpec.h new file mode 100644 index 000000000000..2ee28a28b46e --- /dev/null +++ b/lldb/include/lldb/Target/ThreadSpec.h @@ -0,0 +1,134 @@ +//===-- ThreadSpec.h ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ThreadSpec_h_ +#define liblldb_ThreadSpec_h_ + +#include +#include + +#include "lldb/lldb-private.h" + +namespace lldb_private { + +// Note: For now the thread spec has only fixed elements - +// Thread ID +// Thread Index +// Thread Name +// Thread Queue Name +// +// But if we need more generality, we can hang a key/value map off of this structure. +// That's why the thread matches spec test is done as a virtual method in Thread::MatchesSpec, +// since it is the native thread that would know how to interpret the keys. +// I was going to do the Queue Name this way out of sheer orneriness, but that seems a +// sufficiently general concept, so I put it in here on its own. + +class ThreadSpec +{ +public: + ThreadSpec (); + + ThreadSpec (const ThreadSpec &rhs); + + const ThreadSpec & + operator=(const ThreadSpec &rhs); + + void + SetIndex (uint32_t index) + { + m_index = index; + } + + void + SetTID (lldb::tid_t tid) + { + m_tid = tid; + } + + void + SetName (const char *name) + { + m_name = name; + } + + void + SetQueueName (const char *queue_name) + { + m_queue_name = queue_name; + } + + uint32_t + GetIndex () const + { + return m_index; + } + + lldb::tid_t + GetTID () const + { + return m_tid; + } + + const char * + GetName () const; + + const char * + GetQueueName () const; + + bool + TIDMatches (lldb::tid_t thread_id) const + { + if (m_tid == LLDB_INVALID_THREAD_ID || thread_id == LLDB_INVALID_THREAD_ID) + return true; + else + return thread_id == m_tid; + } + + bool + IndexMatches (uint32_t index) const + { + if (m_index == -1 || index == -1) + return true; + else + return index == m_index; + } + + bool + NameMatches (const char *name) const + { + if (m_name.empty()) + return true; + else if (name == NULL) + return false; + else + return m_name == name; + } + + bool + QueueNameMatches (const char *queue_name) const + { + if (m_queue_name.empty()) + return true; + else if (queue_name == NULL) + return false; + else + return m_queue_name == queue_name; + } + +protected: +private: + uint32_t m_index; + lldb::tid_t m_tid; + std::string m_name; + std::string m_queue_name; +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadSpec_h_ diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index 9e69ca09f52d..59500d8f2dff 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -129,6 +129,7 @@ class ThreadPlanStepOverBreakpoint; class ThreadPlanStepThrough; class ThreadPlanStepRange; class ThreadPlanRunToAddress; +class ThreadSpec; class TimeValue; class Type; class TypeList; diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 790b25130b47..1586c0b4fa1f 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -335,6 +335,8 @@ 49D7072911B5AD11001AD875 /* ClangASTSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D7072811B5AD11001AD875 /* ClangASTSource.cpp */; settings = {COMPILER_FLAGS = "-fno-rtti"; }; }; 49F1A74611B3388F003ED505 /* ClangExpressionDeclMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49F1A74511B3388F003ED505 /* ClangExpressionDeclMap.cpp */; }; 49F1A74A11B338AE003ED505 /* ClangExpressionDeclMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 49F1A74911B338AE003ED505 /* ClangExpressionDeclMap.h */; }; + 4C08CDE811C81EF8001610A8 /* ThreadSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C08CDE711C81EF8001610A8 /* ThreadSpec.cpp */; }; + 4C08CDEC11C81F1E001610A8 /* ThreadSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C08CDEB11C81F1E001610A8 /* ThreadSpec.h */; }; 4CA9637B11B6E99A00780E28 /* CommandObjectApropos.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CA9637911B6E99A00780E28 /* CommandObjectApropos.cpp */; }; 4CA9637C11B6E99A00780E28 /* CommandObjectApropos.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA9637A11B6E99A00780E28 /* CommandObjectApropos.h */; }; 9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A19A6A51163BB7E00E0D453 /* SBValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -920,6 +922,8 @@ 49F1A74911B338AE003ED505 /* ClangExpressionDeclMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangExpressionDeclMap.h; path = include/lldb/Expression/ClangExpressionDeclMap.h; sourceTree = ""; }; 4C00986F11500B4300F316B0 /* UnixSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnixSignals.h; path = include/lldb/Target/UnixSignals.h; sourceTree = ""; }; 4C00987011500B4300F316B0 /* UnixSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnixSignals.cpp; path = source/Target/UnixSignals.cpp; sourceTree = ""; }; + 4C08CDE711C81EF8001610A8 /* ThreadSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadSpec.cpp; path = source/Target/ThreadSpec.cpp; sourceTree = ""; }; + 4C08CDEB11C81F1E001610A8 /* ThreadSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSpec.h; path = include/lldb/Target/ThreadSpec.h; sourceTree = ""; }; 4C09CB73116BD98B00C7A725 /* CommandCompletions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandCompletions.h; path = include/lldb/Interpreter/CommandCompletions.h; sourceTree = ""; }; 4C09CB74116BD98B00C7A725 /* CommandCompletions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandCompletions.cpp; path = source/Commands/CommandCompletions.cpp; sourceTree = ""; }; 4C43DEF9110641F300E55CBF /* ThreadPlanShouldStopHere.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanShouldStopHere.h; path = include/lldb/Target/ThreadPlanShouldStopHere.h; sourceTree = ""; }; @@ -1963,6 +1967,8 @@ 260C847510F50EFC00BB2B04 /* ThreadPlanStepThrough.cpp */, 4CEDAED311754F5E00E875A6 /* ThreadPlanStepUntil.h */, 2660D9FE11922A7F00958FBD /* ThreadPlanStepUntil.cpp */, + 4C08CDEB11C81F1E001610A8 /* ThreadSpec.h */, + 4C08CDE711C81EF8001610A8 /* ThreadSpec.cpp */, 4C00986F11500B4300F316B0 /* UnixSignals.h */, 4C00987011500B4300F316B0 /* UnixSignals.cpp */, 26E3EEBD11A9870400FBADB6 /* Unwind.h */, @@ -2199,6 +2205,7 @@ 49D7072711B5AD03001AD875 /* ClangASTSource.h in Headers */, 4CA9637C11B6E99A00780E28 /* CommandObjectApropos.h in Headers */, 261B5A5511C3F2AD00AABD0A /* SharingPtr.h in Headers */, + 4C08CDEC11C81F1E001610A8 /* ThreadSpec.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2651,6 +2658,7 @@ 4CA9637B11B6E99A00780E28 /* CommandObjectApropos.cpp in Sources */, AF94005911C03F6500085DB9 /* SymbolVendor.cpp in Sources */, 261B5A5411C3F2AD00AABD0A /* SharingPtr.cpp in Sources */, + 4C08CDE811C81EF8001610A8 /* ThreadSpec.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/lldb/source/API/SBBreakpointLocation.cpp b/lldb/source/API/SBBreakpointLocation.cpp index 8bb36bd73240..d917deab4f11 100644 --- a/lldb/source/API/SBBreakpointLocation.cpp +++ b/lldb/source/API/SBBreakpointLocation.cpp @@ -14,6 +14,7 @@ #include "lldb/lldb-types.h" #include "lldb/lldb-defines.h" #include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Target/ThreadSpec.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" @@ -102,7 +103,7 @@ SBBreakpointLocation::GetThreadID () { tid_t sb_thread_id = (lldb::tid_t) LLDB_INVALID_THREAD_ID; if (m_break_loc_sp) - sb_thread_id = m_break_loc_sp->GetThreadID(); + sb_thread_id = m_break_loc_sp->GetLocationOptions()->GetThreadSpec()->GetTID(); return sb_thread_id; } diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp index c475cf0f0d79..b3576b6a5da9 100644 --- a/lldb/source/Breakpoint/Breakpoint.cpp +++ b/lldb/source/Breakpoint/Breakpoint.cpp @@ -24,6 +24,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/Target.h" +#include "lldb/Target/ThreadSpec.h" #include "lldb/lldb-private-log.h" using namespace lldb; @@ -166,13 +167,16 @@ Breakpoint::GetIgnoreCount () const void Breakpoint::SetThreadID (lldb::tid_t thread_id) { - m_options.SetThreadID(thread_id); + m_options.GetThreadSpec()->SetTID(thread_id); } lldb::tid_t Breakpoint::GetThreadID () { - return m_options.GetThreadID(); + if (m_options.GetThreadSpec() == NULL) + return LLDB_INVALID_THREAD_ID; + else + return m_options.GetThreadSpec()->GetTID(); } // This function is used when "baton" doesn't need to be freed diff --git a/lldb/source/Breakpoint/BreakpointList.cpp b/lldb/source/Breakpoint/BreakpointList.cpp index c10aa770b827..0d9444f73719 100644 --- a/lldb/source/Breakpoint/BreakpointList.cpp +++ b/lldb/source/Breakpoint/BreakpointList.cpp @@ -196,3 +196,9 @@ BreakpointList::ClearAllBreakpointSites () (*pos)->ClearAllBreakpointSites (); } + +void +BreakpointList::GetListMutex (Mutex::Locker &locker) +{ + return locker.Reset (m_mutex.GetMutex()); +} diff --git a/lldb/source/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp index 0f82829bdd78..e00afcad7503 100644 --- a/lldb/source/Breakpoint/BreakpointLocation.cpp +++ b/lldb/source/Breakpoint/BreakpointLocation.cpp @@ -22,6 +22,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/lldb-private-log.h" #include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadSpec.h" using namespace lldb; using namespace lldb_private; @@ -34,12 +35,13 @@ BreakpointLocation::BreakpointLocation lldb::tid_t tid, bool hardware ) : - StoppointLocation (loc_id, addr.GetLoadAddress(owner.GetTarget().GetProcessSP().get()), tid, hardware), + StoppointLocation (loc_id, addr.GetLoadAddress(owner.GetTarget().GetProcessSP().get()), hardware), m_address (addr), m_owner (owner), m_options_ap (), m_bp_site_sp () { + SetThreadID (tid); } BreakpointLocation::~BreakpointLocation() @@ -93,13 +95,15 @@ BreakpointLocation::SetEnabled (bool enabled) void BreakpointLocation::SetThreadID (lldb::tid_t thread_id) { - GetLocationOptions()->SetThreadID(thread_id); -} - -lldb::tid_t -BreakpointLocation::GetThreadID () -{ - return GetOptionsNoCopy()->GetThreadID(); + if (thread_id != LLDB_INVALID_THREAD_ID) + GetLocationOptions()->SetThreadID(thread_id); + else + { + // If we're resetting this to an invalid thread id, then + // don't make an options pointer just to do that. + if (m_options_ap.get() != NULL) + m_options_ap->SetThreadID (thread_id); + } } bool @@ -150,8 +154,8 @@ BreakpointLocation::SetIgnoreCount (int32_t n) GetLocationOptions()->SetIgnoreCount(n); } -BreakpointOptions * -BreakpointLocation::GetOptionsNoCopy () +const BreakpointOptions * +BreakpointLocation::GetOptionsNoCopy () const { if (m_options_ap.get() != NULL) return m_options_ap.get(); @@ -168,8 +172,16 @@ BreakpointLocation::GetLocationOptions () return m_options_ap.get(); } +bool +BreakpointLocation::ValidForThisThread (Thread *thread) +{ + return thread->MatchesSpec(GetOptionsNoCopy()->GetThreadSpec()); +} + // RETURNS - true if we should stop at this breakpoint, false if we -// should continue. +// should continue. Note, we don't check the thread spec for the breakpoint +// here, since if the breakpoint is not for this thread, then the event won't +// even get reported, so the check is redundant. bool BreakpointLocation::ShouldStop (StoppointCallbackContext *context) @@ -181,10 +193,6 @@ BreakpointLocation::ShouldStop (StoppointCallbackContext *context) if (!IsEnabled()) return false; - if (GetThreadID() != LLDB_INVALID_THREAD_ID - && context->context.thread->GetID() != GetThreadID()) - return false; - if (m_hit_count <= GetIgnoreCount()) return false; @@ -379,7 +387,7 @@ BreakpointLocation::Dump(Stream *s) const 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, + GetOptionsNoCopy()->GetThreadSpec()->GetTID(), (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", diff --git a/lldb/source/Breakpoint/BreakpointLocationCollection.cpp b/lldb/source/Breakpoint/BreakpointLocationCollection.cpp index 7b574263003d..464d38f1d787 100644 --- a/lldb/source/Breakpoint/BreakpointLocationCollection.cpp +++ b/lldb/source/Breakpoint/BreakpointLocationCollection.cpp @@ -16,6 +16,8 @@ #include "lldb/Core/ModuleList.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/BreakpointLocationList.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadSpec.h" using namespace lldb; using namespace lldb_private; @@ -145,6 +147,22 @@ BreakpointLocationCollection::ShouldStop (StoppointCallbackContext *context) return shouldStop; } +bool +BreakpointLocationCollection::ValidForThisThread (Thread *thread) +{ + collection::iterator pos, + begin = m_break_loc_collection.begin(), + end = m_break_loc_collection.end(); + + for (pos = begin; pos != end; ++pos) + { + if ((*pos)->ValidForThisThread (thread)) + return true; + } + return false; +} + + void BreakpointLocationCollection::GetDescription (Stream *s, lldb::DescriptionLevel level) { diff --git a/lldb/source/Breakpoint/BreakpointOptions.cpp b/lldb/source/Breakpoint/BreakpointOptions.cpp index 4f664c4692fe..695f4ee5ccdf 100644 --- a/lldb/source/Breakpoint/BreakpointOptions.cpp +++ b/lldb/source/Breakpoint/BreakpointOptions.cpp @@ -16,6 +16,7 @@ #include "lldb/Core/Stream.h" #include "lldb/Core/StringList.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Target/ThreadSpec.h" using namespace lldb; using namespace lldb_private; @@ -35,7 +36,7 @@ BreakpointOptions::BreakpointOptions() : m_callback_baton_sp (), m_enabled (true), m_ignore_count (0), - m_thread_id (LLDB_INVALID_THREAD_ID) + m_thread_spec_ap (NULL) { } @@ -48,8 +49,10 @@ BreakpointOptions::BreakpointOptions(const BreakpointOptions& rhs) : 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) + m_thread_spec_ap (NULL) { + if (rhs.m_thread_spec_ap.get() != NULL) + m_thread_spec_ap.reset (new ThreadSpec(*rhs.m_thread_spec_ap.get())); } //---------------------------------------------------------------------- @@ -63,7 +66,8 @@ BreakpointOptions::operator=(const BreakpointOptions& rhs) 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; + if (rhs.m_thread_spec_ap.get() != NULL) + m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get())); return *this; } @@ -98,6 +102,12 @@ BreakpointOptions::GetBaton () return m_callback_baton_sp.get(); } +const Baton * +BreakpointOptions::GetBaton () const +{ + return m_callback_baton_sp.get(); +} + bool BreakpointOptions::InvokeCallback (StoppointCallbackContext *context, lldb::user_id_t break_id, @@ -141,20 +151,27 @@ BreakpointOptions::SetIgnoreCount (int32_t n) m_ignore_count = n; } +const ThreadSpec * +BreakpointOptions::GetThreadSpec () const +{ + return m_thread_spec_ap.get(); +} + +ThreadSpec * +BreakpointOptions::GetThreadSpec () +{ + if (m_thread_spec_ap.get() == NULL) + m_thread_spec_ap.reset (new ThreadSpec()); + + return m_thread_spec_ap.get(); +} + void BreakpointOptions::SetThreadID (lldb::tid_t thread_id) { - m_thread_id = thread_id; + GetThreadSpec()->SetTID(thread_id); } -lldb::tid_t -BreakpointOptions::GetThreadID () const -{ - return m_thread_id; -} - - - void BreakpointOptions::CommandBaton::GetDescription (Stream *s, lldb::DescriptionLevel level) const { diff --git a/lldb/source/Breakpoint/BreakpointSite.cpp b/lldb/source/Breakpoint/BreakpointSite.cpp index cd0920d07c75..d9397fcb4125 100644 --- a/lldb/source/Breakpoint/BreakpointSite.cpp +++ b/lldb/source/Breakpoint/BreakpointSite.cpp @@ -80,9 +80,8 @@ 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", + s->Printf("BreakpointSite %u: addr = 0x%8.8llx type = %s breakpoint hw_index = %i hit_count = %-4u", GetID(), - m_tid, (uint64_t)m_addr, IsHardware() ? "hardware" : "software", GetHardwareIndex(), @@ -177,6 +176,12 @@ BreakpointSite::GetOwnerAtIndex (uint32_t index) return m_owners.GetByIndex (index); } +bool +BreakpointSite::ValidForThisThread (Thread *thread) +{ + return m_owners.ValidForThisThread(thread); +} + bool BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, lldb::addr_t *intersect_addr, size_t *intersect_size, size_t *opcode_offset) const { diff --git a/lldb/source/Breakpoint/StoppointLocation.cpp b/lldb/source/Breakpoint/StoppointLocation.cpp index 999ad536ab8c..60280ef27487 100644 --- a/lldb/source/Breakpoint/StoppointLocation.cpp +++ b/lldb/source/Breakpoint/StoppointLocation.cpp @@ -20,9 +20,8 @@ using namespace lldb_private; //---------------------------------------------------------------------- // StoppointLocation constructor //---------------------------------------------------------------------- -StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, tid_t tid, bool hardware) : +StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, bool hardware) : m_loc_id(bid), - m_tid(tid), m_byte_size(0), m_addr(addr), m_hit_count(0), @@ -31,9 +30,8 @@ StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, tid_t tid, bo { } -StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, tid_t tid, size_t size, bool hardware) : +StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, size_t size, bool hardware) : m_loc_id(bid), - m_tid(tid), m_byte_size(size), m_addr(addr), m_hit_count(0), @@ -62,12 +60,6 @@ StoppointLocation::GetLoadAddress() const return m_addr; } -tid_t -StoppointLocation::GetThreadID() const -{ - return m_tid; -} - uint32_t StoppointLocation::GetHitCount () const { diff --git a/lldb/source/Breakpoint/WatchpointLocation.cpp b/lldb/source/Breakpoint/WatchpointLocation.cpp index f765ef432029..bf24421a091a 100644 --- a/lldb/source/Breakpoint/WatchpointLocation.cpp +++ b/lldb/source/Breakpoint/WatchpointLocation.cpp @@ -79,7 +79,6 @@ WatchpointLocation::Dump(Stream *s) const 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", diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp index e001cbb4028f..698a2999f4c0 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.cpp +++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -25,6 +25,8 @@ #include "lldb/Target/Target.h" #include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Target/StackFrame.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadSpec.h" using namespace lldb; using namespace lldb_private; @@ -51,9 +53,13 @@ CommandObjectBreakpointSet::CommandOptions::CommandOptions() : m_func_name (), m_func_regexp (), m_modules (), - m_load_addr() + m_load_addr(), + m_thread_id(LLDB_INVALID_THREAD_ID), + m_thread_index (-1), + m_thread_name(), + m_queue_name(), + m_ignore_count (-1) { - BuildValidOptionSets(); } CommandObjectBreakpointSet::CommandOptions::~CommandOptions () @@ -69,6 +75,21 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] = { LLDB_OPT_SET_ALL, false, "ignore_inlines", 'i', no_argument, NULL, 0, NULL, "Ignore inlined subroutines when setting the breakppoint." }, + { LLDB_OPT_SET_ALL, false, "ignore_count", 'k', required_argument, NULL, 0, NULL, + "Set the number of times this breakpoint is sKipped before stopping." }, + + { LLDB_OPT_SET_ALL, false, "thread_index", 'x', required_argument, NULL, NULL, "", + "The breakpoint stops only for the thread whose indeX matches this argument."}, + + { LLDB_OPT_SET_ALL, false, "thread_id", 't', required_argument, NULL, NULL, "", + "The breakpoint stops only for the thread whose TID matches this argument."}, + + { LLDB_OPT_SET_ALL, false, "thread_name", 'T', required_argument, NULL, NULL, "", + "The breakpoint stops only for the thread whose thread name matches this argument."}, + + { LLDB_OPT_SET_ALL, false, "queue_name", 'q', required_argument, NULL, NULL, "", + "The breakpoint stops only for threads in the queue whose name is given by this argument."}, + { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, "", "Set the breakpoint by source location in this particular file."}, @@ -138,6 +159,33 @@ CommandObjectBreakpointSet::CommandOptions::SetOptionValue (int option_idx, cons m_modules.push_back (std::string (option_arg)); break; } + case 'k': + { + m_ignore_count = Args::StringToSInt32(optarg, -1, 0); + if (m_ignore_count == -1) + error.SetErrorStringWithFormat ("Invalid ignore count '%s'.\n", optarg); + } + case 't' : + { + m_thread_id = Args::StringToUInt64(optarg, LLDB_INVALID_THREAD_ID, 0); + if (m_thread_id == LLDB_INVALID_THREAD_ID) + error.SetErrorStringWithFormat ("Invalid thread id string '%s'.\n", optarg); + } + break; + case 'T': + m_thread_name = option_arg; + break; + case 'q': + m_queue_name = option_arg; + break; + case 'x': + { + m_thread_index = Args::StringToUInt64(optarg, -1, 0); + if (m_thread_id == -1) + error.SetErrorStringWithFormat ("Invalid thread index string '%s'.\n", optarg); + + } + break; default: error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); break; @@ -159,6 +207,11 @@ CommandObjectBreakpointSet::CommandOptions::ResetOptionValues () m_func_regexp.clear(); m_load_addr = LLDB_INVALID_ADDRESS; m_modules.clear(); + m_ignore_count = -1; + m_thread_id = LLDB_INVALID_THREAD_ID; + m_thread_index = -1; + m_thread_name.clear(); + m_queue_name.clear(); } //------------------------------------------------------------------------- @@ -223,7 +276,7 @@ CommandObjectBreakpointSet::Execute if ((num_modules > 0) && (break_type != eSetTypeAddress)) use_module = true; - + switch (break_type) { case eSetTypeFileAndLine: // Breakpoint by source position @@ -361,6 +414,25 @@ CommandObjectBreakpointSet::Execute break; } + // Now set the various options that were passed in: + if (bp) + { + if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) + bp->SetThreadID (m_options.m_thread_id); + + if (m_options.m_thread_index != -1) + bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index); + + if (!m_options.m_thread_name.empty()) + bp->GetOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str()); + + if (!m_options.m_queue_name.empty()) + bp->GetOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str()); + + if (m_options.m_ignore_count != -1) + bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count); + } + if (bp && !use_module) { StreamString &output_stream = result.GetOutputStream(); @@ -378,8 +450,6 @@ CommandObjectBreakpointSet::Execute return result.Succeeded(); } - - //------------------------------------------------------------------------- // CommandObjectMultiwordBreakpoint //------------------------------------------------------------------------- @@ -397,12 +467,14 @@ CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInter CommandObjectSP disable_command_object (new CommandObjectBreakpointDisable ()); CommandObjectSP set_command_object (new CommandObjectBreakpointSet ()); CommandObjectSP command_command_object (new CommandObjectBreakpointCommand (interpreter)); + CommandObjectSP configure_command_object (new CommandObjectBreakpointConfigure()); enable_command_object->SetCommandName("breakpoint enable"); disable_command_object->SetCommandName("breakpoint disable"); set_command_object->SetCommandName("breakpoint set"); command_command_object->SetCommandName ("breakpoint command"); list_command_object->SetCommandName ("breakpoint list"); + configure_command_object->SetCommandName ("breakpoint configure"); status = LoadSubCommand (list_command_object, "list", interpreter); status = LoadSubCommand (enable_command_object, "enable", interpreter); @@ -410,6 +482,7 @@ CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInter status = LoadSubCommand (delete_command_object, "delete", interpreter); status = LoadSubCommand (set_command_object, "set", interpreter); status = LoadSubCommand (command_command_object, "command", interpreter); + status = LoadSubCommand (configure_command_object, "configure", interpreter); } CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint () @@ -481,7 +554,6 @@ CommandObjectBreakpointList::CommandOptions::CommandOptions() : Options (), m_level (lldb::eDescriptionLevelFull) // Breakpoint List defaults to brief descriptions { - BuildValidOptionSets(); } CommandObjectBreakpointList::CommandOptions::~CommandOptions () @@ -590,6 +662,9 @@ CommandObjectBreakpointList::Execute } const BreakpointList &breakpoints = target->GetBreakpointList(m_options.m_internal); + Mutex::Locker locker; + target->GetBreakpointList(m_options.m_internal).GetListMutex(locker); + size_t num_breakpoints = breakpoints.GetSize(); if (num_breakpoints == 0) @@ -672,7 +747,11 @@ CommandObjectBreakpointEnable::Execute (Args& args, CommandContext *context, return false; } + Mutex::Locker locker; + target->GetBreakpointList().GetListMutex(locker); + const BreakpointList &breakpoints = target->GetBreakpointList(); + size_t num_breakpoints = breakpoints.GetSize(); if (num_breakpoints == 0) @@ -771,6 +850,9 @@ CommandObjectBreakpointDisable::Execute (Args& args, CommandContext *context, return false; } + Mutex::Locker locker; + target->GetBreakpointList().GetListMutex(locker); + const BreakpointList &breakpoints = target->GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); @@ -866,7 +948,11 @@ CommandObjectBreakpointDelete::Execute (Args& args, CommandContext *context, return false; } + Mutex::Locker locker; + target->GetBreakpointList().GetListMutex(locker); + const BreakpointList &breakpoints = target->GetBreakpointList(); + size_t num_breakpoints = breakpoints.GetSize(); if (num_breakpoints == 0) @@ -931,3 +1017,210 @@ CommandObjectBreakpointDelete::Execute (Args& args, CommandContext *context, } return result.Succeeded(); } + +//------------------------------------------------------------------------- +// CommandObjectBreakpointConfigure::CommandOptions +//------------------------------------------------------------------------- + +CommandObjectBreakpointConfigure::CommandOptions::CommandOptions() : + Options (), + m_thread_id(LLDB_INVALID_THREAD_ID), + m_thread_index (-1), + m_thread_name(), + m_queue_name(), + m_ignore_count (-1) +{ +} + +CommandObjectBreakpointConfigure::CommandOptions::~CommandOptions () +{ +} + +lldb::OptionDefinition +CommandObjectBreakpointConfigure::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_ALL, false, "ignore_count", 'k', required_argument, NULL, 0, NULL, + "Set the number of times this breakpoint is sKipped before stopping." }, + + { LLDB_OPT_SET_ALL, false, "thread_index", 'x', required_argument, NULL, NULL, "", + "The breakpoint stops only for the thread whose indeX matches this argument."}, + + { LLDB_OPT_SET_ALL, false, "thread_id", 't', required_argument, NULL, NULL, "", + "The breakpoint stops only for the thread whose TID matches this argument."}, + + { LLDB_OPT_SET_ALL, false, "thread_name", 'T', required_argument, NULL, NULL, "", + "The breakpoint stops only for the thread whose thread name matches this argument."}, + + { LLDB_OPT_SET_ALL, false, "queue_name", 'q', required_argument, NULL, NULL, "", + "The breakpoint stops only for threads in the queue whose name is given by this argument."}, + + { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } +}; + +const lldb::OptionDefinition* +CommandObjectBreakpointConfigure::CommandOptions::GetDefinitions () +{ + return g_option_table; +} + +Error +CommandObjectBreakpointConfigure::CommandOptions::SetOptionValue (int option_idx, const char *option_arg) +{ + Error error; + char short_option = (char) m_getopt_table[option_idx].val; + + switch (short_option) + { + case 'k': + { + m_ignore_count = Args::StringToSInt32(optarg, -1, 0); + if (m_ignore_count == -1) + error.SetErrorStringWithFormat ("Invalid ignore count '%s'.\n", optarg); + } + case 't' : + { + m_thread_id = Args::StringToUInt64(optarg, LLDB_INVALID_THREAD_ID, 0); + if (m_thread_id == LLDB_INVALID_THREAD_ID) + error.SetErrorStringWithFormat ("Invalid thread id string '%s'.\n", optarg); + } + break; + case 'T': + m_thread_name = option_arg; + break; + case 'q': + m_queue_name = option_arg; + break; + case 'x': + { + m_thread_index = Args::StringToUInt64(optarg, -1, 0); + if (m_thread_id == -1) + error.SetErrorStringWithFormat ("Invalid thread index string '%s'.\n", optarg); + + } + break; + default: + error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); + break; + } + + return error; +} + +void +CommandObjectBreakpointConfigure::CommandOptions::ResetOptionValues () +{ + Options::ResetOptionValues(); + + m_ignore_count = -1; + m_thread_id = LLDB_INVALID_THREAD_ID; + m_thread_index = -1; + m_thread_name.clear(); + m_queue_name.clear(); +} + +//------------------------------------------------------------------------- +// CommandObjectBreakpointSet +//------------------------------------------------------------------------- + +CommandObjectBreakpointConfigure::CommandObjectBreakpointConfigure () : + CommandObject ("breakpoint configure", "Configures the options on a breakpoint or set of breakpoints in the executable.", + "breakpoint configure break-id [break-id ...]") +{ +} + +CommandObjectBreakpointConfigure::~CommandObjectBreakpointConfigure () +{ +} + +Options * +CommandObjectBreakpointConfigure::GetOptions () +{ + return &m_options; +} + +bool +CommandObjectBreakpointConfigure::Execute +( + Args& command, + CommandContext *context, + CommandInterpreter *interpreter, + CommandReturnObject &result +) +{ + if (command.GetArgumentCount() == 0) + { + result.AppendError ("No breakpoints specified."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + Target *target = context->GetTarget(); + if (target == NULL) + { + result.AppendError ("Invalid target, set executable file using 'file' command."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + Mutex::Locker locker; + target->GetBreakpointList().GetListMutex(locker); + + BreakpointIDList valid_bp_ids; + + CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); + + if (result.Succeeded()) + { + for (int i = 0; i < valid_bp_ids.Size(); ++i) + { + BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); + + if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) + { + Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); + if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) + { + BreakpointLocation *location = bp->FindLocationByID (cur_bp_id.GetLocationID()).get(); + if (location) + { + if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) + location->SetThreadID (m_options.m_thread_id); + + if (m_options.m_thread_index != -1) + location->GetLocationOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index); + + if (!m_options.m_thread_name.empty()) + location->GetLocationOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str()); + + if (!m_options.m_queue_name.empty()) + location->GetLocationOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str()); + + if (m_options.m_ignore_count != -1) + location->GetLocationOptions()->SetIgnoreCount(m_options.m_ignore_count); + } + } + else + { + if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) + bp->SetThreadID (m_options.m_thread_id); + + if (m_options.m_thread_index != -1) + bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index); + + if (!m_options.m_thread_name.empty()) + bp->GetOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str()); + + if (!m_options.m_queue_name.empty()) + bp->GetOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str()); + + if (m_options.m_ignore_count != -1) + bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count); + } + } + } + } + + return result.Succeeded(); +} + + diff --git a/lldb/source/Commands/CommandObjectBreakpoint.h b/lldb/source/Commands/CommandObjectBreakpoint.h index 8e705918c8ff..7e7bd61181fa 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.h +++ b/lldb/source/Commands/CommandObjectBreakpoint.h @@ -106,6 +106,70 @@ public: std::string m_func_regexp; lldb::addr_t m_load_addr; STLStringArray m_modules; + int32_t m_ignore_count; + lldb::tid_t m_thread_id; + uint32_t m_thread_index; + std::string m_thread_name; + std::string m_queue_name; + + }; + +private: + CommandOptions m_options; +}; + +//------------------------------------------------------------------------- +// CommandObjectMultiwordBreakpointConfigure +//------------------------------------------------------------------------- + + +class CommandObjectBreakpointConfigure : public CommandObject +{ +public: + + CommandObjectBreakpointConfigure (); + + virtual + ~CommandObjectBreakpointConfigure (); + + virtual bool + Execute (Args& command, + CommandContext *context, + CommandInterpreter *interpreter, + CommandReturnObject &result); + + virtual Options * + GetOptions (); + + class CommandOptions : public Options + { + public: + + CommandOptions (); + + virtual + ~CommandOptions (); + + virtual Error + SetOptionValue (int option_idx, const char *option_arg); + + void + ResetOptionValues (); + + const lldb::OptionDefinition* + GetDefinitions (); + + // Options table: Required for subclasses of Options. + + static lldb::OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + int32_t m_ignore_count; + lldb::tid_t m_thread_id; + uint32_t m_thread_index; + std::string m_thread_name; + std::string m_queue_name; }; diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp index dc1c84b0e649..cc0687c7b64d 100644 --- a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp @@ -34,7 +34,6 @@ using namespace lldb_private; CommandObjectBreakpointCommandAdd::CommandOptions::CommandOptions () : Options () { - BuildValidOptionSets(); } CommandObjectBreakpointCommandAdd::CommandOptions::~CommandOptions () @@ -532,7 +531,7 @@ CommandObjectBreakpointCommandList::Execute (Args& command, if (bp) { - BreakpointOptions *bp_options = NULL; + const BreakpointOptions *bp_options = NULL; if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID())); @@ -556,7 +555,7 @@ CommandObjectBreakpointCommandList::Execute (Args& command, { StreamString id_str; BreakpointID::GetCanonicalReference (&id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); - Baton *baton = bp_options->GetBaton(); + const Baton *baton = bp_options->GetBaton(); if (baton) { result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData()); diff --git a/lldb/source/Commands/CommandObjectFile.cpp b/lldb/source/Commands/CommandObjectFile.cpp index 09d9bd0c5582..af7e2fed943a 100644 --- a/lldb/source/Commands/CommandObjectFile.cpp +++ b/lldb/source/Commands/CommandObjectFile.cpp @@ -28,7 +28,6 @@ CommandObjectFile::CommandOptions::CommandOptions() : Options (), m_arch () // Breakpoint info defaults to brief descriptions { - BuildValidOptionSets(); } CommandObjectFile::CommandOptions::~CommandOptions () diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp index d887b09dd3a7..2dfbaa169780 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp +++ b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp @@ -1000,16 +1000,20 @@ ProcessMacOSX::EnableBreakpoint (BreakpointSite *bp_site) if (bp_site->HardwarePreferred()) { - ThreadMacOSX *thread = (ThreadMacOSX *)m_thread_list.FindThreadByID(bp_site->GetThreadID()).get(); - if (thread) - { - bp_site->SetHardwareIndex (thread->SetHardwareBreakpoint(bp_site)); - if (bp_site->IsHardware()) - { - bp_site->SetEnabled(true); - return error; - } - } + // FIXME: This code doesn't make sense. Breakpoint sites don't really have single ThreadID's, since one site could be + // owned by a number of Locations, each with a different Thread ID. So either this should run over all the Locations and + // set it for all threads owned by those locations, or set it for all threads, and let the thread specific code sort it out. + +// ThreadMacOSX *thread = (ThreadMacOSX *)m_thread_list.FindThreadByID(bp_site->GetThreadID()).get(); +// if (thread) +// { +// bp_site->SetHardwareIndex (thread->SetHardwareBreakpoint(bp_site)); +// if (bp_site->IsHardware()) +// { +// bp_site->SetEnabled(true); +// return error; +// } +// } } // Just let lldb::Process::EnableSoftwareBreakpoint() handle everything... @@ -1030,17 +1034,6 @@ ProcessMacOSX::DisableBreakpoint (BreakpointSite *bp_site) if (bp_site->IsHardware()) { - ThreadMacOSX *thread = (ThreadMacOSX *)m_thread_list.FindThreadByID(bp_site->GetThreadID()).get(); - if (thread) - { - if (thread->ClearHardwareBreakpoint(bp_site)) - { - bp_site->SetEnabled(false); - if (log) - log->Printf ("ProcessMacOSX::DisableBreakpoint (site_id = %d) addr = 0x%8.8llx -- SUCCESS (hardware)", site_id, (uint64_t)addr); - return error; - } - } error.SetErrorString("hardware breakpoints are no supported"); return error; } @@ -1068,20 +1061,8 @@ ProcessMacOSX::EnableWatchpoint (WatchpointLocation *wp) } else { - ThreadMacOSX *thread = (ThreadMacOSX *)m_thread_list.FindThreadByID(wp->GetThreadID()).get(); - if (thread) - { - wp->SetHardwareIndex (thread->SetHardwareWatchpoint (wp)); - if (wp->IsHardware ()) - { - wp->SetEnabled(true); - return error; - } - } - else - { - error.SetErrorString("Watchpoints currently only support thread specific watchpoints."); - } + // Watchpoints aren't supported at present. + error.SetErrorString("Watchpoints aren't currently supported."); } } return error; @@ -1103,17 +1084,7 @@ ProcessMacOSX::DisableWatchpoint (WatchpointLocation *wp) if (wp->IsHardware()) { - ThreadMacOSX *thread = (ThreadMacOSX *)m_thread_list.FindThreadByID(wp->GetThreadID()).get(); - if (thread) - { - if (thread->ClearHardwareWatchpoint (wp)) - { - wp->SetEnabled(false); - if (log) - log->Printf ("ProcessMacOSX::Disablewatchpoint (watchID = %d) addr = 0x%8.8llx (hardware) => success", watchID, (uint64_t)addr); - return error; - } - } + error.SetErrorString("Watchpoints aren't currently supported."); } // TODO: clear software watchpoints if we implement them error.SetErrorToGenericError(); diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.cpp b/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.cpp index 46d84a853d0a..826407662ad2 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.cpp +++ b/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.cpp @@ -81,11 +81,19 @@ ThreadMacOSX::GetRawStopReason (Thread::StopInfo *stop_info ) if (data_0 == MACH_SOFTWARE_BREAKPOINT_DATA_0) { lldb::addr_t pc = GetRegisterContext()->GetPC(); - lldb::user_id_t break_id = m_process.GetBreakpointSiteList().FindIDByAddress(pc); - if (break_id != LLDB_INVALID_BREAK_ID) + lldb::BreakpointSiteSP bp_site_sp = m_process.GetBreakpointSiteList().FindByAddress(pc); + if (bp_site_sp) { - stop_info->Clear (); - stop_info->SetStopReasonWithBreakpointSiteID (break_id); + if (bp_site_sp->ValidForThisThread (this)) + { + stop_info->Clear (); + stop_info->SetStopReasonWithBreakpointSiteID (GetID()); + } + else + { + stop_info->Clear (); + stop_info->SetStopReasonToNone(); + } return success; } } diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 81369c2368fc..a528120915d1 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1034,8 +1034,8 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) else if (exc_type == EXC_BREAKPOINT && exc_data[0] == MACH_EXC_DATA0_SOFTWARE_BREAKPOINT) { addr_t pc = gdb_thread->GetRegisterContext()->GetPC(); - user_id_t break_id = GetBreakpointSiteList().FindIDByAddress(pc); - if (break_id == LLDB_INVALID_BREAK_ID) + lldb::BreakpointSiteSP bp_site_sp = GetBreakpointSiteList().FindByAddress(pc); + if (!bp_site_sp) { //log->Printf("got EXC_BREAKPOINT at 0x%llx but didn't find a breakpoint site.\n", pc); stop_info.SetStopReasonWithException(exc_type, exc_data.size()); @@ -1044,8 +1044,17 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) } else { - stop_info.Clear (); - stop_info.SetStopReasonWithBreakpointSiteID (break_id); + if (bp_site_sp->ValidForThisThread (thread_sp.get())) + { + stop_info.Clear (); + stop_info.SetStopReasonWithBreakpointSiteID (bp_site_sp->GetID()); + } + else + { + stop_info.Clear (); + stop_info.SetStopReasonToNone(); + } + } } #endif diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index 068cc392f7d4..510988a15913 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "lldb/lldb-private-log.h" +#include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Log.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamString.h" @@ -29,6 +30,7 @@ #include "lldb/Target/ThreadPlanStepOverRange.h" #include "lldb/Target/ThreadPlanRunToAddress.h" #include "lldb/Target/ThreadPlanStepUntil.h" +#include "lldb/Target/ThreadSpec.h" using namespace lldb; using namespace lldb_private; @@ -292,14 +294,25 @@ Thread::StopInfo::Dump (Stream *s) const case eStopReasonBreakpoint: { bool no_details = true; - s->PutCString ("breakpoint "); + s->PutCString ("breakpoint"); if (m_thread) { BreakpointSiteSP bp_site_sp = m_thread->GetProcess().GetBreakpointSiteList().FindByID(m_details.breakpoint.bp_site_id); if (bp_site_sp) { - bp_site_sp->GetDescription(s, lldb::eDescriptionLevelBrief); - no_details = false; + // Only report the breakpoint locations that actually caused this hit - some of them may + // have options that would have caused us not to stop here... + uint32_t num_locations = bp_site_sp->GetNumberOfOwners(); + for (uint32_t i = 0; i < num_locations; i++) + { + BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(i); + if (bp_loc_sp->ValidForThisThread(m_thread)) + { + s->PutCString(" "); + bp_loc_sp->GetDescription(s, lldb::eDescriptionLevelBrief); + no_details = false; + } + } } } @@ -599,6 +612,27 @@ Thread::ShouldReportRun (Event* event_ptr) return GetCurrentPlan()->ShouldReportRun (event_ptr); } +bool +Thread::MatchesSpec (const ThreadSpec *spec) +{ + if (spec == NULL) + return true; + + if (!spec->TIDMatches(GetID())) + return false; + + if (!spec->IndexMatches(GetIndexID())) + return false; + + if (!spec->NameMatches (GetName())) + return false; + + if (!spec->QueueNameMatches (GetQueueName())) + return false; + + return true; +} + void Thread::PushPlan (ThreadPlanSP &thread_plan_sp) { @@ -990,7 +1024,7 @@ void Thread::DumpThreadPlans (lldb_private::Stream *s) const { uint32_t stack_size = m_plan_stack.size(); - s->Printf ("Plan Stack: %d elements.\n", stack_size); + s->Printf ("Plan Stack for thread #%u: tid = 0x%4.4x - %d elements.\n", GetIndexID(), GetID(), stack_size); for (int i = stack_size - 1; i > 0; i--) { s->Printf ("Element %d: ", i); diff --git a/lldb/source/Target/ThreadPlan.cpp b/lldb/source/Target/ThreadPlan.cpp index c9005c1f345f..3be8e9a36bd0 100644 --- a/lldb/source/Target/ThreadPlan.cpp +++ b/lldb/source/Target/ThreadPlan.cpp @@ -127,8 +127,8 @@ ThreadPlan::WillResume (StateType resume_state, bool current_plan) Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); if (log) - log->Printf("About to resume the \"%s\" plan - state: %s - stop others: %d.", - m_name.c_str(), StateAsCString(resume_state), StopOthers()); + log->Printf("Thread #%u: tid = 0x%4.4x about to resume the \"%s\" plan - state: %s - stop others: %d.", + m_thread.GetIndexID(), m_thread.GetID(), m_name.c_str(), StateAsCString(resume_state), StopOthers()); } return true; } diff --git a/lldb/source/Target/ThreadSpec.cpp b/lldb/source/Target/ThreadSpec.cpp new file mode 100644 index 000000000000..5d1089188fea --- /dev/null +++ b/lldb/source/Target/ThreadSpec.cpp @@ -0,0 +1,58 @@ +//===-- ThreadSpec.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/Target/Thread.h" +#include "lldb/Target/ThreadSpec.h" + +using namespace lldb; +using namespace lldb_private; + +ThreadSpec::ThreadSpec() : + m_index (-1), + m_tid (LLDB_INVALID_THREAD_ID), + m_name(), + m_queue_name () +{ +} + +ThreadSpec::ThreadSpec (const ThreadSpec &rhs) : + m_index(rhs.m_index), + m_tid(rhs.m_tid), + m_name(rhs.m_name), + m_queue_name(rhs.m_queue_name) +{ +} + +const ThreadSpec & +ThreadSpec::operator=(const ThreadSpec &rhs) +{ + m_index = rhs.m_index; + m_tid = rhs.m_tid; + m_name = rhs.m_name; + m_queue_name = rhs.m_queue_name; + return *this; +} + +const char * +ThreadSpec::GetName () const +{ + if (m_name.empty()) + return NULL; + else + return m_name.c_str(); +} + +const char * +ThreadSpec::GetQueueName () const +{ + if (m_queue_name.empty()) + return NULL; + else + return m_queue_name.c_str(); +}