diff options
Diffstat (limited to 'lldb/source')
19 files changed, 597 insertions, 112 deletions
diff --git a/lldb/source/API/SBBreakpointLocation.cpp b/lldb/source/API/SBBreakpointLocation.cpp index 8bb36bd7324..d917deab4f1 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 c475cf0f0d7..b3576b6a5da 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 c10aa770b82..0d9444f7371 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 0f82829bdd7..e00afcad750 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 7b574263003..464d38f1d78 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 4f664c4692f..695f4ee5ccd 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,19 +151,26 @@ BreakpointOptions::SetIgnoreCount (int32_t n) m_ignore_count = n; } -void -BreakpointOptions::SetThreadID (lldb::tid_t thread_id) +const ThreadSpec * +BreakpointOptions::GetThreadSpec () const { - m_thread_id = thread_id; + return m_thread_spec_ap.get(); } -lldb::tid_t -BreakpointOptions::GetThreadID () const +ThreadSpec * +BreakpointOptions::GetThreadSpec () { - return m_thread_id; + 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) +{ + GetThreadSpec()->SetTID(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 cd0920d07c7..d9397fcb412 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(), @@ -178,6 +177,12 @@ BreakpointSite::GetOwnerAtIndex (uint32_t 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 { // We only use software traps for software breakpoints diff --git a/lldb/source/Breakpoint/StoppointLocation.cpp b/lldb/source/Breakpoint/StoppointLocation.cpp index 999ad536ab8..60280ef2748 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 f765ef43202..bf24421a091 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 e001cbb4028..698a2999f4c 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, "<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(); +} + + diff --git a/lldb/source/Commands/CommandObjectBreakpoint.h b/lldb/source/Commands/CommandObjectBreakpoint.h index 8e705918c8f..7e7bd61181f 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 dc1c84b0e64..cc0687c7b64 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 09d9bd0c558..af7e2fed943 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 d887b09dd3a..2dfbaa16978 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 46d84a853d0..826407662ad 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 81369c2368f..a528120915d 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 068cc392f7d..510988a1591 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 c9005c1f345..3be8e9a36bd 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 00000000000..5d1089188fe --- /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(); +} |