Add a "thread specification" class that specifies thread specific breakpoints by name, index, queue or TID.

Push this through all the breakpoint management code.  Allow this to be set when the breakpoint is created.
Fix the Process classes so that a breakpoint hit that is not for a particular thread is not reported as a 
breakpoint hit event for that thread.
Added a "breakpoint configure" command to allow you to reset any of the thread 
specific options (or the ignore count.)

llvm-svn: 106078
This commit is contained in:
Jim Ingham 2010-06-16 02:00:15 +00:00
parent babff2ce56
commit 1b54c88cc4
29 changed files with 804 additions and 142 deletions

View File

@ -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<lldb::BreakpointSP> bp_collection;

View File

@ -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;

View File

@ -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);

View File

@ -12,6 +12,7 @@
// C Includes
// C++ Includes
#include <memory>
// 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<ThreadSpec> m_thread_spec_ap; // Thread for which this breakpoint will take
};

View File

@ -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.

View File

@ -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)

View File

@ -262,6 +262,9 @@ public:
lldb::Vote
ShouldReportRun (Event *event_ptr);
virtual bool
MatchesSpec (const ThreadSpec *spec);
bool
GetStopInfo (StopInfo *stop_info);

View File

@ -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 <map>
#include <string>
#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_

View File

@ -129,6 +129,7 @@ class ThreadPlanStepOverBreakpoint;
class ThreadPlanStepThrough;
class ThreadPlanStepRange;
class ThreadPlanRunToAddress;
class ThreadSpec;
class TimeValue;
class Type;
class TypeList;

View File

@ -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 = "<group>"; };
4C00986F11500B4300F316B0 /* UnixSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnixSignals.h; path = include/lldb/Target/UnixSignals.h; sourceTree = "<group>"; };
4C00987011500B4300F316B0 /* UnixSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnixSignals.cpp; path = source/Target/UnixSignals.cpp; sourceTree = "<group>"; };
4C08CDE711C81EF8001610A8 /* ThreadSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadSpec.cpp; path = source/Target/ThreadSpec.cpp; sourceTree = "<group>"; };
4C08CDEB11C81F1E001610A8 /* ThreadSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSpec.h; path = include/lldb/Target/ThreadSpec.h; sourceTree = "<group>"; };
4C09CB73116BD98B00C7A725 /* CommandCompletions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandCompletions.h; path = include/lldb/Interpreter/CommandCompletions.h; sourceTree = "<group>"; };
4C09CB74116BD98B00C7A725 /* CommandCompletions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandCompletions.cpp; path = source/Commands/CommandCompletions.cpp; sourceTree = "<group>"; };
4C43DEF9110641F300E55CBF /* ThreadPlanShouldStopHere.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanShouldStopHere.h; path = include/lldb/Target/ThreadPlanShouldStopHere.h; sourceTree = "<group>"; };
@ -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;
};

View File

@ -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;
}

View File

@ -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

View File

@ -196,3 +196,9 @@ BreakpointList::ClearAllBreakpointSites ()
(*pos)->ClearAllBreakpointSites ();
}
void
BreakpointList::GetListMutex (Mutex::Locker &locker)
{
return locker.Reset (m_mutex.GetMutex());
}

View File

@ -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",

View File

@ -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)
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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",

View File

@ -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, "<thread_index>",
"The breakpoint stops only for the thread whose indeX matches this argument."},
{ LLDB_OPT_SET_ALL, false, "thread_id", 't', required_argument, NULL, NULL, "<thread_id>",
"The breakpoint stops only for the thread whose TID matches this argument."},
{ LLDB_OPT_SET_ALL, false, "thread_name", 'T', required_argument, NULL, NULL, "<thread_name>",
"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, "<queue_name>",
"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, "<filename>",
"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, "<thread_index>",
"The breakpoint stops only for the thread whose indeX matches this argument."},
{ LLDB_OPT_SET_ALL, false, "thread_id", 't', required_argument, NULL, NULL, "<thread_id>",
"The breakpoint stops only for the thread whose TID matches this argument."},
{ LLDB_OPT_SET_ALL, false, "thread_name", 'T', required_argument, NULL, NULL, "<thread_name>",
"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, "<queue_name>",
"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 <cmd-options> 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();
}

View File

@ -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;
};

View File

@ -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());

View File

@ -28,7 +28,6 @@ CommandObjectFile::CommandOptions::CommandOptions() :
Options (),
m_arch () // Breakpoint info defaults to brief descriptions
{
BuildValidOptionSets();
}
CommandObjectFile::CommandOptions::~CommandOptions ()

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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();
}