summaryrefslogtreecommitdiffstats
path: root/lldb/source/Commands/CommandObjectBreakpoint.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Commands/CommandObjectBreakpoint.cpp')
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.cpp305
1 files changed, 299 insertions, 6 deletions
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();
+}
+
+
OpenPOWER on IntegriCloud