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 using namespace lldb; 41ac7ddfbfSEd Maste using namespace lldb_private; 42ac7ddfbfSEd Maste 43ac7ddfbfSEd Maste //------------------------------------------------------------------------- 44ac7ddfbfSEd Maste // CommandObjectThreadBacktrace 45ac7ddfbfSEd Maste //------------------------------------------------------------------------- 46ac7ddfbfSEd Maste 477aa51b79SEd Maste class CommandObjectIterateOverThreads : public CommandObjectParsed 487aa51b79SEd Maste { 497aa51b79SEd Maste public: 507aa51b79SEd Maste CommandObjectIterateOverThreads (CommandInterpreter &interpreter, 517aa51b79SEd Maste const char *name, 527aa51b79SEd Maste const char *help, 537aa51b79SEd Maste const char *syntax, 547aa51b79SEd Maste uint32_t flags) : 557aa51b79SEd Maste CommandObjectParsed (interpreter, name, help, syntax, flags) 567aa51b79SEd Maste { 577aa51b79SEd Maste } 587aa51b79SEd Maste 594bb0738eSEd Maste ~CommandObjectIterateOverThreads() override = default; 609f2f44ceSEd Maste 619f2f44ceSEd Maste bool 629f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 637aa51b79SEd Maste { 647aa51b79SEd Maste result.SetStatus (m_success_return); 657aa51b79SEd Maste 667aa51b79SEd Maste if (command.GetArgumentCount() == 0) 677aa51b79SEd Maste { 687aa51b79SEd Maste Thread *thread = m_exe_ctx.GetThreadPtr(); 694bb0738eSEd Maste if (!HandleOneThread (thread->GetID(), result)) 707aa51b79SEd Maste return false; 714bb0738eSEd Maste return result.Succeeded(); 727aa51b79SEd Maste } 734bb0738eSEd Maste 744bb0738eSEd Maste // Use tids instead of ThreadSPs to prevent deadlocking problems which result from JIT-ing 754bb0738eSEd Maste // code while iterating over the (locked) ThreadSP list. 764bb0738eSEd Maste std::vector<lldb::tid_t> tids; 774bb0738eSEd Maste 784bb0738eSEd Maste if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0) 797aa51b79SEd Maste { 807aa51b79SEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 817aa51b79SEd Maste 824bb0738eSEd Maste for (ThreadSP thread_sp : process->Threads()) 834bb0738eSEd Maste tids.push_back(thread_sp->GetID()); 847aa51b79SEd Maste } 857aa51b79SEd Maste else 867aa51b79SEd Maste { 877aa51b79SEd Maste const size_t num_args = command.GetArgumentCount(); 887aa51b79SEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 894bb0738eSEd Maste 904bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(process->GetThreadList().GetMutex()); 917aa51b79SEd Maste 927aa51b79SEd Maste for (size_t i = 0; i < num_args; i++) 937aa51b79SEd Maste { 947aa51b79SEd Maste bool success; 957aa51b79SEd Maste 961c3bbb01SEd Maste uint32_t thread_idx = StringConvert::ToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success); 977aa51b79SEd Maste if (!success) 987aa51b79SEd Maste { 997aa51b79SEd Maste result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); 1007aa51b79SEd Maste result.SetStatus (eReturnStatusFailed); 1017aa51b79SEd Maste return false; 1027aa51b79SEd Maste } 1037aa51b79SEd Maste 1044bb0738eSEd Maste ThreadSP thread = process->GetThreadList().FindThreadByIndexID(thread_idx); 1057aa51b79SEd Maste 1064bb0738eSEd Maste if (!thread) 1077aa51b79SEd Maste { 1087aa51b79SEd Maste result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i)); 1097aa51b79SEd Maste result.SetStatus (eReturnStatusFailed); 1107aa51b79SEd Maste return false; 1117aa51b79SEd Maste } 1127aa51b79SEd Maste 1134bb0738eSEd Maste tids.push_back(thread->GetID()); 1144bb0738eSEd Maste } 1157aa51b79SEd Maste } 1167aa51b79SEd Maste 1174bb0738eSEd Maste uint32_t idx = 0; 1184bb0738eSEd Maste for (const lldb::tid_t &tid : tids) 1197aa51b79SEd Maste { 1204bb0738eSEd Maste if (idx != 0 && m_add_return) 1214bb0738eSEd Maste result.AppendMessage(""); 1224bb0738eSEd Maste 1234bb0738eSEd Maste if (!HandleOneThread (tid, result)) 1247aa51b79SEd Maste return false; 1257aa51b79SEd Maste 1264bb0738eSEd Maste ++idx; 1277aa51b79SEd Maste } 1287aa51b79SEd Maste return result.Succeeded(); 1297aa51b79SEd Maste } 1307aa51b79SEd Maste 1317aa51b79SEd Maste protected: 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 1404bb0738eSEd Maste HandleOneThread (lldb::tid_t, 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 // CommandObjectThreadBacktrace 1487aa51b79SEd Maste //------------------------------------------------------------------------- 1497aa51b79SEd Maste 1507aa51b79SEd Maste class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads 151ac7ddfbfSEd Maste { 152ac7ddfbfSEd Maste public: 153ac7ddfbfSEd Maste class CommandOptions : public Options 154ac7ddfbfSEd Maste { 155ac7ddfbfSEd Maste public: 156ac7ddfbfSEd Maste CommandOptions (CommandInterpreter &interpreter) : 157ac7ddfbfSEd Maste Options(interpreter) 158ac7ddfbfSEd Maste { 159ac7ddfbfSEd Maste // Keep default values of all options in one place: OptionParsingStarting () 160ac7ddfbfSEd Maste OptionParsingStarting (); 161ac7ddfbfSEd Maste } 162ac7ddfbfSEd Maste 1634bb0738eSEd Maste ~CommandOptions() override = default; 164ac7ddfbfSEd Maste 1659f2f44ceSEd Maste Error 1669f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 167ac7ddfbfSEd Maste { 168ac7ddfbfSEd Maste Error error; 169ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 170ac7ddfbfSEd Maste 171ac7ddfbfSEd Maste switch (short_option) 172ac7ddfbfSEd Maste { 173ac7ddfbfSEd Maste case 'c': 174ac7ddfbfSEd Maste { 175ac7ddfbfSEd Maste bool success; 1761c3bbb01SEd Maste int32_t input_count = StringConvert::ToSInt32 (option_arg, -1, 0, &success); 177ac7ddfbfSEd Maste if (!success) 178ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option); 179ac7ddfbfSEd Maste if (input_count < -1) 180ac7ddfbfSEd Maste m_count = UINT32_MAX; 181ac7ddfbfSEd Maste else 182ac7ddfbfSEd Maste m_count = input_count; 183ac7ddfbfSEd Maste } 184ac7ddfbfSEd Maste break; 185ac7ddfbfSEd Maste case 's': 186ac7ddfbfSEd Maste { 187ac7ddfbfSEd Maste bool success; 1881c3bbb01SEd Maste m_start = StringConvert::ToUInt32 (option_arg, 0, 0, &success); 189ac7ddfbfSEd Maste if (!success) 190ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option); 191ac7ddfbfSEd Maste } 1924bb0738eSEd Maste break; 193b952cd58SEd Maste case 'e': 194b952cd58SEd Maste { 195b952cd58SEd Maste bool success; 196b952cd58SEd Maste m_extended_backtrace = Args::StringToBoolean (option_arg, false, &success); 197b952cd58SEd Maste if (!success) 198b952cd58SEd Maste error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option); 199b952cd58SEd Maste } 200ac7ddfbfSEd Maste break; 201ac7ddfbfSEd Maste default: 202ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 203ac7ddfbfSEd Maste break; 204ac7ddfbfSEd Maste } 205ac7ddfbfSEd Maste return error; 206ac7ddfbfSEd Maste } 207ac7ddfbfSEd Maste 208ac7ddfbfSEd Maste void 2099f2f44ceSEd Maste OptionParsingStarting () override 210ac7ddfbfSEd Maste { 211ac7ddfbfSEd Maste m_count = UINT32_MAX; 212ac7ddfbfSEd Maste m_start = 0; 213b952cd58SEd Maste m_extended_backtrace = false; 214ac7ddfbfSEd Maste } 215ac7ddfbfSEd Maste 216ac7ddfbfSEd Maste const OptionDefinition* 2179f2f44ceSEd Maste GetDefinitions () override 218ac7ddfbfSEd Maste { 219ac7ddfbfSEd Maste return g_option_table; 220ac7ddfbfSEd Maste } 221ac7ddfbfSEd Maste 222ac7ddfbfSEd Maste // Options table: Required for subclasses of Options. 223ac7ddfbfSEd Maste 224ac7ddfbfSEd Maste static OptionDefinition g_option_table[]; 225ac7ddfbfSEd Maste 226ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 227ac7ddfbfSEd Maste uint32_t m_count; 228ac7ddfbfSEd Maste uint32_t m_start; 229b952cd58SEd Maste bool m_extended_backtrace; 230ac7ddfbfSEd Maste }; 231ac7ddfbfSEd Maste 2324bb0738eSEd Maste CommandObjectThreadBacktrace(CommandInterpreter &interpreter) 2334bb0738eSEd Maste : CommandObjectIterateOverThreads( 2344bb0738eSEd Maste interpreter, "thread backtrace", "Show thread call stacks. Defaults to the current thread, thread " 2354bb0738eSEd Maste "indexes can be specified as arguments. Use the thread-index \"all\" " 2364bb0738eSEd Maste "to see all threads.", 2374bb0738eSEd Maste nullptr, eCommandRequiresProcess | eCommandRequiresThread | eCommandTryTargetAPILock | 2384bb0738eSEd Maste eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 239ac7ddfbfSEd Maste m_options(interpreter) 240ac7ddfbfSEd Maste { 241ac7ddfbfSEd Maste } 242ac7ddfbfSEd Maste 2434bb0738eSEd Maste ~CommandObjectThreadBacktrace() override = default; 244ac7ddfbfSEd Maste 2459f2f44ceSEd Maste Options * 2469f2f44ceSEd Maste GetOptions () override 247ac7ddfbfSEd Maste { 248ac7ddfbfSEd Maste return &m_options; 249ac7ddfbfSEd Maste } 250ac7ddfbfSEd Maste 251ac7ddfbfSEd Maste protected: 252b952cd58SEd Maste void 253b952cd58SEd Maste DoExtendedBacktrace (Thread *thread, CommandReturnObject &result) 254b952cd58SEd Maste { 255b952cd58SEd Maste SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime(); 256b952cd58SEd Maste if (runtime) 257b952cd58SEd Maste { 258b952cd58SEd Maste Stream &strm = result.GetOutputStream(); 259b952cd58SEd Maste const std::vector<ConstString> &types = runtime->GetExtendedBacktraceTypes(); 260b952cd58SEd Maste for (auto type : types) 261b952cd58SEd Maste { 262b952cd58SEd Maste ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread (thread->shared_from_this(), type); 263b952cd58SEd Maste if (ext_thread_sp && ext_thread_sp->IsValid ()) 264b952cd58SEd Maste { 265b952cd58SEd Maste const uint32_t num_frames_with_source = 0; 266b952cd58SEd Maste if (ext_thread_sp->GetStatus (strm, 267b952cd58SEd Maste m_options.m_start, 268b952cd58SEd Maste m_options.m_count, 269b952cd58SEd Maste num_frames_with_source)) 270b952cd58SEd Maste { 271b952cd58SEd Maste DoExtendedBacktrace (ext_thread_sp.get(), result); 272b952cd58SEd Maste } 273b952cd58SEd Maste } 274b952cd58SEd Maste } 275b952cd58SEd Maste } 276b952cd58SEd Maste } 277b952cd58SEd Maste 2789f2f44ceSEd Maste bool 2794bb0738eSEd Maste HandleOneThread (lldb::tid_t tid, CommandReturnObject &result) override 280ac7ddfbfSEd Maste { 2814bb0738eSEd Maste ThreadSP thread_sp = m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); 2824bb0738eSEd Maste if (!thread_sp) 2834bb0738eSEd Maste { 2844bb0738eSEd Maste result.AppendErrorWithFormat ("thread disappeared while computing backtraces: 0x%" PRIx64 "\n", tid); 2854bb0738eSEd Maste result.SetStatus (eReturnStatusFailed); 2864bb0738eSEd Maste return false; 2874bb0738eSEd Maste } 2884bb0738eSEd Maste 2894bb0738eSEd Maste Thread *thread = thread_sp.get(); 2904bb0738eSEd 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 2964bb0738eSEd 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 { 3014bb0738eSEd 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 { 3074bb0738eSEd 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 { 3194bb0738eSEd Maste { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "How many frames to display (-1 for all)"}, 3204bb0738eSEd Maste { LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"}, 3214bb0738eSEd Maste { LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Show the extended backtrace, if available"}, 3224bb0738eSEd Maste { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 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 class CommandOptions : public Options 335ac7ddfbfSEd Maste { 336ac7ddfbfSEd Maste public: 337ac7ddfbfSEd Maste CommandOptions (CommandInterpreter &interpreter) : 338ac7ddfbfSEd Maste Options (interpreter) 339ac7ddfbfSEd Maste { 340ac7ddfbfSEd Maste // Keep default values of all options in one place: OptionParsingStarting () 341ac7ddfbfSEd Maste OptionParsingStarting (); 342ac7ddfbfSEd Maste } 343ac7ddfbfSEd Maste 3444bb0738eSEd Maste ~CommandOptions() override = default; 345ac7ddfbfSEd Maste 3469f2f44ceSEd Maste Error 3479f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 348ac7ddfbfSEd Maste { 349ac7ddfbfSEd Maste Error error; 350ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 351ac7ddfbfSEd Maste 352ac7ddfbfSEd Maste switch (short_option) 353ac7ddfbfSEd Maste { 354ac7ddfbfSEd Maste case 'a': 355ac7ddfbfSEd Maste { 356ac7ddfbfSEd Maste bool success; 3570127ef0fSEd Maste bool avoid_no_debug = Args::StringToBoolean (option_arg, true, &success); 358ac7ddfbfSEd Maste if (!success) 359ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option); 3600127ef0fSEd Maste else 3610127ef0fSEd Maste { 3620127ef0fSEd Maste m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; 3630127ef0fSEd Maste } 364ac7ddfbfSEd Maste } 365ac7ddfbfSEd Maste break; 366ac7ddfbfSEd Maste 3670127ef0fSEd Maste case 'A': 3680127ef0fSEd Maste { 3690127ef0fSEd Maste bool success; 3700127ef0fSEd Maste bool avoid_no_debug = Args::StringToBoolean (option_arg, true, &success); 3710127ef0fSEd Maste if (!success) 3720127ef0fSEd Maste error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option); 3730127ef0fSEd Maste else 3740127ef0fSEd Maste { 3750127ef0fSEd Maste m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; 3760127ef0fSEd Maste } 3770127ef0fSEd Maste } 3780127ef0fSEd Maste break; 3790127ef0fSEd Maste 3800127ef0fSEd Maste case 'c': 3811c3bbb01SEd Maste m_step_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 3820127ef0fSEd Maste if (m_step_count == UINT32_MAX) 3834bb0738eSEd Maste error.SetErrorStringWithFormat ("invalid step count '%s'", option_arg); 3840127ef0fSEd Maste break; 3854bb0738eSEd Maste 3867aa51b79SEd Maste case 'C': 3877aa51b79SEd Maste m_class_name.clear(); 3887aa51b79SEd Maste m_class_name.assign(option_arg); 3897aa51b79SEd Maste break; 3904bb0738eSEd Maste 391ac7ddfbfSEd Maste case 'm': 392ac7ddfbfSEd Maste { 393ac7ddfbfSEd Maste OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 394ac7ddfbfSEd Maste m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error); 395ac7ddfbfSEd Maste } 396ac7ddfbfSEd Maste break; 397ac7ddfbfSEd Maste 3984bb0738eSEd Maste case 'e': 399ac7ddfbfSEd Maste { 4004bb0738eSEd Maste if (strcmp(option_arg, "block") == 0) 4014bb0738eSEd Maste { 4024bb0738eSEd Maste m_end_line_is_block_end = 1; 4034bb0738eSEd Maste break; 4044bb0738eSEd Maste } 4054bb0738eSEd Maste uint32_t tmp_end_line = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 4064bb0738eSEd Maste if (tmp_end_line == UINT32_MAX) 4074bb0738eSEd Maste error.SetErrorStringWithFormat ("invalid end line number '%s'", option_arg); 4084bb0738eSEd Maste else 4094bb0738eSEd Maste m_end_line = tmp_end_line; 4104bb0738eSEd Maste break; 4114bb0738eSEd Maste } 4124bb0738eSEd Maste break; 4134bb0738eSEd Maste 4144bb0738eSEd Maste case 'r': 415ac7ddfbfSEd Maste m_avoid_regexp.clear(); 416ac7ddfbfSEd Maste m_avoid_regexp.assign(option_arg); 417ac7ddfbfSEd Maste break; 418ac7ddfbfSEd Maste 419ac7ddfbfSEd Maste case 't': 420ac7ddfbfSEd Maste m_step_in_target.clear(); 421ac7ddfbfSEd Maste m_step_in_target.assign(option_arg); 422ac7ddfbfSEd Maste break; 4234bb0738eSEd Maste 424ac7ddfbfSEd Maste default: 425ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 426ac7ddfbfSEd Maste break; 427ac7ddfbfSEd Maste } 428ac7ddfbfSEd Maste return error; 429ac7ddfbfSEd Maste } 430ac7ddfbfSEd Maste 431ac7ddfbfSEd Maste void 4329f2f44ceSEd Maste OptionParsingStarting () override 433ac7ddfbfSEd Maste { 4340127ef0fSEd Maste m_step_in_avoid_no_debug = eLazyBoolCalculate; 4350127ef0fSEd Maste m_step_out_avoid_no_debug = eLazyBoolCalculate; 436ac7ddfbfSEd Maste m_run_mode = eOnlyDuringStepping; 4371c3bbb01SEd Maste 4381c3bbb01SEd Maste // Check if we are in Non-Stop mode 4391c3bbb01SEd Maste lldb::TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); 4404bb0738eSEd Maste if (target_sp && target_sp->GetNonStopModeEnabled()) 4411c3bbb01SEd Maste m_run_mode = eOnlyThisThread; 4421c3bbb01SEd Maste 443ac7ddfbfSEd Maste m_avoid_regexp.clear(); 444ac7ddfbfSEd Maste m_step_in_target.clear(); 4457aa51b79SEd Maste m_class_name.clear(); 4460127ef0fSEd Maste m_step_count = 1; 4474bb0738eSEd Maste m_end_line = LLDB_INVALID_LINE_NUMBER; 4484bb0738eSEd Maste m_end_line_is_block_end = false; 449ac7ddfbfSEd Maste } 450ac7ddfbfSEd Maste 451ac7ddfbfSEd Maste const OptionDefinition* 4529f2f44ceSEd Maste GetDefinitions () override 453ac7ddfbfSEd Maste { 454ac7ddfbfSEd Maste return g_option_table; 455ac7ddfbfSEd Maste } 456ac7ddfbfSEd Maste 457ac7ddfbfSEd Maste // Options table: Required for subclasses of Options. 458ac7ddfbfSEd Maste 459ac7ddfbfSEd Maste static OptionDefinition g_option_table[]; 460ac7ddfbfSEd Maste 461ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 4620127ef0fSEd Maste LazyBool m_step_in_avoid_no_debug; 4630127ef0fSEd Maste LazyBool m_step_out_avoid_no_debug; 464ac7ddfbfSEd Maste RunMode m_run_mode; 465ac7ddfbfSEd Maste std::string m_avoid_regexp; 466ac7ddfbfSEd Maste std::string m_step_in_target; 4677aa51b79SEd Maste std::string m_class_name; 4687aa51b79SEd Maste uint32_t m_step_count; 4694bb0738eSEd Maste uint32_t m_end_line; 4704bb0738eSEd Maste bool m_end_line_is_block_end; 471ac7ddfbfSEd Maste }; 472ac7ddfbfSEd Maste 473ac7ddfbfSEd Maste CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter, 474ac7ddfbfSEd Maste const char *name, 475ac7ddfbfSEd Maste const char *help, 476ac7ddfbfSEd Maste const char *syntax, 477ac7ddfbfSEd Maste StepType step_type, 478ac7ddfbfSEd Maste StepScope step_scope) : 479ac7ddfbfSEd Maste CommandObjectParsed (interpreter, name, help, syntax, 4801c3bbb01SEd Maste eCommandRequiresProcess | 4811c3bbb01SEd Maste eCommandRequiresThread | 4821c3bbb01SEd Maste eCommandTryTargetAPILock | 4831c3bbb01SEd Maste eCommandProcessMustBeLaunched | 4841c3bbb01SEd Maste eCommandProcessMustBePaused ), 485ac7ddfbfSEd Maste m_step_type (step_type), 486ac7ddfbfSEd Maste m_step_scope (step_scope), 487ac7ddfbfSEd Maste m_options (interpreter) 488ac7ddfbfSEd Maste { 489ac7ddfbfSEd Maste CommandArgumentEntry arg; 490ac7ddfbfSEd Maste CommandArgumentData thread_id_arg; 491ac7ddfbfSEd Maste 492ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 493ac7ddfbfSEd Maste thread_id_arg.arg_type = eArgTypeThreadID; 494ac7ddfbfSEd Maste thread_id_arg.arg_repetition = eArgRepeatOptional; 495ac7ddfbfSEd Maste 496ac7ddfbfSEd Maste // There is only one variant this argument could be; put it into the argument entry. 497ac7ddfbfSEd Maste arg.push_back (thread_id_arg); 498ac7ddfbfSEd Maste 499ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 500ac7ddfbfSEd Maste m_arguments.push_back (arg); 501ac7ddfbfSEd Maste } 502ac7ddfbfSEd Maste 5034bb0738eSEd Maste ~CommandObjectThreadStepWithTypeAndScope() override = default; 504ac7ddfbfSEd Maste 505ac7ddfbfSEd Maste Options * 5069f2f44ceSEd Maste GetOptions () override 507ac7ddfbfSEd Maste { 508ac7ddfbfSEd Maste return &m_options; 509ac7ddfbfSEd Maste } 510ac7ddfbfSEd Maste 511ac7ddfbfSEd Maste protected: 5129f2f44ceSEd Maste bool 5139f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 514ac7ddfbfSEd Maste { 515ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 516ac7ddfbfSEd Maste bool synchronous_execution = m_interpreter.GetSynchronous(); 517ac7ddfbfSEd Maste 518ac7ddfbfSEd Maste const uint32_t num_threads = process->GetThreadList().GetSize(); 5194bb0738eSEd Maste Thread *thread = nullptr; 520ac7ddfbfSEd Maste 521ac7ddfbfSEd Maste if (command.GetArgumentCount() == 0) 522ac7ddfbfSEd Maste { 5234bb0738eSEd Maste thread = GetDefaultThread(); 5244bb0738eSEd Maste 5254bb0738eSEd Maste if (thread == nullptr) 526ac7ddfbfSEd Maste { 527ac7ddfbfSEd Maste result.AppendError ("no selected thread in process"); 528ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 529ac7ddfbfSEd Maste return false; 530ac7ddfbfSEd Maste } 531ac7ddfbfSEd Maste } 532ac7ddfbfSEd Maste else 533ac7ddfbfSEd Maste { 534ac7ddfbfSEd Maste const char *thread_idx_cstr = command.GetArgumentAtIndex(0); 5351c3bbb01SEd Maste uint32_t step_thread_idx = StringConvert::ToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32); 536ac7ddfbfSEd Maste if (step_thread_idx == LLDB_INVALID_INDEX32) 537ac7ddfbfSEd Maste { 538ac7ddfbfSEd Maste result.AppendErrorWithFormat ("invalid thread index '%s'.\n", thread_idx_cstr); 539ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 540ac7ddfbfSEd Maste return false; 541ac7ddfbfSEd Maste } 542ac7ddfbfSEd Maste thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get(); 5434bb0738eSEd Maste if (thread == nullptr) 544ac7ddfbfSEd Maste { 545ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 546ac7ddfbfSEd Maste step_thread_idx, num_threads); 547ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 548ac7ddfbfSEd Maste return false; 549ac7ddfbfSEd Maste } 550ac7ddfbfSEd Maste } 551ac7ddfbfSEd Maste 5527aa51b79SEd Maste if (m_step_type == eStepTypeScripted) 5537aa51b79SEd Maste { 5547aa51b79SEd Maste if (m_options.m_class_name.empty()) 5557aa51b79SEd Maste { 5567aa51b79SEd Maste result.AppendErrorWithFormat ("empty class name for scripted step."); 5577aa51b79SEd Maste result.SetStatus(eReturnStatusFailed); 5587aa51b79SEd Maste return false; 5597aa51b79SEd Maste } 5607aa51b79SEd Maste else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists(m_options.m_class_name.c_str())) 5617aa51b79SEd Maste { 5627aa51b79SEd Maste result.AppendErrorWithFormat ("class for scripted step: \"%s\" does not exist.", m_options.m_class_name.c_str()); 5637aa51b79SEd Maste result.SetStatus(eReturnStatusFailed); 5647aa51b79SEd Maste return false; 5657aa51b79SEd Maste } 5667aa51b79SEd Maste } 5677aa51b79SEd Maste 5684bb0738eSEd Maste if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER 5694bb0738eSEd Maste && m_step_type != eStepTypeInto) 5704bb0738eSEd Maste { 5714bb0738eSEd Maste result.AppendErrorWithFormat("end line option is only valid for step into"); 5724bb0738eSEd Maste result.SetStatus(eReturnStatusFailed); 5734bb0738eSEd Maste return false; 5744bb0738eSEd Maste } 5754bb0738eSEd Maste 576ac7ddfbfSEd Maste const bool abort_other_plans = false; 577ac7ddfbfSEd Maste const lldb::RunMode stop_other_threads = m_options.m_run_mode; 578ac7ddfbfSEd Maste 579ac7ddfbfSEd Maste // This is a bit unfortunate, but not all the commands in this command object support 580ac7ddfbfSEd Maste // only while stepping, so I use the bool for them. 581ac7ddfbfSEd Maste bool bool_stop_other_threads; 582ac7ddfbfSEd Maste if (m_options.m_run_mode == eAllThreads) 583ac7ddfbfSEd Maste bool_stop_other_threads = false; 584ac7ddfbfSEd Maste else if (m_options.m_run_mode == eOnlyDuringStepping) 5854bb0738eSEd Maste bool_stop_other_threads = (m_step_type != eStepTypeOut && m_step_type != eStepTypeScripted); 586ac7ddfbfSEd Maste else 587ac7ddfbfSEd Maste bool_stop_other_threads = true; 588ac7ddfbfSEd Maste 589ac7ddfbfSEd Maste ThreadPlanSP new_plan_sp; 590ac7ddfbfSEd Maste 591ac7ddfbfSEd Maste if (m_step_type == eStepTypeInto) 592ac7ddfbfSEd Maste { 593ac7ddfbfSEd Maste StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 5941c3bbb01SEd Maste assert(frame != nullptr); 595ac7ddfbfSEd Maste 596ac7ddfbfSEd Maste if (frame->HasDebugInformation ()) 597ac7ddfbfSEd Maste { 5984bb0738eSEd Maste AddressRange range; 5994bb0738eSEd Maste SymbolContext sc = frame->GetSymbolContext(eSymbolContextEverything); 6004bb0738eSEd Maste if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER) 6014bb0738eSEd Maste { 6024bb0738eSEd Maste Error error; 6034bb0738eSEd Maste if (!sc.GetAddressRangeFromHereToEndLine(m_options.m_end_line, range, error)) 6044bb0738eSEd Maste { 6054bb0738eSEd Maste result.AppendErrorWithFormat("invalid end-line option: %s.", error.AsCString()); 6064bb0738eSEd Maste result.SetStatus(eReturnStatusFailed); 6074bb0738eSEd Maste return false; 6084bb0738eSEd Maste } 6094bb0738eSEd Maste } 6104bb0738eSEd Maste else if (m_options.m_end_line_is_block_end) 6114bb0738eSEd Maste { 6124bb0738eSEd Maste Error error; 6134bb0738eSEd Maste Block *block = frame->GetSymbolContext(eSymbolContextBlock).block; 6144bb0738eSEd Maste if (!block) 6154bb0738eSEd Maste { 6164bb0738eSEd Maste result.AppendErrorWithFormat("Could not find the current block."); 6174bb0738eSEd Maste result.SetStatus(eReturnStatusFailed); 6184bb0738eSEd Maste return false; 6194bb0738eSEd Maste } 6204bb0738eSEd Maste 6214bb0738eSEd Maste AddressRange block_range; 6224bb0738eSEd Maste Address pc_address = frame->GetFrameCodeAddress(); 6234bb0738eSEd Maste block->GetRangeContainingAddress(pc_address, block_range); 6244bb0738eSEd Maste if (!block_range.GetBaseAddress().IsValid()) 6254bb0738eSEd Maste { 6264bb0738eSEd Maste result.AppendErrorWithFormat("Could not find the current block address."); 6274bb0738eSEd Maste result.SetStatus(eReturnStatusFailed); 6284bb0738eSEd Maste return false; 6294bb0738eSEd Maste } 6304bb0738eSEd Maste lldb::addr_t pc_offset_in_block = pc_address.GetFileAddress() - block_range.GetBaseAddress().GetFileAddress(); 6314bb0738eSEd Maste lldb::addr_t range_length = block_range.GetByteSize() - pc_offset_in_block; 6324bb0738eSEd Maste range = AddressRange(pc_address, range_length); 6334bb0738eSEd Maste } 6344bb0738eSEd Maste else 6354bb0738eSEd Maste { 6364bb0738eSEd Maste range = sc.line_entry.range; 6374bb0738eSEd Maste } 6384bb0738eSEd Maste 639ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans, 6404bb0738eSEd Maste range, 641ac7ddfbfSEd Maste frame->GetSymbolContext(eSymbolContextEverything), 642ac7ddfbfSEd Maste m_options.m_step_in_target.c_str(), 643ac7ddfbfSEd Maste stop_other_threads, 6440127ef0fSEd Maste m_options.m_step_in_avoid_no_debug, 6450127ef0fSEd Maste m_options.m_step_out_avoid_no_debug); 6460127ef0fSEd Maste 647ac7ddfbfSEd Maste if (new_plan_sp && !m_options.m_avoid_regexp.empty()) 648ac7ddfbfSEd Maste { 649ac7ddfbfSEd Maste ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan_sp.get()); 650ac7ddfbfSEd Maste step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str()); 651ac7ddfbfSEd Maste } 652ac7ddfbfSEd Maste } 653ac7ddfbfSEd Maste else 654ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); 655ac7ddfbfSEd Maste } 656ac7ddfbfSEd Maste else if (m_step_type == eStepTypeOver) 657ac7ddfbfSEd Maste { 658ac7ddfbfSEd Maste StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 659ac7ddfbfSEd Maste 660ac7ddfbfSEd Maste if (frame->HasDebugInformation()) 661ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans, 6629f2f44ceSEd Maste frame->GetSymbolContext(eSymbolContextEverything).line_entry, 663ac7ddfbfSEd Maste frame->GetSymbolContext(eSymbolContextEverything), 6640127ef0fSEd Maste stop_other_threads, 6650127ef0fSEd Maste m_options.m_step_out_avoid_no_debug); 666ac7ddfbfSEd Maste else 667ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, 668ac7ddfbfSEd Maste abort_other_plans, 669ac7ddfbfSEd Maste bool_stop_other_threads); 670ac7ddfbfSEd Maste } 671ac7ddfbfSEd Maste else if (m_step_type == eStepTypeTrace) 672ac7ddfbfSEd Maste { 673ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); 674ac7ddfbfSEd Maste } 675ac7ddfbfSEd Maste else if (m_step_type == eStepTypeTraceOver) 676ac7ddfbfSEd Maste { 677ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads); 678ac7ddfbfSEd Maste } 679ac7ddfbfSEd Maste else if (m_step_type == eStepTypeOut) 680ac7ddfbfSEd Maste { 681ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepOut(abort_other_plans, 6824bb0738eSEd Maste nullptr, 683ac7ddfbfSEd Maste false, 684ac7ddfbfSEd Maste bool_stop_other_threads, 685ac7ddfbfSEd Maste eVoteYes, 686ac7ddfbfSEd Maste eVoteNoOpinion, 6870127ef0fSEd Maste thread->GetSelectedFrameIndex(), 6880127ef0fSEd Maste m_options.m_step_out_avoid_no_debug); 689ac7ddfbfSEd Maste } 6907aa51b79SEd Maste else if (m_step_type == eStepTypeScripted) 6917aa51b79SEd Maste { 6927aa51b79SEd Maste new_plan_sp = thread->QueueThreadPlanForStepScripted (abort_other_plans, 6937aa51b79SEd Maste m_options.m_class_name.c_str(), 6947aa51b79SEd Maste bool_stop_other_threads); 6957aa51b79SEd Maste } 696ac7ddfbfSEd Maste else 697ac7ddfbfSEd Maste { 698ac7ddfbfSEd Maste result.AppendError ("step type is not supported"); 699ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 700ac7ddfbfSEd Maste return false; 701ac7ddfbfSEd Maste } 702ac7ddfbfSEd Maste 703ac7ddfbfSEd Maste // If we got a new plan, then set it to be a master plan (User level Plans should be master plans 704ac7ddfbfSEd Maste // so that they can be interruptible). Then resume the process. 705ac7ddfbfSEd Maste 706ac7ddfbfSEd Maste if (new_plan_sp) 707ac7ddfbfSEd Maste { 708ac7ddfbfSEd Maste new_plan_sp->SetIsMasterPlan (true); 709ac7ddfbfSEd Maste new_plan_sp->SetOkayToDiscard (false); 710ac7ddfbfSEd Maste 7110127ef0fSEd Maste if (m_options.m_step_count > 1) 7120127ef0fSEd Maste { 7130127ef0fSEd Maste if (new_plan_sp->SetIterationCount(m_options.m_step_count)) 7140127ef0fSEd Maste { 7150127ef0fSEd Maste result.AppendWarning ("step operation does not support iteration count."); 7160127ef0fSEd Maste } 7170127ef0fSEd Maste } 7180127ef0fSEd Maste 719ac7ddfbfSEd Maste process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 7207aa51b79SEd Maste 7211c3bbb01SEd Maste const uint32_t iohandler_id = process->GetIOHandlerID(); 7221c3bbb01SEd Maste 7237aa51b79SEd Maste StreamString stream; 7247aa51b79SEd Maste Error error; 7257aa51b79SEd Maste if (synchronous_execution) 7267aa51b79SEd Maste error = process->ResumeSynchronous (&stream); 7277aa51b79SEd Maste else 7287aa51b79SEd Maste error = process->Resume (); 729ac7ddfbfSEd Maste 7300127ef0fSEd Maste // There is a race condition where this thread will return up the call stack to the main command handler 7310127ef0fSEd Maste // and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has 7320127ef0fSEd Maste // a chance to call PushProcessIOHandler(). 7331c3bbb01SEd Maste process->SyncIOHandler(iohandler_id, 2000); 734ac7ddfbfSEd Maste 735ac7ddfbfSEd Maste if (synchronous_execution) 736ac7ddfbfSEd Maste { 7377aa51b79SEd Maste // If any state changed events had anything to say, add that to the result 7387aa51b79SEd Maste if (stream.GetData()) 7397aa51b79SEd Maste result.AppendMessage(stream.GetData()); 740ac7ddfbfSEd Maste 741ac7ddfbfSEd Maste process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 742ac7ddfbfSEd Maste result.SetDidChangeProcessState (true); 743ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishNoResult); 744ac7ddfbfSEd Maste } 745ac7ddfbfSEd Maste else 746ac7ddfbfSEd Maste { 747ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessContinuingNoResult); 748ac7ddfbfSEd Maste } 749ac7ddfbfSEd Maste } 750ac7ddfbfSEd Maste else 751ac7ddfbfSEd Maste { 752ac7ddfbfSEd Maste result.AppendError ("Couldn't find thread plan to implement step type."); 753ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 754ac7ddfbfSEd Maste } 755ac7ddfbfSEd Maste return result.Succeeded(); 756ac7ddfbfSEd Maste } 757ac7ddfbfSEd Maste 758ac7ddfbfSEd Maste protected: 759ac7ddfbfSEd Maste StepType m_step_type; 760ac7ddfbfSEd Maste StepScope m_step_scope; 761ac7ddfbfSEd Maste CommandOptions m_options; 762ac7ddfbfSEd Maste }; 763ac7ddfbfSEd Maste 764ac7ddfbfSEd Maste static OptionEnumValueElement 765ac7ddfbfSEd Maste g_tri_running_mode[] = 766ac7ddfbfSEd Maste { 767ac7ddfbfSEd Maste { eOnlyThisThread, "this-thread", "Run only this thread"}, 768ac7ddfbfSEd Maste { eAllThreads, "all-threads", "Run all threads"}, 769ac7ddfbfSEd Maste { eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"}, 7704bb0738eSEd Maste { 0, nullptr, nullptr } 771ac7ddfbfSEd Maste }; 772ac7ddfbfSEd Maste 773ac7ddfbfSEd Maste static OptionEnumValueElement 774ac7ddfbfSEd Maste g_duo_running_mode[] = 775ac7ddfbfSEd Maste { 776ac7ddfbfSEd Maste { eOnlyThisThread, "this-thread", "Run only this thread"}, 777ac7ddfbfSEd Maste { eAllThreads, "all-threads", "Run all threads"}, 7784bb0738eSEd Maste { 0, nullptr, nullptr } 779ac7ddfbfSEd Maste }; 780ac7ddfbfSEd Maste 781ac7ddfbfSEd Maste OptionDefinition 782ac7ddfbfSEd Maste CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] = 783ac7ddfbfSEd Maste { 7844bb0738eSEd Maste { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "A boolean value that sets whether stepping into functions will step over functions with no debug information."}, 7854bb0738eSEd Maste { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information."}, 7864bb0738eSEd Maste { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."}, 7874bb0738eSEd Maste { LLDB_OPT_SET_1, false, "end-linenumber", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 1, eArgTypeLineNum, "The line at which to stop stepping - defaults to the next line and only supported for step-in and step-over." 7884bb0738eSEd Maste " You can also pass the string 'block' to step to the end of the current block." 7894bb0738eSEd Maste " This is particularly useful in conjunction with --step-target to step through a complex calling sequence."}, 7904bb0738eSEd Maste { LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, nullptr, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."}, 7914bb0738eSEd Maste { LLDB_OPT_SET_1, false, "step-over-regexp", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in."}, 7924bb0738eSEd Maste { LLDB_OPT_SET_1, false, "step-in-target", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."}, 7934bb0738eSEd Maste { LLDB_OPT_SET_2, false, "python-class", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step."}, 7944bb0738eSEd Maste { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 795ac7ddfbfSEd Maste }; 796ac7ddfbfSEd Maste 797ac7ddfbfSEd Maste //------------------------------------------------------------------------- 798ac7ddfbfSEd Maste // CommandObjectThreadContinue 799ac7ddfbfSEd Maste //------------------------------------------------------------------------- 800ac7ddfbfSEd Maste 801ac7ddfbfSEd Maste class CommandObjectThreadContinue : public CommandObjectParsed 802ac7ddfbfSEd Maste { 803ac7ddfbfSEd Maste public: 8044bb0738eSEd Maste CommandObjectThreadContinue(CommandInterpreter &interpreter) 8054bb0738eSEd Maste : CommandObjectParsed(interpreter, "thread continue", "Continue execution of the current target process. One " 8064bb0738eSEd Maste "or more threads may be specified, by default all " 8074bb0738eSEd Maste "threads continue.", 8084bb0738eSEd Maste nullptr, eCommandRequiresThread | eCommandTryTargetAPILock | 8094bb0738eSEd Maste eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) 810ac7ddfbfSEd Maste { 811ac7ddfbfSEd Maste CommandArgumentEntry arg; 812ac7ddfbfSEd Maste CommandArgumentData thread_idx_arg; 813ac7ddfbfSEd Maste 814ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 815ac7ddfbfSEd Maste thread_idx_arg.arg_type = eArgTypeThreadIndex; 816ac7ddfbfSEd Maste thread_idx_arg.arg_repetition = eArgRepeatPlus; 817ac7ddfbfSEd Maste 818ac7ddfbfSEd Maste // There is only one variant this argument could be; put it into the argument entry. 819ac7ddfbfSEd Maste arg.push_back (thread_idx_arg); 820ac7ddfbfSEd Maste 821ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 822ac7ddfbfSEd Maste m_arguments.push_back (arg); 823ac7ddfbfSEd Maste } 824ac7ddfbfSEd Maste 8254bb0738eSEd Maste ~CommandObjectThreadContinue() override = default; 826ac7ddfbfSEd Maste 8279f2f44ceSEd Maste bool 8289f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 829ac7ddfbfSEd Maste { 830ac7ddfbfSEd Maste bool synchronous_execution = m_interpreter.GetSynchronous (); 831ac7ddfbfSEd Maste 8324bb0738eSEd Maste if (!m_interpreter.GetDebugger().GetSelectedTarget()) 833ac7ddfbfSEd Maste { 834ac7ddfbfSEd Maste result.AppendError ("invalid target, create a debug target using the 'target create' command"); 835ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 836ac7ddfbfSEd Maste return false; 837ac7ddfbfSEd Maste } 838ac7ddfbfSEd Maste 839ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 8404bb0738eSEd Maste if (process == nullptr) 841ac7ddfbfSEd Maste { 842ac7ddfbfSEd Maste result.AppendError ("no process exists. Cannot continue"); 843ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 844ac7ddfbfSEd Maste return false; 845ac7ddfbfSEd Maste } 846ac7ddfbfSEd Maste 847ac7ddfbfSEd Maste StateType state = process->GetState(); 848ac7ddfbfSEd Maste if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended)) 849ac7ddfbfSEd Maste { 850ac7ddfbfSEd Maste const size_t argc = command.GetArgumentCount(); 851ac7ddfbfSEd Maste if (argc > 0) 852ac7ddfbfSEd Maste { 85335617911SEd Maste // These two lines appear at the beginning of both blocks in 85435617911SEd Maste // this if..else, but that is because we need to release the 85535617911SEd Maste // lock before calling process->Resume below. 8564bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(process->GetThreadList().GetMutex()); 85735617911SEd Maste const uint32_t num_threads = process->GetThreadList().GetSize(); 858ac7ddfbfSEd Maste std::vector<Thread *> resume_threads; 859ac7ddfbfSEd Maste for (uint32_t i = 0; i < argc; ++i) 860ac7ddfbfSEd Maste { 861ac7ddfbfSEd Maste bool success; 862ac7ddfbfSEd Maste const int base = 0; 8631c3bbb01SEd Maste uint32_t thread_idx = StringConvert::ToUInt32 (command.GetArgumentAtIndex(i), LLDB_INVALID_INDEX32, base, &success); 864ac7ddfbfSEd Maste if (success) 865ac7ddfbfSEd Maste { 866ac7ddfbfSEd Maste Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get(); 867ac7ddfbfSEd Maste 868ac7ddfbfSEd Maste if (thread) 869ac7ddfbfSEd Maste { 870ac7ddfbfSEd Maste resume_threads.push_back(thread); 871ac7ddfbfSEd Maste } 872ac7ddfbfSEd Maste else 873ac7ddfbfSEd Maste { 874ac7ddfbfSEd Maste result.AppendErrorWithFormat("invalid thread index %u.\n", thread_idx); 875ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 876ac7ddfbfSEd Maste return false; 877ac7ddfbfSEd Maste } 878ac7ddfbfSEd Maste } 879ac7ddfbfSEd Maste else 880ac7ddfbfSEd Maste { 881ac7ddfbfSEd Maste result.AppendErrorWithFormat ("invalid thread index argument: \"%s\".\n", command.GetArgumentAtIndex(i)); 882ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 883ac7ddfbfSEd Maste return false; 884ac7ddfbfSEd Maste } 885ac7ddfbfSEd Maste } 886ac7ddfbfSEd Maste 887ac7ddfbfSEd Maste if (resume_threads.empty()) 888ac7ddfbfSEd Maste { 889ac7ddfbfSEd Maste result.AppendError ("no valid thread indexes were specified"); 890ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 891ac7ddfbfSEd Maste return false; 892ac7ddfbfSEd Maste } 893ac7ddfbfSEd Maste else 894ac7ddfbfSEd Maste { 895ac7ddfbfSEd Maste if (resume_threads.size() == 1) 896ac7ddfbfSEd Maste result.AppendMessageWithFormat ("Resuming thread: "); 897ac7ddfbfSEd Maste else 898ac7ddfbfSEd Maste result.AppendMessageWithFormat ("Resuming threads: "); 899ac7ddfbfSEd Maste 900ac7ddfbfSEd Maste for (uint32_t idx = 0; idx < num_threads; ++idx) 901ac7ddfbfSEd Maste { 902ac7ddfbfSEd Maste Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 903ac7ddfbfSEd Maste std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread); 904ac7ddfbfSEd Maste 905ac7ddfbfSEd Maste if (this_thread_pos != resume_threads.end()) 906ac7ddfbfSEd Maste { 907ac7ddfbfSEd Maste resume_threads.erase(this_thread_pos); 9084bb0738eSEd Maste if (!resume_threads.empty()) 909ac7ddfbfSEd Maste result.AppendMessageWithFormat ("%u, ", thread->GetIndexID()); 910ac7ddfbfSEd Maste else 911ac7ddfbfSEd Maste result.AppendMessageWithFormat ("%u ", thread->GetIndexID()); 912ac7ddfbfSEd Maste 9130127ef0fSEd Maste const bool override_suspend = true; 9140127ef0fSEd Maste thread->SetResumeState (eStateRunning, override_suspend); 915ac7ddfbfSEd Maste } 916ac7ddfbfSEd Maste else 917ac7ddfbfSEd Maste { 918ac7ddfbfSEd Maste thread->SetResumeState (eStateSuspended); 919ac7ddfbfSEd Maste } 920ac7ddfbfSEd Maste } 921ac7ddfbfSEd Maste result.AppendMessageWithFormat ("in process %" PRIu64 "\n", process->GetID()); 922ac7ddfbfSEd Maste } 923ac7ddfbfSEd Maste } 924ac7ddfbfSEd Maste else 925ac7ddfbfSEd Maste { 92635617911SEd Maste // These two lines appear at the beginning of both blocks in 92735617911SEd Maste // this if..else, but that is because we need to release the 92835617911SEd Maste // lock before calling process->Resume below. 9294bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(process->GetThreadList().GetMutex()); 93035617911SEd Maste const uint32_t num_threads = process->GetThreadList().GetSize(); 9314bb0738eSEd Maste Thread *current_thread = GetDefaultThread(); 9324bb0738eSEd Maste if (current_thread == nullptr) 933ac7ddfbfSEd Maste { 934ac7ddfbfSEd Maste result.AppendError ("the process doesn't have a current thread"); 935ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 936ac7ddfbfSEd Maste return false; 937ac7ddfbfSEd Maste } 938ac7ddfbfSEd Maste // Set the actions that the threads should each take when resuming 939ac7ddfbfSEd Maste for (uint32_t idx = 0; idx < num_threads; ++idx) 940ac7ddfbfSEd Maste { 941ac7ddfbfSEd Maste Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 942ac7ddfbfSEd Maste if (thread == current_thread) 943ac7ddfbfSEd Maste { 944ac7ddfbfSEd Maste result.AppendMessageWithFormat ("Resuming thread 0x%4.4" PRIx64 " in process %" PRIu64 "\n", thread->GetID(), process->GetID()); 9450127ef0fSEd Maste const bool override_suspend = true; 9460127ef0fSEd Maste thread->SetResumeState (eStateRunning, override_suspend); 947ac7ddfbfSEd Maste } 948ac7ddfbfSEd Maste else 949ac7ddfbfSEd Maste { 950ac7ddfbfSEd Maste thread->SetResumeState (eStateSuspended); 951ac7ddfbfSEd Maste } 952ac7ddfbfSEd Maste } 953ac7ddfbfSEd Maste } 954ac7ddfbfSEd Maste 9557aa51b79SEd Maste StreamString stream; 9567aa51b79SEd Maste Error error; 9577aa51b79SEd Maste if (synchronous_execution) 9587aa51b79SEd Maste error = process->ResumeSynchronous (&stream); 9597aa51b79SEd Maste else 9607aa51b79SEd Maste error = process->Resume (); 9617aa51b79SEd Maste 96235617911SEd Maste // We should not be holding the thread list lock when we do this. 963ac7ddfbfSEd Maste if (error.Success()) 964ac7ddfbfSEd Maste { 965ac7ddfbfSEd Maste result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); 966ac7ddfbfSEd Maste if (synchronous_execution) 967ac7ddfbfSEd Maste { 9687aa51b79SEd Maste // If any state changed events had anything to say, add that to the result 9697aa51b79SEd Maste if (stream.GetData()) 9707aa51b79SEd Maste result.AppendMessage(stream.GetData()); 971ac7ddfbfSEd Maste 972ac7ddfbfSEd Maste result.SetDidChangeProcessState (true); 973ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishNoResult); 974ac7ddfbfSEd Maste } 975ac7ddfbfSEd Maste else 976ac7ddfbfSEd Maste { 977ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessContinuingNoResult); 978ac7ddfbfSEd Maste } 979ac7ddfbfSEd Maste } 980ac7ddfbfSEd Maste else 981ac7ddfbfSEd Maste { 982ac7ddfbfSEd Maste result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString()); 983ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 984ac7ddfbfSEd Maste } 985ac7ddfbfSEd Maste } 986ac7ddfbfSEd Maste else 987ac7ddfbfSEd Maste { 988ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 989ac7ddfbfSEd Maste StateAsCString(state)); 990ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 991ac7ddfbfSEd Maste } 992ac7ddfbfSEd Maste 993ac7ddfbfSEd Maste return result.Succeeded(); 994ac7ddfbfSEd Maste } 995ac7ddfbfSEd Maste }; 996ac7ddfbfSEd Maste 997ac7ddfbfSEd Maste //------------------------------------------------------------------------- 998ac7ddfbfSEd Maste // CommandObjectThreadUntil 999ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1000ac7ddfbfSEd Maste 1001ac7ddfbfSEd Maste class CommandObjectThreadUntil : public CommandObjectParsed 1002ac7ddfbfSEd Maste { 1003ac7ddfbfSEd Maste public: 1004ac7ddfbfSEd Maste class CommandOptions : public Options 1005ac7ddfbfSEd Maste { 1006ac7ddfbfSEd Maste public: 1007ac7ddfbfSEd Maste uint32_t m_thread_idx; 1008ac7ddfbfSEd Maste uint32_t m_frame_idx; 1009ac7ddfbfSEd Maste 1010ac7ddfbfSEd Maste CommandOptions (CommandInterpreter &interpreter) : 1011ac7ddfbfSEd Maste Options (interpreter), 1012ac7ddfbfSEd Maste m_thread_idx(LLDB_INVALID_THREAD_ID), 1013ac7ddfbfSEd Maste m_frame_idx(LLDB_INVALID_FRAME_ID) 1014ac7ddfbfSEd Maste { 1015ac7ddfbfSEd Maste // Keep default values of all options in one place: OptionParsingStarting () 1016ac7ddfbfSEd Maste OptionParsingStarting (); 1017ac7ddfbfSEd Maste } 1018ac7ddfbfSEd Maste 10194bb0738eSEd Maste ~CommandOptions() override = default; 1020ac7ddfbfSEd Maste 10219f2f44ceSEd Maste Error 10229f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 1023ac7ddfbfSEd Maste { 1024ac7ddfbfSEd Maste Error error; 1025ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 1026ac7ddfbfSEd Maste 1027ac7ddfbfSEd Maste switch (short_option) 1028ac7ddfbfSEd Maste { 10291c3bbb01SEd Maste case 'a': 10301c3bbb01SEd Maste { 10311c3bbb01SEd Maste ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 10321c3bbb01SEd Maste lldb::addr_t tmp_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); 10331c3bbb01SEd Maste if (error.Success()) 10341c3bbb01SEd Maste m_until_addrs.push_back(tmp_addr); 10351c3bbb01SEd Maste } 10361c3bbb01SEd Maste break; 1037ac7ddfbfSEd Maste case 't': 10381c3bbb01SEd Maste m_thread_idx = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_INDEX32); 1039ac7ddfbfSEd Maste if (m_thread_idx == LLDB_INVALID_INDEX32) 1040ac7ddfbfSEd Maste { 1041ac7ddfbfSEd Maste error.SetErrorStringWithFormat ("invalid thread index '%s'", option_arg); 1042ac7ddfbfSEd Maste } 1043ac7ddfbfSEd Maste break; 1044ac7ddfbfSEd Maste case 'f': 10451c3bbb01SEd Maste m_frame_idx = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_FRAME_ID); 1046ac7ddfbfSEd Maste if (m_frame_idx == LLDB_INVALID_FRAME_ID) 1047ac7ddfbfSEd Maste { 1048ac7ddfbfSEd Maste error.SetErrorStringWithFormat ("invalid frame index '%s'", option_arg); 1049ac7ddfbfSEd Maste } 1050ac7ddfbfSEd Maste break; 1051ac7ddfbfSEd Maste case 'm': 1052ac7ddfbfSEd Maste { 1053ac7ddfbfSEd Maste OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 1054ac7ddfbfSEd Maste lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error); 1055ac7ddfbfSEd Maste 1056ac7ddfbfSEd Maste if (error.Success()) 1057ac7ddfbfSEd Maste { 1058ac7ddfbfSEd Maste if (run_mode == eAllThreads) 1059ac7ddfbfSEd Maste m_stop_others = false; 1060ac7ddfbfSEd Maste else 1061ac7ddfbfSEd Maste m_stop_others = true; 1062ac7ddfbfSEd Maste } 1063ac7ddfbfSEd Maste } 1064ac7ddfbfSEd Maste break; 1065ac7ddfbfSEd Maste default: 1066ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1067ac7ddfbfSEd Maste break; 1068ac7ddfbfSEd Maste } 1069ac7ddfbfSEd Maste return error; 1070ac7ddfbfSEd Maste } 1071ac7ddfbfSEd Maste 1072ac7ddfbfSEd Maste void 10739f2f44ceSEd Maste OptionParsingStarting () override 1074ac7ddfbfSEd Maste { 1075ac7ddfbfSEd Maste m_thread_idx = LLDB_INVALID_THREAD_ID; 1076ac7ddfbfSEd Maste m_frame_idx = 0; 1077ac7ddfbfSEd Maste m_stop_others = false; 10781c3bbb01SEd Maste m_until_addrs.clear(); 1079ac7ddfbfSEd Maste } 1080ac7ddfbfSEd Maste 1081ac7ddfbfSEd Maste const OptionDefinition* 10829f2f44ceSEd Maste GetDefinitions () override 1083ac7ddfbfSEd Maste { 1084ac7ddfbfSEd Maste return g_option_table; 1085ac7ddfbfSEd Maste } 1086ac7ddfbfSEd Maste 1087ac7ddfbfSEd Maste uint32_t m_step_thread_idx; 1088ac7ddfbfSEd Maste bool m_stop_others; 10891c3bbb01SEd Maste std::vector<lldb::addr_t> m_until_addrs; 1090ac7ddfbfSEd Maste 1091ac7ddfbfSEd Maste // Options table: Required for subclasses of Options. 1092ac7ddfbfSEd Maste 1093ac7ddfbfSEd Maste static OptionDefinition g_option_table[]; 1094ac7ddfbfSEd Maste 1095ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 1096ac7ddfbfSEd Maste }; 1097ac7ddfbfSEd Maste 10984bb0738eSEd Maste CommandObjectThreadUntil(CommandInterpreter &interpreter) 10994bb0738eSEd Maste : CommandObjectParsed(interpreter, "thread until", "Continue until a line number or address is reached by the " 11004bb0738eSEd Maste "current or specified thread. Stops when returning from " 11014bb0738eSEd Maste "the current function as a safety measure.", 11024bb0738eSEd Maste nullptr, eCommandRequiresThread | eCommandTryTargetAPILock | 11034bb0738eSEd Maste eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 1104ac7ddfbfSEd Maste m_options(interpreter) 1105ac7ddfbfSEd Maste { 1106ac7ddfbfSEd Maste CommandArgumentEntry arg; 1107ac7ddfbfSEd Maste CommandArgumentData line_num_arg; 1108ac7ddfbfSEd Maste 1109ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 1110ac7ddfbfSEd Maste line_num_arg.arg_type = eArgTypeLineNum; 1111ac7ddfbfSEd Maste line_num_arg.arg_repetition = eArgRepeatPlain; 1112ac7ddfbfSEd Maste 1113ac7ddfbfSEd Maste // There is only one variant this argument could be; put it into the argument entry. 1114ac7ddfbfSEd Maste arg.push_back (line_num_arg); 1115ac7ddfbfSEd Maste 1116ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 1117ac7ddfbfSEd Maste m_arguments.push_back (arg); 1118ac7ddfbfSEd Maste } 1119ac7ddfbfSEd Maste 11204bb0738eSEd Maste ~CommandObjectThreadUntil() override = default; 1121ac7ddfbfSEd Maste 1122ac7ddfbfSEd Maste Options * 11239f2f44ceSEd Maste GetOptions () override 1124ac7ddfbfSEd Maste { 1125ac7ddfbfSEd Maste return &m_options; 1126ac7ddfbfSEd Maste } 1127ac7ddfbfSEd Maste 1128ac7ddfbfSEd Maste protected: 11299f2f44ceSEd Maste bool 11309f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 1131ac7ddfbfSEd Maste { 1132ac7ddfbfSEd Maste bool synchronous_execution = m_interpreter.GetSynchronous (); 1133ac7ddfbfSEd Maste 1134ac7ddfbfSEd Maste Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 11354bb0738eSEd Maste if (target == nullptr) 1136ac7ddfbfSEd Maste { 1137ac7ddfbfSEd Maste result.AppendError ("invalid target, create a debug target using the 'target create' command"); 1138ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1139ac7ddfbfSEd Maste return false; 1140ac7ddfbfSEd Maste } 1141ac7ddfbfSEd Maste 1142ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 11434bb0738eSEd Maste if (process == nullptr) 1144ac7ddfbfSEd Maste { 1145ac7ddfbfSEd Maste result.AppendError ("need a valid process to step"); 1146ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1147ac7ddfbfSEd Maste } 1148ac7ddfbfSEd Maste else 1149ac7ddfbfSEd Maste { 11504bb0738eSEd Maste Thread *thread = nullptr; 11511c3bbb01SEd Maste std::vector<uint32_t> line_numbers; 1152ac7ddfbfSEd Maste 11531c3bbb01SEd Maste if (command.GetArgumentCount() >= 1) 1154ac7ddfbfSEd Maste { 11551c3bbb01SEd Maste size_t num_args = command.GetArgumentCount(); 11561c3bbb01SEd Maste for (size_t i = 0; i < num_args; i++) 11571c3bbb01SEd Maste { 11581c3bbb01SEd Maste uint32_t line_number; 11591c3bbb01SEd Maste line_number = StringConvert::ToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX); 1160ac7ddfbfSEd Maste if (line_number == UINT32_MAX) 1161ac7ddfbfSEd Maste { 1162ac7ddfbfSEd Maste result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0)); 1163ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1164ac7ddfbfSEd Maste return false; 1165ac7ddfbfSEd Maste } 11661c3bbb01SEd Maste else 11671c3bbb01SEd Maste line_numbers.push_back(line_number); 11681c3bbb01SEd Maste } 11691c3bbb01SEd Maste } 11701c3bbb01SEd Maste else if (m_options.m_until_addrs.empty()) 11711c3bbb01SEd Maste { 11721c3bbb01SEd Maste result.AppendErrorWithFormat ("No line number or address provided:\n%s", GetSyntax()); 11731c3bbb01SEd Maste result.SetStatus (eReturnStatusFailed); 11741c3bbb01SEd Maste return false; 11751c3bbb01SEd Maste } 11761c3bbb01SEd Maste 1177ac7ddfbfSEd Maste if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) 1178ac7ddfbfSEd Maste { 11794bb0738eSEd Maste thread = GetDefaultThread(); 1180ac7ddfbfSEd Maste } 1181ac7ddfbfSEd Maste else 1182ac7ddfbfSEd Maste { 1183ac7ddfbfSEd Maste thread = process->GetThreadList().FindThreadByIndexID(m_options.m_thread_idx).get(); 1184ac7ddfbfSEd Maste } 1185ac7ddfbfSEd Maste 11864bb0738eSEd Maste if (thread == nullptr) 1187ac7ddfbfSEd Maste { 1188ac7ddfbfSEd Maste const uint32_t num_threads = process->GetThreadList().GetSize(); 1189ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 1190ac7ddfbfSEd Maste m_options.m_thread_idx, 1191ac7ddfbfSEd Maste num_threads); 1192ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1193ac7ddfbfSEd Maste return false; 1194ac7ddfbfSEd Maste } 1195ac7ddfbfSEd Maste 1196ac7ddfbfSEd Maste const bool abort_other_plans = false; 1197ac7ddfbfSEd Maste 1198ac7ddfbfSEd Maste StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get(); 11994bb0738eSEd Maste if (frame == nullptr) 1200ac7ddfbfSEd Maste { 1201ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", 1202ac7ddfbfSEd Maste m_options.m_frame_idx, 1203ac7ddfbfSEd Maste m_options.m_thread_idx); 1204ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1205ac7ddfbfSEd Maste return false; 1206ac7ddfbfSEd Maste } 1207ac7ddfbfSEd Maste 1208ac7ddfbfSEd Maste ThreadPlanSP new_plan_sp; 1209ac7ddfbfSEd Maste 1210ac7ddfbfSEd Maste if (frame->HasDebugInformation ()) 1211ac7ddfbfSEd Maste { 1212ac7ddfbfSEd Maste // Finally we got here... Translate the given line number to a bunch of addresses: 1213ac7ddfbfSEd Maste SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit)); 12144bb0738eSEd Maste LineTable *line_table = nullptr; 1215ac7ddfbfSEd Maste if (sc.comp_unit) 1216ac7ddfbfSEd Maste line_table = sc.comp_unit->GetLineTable(); 1217ac7ddfbfSEd Maste 12184bb0738eSEd Maste if (line_table == nullptr) 1219ac7ddfbfSEd Maste { 1220ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n", 1221ac7ddfbfSEd Maste m_options.m_frame_idx, m_options.m_thread_idx); 1222ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1223ac7ddfbfSEd Maste return false; 1224ac7ddfbfSEd Maste } 1225ac7ddfbfSEd Maste 1226ac7ddfbfSEd Maste LineEntry function_start; 1227ac7ddfbfSEd Maste uint32_t index_ptr = 0, end_ptr; 1228ac7ddfbfSEd Maste std::vector<addr_t> address_list; 1229ac7ddfbfSEd Maste 1230ac7ddfbfSEd Maste // Find the beginning & end index of the 1231ac7ddfbfSEd Maste AddressRange fun_addr_range = sc.function->GetAddressRange(); 1232ac7ddfbfSEd Maste Address fun_start_addr = fun_addr_range.GetBaseAddress(); 1233ac7ddfbfSEd Maste line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr); 1234ac7ddfbfSEd Maste 1235ac7ddfbfSEd Maste Address fun_end_addr(fun_start_addr.GetSection(), 1236ac7ddfbfSEd Maste fun_start_addr.GetOffset() + fun_addr_range.GetByteSize()); 1237ac7ddfbfSEd Maste 1238ac7ddfbfSEd Maste bool all_in_function = true; 1239ac7ddfbfSEd Maste 12401c3bbb01SEd Maste line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr); 12411c3bbb01SEd Maste 12421c3bbb01SEd Maste for (uint32_t line_number : line_numbers) 12431c3bbb01SEd Maste { 12441c3bbb01SEd Maste uint32_t start_idx_ptr = index_ptr; 12451c3bbb01SEd Maste while (start_idx_ptr <= end_ptr) 1246ac7ddfbfSEd Maste { 1247ac7ddfbfSEd Maste LineEntry line_entry; 1248ac7ddfbfSEd Maste const bool exact = false; 12491c3bbb01SEd Maste start_idx_ptr = sc.comp_unit->FindLineEntry(start_idx_ptr, line_number, sc.comp_unit, exact, &line_entry); 12501c3bbb01SEd Maste if (start_idx_ptr == UINT32_MAX) 1251ac7ddfbfSEd Maste break; 1252ac7ddfbfSEd Maste 1253ac7ddfbfSEd Maste addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target); 1254ac7ddfbfSEd Maste if (address != LLDB_INVALID_ADDRESS) 1255ac7ddfbfSEd Maste { 1256ac7ddfbfSEd Maste if (fun_addr_range.ContainsLoadAddress (address, target)) 1257ac7ddfbfSEd Maste address_list.push_back (address); 1258ac7ddfbfSEd Maste else 1259ac7ddfbfSEd Maste all_in_function = false; 1260ac7ddfbfSEd Maste } 12611c3bbb01SEd Maste start_idx_ptr++; 12621c3bbb01SEd Maste } 12631c3bbb01SEd Maste } 12641c3bbb01SEd Maste 12651c3bbb01SEd Maste for (lldb::addr_t address : m_options.m_until_addrs) 12661c3bbb01SEd Maste { 12671c3bbb01SEd Maste if (fun_addr_range.ContainsLoadAddress (address, target)) 12681c3bbb01SEd Maste address_list.push_back (address); 12691c3bbb01SEd Maste else 12701c3bbb01SEd Maste all_in_function = false; 1271ac7ddfbfSEd Maste } 1272ac7ddfbfSEd Maste 12734bb0738eSEd Maste if (address_list.empty()) 1274ac7ddfbfSEd Maste { 1275ac7ddfbfSEd Maste if (all_in_function) 1276ac7ddfbfSEd Maste result.AppendErrorWithFormat ("No line entries matching until target.\n"); 1277ac7ddfbfSEd Maste else 1278ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Until target outside of the current function.\n"); 1279ac7ddfbfSEd Maste 1280ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1281ac7ddfbfSEd Maste return false; 1282ac7ddfbfSEd Maste } 1283ac7ddfbfSEd Maste 1284ac7ddfbfSEd Maste new_plan_sp = thread->QueueThreadPlanForStepUntil (abort_other_plans, 1285ac7ddfbfSEd Maste &address_list.front(), 1286ac7ddfbfSEd Maste address_list.size(), 1287ac7ddfbfSEd Maste m_options.m_stop_others, 1288ac7ddfbfSEd Maste m_options.m_frame_idx); 1289ac7ddfbfSEd Maste // User level plans should be master plans so they can be interrupted (e.g. by hitting a breakpoint) 1290ac7ddfbfSEd Maste // and other plans executed by the user (stepping around the breakpoint) and then a "continue" 1291ac7ddfbfSEd Maste // will resume the original plan. 1292ac7ddfbfSEd Maste new_plan_sp->SetIsMasterPlan (true); 1293ac7ddfbfSEd Maste new_plan_sp->SetOkayToDiscard(false); 1294ac7ddfbfSEd Maste } 1295ac7ddfbfSEd Maste else 1296ac7ddfbfSEd Maste { 1297ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", 1298ac7ddfbfSEd Maste m_options.m_frame_idx, 1299ac7ddfbfSEd Maste m_options.m_thread_idx); 1300ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1301ac7ddfbfSEd Maste return false; 1302ac7ddfbfSEd Maste } 1303ac7ddfbfSEd Maste 1304ac7ddfbfSEd Maste process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx); 13057aa51b79SEd Maste 13067aa51b79SEd Maste StreamString stream; 13077aa51b79SEd Maste Error error; 13087aa51b79SEd Maste if (synchronous_execution) 13097aa51b79SEd Maste error = process->ResumeSynchronous (&stream); 13107aa51b79SEd Maste else 13117aa51b79SEd Maste error = process->Resume (); 13127aa51b79SEd Maste 1313ac7ddfbfSEd Maste if (error.Success()) 1314ac7ddfbfSEd Maste { 1315ac7ddfbfSEd Maste result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); 1316ac7ddfbfSEd Maste if (synchronous_execution) 1317ac7ddfbfSEd Maste { 13187aa51b79SEd Maste // If any state changed events had anything to say, add that to the result 13197aa51b79SEd Maste if (stream.GetData()) 13207aa51b79SEd Maste result.AppendMessage(stream.GetData()); 1321ac7ddfbfSEd Maste 1322ac7ddfbfSEd Maste result.SetDidChangeProcessState (true); 1323ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishNoResult); 1324ac7ddfbfSEd Maste } 1325ac7ddfbfSEd Maste else 1326ac7ddfbfSEd Maste { 1327ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessContinuingNoResult); 1328ac7ddfbfSEd Maste } 1329ac7ddfbfSEd Maste } 1330ac7ddfbfSEd Maste else 1331ac7ddfbfSEd Maste { 1332ac7ddfbfSEd Maste result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 1333ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1334ac7ddfbfSEd Maste } 1335ac7ddfbfSEd Maste 1336ac7ddfbfSEd Maste } 1337ac7ddfbfSEd Maste return result.Succeeded(); 1338ac7ddfbfSEd Maste } 1339ac7ddfbfSEd Maste 1340ac7ddfbfSEd Maste CommandOptions m_options; 1341ac7ddfbfSEd Maste }; 1342ac7ddfbfSEd Maste 1343ac7ddfbfSEd Maste OptionDefinition 1344ac7ddfbfSEd Maste CommandObjectThreadUntil::CommandOptions::g_option_table[] = 1345ac7ddfbfSEd Maste { 13464bb0738eSEd Maste { LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"}, 13474bb0738eSEd Maste { LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"}, 13484bb0738eSEd Maste { LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, nullptr, g_duo_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping this one"}, 13494bb0738eSEd Maste { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Run until we reach the specified address, or leave the function - can be specified multiple times."}, 13504bb0738eSEd Maste { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 1351ac7ddfbfSEd Maste }; 1352ac7ddfbfSEd Maste 1353ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1354ac7ddfbfSEd Maste // CommandObjectThreadSelect 1355ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1356ac7ddfbfSEd Maste 1357ac7ddfbfSEd Maste class CommandObjectThreadSelect : public CommandObjectParsed 1358ac7ddfbfSEd Maste { 1359ac7ddfbfSEd Maste public: 13604bb0738eSEd Maste CommandObjectThreadSelect(CommandInterpreter &interpreter) 13614bb0738eSEd Maste : CommandObjectParsed(interpreter, "thread select", "Change the currently selected thread.", nullptr, 13624bb0738eSEd Maste eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | 13631c3bbb01SEd Maste eCommandProcessMustBePaused) 1364ac7ddfbfSEd Maste { 1365ac7ddfbfSEd Maste CommandArgumentEntry arg; 1366ac7ddfbfSEd Maste CommandArgumentData thread_idx_arg; 1367ac7ddfbfSEd Maste 1368ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 1369ac7ddfbfSEd Maste thread_idx_arg.arg_type = eArgTypeThreadIndex; 1370ac7ddfbfSEd Maste thread_idx_arg.arg_repetition = eArgRepeatPlain; 1371ac7ddfbfSEd Maste 1372ac7ddfbfSEd Maste // There is only one variant this argument could be; put it into the argument entry. 1373ac7ddfbfSEd Maste arg.push_back (thread_idx_arg); 1374ac7ddfbfSEd Maste 1375ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 1376ac7ddfbfSEd Maste m_arguments.push_back (arg); 1377ac7ddfbfSEd Maste } 1378ac7ddfbfSEd Maste 13794bb0738eSEd Maste ~CommandObjectThreadSelect() override = default; 1380ac7ddfbfSEd Maste 1381ac7ddfbfSEd Maste protected: 13829f2f44ceSEd Maste bool 13839f2f44ceSEd Maste DoExecute (Args& command, CommandReturnObject &result) override 1384ac7ddfbfSEd Maste { 1385ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr(); 13864bb0738eSEd Maste if (process == nullptr) 1387ac7ddfbfSEd Maste { 1388ac7ddfbfSEd Maste result.AppendError ("no process"); 1389ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1390ac7ddfbfSEd Maste return false; 1391ac7ddfbfSEd Maste } 1392ac7ddfbfSEd Maste else if (command.GetArgumentCount() != 1) 1393ac7ddfbfSEd Maste { 1394ac7ddfbfSEd Maste result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1395ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1396ac7ddfbfSEd Maste return false; 1397ac7ddfbfSEd Maste } 1398ac7ddfbfSEd Maste 13991c3bbb01SEd Maste uint32_t index_id = StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0); 1400ac7ddfbfSEd Maste 1401ac7ddfbfSEd Maste Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get(); 14024bb0738eSEd Maste if (new_thread == nullptr) 1403ac7ddfbfSEd Maste { 1404ac7ddfbfSEd Maste result.AppendErrorWithFormat ("invalid thread #%s.\n", command.GetArgumentAtIndex(0)); 1405ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1406ac7ddfbfSEd Maste return false; 1407ac7ddfbfSEd Maste } 1408ac7ddfbfSEd Maste 1409ac7ddfbfSEd Maste process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true); 1410ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishNoResult); 1411ac7ddfbfSEd Maste 1412ac7ddfbfSEd Maste return result.Succeeded(); 1413ac7ddfbfSEd Maste } 1414ac7ddfbfSEd Maste }; 1415ac7ddfbfSEd Maste 1416ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1417ac7ddfbfSEd Maste // CommandObjectThreadList 1418ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1419ac7ddfbfSEd Maste 1420ac7ddfbfSEd Maste class CommandObjectThreadList : public CommandObjectParsed 1421ac7ddfbfSEd Maste { 1422ac7ddfbfSEd Maste public: 14234bb0738eSEd Maste CommandObjectThreadList(CommandInterpreter &interpreter) 14244bb0738eSEd Maste : CommandObjectParsed(interpreter, "thread list", 14254bb0738eSEd Maste "Show a summary of each thread in the current target process.", "thread list", 14264bb0738eSEd Maste eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | 14271c3bbb01SEd Maste eCommandProcessMustBePaused) 1428ac7ddfbfSEd Maste { 1429ac7ddfbfSEd Maste } 1430ac7ddfbfSEd Maste 14314bb0738eSEd Maste ~CommandObjectThreadList() override = default; 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 class CommandOptions : public Options 14620127ef0fSEd Maste { 14630127ef0fSEd Maste public: 14640127ef0fSEd Maste CommandOptions (CommandInterpreter &interpreter) : 14650127ef0fSEd Maste Options (interpreter) 14660127ef0fSEd Maste { 14670127ef0fSEd Maste OptionParsingStarting (); 14680127ef0fSEd Maste } 14690127ef0fSEd Maste 14704bb0738eSEd Maste ~CommandOptions() override = default; 14714bb0738eSEd Maste 14720127ef0fSEd Maste void 14739f2f44ceSEd Maste OptionParsingStarting () override 14740127ef0fSEd Maste { 14757aa51b79SEd Maste m_json_thread = false; 14767aa51b79SEd Maste m_json_stopinfo = false; 14770127ef0fSEd Maste } 14780127ef0fSEd Maste 14799f2f44ceSEd Maste Error 14809f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 14810127ef0fSEd Maste { 14820127ef0fSEd Maste const int short_option = m_getopt_table[option_idx].val; 14830127ef0fSEd Maste Error error; 14840127ef0fSEd Maste 14850127ef0fSEd Maste switch (short_option) 14860127ef0fSEd Maste { 14870127ef0fSEd Maste case 'j': 14887aa51b79SEd Maste m_json_thread = true; 14897aa51b79SEd Maste break; 14907aa51b79SEd Maste 14917aa51b79SEd Maste case 's': 14927aa51b79SEd Maste m_json_stopinfo = true; 14930127ef0fSEd Maste break; 14940127ef0fSEd Maste 14950127ef0fSEd Maste default: 14960127ef0fSEd Maste return Error("invalid short option character '%c'", short_option); 14970127ef0fSEd Maste } 14980127ef0fSEd Maste return error; 14990127ef0fSEd Maste } 15000127ef0fSEd Maste 15010127ef0fSEd Maste const OptionDefinition* 15029f2f44ceSEd Maste GetDefinitions () override 15030127ef0fSEd Maste { 15040127ef0fSEd Maste return g_option_table; 15050127ef0fSEd Maste } 15060127ef0fSEd Maste 15077aa51b79SEd Maste bool m_json_thread; 15087aa51b79SEd Maste bool m_json_stopinfo; 15090127ef0fSEd Maste 15100127ef0fSEd Maste static OptionDefinition g_option_table[]; 15110127ef0fSEd Maste }; 15120127ef0fSEd Maste 15134bb0738eSEd Maste CommandObjectThreadInfo(CommandInterpreter &interpreter) 15144bb0738eSEd Maste : CommandObjectIterateOverThreads( 15154bb0738eSEd Maste interpreter, "thread info", 15164bb0738eSEd Maste "Show an extended summary of one or more threads. Defaults to the current thread.", "thread info", 15174bb0738eSEd Maste eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | 15184bb0738eSEd Maste eCommandProcessMustBePaused), 15194bb0738eSEd Maste m_options(interpreter) 15204bb0738eSEd Maste { 15214bb0738eSEd Maste m_add_return = false; 15224bb0738eSEd Maste } 15234bb0738eSEd Maste 15244bb0738eSEd Maste ~CommandObjectThreadInfo() override = default; 15254bb0738eSEd Maste 15260127ef0fSEd Maste Options * 15279f2f44ceSEd Maste GetOptions () override 15280127ef0fSEd Maste { 15290127ef0fSEd Maste return &m_options; 15300127ef0fSEd Maste } 15310127ef0fSEd Maste 15324bb0738eSEd Maste bool 15334bb0738eSEd Maste HandleOneThread (lldb::tid_t tid, CommandReturnObject &result) override 15340127ef0fSEd Maste { 15354bb0738eSEd Maste ThreadSP thread_sp = m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); 15364bb0738eSEd Maste if (!thread_sp) 15374bb0738eSEd Maste { 15384bb0738eSEd Maste result.AppendErrorWithFormat ("thread no longer exists: 0x%" PRIx64 "\n", tid); 15394bb0738eSEd Maste result.SetStatus (eReturnStatusFailed); 15404bb0738eSEd Maste return false; 15410127ef0fSEd Maste } 15420127ef0fSEd Maste 15434bb0738eSEd Maste Thread *thread = thread_sp.get(); 15444bb0738eSEd Maste 15450127ef0fSEd Maste Stream &strm = result.GetOutputStream(); 15464bb0738eSEd Maste if (!thread->GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo)) 15470127ef0fSEd Maste { 15484bb0738eSEd 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 OptionDefinition 15590127ef0fSEd Maste CommandObjectThreadInfo::CommandOptions::g_option_table[] = 15600127ef0fSEd Maste { 15614bb0738eSEd Maste { LLDB_OPT_SET_ALL, false, "json",'j', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the thread info in JSON format."}, 15624bb0738eSEd Maste { LLDB_OPT_SET_ALL, false, "stop-info",'s', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the extended stop info in JSON format."}, 15630127ef0fSEd Maste 15644bb0738eSEd Maste { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 15650127ef0fSEd Maste }; 15660127ef0fSEd Maste 15670127ef0fSEd Maste //------------------------------------------------------------------------- 1568ac7ddfbfSEd Maste // CommandObjectThreadReturn 1569ac7ddfbfSEd Maste //------------------------------------------------------------------------- 1570ac7ddfbfSEd Maste 1571ac7ddfbfSEd Maste class CommandObjectThreadReturn : public CommandObjectRaw 1572ac7ddfbfSEd Maste { 1573ac7ddfbfSEd Maste public: 1574ac7ddfbfSEd Maste class CommandOptions : public Options 1575ac7ddfbfSEd Maste { 1576ac7ddfbfSEd Maste public: 1577ac7ddfbfSEd Maste CommandOptions (CommandInterpreter &interpreter) : 1578ac7ddfbfSEd Maste Options (interpreter), 1579ac7ddfbfSEd Maste m_from_expression (false) 1580ac7ddfbfSEd Maste { 1581ac7ddfbfSEd Maste // Keep default values of all options in one place: OptionParsingStarting () 1582ac7ddfbfSEd Maste OptionParsingStarting (); 1583ac7ddfbfSEd Maste } 1584ac7ddfbfSEd Maste 15854bb0738eSEd Maste ~CommandOptions() override = default; 1586ac7ddfbfSEd Maste 15879f2f44ceSEd Maste Error 15889f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 1589ac7ddfbfSEd Maste { 1590ac7ddfbfSEd Maste Error error; 1591ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val; 1592ac7ddfbfSEd Maste 1593ac7ddfbfSEd Maste switch (short_option) 1594ac7ddfbfSEd Maste { 1595ac7ddfbfSEd Maste case 'x': 1596ac7ddfbfSEd Maste { 1597ac7ddfbfSEd Maste bool success; 1598ac7ddfbfSEd Maste bool tmp_value = Args::StringToBoolean (option_arg, false, &success); 1599ac7ddfbfSEd Maste if (success) 1600ac7ddfbfSEd Maste m_from_expression = tmp_value; 1601ac7ddfbfSEd Maste else 1602ac7ddfbfSEd Maste { 1603ac7ddfbfSEd Maste error.SetErrorStringWithFormat ("invalid boolean value '%s' for 'x' option", option_arg); 1604ac7ddfbfSEd Maste } 1605ac7ddfbfSEd Maste } 1606ac7ddfbfSEd Maste break; 1607ac7ddfbfSEd Maste default: 1608ac7ddfbfSEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1609ac7ddfbfSEd Maste break; 1610ac7ddfbfSEd Maste } 1611ac7ddfbfSEd Maste return error; 1612ac7ddfbfSEd Maste } 1613ac7ddfbfSEd Maste 1614ac7ddfbfSEd Maste void 16159f2f44ceSEd Maste OptionParsingStarting () override 1616ac7ddfbfSEd Maste { 1617ac7ddfbfSEd Maste m_from_expression = false; 1618ac7ddfbfSEd Maste } 1619ac7ddfbfSEd Maste 1620ac7ddfbfSEd Maste const OptionDefinition* 16219f2f44ceSEd Maste GetDefinitions () override 1622ac7ddfbfSEd Maste { 1623ac7ddfbfSEd Maste return g_option_table; 1624ac7ddfbfSEd Maste } 1625ac7ddfbfSEd Maste 1626ac7ddfbfSEd Maste bool m_from_expression; 1627ac7ddfbfSEd Maste 1628ac7ddfbfSEd Maste // Options table: Required for subclasses of Options. 1629ac7ddfbfSEd Maste 1630ac7ddfbfSEd Maste static OptionDefinition g_option_table[]; 1631ac7ddfbfSEd Maste 1632ac7ddfbfSEd Maste // Instance variables to hold the values for command options. 1633ac7ddfbfSEd Maste }; 1634ac7ddfbfSEd Maste 16354bb0738eSEd Maste CommandObjectThreadReturn(CommandInterpreter &interpreter) 16364bb0738eSEd Maste : CommandObjectRaw(interpreter, "thread return", 16374bb0738eSEd Maste "Prematurely return from a stack frame, short-circuiting execution of newer frames " 16384bb0738eSEd Maste "and optionally yielding a specified value. Defaults to the exiting the current stack " 16394bb0738eSEd Maste "frame.", 16404bb0738eSEd Maste "thread return", eCommandRequiresFrame | eCommandTryTargetAPILock | 16414bb0738eSEd Maste eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 1642ac7ddfbfSEd Maste m_options(interpreter) 1643ac7ddfbfSEd Maste { 1644ac7ddfbfSEd Maste CommandArgumentEntry arg; 1645ac7ddfbfSEd Maste CommandArgumentData expression_arg; 1646ac7ddfbfSEd Maste 1647ac7ddfbfSEd Maste // Define the first (and only) variant of this arg. 1648ac7ddfbfSEd Maste expression_arg.arg_type = eArgTypeExpression; 1649ac7ddfbfSEd Maste expression_arg.arg_repetition = eArgRepeatOptional; 1650ac7ddfbfSEd Maste 1651ac7ddfbfSEd Maste // There is only one variant this argument could be; put it into the argument entry. 1652ac7ddfbfSEd Maste arg.push_back (expression_arg); 1653ac7ddfbfSEd Maste 1654ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector. 1655ac7ddfbfSEd Maste m_arguments.push_back (arg); 1656ac7ddfbfSEd Maste } 1657ac7ddfbfSEd Maste 16584bb0738eSEd Maste ~CommandObjectThreadReturn() override = default; 16594bb0738eSEd Maste 16604bb0738eSEd Maste Options * 16614bb0738eSEd Maste GetOptions() override 1662ac7ddfbfSEd Maste { 16634bb0738eSEd Maste return &m_options; 1664ac7ddfbfSEd Maste } 1665ac7ddfbfSEd Maste 1666ac7ddfbfSEd Maste protected: 16679f2f44ceSEd Maste bool 16689f2f44ceSEd Maste DoExecute (const char *command, CommandReturnObject &result) override 1669ac7ddfbfSEd Maste { 1670ac7ddfbfSEd Maste // I am going to handle this by hand, because I don't want you to have to say: 1671ac7ddfbfSEd Maste // "thread return -- -5". 1672ac7ddfbfSEd Maste if (command[0] == '-' && command[1] == 'x') 1673ac7ddfbfSEd Maste { 1674ac7ddfbfSEd Maste if (command && command[2] != '\0') 1675ac7ddfbfSEd Maste result.AppendWarning("Return values ignored when returning from user called expressions"); 1676ac7ddfbfSEd Maste 1677ac7ddfbfSEd Maste Thread *thread = m_exe_ctx.GetThreadPtr(); 1678ac7ddfbfSEd Maste Error error; 1679ac7ddfbfSEd Maste error = thread->UnwindInnermostExpression(); 1680ac7ddfbfSEd Maste if (!error.Success()) 1681ac7ddfbfSEd Maste { 1682ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Unwinding expression failed - %s.", error.AsCString()); 1683ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1684ac7ddfbfSEd Maste } 1685ac7ddfbfSEd Maste else 1686ac7ddfbfSEd Maste { 1687ac7ddfbfSEd Maste bool success = thread->SetSelectedFrameByIndexNoisily (0, result.GetOutputStream()); 1688ac7ddfbfSEd Maste if (success) 1689ac7ddfbfSEd Maste { 1690ac7ddfbfSEd Maste m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ()); 1691ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 1692ac7ddfbfSEd Maste } 1693ac7ddfbfSEd Maste else 1694ac7ddfbfSEd Maste { 1695ac7ddfbfSEd Maste result.AppendErrorWithFormat ("Could not select 0th frame after unwinding expression."); 1696ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1697ac7ddfbfSEd Maste } 1698ac7ddfbfSEd Maste } 1699ac7ddfbfSEd Maste return result.Succeeded(); 1700ac7ddfbfSEd Maste } 1701ac7ddfbfSEd Maste 1702ac7ddfbfSEd Maste ValueObjectSP return_valobj_sp; 1703ac7ddfbfSEd Maste 1704ac7ddfbfSEd Maste StackFrameSP frame_sp = m_exe_ctx.GetFrameSP(); 1705ac7ddfbfSEd Maste uint32_t frame_idx = frame_sp->GetFrameIndex(); 1706ac7ddfbfSEd Maste 1707ac7ddfbfSEd Maste if (frame_sp->IsInlined()) 1708ac7ddfbfSEd Maste { 1709ac7ddfbfSEd Maste result.AppendError("Don't know how to return from inlined frames."); 1710ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1711ac7ddfbfSEd Maste return false; 1712ac7ddfbfSEd Maste } 1713ac7ddfbfSEd Maste 1714ac7ddfbfSEd Maste if (command && command[0] != '\0') 1715ac7ddfbfSEd Maste { 1716ac7ddfbfSEd Maste Target *target = m_exe_ctx.GetTargetPtr(); 1717ac7ddfbfSEd Maste EvaluateExpressionOptions options; 1718ac7ddfbfSEd Maste 1719ac7ddfbfSEd Maste options.SetUnwindOnError(true); 1720ac7ddfbfSEd Maste options.SetUseDynamic(eNoDynamicValues); 1721ac7ddfbfSEd Maste 17220127ef0fSEd Maste ExpressionResults exe_results = eExpressionSetupError; 1723ac7ddfbfSEd Maste exe_results = target->EvaluateExpression (command, 1724ac7ddfbfSEd Maste frame_sp.get(), 1725ac7ddfbfSEd Maste return_valobj_sp, 1726ac7ddfbfSEd Maste options); 17270127ef0fSEd Maste if (exe_results != eExpressionCompleted) 1728ac7ddfbfSEd Maste { 1729ac7ddfbfSEd Maste if (return_valobj_sp) 1730ac7ddfbfSEd Maste result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString()); 1731ac7ddfbfSEd Maste else 1732ac7ddfbfSEd Maste result.AppendErrorWithFormat("Unknown error evaluating result expression."); 1733ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1734ac7ddfbfSEd Maste return false; 1735ac7ddfbfSEd Maste } 1736ac7ddfbfSEd Maste } 1737ac7ddfbfSEd Maste 1738ac7ddfbfSEd Maste Error error; 1739ac7ddfbfSEd Maste ThreadSP thread_sp = m_exe_ctx.GetThreadSP(); 1740ac7ddfbfSEd Maste const bool broadcast = true; 1741ac7ddfbfSEd Maste error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast); 1742ac7ddfbfSEd Maste if (!error.Success()) 1743ac7ddfbfSEd Maste { 1744ac7ddfbfSEd Maste result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString()); 1745ac7ddfbfSEd Maste result.SetStatus (eReturnStatusFailed); 1746ac7ddfbfSEd Maste return false; 1747ac7ddfbfSEd Maste } 1748ac7ddfbfSEd Maste 1749ac7ddfbfSEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 1750ac7ddfbfSEd Maste return true; 1751ac7ddfbfSEd Maste } 1752ac7ddfbfSEd Maste 1753ac7ddfbfSEd Maste CommandOptions m_options; 1754ac7ddfbfSEd Maste }; 17554bb0738eSEd Maste 1756ac7ddfbfSEd Maste OptionDefinition 1757ac7ddfbfSEd Maste CommandObjectThreadReturn::CommandOptions::g_option_table[] = 1758ac7ddfbfSEd Maste { 17594bb0738eSEd Maste { LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Return from the innermost expression evaluation."}, 17604bb0738eSEd Maste { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 176135617911SEd Maste }; 176235617911SEd Maste 176335617911SEd Maste //------------------------------------------------------------------------- 176435617911SEd Maste // CommandObjectThreadJump 176535617911SEd Maste //------------------------------------------------------------------------- 176635617911SEd Maste 176735617911SEd Maste class CommandObjectThreadJump : public CommandObjectParsed 176835617911SEd Maste { 176935617911SEd Maste public: 177035617911SEd Maste class CommandOptions : public Options 177135617911SEd Maste { 177235617911SEd Maste public: 177335617911SEd Maste CommandOptions (CommandInterpreter &interpreter) : 177435617911SEd Maste Options (interpreter) 177535617911SEd Maste { 177635617911SEd Maste OptionParsingStarting (); 177735617911SEd Maste } 177835617911SEd Maste 17794bb0738eSEd Maste ~CommandOptions() override = default; 17804bb0738eSEd Maste 178135617911SEd Maste void 17829f2f44ceSEd Maste OptionParsingStarting () override 178335617911SEd Maste { 178435617911SEd Maste m_filenames.Clear(); 178535617911SEd Maste m_line_num = 0; 178635617911SEd Maste m_line_offset = 0; 178735617911SEd Maste m_load_addr = LLDB_INVALID_ADDRESS; 178835617911SEd Maste m_force = false; 178935617911SEd Maste } 179035617911SEd Maste 17919f2f44ceSEd Maste Error 17929f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 179335617911SEd Maste { 179435617911SEd Maste bool success; 179535617911SEd Maste const int short_option = m_getopt_table[option_idx].val; 179635617911SEd Maste Error error; 179735617911SEd Maste 179835617911SEd Maste switch (short_option) 179935617911SEd Maste { 180035617911SEd Maste case 'f': 180135617911SEd Maste m_filenames.AppendIfUnique (FileSpec(option_arg, false)); 180235617911SEd Maste if (m_filenames.GetSize() > 1) 180335617911SEd Maste return Error("only one source file expected."); 180435617911SEd Maste break; 180535617911SEd Maste case 'l': 18061c3bbb01SEd Maste m_line_num = StringConvert::ToUInt32 (option_arg, 0, 0, &success); 180735617911SEd Maste if (!success || m_line_num == 0) 180835617911SEd Maste return Error("invalid line number: '%s'.", option_arg); 180935617911SEd Maste break; 181035617911SEd Maste case 'b': 18111c3bbb01SEd Maste m_line_offset = StringConvert::ToSInt32 (option_arg, 0, 0, &success); 181235617911SEd Maste if (!success) 181335617911SEd Maste return Error("invalid line offset: '%s'.", option_arg); 181435617911SEd Maste break; 181535617911SEd Maste case 'a': 181635617911SEd Maste { 181735617911SEd Maste ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 181835617911SEd Maste m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); 181935617911SEd Maste } 182035617911SEd Maste break; 182135617911SEd Maste case 'r': 182235617911SEd Maste m_force = true; 182335617911SEd Maste break; 182435617911SEd Maste default: 182535617911SEd Maste return Error("invalid short option character '%c'", short_option); 182635617911SEd Maste } 182735617911SEd Maste return error; 182835617911SEd Maste } 182935617911SEd Maste 183035617911SEd Maste const OptionDefinition* 18319f2f44ceSEd Maste GetDefinitions () override 183235617911SEd Maste { 183335617911SEd Maste return g_option_table; 183435617911SEd Maste } 183535617911SEd Maste 183635617911SEd Maste FileSpecList m_filenames; 183735617911SEd Maste uint32_t m_line_num; 183835617911SEd Maste int32_t m_line_offset; 183935617911SEd Maste lldb::addr_t m_load_addr; 184035617911SEd Maste bool m_force; 184135617911SEd Maste 184235617911SEd Maste static OptionDefinition g_option_table[]; 184335617911SEd Maste }; 184435617911SEd Maste 184535617911SEd Maste CommandObjectThreadJump (CommandInterpreter &interpreter) : 184635617911SEd Maste CommandObjectParsed (interpreter, 184735617911SEd Maste "thread jump", 184835617911SEd Maste "Sets the program counter to a new address.", 184935617911SEd Maste "thread jump", 18501c3bbb01SEd Maste eCommandRequiresFrame | 18511c3bbb01SEd Maste eCommandTryTargetAPILock | 18521c3bbb01SEd Maste eCommandProcessMustBeLaunched | 18531c3bbb01SEd Maste eCommandProcessMustBePaused ), 185435617911SEd Maste m_options (interpreter) 185535617911SEd Maste { 185635617911SEd Maste } 185735617911SEd Maste 18584bb0738eSEd Maste ~CommandObjectThreadJump() override = default; 18594bb0738eSEd Maste 18604bb0738eSEd Maste Options * 18614bb0738eSEd Maste GetOptions() override 186235617911SEd Maste { 18634bb0738eSEd Maste return &m_options; 186435617911SEd Maste } 186535617911SEd Maste 186635617911SEd Maste protected: 18679f2f44ceSEd Maste bool DoExecute (Args& args, CommandReturnObject &result) override 186835617911SEd Maste { 186935617911SEd Maste RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); 187035617911SEd Maste StackFrame *frame = m_exe_ctx.GetFramePtr(); 187135617911SEd Maste Thread *thread = m_exe_ctx.GetThreadPtr(); 187235617911SEd Maste Target *target = m_exe_ctx.GetTargetPtr(); 187335617911SEd Maste const SymbolContext &sym_ctx = frame->GetSymbolContext (eSymbolContextLineEntry); 187435617911SEd Maste 187535617911SEd Maste if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 187635617911SEd Maste { 187735617911SEd Maste // Use this address directly. 187835617911SEd Maste Address dest = Address(m_options.m_load_addr); 187935617911SEd Maste 188035617911SEd Maste lldb::addr_t callAddr = dest.GetCallableLoadAddress (target); 188135617911SEd Maste if (callAddr == LLDB_INVALID_ADDRESS) 188235617911SEd Maste { 188335617911SEd Maste result.AppendErrorWithFormat ("Invalid destination address."); 188435617911SEd Maste result.SetStatus (eReturnStatusFailed); 188535617911SEd Maste return false; 188635617911SEd Maste } 188735617911SEd Maste 188835617911SEd Maste if (!reg_ctx->SetPC (callAddr)) 188935617911SEd Maste { 189035617911SEd Maste result.AppendErrorWithFormat ("Error changing PC value for thread %d.", thread->GetIndexID()); 189135617911SEd Maste result.SetStatus (eReturnStatusFailed); 189235617911SEd Maste return false; 189335617911SEd Maste } 189435617911SEd Maste } 189535617911SEd Maste else 189635617911SEd Maste { 189735617911SEd Maste // Pick either the absolute line, or work out a relative one. 189835617911SEd Maste int32_t line = (int32_t)m_options.m_line_num; 189935617911SEd Maste if (line == 0) 190035617911SEd Maste line = sym_ctx.line_entry.line + m_options.m_line_offset; 190135617911SEd Maste 190235617911SEd Maste // Try the current file, but override if asked. 190335617911SEd Maste FileSpec file = sym_ctx.line_entry.file; 190435617911SEd Maste if (m_options.m_filenames.GetSize() == 1) 190535617911SEd Maste file = m_options.m_filenames.GetFileSpecAtIndex(0); 190635617911SEd Maste 190735617911SEd Maste if (!file) 190835617911SEd Maste { 190935617911SEd Maste result.AppendErrorWithFormat ("No source file available for the current location."); 191035617911SEd Maste result.SetStatus (eReturnStatusFailed); 191135617911SEd Maste return false; 191235617911SEd Maste } 191335617911SEd Maste 191435617911SEd Maste std::string warnings; 191535617911SEd Maste Error err = thread->JumpToLine (file, line, m_options.m_force, &warnings); 191635617911SEd Maste 191735617911SEd Maste if (err.Fail()) 191835617911SEd Maste { 191935617911SEd Maste result.SetError (err); 192035617911SEd Maste return false; 192135617911SEd Maste } 192235617911SEd Maste 192335617911SEd Maste if (!warnings.empty()) 192435617911SEd Maste result.AppendWarning (warnings.c_str()); 192535617911SEd Maste } 192635617911SEd Maste 192735617911SEd Maste result.SetStatus (eReturnStatusSuccessFinishResult); 192835617911SEd Maste return true; 192935617911SEd Maste } 193035617911SEd Maste 193135617911SEd Maste CommandOptions m_options; 193235617911SEd Maste }; 19334bb0738eSEd Maste 193435617911SEd Maste OptionDefinition 193535617911SEd Maste CommandObjectThreadJump::CommandOptions::g_option_table[] = 193635617911SEd Maste { 19374bb0738eSEd Maste { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, 193835617911SEd Maste "Specifies the source file to jump to."}, 193935617911SEd Maste 19404bb0738eSEd Maste { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, 194135617911SEd Maste "Specifies the line number to jump to."}, 194235617911SEd Maste 19434bb0738eSEd Maste { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, 194435617911SEd Maste "Jumps by a relative line offset from the current line."}, 194535617911SEd Maste 19464bb0738eSEd Maste { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, 194735617911SEd Maste "Jumps to a specific address."}, 194835617911SEd Maste 194935617911SEd Maste { LLDB_OPT_SET_1| 195035617911SEd Maste LLDB_OPT_SET_2| 19514bb0738eSEd Maste LLDB_OPT_SET_3, false, "force",'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,"Allows the PC to leave the current function."}, 195235617911SEd Maste 19534bb0738eSEd Maste { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 1954ac7ddfbfSEd Maste }; 1955ac7ddfbfSEd Maste 1956ac7ddfbfSEd Maste //------------------------------------------------------------------------- 19577aa51b79SEd Maste // Next are the subcommands of CommandObjectMultiwordThreadPlan 19587aa51b79SEd Maste //------------------------------------------------------------------------- 19597aa51b79SEd Maste 19607aa51b79SEd Maste //------------------------------------------------------------------------- 19617aa51b79SEd Maste // CommandObjectThreadPlanList 19627aa51b79SEd Maste //------------------------------------------------------------------------- 19634bb0738eSEd Maste 19647aa51b79SEd Maste class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads 19657aa51b79SEd Maste { 19667aa51b79SEd Maste public: 19677aa51b79SEd Maste class CommandOptions : public Options 19687aa51b79SEd Maste { 19697aa51b79SEd Maste public: 19707aa51b79SEd Maste CommandOptions (CommandInterpreter &interpreter) : 19717aa51b79SEd Maste Options(interpreter) 19727aa51b79SEd Maste { 19737aa51b79SEd Maste // Keep default values of all options in one place: OptionParsingStarting () 19747aa51b79SEd Maste OptionParsingStarting (); 19757aa51b79SEd Maste } 19767aa51b79SEd Maste 19774bb0738eSEd Maste ~CommandOptions() override = default; 19787aa51b79SEd Maste 19799f2f44ceSEd Maste Error 19809f2f44ceSEd Maste SetOptionValue (uint32_t option_idx, const char *option_arg) override 19817aa51b79SEd Maste { 19827aa51b79SEd Maste Error error; 19837aa51b79SEd Maste const int short_option = m_getopt_table[option_idx].val; 19847aa51b79SEd Maste 19857aa51b79SEd Maste switch (short_option) 19867aa51b79SEd Maste { 19877aa51b79SEd Maste case 'i': 19887aa51b79SEd Maste m_internal = true; 19897aa51b79SEd Maste break; 19907aa51b79SEd Maste case 'v': 19917aa51b79SEd Maste m_verbose = true; 19927aa51b79SEd Maste break; 19937aa51b79SEd Maste default: 19947aa51b79SEd Maste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 19957aa51b79SEd Maste break; 19967aa51b79SEd Maste } 19977aa51b79SEd Maste return error; 19987aa51b79SEd Maste } 19997aa51b79SEd Maste 20007aa51b79SEd Maste void 20019f2f44ceSEd Maste OptionParsingStarting () override 20027aa51b79SEd Maste { 20037aa51b79SEd Maste m_verbose = false; 20047aa51b79SEd Maste m_internal = false; 20057aa51b79SEd Maste } 20067aa51b79SEd Maste 20077aa51b79SEd Maste const OptionDefinition* 20089f2f44ceSEd Maste GetDefinitions () override 20097aa51b79SEd Maste { 20107aa51b79SEd Maste return g_option_table; 20117aa51b79SEd Maste } 20127aa51b79SEd Maste 20137aa51b79SEd Maste // Options table: Required for subclasses of Options. 20147aa51b79SEd Maste 20157aa51b79SEd Maste static OptionDefinition g_option_table[]; 20167aa51b79SEd Maste 20177aa51b79SEd Maste // Instance variables to hold the values for command options. 20187aa51b79SEd Maste bool m_verbose; 20197aa51b79SEd Maste bool m_internal; 20207aa51b79SEd Maste }; 20217aa51b79SEd Maste 20224bb0738eSEd Maste CommandObjectThreadPlanList(CommandInterpreter &interpreter) 20234bb0738eSEd Maste : CommandObjectIterateOverThreads( 20244bb0738eSEd Maste interpreter, "thread plan list", 20257aa51b79SEd Maste "Show thread plans for one or more threads. If no threads are specified, show the " 20264bb0738eSEd Maste "current thread. Use the thread-index \"all\" to see all threads.", 20274bb0738eSEd Maste nullptr, eCommandRequiresProcess | eCommandRequiresThread | eCommandTryTargetAPILock | 20284bb0738eSEd Maste eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 20297aa51b79SEd Maste m_options(interpreter) 20307aa51b79SEd Maste { 20317aa51b79SEd Maste } 20327aa51b79SEd Maste 20334bb0738eSEd Maste ~CommandObjectThreadPlanList() override = default; 20347aa51b79SEd Maste 20359f2f44ceSEd Maste Options * 20369f2f44ceSEd Maste GetOptions () override 20377aa51b79SEd Maste { 20387aa51b79SEd Maste return &m_options; 20397aa51b79SEd Maste } 20407aa51b79SEd Maste 20417aa51b79SEd Maste protected: 20429f2f44ceSEd Maste bool 20434bb0738eSEd Maste HandleOneThread (lldb::tid_t tid, CommandReturnObject &result) override 20447aa51b79SEd Maste { 20454bb0738eSEd Maste ThreadSP thread_sp = m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); 20464bb0738eSEd Maste if (!thread_sp) 20474bb0738eSEd Maste { 20484bb0738eSEd Maste result.AppendErrorWithFormat ("thread no longer exists: 0x%" PRIx64 "\n", tid); 20494bb0738eSEd Maste result.SetStatus (eReturnStatusFailed); 20504bb0738eSEd Maste return false; 20514bb0738eSEd Maste } 20524bb0738eSEd Maste 20534bb0738eSEd Maste Thread *thread = thread_sp.get(); 20544bb0738eSEd Maste 20557aa51b79SEd Maste Stream &strm = result.GetOutputStream(); 20567aa51b79SEd Maste DescriptionLevel desc_level = eDescriptionLevelFull; 20577aa51b79SEd Maste if (m_options.m_verbose) 20587aa51b79SEd Maste desc_level = eDescriptionLevelVerbose; 20597aa51b79SEd Maste 20604bb0738eSEd Maste thread->DumpThreadPlans (&strm, desc_level, m_options.m_internal, true); 20617aa51b79SEd Maste return true; 20627aa51b79SEd Maste } 20634bb0738eSEd Maste 20647aa51b79SEd Maste CommandOptions m_options; 20657aa51b79SEd Maste }; 20667aa51b79SEd Maste 20677aa51b79SEd Maste OptionDefinition 20687aa51b79SEd Maste CommandObjectThreadPlanList::CommandOptions::g_option_table[] = 20697aa51b79SEd Maste { 20704bb0738eSEd Maste { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display more information about the thread plans"}, 20714bb0738eSEd Maste { LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display internal as well as user thread plans"}, 20724bb0738eSEd Maste { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 20737aa51b79SEd Maste }; 20747aa51b79SEd Maste 20757aa51b79SEd Maste class CommandObjectThreadPlanDiscard : public CommandObjectParsed 20767aa51b79SEd Maste { 20777aa51b79SEd Maste public: 20784bb0738eSEd Maste CommandObjectThreadPlanDiscard(CommandInterpreter &interpreter) 20794bb0738eSEd Maste : CommandObjectParsed( 20804bb0738eSEd Maste interpreter, "thread plan discard", 20814bb0738eSEd Maste "Discards thread plans up to and including the specified index (see 'thread plan list'.) " 20824bb0738eSEd Maste "Only user visible plans can be discarded.", 20834bb0738eSEd Maste nullptr, eCommandRequiresProcess | eCommandRequiresThread | eCommandTryTargetAPILock | 20844bb0738eSEd Maste eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) 20857aa51b79SEd Maste { 20867aa51b79SEd Maste CommandArgumentEntry arg; 20877aa51b79SEd Maste CommandArgumentData plan_index_arg; 20887aa51b79SEd Maste 20897aa51b79SEd Maste // Define the first (and only) variant of this arg. 20907aa51b79SEd Maste plan_index_arg.arg_type = eArgTypeUnsignedInteger; 20917aa51b79SEd Maste plan_index_arg.arg_repetition = eArgRepeatPlain; 20927aa51b79SEd Maste 20937aa51b79SEd Maste // There is only one variant this argument could be; put it into the argument entry. 20947aa51b79SEd Maste arg.push_back (plan_index_arg); 20957aa51b79SEd Maste 20967aa51b79SEd Maste // Push the data for the first argument into the m_arguments vector. 20977aa51b79SEd Maste m_arguments.push_back (arg); 20987aa51b79SEd Maste } 20997aa51b79SEd Maste 21004bb0738eSEd Maste ~CommandObjectThreadPlanDiscard() override = default; 21017aa51b79SEd Maste 21027aa51b79SEd Maste bool 21039f2f44ceSEd Maste DoExecute (Args& args, CommandReturnObject &result) override 21047aa51b79SEd Maste { 21057aa51b79SEd Maste Thread *thread = m_exe_ctx.GetThreadPtr(); 21067aa51b79SEd Maste if (args.GetArgumentCount() != 1) 21077aa51b79SEd Maste { 21087aa51b79SEd Maste result.AppendErrorWithFormat("Too many arguments, expected one - the thread plan index - but got %zu.", 21097aa51b79SEd Maste args.GetArgumentCount()); 21107aa51b79SEd Maste result.SetStatus (eReturnStatusFailed); 21117aa51b79SEd Maste return false; 21127aa51b79SEd Maste } 21137aa51b79SEd Maste 21147aa51b79SEd Maste bool success; 21151c3bbb01SEd Maste uint32_t thread_plan_idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success); 21167aa51b79SEd Maste if (!success) 21177aa51b79SEd Maste { 21187aa51b79SEd Maste result.AppendErrorWithFormat("Invalid thread index: \"%s\" - should be unsigned int.", 21197aa51b79SEd Maste args.GetArgumentAtIndex(0)); 21207aa51b79SEd Maste result.SetStatus (eReturnStatusFailed); 21217aa51b79SEd Maste return false; 21227aa51b79SEd Maste } 21237aa51b79SEd Maste 21247aa51b79SEd Maste if (thread_plan_idx == 0) 21257aa51b79SEd Maste { 21267aa51b79SEd Maste result.AppendErrorWithFormat("You wouldn't really want me to discard the base thread plan."); 21277aa51b79SEd Maste result.SetStatus (eReturnStatusFailed); 21287aa51b79SEd Maste return false; 21297aa51b79SEd Maste } 21307aa51b79SEd Maste 21317aa51b79SEd Maste if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) 21327aa51b79SEd Maste { 21337aa51b79SEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult); 21347aa51b79SEd Maste return true; 21357aa51b79SEd Maste } 21367aa51b79SEd Maste else 21377aa51b79SEd Maste { 21387aa51b79SEd Maste result.AppendErrorWithFormat("Could not find User thread plan with index %s.", 21397aa51b79SEd Maste args.GetArgumentAtIndex(0)); 21407aa51b79SEd Maste result.SetStatus (eReturnStatusFailed); 21417aa51b79SEd Maste return false; 21427aa51b79SEd Maste } 21437aa51b79SEd Maste } 21447aa51b79SEd Maste }; 21457aa51b79SEd Maste 21467aa51b79SEd Maste //------------------------------------------------------------------------- 21477aa51b79SEd Maste // CommandObjectMultiwordThreadPlan 21487aa51b79SEd Maste //------------------------------------------------------------------------- 21497aa51b79SEd Maste 21507aa51b79SEd Maste class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword 21517aa51b79SEd Maste { 21527aa51b79SEd Maste public: 21534bb0738eSEd Maste CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) 21544bb0738eSEd Maste : CommandObjectMultiword(interpreter, "plan", "Commands for managing thread plans that control execution.", 21557aa51b79SEd Maste "thread plan <subcommand> [<subcommand objects]") 21567aa51b79SEd Maste { 21577aa51b79SEd Maste LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadPlanList (interpreter))); 21587aa51b79SEd Maste LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter))); 21597aa51b79SEd Maste } 21607aa51b79SEd Maste 21614bb0738eSEd Maste ~CommandObjectMultiwordThreadPlan() override = default; 21627aa51b79SEd Maste }; 21637aa51b79SEd Maste 21647aa51b79SEd Maste //------------------------------------------------------------------------- 2165ac7ddfbfSEd Maste // CommandObjectMultiwordThread 2166ac7ddfbfSEd Maste //------------------------------------------------------------------------- 2167ac7ddfbfSEd Maste 21684bb0738eSEd Maste CommandObjectMultiwordThread::CommandObjectMultiwordThread(CommandInterpreter &interpreter) 21694bb0738eSEd Maste : CommandObjectMultiword(interpreter, "thread", 21704bb0738eSEd Maste "Commands for operating on one or more threads in the current process.", 2171ac7ddfbfSEd Maste "thread <subcommand> [<subcommand-options>]") 2172ac7ddfbfSEd Maste { 2173ac7ddfbfSEd Maste LoadSubCommand ("backtrace", CommandObjectSP (new CommandObjectThreadBacktrace (interpreter))); 2174ac7ddfbfSEd Maste LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter))); 2175ac7ddfbfSEd Maste LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter))); 2176ac7ddfbfSEd Maste LoadSubCommand ("return", CommandObjectSP (new CommandObjectThreadReturn (interpreter))); 217735617911SEd Maste LoadSubCommand ("jump", CommandObjectSP (new CommandObjectThreadJump (interpreter))); 2178ac7ddfbfSEd Maste LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter))); 2179ac7ddfbfSEd Maste LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter))); 21800127ef0fSEd Maste LoadSubCommand ("info", CommandObjectSP (new CommandObjectThreadInfo (interpreter))); 21814bb0738eSEd Maste LoadSubCommand("step-in", 21824bb0738eSEd Maste CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 21834bb0738eSEd Maste interpreter, "thread step-in", 21844bb0738eSEd Maste "Source level single step, stepping into calls. Defaults to current thread unless specified.", 21854bb0738eSEd Maste nullptr, eStepTypeInto, eStepScopeSource))); 2186ac7ddfbfSEd Maste 21874bb0738eSEd Maste LoadSubCommand("step-out", 21884bb0738eSEd Maste CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 21894bb0738eSEd Maste interpreter, "thread step-out", "Finish executing the current stack frame and stop after " 21904bb0738eSEd Maste "returning. Defaults to current thread unless specified.", 21914bb0738eSEd Maste nullptr, eStepTypeOut, eStepScopeSource))); 2192ac7ddfbfSEd Maste 21934bb0738eSEd Maste LoadSubCommand("step-over", 21944bb0738eSEd Maste CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 21954bb0738eSEd Maste interpreter, "thread step-over", 21964bb0738eSEd Maste "Source level single step, stepping over calls. Defaults to current thread unless specified.", 21974bb0738eSEd Maste nullptr, eStepTypeOver, eStepScopeSource))); 2198ac7ddfbfSEd Maste 21994bb0738eSEd Maste LoadSubCommand( 22004bb0738eSEd Maste "step-inst", 22014bb0738eSEd Maste CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 22024bb0738eSEd Maste interpreter, "thread step-inst", 22034bb0738eSEd Maste "Instruction level single step, stepping into calls. Defaults to current thread unless specified.", 22044bb0738eSEd Maste nullptr, eStepTypeTrace, eStepScopeInstruction))); 2205ac7ddfbfSEd Maste 22064bb0738eSEd Maste LoadSubCommand( 22074bb0738eSEd Maste "step-inst-over", 22084bb0738eSEd Maste CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 22094bb0738eSEd Maste interpreter, "thread step-inst-over", 22104bb0738eSEd Maste "Instruction level single step, stepping over calls. Defaults to current thread unless specified.", 22114bb0738eSEd Maste nullptr, eStepTypeTraceOver, eStepScopeInstruction))); 22127aa51b79SEd Maste 22137aa51b79SEd Maste LoadSubCommand ("step-scripted", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 22147aa51b79SEd Maste interpreter, 22157aa51b79SEd Maste "thread step-scripted", 22167aa51b79SEd Maste "Step as instructed by the script class passed in the -C option.", 22174bb0738eSEd Maste nullptr, 22187aa51b79SEd Maste eStepTypeScripted, 22197aa51b79SEd Maste eStepScopeSource))); 22207aa51b79SEd Maste 22217aa51b79SEd Maste LoadSubCommand ("plan", CommandObjectSP (new CommandObjectMultiwordThreadPlan(interpreter))); 2222ac7ddfbfSEd Maste } 2223ac7ddfbfSEd Maste 22244bb0738eSEd Maste CommandObjectMultiwordThread::~CommandObjectMultiwordThread() = default; 2225