1ac7ddfbfSEd Maste //===-- CommandObjectThread.cpp ---------------------------------*- C++ -*-===// 2ac7ddfbfSEd Maste // 3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure 4ac7ddfbfSEd Maste // 5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source 6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details. 7ac7ddfbfSEd Maste // 8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===// 9ac7ddfbfSEd Maste 10ac7ddfbfSEd Maste #include "CommandObjectThread.h" 11ac7ddfbfSEd Maste 12ac7ddfbfSEd Maste // C Includes 13ac7ddfbfSEd Maste // C++ Includes 14ac7ddfbfSEd Maste // Other libraries and framework includes 15ac7ddfbfSEd Maste // Project includes 16ac7ddfbfSEd Maste #include "lldb/lldb-private.h" 17ac7ddfbfSEd Maste #include "lldb/Core/State.h" 18ac7ddfbfSEd Maste #include "lldb/Core/SourceManager.h" 191c3bbb01SEd Maste #include "lldb/Core/ValueObject.h" 20ac7ddfbfSEd Maste #include "lldb/Host/Host.h" 211c3bbb01SEd Maste #include "lldb/Host/StringConvert.h" 22ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h" 23ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h" 24ac7ddfbfSEd Maste #include "lldb/Interpreter/Options.h" 25ac7ddfbfSEd Maste #include "lldb/Symbol/CompileUnit.h" 26ac7ddfbfSEd Maste #include "lldb/Symbol/Function.h" 27ac7ddfbfSEd Maste #include "lldb/Symbol/LineTable.h" 28ac7ddfbfSEd Maste #include "lldb/Symbol/LineEntry.h" 29ac7ddfbfSEd Maste #include "lldb/Target/Process.h" 30ac7ddfbfSEd Maste #include "lldb/Target/RegisterContext.h" 31b952cd58SEd Maste #include "lldb/Target/SystemRuntime.h" 32ac7ddfbfSEd Maste #include "lldb/Target/Target.h" 33ac7ddfbfSEd Maste #include "lldb/Target/Thread.h" 34ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlan.h" 35ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepInstruction.h" 36ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepOut.h" 37ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepRange.h" 38ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepInRange.h" 39ac7ddfbfSEd Maste 40ac7ddfbfSEd Maste 41ac7ddfbfSEd Maste using namespace lldb; 42ac7ddfbfSEd Maste using namespace lldb_private; 43ac7ddfbfSEd Maste 44ac7ddfbfSEd Maste 45ac7ddfbfSEd Maste //------------------------------------------------------------------------- 46ac7ddfbfSEd Maste // CommandObjectThreadBacktrace 47ac7ddfbfSEd Maste //------------------------------------------------------------------------- 48ac7ddfbfSEd Maste 497aa51b79SEd Maste class CommandObjectIterateOverThreads : public CommandObjectParsed 507aa51b79SEd Maste { 517aa51b79SEd Maste public: 527aa51b79SEd Maste CommandObjectIterateOverThreads (CommandInterpreter &interpreter, 537aa51b79SEd Maste const char *name, 547aa51b79SEd Maste const char *help, 557aa51b79SEd Maste const char *syntax, 567aa51b79SEd Maste uint32_t flags) : 577aa51b79SEd Maste CommandObjectParsed (interpreter, name, help, syntax, flags) 587aa51b79SEd Maste { 597aa51b79SEd Maste } 607aa51b79SEd Maste 619f2f44ceSEd Maste ~CommandObjectIterateOverThreads() override {} 629f2f44ceSEd Maste 639f2f44ceSEd Maste bool 649f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 657aa51b79SEd Maste { 667aa51b79SEd Maste result.SetStatus (m_success_return); 677aa51b79SEd Maste 687aa51b79SEd Maste if (command.GetArgumentCount() == 0) 697aa51b79SEd Maste { 707aa51b79SEd Maste Thread *thread = m_exe_ctx.GetThreadPtr(); 717aa51b79SEd Maste if (!HandleOneThread (*thread, result)) 727aa51b79SEd Maste return false; 737aa51b79SEd Maste } 747aa51b79SEd Maste else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0) 757aa51b79SEd Maste { 767aa51b79SEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 777aa51b79SEd Maste uint32_t idx = 0; 787aa51b79SEd Maste for (ThreadSP thread_sp : process->Threads()) 797aa51b79SEd Maste { 807aa51b79SEd Maste if (idx != 0 && m_add_return) 817aa51b79SEd Maste result.AppendMessage(""); 827aa51b79SEd Maste 837aa51b79SEd Maste if (!HandleOneThread(*(thread_sp.get()), result)) 847aa51b79SEd Maste return false; 857aa51b79SEd Maste ++idx; 867aa51b79SEd Maste } 877aa51b79SEd Maste } 887aa51b79SEd Maste else 897aa51b79SEd Maste { 907aa51b79SEd Maste const size_t num_args = command.GetArgumentCount(); 917aa51b79SEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 927aa51b79SEd Maste Mutex::Locker locker (process->GetThreadList().GetMutex()); 937aa51b79SEd Maste std::vector<ThreadSP> thread_sps; 947aa51b79SEd Maste 957aa51b79SEd Maste for (size_t i = 0; i < num_args; i++) 967aa51b79SEd Maste { 977aa51b79SEd Maste bool success; 987aa51b79SEd Maste 991c3bbb01SEd Maste uint32_t thread_idx = StringConvert::ToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success); 1007aa51b79SEd Maste if (!success) 1017aa51b79SEd Maste { 1027aa51b79SEd Maste result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); 1037aa51b79SEd Maste result.SetStatus (eReturnStatusFailed); 1047aa51b79SEd Maste return false; 1057aa51b79SEd Maste } 1067aa51b79SEd Maste 1077aa51b79SEd Maste thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx)); 1087aa51b79SEd Maste 1097aa51b79SEd Maste if (!thread_sps[i]) 1107aa51b79SEd Maste { 1117aa51b79SEd Maste result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i)); 1127aa51b79SEd Maste result.SetStatus (eReturnStatusFailed); 1137aa51b79SEd Maste return false; 1147aa51b79SEd Maste } 1157aa51b79SEd Maste 1167aa51b79SEd Maste } 1177aa51b79SEd Maste 1187aa51b79SEd Maste for (uint32_t i = 0; i < num_args; i++) 1197aa51b79SEd Maste { 1207aa51b79SEd Maste if (!HandleOneThread (*(thread_sps[i].get()), result)) 1217aa51b79SEd Maste return false; 1227aa51b79SEd Maste 1237aa51b79SEd Maste if (i < num_args - 1 && m_add_return) 1247aa51b79SEd Maste result.AppendMessage(""); 1257aa51b79SEd Maste } 1267aa51b79SEd Maste } 1277aa51b79SEd Maste return result.Succeeded(); 1287aa51b79SEd Maste } 1297aa51b79SEd Maste 1307aa51b79SEd Maste protected: 1317aa51b79SEd Maste 1327aa51b79SEd Maste // Override this to do whatever you need to do for one thread. 1337aa51b79SEd Maste // 1347aa51b79SEd Maste // If you return false, the iteration will stop, otherwise it will proceed. 1357aa51b79SEd Maste // The result is set to m_success_return (defaults to eReturnStatusSuccessFinishResult) before the iteration, 1367aa51b79SEd Maste // so you only need to set the return status in HandleOneThread if you want to indicate an error. 1377aa51b79SEd Maste // If m_add_return is true, a blank line will be inserted between each of the listings (except the last one.) 1387aa51b79SEd Maste 1397aa51b79SEd Maste virtual bool 1407aa51b79SEd Maste HandleOneThread (Thread &thread, CommandReturnObject &result) = 0; 1417aa51b79SEd Maste 1427aa51b79SEd Maste ReturnStatus m_success_return = eReturnStatusSuccessFinishResult; 1437aa51b79SEd Maste bool m_add_return = true; 1447aa51b79SEd Maste 1457aa51b79SEd Maste }; 1467aa51b79SEd Maste 1477aa51b79SEd Maste //------------------------------------------------------------------------- 1487aa51b79SEd Maste // CommandObjectThreadBacktrace 1497aa51b79SEd Maste //------------------------------------------------------------------------- 1507aa51b79SEd Maste 1517aa51b79SEd Maste class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads 152ac7ddfbfSEd Maste { 153ac7ddfbfSEd Maste public: 154ac7ddfbfSEd Maste 155ac7ddfbfSEd Maste class CommandOptions : public Options 156ac7ddfbfSEd Maste { 157ac7ddfbfSEd Maste public: 158ac7ddfbfSEd Maste 159ac7ddfbfSEd Maste CommandOptions (CommandInterpreter &interpreter) : 160ac7ddfbfSEd Maste Options(interpreter) 161ac7ddfbfSEd Maste { 162ac7ddfbfSEd Maste // Keep default values of all options in one place: OptionParsingStarting () 163ac7ddfbfSEd Maste OptionParsingStarting (); 164ac7ddfbfSEd Maste } 165ac7ddfbfSEd Maste 1669f2f44ceSEd Maste ~CommandOptions () override 167ac7ddfbfSEd Maste { 168ac7ddfbfSEd Maste } 169ac7ddfbfSEd Maste 1709f2f44ceSEd Maste Error 1719f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 172ac7ddfbfSEd Maste { 173ac7ddfbfSEd Maste Error error; 174ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 175ac7ddfbfSEd Maste 176ac7ddfbfSEd Maste switch (short_option) 177ac7ddfbfSEd Maste { 178ac7ddfbfSEd Maste case 'c': 179ac7ddfbfSEd Maste { 180ac7ddfbfSEd Maste bool success; 1811c3bbb01SEd Maste int32_t input_count = StringConvert::ToSInt32 (option_arg, -1, 0, &success); 182ac7ddfbfSEd Maste if (!success) 183ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option); 184ac7ddfbfSEd Maste if (input_count < -1) 185ac7ddfbfSEd Maste m_count = UINT32_MAX; 186ac7ddfbfSEd Maste else 187ac7ddfbfSEd Maste m_count = input_count; 188ac7ddfbfSEd Maste } 189ac7ddfbfSEd Maste break; 190ac7ddfbfSEd Maste case 's': 191ac7ddfbfSEd Maste { 192ac7ddfbfSEd Maste bool success; 1931c3bbb01SEd Maste m_start = StringConvert::ToUInt32 (option_arg, 0, 0, &success); 194ac7ddfbfSEd Maste if (!success) 195ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option); 196ac7ddfbfSEd Maste } 197b952cd58SEd Maste case 'e': 198b952cd58SEd Maste { 199b952cd58SEd Maste bool success; 200b952cd58SEd Maste m_extended_backtrace = Args::StringToBoolean (option_arg, false, &success); 201b952cd58SEd Maste if (!success) 202b952cd58SEd Maste error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option); 203b952cd58SEd Maste } 204ac7ddfbfSEd Maste break; 205ac7ddfbfSEd Maste default: 206ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 207ac7ddfbfSEd Maste break; 208ac7ddfbfSEd Maste 209ac7ddfbfSEd Maste } 210ac7ddfbfSEd Maste return error; 211ac7ddfbfSEd Maste } 212ac7ddfbfSEd Maste 213ac7ddfbfSEd Maste void 2149f2f44ceSEd Maste OptionParsingStarting () override 215ac7ddfbfSEd Maste { 216ac7ddfbfSEd Maste m_count = UINT32_MAX; 217ac7ddfbfSEd Maste m_start = 0; 218b952cd58SEd Maste m_extended_backtrace = false; 219ac7ddfbfSEd Maste } 220ac7ddfbfSEd Maste 221ac7ddfbfSEd Maste const OptionDefinition* 2229f2f44ceSEd Maste GetDefinitions () override 223ac7ddfbfSEd Maste { 224ac7ddfbfSEd Maste return g_option_table; 225ac7ddfbfSEd Maste } 226ac7ddfbfSEd Maste 227ac7ddfbfSEd Maste // Options table: Required for subclasses of Options. 228ac7ddfbfSEd Maste 229ac7ddfbfSEd Maste static OptionDefinition g_option_table[]; 230ac7ddfbfSEd Maste 231ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 232ac7ddfbfSEd Maste uint32_t m_count; 233ac7ddfbfSEd Maste uint32_t m_start; 234b952cd58SEd Maste bool m_extended_backtrace; 235ac7ddfbfSEd Maste }; 236ac7ddfbfSEd Maste 237ac7ddfbfSEd Maste CommandObjectThreadBacktrace (CommandInterpreter &interpreter) : 2387aa51b79SEd Maste CommandObjectIterateOverThreads (interpreter, 239ac7ddfbfSEd Maste "thread backtrace", 240ac7ddfbfSEd Maste "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.", 241ac7ddfbfSEd Maste NULL, 2421c3bbb01SEd Maste eCommandRequiresProcess | 2431c3bbb01SEd Maste eCommandRequiresThread | 2441c3bbb01SEd Maste eCommandTryTargetAPILock | 2451c3bbb01SEd Maste eCommandProcessMustBeLaunched | 2461c3bbb01SEd Maste eCommandProcessMustBePaused ), 247ac7ddfbfSEd Maste m_options(interpreter) 248ac7ddfbfSEd Maste { 249ac7ddfbfSEd Maste } 250ac7ddfbfSEd Maste 2519f2f44ceSEd Maste ~CommandObjectThreadBacktrace() override 252ac7ddfbfSEd Maste { 253ac7ddfbfSEd Maste } 254ac7ddfbfSEd Maste 2559f2f44ceSEd Maste Options * 2569f2f44ceSEd Maste GetOptions () override 257ac7ddfbfSEd Maste { 258ac7ddfbfSEd Maste return &m_options; 259ac7ddfbfSEd Maste } 260ac7ddfbfSEd Maste 261ac7ddfbfSEd Maste protected: 262b952cd58SEd Maste void 263b952cd58SEd Maste DoExtendedBacktrace (Thread *thread, CommandReturnObject &result) 264b952cd58SEd Maste { 265b952cd58SEd Maste SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime(); 266b952cd58SEd Maste if (runtime) 267b952cd58SEd Maste { 268b952cd58SEd Maste Stream &strm = result.GetOutputStream(); 269b952cd58SEd Maste const std::vector<ConstString> &types = runtime->GetExtendedBacktraceTypes(); 270b952cd58SEd Maste for (auto type : types) 271b952cd58SEd Maste { 272b952cd58SEd Maste ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread (thread->shared_from_this(), type); 273b952cd58SEd Maste if (ext_thread_sp && ext_thread_sp->IsValid ()) 274b952cd58SEd Maste { 275b952cd58SEd Maste const uint32_t num_frames_with_source = 0; 276b952cd58SEd Maste if (ext_thread_sp->GetStatus (strm, 277b952cd58SEd Maste m_options.m_start, 278b952cd58SEd Maste m_options.m_count, 279b952cd58SEd Maste num_frames_with_source)) 280b952cd58SEd Maste { 281b952cd58SEd Maste DoExtendedBacktrace (ext_thread_sp.get(), result); 282b952cd58SEd Maste } 283b952cd58SEd Maste } 284b952cd58SEd Maste } 285b952cd58SEd Maste } 286b952cd58SEd Maste } 287b952cd58SEd Maste 2889f2f44ceSEd Maste bool 2899f2f44ceSEd Maste HandleOneThread (Thread &thread, CommandReturnObject &result) override 290ac7ddfbfSEd Maste { 291ac7ddfbfSEd Maste Stream &strm = result.GetOutputStream(); 292ac7ddfbfSEd Maste 293ac7ddfbfSEd Maste // Don't show source context when doing backtraces. 294ac7ddfbfSEd Maste const uint32_t num_frames_with_source = 0; 295b952cd58SEd Maste 2967aa51b79SEd Maste if (!thread.GetStatus (strm, 297ac7ddfbfSEd Maste m_options.m_start, 298ac7ddfbfSEd Maste m_options.m_count, 299ac7ddfbfSEd Maste num_frames_with_source)) 300ac7ddfbfSEd Maste { 3017aa51b79SEd Maste result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", thread.GetIndexID()); 302ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 303ac7ddfbfSEd Maste return false; 304ac7ddfbfSEd Maste } 305b952cd58SEd Maste if (m_options.m_extended_backtrace) 306b952cd58SEd Maste { 3077aa51b79SEd Maste DoExtendedBacktrace (&thread, result); 308b952cd58SEd Maste } 309ac7ddfbfSEd Maste 3107aa51b79SEd Maste return true; 311ac7ddfbfSEd Maste } 312ac7ddfbfSEd Maste 313ac7ddfbfSEd Maste CommandOptions m_options; 314ac7ddfbfSEd Maste }; 315ac7ddfbfSEd Maste 316ac7ddfbfSEd Maste OptionDefinition 317ac7ddfbfSEd Maste CommandObjectThreadBacktrace::CommandOptions::g_option_table[] = 318ac7ddfbfSEd Maste { 3190127ef0fSEd Maste { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"}, 3200127ef0fSEd Maste { LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"}, 3210127ef0fSEd Maste { LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Show the extended backtrace, if available"}, 3220127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 323ac7ddfbfSEd Maste }; 324ac7ddfbfSEd Maste 325ac7ddfbfSEd Maste enum StepScope 326ac7ddfbfSEd Maste { 327ac7ddfbfSEd Maste eStepScopeSource, 328ac7ddfbfSEd Maste eStepScopeInstruction 329ac7ddfbfSEd Maste }; 330ac7ddfbfSEd Maste 331ac7ddfbfSEd Maste class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed 332ac7ddfbfSEd Maste { 333ac7ddfbfSEd Maste public: 334ac7ddfbfSEd Maste 335ac7ddfbfSEd Maste class CommandOptions : public Options 336ac7ddfbfSEd Maste { 337ac7ddfbfSEd Maste public: 338ac7ddfbfSEd Maste 339ac7ddfbfSEd Maste CommandOptions (CommandInterpreter &interpreter) : 340ac7ddfbfSEd Maste Options (interpreter) 341ac7ddfbfSEd Maste { 342ac7ddfbfSEd Maste // Keep default values of all options in one place: OptionParsingStarting () 343ac7ddfbfSEd Maste OptionParsingStarting (); 344ac7ddfbfSEd Maste } 345ac7ddfbfSEd Maste 3469f2f44ceSEd Maste ~CommandOptions () override 347ac7ddfbfSEd Maste { 348ac7ddfbfSEd Maste } 349ac7ddfbfSEd Maste 3509f2f44ceSEd Maste Error 3519f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 352ac7ddfbfSEd Maste { 353ac7ddfbfSEd Maste Error error; 354ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 355ac7ddfbfSEd Maste 356ac7ddfbfSEd Maste switch (short_option) 357ac7ddfbfSEd Maste { 358ac7ddfbfSEd Maste case 'a': 359ac7ddfbfSEd Maste { 360ac7ddfbfSEd Maste bool success; 3610127ef0fSEd Maste bool avoid_no_debug = Args::StringToBoolean (option_arg, true, &success); 362ac7ddfbfSEd Maste if (!success) 363ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option); 3640127ef0fSEd Maste else 3650127ef0fSEd Maste { 3660127ef0fSEd Maste m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; 3670127ef0fSEd Maste } 368ac7ddfbfSEd Maste } 369ac7ddfbfSEd Maste break; 370ac7ddfbfSEd Maste 3710127ef0fSEd Maste case 'A': 3720127ef0fSEd Maste { 3730127ef0fSEd Maste bool success; 3740127ef0fSEd Maste bool avoid_no_debug = Args::StringToBoolean (option_arg, true, &success); 3750127ef0fSEd Maste if (!success) 3760127ef0fSEd Maste error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option); 3770127ef0fSEd Maste else 3780127ef0fSEd Maste { 3790127ef0fSEd Maste m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; 3800127ef0fSEd Maste } 3810127ef0fSEd Maste } 3820127ef0fSEd Maste break; 3830127ef0fSEd Maste 3840127ef0fSEd Maste case 'c': 3850127ef0fSEd Maste { 3861c3bbb01SEd Maste m_step_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 3870127ef0fSEd Maste if (m_step_count == UINT32_MAX) 3880127ef0fSEd Maste error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); 3890127ef0fSEd Maste break; 3900127ef0fSEd Maste } 3910127ef0fSEd Maste break; 3927aa51b79SEd Maste case 'C': 3937aa51b79SEd Maste { 3947aa51b79SEd Maste m_class_name.clear(); 3957aa51b79SEd Maste m_class_name.assign(option_arg); 3967aa51b79SEd Maste } 3977aa51b79SEd Maste break; 398ac7ddfbfSEd Maste case 'm': 399ac7ddfbfSEd Maste { 400ac7ddfbfSEd Maste OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 401ac7ddfbfSEd Maste m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error); 402ac7ddfbfSEd Maste } 403ac7ddfbfSEd Maste break; 404ac7ddfbfSEd Maste 405ac7ddfbfSEd Maste case 'r': 406ac7ddfbfSEd Maste { 407ac7ddfbfSEd Maste m_avoid_regexp.clear(); 408ac7ddfbfSEd Maste m_avoid_regexp.assign(option_arg); 409ac7ddfbfSEd Maste } 410ac7ddfbfSEd Maste break; 411ac7ddfbfSEd Maste 412ac7ddfbfSEd Maste case 't': 413ac7ddfbfSEd Maste { 414ac7ddfbfSEd Maste m_step_in_target.clear(); 415ac7ddfbfSEd Maste m_step_in_target.assign(option_arg); 416ac7ddfbfSEd Maste 417ac7ddfbfSEd Maste } 418ac7ddfbfSEd Maste break; 419ac7ddfbfSEd Maste default: 420ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 421ac7ddfbfSEd Maste break; 422ac7ddfbfSEd Maste 423ac7ddfbfSEd Maste } 424ac7ddfbfSEd Maste return error; 425ac7ddfbfSEd Maste } 426ac7ddfbfSEd Maste 427ac7ddfbfSEd Maste void 4289f2f44ceSEd Maste OptionParsingStarting () override 429ac7ddfbfSEd Maste { 4300127ef0fSEd Maste m_step_in_avoid_no_debug = eLazyBoolCalculate; 4310127ef0fSEd Maste m_step_out_avoid_no_debug = eLazyBoolCalculate; 432ac7ddfbfSEd Maste m_run_mode = eOnlyDuringStepping; 4331c3bbb01SEd Maste 4341c3bbb01SEd Maste // Check if we are in Non-Stop mode 4351c3bbb01SEd Maste lldb::TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); 4361c3bbb01SEd Maste if (target_sp.get() != nullptr && target_sp->GetNonStopModeEnabled()) 4371c3bbb01SEd Maste m_run_mode = eOnlyThisThread; 4381c3bbb01SEd Maste 439ac7ddfbfSEd Maste m_avoid_regexp.clear(); 440ac7ddfbfSEd Maste m_step_in_target.clear(); 4417aa51b79SEd Maste m_class_name.clear(); 4420127ef0fSEd Maste m_step_count = 1; 443ac7ddfbfSEd Maste } 444ac7ddfbfSEd Maste 445ac7ddfbfSEd Maste const OptionDefinition* 4469f2f44ceSEd Maste GetDefinitions () override 447ac7ddfbfSEd Maste { 448ac7ddfbfSEd Maste return g_option_table; 449ac7ddfbfSEd Maste } 450ac7ddfbfSEd Maste 451ac7ddfbfSEd Maste // Options table: Required for subclasses of Options. 452ac7ddfbfSEd Maste 453ac7ddfbfSEd Maste static OptionDefinition g_option_table[]; 454ac7ddfbfSEd Maste 455ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 4560127ef0fSEd Maste LazyBool m_step_in_avoid_no_debug; 4570127ef0fSEd Maste LazyBool m_step_out_avoid_no_debug; 458ac7ddfbfSEd Maste RunMode m_run_mode; 459ac7ddfbfSEd Maste std::string m_avoid_regexp; 460ac7ddfbfSEd Maste std::string m_step_in_target; 4617aa51b79SEd Maste std::string m_class_name; 4627aa51b79SEd Maste uint32_t m_step_count; 463ac7ddfbfSEd Maste }; 464ac7ddfbfSEd Maste 465ac7ddfbfSEd Maste CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter, 466ac7ddfbfSEd Maste const char *name, 467ac7ddfbfSEd Maste const char *help, 468ac7ddfbfSEd Maste const char *syntax, 469ac7ddfbfSEd Maste StepType step_type, 470ac7ddfbfSEd Maste StepScope step_scope) : 471ac7ddfbfSEd Maste CommandObjectParsed (interpreter, name, help, syntax, 4721c3bbb01SEd Maste eCommandRequiresProcess | 4731c3bbb01SEd Maste eCommandRequiresThread | 4741c3bbb01SEd Maste eCommandTryTargetAPILock | 4751c3bbb01SEd Maste eCommandProcessMustBeLaunched | 4761c3bbb01SEd Maste eCommandProcessMustBePaused ), 477ac7ddfbfSEd Maste m_step_type (step_type), 478ac7ddfbfSEd Maste m_step_scope (step_scope), 479ac7ddfbfSEd Maste m_options (interpreter) 480ac7ddfbfSEd Maste { 481ac7ddfbfSEd Maste CommandArgumentEntry arg; 482ac7ddfbfSEd Maste CommandArgumentData thread_id_arg; 483ac7ddfbfSEd Maste 484ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 485ac7ddfbfSEd Maste thread_id_arg.arg_type = eArgTypeThreadID; 486ac7ddfbfSEd Maste thread_id_arg.arg_repetition = eArgRepeatOptional; 487ac7ddfbfSEd Maste 488ac7ddfbfSEd Maste // There is only one variant this argument could be; put it into the argument entry. 489ac7ddfbfSEd Maste arg.push_back (thread_id_arg); 490ac7ddfbfSEd Maste 491ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 492ac7ddfbfSEd Maste m_arguments.push_back (arg); 493ac7ddfbfSEd Maste } 494ac7ddfbfSEd Maste 4959f2f44ceSEd Maste ~CommandObjectThreadStepWithTypeAndScope () override 496ac7ddfbfSEd Maste { 497ac7ddfbfSEd Maste } 498ac7ddfbfSEd Maste 499ac7ddfbfSEd Maste Options * 5009f2f44ceSEd Maste GetOptions () override 501ac7ddfbfSEd Maste { 502ac7ddfbfSEd Maste return &m_options; 503ac7ddfbfSEd Maste } 504ac7ddfbfSEd Maste 505ac7ddfbfSEd Maste protected: 5069f2f44ceSEd Maste bool 5079f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 508ac7ddfbfSEd Maste { 509ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 510ac7ddfbfSEd Maste bool synchronous_execution = m_interpreter.GetSynchronous(); 511ac7ddfbfSEd Maste 512ac7ddfbfSEd Maste const uint32_t num_threads = process->GetThreadList().GetSize(); 513ac7ddfbfSEd Maste Thread *thread = NULL; 514ac7ddfbfSEd Maste 515ac7ddfbfSEd Maste if (command.GetArgumentCount() == 0) 516ac7ddfbfSEd Maste { 517ac7ddfbfSEd Maste thread = process->GetThreadList().GetSelectedThread().get(); 518ac7ddfbfSEd Maste if (thread == NULL) 519ac7ddfbfSEd Maste { 520ac7ddfbfSEd Maste result.AppendError ("no selected thread in process"); 521ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 522ac7ddfbfSEd Maste return false; 523ac7ddfbfSEd Maste } 524ac7ddfbfSEd Maste } 525ac7ddfbfSEd Maste else 526ac7ddfbfSEd Maste { 527ac7ddfbfSEd Maste const char *thread_idx_cstr = command.GetArgumentAtIndex(0); 5281c3bbb01SEd Maste uint32_t step_thread_idx = StringConvert::ToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32); 529ac7ddfbfSEd Maste if (step_thread_idx == LLDB_INVALID_INDEX32) 530ac7ddfbfSEd Maste { 531ac7ddfbfSEd Maste result.AppendErrorWithFormat ("invalid thread index '%s'.\n", thread_idx_cstr); 532ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 533ac7ddfbfSEd Maste return false; 534ac7ddfbfSEd Maste } 535ac7ddfbfSEd Maste thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get(); 536ac7ddfbfSEd Maste if (thread == NULL) 537ac7ddfbfSEd Maste { 538ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 539ac7ddfbfSEd Maste step_thread_idx, num_threads); 540ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 541ac7ddfbfSEd Maste return false; 542ac7ddfbfSEd Maste } 543ac7ddfbfSEd Maste } 544ac7ddfbfSEd Maste 5457aa51b79SEd Maste if (m_step_type == eStepTypeScripted) 5467aa51b79SEd Maste { 5477aa51b79SEd Maste if (m_options.m_class_name.empty()) 5487aa51b79SEd Maste { 5497aa51b79SEd Maste result.AppendErrorWithFormat ("empty class name for scripted step."); 5507aa51b79SEd Maste result.SetStatus(eReturnStatusFailed); 5517aa51b79SEd Maste return false; 5527aa51b79SEd Maste } 5537aa51b79SEd Maste else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists(m_options.m_class_name.c_str())) 5547aa51b79SEd Maste { 5557aa51b79SEd Maste result.AppendErrorWithFormat ("class for scripted step: \"%s\" does not exist.", m_options.m_class_name.c_str()); 5567aa51b79SEd Maste result.SetStatus(eReturnStatusFailed); 5577aa51b79SEd Maste return false; 5587aa51b79SEd Maste } 5597aa51b79SEd Maste } 5607aa51b79SEd Maste 561ac7ddfbfSEd Maste const bool abort_other_plans = false; 562ac7ddfbfSEd Maste const lldb::RunMode stop_other_threads = m_options.m_run_mode; 563ac7ddfbfSEd Maste 564ac7ddfbfSEd Maste // This is a bit unfortunate, but not all the commands in this command object support 565ac7ddfbfSEd Maste // only while stepping, so I use the bool for them. 566ac7ddfbfSEd Maste bool bool_stop_other_threads; 567ac7ddfbfSEd Maste if (m_options.m_run_mode == eAllThreads) 568ac7ddfbfSEd Maste bool_stop_other_threads = false; 569ac7ddfbfSEd Maste else if (m_options.m_run_mode == eOnlyDuringStepping) 570ac7ddfbfSEd Maste { 5717aa51b79SEd Maste if (m_step_type == eStepTypeOut || m_step_type == eStepTypeScripted) 572ac7ddfbfSEd Maste bool_stop_other_threads = false; 573ac7ddfbfSEd Maste else 574ac7ddfbfSEd Maste bool_stop_other_threads = true; 575ac7ddfbfSEd Maste } 576ac7ddfbfSEd Maste else 577ac7ddfbfSEd Maste bool_stop_other_threads = true; 578ac7ddfbfSEd Maste 579ac7ddfbfSEd Maste ThreadPlanSP new_plan_sp; 580ac7ddfbfSEd Maste 581ac7ddfbfSEd Maste if (m_step_type == eStepTypeInto) 582ac7ddfbfSEd Maste { 583ac7ddfbfSEd Maste StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 5841c3bbb01SEd Maste assert(frame != nullptr); 585ac7ddfbfSEd Maste 586ac7ddfbfSEd Maste if (frame->HasDebugInformation ()) 587ac7ddfbfSEd Maste { 588ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans, 5899f2f44ceSEd Maste frame->GetSymbolContext(eSymbolContextEverything).line_entry, 590ac7ddfbfSEd Maste frame->GetSymbolContext(eSymbolContextEverything), 591ac7ddfbfSEd Maste m_options.m_step_in_target.c_str(), 592ac7ddfbfSEd Maste stop_other_threads, 5930127ef0fSEd Maste m_options.m_step_in_avoid_no_debug, 5940127ef0fSEd Maste m_options.m_step_out_avoid_no_debug); 5950127ef0fSEd Maste 596ac7ddfbfSEd Maste if (new_plan_sp && !m_options.m_avoid_regexp.empty()) 597ac7ddfbfSEd Maste { 598ac7ddfbfSEd Maste ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan_sp.get()); 599ac7ddfbfSEd Maste step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str()); 600ac7ddfbfSEd Maste } 601ac7ddfbfSEd Maste } 602ac7ddfbfSEd Maste else 603ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); 604ac7ddfbfSEd Maste 605ac7ddfbfSEd Maste } 606ac7ddfbfSEd Maste else if (m_step_type == eStepTypeOver) 607ac7ddfbfSEd Maste { 608ac7ddfbfSEd Maste StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 609ac7ddfbfSEd Maste 610ac7ddfbfSEd Maste if (frame->HasDebugInformation()) 611ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans, 6129f2f44ceSEd Maste frame->GetSymbolContext(eSymbolContextEverything).line_entry, 613ac7ddfbfSEd Maste frame->GetSymbolContext(eSymbolContextEverything), 6140127ef0fSEd Maste stop_other_threads, 6150127ef0fSEd Maste m_options.m_step_out_avoid_no_debug); 616ac7ddfbfSEd Maste else 617ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, 618ac7ddfbfSEd Maste abort_other_plans, 619ac7ddfbfSEd Maste bool_stop_other_threads); 620ac7ddfbfSEd Maste 621ac7ddfbfSEd Maste } 622ac7ddfbfSEd Maste else if (m_step_type == eStepTypeTrace) 623ac7ddfbfSEd Maste { 624ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); 625ac7ddfbfSEd Maste } 626ac7ddfbfSEd Maste else if (m_step_type == eStepTypeTraceOver) 627ac7ddfbfSEd Maste { 628ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads); 629ac7ddfbfSEd Maste } 630ac7ddfbfSEd Maste else if (m_step_type == eStepTypeOut) 631ac7ddfbfSEd Maste { 632ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepOut (abort_other_plans, 633ac7ddfbfSEd Maste NULL, 634ac7ddfbfSEd Maste false, 635ac7ddfbfSEd Maste bool_stop_other_threads, 636ac7ddfbfSEd Maste eVoteYes, 637ac7ddfbfSEd Maste eVoteNoOpinion, 6380127ef0fSEd Maste thread->GetSelectedFrameIndex(), 6390127ef0fSEd Maste m_options.m_step_out_avoid_no_debug); 640ac7ddfbfSEd Maste } 6417aa51b79SEd Maste else if (m_step_type == eStepTypeScripted) 6427aa51b79SEd Maste { 6437aa51b79SEd Maste new_plan_sp = thread->QueueThreadPlanForStepScripted (abort_other_plans, 6447aa51b79SEd Maste m_options.m_class_name.c_str(), 6457aa51b79SEd Maste bool_stop_other_threads); 6467aa51b79SEd Maste } 647ac7ddfbfSEd Maste else 648ac7ddfbfSEd Maste { 649ac7ddfbfSEd Maste result.AppendError ("step type is not supported"); 650ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 651ac7ddfbfSEd Maste return false; 652ac7ddfbfSEd Maste } 653ac7ddfbfSEd Maste 654ac7ddfbfSEd Maste // If we got a new plan, then set it to be a master plan (User level Plans should be master plans 655ac7ddfbfSEd Maste // so that they can be interruptible). Then resume the process. 656ac7ddfbfSEd Maste 657ac7ddfbfSEd Maste if (new_plan_sp) 658ac7ddfbfSEd Maste { 659ac7ddfbfSEd Maste new_plan_sp->SetIsMasterPlan (true); 660ac7ddfbfSEd Maste new_plan_sp->SetOkayToDiscard (false); 661ac7ddfbfSEd Maste 6620127ef0fSEd Maste if (m_options.m_step_count > 1) 6630127ef0fSEd Maste { 6640127ef0fSEd Maste if (new_plan_sp->SetIterationCount(m_options.m_step_count)) 6650127ef0fSEd Maste { 6660127ef0fSEd Maste result.AppendWarning ("step operation does not support iteration count."); 6670127ef0fSEd Maste } 6680127ef0fSEd Maste } 6690127ef0fSEd Maste 6707aa51b79SEd Maste 671ac7ddfbfSEd Maste process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 6727aa51b79SEd Maste 6731c3bbb01SEd Maste const uint32_t iohandler_id = process->GetIOHandlerID(); 6741c3bbb01SEd Maste 6757aa51b79SEd Maste StreamString stream; 6767aa51b79SEd Maste Error error; 6777aa51b79SEd Maste if (synchronous_execution) 6787aa51b79SEd Maste error = process->ResumeSynchronous (&stream); 6797aa51b79SEd Maste else 6807aa51b79SEd Maste error = process->Resume (); 681ac7ddfbfSEd Maste 6820127ef0fSEd Maste // There is a race condition where this thread will return up the call stack to the main command handler 6830127ef0fSEd Maste // and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has 6840127ef0fSEd Maste // a chance to call PushProcessIOHandler(). 6851c3bbb01SEd Maste process->SyncIOHandler(iohandler_id, 2000); 686ac7ddfbfSEd Maste 687ac7ddfbfSEd Maste if (synchronous_execution) 688ac7ddfbfSEd Maste { 6897aa51b79SEd Maste // If any state changed events had anything to say, add that to the result 6907aa51b79SEd Maste if (stream.GetData()) 6917aa51b79SEd Maste result.AppendMessage(stream.GetData()); 692ac7ddfbfSEd Maste 693ac7ddfbfSEd Maste process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 694ac7ddfbfSEd Maste result.SetDidChangeProcessState (true); 695ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishNoResult); 696ac7ddfbfSEd Maste } 697ac7ddfbfSEd Maste else 698ac7ddfbfSEd Maste { 699ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessContinuingNoResult); 700ac7ddfbfSEd Maste } 701ac7ddfbfSEd Maste } 702ac7ddfbfSEd Maste else 703ac7ddfbfSEd Maste { 704ac7ddfbfSEd Maste result.AppendError ("Couldn't find thread plan to implement step type."); 705ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 706ac7ddfbfSEd Maste } 707ac7ddfbfSEd Maste return result.Succeeded(); 708ac7ddfbfSEd Maste } 709ac7ddfbfSEd Maste 710ac7ddfbfSEd Maste protected: 711ac7ddfbfSEd Maste StepType m_step_type; 712ac7ddfbfSEd Maste StepScope m_step_scope; 713ac7ddfbfSEd Maste CommandOptions m_options; 714ac7ddfbfSEd Maste }; 715ac7ddfbfSEd Maste 716ac7ddfbfSEd Maste static OptionEnumValueElement 717ac7ddfbfSEd Maste g_tri_running_mode[] = 718ac7ddfbfSEd Maste { 719ac7ddfbfSEd Maste { eOnlyThisThread, "this-thread", "Run only this thread"}, 720ac7ddfbfSEd Maste { eAllThreads, "all-threads", "Run all threads"}, 721ac7ddfbfSEd Maste { eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"}, 722ac7ddfbfSEd Maste { 0, NULL, NULL } 723ac7ddfbfSEd Maste }; 724ac7ddfbfSEd Maste 725ac7ddfbfSEd Maste static OptionEnumValueElement 726ac7ddfbfSEd Maste g_duo_running_mode[] = 727ac7ddfbfSEd Maste { 728ac7ddfbfSEd Maste { eOnlyThisThread, "this-thread", "Run only this thread"}, 729ac7ddfbfSEd Maste { eAllThreads, "all-threads", "Run all threads"}, 730ac7ddfbfSEd Maste { 0, NULL, NULL } 731ac7ddfbfSEd Maste }; 732ac7ddfbfSEd Maste 733ac7ddfbfSEd Maste OptionDefinition 734ac7ddfbfSEd Maste CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] = 735ac7ddfbfSEd Maste { 7360127ef0fSEd Maste { 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."}, 7370127ef0fSEd Maste { 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."}, 7380127ef0fSEd Maste { 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."}, 7390127ef0fSEd Maste { 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."}, 7400127ef0fSEd Maste { 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."}, 7410127ef0fSEd Maste { 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."}, 7427aa51b79SEd Maste { 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."}, 7430127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 744ac7ddfbfSEd Maste }; 745ac7ddfbfSEd Maste 746ac7ddfbfSEd Maste 747ac7ddfbfSEd Maste //------------------------------------------------------------------------- 748ac7ddfbfSEd Maste // CommandObjectThreadContinue 749ac7ddfbfSEd Maste //------------------------------------------------------------------------- 750ac7ddfbfSEd Maste 751ac7ddfbfSEd Maste class CommandObjectThreadContinue : public CommandObjectParsed 752ac7ddfbfSEd Maste { 753ac7ddfbfSEd Maste public: 754ac7ddfbfSEd Maste 755ac7ddfbfSEd Maste CommandObjectThreadContinue (CommandInterpreter &interpreter) : 756ac7ddfbfSEd Maste CommandObjectParsed (interpreter, 757ac7ddfbfSEd Maste "thread continue", 758ac7ddfbfSEd Maste "Continue execution of one or more threads in an active process.", 759ac7ddfbfSEd Maste NULL, 7601c3bbb01SEd Maste eCommandRequiresThread | 7611c3bbb01SEd Maste eCommandTryTargetAPILock | 7621c3bbb01SEd Maste eCommandProcessMustBeLaunched | 7631c3bbb01SEd Maste eCommandProcessMustBePaused) 764ac7ddfbfSEd Maste { 765ac7ddfbfSEd Maste CommandArgumentEntry arg; 766ac7ddfbfSEd Maste CommandArgumentData thread_idx_arg; 767ac7ddfbfSEd Maste 768ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 769ac7ddfbfSEd Maste thread_idx_arg.arg_type = eArgTypeThreadIndex; 770ac7ddfbfSEd Maste thread_idx_arg.arg_repetition = eArgRepeatPlus; 771ac7ddfbfSEd Maste 772ac7ddfbfSEd Maste // There is only one variant this argument could be; put it into the argument entry. 773ac7ddfbfSEd Maste arg.push_back (thread_idx_arg); 774ac7ddfbfSEd Maste 775ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 776ac7ddfbfSEd Maste m_arguments.push_back (arg); 777ac7ddfbfSEd Maste } 778ac7ddfbfSEd Maste 779ac7ddfbfSEd Maste 7809f2f44ceSEd Maste ~CommandObjectThreadContinue () override 781ac7ddfbfSEd Maste { 782ac7ddfbfSEd Maste } 783ac7ddfbfSEd Maste 7849f2f44ceSEd Maste bool 7859f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 786ac7ddfbfSEd Maste { 787ac7ddfbfSEd Maste bool synchronous_execution = m_interpreter.GetSynchronous (); 788ac7ddfbfSEd Maste 789ac7ddfbfSEd Maste if (!m_interpreter.GetDebugger().GetSelectedTarget().get()) 790ac7ddfbfSEd Maste { 791ac7ddfbfSEd Maste result.AppendError ("invalid target, create a debug target using the 'target create' command"); 792ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 793ac7ddfbfSEd Maste return false; 794ac7ddfbfSEd Maste } 795ac7ddfbfSEd Maste 796ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 797ac7ddfbfSEd Maste if (process == NULL) 798ac7ddfbfSEd Maste { 799ac7ddfbfSEd Maste result.AppendError ("no process exists. Cannot continue"); 800ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 801ac7ddfbfSEd Maste return false; 802ac7ddfbfSEd Maste } 803ac7ddfbfSEd Maste 804ac7ddfbfSEd Maste StateType state = process->GetState(); 805ac7ddfbfSEd Maste if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended)) 806ac7ddfbfSEd Maste { 807ac7ddfbfSEd Maste const size_t argc = command.GetArgumentCount(); 808ac7ddfbfSEd Maste if (argc > 0) 809ac7ddfbfSEd Maste { 81035617911SEd Maste // These two lines appear at the beginning of both blocks in 81135617911SEd Maste // this if..else, but that is because we need to release the 81235617911SEd Maste // lock before calling process->Resume below. 81335617911SEd Maste Mutex::Locker locker (process->GetThreadList().GetMutex()); 81435617911SEd Maste const uint32_t num_threads = process->GetThreadList().GetSize(); 815ac7ddfbfSEd Maste std::vector<Thread *> resume_threads; 816ac7ddfbfSEd Maste for (uint32_t i=0; i<argc; ++i) 817ac7ddfbfSEd Maste { 818ac7ddfbfSEd Maste bool success; 819ac7ddfbfSEd Maste const int base = 0; 8201c3bbb01SEd Maste uint32_t thread_idx = StringConvert::ToUInt32 (command.GetArgumentAtIndex(i), LLDB_INVALID_INDEX32, base, &success); 821ac7ddfbfSEd Maste if (success) 822ac7ddfbfSEd Maste { 823ac7ddfbfSEd Maste Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get(); 824ac7ddfbfSEd Maste 825ac7ddfbfSEd Maste if (thread) 826ac7ddfbfSEd Maste { 827ac7ddfbfSEd Maste resume_threads.push_back(thread); 828ac7ddfbfSEd Maste } 829ac7ddfbfSEd Maste else 830ac7ddfbfSEd Maste { 831ac7ddfbfSEd Maste result.AppendErrorWithFormat("invalid thread index %u.\n", thread_idx); 832ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 833ac7ddfbfSEd Maste return false; 834ac7ddfbfSEd Maste } 835ac7ddfbfSEd Maste } 836ac7ddfbfSEd Maste else 837ac7ddfbfSEd Maste { 838ac7ddfbfSEd Maste result.AppendErrorWithFormat ("invalid thread index argument: \"%s\".\n", command.GetArgumentAtIndex(i)); 839ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 840ac7ddfbfSEd Maste return false; 841ac7ddfbfSEd Maste } 842ac7ddfbfSEd Maste } 843ac7ddfbfSEd Maste 844ac7ddfbfSEd Maste if (resume_threads.empty()) 845ac7ddfbfSEd Maste { 846ac7ddfbfSEd Maste result.AppendError ("no valid thread indexes were specified"); 847ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 848ac7ddfbfSEd Maste return false; 849ac7ddfbfSEd Maste } 850ac7ddfbfSEd Maste else 851ac7ddfbfSEd Maste { 852ac7ddfbfSEd Maste if (resume_threads.size() == 1) 853ac7ddfbfSEd Maste result.AppendMessageWithFormat ("Resuming thread: "); 854ac7ddfbfSEd Maste else 855ac7ddfbfSEd Maste result.AppendMessageWithFormat ("Resuming threads: "); 856ac7ddfbfSEd Maste 857ac7ddfbfSEd Maste for (uint32_t idx=0; idx<num_threads; ++idx) 858ac7ddfbfSEd Maste { 859ac7ddfbfSEd Maste Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 860ac7ddfbfSEd Maste std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread); 861ac7ddfbfSEd Maste 862ac7ddfbfSEd Maste if (this_thread_pos != resume_threads.end()) 863ac7ddfbfSEd Maste { 864ac7ddfbfSEd Maste resume_threads.erase(this_thread_pos); 865ac7ddfbfSEd Maste if (resume_threads.size() > 0) 866ac7ddfbfSEd Maste result.AppendMessageWithFormat ("%u, ", thread->GetIndexID()); 867ac7ddfbfSEd Maste else 868ac7ddfbfSEd Maste result.AppendMessageWithFormat ("%u ", thread->GetIndexID()); 869ac7ddfbfSEd Maste 8700127ef0fSEd Maste const bool override_suspend = true; 8710127ef0fSEd Maste thread->SetResumeState (eStateRunning, override_suspend); 872ac7ddfbfSEd Maste } 873ac7ddfbfSEd Maste else 874ac7ddfbfSEd Maste { 875ac7ddfbfSEd Maste thread->SetResumeState (eStateSuspended); 876ac7ddfbfSEd Maste } 877ac7ddfbfSEd Maste } 878ac7ddfbfSEd Maste result.AppendMessageWithFormat ("in process %" PRIu64 "\n", process->GetID()); 879ac7ddfbfSEd Maste } 880ac7ddfbfSEd Maste } 881ac7ddfbfSEd Maste else 882ac7ddfbfSEd Maste { 88335617911SEd Maste // These two lines appear at the beginning of both blocks in 88435617911SEd Maste // this if..else, but that is because we need to release the 88535617911SEd Maste // lock before calling process->Resume below. 88635617911SEd Maste Mutex::Locker locker (process->GetThreadList().GetMutex()); 88735617911SEd Maste const uint32_t num_threads = process->GetThreadList().GetSize(); 888ac7ddfbfSEd Maste Thread *current_thread = process->GetThreadList().GetSelectedThread().get(); 889ac7ddfbfSEd Maste if (current_thread == NULL) 890ac7ddfbfSEd Maste { 891ac7ddfbfSEd Maste result.AppendError ("the process doesn't have a current thread"); 892ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 893ac7ddfbfSEd Maste return false; 894ac7ddfbfSEd Maste } 895ac7ddfbfSEd Maste // Set the actions that the threads should each take when resuming 896ac7ddfbfSEd Maste for (uint32_t idx=0; idx<num_threads; ++idx) 897ac7ddfbfSEd Maste { 898ac7ddfbfSEd Maste Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 899ac7ddfbfSEd Maste if (thread == current_thread) 900ac7ddfbfSEd Maste { 901ac7ddfbfSEd Maste result.AppendMessageWithFormat ("Resuming thread 0x%4.4" PRIx64 " in process %" PRIu64 "\n", thread->GetID(), process->GetID()); 9020127ef0fSEd Maste const bool override_suspend = true; 9030127ef0fSEd Maste thread->SetResumeState (eStateRunning, override_suspend); 904ac7ddfbfSEd Maste } 905ac7ddfbfSEd Maste else 906ac7ddfbfSEd Maste { 907ac7ddfbfSEd Maste thread->SetResumeState (eStateSuspended); 908ac7ddfbfSEd Maste } 909ac7ddfbfSEd Maste } 910ac7ddfbfSEd Maste } 911ac7ddfbfSEd Maste 9127aa51b79SEd Maste 9137aa51b79SEd Maste StreamString stream; 9147aa51b79SEd Maste Error error; 9157aa51b79SEd Maste if (synchronous_execution) 9167aa51b79SEd Maste error = process->ResumeSynchronous (&stream); 9177aa51b79SEd Maste else 9187aa51b79SEd Maste error = process->Resume (); 9197aa51b79SEd Maste 92035617911SEd Maste // We should not be holding the thread list lock when we do this. 921ac7ddfbfSEd Maste if (error.Success()) 922ac7ddfbfSEd Maste { 923ac7ddfbfSEd Maste result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); 924ac7ddfbfSEd Maste if (synchronous_execution) 925ac7ddfbfSEd Maste { 9267aa51b79SEd Maste // If any state changed events had anything to say, add that to the result 9277aa51b79SEd Maste if (stream.GetData()) 9287aa51b79SEd Maste result.AppendMessage(stream.GetData()); 929ac7ddfbfSEd Maste 930ac7ddfbfSEd Maste result.SetDidChangeProcessState (true); 931ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishNoResult); 932ac7ddfbfSEd Maste } 933ac7ddfbfSEd Maste else 934ac7ddfbfSEd Maste { 935ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessContinuingNoResult); 936ac7ddfbfSEd Maste } 937ac7ddfbfSEd Maste } 938ac7ddfbfSEd Maste else 939ac7ddfbfSEd Maste { 940ac7ddfbfSEd Maste result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString()); 941ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 942ac7ddfbfSEd Maste } 943ac7ddfbfSEd Maste } 944ac7ddfbfSEd Maste else 945ac7ddfbfSEd Maste { 946ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 947ac7ddfbfSEd Maste StateAsCString(state)); 948ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 949ac7ddfbfSEd Maste } 950ac7ddfbfSEd Maste 951ac7ddfbfSEd Maste return result.Succeeded(); 952ac7ddfbfSEd Maste } 953ac7ddfbfSEd Maste 954ac7ddfbfSEd Maste }; 955ac7ddfbfSEd Maste 956ac7ddfbfSEd Maste //------------------------------------------------------------------------- 957ac7ddfbfSEd Maste // CommandObjectThreadUntil 958ac7ddfbfSEd Maste //------------------------------------------------------------------------- 959ac7ddfbfSEd Maste 960ac7ddfbfSEd Maste class CommandObjectThreadUntil : public CommandObjectParsed 961ac7ddfbfSEd Maste { 962ac7ddfbfSEd Maste public: 963ac7ddfbfSEd Maste 964ac7ddfbfSEd Maste class CommandOptions : public Options 965ac7ddfbfSEd Maste { 966ac7ddfbfSEd Maste public: 967ac7ddfbfSEd Maste uint32_t m_thread_idx; 968ac7ddfbfSEd Maste uint32_t m_frame_idx; 969ac7ddfbfSEd Maste 970ac7ddfbfSEd Maste CommandOptions (CommandInterpreter &interpreter) : 971ac7ddfbfSEd Maste Options (interpreter), 972ac7ddfbfSEd Maste m_thread_idx(LLDB_INVALID_THREAD_ID), 973ac7ddfbfSEd Maste m_frame_idx(LLDB_INVALID_FRAME_ID) 974ac7ddfbfSEd Maste { 975ac7ddfbfSEd Maste // Keep default values of all options in one place: OptionParsingStarting () 976ac7ddfbfSEd Maste OptionParsingStarting (); 977ac7ddfbfSEd Maste } 978ac7ddfbfSEd Maste 9799f2f44ceSEd Maste ~CommandOptions () override 980ac7ddfbfSEd Maste { 981ac7ddfbfSEd Maste } 982ac7ddfbfSEd Maste 9839f2f44ceSEd Maste Error 9849f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 985ac7ddfbfSEd Maste { 986ac7ddfbfSEd Maste Error error; 987ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 988ac7ddfbfSEd Maste 989ac7ddfbfSEd Maste switch (short_option) 990ac7ddfbfSEd Maste { 9911c3bbb01SEd Maste case 'a': 9921c3bbb01SEd Maste { 9931c3bbb01SEd Maste ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 9941c3bbb01SEd Maste lldb::addr_t tmp_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); 9951c3bbb01SEd Maste if (error.Success()) 9961c3bbb01SEd Maste m_until_addrs.push_back(tmp_addr); 9971c3bbb01SEd Maste } 9981c3bbb01SEd Maste break; 999ac7ddfbfSEd Maste case 't': 1000ac7ddfbfSEd Maste { 10011c3bbb01SEd Maste m_thread_idx = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_INDEX32); 1002ac7ddfbfSEd Maste if (m_thread_idx == LLDB_INVALID_INDEX32) 1003ac7ddfbfSEd Maste { 1004ac7ddfbfSEd Maste error.SetErrorStringWithFormat ("invalid thread index '%s'", option_arg); 1005ac7ddfbfSEd Maste } 1006ac7ddfbfSEd Maste } 1007ac7ddfbfSEd Maste break; 1008ac7ddfbfSEd Maste case 'f': 1009ac7ddfbfSEd Maste { 10101c3bbb01SEd Maste m_frame_idx = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_FRAME_ID); 1011ac7ddfbfSEd Maste if (m_frame_idx == LLDB_INVALID_FRAME_ID) 1012ac7ddfbfSEd Maste { 1013ac7ddfbfSEd Maste error.SetErrorStringWithFormat ("invalid frame index '%s'", option_arg); 1014ac7ddfbfSEd Maste } 1015ac7ddfbfSEd Maste } 1016ac7ddfbfSEd Maste break; 1017ac7ddfbfSEd Maste case 'm': 1018ac7ddfbfSEd Maste { 1019ac7ddfbfSEd Maste OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 1020ac7ddfbfSEd Maste lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error); 1021ac7ddfbfSEd Maste 1022ac7ddfbfSEd Maste if (error.Success()) 1023ac7ddfbfSEd Maste { 1024ac7ddfbfSEd Maste if (run_mode == eAllThreads) 1025ac7ddfbfSEd Maste m_stop_others = false; 1026ac7ddfbfSEd Maste else 1027ac7ddfbfSEd Maste m_stop_others = true; 1028ac7ddfbfSEd Maste } 1029ac7ddfbfSEd Maste } 1030ac7ddfbfSEd Maste break; 1031ac7ddfbfSEd Maste default: 1032ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1033ac7ddfbfSEd Maste break; 1034ac7ddfbfSEd Maste 1035ac7ddfbfSEd Maste } 1036ac7ddfbfSEd Maste return error; 1037ac7ddfbfSEd Maste } 1038ac7ddfbfSEd Maste 1039ac7ddfbfSEd Maste void 10409f2f44ceSEd Maste OptionParsingStarting () override 1041ac7ddfbfSEd Maste { 1042ac7ddfbfSEd Maste m_thread_idx = LLDB_INVALID_THREAD_ID; 1043ac7ddfbfSEd Maste m_frame_idx = 0; 1044ac7ddfbfSEd Maste m_stop_others = false; 10451c3bbb01SEd Maste m_until_addrs.clear(); 1046ac7ddfbfSEd Maste } 1047ac7ddfbfSEd Maste 1048ac7ddfbfSEd Maste const OptionDefinition* 10499f2f44ceSEd Maste GetDefinitions () override 1050ac7ddfbfSEd Maste { 1051ac7ddfbfSEd Maste return g_option_table; 1052ac7ddfbfSEd Maste } 1053ac7ddfbfSEd Maste 1054ac7ddfbfSEd Maste uint32_t m_step_thread_idx; 1055ac7ddfbfSEd Maste bool m_stop_others; 10561c3bbb01SEd Maste std::vector<lldb::addr_t> m_until_addrs; 1057ac7ddfbfSEd Maste 1058ac7ddfbfSEd Maste // Options table: Required for subclasses of Options. 1059ac7ddfbfSEd Maste 1060ac7ddfbfSEd Maste static OptionDefinition g_option_table[]; 1061ac7ddfbfSEd Maste 1062ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 1063ac7ddfbfSEd Maste }; 1064ac7ddfbfSEd Maste 1065ac7ddfbfSEd Maste CommandObjectThreadUntil (CommandInterpreter &interpreter) : 1066ac7ddfbfSEd Maste CommandObjectParsed (interpreter, 1067ac7ddfbfSEd Maste "thread until", 10681c3bbb01SEd Maste "Run the current or specified thread until it reaches a given line number or address or leaves the current function.", 1069ac7ddfbfSEd Maste NULL, 10701c3bbb01SEd Maste eCommandRequiresThread | 10711c3bbb01SEd Maste eCommandTryTargetAPILock | 10721c3bbb01SEd Maste eCommandProcessMustBeLaunched | 10731c3bbb01SEd Maste eCommandProcessMustBePaused ), 1074ac7ddfbfSEd Maste m_options (interpreter) 1075ac7ddfbfSEd Maste { 1076ac7ddfbfSEd Maste CommandArgumentEntry arg; 1077ac7ddfbfSEd Maste CommandArgumentData line_num_arg; 1078ac7ddfbfSEd Maste 1079ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 1080ac7ddfbfSEd Maste line_num_arg.arg_type = eArgTypeLineNum; 1081ac7ddfbfSEd Maste line_num_arg.arg_repetition = eArgRepeatPlain; 1082ac7ddfbfSEd Maste 1083ac7ddfbfSEd Maste // There is only one variant this argument could be; put it into the argument entry. 1084ac7ddfbfSEd Maste arg.push_back (line_num_arg); 1085ac7ddfbfSEd Maste 1086ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 1087ac7ddfbfSEd Maste m_arguments.push_back (arg); 1088ac7ddfbfSEd Maste } 1089ac7ddfbfSEd Maste 1090ac7ddfbfSEd Maste 10919f2f44ceSEd Maste ~CommandObjectThreadUntil () override 1092ac7ddfbfSEd Maste { 1093ac7ddfbfSEd Maste } 1094ac7ddfbfSEd Maste 1095ac7ddfbfSEd Maste Options * 10969f2f44ceSEd Maste GetOptions () override 1097ac7ddfbfSEd Maste { 1098ac7ddfbfSEd Maste return &m_options; 1099ac7ddfbfSEd Maste } 1100ac7ddfbfSEd Maste 1101ac7ddfbfSEd Maste protected: 11029f2f44ceSEd Maste bool 11039f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 1104ac7ddfbfSEd Maste { 1105ac7ddfbfSEd Maste bool synchronous_execution = m_interpreter.GetSynchronous (); 1106ac7ddfbfSEd Maste 1107ac7ddfbfSEd Maste Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1108ac7ddfbfSEd Maste if (target == NULL) 1109ac7ddfbfSEd Maste { 1110ac7ddfbfSEd Maste result.AppendError ("invalid target, create a debug target using the 'target create' command"); 1111ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1112ac7ddfbfSEd Maste return false; 1113ac7ddfbfSEd Maste } 1114ac7ddfbfSEd Maste 1115ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1116ac7ddfbfSEd Maste if (process == NULL) 1117ac7ddfbfSEd Maste { 1118ac7ddfbfSEd Maste result.AppendError ("need a valid process to step"); 1119ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1120ac7ddfbfSEd Maste 1121ac7ddfbfSEd Maste } 1122ac7ddfbfSEd Maste else 1123ac7ddfbfSEd Maste { 1124ac7ddfbfSEd Maste Thread *thread = NULL; 11251c3bbb01SEd Maste std::vector<uint32_t> line_numbers; 1126ac7ddfbfSEd Maste 11271c3bbb01SEd Maste if (command.GetArgumentCount() >= 1) 1128ac7ddfbfSEd Maste { 11291c3bbb01SEd Maste size_t num_args = command.GetArgumentCount(); 11301c3bbb01SEd Maste for (size_t i = 0; i < num_args; i++) 11311c3bbb01SEd Maste { 11321c3bbb01SEd Maste uint32_t line_number; 11331c3bbb01SEd Maste line_number = StringConvert::ToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX); 1134ac7ddfbfSEd Maste if (line_number == UINT32_MAX) 1135ac7ddfbfSEd Maste { 1136ac7ddfbfSEd Maste result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0)); 1137ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1138ac7ddfbfSEd Maste return false; 1139ac7ddfbfSEd Maste } 11401c3bbb01SEd Maste else 11411c3bbb01SEd Maste line_numbers.push_back(line_number); 11421c3bbb01SEd Maste } 11431c3bbb01SEd Maste } 11441c3bbb01SEd Maste else if (m_options.m_until_addrs.empty()) 11451c3bbb01SEd Maste { 11461c3bbb01SEd Maste result.AppendErrorWithFormat ("No line number or address provided:\n%s", GetSyntax()); 11471c3bbb01SEd Maste result.SetStatus (eReturnStatusFailed); 11481c3bbb01SEd Maste return false; 11491c3bbb01SEd Maste } 11501c3bbb01SEd Maste 1151ac7ddfbfSEd Maste 1152ac7ddfbfSEd Maste if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) 1153ac7ddfbfSEd Maste { 1154ac7ddfbfSEd Maste thread = process->GetThreadList().GetSelectedThread().get(); 1155ac7ddfbfSEd Maste } 1156ac7ddfbfSEd Maste else 1157ac7ddfbfSEd Maste { 1158ac7ddfbfSEd Maste thread = process->GetThreadList().FindThreadByIndexID(m_options.m_thread_idx).get(); 1159ac7ddfbfSEd Maste } 1160ac7ddfbfSEd Maste 1161ac7ddfbfSEd Maste if (thread == NULL) 1162ac7ddfbfSEd Maste { 1163ac7ddfbfSEd Maste const uint32_t num_threads = process->GetThreadList().GetSize(); 1164ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 1165ac7ddfbfSEd Maste m_options.m_thread_idx, 1166ac7ddfbfSEd Maste num_threads); 1167ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1168ac7ddfbfSEd Maste return false; 1169ac7ddfbfSEd Maste } 1170ac7ddfbfSEd Maste 1171ac7ddfbfSEd Maste const bool abort_other_plans = false; 1172ac7ddfbfSEd Maste 1173ac7ddfbfSEd Maste StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get(); 1174ac7ddfbfSEd Maste if (frame == NULL) 1175ac7ddfbfSEd Maste { 1176ac7ddfbfSEd Maste 1177ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", 1178ac7ddfbfSEd Maste m_options.m_frame_idx, 1179ac7ddfbfSEd Maste m_options.m_thread_idx); 1180ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1181ac7ddfbfSEd Maste return false; 1182ac7ddfbfSEd Maste } 1183ac7ddfbfSEd Maste 1184ac7ddfbfSEd Maste ThreadPlanSP new_plan_sp; 1185ac7ddfbfSEd Maste 1186ac7ddfbfSEd Maste if (frame->HasDebugInformation ()) 1187ac7ddfbfSEd Maste { 1188ac7ddfbfSEd Maste // Finally we got here... Translate the given line number to a bunch of addresses: 1189ac7ddfbfSEd Maste SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit)); 1190ac7ddfbfSEd Maste LineTable *line_table = NULL; 1191ac7ddfbfSEd Maste if (sc.comp_unit) 1192ac7ddfbfSEd Maste line_table = sc.comp_unit->GetLineTable(); 1193ac7ddfbfSEd Maste 1194ac7ddfbfSEd Maste if (line_table == NULL) 1195ac7ddfbfSEd Maste { 1196ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n", 1197ac7ddfbfSEd Maste m_options.m_frame_idx, m_options.m_thread_idx); 1198ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1199ac7ddfbfSEd Maste return false; 1200ac7ddfbfSEd Maste } 1201ac7ddfbfSEd Maste 1202ac7ddfbfSEd Maste LineEntry function_start; 1203ac7ddfbfSEd Maste uint32_t index_ptr = 0, end_ptr; 1204ac7ddfbfSEd Maste std::vector<addr_t> address_list; 1205ac7ddfbfSEd Maste 1206ac7ddfbfSEd Maste // Find the beginning & end index of the 1207ac7ddfbfSEd Maste AddressRange fun_addr_range = sc.function->GetAddressRange(); 1208ac7ddfbfSEd Maste Address fun_start_addr = fun_addr_range.GetBaseAddress(); 1209ac7ddfbfSEd Maste line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr); 1210ac7ddfbfSEd Maste 1211ac7ddfbfSEd Maste Address fun_end_addr(fun_start_addr.GetSection(), 1212ac7ddfbfSEd Maste fun_start_addr.GetOffset() + fun_addr_range.GetByteSize()); 1213ac7ddfbfSEd Maste 1214ac7ddfbfSEd Maste bool all_in_function = true; 1215ac7ddfbfSEd Maste 12161c3bbb01SEd Maste line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr); 12171c3bbb01SEd Maste 12181c3bbb01SEd Maste for (uint32_t line_number : line_numbers) 12191c3bbb01SEd Maste { 12201c3bbb01SEd Maste uint32_t start_idx_ptr = index_ptr; 12211c3bbb01SEd Maste while (start_idx_ptr <= end_ptr) 1222ac7ddfbfSEd Maste { 1223ac7ddfbfSEd Maste LineEntry line_entry; 1224ac7ddfbfSEd Maste const bool exact = false; 12251c3bbb01SEd Maste start_idx_ptr = sc.comp_unit->FindLineEntry(start_idx_ptr, line_number, sc.comp_unit, exact, &line_entry); 12261c3bbb01SEd Maste if (start_idx_ptr == UINT32_MAX) 1227ac7ddfbfSEd Maste break; 1228ac7ddfbfSEd Maste 1229ac7ddfbfSEd Maste addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target); 1230ac7ddfbfSEd Maste if (address != LLDB_INVALID_ADDRESS) 1231ac7ddfbfSEd Maste { 1232ac7ddfbfSEd Maste if (fun_addr_range.ContainsLoadAddress (address, target)) 1233ac7ddfbfSEd Maste address_list.push_back (address); 1234ac7ddfbfSEd Maste else 1235ac7ddfbfSEd Maste all_in_function = false; 1236ac7ddfbfSEd Maste } 12371c3bbb01SEd Maste start_idx_ptr++; 12381c3bbb01SEd Maste } 12391c3bbb01SEd Maste } 12401c3bbb01SEd Maste 12411c3bbb01SEd Maste for (lldb::addr_t address : m_options.m_until_addrs) 12421c3bbb01SEd Maste { 12431c3bbb01SEd Maste if (fun_addr_range.ContainsLoadAddress (address, target)) 12441c3bbb01SEd Maste address_list.push_back (address); 12451c3bbb01SEd Maste else 12461c3bbb01SEd Maste all_in_function = false; 1247ac7ddfbfSEd Maste } 1248ac7ddfbfSEd Maste 1249ac7ddfbfSEd Maste if (address_list.size() == 0) 1250ac7ddfbfSEd Maste { 1251ac7ddfbfSEd Maste if (all_in_function) 1252ac7ddfbfSEd Maste result.AppendErrorWithFormat ("No line entries matching until target.\n"); 1253ac7ddfbfSEd Maste else 1254ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Until target outside of the current function.\n"); 1255ac7ddfbfSEd Maste 1256ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1257ac7ddfbfSEd Maste return false; 1258ac7ddfbfSEd Maste } 1259ac7ddfbfSEd Maste 1260ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepUntil (abort_other_plans, 1261ac7ddfbfSEd Maste &address_list.front(), 1262ac7ddfbfSEd Maste address_list.size(), 1263ac7ddfbfSEd Maste m_options.m_stop_others, 1264ac7ddfbfSEd Maste m_options.m_frame_idx); 1265ac7ddfbfSEd Maste // User level plans should be master plans so they can be interrupted (e.g. by hitting a breakpoint) 1266ac7ddfbfSEd Maste // and other plans executed by the user (stepping around the breakpoint) and then a "continue" 1267ac7ddfbfSEd Maste // will resume the original plan. 1268ac7ddfbfSEd Maste new_plan_sp->SetIsMasterPlan (true); 1269ac7ddfbfSEd Maste new_plan_sp->SetOkayToDiscard(false); 1270ac7ddfbfSEd Maste } 1271ac7ddfbfSEd Maste else 1272ac7ddfbfSEd Maste { 1273ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", 1274ac7ddfbfSEd Maste m_options.m_frame_idx, 1275ac7ddfbfSEd Maste m_options.m_thread_idx); 1276ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1277ac7ddfbfSEd Maste return false; 1278ac7ddfbfSEd Maste 1279ac7ddfbfSEd Maste } 1280ac7ddfbfSEd Maste 12817aa51b79SEd Maste 12827aa51b79SEd Maste 1283ac7ddfbfSEd Maste process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx); 12847aa51b79SEd Maste 12857aa51b79SEd Maste StreamString stream; 12867aa51b79SEd Maste Error error; 12877aa51b79SEd Maste if (synchronous_execution) 12887aa51b79SEd Maste error = process->ResumeSynchronous (&stream); 12897aa51b79SEd Maste else 12907aa51b79SEd Maste error = process->Resume (); 12917aa51b79SEd Maste 1292ac7ddfbfSEd Maste if (error.Success()) 1293ac7ddfbfSEd Maste { 1294ac7ddfbfSEd Maste result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); 1295ac7ddfbfSEd Maste if (synchronous_execution) 1296ac7ddfbfSEd Maste { 12977aa51b79SEd Maste // If any state changed events had anything to say, add that to the result 12987aa51b79SEd Maste if (stream.GetData()) 12997aa51b79SEd Maste result.AppendMessage(stream.GetData()); 1300ac7ddfbfSEd Maste 1301ac7ddfbfSEd Maste result.SetDidChangeProcessState (true); 1302ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishNoResult); 1303ac7ddfbfSEd Maste } 1304ac7ddfbfSEd Maste else 1305ac7ddfbfSEd Maste { 1306ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessContinuingNoResult); 1307ac7ddfbfSEd Maste } 1308ac7ddfbfSEd Maste } 1309ac7ddfbfSEd Maste else 1310ac7ddfbfSEd Maste { 1311ac7ddfbfSEd Maste result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 1312ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1313ac7ddfbfSEd Maste } 1314ac7ddfbfSEd Maste 1315ac7ddfbfSEd Maste } 1316ac7ddfbfSEd Maste return result.Succeeded(); 1317ac7ddfbfSEd Maste } 1318ac7ddfbfSEd Maste 1319ac7ddfbfSEd Maste CommandOptions m_options; 1320ac7ddfbfSEd Maste 1321ac7ddfbfSEd Maste }; 1322ac7ddfbfSEd Maste 1323ac7ddfbfSEd Maste OptionDefinition 1324ac7ddfbfSEd Maste CommandObjectThreadUntil::CommandOptions::g_option_table[] = 1325ac7ddfbfSEd Maste { 13260127ef0fSEd Maste { LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"}, 13270127ef0fSEd Maste { LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"}, 13280127ef0fSEd Maste { LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, NULL, g_duo_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping this one"}, 13291c3bbb01SEd Maste { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression, "Run until we reach the specified address, or leave the function - can be specified multiple times."}, 13300127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1331ac7ddfbfSEd Maste }; 1332ac7ddfbfSEd Maste 1333ac7ddfbfSEd Maste 1334ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1335ac7ddfbfSEd Maste // CommandObjectThreadSelect 1336ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1337ac7ddfbfSEd Maste 1338ac7ddfbfSEd Maste class CommandObjectThreadSelect : public CommandObjectParsed 1339ac7ddfbfSEd Maste { 1340ac7ddfbfSEd Maste public: 1341ac7ddfbfSEd Maste 1342ac7ddfbfSEd Maste CommandObjectThreadSelect (CommandInterpreter &interpreter) : 1343ac7ddfbfSEd Maste CommandObjectParsed (interpreter, 1344ac7ddfbfSEd Maste "thread select", 1345ac7ddfbfSEd Maste "Select a thread as the currently active thread.", 1346ac7ddfbfSEd Maste NULL, 13471c3bbb01SEd Maste eCommandRequiresProcess | 13481c3bbb01SEd Maste eCommandTryTargetAPILock | 13491c3bbb01SEd Maste eCommandProcessMustBeLaunched | 13501c3bbb01SEd Maste eCommandProcessMustBePaused ) 1351ac7ddfbfSEd Maste { 1352ac7ddfbfSEd Maste CommandArgumentEntry arg; 1353ac7ddfbfSEd Maste CommandArgumentData thread_idx_arg; 1354ac7ddfbfSEd Maste 1355ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 1356ac7ddfbfSEd Maste thread_idx_arg.arg_type = eArgTypeThreadIndex; 1357ac7ddfbfSEd Maste thread_idx_arg.arg_repetition = eArgRepeatPlain; 1358ac7ddfbfSEd Maste 1359ac7ddfbfSEd Maste // There is only one variant this argument could be; put it into the argument entry. 1360ac7ddfbfSEd Maste arg.push_back (thread_idx_arg); 1361ac7ddfbfSEd Maste 1362ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 1363ac7ddfbfSEd Maste m_arguments.push_back (arg); 1364ac7ddfbfSEd Maste } 1365ac7ddfbfSEd Maste 1366ac7ddfbfSEd Maste 13679f2f44ceSEd Maste ~CommandObjectThreadSelect () override 1368ac7ddfbfSEd Maste { 1369ac7ddfbfSEd Maste } 1370ac7ddfbfSEd Maste 1371ac7ddfbfSEd Maste protected: 13729f2f44ceSEd Maste bool 13739f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 1374ac7ddfbfSEd Maste { 1375ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1376ac7ddfbfSEd Maste if (process == NULL) 1377ac7ddfbfSEd Maste { 1378ac7ddfbfSEd Maste result.AppendError ("no process"); 1379ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1380ac7ddfbfSEd Maste return false; 1381ac7ddfbfSEd Maste } 1382ac7ddfbfSEd Maste else if (command.GetArgumentCount() != 1) 1383ac7ddfbfSEd Maste { 1384ac7ddfbfSEd Maste result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1385ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1386ac7ddfbfSEd Maste return false; 1387ac7ddfbfSEd Maste } 1388ac7ddfbfSEd Maste 13891c3bbb01SEd Maste uint32_t index_id = StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0); 1390ac7ddfbfSEd Maste 1391ac7ddfbfSEd Maste Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get(); 1392ac7ddfbfSEd Maste if (new_thread == NULL) 1393ac7ddfbfSEd Maste { 1394ac7ddfbfSEd Maste result.AppendErrorWithFormat ("invalid thread #%s.\n", command.GetArgumentAtIndex(0)); 1395ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1396ac7ddfbfSEd Maste return false; 1397ac7ddfbfSEd Maste } 1398ac7ddfbfSEd Maste 1399ac7ddfbfSEd Maste process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true); 1400ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishNoResult); 1401ac7ddfbfSEd Maste 1402ac7ddfbfSEd Maste return result.Succeeded(); 1403ac7ddfbfSEd Maste } 1404ac7ddfbfSEd Maste 1405ac7ddfbfSEd Maste }; 1406ac7ddfbfSEd Maste 1407ac7ddfbfSEd Maste 1408ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1409ac7ddfbfSEd Maste // CommandObjectThreadList 1410ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1411ac7ddfbfSEd Maste 1412ac7ddfbfSEd Maste class CommandObjectThreadList : public CommandObjectParsed 1413ac7ddfbfSEd Maste { 1414ac7ddfbfSEd Maste public: 1415ac7ddfbfSEd Maste 1416ac7ddfbfSEd Maste 1417ac7ddfbfSEd Maste CommandObjectThreadList (CommandInterpreter &interpreter): 1418ac7ddfbfSEd Maste CommandObjectParsed (interpreter, 1419ac7ddfbfSEd Maste "thread list", 1420ac7ddfbfSEd Maste "Show a summary of all current threads in a process.", 1421ac7ddfbfSEd Maste "thread list", 14221c3bbb01SEd Maste eCommandRequiresProcess | 14231c3bbb01SEd Maste eCommandTryTargetAPILock | 14241c3bbb01SEd Maste eCommandProcessMustBeLaunched | 14251c3bbb01SEd Maste eCommandProcessMustBePaused ) 1426ac7ddfbfSEd Maste { 1427ac7ddfbfSEd Maste } 1428ac7ddfbfSEd Maste 14299f2f44ceSEd Maste ~CommandObjectThreadList() override 1430ac7ddfbfSEd Maste { 1431ac7ddfbfSEd Maste } 1432ac7ddfbfSEd Maste 1433ac7ddfbfSEd Maste protected: 1434ac7ddfbfSEd Maste bool 14359f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 1436ac7ddfbfSEd Maste { 1437ac7ddfbfSEd Maste Stream &strm = result.GetOutputStream(); 1438ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishNoResult); 1439ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 1440ac7ddfbfSEd Maste const bool only_threads_with_stop_reason = false; 1441ac7ddfbfSEd Maste const uint32_t start_frame = 0; 1442ac7ddfbfSEd Maste const uint32_t num_frames = 0; 1443ac7ddfbfSEd Maste const uint32_t num_frames_with_source = 0; 1444ac7ddfbfSEd Maste process->GetStatus(strm); 1445ac7ddfbfSEd Maste process->GetThreadStatus (strm, 1446ac7ddfbfSEd Maste only_threads_with_stop_reason, 1447ac7ddfbfSEd Maste start_frame, 1448ac7ddfbfSEd Maste num_frames, 1449ac7ddfbfSEd Maste num_frames_with_source); 1450ac7ddfbfSEd Maste return result.Succeeded(); 1451ac7ddfbfSEd Maste } 1452ac7ddfbfSEd Maste }; 1453ac7ddfbfSEd Maste 1454ac7ddfbfSEd Maste //------------------------------------------------------------------------- 14550127ef0fSEd Maste // CommandObjectThreadInfo 14560127ef0fSEd Maste //------------------------------------------------------------------------- 14570127ef0fSEd Maste 14587aa51b79SEd Maste class CommandObjectThreadInfo : public CommandObjectIterateOverThreads 14590127ef0fSEd Maste { 14600127ef0fSEd Maste public: 14610127ef0fSEd Maste 14620127ef0fSEd Maste CommandObjectThreadInfo (CommandInterpreter &interpreter) : 14637aa51b79SEd Maste CommandObjectIterateOverThreads (interpreter, 14640127ef0fSEd Maste "thread info", 14650127ef0fSEd Maste "Show an extended summary of information about thread(s) in a process.", 14660127ef0fSEd Maste "thread info", 14671c3bbb01SEd Maste eCommandRequiresProcess | 14681c3bbb01SEd Maste eCommandTryTargetAPILock | 14691c3bbb01SEd Maste eCommandProcessMustBeLaunched | 14701c3bbb01SEd Maste eCommandProcessMustBePaused), 14710127ef0fSEd Maste m_options (interpreter) 14720127ef0fSEd Maste { 14737aa51b79SEd Maste m_add_return = false; 14740127ef0fSEd Maste } 14750127ef0fSEd Maste 14760127ef0fSEd Maste class CommandOptions : public Options 14770127ef0fSEd Maste { 14780127ef0fSEd Maste public: 14790127ef0fSEd Maste 14800127ef0fSEd Maste CommandOptions (CommandInterpreter &interpreter) : 14810127ef0fSEd Maste Options (interpreter) 14820127ef0fSEd Maste { 14830127ef0fSEd Maste OptionParsingStarting (); 14840127ef0fSEd Maste } 14850127ef0fSEd Maste 14860127ef0fSEd Maste void 14879f2f44ceSEd Maste OptionParsingStarting () override 14880127ef0fSEd Maste { 14897aa51b79SEd Maste m_json_thread = false; 14907aa51b79SEd Maste m_json_stopinfo = false; 14910127ef0fSEd Maste } 14920127ef0fSEd Maste 14939f2f44ceSEd Maste ~CommandOptions () override 14940127ef0fSEd Maste { 14950127ef0fSEd Maste } 14960127ef0fSEd Maste 14979f2f44ceSEd Maste Error 14989f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 14990127ef0fSEd Maste { 15000127ef0fSEd Maste const int short_option = m_getopt_table[option_idx].val; 15010127ef0fSEd Maste Error error; 15020127ef0fSEd Maste 15030127ef0fSEd Maste switch (short_option) 15040127ef0fSEd Maste { 15050127ef0fSEd Maste case 'j': 15067aa51b79SEd Maste m_json_thread = true; 15077aa51b79SEd Maste break; 15087aa51b79SEd Maste 15097aa51b79SEd Maste case 's': 15107aa51b79SEd Maste m_json_stopinfo = true; 15110127ef0fSEd Maste break; 15120127ef0fSEd Maste 15130127ef0fSEd Maste default: 15140127ef0fSEd Maste return Error("invalid short option character '%c'", short_option); 15150127ef0fSEd Maste 15160127ef0fSEd Maste } 15170127ef0fSEd Maste return error; 15180127ef0fSEd Maste } 15190127ef0fSEd Maste 15200127ef0fSEd Maste const OptionDefinition* 15219f2f44ceSEd Maste GetDefinitions () override 15220127ef0fSEd Maste { 15230127ef0fSEd Maste return g_option_table; 15240127ef0fSEd Maste } 15250127ef0fSEd Maste 15267aa51b79SEd Maste bool m_json_thread; 15277aa51b79SEd Maste bool m_json_stopinfo; 15280127ef0fSEd Maste 15290127ef0fSEd Maste static OptionDefinition g_option_table[]; 15300127ef0fSEd Maste }; 15310127ef0fSEd Maste 15320127ef0fSEd Maste Options * 15339f2f44ceSEd Maste GetOptions () override 15340127ef0fSEd Maste { 15350127ef0fSEd Maste return &m_options; 15360127ef0fSEd Maste } 15370127ef0fSEd Maste 15389f2f44ceSEd Maste ~CommandObjectThreadInfo () override 15390127ef0fSEd Maste { 15400127ef0fSEd Maste } 15410127ef0fSEd Maste 15429f2f44ceSEd Maste bool 15439f2f44ceSEd Maste HandleOneThread (Thread &thread, CommandReturnObject &result) override 15440127ef0fSEd Maste { 15450127ef0fSEd Maste Stream &strm = result.GetOutputStream(); 15467aa51b79SEd Maste if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo)) 15470127ef0fSEd Maste { 15487aa51b79SEd Maste result.AppendErrorWithFormat ("error displaying info for thread: \"%d\"\n", thread.GetIndexID()); 15490127ef0fSEd Maste result.SetStatus (eReturnStatusFailed); 15500127ef0fSEd Maste return false; 15510127ef0fSEd Maste } 15527aa51b79SEd Maste return true; 15530127ef0fSEd Maste } 15540127ef0fSEd Maste 15550127ef0fSEd Maste CommandOptions m_options; 15560127ef0fSEd Maste 15570127ef0fSEd Maste }; 15580127ef0fSEd Maste 15590127ef0fSEd Maste OptionDefinition 15600127ef0fSEd Maste CommandObjectThreadInfo::CommandOptions::g_option_table[] = 15610127ef0fSEd Maste { 15620127ef0fSEd Maste { LLDB_OPT_SET_ALL, false, "json",'j', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the thread info in JSON format."}, 15637aa51b79SEd Maste { LLDB_OPT_SET_ALL, false, "stop-info",'s', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the extended stop info in JSON format."}, 15640127ef0fSEd Maste 15650127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 15660127ef0fSEd Maste }; 15670127ef0fSEd Maste 15680127ef0fSEd Maste 15690127ef0fSEd Maste //------------------------------------------------------------------------- 1570ac7ddfbfSEd Maste // CommandObjectThreadReturn 1571ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1572ac7ddfbfSEd Maste 1573ac7ddfbfSEd Maste class CommandObjectThreadReturn : public CommandObjectRaw 1574ac7ddfbfSEd Maste { 1575ac7ddfbfSEd Maste public: 1576ac7ddfbfSEd Maste class CommandOptions : public Options 1577ac7ddfbfSEd Maste { 1578ac7ddfbfSEd Maste public: 1579ac7ddfbfSEd Maste 1580ac7ddfbfSEd Maste CommandOptions (CommandInterpreter &interpreter) : 1581ac7ddfbfSEd Maste Options (interpreter), 1582ac7ddfbfSEd Maste m_from_expression (false) 1583ac7ddfbfSEd Maste { 1584ac7ddfbfSEd Maste // Keep default values of all options in one place: OptionParsingStarting () 1585ac7ddfbfSEd Maste OptionParsingStarting (); 1586ac7ddfbfSEd Maste } 1587ac7ddfbfSEd Maste 15889f2f44ceSEd Maste ~CommandOptions () override 1589ac7ddfbfSEd Maste { 1590ac7ddfbfSEd Maste } 1591ac7ddfbfSEd Maste 15929f2f44ceSEd Maste Error 15939f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 1594ac7ddfbfSEd Maste { 1595ac7ddfbfSEd Maste Error error; 1596ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 1597ac7ddfbfSEd Maste 1598ac7ddfbfSEd Maste switch (short_option) 1599ac7ddfbfSEd Maste { 1600ac7ddfbfSEd Maste case 'x': 1601ac7ddfbfSEd Maste { 1602ac7ddfbfSEd Maste bool success; 1603ac7ddfbfSEd Maste bool tmp_value = Args::StringToBoolean (option_arg, false, &success); 1604ac7ddfbfSEd Maste if (success) 1605ac7ddfbfSEd Maste m_from_expression = tmp_value; 1606ac7ddfbfSEd Maste else 1607ac7ddfbfSEd Maste { 1608ac7ddfbfSEd Maste error.SetErrorStringWithFormat ("invalid boolean value '%s' for 'x' option", option_arg); 1609ac7ddfbfSEd Maste } 1610ac7ddfbfSEd Maste } 1611ac7ddfbfSEd Maste break; 1612ac7ddfbfSEd Maste default: 1613ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1614ac7ddfbfSEd Maste break; 1615ac7ddfbfSEd Maste 1616ac7ddfbfSEd Maste } 1617ac7ddfbfSEd Maste return error; 1618ac7ddfbfSEd Maste } 1619ac7ddfbfSEd Maste 1620ac7ddfbfSEd Maste void 16219f2f44ceSEd Maste OptionParsingStarting () override 1622ac7ddfbfSEd Maste { 1623ac7ddfbfSEd Maste m_from_expression = false; 1624ac7ddfbfSEd Maste } 1625ac7ddfbfSEd Maste 1626ac7ddfbfSEd Maste const OptionDefinition* 16279f2f44ceSEd Maste GetDefinitions () override 1628ac7ddfbfSEd Maste { 1629ac7ddfbfSEd Maste return g_option_table; 1630ac7ddfbfSEd Maste } 1631ac7ddfbfSEd Maste 1632ac7ddfbfSEd Maste bool m_from_expression; 1633ac7ddfbfSEd Maste 1634ac7ddfbfSEd Maste // Options table: Required for subclasses of Options. 1635ac7ddfbfSEd Maste 1636ac7ddfbfSEd Maste static OptionDefinition g_option_table[]; 1637ac7ddfbfSEd Maste 1638ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 1639ac7ddfbfSEd Maste }; 1640ac7ddfbfSEd Maste 1641ac7ddfbfSEd Maste Options * 16429f2f44ceSEd Maste GetOptions () override 1643ac7ddfbfSEd Maste { 1644ac7ddfbfSEd Maste return &m_options; 1645ac7ddfbfSEd Maste } 1646ac7ddfbfSEd Maste 1647ac7ddfbfSEd Maste CommandObjectThreadReturn (CommandInterpreter &interpreter) : 1648ac7ddfbfSEd Maste CommandObjectRaw (interpreter, 1649ac7ddfbfSEd Maste "thread return", 1650ac7ddfbfSEd Maste "Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value," 1651ac7ddfbfSEd Maste " or with the -x option from the innermost function evaluation.", 1652ac7ddfbfSEd Maste "thread return", 16531c3bbb01SEd Maste eCommandRequiresFrame | 16541c3bbb01SEd Maste eCommandTryTargetAPILock | 16551c3bbb01SEd Maste eCommandProcessMustBeLaunched | 16561c3bbb01SEd Maste eCommandProcessMustBePaused ), 1657ac7ddfbfSEd Maste m_options (interpreter) 1658ac7ddfbfSEd Maste { 1659ac7ddfbfSEd Maste CommandArgumentEntry arg; 1660ac7ddfbfSEd Maste CommandArgumentData expression_arg; 1661ac7ddfbfSEd Maste 1662ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 1663ac7ddfbfSEd Maste expression_arg.arg_type = eArgTypeExpression; 1664ac7ddfbfSEd Maste expression_arg.arg_repetition = eArgRepeatOptional; 1665ac7ddfbfSEd Maste 1666ac7ddfbfSEd Maste // There is only one variant this argument could be; put it into the argument entry. 1667ac7ddfbfSEd Maste arg.push_back (expression_arg); 1668ac7ddfbfSEd Maste 1669ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 1670ac7ddfbfSEd Maste m_arguments.push_back (arg); 1671ac7ddfbfSEd Maste 1672ac7ddfbfSEd Maste 1673ac7ddfbfSEd Maste } 1674ac7ddfbfSEd Maste 16759f2f44ceSEd Maste ~CommandObjectThreadReturn() override 1676ac7ddfbfSEd Maste { 1677ac7ddfbfSEd Maste } 1678ac7ddfbfSEd Maste 1679ac7ddfbfSEd Maste protected: 1680ac7ddfbfSEd Maste 16819f2f44ceSEd Maste bool 16829f2f44ceSEd Maste DoExecute (const char *command, CommandReturnObject &result) override 1683ac7ddfbfSEd Maste { 1684ac7ddfbfSEd Maste // I am going to handle this by hand, because I don't want you to have to say: 1685ac7ddfbfSEd Maste // "thread return -- -5". 1686ac7ddfbfSEd Maste if (command[0] == '-' && command[1] == 'x') 1687ac7ddfbfSEd Maste { 1688ac7ddfbfSEd Maste if (command && command[2] != '\0') 1689ac7ddfbfSEd Maste result.AppendWarning("Return values ignored when returning from user called expressions"); 1690ac7ddfbfSEd Maste 1691ac7ddfbfSEd Maste Thread *thread = m_exe_ctx.GetThreadPtr(); 1692ac7ddfbfSEd Maste Error error; 1693ac7ddfbfSEd Maste error = thread->UnwindInnermostExpression(); 1694ac7ddfbfSEd Maste if (!error.Success()) 1695ac7ddfbfSEd Maste { 1696ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Unwinding expression failed - %s.", error.AsCString()); 1697ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1698ac7ddfbfSEd Maste } 1699ac7ddfbfSEd Maste else 1700ac7ddfbfSEd Maste { 1701ac7ddfbfSEd Maste bool success = thread->SetSelectedFrameByIndexNoisily (0, result.GetOutputStream()); 1702ac7ddfbfSEd Maste if (success) 1703ac7ddfbfSEd Maste { 1704ac7ddfbfSEd Maste m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ()); 1705ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 1706ac7ddfbfSEd Maste } 1707ac7ddfbfSEd Maste else 1708ac7ddfbfSEd Maste { 1709ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Could not select 0th frame after unwinding expression."); 1710ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1711ac7ddfbfSEd Maste } 1712ac7ddfbfSEd Maste } 1713ac7ddfbfSEd Maste return result.Succeeded(); 1714ac7ddfbfSEd Maste } 1715ac7ddfbfSEd Maste 1716ac7ddfbfSEd Maste ValueObjectSP return_valobj_sp; 1717ac7ddfbfSEd Maste 1718ac7ddfbfSEd Maste StackFrameSP frame_sp = m_exe_ctx.GetFrameSP(); 1719ac7ddfbfSEd Maste uint32_t frame_idx = frame_sp->GetFrameIndex(); 1720ac7ddfbfSEd Maste 1721ac7ddfbfSEd Maste if (frame_sp->IsInlined()) 1722ac7ddfbfSEd Maste { 1723ac7ddfbfSEd Maste result.AppendError("Don't know how to return from inlined frames."); 1724ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1725ac7ddfbfSEd Maste return false; 1726ac7ddfbfSEd Maste } 1727ac7ddfbfSEd Maste 1728ac7ddfbfSEd Maste if (command && command[0] != '\0') 1729ac7ddfbfSEd Maste { 1730ac7ddfbfSEd Maste Target *target = m_exe_ctx.GetTargetPtr(); 1731ac7ddfbfSEd Maste EvaluateExpressionOptions options; 1732ac7ddfbfSEd Maste 1733ac7ddfbfSEd Maste options.SetUnwindOnError(true); 1734ac7ddfbfSEd Maste options.SetUseDynamic(eNoDynamicValues); 1735ac7ddfbfSEd Maste 17360127ef0fSEd Maste ExpressionResults exe_results = eExpressionSetupError; 1737ac7ddfbfSEd Maste exe_results = target->EvaluateExpression (command, 1738ac7ddfbfSEd Maste frame_sp.get(), 1739ac7ddfbfSEd Maste return_valobj_sp, 1740ac7ddfbfSEd Maste options); 17410127ef0fSEd Maste if (exe_results != eExpressionCompleted) 1742ac7ddfbfSEd Maste { 1743ac7ddfbfSEd Maste if (return_valobj_sp) 1744ac7ddfbfSEd Maste result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString()); 1745ac7ddfbfSEd Maste else 1746ac7ddfbfSEd Maste result.AppendErrorWithFormat("Unknown error evaluating result expression."); 1747ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1748ac7ddfbfSEd Maste return false; 1749ac7ddfbfSEd Maste 1750ac7ddfbfSEd Maste } 1751ac7ddfbfSEd Maste } 1752ac7ddfbfSEd Maste 1753ac7ddfbfSEd Maste Error error; 1754ac7ddfbfSEd Maste ThreadSP thread_sp = m_exe_ctx.GetThreadSP(); 1755ac7ddfbfSEd Maste const bool broadcast = true; 1756ac7ddfbfSEd Maste error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast); 1757ac7ddfbfSEd Maste if (!error.Success()) 1758ac7ddfbfSEd Maste { 1759ac7ddfbfSEd Maste result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString()); 1760ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1761ac7ddfbfSEd Maste return false; 1762ac7ddfbfSEd Maste } 1763ac7ddfbfSEd Maste 1764ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 1765ac7ddfbfSEd Maste return true; 1766ac7ddfbfSEd Maste } 1767ac7ddfbfSEd Maste 1768ac7ddfbfSEd Maste CommandOptions m_options; 1769ac7ddfbfSEd Maste 1770ac7ddfbfSEd Maste }; 1771ac7ddfbfSEd Maste OptionDefinition 1772ac7ddfbfSEd Maste CommandObjectThreadReturn::CommandOptions::g_option_table[] = 1773ac7ddfbfSEd Maste { 17740127ef0fSEd Maste { LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Return from the innermost expression evaluation."}, 17750127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 177635617911SEd Maste }; 177735617911SEd Maste 177835617911SEd Maste //------------------------------------------------------------------------- 177935617911SEd Maste // CommandObjectThreadJump 178035617911SEd Maste //------------------------------------------------------------------------- 178135617911SEd Maste 178235617911SEd Maste class CommandObjectThreadJump : public CommandObjectParsed 178335617911SEd Maste { 178435617911SEd Maste public: 178535617911SEd Maste class CommandOptions : public Options 178635617911SEd Maste { 178735617911SEd Maste public: 178835617911SEd Maste 178935617911SEd Maste CommandOptions (CommandInterpreter &interpreter) : 179035617911SEd Maste Options (interpreter) 179135617911SEd Maste { 179235617911SEd Maste OptionParsingStarting (); 179335617911SEd Maste } 179435617911SEd Maste 179535617911SEd Maste void 17969f2f44ceSEd Maste OptionParsingStarting () override 179735617911SEd Maste { 179835617911SEd Maste m_filenames.Clear(); 179935617911SEd Maste m_line_num = 0; 180035617911SEd Maste m_line_offset = 0; 180135617911SEd Maste m_load_addr = LLDB_INVALID_ADDRESS; 180235617911SEd Maste m_force = false; 180335617911SEd Maste } 180435617911SEd Maste 18059f2f44ceSEd Maste ~CommandOptions () override 180635617911SEd Maste { 180735617911SEd Maste } 180835617911SEd Maste 18099f2f44ceSEd Maste Error 18109f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 181135617911SEd Maste { 181235617911SEd Maste bool success; 181335617911SEd Maste const int short_option = m_getopt_table[option_idx].val; 181435617911SEd Maste Error error; 181535617911SEd Maste 181635617911SEd Maste switch (short_option) 181735617911SEd Maste { 181835617911SEd Maste case 'f': 181935617911SEd Maste m_filenames.AppendIfUnique (FileSpec(option_arg, false)); 182035617911SEd Maste if (m_filenames.GetSize() > 1) 182135617911SEd Maste return Error("only one source file expected."); 182235617911SEd Maste break; 182335617911SEd Maste case 'l': 18241c3bbb01SEd Maste m_line_num = StringConvert::ToUInt32 (option_arg, 0, 0, &success); 182535617911SEd Maste if (!success || m_line_num == 0) 182635617911SEd Maste return Error("invalid line number: '%s'.", option_arg); 182735617911SEd Maste break; 182835617911SEd Maste case 'b': 18291c3bbb01SEd Maste m_line_offset = StringConvert::ToSInt32 (option_arg, 0, 0, &success); 183035617911SEd Maste if (!success) 183135617911SEd Maste return Error("invalid line offset: '%s'.", option_arg); 183235617911SEd Maste break; 183335617911SEd Maste case 'a': 183435617911SEd Maste { 183535617911SEd Maste ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 183635617911SEd Maste m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); 183735617911SEd Maste } 183835617911SEd Maste break; 183935617911SEd Maste case 'r': 184035617911SEd Maste m_force = true; 184135617911SEd Maste break; 184235617911SEd Maste 184335617911SEd Maste default: 184435617911SEd Maste return Error("invalid short option character '%c'", short_option); 184535617911SEd Maste 184635617911SEd Maste } 184735617911SEd Maste return error; 184835617911SEd Maste } 184935617911SEd Maste 185035617911SEd Maste const OptionDefinition* 18519f2f44ceSEd Maste GetDefinitions () override 185235617911SEd Maste { 185335617911SEd Maste return g_option_table; 185435617911SEd Maste } 185535617911SEd Maste 185635617911SEd Maste FileSpecList m_filenames; 185735617911SEd Maste uint32_t m_line_num; 185835617911SEd Maste int32_t m_line_offset; 185935617911SEd Maste lldb::addr_t m_load_addr; 186035617911SEd Maste bool m_force; 186135617911SEd Maste 186235617911SEd Maste static OptionDefinition g_option_table[]; 186335617911SEd Maste }; 186435617911SEd Maste 186535617911SEd Maste Options * 18669f2f44ceSEd Maste GetOptions () override 186735617911SEd Maste { 186835617911SEd Maste return &m_options; 186935617911SEd Maste } 187035617911SEd Maste 187135617911SEd Maste CommandObjectThreadJump (CommandInterpreter &interpreter) : 187235617911SEd Maste CommandObjectParsed (interpreter, 187335617911SEd Maste "thread jump", 187435617911SEd Maste "Sets the program counter to a new address.", 187535617911SEd Maste "thread jump", 18761c3bbb01SEd Maste eCommandRequiresFrame | 18771c3bbb01SEd Maste eCommandTryTargetAPILock | 18781c3bbb01SEd Maste eCommandProcessMustBeLaunched | 18791c3bbb01SEd Maste eCommandProcessMustBePaused ), 188035617911SEd Maste m_options (interpreter) 188135617911SEd Maste { 188235617911SEd Maste } 188335617911SEd Maste 18849f2f44ceSEd Maste ~CommandObjectThreadJump() override 188535617911SEd Maste { 188635617911SEd Maste } 188735617911SEd Maste 188835617911SEd Maste protected: 188935617911SEd Maste 18909f2f44ceSEd Maste bool DoExecute (Args& args, CommandReturnObject &result) override 189135617911SEd Maste { 189235617911SEd Maste RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); 189335617911SEd Maste StackFrame *frame = m_exe_ctx.GetFramePtr(); 189435617911SEd Maste Thread *thread = m_exe_ctx.GetThreadPtr(); 189535617911SEd Maste Target *target = m_exe_ctx.GetTargetPtr(); 189635617911SEd Maste const SymbolContext &sym_ctx = frame->GetSymbolContext (eSymbolContextLineEntry); 189735617911SEd Maste 189835617911SEd Maste if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 189935617911SEd Maste { 190035617911SEd Maste // Use this address directly. 190135617911SEd Maste Address dest = Address(m_options.m_load_addr); 190235617911SEd Maste 190335617911SEd Maste lldb::addr_t callAddr = dest.GetCallableLoadAddress (target); 190435617911SEd Maste if (callAddr == LLDB_INVALID_ADDRESS) 190535617911SEd Maste { 190635617911SEd Maste result.AppendErrorWithFormat ("Invalid destination address."); 190735617911SEd Maste result.SetStatus (eReturnStatusFailed); 190835617911SEd Maste return false; 190935617911SEd Maste } 191035617911SEd Maste 191135617911SEd Maste if (!reg_ctx->SetPC (callAddr)) 191235617911SEd Maste { 191335617911SEd Maste result.AppendErrorWithFormat ("Error changing PC value for thread %d.", thread->GetIndexID()); 191435617911SEd Maste result.SetStatus (eReturnStatusFailed); 191535617911SEd Maste return false; 191635617911SEd Maste } 191735617911SEd Maste } 191835617911SEd Maste else 191935617911SEd Maste { 192035617911SEd Maste // Pick either the absolute line, or work out a relative one. 192135617911SEd Maste int32_t line = (int32_t)m_options.m_line_num; 192235617911SEd Maste if (line == 0) 192335617911SEd Maste line = sym_ctx.line_entry.line + m_options.m_line_offset; 192435617911SEd Maste 192535617911SEd Maste // Try the current file, but override if asked. 192635617911SEd Maste FileSpec file = sym_ctx.line_entry.file; 192735617911SEd Maste if (m_options.m_filenames.GetSize() == 1) 192835617911SEd Maste file = m_options.m_filenames.GetFileSpecAtIndex(0); 192935617911SEd Maste 193035617911SEd Maste if (!file) 193135617911SEd Maste { 193235617911SEd Maste result.AppendErrorWithFormat ("No source file available for the current location."); 193335617911SEd Maste result.SetStatus (eReturnStatusFailed); 193435617911SEd Maste return false; 193535617911SEd Maste } 193635617911SEd Maste 193735617911SEd Maste std::string warnings; 193835617911SEd Maste Error err = thread->JumpToLine (file, line, m_options.m_force, &warnings); 193935617911SEd Maste 194035617911SEd Maste if (err.Fail()) 194135617911SEd Maste { 194235617911SEd Maste result.SetError (err); 194335617911SEd Maste return false; 194435617911SEd Maste } 194535617911SEd Maste 194635617911SEd Maste if (!warnings.empty()) 194735617911SEd Maste result.AppendWarning (warnings.c_str()); 194835617911SEd Maste } 194935617911SEd Maste 195035617911SEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 195135617911SEd Maste return true; 195235617911SEd Maste } 195335617911SEd Maste 195435617911SEd Maste CommandOptions m_options; 195535617911SEd Maste }; 195635617911SEd Maste OptionDefinition 195735617911SEd Maste CommandObjectThreadJump::CommandOptions::g_option_table[] = 195835617911SEd Maste { 19590127ef0fSEd Maste { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, 196035617911SEd Maste "Specifies the source file to jump to."}, 196135617911SEd Maste 19620127ef0fSEd Maste { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum, 196335617911SEd Maste "Specifies the line number to jump to."}, 196435617911SEd Maste 19650127ef0fSEd Maste { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, 196635617911SEd Maste "Jumps by a relative line offset from the current line."}, 196735617911SEd Maste 19680127ef0fSEd Maste { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression, 196935617911SEd Maste "Jumps to a specific address."}, 197035617911SEd Maste 197135617911SEd Maste { LLDB_OPT_SET_1| 197235617911SEd Maste LLDB_OPT_SET_2| 19730127ef0fSEd Maste LLDB_OPT_SET_3, false, "force",'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,"Allows the PC to leave the current function."}, 197435617911SEd Maste 19750127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1976ac7ddfbfSEd Maste }; 1977ac7ddfbfSEd Maste 1978ac7ddfbfSEd Maste //------------------------------------------------------------------------- 19797aa51b79SEd Maste // Next are the subcommands of CommandObjectMultiwordThreadPlan 19807aa51b79SEd Maste //------------------------------------------------------------------------- 19817aa51b79SEd Maste 19827aa51b79SEd Maste 19837aa51b79SEd Maste //------------------------------------------------------------------------- 19847aa51b79SEd Maste // CommandObjectThreadPlanList 19857aa51b79SEd Maste //------------------------------------------------------------------------- 19867aa51b79SEd Maste class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads 19877aa51b79SEd Maste { 19887aa51b79SEd Maste public: 19897aa51b79SEd Maste 19907aa51b79SEd Maste class CommandOptions : public Options 19917aa51b79SEd Maste { 19927aa51b79SEd Maste public: 19937aa51b79SEd Maste 19947aa51b79SEd Maste CommandOptions (CommandInterpreter &interpreter) : 19957aa51b79SEd Maste Options(interpreter) 19967aa51b79SEd Maste { 19977aa51b79SEd Maste // Keep default values of all options in one place: OptionParsingStarting () 19987aa51b79SEd Maste OptionParsingStarting (); 19997aa51b79SEd Maste } 20007aa51b79SEd Maste 20019f2f44ceSEd Maste ~CommandOptions () override 20027aa51b79SEd Maste { 20037aa51b79SEd Maste } 20047aa51b79SEd Maste 20059f2f44ceSEd Maste Error 20069f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 20077aa51b79SEd Maste { 20087aa51b79SEd Maste Error error; 20097aa51b79SEd Maste const int short_option = m_getopt_table[option_idx].val; 20107aa51b79SEd Maste 20117aa51b79SEd Maste switch (short_option) 20127aa51b79SEd Maste { 20137aa51b79SEd Maste case 'i': 20147aa51b79SEd Maste { 20157aa51b79SEd Maste m_internal = true; 20167aa51b79SEd Maste } 20177aa51b79SEd Maste break; 20187aa51b79SEd Maste case 'v': 20197aa51b79SEd Maste { 20207aa51b79SEd Maste m_verbose = true; 20217aa51b79SEd Maste } 20227aa51b79SEd Maste break; 20237aa51b79SEd Maste default: 20247aa51b79SEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 20257aa51b79SEd Maste break; 20267aa51b79SEd Maste 20277aa51b79SEd Maste } 20287aa51b79SEd Maste return error; 20297aa51b79SEd Maste } 20307aa51b79SEd Maste 20317aa51b79SEd Maste void 20329f2f44ceSEd Maste OptionParsingStarting () override 20337aa51b79SEd Maste { 20347aa51b79SEd Maste m_verbose = false; 20357aa51b79SEd Maste m_internal = false; 20367aa51b79SEd Maste } 20377aa51b79SEd Maste 20387aa51b79SEd Maste const OptionDefinition* 20399f2f44ceSEd Maste GetDefinitions () override 20407aa51b79SEd Maste { 20417aa51b79SEd Maste return g_option_table; 20427aa51b79SEd Maste } 20437aa51b79SEd Maste 20447aa51b79SEd Maste // Options table: Required for subclasses of Options. 20457aa51b79SEd Maste 20467aa51b79SEd Maste static OptionDefinition g_option_table[]; 20477aa51b79SEd Maste 20487aa51b79SEd Maste // Instance variables to hold the values for command options. 20497aa51b79SEd Maste bool m_verbose; 20507aa51b79SEd Maste bool m_internal; 20517aa51b79SEd Maste }; 20527aa51b79SEd Maste 20537aa51b79SEd Maste CommandObjectThreadPlanList (CommandInterpreter &interpreter) : 20547aa51b79SEd Maste CommandObjectIterateOverThreads (interpreter, 20557aa51b79SEd Maste "thread plan list", 20567aa51b79SEd Maste "Show thread plans for one or more threads. If no threads are specified, show the " 20577aa51b79SEd Maste "currently selected thread. Use the thread-index \"all\" to see all threads.", 20587aa51b79SEd Maste NULL, 20591c3bbb01SEd Maste eCommandRequiresProcess | 20601c3bbb01SEd Maste eCommandRequiresThread | 20611c3bbb01SEd Maste eCommandTryTargetAPILock | 20621c3bbb01SEd Maste eCommandProcessMustBeLaunched | 20631c3bbb01SEd Maste eCommandProcessMustBePaused ), 20647aa51b79SEd Maste m_options(interpreter) 20657aa51b79SEd Maste { 20667aa51b79SEd Maste } 20677aa51b79SEd Maste 20689f2f44ceSEd Maste ~CommandObjectThreadPlanList () override 20697aa51b79SEd Maste { 20707aa51b79SEd Maste } 20717aa51b79SEd Maste 20729f2f44ceSEd Maste Options * 20739f2f44ceSEd Maste GetOptions () override 20747aa51b79SEd Maste { 20757aa51b79SEd Maste return &m_options; 20767aa51b79SEd Maste } 20777aa51b79SEd Maste 20787aa51b79SEd Maste protected: 20799f2f44ceSEd Maste bool 20809f2f44ceSEd Maste HandleOneThread (Thread &thread, CommandReturnObject &result) override 20817aa51b79SEd Maste { 20827aa51b79SEd Maste Stream &strm = result.GetOutputStream(); 20837aa51b79SEd Maste DescriptionLevel desc_level = eDescriptionLevelFull; 20847aa51b79SEd Maste if (m_options.m_verbose) 20857aa51b79SEd Maste desc_level = eDescriptionLevelVerbose; 20867aa51b79SEd Maste 20877aa51b79SEd Maste thread.DumpThreadPlans (&strm, desc_level, m_options.m_internal, true); 20887aa51b79SEd Maste return true; 20897aa51b79SEd Maste } 20907aa51b79SEd Maste CommandOptions m_options; 20917aa51b79SEd Maste }; 20927aa51b79SEd Maste 20937aa51b79SEd Maste OptionDefinition 20947aa51b79SEd Maste CommandObjectThreadPlanList::CommandOptions::g_option_table[] = 20957aa51b79SEd Maste { 20967aa51b79SEd Maste { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display more information about the thread plans"}, 20977aa51b79SEd Maste { LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display internal as well as user thread plans"}, 20987aa51b79SEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 20997aa51b79SEd Maste }; 21007aa51b79SEd Maste 21017aa51b79SEd Maste class CommandObjectThreadPlanDiscard : public CommandObjectParsed 21027aa51b79SEd Maste { 21037aa51b79SEd Maste public: 21047aa51b79SEd Maste CommandObjectThreadPlanDiscard (CommandInterpreter &interpreter) : 21057aa51b79SEd Maste CommandObjectParsed (interpreter, 21067aa51b79SEd Maste "thread plan discard", 21077aa51b79SEd Maste "Discards thread plans up to and including the plan passed as the command argument." 21087aa51b79SEd Maste "Only user visible plans can be discarded, use the index from \"thread plan list\"" 21097aa51b79SEd Maste " without the \"-i\" argument.", 21107aa51b79SEd Maste NULL, 21111c3bbb01SEd Maste eCommandRequiresProcess | 21121c3bbb01SEd Maste eCommandRequiresThread | 21131c3bbb01SEd Maste eCommandTryTargetAPILock | 21141c3bbb01SEd Maste eCommandProcessMustBeLaunched | 21151c3bbb01SEd Maste eCommandProcessMustBePaused ) 21167aa51b79SEd Maste { 21177aa51b79SEd Maste CommandArgumentEntry arg; 21187aa51b79SEd Maste CommandArgumentData plan_index_arg; 21197aa51b79SEd Maste 21207aa51b79SEd Maste // Define the first (and only) variant of this arg. 21217aa51b79SEd Maste plan_index_arg.arg_type = eArgTypeUnsignedInteger; 21227aa51b79SEd Maste plan_index_arg.arg_repetition = eArgRepeatPlain; 21237aa51b79SEd Maste 21247aa51b79SEd Maste // There is only one variant this argument could be; put it into the argument entry. 21257aa51b79SEd Maste arg.push_back (plan_index_arg); 21267aa51b79SEd Maste 21277aa51b79SEd Maste // Push the data for the first argument into the m_arguments vector. 21287aa51b79SEd Maste m_arguments.push_back (arg); 21297aa51b79SEd Maste } 21307aa51b79SEd Maste 21319f2f44ceSEd Maste ~CommandObjectThreadPlanDiscard () override {} 21327aa51b79SEd Maste 21337aa51b79SEd Maste bool 21349f2f44ceSEd Maste DoExecute (Args& args, CommandReturnObject &result) override 21357aa51b79SEd Maste { 21367aa51b79SEd Maste Thread *thread = m_exe_ctx.GetThreadPtr(); 21377aa51b79SEd Maste if (args.GetArgumentCount() != 1) 21387aa51b79SEd Maste { 21397aa51b79SEd Maste result.AppendErrorWithFormat("Too many arguments, expected one - the thread plan index - but got %zu.", 21407aa51b79SEd Maste args.GetArgumentCount()); 21417aa51b79SEd Maste result.SetStatus (eReturnStatusFailed); 21427aa51b79SEd Maste return false; 21437aa51b79SEd Maste } 21447aa51b79SEd Maste 21457aa51b79SEd Maste bool success; 21461c3bbb01SEd Maste uint32_t thread_plan_idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success); 21477aa51b79SEd Maste if (!success) 21487aa51b79SEd Maste { 21497aa51b79SEd Maste result.AppendErrorWithFormat("Invalid thread index: \"%s\" - should be unsigned int.", 21507aa51b79SEd Maste args.GetArgumentAtIndex(0)); 21517aa51b79SEd Maste result.SetStatus (eReturnStatusFailed); 21527aa51b79SEd Maste return false; 21537aa51b79SEd Maste } 21547aa51b79SEd Maste 21557aa51b79SEd Maste if (thread_plan_idx == 0) 21567aa51b79SEd Maste { 21577aa51b79SEd Maste result.AppendErrorWithFormat("You wouldn't really want me to discard the base thread plan."); 21587aa51b79SEd Maste result.SetStatus (eReturnStatusFailed); 21597aa51b79SEd Maste return false; 21607aa51b79SEd Maste } 21617aa51b79SEd Maste 21627aa51b79SEd Maste if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) 21637aa51b79SEd Maste { 21647aa51b79SEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult); 21657aa51b79SEd Maste return true; 21667aa51b79SEd Maste } 21677aa51b79SEd Maste else 21687aa51b79SEd Maste { 21697aa51b79SEd Maste result.AppendErrorWithFormat("Could not find User thread plan with index %s.", 21707aa51b79SEd Maste args.GetArgumentAtIndex(0)); 21717aa51b79SEd Maste result.SetStatus (eReturnStatusFailed); 21727aa51b79SEd Maste return false; 21737aa51b79SEd Maste } 21747aa51b79SEd Maste } 21757aa51b79SEd Maste }; 21767aa51b79SEd Maste 21777aa51b79SEd Maste //------------------------------------------------------------------------- 21787aa51b79SEd Maste // CommandObjectMultiwordThreadPlan 21797aa51b79SEd Maste //------------------------------------------------------------------------- 21807aa51b79SEd Maste 21817aa51b79SEd Maste class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword 21827aa51b79SEd Maste { 21837aa51b79SEd Maste public: 21847aa51b79SEd Maste CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) : 21857aa51b79SEd Maste CommandObjectMultiword (interpreter, 21867aa51b79SEd Maste "plan", 21877aa51b79SEd Maste "A set of subcommands for accessing the thread plans controlling execution control on one or more threads.", 21887aa51b79SEd Maste "thread plan <subcommand> [<subcommand objects]") 21897aa51b79SEd Maste { 21907aa51b79SEd Maste LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadPlanList (interpreter))); 21917aa51b79SEd Maste LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter))); 21927aa51b79SEd Maste } 21937aa51b79SEd Maste 21949f2f44ceSEd Maste ~CommandObjectMultiwordThreadPlan () override {} 21957aa51b79SEd Maste 21967aa51b79SEd Maste 21977aa51b79SEd Maste }; 21987aa51b79SEd Maste 21997aa51b79SEd Maste //------------------------------------------------------------------------- 2200ac7ddfbfSEd Maste // CommandObjectMultiwordThread 2201ac7ddfbfSEd Maste //------------------------------------------------------------------------- 2202ac7ddfbfSEd Maste 2203ac7ddfbfSEd Maste CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) : 2204ac7ddfbfSEd Maste CommandObjectMultiword (interpreter, 2205ac7ddfbfSEd Maste "thread", 2206ac7ddfbfSEd Maste "A set of commands for operating on one or more threads within a running process.", 2207ac7ddfbfSEd Maste "thread <subcommand> [<subcommand-options>]") 2208ac7ddfbfSEd Maste { 2209ac7ddfbfSEd Maste LoadSubCommand ("backtrace", CommandObjectSP (new CommandObjectThreadBacktrace (interpreter))); 2210ac7ddfbfSEd Maste LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter))); 2211ac7ddfbfSEd Maste LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter))); 2212ac7ddfbfSEd Maste LoadSubCommand ("return", CommandObjectSP (new CommandObjectThreadReturn (interpreter))); 221335617911SEd Maste LoadSubCommand ("jump", CommandObjectSP (new CommandObjectThreadJump (interpreter))); 2214ac7ddfbfSEd Maste LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter))); 2215ac7ddfbfSEd Maste LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter))); 22160127ef0fSEd Maste LoadSubCommand ("info", CommandObjectSP (new CommandObjectThreadInfo (interpreter))); 2217ac7ddfbfSEd Maste LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2218ac7ddfbfSEd Maste interpreter, 2219ac7ddfbfSEd Maste "thread step-in", 2220ac7ddfbfSEd Maste "Source level single step in specified thread (current thread, if none specified).", 2221ac7ddfbfSEd Maste NULL, 2222ac7ddfbfSEd Maste eStepTypeInto, 2223ac7ddfbfSEd Maste eStepScopeSource))); 2224ac7ddfbfSEd Maste 2225ac7ddfbfSEd Maste LoadSubCommand ("step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2226ac7ddfbfSEd Maste interpreter, 2227ac7ddfbfSEd Maste "thread step-out", 2228ac7ddfbfSEd Maste "Finish executing the function of the currently selected frame and return to its call site in specified thread (current thread, if none specified).", 2229ac7ddfbfSEd Maste NULL, 2230ac7ddfbfSEd Maste eStepTypeOut, 2231ac7ddfbfSEd Maste eStepScopeSource))); 2232ac7ddfbfSEd Maste 2233ac7ddfbfSEd Maste LoadSubCommand ("step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2234ac7ddfbfSEd Maste interpreter, 2235ac7ddfbfSEd Maste "thread step-over", 2236ac7ddfbfSEd Maste "Source level single step in specified thread (current thread, if none specified), stepping over calls.", 2237ac7ddfbfSEd Maste NULL, 2238ac7ddfbfSEd Maste eStepTypeOver, 2239ac7ddfbfSEd Maste eStepScopeSource))); 2240ac7ddfbfSEd Maste 2241ac7ddfbfSEd Maste LoadSubCommand ("step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2242ac7ddfbfSEd Maste interpreter, 2243ac7ddfbfSEd Maste "thread step-inst", 2244ac7ddfbfSEd Maste "Single step one instruction in specified thread (current thread, if none specified).", 2245ac7ddfbfSEd Maste NULL, 2246ac7ddfbfSEd Maste eStepTypeTrace, 2247ac7ddfbfSEd Maste eStepScopeInstruction))); 2248ac7ddfbfSEd Maste 2249ac7ddfbfSEd Maste LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2250ac7ddfbfSEd Maste interpreter, 2251ac7ddfbfSEd Maste "thread step-inst-over", 2252ac7ddfbfSEd Maste "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.", 2253ac7ddfbfSEd Maste NULL, 2254ac7ddfbfSEd Maste eStepTypeTraceOver, 2255ac7ddfbfSEd Maste eStepScopeInstruction))); 22567aa51b79SEd Maste 22577aa51b79SEd Maste LoadSubCommand ("step-scripted", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 22587aa51b79SEd Maste interpreter, 22597aa51b79SEd Maste "thread step-scripted", 22607aa51b79SEd Maste "Step as instructed by the script class passed in the -C option.", 22617aa51b79SEd Maste NULL, 22627aa51b79SEd Maste eStepTypeScripted, 22637aa51b79SEd Maste eStepScopeSource))); 22647aa51b79SEd Maste 22657aa51b79SEd Maste LoadSubCommand ("plan", CommandObjectSP (new CommandObjectMultiwordThreadPlan(interpreter))); 2266ac7ddfbfSEd Maste } 2267ac7ddfbfSEd Maste 2268ac7ddfbfSEd Maste CommandObjectMultiwordThread::~CommandObjectMultiwordThread () 2269ac7ddfbfSEd Maste { 2270ac7ddfbfSEd Maste } 2271ac7ddfbfSEd Maste 2272ac7ddfbfSEd Maste 2273