diff options
author | Jim Ingham <jingham@apple.com> | 2014-09-29 23:17:18 +0000 |
---|---|---|
committer | Jim Ingham <jingham@apple.com> | 2014-09-29 23:17:18 +0000 |
commit | 2bdbfd50d2c9a80c6132a3f83d1c097b0b0c6ca5 (patch) | |
tree | 08490741e71cb48256f74dc8e42944b6c427d79f /lldb/source/Commands | |
parent | 8b6fefb3a3b56597e3b1f92539f876c4555e7e2e (diff) | |
download | bcm5719-llvm-2bdbfd50d2c9a80c6132a3f83d1c097b0b0c6ca5.tar.gz bcm5719-llvm-2bdbfd50d2c9a80c6132a3f83d1c097b0b0c6ca5.zip |
This checkin is the first step in making the lldb thread stepping mechanism more accessible from
the user level. It adds the ability to invent new stepping modes implemented by python classes,
and to view the current thread plan stack and to some extent alter it.
I haven't gotten to documentation or tests yet. But this should not cause any behavior changes
if you don't use it, so its safe to check it in now and work on it incrementally.
llvm-svn: 218642
Diffstat (limited to 'lldb/source/Commands')
-rw-r--r-- | lldb/source/Commands/CommandObjectThread.cpp | 597 |
1 files changed, 398 insertions, 199 deletions
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index e7a8652ac89..785e8f078ee 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/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,6 +453,7 @@ public: RunMode m_run_mode; std::string m_avoid_regexp; std::string m_step_in_target; + std::string m_class_name; int32_t m_step_count; }; @@ -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"); @@ -686,10 +727,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 } }; @@ -1358,32 +1400,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 @@ -1451,81 +1483,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) + if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json)) { - 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 - { - 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; @@ -1958,6 +1925,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 +2203,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 () |