summaryrefslogtreecommitdiffstats
path: root/source/Commands
diff options
context:
space:
mode:
Diffstat (limited to 'source/Commands')
-rw-r--r--source/Commands/CommandCompletions.cpp6
-rw-r--r--source/Commands/CommandObjectBreakpoint.cpp588
-rw-r--r--source/Commands/CommandObjectBreakpoint.h14
-rw-r--r--source/Commands/CommandObjectBreakpointCommand.cpp112
-rw-r--r--source/Commands/CommandObjectCommands.cpp238
-rw-r--r--source/Commands/CommandObjectExpression.cpp6
-rw-r--r--source/Commands/CommandObjectMemory.cpp113
-rw-r--r--source/Commands/CommandObjectPlatform.cpp5
-rw-r--r--source/Commands/CommandObjectProcess.cpp27
-rw-r--r--source/Commands/CommandObjectSource.cpp12
-rw-r--r--source/Commands/CommandObjectSyntax.cpp6
-rw-r--r--source/Commands/CommandObjectTarget.cpp120
-rw-r--r--source/Commands/CommandObjectThread.cpp666
-rw-r--r--source/Commands/CommandObjectType.cpp125
-rw-r--r--source/Commands/CommandObjectWatchpointCommand.cpp15
15 files changed, 1618 insertions, 435 deletions
diff --git a/source/Commands/CommandCompletions.cpp b/source/Commands/CommandCompletions.cpp
index f0ad4a8..c65dd9d 100644
--- a/source/Commands/CommandCompletions.cpp
+++ b/source/Commands/CommandCompletions.cpp
@@ -112,7 +112,7 @@ CommandCompletions::SourceFiles
if (searcher == NULL)
{
lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
- SearchFilter null_searcher (target_sp);
+ SearchFilterForUnconstrainedSearches null_searcher (target_sp);
completer.DoCompletion (&null_searcher);
}
else
@@ -375,7 +375,7 @@ CommandCompletions::Modules
if (searcher == NULL)
{
lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
- SearchFilter null_searcher (target_sp);
+ SearchFilterForUnconstrainedSearches null_searcher (target_sp);
completer.DoCompletion (&null_searcher);
}
else
@@ -406,7 +406,7 @@ CommandCompletions::Symbols
if (searcher == NULL)
{
lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
- SearchFilter null_searcher (target_sp);
+ SearchFilterForUnconstrainedSearches null_searcher (target_sp);
completer.DoCompletion (&null_searcher);
}
else
diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp
index 13bf127..3d4b3af 100644
--- a/source/Commands/CommandObjectBreakpoint.cpp
+++ b/source/Commands/CommandObjectBreakpoint.cpp
@@ -20,6 +20,8 @@
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Interpreter/Options.h"
+#include "lldb/Interpreter/OptionValueString.h"
+#include "lldb/Interpreter/OptionValueUInt64.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -145,6 +147,10 @@ public:
m_condition.assign(option_arg);
break;
+ case 'D':
+ m_use_dummy = true;
+ break;
+
case 'E':
{
LanguageType language = LanguageRuntime::GetLanguageTypeFromString (option_arg);
@@ -236,6 +242,11 @@ public:
m_func_name_type_mask |= eFunctionNameTypeAuto;
break;
+ case 'N':
+ if (BreakpointID::StringIsBreakpointName(option_arg, error))
+ m_breakpoint_names.push_back (option_arg);
+ break;
+
case 'o':
m_one_shot = true;
break;
@@ -324,6 +335,8 @@ public:
m_language = eLanguageTypeUnknown;
m_skip_prologue = eLazyBoolCalculate;
m_one_shot = false;
+ m_use_dummy = false;
+ m_breakpoint_names.clear();
}
const OptionDefinition*
@@ -343,6 +356,7 @@ public:
uint32_t m_line_num;
uint32_t m_column;
std::vector<std::string> m_func_names;
+ std::vector<std::string> m_breakpoint_names;
uint32_t m_func_name_type_mask;
std::string m_func_regexp;
std::string m_source_text_regexp;
@@ -359,16 +373,18 @@ public:
lldb::LanguageType m_language;
LazyBool m_skip_prologue;
bool m_one_shot;
+ bool m_use_dummy;
};
protected:
virtual bool
DoExecute (Args& command,
- CommandReturnObject &result)
+ CommandReturnObject &result)
{
- Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
- if (target == NULL)
+ Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
+
+ if (target == nullptr)
{
result.AppendError ("Invalid target. Must set target before setting breakpoints (see 'target create' command).");
result.SetStatus (eReturnStatusFailed);
@@ -551,6 +567,13 @@ protected:
if (!m_options.m_condition.empty())
bp->GetOptions()->SetCondition(m_options.m_condition.c_str());
+
+ if (!m_options.m_breakpoint_names.empty())
+ {
+ Error error; // We don't need to check the error here, since the option parser checked it...
+ for (auto name : m_options.m_breakpoint_names)
+ bp->AddName(name.c_str(), error);
+ }
bp->SetOneShot (m_options.m_one_shot);
}
@@ -560,10 +583,17 @@ protected:
Stream &output_stream = result.GetOutputStream();
const bool show_locations = false;
bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, show_locations);
- // Don't print out this warning for exception breakpoints. They can get set before the target
- // is set, but we won't know how to actually set the breakpoint till we run.
- if (bp->GetNumLocations() == 0 && break_type != eSetTypeException)
- output_stream.Printf ("WARNING: Unable to resolve breakpoint to any actual locations.\n");
+ if (target == m_interpreter.GetDebugger().GetDummyTarget())
+ output_stream.Printf ("Breakpoint set in dummy target, will get copied into future targets.\n");
+ else
+ {
+ // Don't print out this warning for exception breakpoints. They can get set before the target
+ // is set, but we won't know how to actually set the breakpoint till we run.
+ if (bp->GetNumLocations() == 0 && break_type != eSetTypeException)
+ {
+ output_stream.Printf ("WARNING: Unable to resolve breakpoint to any actual locations.\n");
+ }
+ }
result.SetStatus (eReturnStatusSuccessFinishResult);
}
else if (!bp)
@@ -709,6 +739,12 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
{ LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
"sKip the prologue if the breakpoint is at the beginning of a function. If not set the target.skip-prologue setting is used." },
+ { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
+ "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
+
+ { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBreakpointName,
+ "Adds this to the list of names for this breakopint."},
+
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -766,7 +802,8 @@ public:
m_name_passed (false),
m_queue_passed (false),
m_condition_passed (false),
- m_one_shot_passed (false)
+ m_one_shot_passed (false),
+ m_use_dummy (false)
{
}
@@ -792,6 +829,9 @@ public:
m_enable_passed = true;
m_enable_value = false;
break;
+ case 'D':
+ m_use_dummy = true;
+ break;
case 'e':
m_enable_passed = true;
m_enable_value = true;
@@ -888,6 +928,7 @@ public:
m_name_passed = false;
m_condition_passed = false;
m_one_shot_passed = false;
+ m_use_dummy = false;
}
const OptionDefinition*
@@ -918,6 +959,7 @@ public:
bool m_queue_passed;
bool m_condition_passed;
bool m_one_shot_passed;
+ bool m_use_dummy;
};
@@ -925,7 +967,7 @@ protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
- Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
if (target == NULL)
{
result.AppendError ("Invalid target. No existing target or breakpoints.");
@@ -938,7 +980,7 @@ protected:
BreakpointIDList valid_bp_ids;
- CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
if (result.Succeeded())
{
@@ -1024,6 +1066,8 @@ CommandObjectBreakpointModify::CommandOptions::g_option_table[] =
{ LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."},
{ LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Enable the breakpoint."},
{ LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Disable the breakpoint."},
+{ LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
+
{ 0, false, NULL, 0 , 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -1055,7 +1099,7 @@ protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
- Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ Target *target = GetSelectedOrDummyTarget();
if (target == NULL)
{
result.AppendError ("Invalid target. No existing target or breakpoints.");
@@ -1088,7 +1132,7 @@ protected:
{
// Particular breakpoint selected; enable that breakpoint.
BreakpointIDList valid_bp_ids;
- CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
if (result.Succeeded())
{
@@ -1175,7 +1219,7 @@ protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
- Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ Target *target = GetSelectedOrDummyTarget();
if (target == NULL)
{
result.AppendError ("Invalid target. No existing target or breakpoints.");
@@ -1208,7 +1252,7 @@ protected:
// Particular breakpoint selected; disable that breakpoint.
BreakpointIDList valid_bp_ids;
- CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
if (result.Succeeded())
{
@@ -1293,7 +1337,8 @@ public:
CommandOptions (CommandInterpreter &interpreter) :
Options (interpreter),
- m_level (lldb::eDescriptionLevelBrief) // Breakpoint List defaults to brief descriptions
+ m_level (lldb::eDescriptionLevelBrief),
+ m_use_dummy(false)
{
}
@@ -1311,6 +1356,9 @@ public:
case 'b':
m_level = lldb::eDescriptionLevelBrief;
break;
+ case 'D':
+ m_use_dummy = true;
+ break;
case 'f':
m_level = lldb::eDescriptionLevelFull;
break;
@@ -1333,6 +1381,7 @@ public:
{
m_level = lldb::eDescriptionLevelFull;
m_internal = false;
+ m_use_dummy = false;
}
const OptionDefinition *
@@ -1350,13 +1399,15 @@ public:
lldb::DescriptionLevel m_level;
bool m_internal;
+ bool m_use_dummy;
};
protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
- Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
+
if (target == NULL)
{
result.AppendError ("Invalid target. No current target or breakpoints.");
@@ -1394,7 +1445,7 @@ protected:
{
// Particular breakpoints selected; show info about that breakpoint.
BreakpointIDList valid_bp_ids;
- CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
if (result.Succeeded())
{
@@ -1438,6 +1489,9 @@ CommandObjectBreakpointList::CommandOptions::g_option_table[] =
{ LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"Explain everything we know about the breakpoint (for debugging debugger bugs)." },
+ { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
+ "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
+
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -1540,7 +1594,7 @@ protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
- Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ Target *target = GetSelectedOrDummyTarget();
if (target == NULL)
{
result.AppendError ("Invalid target. No existing target or breakpoints.");
@@ -1656,7 +1710,8 @@ public:
CommandObjectParsed (interpreter,
"breakpoint delete",
"Delete the specified breakpoint(s). If no breakpoints are specified, delete them all.",
- NULL)
+ NULL),
+ m_options (interpreter)
{
CommandArgumentEntry arg;
CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);
@@ -1667,11 +1722,78 @@ public:
virtual
~CommandObjectBreakpointDelete () {}
+ virtual Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options (interpreter),
+ m_use_dummy (false),
+ m_force (false)
+ {
+ }
+
+ virtual
+ ~CommandOptions () {}
+
+ virtual Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg)
+ {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'f':
+ m_force = true;
+ break;
+
+ case 'D':
+ m_use_dummy = true;
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ OptionParsingStarting ()
+ {
+ m_use_dummy = false;
+ m_force = false;
+ }
+
+ const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ bool m_use_dummy;
+ bool m_force;
+ };
+
protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
- Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
+
if (target == NULL)
{
result.AppendError ("Invalid target. No existing target or breakpoints.");
@@ -1695,7 +1817,7 @@ protected:
if (command.GetArgumentCount() == 0)
{
- if (!m_interpreter.Confirm ("About to delete all breakpoints, do you want to do that?", true))
+ if (!m_options.m_force && !m_interpreter.Confirm ("About to delete all breakpoints, do you want to do that?", true))
{
result.AppendMessage("Operation cancelled...");
}
@@ -1710,7 +1832,7 @@ protected:
{
// Particular breakpoint selected; disable that breakpoint.
BreakpointIDList valid_bp_ids;
- CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
if (result.Succeeded())
{
@@ -1748,7 +1870,416 @@ protected:
}
return result.Succeeded();
}
+private:
+ CommandOptions m_options;
+};
+
+OptionDefinition
+CommandObjectBreakpointDelete::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
+ "Delete all breakpoints without querying for confirmation."},
+
+ { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
+ "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
+
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointName
+//-------------------------------------------------------------------------
+
+static OptionDefinition
+g_breakpoint_name_options[] =
+{
+ { LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
+ { LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBreakpointID, "Specify a breakpoint id to use."},
+ { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
+ "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
};
+class BreakpointNameOptionGroup : public OptionGroup
+{
+public:
+ BreakpointNameOptionGroup() :
+ OptionGroup(),
+ m_breakpoint(LLDB_INVALID_BREAK_ID),
+ m_use_dummy (false)
+ {
+
+ }
+
+ virtual
+ ~BreakpointNameOptionGroup ()
+ {
+ }
+
+ virtual uint32_t
+ GetNumDefinitions ()
+ {
+ return sizeof (g_breakpoint_name_options) / sizeof (OptionDefinition);
+ }
+
+ virtual const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_breakpoint_name_options;
+ }
+
+ virtual Error
+ SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value)
+ {
+ Error error;
+ const int short_option = g_breakpoint_name_options[option_idx].short_option;
+
+ switch (short_option)
+ {
+ case 'N':
+ if (BreakpointID::StringIsBreakpointName(option_value, error) && error.Success())
+ m_name.SetValueFromCString(option_value);
+ break;
+
+ case 'B':
+ if (m_breakpoint.SetValueFromCString(option_value).Fail())
+ error.SetErrorStringWithFormat ("unrecognized value \"%s\" for breakpoint", option_value);
+ break;
+ case 'D':
+ if (m_use_dummy.SetValueFromCString(option_value).Fail())
+ error.SetErrorStringWithFormat ("unrecognized value \"%s\" for use-dummy", option_value);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
+ break;
+ }
+ return error;
+ }
+
+ virtual void
+ OptionParsingStarting (CommandInterpreter &interpreter)
+ {
+ m_name.Clear();
+ m_breakpoint.Clear();
+ m_use_dummy.Clear();
+ m_use_dummy.SetDefaultValue(false);
+ }
+
+ OptionValueString m_name;
+ OptionValueUInt64 m_breakpoint;
+ OptionValueBoolean m_use_dummy;
+};
+
+
+class CommandObjectBreakpointNameAdd : public CommandObjectParsed
+{
+public:
+ CommandObjectBreakpointNameAdd (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "add",
+ "Add a name to the breakpoints provided.",
+ "breakpoint name add <command-options> <breakpoint-id-list>"),
+ m_name_options(),
+ m_option_group(interpreter)
+ {
+ // Create the first variant for the first (and only) argument for this command.
+ CommandArgumentEntry arg1;
+ CommandArgumentData id_arg;
+ id_arg.arg_type = eArgTypeBreakpointID;
+ id_arg.arg_repetition = eArgRepeatOptional;
+ arg1.push_back(id_arg);
+ m_arguments.push_back (arg1);
+
+ m_option_group.Append (&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
+ m_option_group.Finalize();
+ }
+
+ virtual
+ ~CommandObjectBreakpointNameAdd () {}
+
+ Options *
+ GetOptions ()
+ {
+ return &m_option_group;
+ }
+
+protected:
+ virtual bool
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+ if (!m_name_options.m_name.OptionWasSet())
+ {
+ result.SetError("No name option provided.");
+ return false;
+ }
+
+ Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
+
+ if (target == NULL)
+ {
+ result.AppendError ("Invalid target. No existing target or breakpoints.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ Mutex::Locker locker;
+ target->GetBreakpointList().GetListMutex(locker);
+
+ const BreakpointList &breakpoints = target->GetBreakpointList();
+
+ size_t num_breakpoints = breakpoints.GetSize();
+ if (num_breakpoints == 0)
+ {
+ result.SetError("No breakpoints, cannot add names.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ // Particular breakpoint selected; disable that breakpoint.
+ BreakpointIDList valid_bp_ids;
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+
+ if (result.Succeeded())
+ {
+ if (valid_bp_ids.GetSize() == 0)
+ {
+ result.SetError("No breakpoints specified, cannot add names.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ size_t num_valid_ids = valid_bp_ids.GetSize();
+ for (size_t index = 0; index < num_valid_ids; index++)
+ {
+ lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
+ BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
+ Error error; // We don't need to check the error here, since the option parser checked it...
+ bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error);
+ }
+ }
+
+ return true;
+ }
+
+private:
+ BreakpointNameOptionGroup m_name_options;
+ OptionGroupOptions m_option_group;
+};
+
+
+
+class CommandObjectBreakpointNameDelete : public CommandObjectParsed
+{
+public:
+ CommandObjectBreakpointNameDelete (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "delete",
+ "Delete a name from the breakpoints provided.",
+ "breakpoint name delete <command-options> <breakpoint-id-list>"),
+ m_name_options(),
+ m_option_group(interpreter)
+ {
+ // Create the first variant for the first (and only) argument for this command.
+ CommandArgumentEntry arg1;
+ CommandArgumentData id_arg;
+ id_arg.arg_type = eArgTypeBreakpointID;
+ id_arg.arg_repetition = eArgRepeatOptional;
+ arg1.push_back(id_arg);
+ m_arguments.push_back (arg1);
+
+ m_option_group.Append (&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
+ m_option_group.Finalize();
+ }
+
+ virtual
+ ~CommandObjectBreakpointNameDelete () {}
+
+ Options *
+ GetOptions ()
+ {
+ return &m_option_group;
+ }
+
+protected:
+ virtual bool
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+ if (!m_name_options.m_name.OptionWasSet())
+ {
+ result.SetError("No name option provided.");
+ return false;
+ }
+
+ Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
+
+ if (target == NULL)
+ {
+ result.AppendError ("Invalid target. No existing target or breakpoints.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ Mutex::Locker locker;
+ target->GetBreakpointList().GetListMutex(locker);
+
+ const BreakpointList &breakpoints = target->GetBreakpointList();
+
+ size_t num_breakpoints = breakpoints.GetSize();
+ if (num_breakpoints == 0)
+ {
+ result.SetError("No breakpoints, cannot delete names.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ // Particular breakpoint selected; disable that breakpoint.
+ BreakpointIDList valid_bp_ids;
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+
+ if (result.Succeeded())
+ {
+ if (valid_bp_ids.GetSize() == 0)
+ {
+ result.SetError("No breakpoints specified, cannot delete names.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ size_t num_valid_ids = valid_bp_ids.GetSize();
+ for (size_t index = 0; index < num_valid_ids; index++)
+ {
+ lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
+ BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
+ bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue());
+ }
+ }
+
+ return true;
+ }
+
+private:
+ BreakpointNameOptionGroup m_name_options;
+ OptionGroupOptions m_option_group;
+};
+
+class CommandObjectBreakpointNameList : public CommandObjectParsed
+{
+public:
+ CommandObjectBreakpointNameList (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "list",
+ "List either the names for a breakpoint or the breakpoints for a given name.",
+ "breakpoint name list <command-options>"),
+ m_name_options(),
+ m_option_group(interpreter)
+ {
+ m_option_group.Append (&m_name_options);
+ m_option_group.Finalize();
+ }
+
+ virtual
+ ~CommandObjectBreakpointNameList () {}
+
+ Options *
+ GetOptions ()
+ {
+ return &m_option_group;
+ }
+
+protected:
+protected:
+ virtual bool
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+ Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
+
+ if (target == NULL)
+ {
+ result.AppendError ("Invalid target. No existing target or breakpoints.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (m_name_options.m_name.OptionWasSet())
+ {
+ const char *name = m_name_options.m_name.GetCurrentValue();
+ Mutex::Locker locker;
+ target->GetBreakpointList().GetListMutex(locker);
+
+ BreakpointList &breakpoints = target->GetBreakpointList();
+ for (BreakpointSP bp_sp : breakpoints.Breakpoints())
+ {
+ if (bp_sp->MatchesName(name))
+ {
+ StreamString s;
+ bp_sp->GetDescription(&s, eDescriptionLevelBrief);
+ s.EOL();
+ result.AppendMessage(s.GetData());
+ }
+ }
+
+ }
+ else if (m_name_options.m_breakpoint.OptionWasSet())
+ {
+ BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID(m_name_options.m_breakpoint.GetCurrentValue());
+ if (bp_sp)
+ {
+ std::vector<std::string> names;
+ bp_sp->GetNames (names);
+ result.AppendMessage ("Names:");
+ for (auto name : names)
+ result.AppendMessageWithFormat (" %s\n", name.c_str());
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Could not find breakpoint %" PRId64 ".\n",
+ m_name_options.m_breakpoint.GetCurrentValue());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ result.SetError ("Must specify -N or -B option to list.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ return true;
+ }
+
+private:
+ BreakpointNameOptionGroup m_name_options;
+ OptionGroupOptions m_option_group;
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordBreakpoint
+//-------------------------------------------------------------------------
+class CommandObjectBreakpointName : public CommandObjectMultiword
+{
+public:
+ CommandObjectBreakpointName (CommandInterpreter &interpreter) :
+ CommandObjectMultiword(interpreter,
+ "name",
+ "A set of commands to manage name tags for breakpoints",
+ "breakpoint name <command> [<command-options>]")
+ {
+ CommandObjectSP add_command_object (new CommandObjectBreakpointNameAdd (interpreter));
+ CommandObjectSP delete_command_object (new CommandObjectBreakpointNameDelete (interpreter));
+ CommandObjectSP list_command_object (new CommandObjectBreakpointNameList (interpreter));
+
+ LoadSubCommand ("add", add_command_object);
+ LoadSubCommand ("delete", delete_command_object);
+ LoadSubCommand ("list", list_command_object);
+
+ }
+
+ virtual
+ ~CommandObjectBreakpointName ()
+ {
+ }
+
+};
+
//-------------------------------------------------------------------------
// CommandObjectMultiwordBreakpoint
@@ -1769,6 +2300,7 @@ CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInter
CommandObjectSP set_command_object (new CommandObjectBreakpointSet (interpreter));
CommandObjectSP command_command_object (new CommandObjectBreakpointCommand (interpreter));
CommandObjectSP modify_command_object (new CommandObjectBreakpointModify(interpreter));
+ CommandObjectSP name_command_object (new CommandObjectBreakpointName(interpreter));
list_command_object->SetCommandName ("breakpoint list");
enable_command_object->SetCommandName("breakpoint enable");
@@ -1778,6 +2310,7 @@ CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInter
set_command_object->SetCommandName("breakpoint set");
command_command_object->SetCommandName ("breakpoint command");
modify_command_object->SetCommandName ("breakpoint modify");
+ name_command_object->SetCommandName ("breakpoint name");
LoadSubCommand ("list", list_command_object);
LoadSubCommand ("enable", enable_command_object);
@@ -1787,6 +2320,7 @@ CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInter
LoadSubCommand ("set", set_command_object);
LoadSubCommand ("command", command_command_object);
LoadSubCommand ("modify", modify_command_object);
+ LoadSubCommand ("name", name_command_object);
}
CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint ()
@@ -1794,13 +2328,17 @@ CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint ()
}
void
-CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result,
- BreakpointIDList *valid_ids)
+CommandObjectMultiwordBreakpoint::VerifyIDs (Args &args,
+ Target *target,
+ bool allow_locations,
+ CommandReturnObject &result,
+ BreakpointIDList *valid_ids)
{
// args can be strings representing 1). integers (for breakpoint ids)
// 2). the full breakpoint & location canonical representation
// 3). the word "to" or a hyphen, representing a range (in which case there
// had *better* be an entry both before & after of one of the first two types.
+ // 4). A breakpoint name
// If args is empty, we will use the last created breakpoint (if there is one.)
Args temp_args;
@@ -1824,7 +2362,7 @@ CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (Args &args, Target *targe
// the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead generate a list of strings for
// all the breakpoint ids in the range, and shove all of those breakpoint id strings into TEMP_ARGS.
- BreakpointIDList::FindAndReplaceIDRanges (args, target, result, temp_args);
+ BreakpointIDList::FindAndReplaceIDRanges (args, target, allow_locations, result, temp_args);
// NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual BreakpointIDList:
diff --git a/source/Commands/CommandObjectBreakpoint.h b/source/Commands/CommandObjectBreakpoint.h
index 2d674b2..3fdd2a5 100644
--- a/source/Commands/CommandObjectBreakpoint.h
+++ b/source/Commands/CommandObjectBreakpoint.h
@@ -38,8 +38,20 @@ public:
~CommandObjectMultiwordBreakpoint ();
static void
- VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids);
+ VerifyBreakpointOrLocationIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids)
+ {
+ VerifyIDs (args, target, true, result, valid_ids);
+ }
+ static void
+ VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids)
+ {
+ VerifyIDs (args, target, false, result, valid_ids);
+ }
+
+private:
+ static void
+ VerifyIDs (Args &args, Target *target, bool allow_locations, CommandReturnObject &result, BreakpointIDList *valid_ids);
};
} // namespace lldb_private
diff --git a/source/Commands/CommandObjectBreakpointCommand.cpp b/source/Commands/CommandObjectBreakpointCommand.cpp
index fdb87d1..8f8404b 100644
--- a/source/Commands/CommandObjectBreakpointCommand.cpp
+++ b/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -307,17 +307,16 @@ one command per line.\n" );
result.SetImmediateOutputStream (output_stream);
result.SetImmediateErrorStream (error_stream);
- bool stop_on_continue = true;
- bool echo_commands = false;
- bool print_results = true;
-
- debugger.GetCommandInterpreter().HandleCommands (commands,
+ CommandInterpreterRunOptions options;
+ options.SetStopOnContinue(true);
+ options.SetStopOnError (data->stop_on_error);
+ options.SetEchoCommands (true);
+ options.SetPrintResults (true);
+ options.SetAddToHistory (false);
+
+ debugger.GetCommandInterpreter().HandleCommands (commands,
&exe_ctx,
- stop_on_continue,
- data->stop_on_error,
- echo_commands,
- print_results,
- eLazyBoolNo,
+ options,
result);
result.GetImmediateOutputStream()->Flush();
result.GetImmediateErrorStream()->Flush();
@@ -390,6 +389,10 @@ one command per line.\n" );
}
break;
+ case 'D':
+ m_use_dummy = true;
+ break;
+
default:
break;
}
@@ -406,6 +409,7 @@ one command per line.\n" );
m_stop_on_error = true;
m_one_liner.clear();
m_function_name.clear();
+ m_use_dummy = false;
}
const OptionDefinition*
@@ -429,13 +433,14 @@ one command per line.\n" );
std::string m_one_liner;
bool m_stop_on_error;
std::string m_function_name;
+ bool m_use_dummy;
};
protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
- Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
if (target == NULL)
{
@@ -462,7 +467,7 @@ protected:
}
BreakpointIDList valid_bp_ids;
- CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
m_bp_options_vec.clear();
@@ -581,6 +586,9 @@ CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
{ LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction,
"Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
+ { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
+ "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
+
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -595,7 +603,8 @@ public:
CommandObjectParsed (interpreter,
"delete",
"Delete the set of commands from a breakpoint.",
- NULL)
+ NULL),
+ m_options (interpreter)
{
CommandArgumentEntry arg;
CommandArgumentData bp_id_arg;
@@ -615,11 +624,70 @@ public:
virtual
~CommandObjectBreakpointCommandDelete () {}
+ virtual Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options (interpreter),
+ m_use_dummy (false)
+ {
+ }
+
+ virtual
+ ~CommandOptions () {}
+
+ virtual Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg)
+ {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'D':
+ m_use_dummy = true;
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ OptionParsingStarting ()
+ {
+ m_use_dummy = false;
+ }
+
+ const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ bool m_use_dummy;
+ };
+
protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
- Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
if (target == NULL)
{
@@ -646,7 +714,7 @@ protected:
}
BreakpointIDList valid_bp_ids;
- CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
if (result.Succeeded())
{
@@ -680,8 +748,20 @@ protected:
}
return result.Succeeded();
}
+private:
+ CommandOptions m_options;
+};
+
+OptionDefinition
+CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
+ "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
+
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
+
//-------------------------------------------------------------------------
// CommandObjectBreakpointCommandList
//-------------------------------------------------------------------------
@@ -744,7 +824,7 @@ protected:
}
BreakpointIDList valid_bp_ids;
- CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
if (result.Succeeded())
{
diff --git a/source/Commands/CommandObjectCommands.cpp b/source/Commands/CommandObjectCommands.cpp
index 7d9bb7d..f98eac0 100644
--- a/source/Commands/CommandObjectCommands.cpp
+++ b/source/Commands/CommandObjectCommands.cpp
@@ -366,7 +366,7 @@ protected:
// Instance variables to hold the values for command options.
OptionValueBoolean m_stop_on_error;
- OptionValueBoolean m_silent_run;
+ OptionValueBoolean m_silent_run;
OptionValueBoolean m_stop_on_continue;
};
@@ -387,14 +387,15 @@ protected:
m_options.m_stop_on_continue.OptionWasSet())
{
// Use user set settings
- LazyBool print_command = m_options.m_silent_run.GetCurrentValue() ? eLazyBoolNo : eLazyBoolYes;
+ CommandInterpreterRunOptions options;
+ options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue());
+ options.SetStopOnError (m_options.m_stop_on_error.GetCurrentValue());
+ options.SetEchoCommands (!m_options.m_silent_run.GetCurrentValue());
+ options.SetPrintResults (!m_options.m_silent_run.GetCurrentValue());
+
m_interpreter.HandleCommandsFromFile (cmd_file,
exe_ctx,
- m_options.m_stop_on_continue.GetCurrentValue() ? eLazyBoolYes : eLazyBoolNo, // Stop on continue
- m_options.m_stop_on_error.GetCurrentValue() ? eLazyBoolYes : eLazyBoolNo, // Stop on error
- print_command, // Echo command
- print_command, // Print command output
- eLazyBoolCalculate, // Add to history
+ options,
result);
}
@@ -402,13 +403,10 @@ protected:
{
// No options were set, inherit any settings from nested "command source" commands,
// or set to sane default settings...
+ CommandInterpreterRunOptions options;
m_interpreter.HandleCommandsFromFile (cmd_file,
exe_ctx,
- eLazyBoolCalculate, // Stop on continue
- eLazyBoolCalculate, // Stop on error
- eLazyBoolCalculate, // Echo command
- eLazyBoolCalculate, // Print command output
- eLazyBoolCalculate, // Add to history
+ options,
result);
}
@@ -830,8 +828,16 @@ protected:
{
if (m_interpreter.CommandExists (command_name))
{
- result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
- command_name);
+ if (cmd_obj->IsRemovable())
+ {
+ result.AppendErrorWithFormat ("'%s' is not an alias, it is a debugger command which can be removed using the 'command delete' command.\n",
+ command_name);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
+ command_name);
+ }
result.SetStatus (eReturnStatusFailed);
}
else
@@ -868,6 +874,77 @@ protected:
}
};
+#pragma mark CommandObjectCommandsDelete
+//-------------------------------------------------------------------------
+// CommandObjectCommandsDelete
+//-------------------------------------------------------------------------
+
+class CommandObjectCommandsDelete : public CommandObjectParsed
+{
+public:
+ CommandObjectCommandsDelete (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "command delete",
+ "Allow the user to delete user-defined regular expression, python or multi-word commands.",
+ NULL)
+ {
+ CommandArgumentEntry arg;
+ CommandArgumentData alias_arg;
+
+ // Define the first (and only) variant of this arg.
+ alias_arg.arg_type = eArgTypeCommandName;
+ alias_arg.arg_repetition = eArgRepeatPlain;
+
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg.push_back (alias_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back (arg);
+ }
+
+ ~CommandObjectCommandsDelete()
+ {
+ }
+
+protected:
+ bool
+ DoExecute (Args& args, CommandReturnObject &result)
+ {
+ CommandObject::CommandMap::iterator pos;
+
+ if (args.GetArgumentCount() != 0)
+ {
+ const char *command_name = args.GetArgumentAtIndex(0);
+ if (m_interpreter.CommandExists (command_name))
+ {
+ if (m_interpreter.RemoveCommand (command_name))
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
+ command_name);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
+ command_name);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("must call '%s' with one or more valid user defined regular expression, python or multi-word command names", GetCommandName ());
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ return result.Succeeded();
+ }
+};
+
//-------------------------------------------------------------------------
// CommandObjectCommandsAddRegex
//-------------------------------------------------------------------------
@@ -875,7 +952,7 @@ protected:
class CommandObjectCommandsAddRegex :
public CommandObjectParsed,
- public IOHandlerDelegate
+ public IOHandlerDelegateMultiline
{
public:
CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
@@ -883,7 +960,7 @@ public:
"command regex",
"Allow the user to create a regular expression command.",
"command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
- IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand),
+ IOHandlerDelegateMultiline ("", IOHandlerDelegate::Completion::LLDBCommand),
m_options (interpreter)
{
SetHelpLong(
@@ -920,8 +997,8 @@ public:
protected:
- virtual void
- IOHandlerActivated (IOHandler &io_handler)
+ void
+ IOHandlerActivated (IOHandler &io_handler) override
{
StreamFileSP output_sp(io_handler.GetOutputStreamFile());
if (output_sp)
@@ -931,8 +1008,8 @@ protected:
}
}
- virtual void
- IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
+ void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override
{
io_handler.SetIsDone(true);
if (m_regex_cmd_ap.get())
@@ -944,7 +1021,6 @@ protected:
bool check_only = false;
for (size_t i=0; i<num_lines; ++i)
{
- printf ("regex[%zu] = %s\n", i, lines[i].c_str());
llvm::StringRef bytes_strref (lines[i]);
Error error = AppendRegexSubstitution (bytes_strref, check_only);
if (error.Fail())
@@ -964,54 +1040,9 @@ protected:
}
}
}
-
- virtual LineStatus
- IOHandlerLinesUpdated (IOHandler &io_handler,
- StringList &lines,
- uint32_t line_idx,
- Error &error)
- {
- if (line_idx == UINT32_MAX)
- {
- // Return true to indicate we are done getting lines (this
- // is a "fake" line - the real terminating blank line was
- // removed during a previous call with the code below)
- error.Clear();
- return LineStatus::Done;
- }
- else
- {
- const size_t num_lines = lines.GetSize();
- if (line_idx + 1 == num_lines)
- {
- // The last line was edited, if this line is empty, then we are done
- // getting our multiple lines.
- if (lines[line_idx].empty())
- {
- // Remove the last empty line from "lines" so it doesn't appear
- // in our final expression and return true to indicate we are done
- // getting lines
- lines.PopBack();
- return LineStatus::Done;
- }
- }
- // Check the current line to make sure it is formatted correctly
- bool check_only = true;
- llvm::StringRef regex_sed(lines[line_idx]);
- error = AppendRegexSubstitution (regex_sed, check_only);
- if (error.Fail())
- {
- return LineStatus::Error;
- }
- else
- {
- return LineStatus::Success;
- }
- }
- }
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
const size_t argc = command.GetArgumentCount();
if (argc == 0)
@@ -1027,16 +1058,22 @@ protected:
name,
m_options.GetHelp (),
m_options.GetSyntax (),
- 10));
+ 10,
+ 0,
+ true));
if (argc == 1)
{
Debugger &debugger = m_interpreter.GetDebugger();
+ bool color_prompt = debugger.GetUseColor();
const bool multiple_lines = true; // Get multiple lines
IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
+ IOHandler::Type::Other,
"lldb-regex", // Name of input reader for history
- "\033[K> ", // Prompt and clear line
+ "> ", // Prompt
+ NULL, // Continuation prompt
multiple_lines,
+ color_prompt,
0, // Don't show line numbers
*this));
@@ -1110,21 +1147,25 @@ protected:
if (second_separator_char_pos == std::string::npos)
{
- error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s'",
+ error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s' in '%.*s'",
separator_char,
(int)(regex_sed.size() - first_separator_char_pos - 1),
- regex_sed.data() + (first_separator_char_pos + 1));
- return error;
+ regex_sed.data() + (first_separator_char_pos + 1),
+ (int)regex_sed.size(),
+ regex_sed.data());
+ return error;
}
const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);
if (third_separator_char_pos == std::string::npos)
{
- error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s'",
+ error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s' in '%.*s'",
separator_char,
(int)(regex_sed.size() - second_separator_char_pos - 1),
- regex_sed.data() + (second_separator_char_pos + 1));
+ regex_sed.data() + (second_separator_char_pos + 1),
+ (int)regex_sed.size(),
+ regex_sed.data());
return error;
}
@@ -1262,8 +1303,8 @@ private:
std::string m_syntax;
};
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -1292,15 +1333,24 @@ public:
CommandObjectPythonFunction (CommandInterpreter &interpreter,
std::string name,
std::string funct,
+ std::string help,
ScriptedCommandSynchronicity synch) :
CommandObjectRaw (interpreter,
name.c_str(),
- (std::string("Run Python function ") + funct).c_str(),
+ NULL,
NULL),
m_function_name(funct),
m_synchro(synch),
m_fetched_help_long(false)
{
+ if (!help.empty())
+ SetHelp(help.c_str());
+ else
+ {
+ StreamString stream;
+ stream.Printf("For more information run 'help %s'",name.c_str());
+ SetHelp(stream.GetData());
+ }
}
virtual
@@ -1357,7 +1407,8 @@ protected:
raw_command_line,
m_synchro,
result,
- error) == false)
+ error,
+ m_exe_ctx) == false)
{
result.AppendError(error.AsCString());
result.SetStatus(eReturnStatusFailed);
@@ -1617,7 +1668,12 @@ protected:
switch (short_option)
{
case 'f':
- m_funct_name = std::string(option_arg);
+ if (option_arg)
+ m_funct_name.assign(option_arg);
+ break;
+ case 'h':
+ if (option_arg)
+ m_short_help.assign(option_arg);
break;
case 's':
m_synchronicity = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
@@ -1635,7 +1691,8 @@ protected:
void
OptionParsingStarting ()
{
- m_funct_name = "";
+ m_funct_name.clear();
+ m_short_help.clear();
m_synchronicity = eScriptedCommandSynchronicitySynchronous;
}
@@ -1652,6 +1709,7 @@ protected:
// Instance variables to hold the values for command options.
std::string m_funct_name;
+ std::string m_short_help;
ScriptedCommandSynchronicity m_synchronicity;
};
@@ -1695,6 +1753,7 @@ protected:
CommandObjectSP command_obj_sp(new CommandObjectPythonFunction (m_interpreter,
m_cmd_name,
funct_name_str.c_str(),
+ m_short_help,
m_synchronicity));
if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true))
@@ -1748,8 +1807,9 @@ protected:
return false;
}
- // Store the command name and synchronicity in case we get multi-line input
+ // Store the options in case we get multi-line input
m_cmd_name = command.GetArgumentAtIndex(0);
+ m_short_help.assign(m_options.m_short_help);
m_synchronicity = m_options.m_synchronicity;
if (m_options.m_funct_name.empty())
@@ -1764,6 +1824,7 @@ protected:
CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter,
m_cmd_name,
m_options.m_funct_name,
+ m_options.m_short_help,
m_synchronicity));
if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true))
{
@@ -1782,6 +1843,7 @@ protected:
CommandOptions m_options;
std::string m_cmd_name;
+ std::string m_short_help;
ScriptedCommandSynchronicity m_synchronicity;
};
@@ -1797,6 +1859,7 @@ OptionDefinition
CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."},
+ { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeHelpText, "The help text to display for this command."},
{ LLDB_OPT_SET_1, false, "synchronicity", 's', OptionParser::eRequiredArgument, NULL, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -1949,11 +2012,11 @@ public:
"A set of commands for managing or customizing script commands.",
"command script <subcommand> [<subcommand-options>]")
{
- LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter)));
- LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter)));
- LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter)));
+ LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter)));
+ LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter)));
+ LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter)));
LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter)));
- LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter)));
+ LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter)));
}
~CommandObjectMultiwordCommandsScript ()
@@ -1978,9 +2041,10 @@ CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpret
LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
+ LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsDelete (interpreter)));
LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
- LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
- LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter)));
+ LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
+ LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter)));
}
CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp
index 079c62d..b4c559c 100644
--- a/source/Commands/CommandObjectExpression.cpp
+++ b/source/Commands/CommandObjectExpression.cpp
@@ -281,7 +281,7 @@ CommandObjectExpression::EvaluateExpression
Target *target = exe_ctx.GetTargetPtr();
if (!target)
- target = Host::GetDummyTarget(m_interpreter.GetDebugger()).get();
+ target = GetDummyTarget();
if (target)
{
@@ -425,11 +425,15 @@ CommandObjectExpression::GetMultilineExpression ()
m_expr_line_count = 0;
Debugger &debugger = GetCommandInterpreter().GetDebugger();
+ bool color_prompt = debugger.GetUseColor();
const bool multiple_lines = true; // Get multiple lines
IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
+ IOHandler::Type::Expression,
"lldb-expr", // Name of input reader for history
NULL, // No prompt
+ NULL, // Continuation prompt
multiple_lines,
+ color_prompt,
1, // Show line numbers starting at 1
*this));
diff --git a/source/Commands/CommandObjectMemory.cpp b/source/Commands/CommandObjectMemory.cpp
index bfbb296..6c06ec8 100644
--- a/source/Commands/CommandObjectMemory.cpp
+++ b/source/Commands/CommandObjectMemory.cpp
@@ -33,8 +33,10 @@
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Symbol/TypeList.h"
+#include "lldb/Target/MemoryHistory.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
@@ -612,7 +614,16 @@ protected:
}
size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
- size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
+
+ // TODO For non-8-bit byte addressable architectures this needs to be
+ // revisited to fully support all lldb's range of formatting options.
+ // Furthermore code memory reads (for those architectures) will not
+ // be correctly formatted even w/o formatting options.
+ size_t item_byte_size =
+ target->GetArchitecture().GetDataByteSize() > 1 ?
+ target->GetArchitecture().GetDataByteSize() :
+ m_format_options.GetByteSizeValue().GetCurrentValue();
+
const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
if (total_byte_size == 0)
@@ -659,7 +670,7 @@ protected:
total_byte_size = end_addr - addr;
item_count = total_byte_size / item_byte_size;
}
-
+
uint32_t max_unforced_size = target->GetMaximumMemReadSize();
if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
@@ -856,7 +867,8 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
DataExtractor data (data_sp,
target->GetArchitecture().GetByteOrder(),
- target->GetArchitecture().GetAddressByteSize());
+ target->GetArchitecture().GetAddressByteSize(),
+ target->GetArchitecture().GetDataByteSize());
Format format = m_format_options.GetFormat();
if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
@@ -890,7 +902,7 @@ protected:
format,
item_byte_size,
item_count,
- num_per_line,
+ num_per_line / target->GetArchitecture().GetDataByteSize(),
addr,
0,
0,
@@ -1078,7 +1090,7 @@ protected:
lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
{
- result.AppendError("invalid low address");
+ result.AppendError("invalid high address");
return false;
}
@@ -1667,6 +1679,96 @@ protected:
OptionGroupWriteMemory m_memory_options;
};
+//----------------------------------------------------------------------
+// Get malloc/free history of a memory address.
+//----------------------------------------------------------------------
+class CommandObjectMemoryHistory : public CommandObjectParsed
+{
+public:
+
+ CommandObjectMemoryHistory (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "memory history",
+ "Prints out the recorded stack traces for allocation/deallocation of a memory address.",
+ NULL,
+ eFlagRequiresTarget | eFlagRequiresProcess | eFlagProcessMustBePaused | eFlagProcessMustBeLaunched)
+ {
+ CommandArgumentEntry arg1;
+ CommandArgumentData addr_arg;
+
+ // Define the first (and only) variant of this arg.
+ addr_arg.arg_type = eArgTypeAddress;
+ addr_arg.arg_repetition = eArgRepeatPlain;
+
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg1.push_back (addr_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back (arg1);
+ }
+
+ virtual
+ ~CommandObjectMemoryHistory ()
+ {
+ }
+
+ virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
+ {
+ return m_cmd_name.c_str();
+ }
+
+protected:
+ virtual bool
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+ const size_t argc = command.GetArgumentCount();
+
+ if (argc == 0 || argc > 1)
+ {
+ result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ Error error;
+ lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
+ command.GetArgumentAtIndex(0),
+ LLDB_INVALID_ADDRESS,
+ &error);
+
+ if (addr == LLDB_INVALID_ADDRESS)
+ {
+ result.AppendError("invalid address expression");
+ result.AppendError(error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ Stream *output_stream = &result.GetOutputStream();
+
+ const ProcessSP &process_sp = m_exe_ctx.GetProcessSP();
+ const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp);
+
+ if (! memory_history.get())
+ {
+ result.AppendError("no available memory history provider");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ HistoryThreads thread_list = memory_history->GetHistoryThreads(addr);
+
+ for (auto thread : thread_list) {
+ thread->GetStatus(*output_stream, 0, UINT32_MAX, 0);
+ }
+
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+
+ return true;
+ }
+
+};
+
//-------------------------------------------------------------------------
// CommandObjectMemory
@@ -1681,6 +1783,7 @@ CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
+ LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter)));
}
CommandObjectMemory::~CommandObjectMemory ()
diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp
index 9998dbd..d176d52 100644
--- a/source/Commands/CommandObjectPlatform.cpp
+++ b/source/Commands/CommandObjectPlatform.cpp
@@ -302,7 +302,7 @@ protected:
Stream &ostrm = result.GetOutputStream();
ostrm.Printf("Available platforms:\n");
- PlatformSP host_platform_sp (Platform::GetDefaultPlatform());
+ PlatformSP host_platform_sp (Platform::GetHostPlatform());
ostrm.Printf ("%s: %s\n",
host_platform_sp->GetPluginName().GetCString(),
host_platform_sp->GetDescription());
@@ -1347,7 +1347,6 @@ protected:
ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info,
debugger,
target,
- debugger.GetListener(),
error));
if (process_sp && process_sp->IsAlive())
{
@@ -1933,7 +1932,7 @@ public:
{
Error err;
ProcessSP remote_process_sp =
- platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), NULL, m_interpreter.GetDebugger().GetListener(), err);
+ platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), NULL, err);
if (err.Fail())
{
result.AppendError(err.AsCString());
diff --git a/source/Commands/CommandObjectProcess.cpp b/source/Commands/CommandObjectProcess.cpp
index 6536c6e..ec7b478 100644
--- a/source/Commands/CommandObjectProcess.cpp
+++ b/source/Commands/CommandObjectProcess.cpp
@@ -258,8 +258,9 @@ protected:
// Save the arguments for subsequent runs in the current target.
target->SetRunArguments (launch_args);
}
-
- Error error = target->Launch(debugger.GetListener(), m_options.launch_info);
+
+ StreamString stream;
+ Error error = target->Launch(m_options.launch_info, &stream);
if (error.Success())
{
@@ -267,6 +268,9 @@ protected:
ProcessSP process_sp (target->GetProcessSP());
if (process_sp)
{
+ const char *data = stream.GetData();
+ if (data && strlen(data) > 0)
+ result.AppendMessage(stream.GetData());
result.AppendMessageWithFormat ("Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
result.SetStatus (eReturnStatusSuccessFinishResult);
result.SetDidChangeProcessState (true);
@@ -564,15 +568,18 @@ protected:
if (error.Success())
{
result.SetStatus (eReturnStatusSuccessContinuingNoResult);
- StateType state = process->WaitForProcessToStop (NULL, NULL, false, listener_sp.get());
+ StreamString stream;
+ StateType state = process->WaitForProcessToStop (NULL, NULL, false, listener_sp.get(), &stream);
process->RestoreProcessEvents();
result.SetDidChangeProcessState (true);
+ if (stream.GetData())
+ result.AppendMessage(stream.GetData());
+
if (state == eStateStopped)
{
- result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
@@ -791,7 +798,12 @@ protected:
}
}
- Error error(process->Resume());
+ StreamString stream;
+ Error error;
+ if (synchronous_execution)
+ error = process->ResumeSynchronous (&stream);
+ else
+ error = process->Resume ();
if (error.Success())
{
@@ -803,10 +815,11 @@ protected:
result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
if (synchronous_execution)
{
- state = process->WaitForProcessToStop (NULL);
+ // If any state changed events had anything to say, add that to the result
+ if (stream.GetData())
+ result.AppendMessage(stream.GetData());
result.SetDidChangeProcessState (true);
- result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
diff --git a/source/Commands/CommandObjectSource.cpp b/source/Commands/CommandObjectSource.cpp
index 6b1b6aa..8fb03e6 100644
--- a/source/Commands/CommandObjectSource.cpp
+++ b/source/Commands/CommandObjectSource.cpp
@@ -421,7 +421,7 @@ protected:
{
const bool show_inlines = true;
m_breakpoint_locations.Reset (start_file, 0, show_inlines);
- SearchFilter target_search_filter (m_exe_ctx.GetTargetSP());
+ SearchFilterForUnconstrainedSearches target_search_filter (m_exe_ctx.GetTargetSP());
target_search_filter.Search (m_breakpoint_locations);
}
@@ -682,19 +682,21 @@ protected:
m_breakpoint_locations.Clear();
const bool show_inlines = true;
m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines);
- SearchFilter target_search_filter (target->shared_from_this());
+ SearchFilterForUnconstrainedSearches target_search_filter (target->shared_from_this());
target_search_filter.Search (m_breakpoint_locations);
}
bool show_fullpaths = true;
bool show_module = true;
bool show_inlined_frames = true;
+ const bool show_function_arguments = true;
sc.DumpStopContext(&result.GetOutputStream(),
m_exe_ctx.GetBestExecutionContextScope(),
sc.line_entry.range.GetBaseAddress(),
show_fullpaths,
show_module,
- show_inlined_frames);
+ show_inlined_frames,
+ show_function_arguments);
result.GetOutputStream().EOL();
if (m_options.num_lines == 0)
@@ -741,7 +743,7 @@ protected:
{
const bool show_inlines = true;
m_breakpoint_locations.Reset (last_file_sp->GetFileSpec(), 0, show_inlines);
- SearchFilter target_search_filter (target->shared_from_this());
+ SearchFilterForUnconstrainedSearches target_search_filter (target->shared_from_this());
target_search_filter.Search (m_breakpoint_locations);
}
}
@@ -844,7 +846,7 @@ protected:
{
const bool show_inlines = true;
m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines);
- SearchFilter target_search_filter (target->shared_from_this());
+ SearchFilterForUnconstrainedSearches target_search_filter (target->shared_from_this());
target_search_filter.Search (m_breakpoint_locations);
}
else
diff --git a/source/Commands/CommandObjectSyntax.cpp b/source/Commands/CommandObjectSyntax.cpp
index d2021ea..5093c3b 100644
--- a/source/Commands/CommandObjectSyntax.cpp
+++ b/source/Commands/CommandObjectSyntax.cpp
@@ -69,12 +69,18 @@ CommandObjectSyntax::DoExecute (Args& command, CommandReturnObject &result)
{
std::string sub_command = command.GetArgumentAtIndex (i);
if (!cmd_obj->IsMultiwordObject())
+ {
all_okay = false;
+ break;
+ }
else
{
cmd_obj = cmd_obj->GetSubcommandObject(sub_command.c_str());
if (!cmd_obj)
+ {
all_okay = false;
+ break;
+ }
}
}
diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp
index 024f7b5..0d9ffda 100644
--- a/source/Commands/CommandObjectTarget.cpp
+++ b/source/Commands/CommandObjectTarget.cpp
@@ -39,6 +39,7 @@
#include "lldb/Interpreter/OptionGroupPlatform.h"
#include "lldb/Interpreter/OptionGroupUInt64.h"
#include "lldb/Interpreter/OptionGroupUUID.h"
+#include "lldb/Interpreter/OptionGroupString.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/FuncUnwinders.h"
@@ -2844,7 +2845,7 @@ public:
"Set the load addresses for one or more sections in a target module.",
"target modules load [--file <module> --uuid <uuid>] <sect-name> <address> [<sect-name> <address> ....]"),
m_option_group (interpreter),
- m_file_option (LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeFilename, "Fullpath or basename for module to load."),
+ m_file_option (LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName, "Fullpath or basename for module to load.", ""),
m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset, "Set the load address for all sections to be the virtual address in the file plus the offset.", 0)
{
m_option_group.Append (&m_uuid_option_group, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
@@ -2884,7 +2885,26 @@ protected:
if (m_file_option.GetOptionValue().OptionWasSet())
{
search_using_module_spec = true;
- module_spec.GetFileSpec() = m_file_option.GetOptionValue().GetCurrentValue();
+ const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue();
+ const bool use_global_module_list = true;
+ ModuleList module_list;
+ const size_t num_matches = FindModulesByName (target, arg_cstr, module_list, use_global_module_list);
+ if (num_matches == 1)
+ {
+ module_spec.GetFileSpec() = module_list.GetModuleAtIndex(0)->GetFileSpec();
+ }
+ else if (num_matches > 1 )
+ {
+ search_using_module_spec = false;
+ result.AppendErrorWithFormat ("more than 1 module matched by name '%s'\n", arg_cstr);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ search_using_module_spec = false;
+ result.AppendErrorWithFormat ("no object file for module '%s'\n", arg_cstr);
+ result.SetStatus (eReturnStatusFailed);
+ }
}
if (m_uuid_option_group.GetOptionValue().OptionWasSet())
@@ -3070,7 +3090,7 @@ protected:
OptionGroupOptions m_option_group;
OptionGroupUUID m_uuid_option_group;
- OptionGroupFile m_file_option;
+ OptionGroupString m_file_option;
OptionGroupUInt64 m_slide_option;
};
@@ -3724,45 +3744,85 @@ protected:
if (func_unwinders_sp.get() == NULL)
continue;
- Address first_non_prologue_insn (func_unwinders_sp->GetFirstNonPrologueInsn(*target));
- if (first_non_prologue_insn.IsValid())
- {
- result.GetOutputStream().Printf("First non-prologue instruction is at address 0x%" PRIx64 " or offset %" PRId64 " into the function.\n", first_non_prologue_insn.GetLoadAddress(target), first_non_prologue_insn.GetLoadAddress(target) - start_addr);
- result.GetOutputStream().Printf ("\n");
- }
+ result.GetOutputStream().Printf("UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr);
UnwindPlanSP non_callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread.get(), -1);
if (non_callsite_unwind_plan.get())
{
- result.GetOutputStream().Printf("Asynchronous (not restricted to call-sites) UnwindPlan for %s`%s (start addr 0x%" PRIx64 "):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr);
- non_callsite_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
- result.GetOutputStream().Printf ("\n");
+ result.GetOutputStream().Printf("Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n", non_callsite_unwind_plan->GetSourceName().AsCString());
}
-
- UnwindPlanSP callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(-1);
+ UnwindPlanSP callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(*target, -1);
if (callsite_unwind_plan.get())
{
- result.GetOutputStream().Printf("Synchronous (restricted to call-sites) UnwindPlan for %s`%s (start addr 0x%" PRIx64 "):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr);
- callsite_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
- result.GetOutputStream().Printf ("\n");
+ result.GetOutputStream().Printf("Synchronous (restricted to call-sites) UnwindPlan is '%s'\n", callsite_unwind_plan->GetSourceName().AsCString());
+ }
+ UnwindPlanSP fast_unwind_plan = func_unwinders_sp->GetUnwindPlanFastUnwind(*thread.get());
+ if (fast_unwind_plan.get())
+ {
+ result.GetOutputStream().Printf("Fast UnwindPlan is '%s'\n", fast_unwind_plan->GetSourceName().AsCString());
}
- UnwindPlanSP arch_default_unwind_plan = func_unwinders_sp->GetUnwindPlanArchitectureDefault(*thread.get());
- if (arch_default_unwind_plan.get())
+ result.GetOutputStream().Printf("\n");
+
+ UnwindPlanSP assembly_sp = func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread.get(), 0);
+ if (assembly_sp)
{
- result.GetOutputStream().Printf("Architecture default UnwindPlan for %s`%s (start addr 0x%" PRIx64 "):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr);
- arch_default_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
- result.GetOutputStream().Printf ("\n");
+ result.GetOutputStream().Printf("Assembly language inspection UnwindPlan:\n");
+ assembly_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
+ result.GetOutputStream().Printf("\n");
}
+
- UnwindPlanSP fast_unwind_plan = func_unwinders_sp->GetUnwindPlanFastUnwind(*thread.get());
- if (fast_unwind_plan.get())
+ UnwindPlanSP ehframe_sp = func_unwinders_sp->GetEHFrameUnwindPlan(*target, 0);
+ if (ehframe_sp)
{
- result.GetOutputStream().Printf("Fast UnwindPlan for %s`%s (start addr 0x%" PRIx64 "):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr);
+ result.GetOutputStream().Printf("eh_frame UnwindPlan:\n");
+ ehframe_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
+ result.GetOutputStream().Printf("\n");
+ }
+
+ UnwindPlanSP ehframe_augmented_sp = func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread.get(), 0);
+ if (ehframe_augmented_sp)
+ {
+ result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n");
+ ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
+ result.GetOutputStream().Printf("\n");
+ }
+
+ UnwindPlanSP compact_unwind_sp = func_unwinders_sp->GetCompactUnwindUnwindPlan(*target, 0);
+ if (compact_unwind_sp)
+ {
+ result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n");
+ compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
+ result.GetOutputStream().Printf("\n");
+ }
+
+ if (fast_unwind_plan)
+ {
+ result.GetOutputStream().Printf("Fast UnwindPlan:\n");
fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
- result.GetOutputStream().Printf ("\n");
+ result.GetOutputStream().Printf("\n");
}
+ ABISP abi_sp = process->GetABI();
+ if (abi_sp)
+ {
+ UnwindPlan arch_default(lldb::eRegisterKindGeneric);
+ if (abi_sp->CreateDefaultUnwindPlan (arch_default))
+ {
+ result.GetOutputStream().Printf("Arch default UnwindPlan:\n");
+ arch_default.Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
+ result.GetOutputStream().Printf("\n");
+ }
+
+ UnwindPlan arch_entry(lldb::eRegisterKindGeneric);
+ if (abi_sp->CreateFunctionEntryUnwindPlan (arch_entry))
+ {
+ result.GetOutputStream().Printf("Arch default at entry point UnwindPlan:\n");
+ arch_entry.Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
+ result.GetOutputStream().Printf("\n");
+ }
+ }
result.GetOutputStream().Printf ("\n");
}
@@ -4999,7 +5059,7 @@ protected:
{
m_stop_hook_sp.reset();
- Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ Target *target = GetSelectedOrDummyTarget();
if (target)
{
Target::StopHookSP new_hook_sp = target->CreateStopHook();
@@ -5151,7 +5211,7 @@ protected:
bool
DoExecute (Args& command, CommandReturnObject &result)
{
- Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ Target *target = GetSelectedOrDummyTarget();
if (target)
{
// FIXME: see if we can use the breakpoint id style parser?
@@ -5227,7 +5287,7 @@ protected:
bool
DoExecute (Args& command, CommandReturnObject &result)
{
- Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ Target *target = GetSelectedOrDummyTarget();
if (target)
{
// FIXME: see if we can use the breakpoint id style parser?
@@ -5297,7 +5357,7 @@ protected:
bool
DoExecute (Args& command, CommandReturnObject &result)
{
- Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ Target *target = GetSelectedOrDummyTarget();
if (!target)
{
result.AppendError ("invalid target\n");
diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp
index e7a8652..bace4e5 100644
--- a/source/Commands/CommandObjectThread.cpp
+++ b/source/Commands/CommandObjectThread.cpp
@@ -46,7 +46,108 @@ using namespace lldb_private;
// CommandObjectThreadBacktrace
//-------------------------------------------------------------------------
-class CommandObjectThreadBacktrace : public CommandObjectParsed
+class CommandObjectIterateOverThreads : public CommandObjectParsed
+{
+public:
+ CommandObjectIterateOverThreads (CommandInterpreter &interpreter,
+ const char *name,
+ const char *help,
+ const char *syntax,
+ uint32_t flags) :
+ CommandObjectParsed (interpreter, name, help, syntax, flags)
+ {
+ }
+
+ virtual ~CommandObjectIterateOverThreads() {}
+ virtual bool
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+ result.SetStatus (m_success_return);
+
+ if (command.GetArgumentCount() == 0)
+ {
+ Thread *thread = m_exe_ctx.GetThreadPtr();
+ if (!HandleOneThread (*thread, result))
+ return false;
+ }
+ else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
+ {
+ Process *process = m_exe_ctx.GetProcessPtr();
+ uint32_t idx = 0;
+ for (ThreadSP thread_sp : process->Threads())
+ {
+ if (idx != 0 && m_add_return)
+ result.AppendMessage("");
+
+ if (!HandleOneThread(*(thread_sp.get()), result))
+ return false;
+ ++idx;
+ }
+ }
+ else
+ {
+ const size_t num_args = command.GetArgumentCount();
+ Process *process = m_exe_ctx.GetProcessPtr();
+ Mutex::Locker locker (process->GetThreadList().GetMutex());
+ std::vector<ThreadSP> thread_sps;
+
+ for (size_t i = 0; i < num_args; i++)
+ {
+ bool success;
+
+ uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
+ if (!success)
+ {
+ result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
+
+ if (!thread_sps[i])
+ {
+ result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ }
+
+ for (uint32_t i = 0; i < num_args; i++)
+ {
+ if (!HandleOneThread (*(thread_sps[i].get()), result))
+ return false;
+
+ if (i < num_args - 1 && m_add_return)
+ result.AppendMessage("");
+ }
+ }
+ return result.Succeeded();
+ }
+
+protected:
+
+ // Override this to do whatever you need to do for one thread.
+ //
+ // If you return false, the iteration will stop, otherwise it will proceed.
+ // The result is set to m_success_return (defaults to eReturnStatusSuccessFinishResult) before the iteration,
+ // so you only need to set the return status in HandleOneThread if you want to indicate an error.
+ // If m_add_return is true, a blank line will be inserted between each of the listings (except the last one.)
+
+ virtual bool
+ HandleOneThread (Thread &thread, CommandReturnObject &result) = 0;
+
+ ReturnStatus m_success_return = eReturnStatusSuccessFinishResult;
+ bool m_add_return = true;
+
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadBacktrace
+//-------------------------------------------------------------------------
+
+class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads
{
public:
@@ -134,7 +235,7 @@ public:
};
CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
+ CommandObjectIterateOverThreads (interpreter,
"thread backtrace",
"Show the stack for one or more threads. If no threads are specified, show the currently selected thread. Use the thread-index \"all\" to see all threads.",
NULL,
@@ -145,18 +246,6 @@ public:
eFlagProcessMustBePaused ),
m_options(interpreter)
{
- CommandArgumentEntry arg;
- CommandArgumentData thread_idx_arg;
-
- // Define the first (and only) variant of this arg.
- thread_idx_arg.arg_type = eArgTypeThreadIndex;
- thread_idx_arg.arg_repetition = eArgRepeatStar;
-
- // There is only one variant this argument could be; put it into the argument entry.
- arg.push_back (thread_idx_arg);
-
- // Push the data for the first argument into the m_arguments vector.
- m_arguments.push_back (arg);
}
~CommandObjectThreadBacktrace()
@@ -197,106 +286,28 @@ protected:
}
virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
- {
- result.SetStatus (eReturnStatusSuccessFinishResult);
+ HandleOneThread (Thread &thread, CommandReturnObject &result)
+ {
Stream &strm = result.GetOutputStream();
// Don't show source context when doing backtraces.
const uint32_t num_frames_with_source = 0;
- if (command.GetArgumentCount() == 0)
- {
- Thread *thread = m_exe_ctx.GetThreadPtr();
- // Thread::GetStatus() returns the number of frames shown.
- if (thread->GetStatus (strm,
+
+ if (!thread.GetStatus (strm,
m_options.m_start,
m_options.m_count,
num_frames_with_source))
- {
- result.SetStatus (eReturnStatusSuccessFinishResult);
- if (m_options.m_extended_backtrace)
- {
- DoExtendedBacktrace (thread, result);
- }
- }
- }
- else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
{
- Process *process = m_exe_ctx.GetProcessPtr();
- uint32_t idx = 0;
- for (ThreadSP thread_sp : process->Threads())
- {
- if (idx != 0)
- result.AppendMessage("");
-
- if (!thread_sp->GetStatus (strm,
- m_options.m_start,
- m_options.m_count,
- num_frames_with_source))
- {
- result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", idx);
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- if (m_options.m_extended_backtrace)
- {
- DoExtendedBacktrace (thread_sp.get(), result);
- }
-
- ++idx;
- }
+ result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", thread.GetIndexID());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
}
- else
+ if (m_options.m_extended_backtrace)
{
- const size_t num_args = command.GetArgumentCount();
- Process *process = m_exe_ctx.GetProcessPtr();
- Mutex::Locker locker (process->GetThreadList().GetMutex());
- std::vector<ThreadSP> thread_sps;
-
- for (size_t i = 0; i < num_args; i++)
- {
- bool success;
-
- uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
- if (!success)
- {
- result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
-
- if (!thread_sps[i])
- {
- result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- }
-
- for (uint32_t i = 0; i < num_args; i++)
- {
- if (!thread_sps[i]->GetStatus (strm,
- m_options.m_start,
- m_options.m_count,
- num_frames_with_source))
- {
- result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- if (m_options.m_extended_backtrace)
- {
- DoExtendedBacktrace (thread_sps[i].get(), result);
- }
-
- if (i < num_args - 1)
- result.AppendMessage("");
- }
+ DoExtendedBacktrace (&thread, result);
}
- return result.Succeeded();
+
+ return true;
}
CommandOptions m_options;
@@ -379,6 +390,12 @@ public:
break;
}
break;
+ case 'C':
+ {
+ m_class_name.clear();
+ m_class_name.assign(option_arg);
+ }
+ break;
case 'm':
{
OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
@@ -416,6 +433,7 @@ public:
m_run_mode = eOnlyDuringStepping;
m_avoid_regexp.clear();
m_step_in_target.clear();
+ m_class_name.clear();
m_step_count = 1;
}
@@ -435,7 +453,8 @@ public:
RunMode m_run_mode;
std::string m_avoid_regexp;
std::string m_step_in_target;
- int32_t m_step_count;
+ std::string m_class_name;
+ uint32_t m_step_count;
};
CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
@@ -520,6 +539,22 @@ protected:
}
}
+ if (m_step_type == eStepTypeScripted)
+ {
+ if (m_options.m_class_name.empty())
+ {
+ result.AppendErrorWithFormat ("empty class name for scripted step.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists(m_options.m_class_name.c_str()))
+ {
+ result.AppendErrorWithFormat ("class for scripted step: \"%s\" does not exist.", m_options.m_class_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+
const bool abort_other_plans = false;
const lldb::RunMode stop_other_threads = m_options.m_run_mode;
@@ -530,7 +565,7 @@ protected:
bool_stop_other_threads = false;
else if (m_options.m_run_mode == eOnlyDuringStepping)
{
- if (m_step_type == eStepTypeOut)
+ if (m_step_type == eStepTypeOut || m_step_type == eStepTypeScripted)
bool_stop_other_threads = false;
else
bool_stop_other_threads = true;
@@ -599,6 +634,12 @@ protected:
thread->GetSelectedFrameIndex(),
m_options.m_step_out_avoid_no_debug);
}
+ else if (m_step_type == eStepTypeScripted)
+ {
+ new_plan_sp = thread->QueueThreadPlanForStepScripted (abort_other_plans,
+ m_options.m_class_name.c_str(),
+ bool_stop_other_threads);
+ }
else
{
result.AppendError ("step type is not supported");
@@ -622,8 +663,15 @@ protected:
}
}
+
process->GetThreadList().SetSelectedThreadByID (thread->GetID());
- process->Resume ();
+
+ StreamString stream;
+ Error error;
+ if (synchronous_execution)
+ error = process->ResumeSynchronous (&stream);
+ else
+ error = process->Resume ();
// There is a race condition where this thread will return up the call stack to the main command handler
// and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has
@@ -632,17 +680,12 @@ protected:
if (synchronous_execution)
{
- StateType state = process->WaitForProcessToStop (NULL);
-
- //EventSP event_sp;
- //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
- //while (! StateIsStoppedState (state))
- // {
- // state = process->WaitForStateChangedEvents (NULL, event_sp);
- // }
+ // If any state changed events had anything to say, add that to the result
+ if (stream.GetData())
+ result.AppendMessage(stream.GetData());
+
process->GetThreadList().SetSelectedThreadByID (thread->GetID());
result.SetDidChangeProcessState (true);
- result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
@@ -686,10 +729,11 @@ CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "step-in-avoids-no-debug", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether stepping into functions will step over functions with no debug information."},
{ LLDB_OPT_SET_1, false, "step-out-avoids-no-debug", 'A', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information."},
-{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."},
-{ LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, NULL, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."},
-{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in."},
-{ LLDB_OPT_SET_1, false, "step-in-target", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."},
+{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."},
+{ LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, NULL, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."},
+{ LLDB_OPT_SET_1, false, "step-over-regexp", 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in."},
+{ LLDB_OPT_SET_1, false, "step-in-target", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."},
+{ LLDB_OPT_SET_2, false, "python-class", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -860,17 +904,25 @@ public:
}
}
+
+ StreamString stream;
+ Error error;
+ if (synchronous_execution)
+ error = process->ResumeSynchronous (&stream);
+ else
+ error = process->Resume ();
+
// We should not be holding the thread list lock when we do this.
- Error error (process->Resume());
if (error.Success())
{
result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
if (synchronous_execution)
{
- state = process->WaitForProcessToStop (NULL);
+ // If any state changed events had anything to say, add that to the result
+ if (stream.GetData())
+ result.AppendMessage(stream.GetData());
result.SetDidChangeProcessState (true);
- result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
@@ -1191,17 +1243,27 @@ protected:
}
+
+
process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
- Error error (process->Resume ());
+
+ StreamString stream;
+ Error error;
+ if (synchronous_execution)
+ error = process->ResumeSynchronous (&stream);
+ else
+ error = process->Resume ();
+
if (error.Success())
{
result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
if (synchronous_execution)
{
- StateType state = process->WaitForProcessToStop (NULL);
+ // If any state changed events had anything to say, add that to the result
+ if (stream.GetData())
+ result.AppendMessage(stream.GetData());
result.SetDidChangeProcessState (true);
- result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
@@ -1358,32 +1420,22 @@ protected:
// CommandObjectThreadInfo
//-------------------------------------------------------------------------
-class CommandObjectThreadInfo : public CommandObjectParsed
+class CommandObjectThreadInfo : public CommandObjectIterateOverThreads
{
public:
CommandObjectThreadInfo (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "thread info",
- "Show an extended summary of information about thread(s) in a process.",
- "thread info",
- eFlagRequiresProcess |
- eFlagTryTargetAPILock |
- eFlagProcessMustBeLaunched |
- eFlagProcessMustBePaused),
+ CommandObjectIterateOverThreads (interpreter,
+ "thread info",
+ "Show an extended summary of information about thread(s) in a process.",
+ "thread info",
+ eFlagRequiresProcess |
+ eFlagTryTargetAPILock |
+ eFlagProcessMustBeLaunched |
+ eFlagProcessMustBePaused),
m_options (interpreter)
{
- CommandArgumentEntry arg;
- CommandArgumentData thread_idx_arg;
-
- thread_idx_arg.arg_type = eArgTypeThreadIndex;
- thread_idx_arg.arg_repetition = eArgRepeatStar;
-
- // There is only one variant this argument could be; put it into the argument entry.
- arg.push_back (thread_idx_arg);
-
- // Push the data for the first argument into the m_arguments vector.
- m_arguments.push_back (arg);
+ m_add_return = false;
}
class CommandOptions : public Options
@@ -1399,7 +1451,8 @@ public:
void
OptionParsingStarting ()
{
- m_json = false;
+ m_json_thread = false;
+ m_json_stopinfo = false;
}
virtual
@@ -1416,10 +1469,14 @@ public:
switch (short_option)
{
case 'j':
- m_json = true;
+ m_json_thread = true;
+ break;
+
+ case 's':
+ m_json_stopinfo = true;
break;
- default:
+ default:
return Error("invalid short option character '%c'", short_option);
}
@@ -1432,7 +1489,8 @@ public:
return g_option_table;
}
- bool m_json;
+ bool m_json_thread;
+ bool m_json_stopinfo;
static OptionDefinition g_option_table[];
};
@@ -1451,81 +1509,16 @@ public:
}
virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ HandleOneThread (Thread &thread, CommandReturnObject &result)
{
- result.SetStatus (eReturnStatusSuccessFinishResult);
Stream &strm = result.GetOutputStream();
-
- if (command.GetArgumentCount() == 0)
- {
- Thread *thread = m_exe_ctx.GetThreadPtr();
- if (thread->GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
- {
- result.SetStatus (eReturnStatusSuccessFinishResult);
- }
- }
- else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
- {
- Process *process = m_exe_ctx.GetProcessPtr();
- uint32_t idx = 0;
- for (ThreadSP thread_sp : process->Threads())
- {
- if (idx != 0)
- result.AppendMessage("");
- if (!thread_sp->GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
- {
- result.AppendErrorWithFormat ("error displaying info for thread: \"0x%4.4x\"\n", idx);
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- ++idx;
- }
- }
- else
+ if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo))
{
- const size_t num_args = command.GetArgumentCount();
- Process *process = m_exe_ctx.GetProcessPtr();
- Mutex::Locker locker (process->GetThreadList().GetMutex());
- std::vector<ThreadSP> thread_sps;
-
- for (size_t i = 0; i < num_args; i++)
- {
- bool success;
-
- uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
- if (!success)
- {
- result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
-
- if (!thread_sps[i])
- {
- result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- }
-
- for (uint32_t i = 0; i < num_args; i++)
- {
- if (!thread_sps[i]->GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
- {
- result.AppendErrorWithFormat ("error displaying info for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- if (i < num_args - 1)
- result.AppendMessage("");
- }
-
+ result.AppendErrorWithFormat ("error displaying info for thread: \"%d\"\n", thread.GetIndexID());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
}
- return result.Succeeded();
+ return true;
}
CommandOptions m_options;
@@ -1536,6 +1529,7 @@ OptionDefinition
CommandObjectThreadInfo::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_ALL, false, "json",'j', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the thread info in JSON format."},
+ { LLDB_OPT_SET_ALL, false, "stop-info",'s', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the extended stop info in JSON format."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -1958,6 +1952,228 @@ CommandObjectThreadJump::CommandOptions::g_option_table[] =
};
//-------------------------------------------------------------------------
+// Next are the subcommands of CommandObjectMultiwordThreadPlan
+//-------------------------------------------------------------------------
+
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadPlanList
+//-------------------------------------------------------------------------
+class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads
+{
+public:
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options(interpreter)
+ {
+ // Keep default values of all options in one place: OptionParsingStarting ()
+ OptionParsingStarting ();
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg)
+ {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'i':
+ {
+ m_internal = true;
+ }
+ break;
+ case 'v':
+ {
+ m_verbose = true;
+ }
+ break;
+ default:
+ error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
+ break;
+
+ }
+ return error;
+ }
+
+ void
+ OptionParsingStarting ()
+ {
+ m_verbose = false;
+ m_internal = false;
+ }
+
+ const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ bool m_verbose;
+ bool m_internal;
+ };
+
+ CommandObjectThreadPlanList (CommandInterpreter &interpreter) :
+ CommandObjectIterateOverThreads (interpreter,
+ "thread plan list",
+ "Show thread plans for one or more threads. If no threads are specified, show the "
+ "currently selected thread. Use the thread-index \"all\" to see all threads.",
+ NULL,
+ eFlagRequiresProcess |
+ eFlagRequiresThread |
+ eFlagTryTargetAPILock |
+ eFlagProcessMustBeLaunched |
+ eFlagProcessMustBePaused ),
+ m_options(interpreter)
+ {
+ }
+
+ ~CommandObjectThreadPlanList ()
+ {
+ }
+
+ virtual Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+protected:
+ virtual bool
+ HandleOneThread (Thread &thread, CommandReturnObject &result)
+ {
+ Stream &strm = result.GetOutputStream();
+ DescriptionLevel desc_level = eDescriptionLevelFull;
+ if (m_options.m_verbose)
+ desc_level = eDescriptionLevelVerbose;
+
+ thread.DumpThreadPlans (&strm, desc_level, m_options.m_internal, true);
+ return true;
+ }
+ CommandOptions m_options;
+};
+
+OptionDefinition
+CommandObjectThreadPlanList::CommandOptions::g_option_table[] =
+{
+{ LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display more information about the thread plans"},
+{ LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display internal as well as user thread plans"},
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
+class CommandObjectThreadPlanDiscard : public CommandObjectParsed
+{
+public:
+ CommandObjectThreadPlanDiscard (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "thread plan discard",
+ "Discards thread plans up to and including the plan passed as the command argument."
+ "Only user visible plans can be discarded, use the index from \"thread plan list\""
+ " without the \"-i\" argument.",
+ NULL,
+ eFlagRequiresProcess |
+ eFlagRequiresThread |
+ eFlagTryTargetAPILock |
+ eFlagProcessMustBeLaunched |
+ eFlagProcessMustBePaused )
+ {
+ CommandArgumentEntry arg;
+ CommandArgumentData plan_index_arg;
+
+ // Define the first (and only) variant of this arg.
+ plan_index_arg.arg_type = eArgTypeUnsignedInteger;
+ plan_index_arg.arg_repetition = eArgRepeatPlain;
+
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg.push_back (plan_index_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back (arg);
+ }
+
+ virtual ~CommandObjectThreadPlanDiscard () {}
+
+ bool
+ DoExecute (Args& args, CommandReturnObject &result)
+ {
+ Thread *thread = m_exe_ctx.GetThreadPtr();
+ if (args.GetArgumentCount() != 1)
+ {
+ result.AppendErrorWithFormat("Too many arguments, expected one - the thread plan index - but got %zu.",
+ args.GetArgumentCount());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ bool success;
+ uint32_t thread_plan_idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success);
+ if (!success)
+ {
+ result.AppendErrorWithFormat("Invalid thread index: \"%s\" - should be unsigned int.",
+ args.GetArgumentAtIndex(0));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (thread_plan_idx == 0)
+ {
+ result.AppendErrorWithFormat("You wouldn't really want me to discard the base thread plan.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx))
+ {
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+ else
+ {
+ result.AppendErrorWithFormat("Could not find User thread plan with index %s.",
+ args.GetArgumentAtIndex(0));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordThreadPlan
+//-------------------------------------------------------------------------
+
+class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword
+{
+public:
+ CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) :
+ CommandObjectMultiword (interpreter,
+ "plan",
+ "A set of subcommands for accessing the thread plans controlling execution control on one or more threads.",
+ "thread plan <subcommand> [<subcommand objects]")
+ {
+ LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadPlanList (interpreter)));
+ LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter)));
+ }
+
+ virtual ~CommandObjectMultiwordThreadPlan () {}
+
+
+};
+
+//-------------------------------------------------------------------------
// CommandObjectMultiwordThread
//-------------------------------------------------------------------------
@@ -2014,6 +2230,16 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
NULL,
eStepTypeTraceOver,
eStepScopeInstruction)));
+
+ LoadSubCommand ("step-scripted", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
+ interpreter,
+ "thread step-scripted",
+ "Step as instructed by the script class passed in the -C option.",
+ NULL,
+ eStepTypeScripted,
+ eStepScopeSource)));
+
+ LoadSubCommand ("plan", CommandObjectSP (new CommandObjectMultiwordThreadPlan(interpreter)));
}
CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
diff --git a/source/Commands/CommandObjectType.cpp b/source/Commands/CommandObjectType.cpp
index 640fd6d..3a4c60c 100644
--- a/source/Commands/CommandObjectType.cpp
+++ b/source/Commands/CommandObjectType.cpp
@@ -16,6 +16,7 @@
#include <ctype.h>
// C++ Includes
+#include <functional>
#include "llvm/ADT/StringRef.h"
@@ -31,6 +32,11 @@
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadList.h"
using namespace lldb;
using namespace lldb_private;
@@ -2465,22 +2471,7 @@ protected:
if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0)
{
- // we want to make sure to enable "system" last and "default" first
- DataVisualization::Categories::Enable(ConstString("default"), TypeCategoryMap::First);
- uint32_t num_categories = DataVisualization::Categories::GetCount();
- for (uint32_t i = 0; i < num_categories; i++)
- {
- lldb::TypeCategoryImplSP category_sp = DataVisualization::Categories::GetCategoryAtIndex(i);
- if (category_sp)
- {
- if ( ::strcmp(category_sp->GetName(), "system") == 0 ||
- ::strcmp(category_sp->GetName(), "default") == 0 )
- continue;
- else
- DataVisualization::Categories::Enable(category_sp, TypeCategoryMap::Default);
- }
- }
- DataVisualization::Categories::Enable(ConstString("system"), TypeCategoryMap::Last);
+ DataVisualization::Categories::EnableStar();
}
else
{
@@ -2630,14 +2621,7 @@ protected:
if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0)
{
- uint32_t num_categories = DataVisualization::Categories::GetCount();
- for (uint32_t i = 0; i < num_categories; i++)
- {
- lldb::TypeCategoryImplSP category_sp = DataVisualization::Categories::GetCategoryAtIndex(i);
- // no need to check if the category is enabled - disabling a disabled category has no effect
- if (category_sp)
- DataVisualization::Categories::Disable(category_sp);
- }
+ DataVisualization::Categories::DisableStar();
}
else
{
@@ -4253,6 +4237,84 @@ CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] =
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
+template <typename FormatterType>
+class CommandObjectFormatterInfo : public CommandObjectRaw
+{
+public:
+ typedef std::function<typename FormatterType::SharedPointer(ValueObject&)> DiscoveryFunction;
+ CommandObjectFormatterInfo (CommandInterpreter &interpreter,
+ const char* formatter_name,
+ DiscoveryFunction discovery_func) :
+ CommandObjectRaw(interpreter,
+ nullptr,
+ nullptr,
+ nullptr,
+ eFlagRequiresFrame),
+ m_formatter_name(formatter_name ? formatter_name : ""),
+ m_discovery_function(discovery_func)
+ {
+ StreamString name;
+ name.Printf("type %s info", formatter_name);
+ SetCommandName(name.GetData());
+ StreamString help;
+ help.Printf("This command evaluates the provided expression and shows which %s is applied to the resulting value (if any).", formatter_name);
+ SetHelp(help.GetData());
+ StreamString syntax;
+ syntax.Printf("type %s info <expr>", formatter_name);
+ SetSyntax(syntax.GetData());
+ }
+
+ virtual
+ ~CommandObjectFormatterInfo ()
+ {
+ }
+
+protected:
+ virtual bool
+ DoExecute (const char *command, CommandReturnObject &result)
+ {
+ auto target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
+ auto frame_sp = target_sp->GetProcessSP()->GetThreadList().GetSelectedThread()->GetSelectedFrame();
+ ValueObjectSP result_valobj_sp;
+ EvaluateExpressionOptions options;
+ lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(command, frame_sp.get(), result_valobj_sp, options);
+ if (expr_result == eExpressionCompleted && result_valobj_sp)
+ {
+ result_valobj_sp = result_valobj_sp->GetQualifiedRepresentationIfAvailable(target_sp->GetPreferDynamicValue(), target_sp->GetEnableSyntheticValue());
+ typename FormatterType::SharedPointer formatter_sp = m_discovery_function(*result_valobj_sp);
+ if (formatter_sp)
+ {
+ std::string description(formatter_sp->GetDescription());
+ result.AppendMessageWithFormat("%s applied to (%s) %s is: %s\n",
+ m_formatter_name.c_str(),
+ result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"),
+ command,
+ description.c_str());
+ result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendMessageWithFormat("no %s applies to (%s) %s\n",
+ m_formatter_name.c_str(),
+ result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"),
+ command);
+ result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
+ }
+ return true;
+ }
+ else
+ {
+ result.AppendError("failed to evaluate expression");
+ result.SetStatus(lldb::eReturnStatusFailed);
+ return false;
+ }
+ }
+
+private:
+ std::string m_formatter_name;
+ DiscoveryFunction m_discovery_function;
+};
+
class CommandObjectTypeFormat : public CommandObjectMultiword
{
public:
@@ -4266,6 +4328,11 @@ public:
LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFormatClear (interpreter)));
LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter)));
LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFormatList (interpreter)));
+ LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo<TypeFormatImpl>(interpreter,
+ "format",
+ [](ValueObject& valobj) -> TypeFormatImpl::SharedPointer {
+ return valobj.GetValueFormat();
+ })));
}
@@ -4289,6 +4356,11 @@ public:
LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSynthClear (interpreter)));
LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter)));
LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSynthList (interpreter)));
+ LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo<SyntheticChildren>(interpreter,
+ "synthetic",
+ [](ValueObject& valobj) -> SyntheticChildren::SharedPointer {
+ return valobj.GetSyntheticChildren();
+ })));
}
@@ -4354,6 +4426,11 @@ public:
LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter)));
LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter)));
LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter)));
+ LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo<TypeSummaryImpl>(interpreter,
+ "summary",
+ [](ValueObject& valobj) -> TypeSummaryImpl::SharedPointer {
+ return valobj.GetSummaryFormat();
+ })));
}
diff --git a/source/Commands/CommandObjectWatchpointCommand.cpp b/source/Commands/CommandObjectWatchpointCommand.cpp
index f46db7a..275ee92 100644
--- a/source/Commands/CommandObjectWatchpointCommand.cpp
+++ b/source/Commands/CommandObjectWatchpointCommand.cpp
@@ -279,17 +279,16 @@ but do NOT enter more than one command per line. \n" );
result.SetImmediateOutputStream (output_stream);
result.SetImmediateErrorStream (error_stream);
- bool stop_on_continue = true;
- bool echo_commands = false;
- bool print_results = true;
+ CommandInterpreterRunOptions options;
+ options.SetStopOnContinue (true);
+ options.SetStopOnError (data->stop_on_error);
+ options.SetEchoCommands (false);
+ options.SetPrintResults (true);
+ options.SetAddToHistory (false);
debugger.GetCommandInterpreter().HandleCommands (commands,
&exe_ctx,
- stop_on_continue,
- data->stop_on_error,
- echo_commands,
- print_results,
- eLazyBoolNo,
+ options,
result);
result.GetImmediateOutputStream()->Flush();
result.GetImmediateErrorStream()->Flush();
OpenPOWER on IntegriCloud