1 //===-- CommandObjectThread.cpp ---------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "CommandObjectThread.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/lldb-private.h" 17 #include "lldb/Core/State.h" 18 #include "lldb/Core/SourceManager.h" 19 #include "lldb/Core/ValueObject.h" 20 #include "lldb/Host/Host.h" 21 #include "lldb/Host/StringConvert.h" 22 #include "lldb/Interpreter/CommandInterpreter.h" 23 #include "lldb/Interpreter/CommandReturnObject.h" 24 #include "lldb/Interpreter/Options.h" 25 #include "lldb/Symbol/CompileUnit.h" 26 #include "lldb/Symbol/Function.h" 27 #include "lldb/Symbol/LineTable.h" 28 #include "lldb/Symbol/LineEntry.h" 29 #include "lldb/Target/Process.h" 30 #include "lldb/Target/RegisterContext.h" 31 #include "lldb/Target/SystemRuntime.h" 32 #include "lldb/Target/Target.h" 33 #include "lldb/Target/Thread.h" 34 #include "lldb/Target/ThreadPlan.h" 35 #include "lldb/Target/ThreadPlanStepInstruction.h" 36 #include "lldb/Target/ThreadPlanStepOut.h" 37 #include "lldb/Target/ThreadPlanStepRange.h" 38 #include "lldb/Target/ThreadPlanStepInRange.h" 39 40 41 using namespace lldb; 42 using namespace lldb_private; 43 44 45 //------------------------------------------------------------------------- 46 // CommandObjectThreadBacktrace 47 //------------------------------------------------------------------------- 48 49 class CommandObjectIterateOverThreads : public CommandObjectParsed 50 { 51 public: 52 CommandObjectIterateOverThreads (CommandInterpreter &interpreter, 53 const char *name, 54 const char *help, 55 const char *syntax, 56 uint32_t flags) : 57 CommandObjectParsed (interpreter, name, help, syntax, flags) 58 { 59 } 60 61 ~CommandObjectIterateOverThreads() override {} 62 63 bool 64 DoExecute (Args& command, CommandReturnObject &result) override 65 { 66 result.SetStatus (m_success_return); 67 68 if (command.GetArgumentCount() == 0) 69 { 70 Thread *thread = m_exe_ctx.GetThreadPtr(); 71 if (!HandleOneThread (*thread, result)) 72 return false; 73 } 74 else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0) 75 { 76 Process *process = m_exe_ctx.GetProcessPtr(); 77 uint32_t idx = 0; 78 for (ThreadSP thread_sp : process->Threads()) 79 { 80 if (idx != 0 && m_add_return) 81 result.AppendMessage(""); 82 83 if (!HandleOneThread(*(thread_sp.get()), result)) 84 return false; 85 ++idx; 86 } 87 } 88 else 89 { 90 const size_t num_args = command.GetArgumentCount(); 91 Process *process = m_exe_ctx.GetProcessPtr(); 92 Mutex::Locker locker (process->GetThreadList().GetMutex()); 93 std::vector<ThreadSP> thread_sps; 94 95 for (size_t i = 0; i < num_args; i++) 96 { 97 bool success; 98 99 uint32_t thread_idx = StringConvert::ToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success); 100 if (!success) 101 { 102 result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); 103 result.SetStatus (eReturnStatusFailed); 104 return false; 105 } 106 107 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx)); 108 109 if (!thread_sps[i]) 110 { 111 result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i)); 112 result.SetStatus (eReturnStatusFailed); 113 return false; 114 } 115 116 } 117 118 for (uint32_t i = 0; i < num_args; i++) 119 { 120 if (!HandleOneThread (*(thread_sps[i].get()), result)) 121 return false; 122 123 if (i < num_args - 1 && m_add_return) 124 result.AppendMessage(""); 125 } 126 } 127 return result.Succeeded(); 128 } 129 130 protected: 131 132 // Override this to do whatever you need to do for one thread. 133 // 134 // If you return false, the iteration will stop, otherwise it will proceed. 135 // The result is set to m_success_return (defaults to eReturnStatusSuccessFinishResult) before the iteration, 136 // so you only need to set the return status in HandleOneThread if you want to indicate an error. 137 // If m_add_return is true, a blank line will be inserted between each of the listings (except the last one.) 138 139 virtual bool 140 HandleOneThread (Thread &thread, CommandReturnObject &result) = 0; 141 142 ReturnStatus m_success_return = eReturnStatusSuccessFinishResult; 143 bool m_add_return = true; 144 145 }; 146 147 //------------------------------------------------------------------------- 148 // CommandObjectThreadBacktrace 149 //------------------------------------------------------------------------- 150 151 class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads 152 { 153 public: 154 155 class CommandOptions : public Options 156 { 157 public: 158 159 CommandOptions (CommandInterpreter &interpreter) : 160 Options(interpreter) 161 { 162 // Keep default values of all options in one place: OptionParsingStarting () 163 OptionParsingStarting (); 164 } 165 166 ~CommandOptions () override 167 { 168 } 169 170 Error 171 SetOptionValue (uint32_t option_idx, const char *option_arg) override 172 { 173 Error error; 174 const int short_option = m_getopt_table[option_idx].val; 175 176 switch (short_option) 177 { 178 case 'c': 179 { 180 bool success; 181 int32_t input_count = StringConvert::ToSInt32 (option_arg, -1, 0, &success); 182 if (!success) 183 error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option); 184 if (input_count < -1) 185 m_count = UINT32_MAX; 186 else 187 m_count = input_count; 188 } 189 break; 190 case 's': 191 { 192 bool success; 193 m_start = StringConvert::ToUInt32 (option_arg, 0, 0, &success); 194 if (!success) 195 error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option); 196 } 197 break; 198 case 'e': 199 { 200 bool success; 201 m_extended_backtrace = Args::StringToBoolean (option_arg, false, &success); 202 if (!success) 203 error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option); 204 } 205 break; 206 default: 207 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 208 break; 209 210 } 211 return error; 212 } 213 214 void 215 OptionParsingStarting () override 216 { 217 m_count = UINT32_MAX; 218 m_start = 0; 219 m_extended_backtrace = false; 220 } 221 222 const OptionDefinition* 223 GetDefinitions () override 224 { 225 return g_option_table; 226 } 227 228 // Options table: Required for subclasses of Options. 229 230 static OptionDefinition g_option_table[]; 231 232 // Instance variables to hold the values for command options. 233 uint32_t m_count; 234 uint32_t m_start; 235 bool m_extended_backtrace; 236 }; 237 238 CommandObjectThreadBacktrace (CommandInterpreter &interpreter) : 239 CommandObjectIterateOverThreads (interpreter, 240 "thread backtrace", 241 "Show the stack for one or more threads. If no threads are specified, show the currently selected thread. Use the thread-index \"all\" to see all threads.", 242 NULL, 243 eCommandRequiresProcess | 244 eCommandRequiresThread | 245 eCommandTryTargetAPILock | 246 eCommandProcessMustBeLaunched | 247 eCommandProcessMustBePaused ), 248 m_options(interpreter) 249 { 250 } 251 252 ~CommandObjectThreadBacktrace() override 253 { 254 } 255 256 Options * 257 GetOptions () override 258 { 259 return &m_options; 260 } 261 262 protected: 263 void 264 DoExtendedBacktrace (Thread *thread, CommandReturnObject &result) 265 { 266 SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime(); 267 if (runtime) 268 { 269 Stream &strm = result.GetOutputStream(); 270 const std::vector<ConstString> &types = runtime->GetExtendedBacktraceTypes(); 271 for (auto type : types) 272 { 273 ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread (thread->shared_from_this(), type); 274 if (ext_thread_sp && ext_thread_sp->IsValid ()) 275 { 276 const uint32_t num_frames_with_source = 0; 277 if (ext_thread_sp->GetStatus (strm, 278 m_options.m_start, 279 m_options.m_count, 280 num_frames_with_source)) 281 { 282 DoExtendedBacktrace (ext_thread_sp.get(), result); 283 } 284 } 285 } 286 } 287 } 288 289 bool 290 HandleOneThread (Thread &thread, CommandReturnObject &result) override 291 { 292 Stream &strm = result.GetOutputStream(); 293 294 // Don't show source context when doing backtraces. 295 const uint32_t num_frames_with_source = 0; 296 297 if (!thread.GetStatus (strm, 298 m_options.m_start, 299 m_options.m_count, 300 num_frames_with_source)) 301 { 302 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", thread.GetIndexID()); 303 result.SetStatus (eReturnStatusFailed); 304 return false; 305 } 306 if (m_options.m_extended_backtrace) 307 { 308 DoExtendedBacktrace (&thread, result); 309 } 310 311 return true; 312 } 313 314 CommandOptions m_options; 315 }; 316 317 OptionDefinition 318 CommandObjectThreadBacktrace::CommandOptions::g_option_table[] = 319 { 320 { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"}, 321 { LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"}, 322 { LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Show the extended backtrace, if available"}, 323 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 324 }; 325 326 enum StepScope 327 { 328 eStepScopeSource, 329 eStepScopeInstruction 330 }; 331 332 class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed 333 { 334 public: 335 336 class CommandOptions : public Options 337 { 338 public: 339 340 CommandOptions (CommandInterpreter &interpreter) : 341 Options (interpreter) 342 { 343 // Keep default values of all options in one place: OptionParsingStarting () 344 OptionParsingStarting (); 345 } 346 347 ~CommandOptions () override 348 { 349 } 350 351 Error 352 SetOptionValue (uint32_t option_idx, const char *option_arg) override 353 { 354 Error error; 355 const int short_option = m_getopt_table[option_idx].val; 356 357 switch (short_option) 358 { 359 case 'a': 360 { 361 bool success; 362 bool avoid_no_debug = Args::StringToBoolean (option_arg, true, &success); 363 if (!success) 364 error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option); 365 else 366 { 367 m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; 368 } 369 } 370 break; 371 372 case 'A': 373 { 374 bool success; 375 bool avoid_no_debug = Args::StringToBoolean (option_arg, true, &success); 376 if (!success) 377 error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option); 378 else 379 { 380 m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; 381 } 382 } 383 break; 384 385 case 'c': 386 { 387 m_step_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 388 if (m_step_count == UINT32_MAX) 389 error.SetErrorStringWithFormat ("invalid step count '%s'", option_arg); 390 break; 391 } 392 break; 393 case 'C': 394 { 395 m_class_name.clear(); 396 m_class_name.assign(option_arg); 397 } 398 break; 399 case 'm': 400 { 401 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 402 m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error); 403 } 404 break; 405 406 case 'e': 407 { 408 uint32_t tmp_end_line = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 409 if (tmp_end_line == UINT32_MAX) 410 error.SetErrorStringWithFormat ("invalid end line number '%s'", option_arg); 411 else 412 m_end_line = tmp_end_line; 413 break; 414 } 415 break; 416 case 'r': 417 { 418 m_avoid_regexp.clear(); 419 m_avoid_regexp.assign(option_arg); 420 } 421 break; 422 423 case 't': 424 { 425 m_step_in_target.clear(); 426 m_step_in_target.assign(option_arg); 427 428 } 429 break; 430 default: 431 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 432 break; 433 434 } 435 return error; 436 } 437 438 void 439 OptionParsingStarting () override 440 { 441 m_step_in_avoid_no_debug = eLazyBoolCalculate; 442 m_step_out_avoid_no_debug = eLazyBoolCalculate; 443 m_run_mode = eOnlyDuringStepping; 444 445 // Check if we are in Non-Stop mode 446 lldb::TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); 447 if (target_sp.get() != nullptr && target_sp->GetNonStopModeEnabled()) 448 m_run_mode = eOnlyThisThread; 449 450 m_avoid_regexp.clear(); 451 m_step_in_target.clear(); 452 m_class_name.clear(); 453 m_step_count = 1; 454 m_end_line = LLDB_INVALID_LINE_NUMBER; 455 } 456 457 const OptionDefinition* 458 GetDefinitions () override 459 { 460 return g_option_table; 461 } 462 463 // Options table: Required for subclasses of Options. 464 465 static OptionDefinition g_option_table[]; 466 467 // Instance variables to hold the values for command options. 468 LazyBool m_step_in_avoid_no_debug; 469 LazyBool m_step_out_avoid_no_debug; 470 RunMode m_run_mode; 471 std::string m_avoid_regexp; 472 std::string m_step_in_target; 473 std::string m_class_name; 474 uint32_t m_step_count; 475 uint32_t m_end_line; 476 }; 477 478 CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter, 479 const char *name, 480 const char *help, 481 const char *syntax, 482 StepType step_type, 483 StepScope step_scope) : 484 CommandObjectParsed (interpreter, name, help, syntax, 485 eCommandRequiresProcess | 486 eCommandRequiresThread | 487 eCommandTryTargetAPILock | 488 eCommandProcessMustBeLaunched | 489 eCommandProcessMustBePaused ), 490 m_step_type (step_type), 491 m_step_scope (step_scope), 492 m_options (interpreter) 493 { 494 CommandArgumentEntry arg; 495 CommandArgumentData thread_id_arg; 496 497 // Define the first (and only) variant of this arg. 498 thread_id_arg.arg_type = eArgTypeThreadID; 499 thread_id_arg.arg_repetition = eArgRepeatOptional; 500 501 // There is only one variant this argument could be; put it into the argument entry. 502 arg.push_back (thread_id_arg); 503 504 // Push the data for the first argument into the m_arguments vector. 505 m_arguments.push_back (arg); 506 } 507 508 ~CommandObjectThreadStepWithTypeAndScope () override 509 { 510 } 511 512 Options * 513 GetOptions () override 514 { 515 return &m_options; 516 } 517 518 protected: 519 bool 520 DoExecute (Args& command, CommandReturnObject &result) override 521 { 522 Process *process = m_exe_ctx.GetProcessPtr(); 523 bool synchronous_execution = m_interpreter.GetSynchronous(); 524 525 const uint32_t num_threads = process->GetThreadList().GetSize(); 526 Thread *thread = NULL; 527 528 if (command.GetArgumentCount() == 0) 529 { 530 thread = process->GetThreadList().GetSelectedThread().get(); 531 if (thread == NULL) 532 { 533 result.AppendError ("no selected thread in process"); 534 result.SetStatus (eReturnStatusFailed); 535 return false; 536 } 537 } 538 else 539 { 540 const char *thread_idx_cstr = command.GetArgumentAtIndex(0); 541 uint32_t step_thread_idx = StringConvert::ToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32); 542 if (step_thread_idx == LLDB_INVALID_INDEX32) 543 { 544 result.AppendErrorWithFormat ("invalid thread index '%s'.\n", thread_idx_cstr); 545 result.SetStatus (eReturnStatusFailed); 546 return false; 547 } 548 thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get(); 549 if (thread == NULL) 550 { 551 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 552 step_thread_idx, num_threads); 553 result.SetStatus (eReturnStatusFailed); 554 return false; 555 } 556 } 557 558 if (m_step_type == eStepTypeScripted) 559 { 560 if (m_options.m_class_name.empty()) 561 { 562 result.AppendErrorWithFormat ("empty class name for scripted step."); 563 result.SetStatus(eReturnStatusFailed); 564 return false; 565 } 566 else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists(m_options.m_class_name.c_str())) 567 { 568 result.AppendErrorWithFormat ("class for scripted step: \"%s\" does not exist.", m_options.m_class_name.c_str()); 569 result.SetStatus(eReturnStatusFailed); 570 return false; 571 } 572 } 573 574 if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER 575 && m_step_type != eStepTypeInto) 576 { 577 result.AppendErrorWithFormat("end line option is only valid for step into"); 578 result.SetStatus(eReturnStatusFailed); 579 return false; 580 } 581 582 const bool abort_other_plans = false; 583 const lldb::RunMode stop_other_threads = m_options.m_run_mode; 584 585 // This is a bit unfortunate, but not all the commands in this command object support 586 // only while stepping, so I use the bool for them. 587 bool bool_stop_other_threads; 588 if (m_options.m_run_mode == eAllThreads) 589 bool_stop_other_threads = false; 590 else if (m_options.m_run_mode == eOnlyDuringStepping) 591 { 592 if (m_step_type == eStepTypeOut || m_step_type == eStepTypeScripted) 593 bool_stop_other_threads = false; 594 else 595 bool_stop_other_threads = true; 596 } 597 else 598 bool_stop_other_threads = true; 599 600 ThreadPlanSP new_plan_sp; 601 602 if (m_step_type == eStepTypeInto) 603 { 604 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 605 assert(frame != nullptr); 606 607 if (frame->HasDebugInformation ()) 608 { 609 AddressRange range = frame->GetSymbolContext(eSymbolContextEverything).line_entry.range; 610 if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER) 611 { 612 SymbolContext sc = frame->GetSymbolContext(eSymbolContextEverything); 613 if (sc.line_entry.line > m_options.m_end_line) 614 { 615 result.AppendErrorWithFormat("end line option %d must be after the current line: %d", 616 m_options.m_end_line, 617 sc.line_entry.line); 618 result.SetStatus(eReturnStatusFailed); 619 return false; 620 } 621 622 CompileUnit *cu = sc.comp_unit; 623 uint32_t line_index = 0; 624 bool found = false; 625 while (1) 626 { 627 LineEntry this_line; 628 line_index = cu->FindLineEntry(line_index, sc.line_entry.line, nullptr, false, &this_line); 629 if (line_index == UINT32_MAX) 630 break; 631 if (LineEntry::Compare(this_line, sc.line_entry) == 0) 632 { 633 found = true; 634 break; 635 } 636 } 637 LineEntry end_entry; 638 if (!found) 639 { 640 // Can't find the index of the SymbolContext's line entry in the SymbolContext's CompUnit. 641 result.AppendErrorWithFormat("Can't find the current line entry in the CompUnit - can't process " 642 "the end-line option"); 643 result.SetStatus(eReturnStatusFailed); 644 return false; 645 } 646 647 line_index = cu->FindLineEntry(line_index, m_options.m_end_line, nullptr, false, &end_entry); 648 if (line_index == UINT32_MAX) 649 { 650 result.AppendErrorWithFormat("could not find a line table entry corresponding " 651 "to end line number %d", 652 m_options.m_end_line); 653 result.SetStatus(eReturnStatusFailed); 654 return false; 655 } 656 657 Block *func_block = sc.GetFunctionBlock(); 658 if (func_block && func_block->GetRangeIndexContainingAddress(end_entry.range.GetBaseAddress()) == UINT32_MAX) 659 { 660 result.AppendErrorWithFormat("end line number %d is not contained within the current function.", 661 m_options.m_end_line); 662 result.SetStatus(eReturnStatusFailed); 663 return false; 664 } 665 666 lldb::addr_t range_size = end_entry.range.GetBaseAddress().GetFileAddress() 667 - range.GetBaseAddress().GetFileAddress(); 668 range.SetByteSize(range_size); 669 } 670 671 new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans, 672 range, 673 frame->GetSymbolContext(eSymbolContextEverything), 674 m_options.m_step_in_target.c_str(), 675 stop_other_threads, 676 m_options.m_step_in_avoid_no_debug, 677 m_options.m_step_out_avoid_no_debug); 678 679 if (new_plan_sp && !m_options.m_avoid_regexp.empty()) 680 { 681 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan_sp.get()); 682 step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str()); 683 } 684 } 685 else 686 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); 687 688 } 689 else if (m_step_type == eStepTypeOver) 690 { 691 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 692 693 if (frame->HasDebugInformation()) 694 new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans, 695 frame->GetSymbolContext(eSymbolContextEverything).line_entry, 696 frame->GetSymbolContext(eSymbolContextEverything), 697 stop_other_threads, 698 m_options.m_step_out_avoid_no_debug); 699 else 700 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, 701 abort_other_plans, 702 bool_stop_other_threads); 703 704 } 705 else if (m_step_type == eStepTypeTrace) 706 { 707 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); 708 } 709 else if (m_step_type == eStepTypeTraceOver) 710 { 711 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads); 712 } 713 else if (m_step_type == eStepTypeOut) 714 { 715 new_plan_sp = thread->QueueThreadPlanForStepOut (abort_other_plans, 716 NULL, 717 false, 718 bool_stop_other_threads, 719 eVoteYes, 720 eVoteNoOpinion, 721 thread->GetSelectedFrameIndex(), 722 m_options.m_step_out_avoid_no_debug); 723 } 724 else if (m_step_type == eStepTypeScripted) 725 { 726 new_plan_sp = thread->QueueThreadPlanForStepScripted (abort_other_plans, 727 m_options.m_class_name.c_str(), 728 bool_stop_other_threads); 729 } 730 else 731 { 732 result.AppendError ("step type is not supported"); 733 result.SetStatus (eReturnStatusFailed); 734 return false; 735 } 736 737 // If we got a new plan, then set it to be a master plan (User level Plans should be master plans 738 // so that they can be interruptible). Then resume the process. 739 740 if (new_plan_sp) 741 { 742 new_plan_sp->SetIsMasterPlan (true); 743 new_plan_sp->SetOkayToDiscard (false); 744 745 if (m_options.m_step_count > 1) 746 { 747 if (new_plan_sp->SetIterationCount(m_options.m_step_count)) 748 { 749 result.AppendWarning ("step operation does not support iteration count."); 750 } 751 } 752 753 754 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 755 756 const uint32_t iohandler_id = process->GetIOHandlerID(); 757 758 StreamString stream; 759 Error error; 760 if (synchronous_execution) 761 error = process->ResumeSynchronous (&stream); 762 else 763 error = process->Resume (); 764 765 // There is a race condition where this thread will return up the call stack to the main command handler 766 // and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has 767 // a chance to call PushProcessIOHandler(). 768 process->SyncIOHandler(iohandler_id, 2000); 769 770 if (synchronous_execution) 771 { 772 // If any state changed events had anything to say, add that to the result 773 if (stream.GetData()) 774 result.AppendMessage(stream.GetData()); 775 776 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 777 result.SetDidChangeProcessState (true); 778 result.SetStatus (eReturnStatusSuccessFinishNoResult); 779 } 780 else 781 { 782 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 783 } 784 } 785 else 786 { 787 result.AppendError ("Couldn't find thread plan to implement step type."); 788 result.SetStatus (eReturnStatusFailed); 789 } 790 return result.Succeeded(); 791 } 792 793 protected: 794 StepType m_step_type; 795 StepScope m_step_scope; 796 CommandOptions m_options; 797 }; 798 799 static OptionEnumValueElement 800 g_tri_running_mode[] = 801 { 802 { eOnlyThisThread, "this-thread", "Run only this thread"}, 803 { eAllThreads, "all-threads", "Run all threads"}, 804 { eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"}, 805 { 0, NULL, NULL } 806 }; 807 808 static OptionEnumValueElement 809 g_duo_running_mode[] = 810 { 811 { eOnlyThisThread, "this-thread", "Run only this thread"}, 812 { eAllThreads, "all-threads", "Run all threads"}, 813 { 0, NULL, NULL } 814 }; 815 816 OptionDefinition 817 CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] = 818 { 819 { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether stepping into functions will step over functions with no debug information."}, 820 { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug", 'A', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information."}, 821 { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."}, 822 { LLDB_OPT_SET_1, false, "end-linenumber", 'e', OptionParser::eRequiredArgument, NULL, NULL, 1, eArgTypeLineNum, "The line at which to stop stepping - defaults to the next line and only supported for step-in and step-over."}, 823 { LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, NULL, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."}, 824 { LLDB_OPT_SET_1, false, "step-over-regexp", 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in."}, 825 { LLDB_OPT_SET_1, false, "step-in-target", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."}, 826 { LLDB_OPT_SET_2, false, "python-class", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step."}, 827 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 828 }; 829 830 831 //------------------------------------------------------------------------- 832 // CommandObjectThreadContinue 833 //------------------------------------------------------------------------- 834 835 class CommandObjectThreadContinue : public CommandObjectParsed 836 { 837 public: 838 839 CommandObjectThreadContinue (CommandInterpreter &interpreter) : 840 CommandObjectParsed (interpreter, 841 "thread continue", 842 "Continue execution of one or more threads in an active process.", 843 NULL, 844 eCommandRequiresThread | 845 eCommandTryTargetAPILock | 846 eCommandProcessMustBeLaunched | 847 eCommandProcessMustBePaused) 848 { 849 CommandArgumentEntry arg; 850 CommandArgumentData thread_idx_arg; 851 852 // Define the first (and only) variant of this arg. 853 thread_idx_arg.arg_type = eArgTypeThreadIndex; 854 thread_idx_arg.arg_repetition = eArgRepeatPlus; 855 856 // There is only one variant this argument could be; put it into the argument entry. 857 arg.push_back (thread_idx_arg); 858 859 // Push the data for the first argument into the m_arguments vector. 860 m_arguments.push_back (arg); 861 } 862 863 864 ~CommandObjectThreadContinue () override 865 { 866 } 867 868 bool 869 DoExecute (Args& command, CommandReturnObject &result) override 870 { 871 bool synchronous_execution = m_interpreter.GetSynchronous (); 872 873 if (!m_interpreter.GetDebugger().GetSelectedTarget().get()) 874 { 875 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 876 result.SetStatus (eReturnStatusFailed); 877 return false; 878 } 879 880 Process *process = m_exe_ctx.GetProcessPtr(); 881 if (process == NULL) 882 { 883 result.AppendError ("no process exists. Cannot continue"); 884 result.SetStatus (eReturnStatusFailed); 885 return false; 886 } 887 888 StateType state = process->GetState(); 889 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended)) 890 { 891 const size_t argc = command.GetArgumentCount(); 892 if (argc > 0) 893 { 894 // These two lines appear at the beginning of both blocks in 895 // this if..else, but that is because we need to release the 896 // lock before calling process->Resume below. 897 Mutex::Locker locker (process->GetThreadList().GetMutex()); 898 const uint32_t num_threads = process->GetThreadList().GetSize(); 899 std::vector<Thread *> resume_threads; 900 for (uint32_t i=0; i<argc; ++i) 901 { 902 bool success; 903 const int base = 0; 904 uint32_t thread_idx = StringConvert::ToUInt32 (command.GetArgumentAtIndex(i), LLDB_INVALID_INDEX32, base, &success); 905 if (success) 906 { 907 Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get(); 908 909 if (thread) 910 { 911 resume_threads.push_back(thread); 912 } 913 else 914 { 915 result.AppendErrorWithFormat("invalid thread index %u.\n", thread_idx); 916 result.SetStatus (eReturnStatusFailed); 917 return false; 918 } 919 } 920 else 921 { 922 result.AppendErrorWithFormat ("invalid thread index argument: \"%s\".\n", command.GetArgumentAtIndex(i)); 923 result.SetStatus (eReturnStatusFailed); 924 return false; 925 } 926 } 927 928 if (resume_threads.empty()) 929 { 930 result.AppendError ("no valid thread indexes were specified"); 931 result.SetStatus (eReturnStatusFailed); 932 return false; 933 } 934 else 935 { 936 if (resume_threads.size() == 1) 937 result.AppendMessageWithFormat ("Resuming thread: "); 938 else 939 result.AppendMessageWithFormat ("Resuming threads: "); 940 941 for (uint32_t idx=0; idx<num_threads; ++idx) 942 { 943 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 944 std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread); 945 946 if (this_thread_pos != resume_threads.end()) 947 { 948 resume_threads.erase(this_thread_pos); 949 if (resume_threads.size() > 0) 950 result.AppendMessageWithFormat ("%u, ", thread->GetIndexID()); 951 else 952 result.AppendMessageWithFormat ("%u ", thread->GetIndexID()); 953 954 const bool override_suspend = true; 955 thread->SetResumeState (eStateRunning, override_suspend); 956 } 957 else 958 { 959 thread->SetResumeState (eStateSuspended); 960 } 961 } 962 result.AppendMessageWithFormat ("in process %" PRIu64 "\n", process->GetID()); 963 } 964 } 965 else 966 { 967 // These two lines appear at the beginning of both blocks in 968 // this if..else, but that is because we need to release the 969 // lock before calling process->Resume below. 970 Mutex::Locker locker (process->GetThreadList().GetMutex()); 971 const uint32_t num_threads = process->GetThreadList().GetSize(); 972 Thread *current_thread = process->GetThreadList().GetSelectedThread().get(); 973 if (current_thread == NULL) 974 { 975 result.AppendError ("the process doesn't have a current thread"); 976 result.SetStatus (eReturnStatusFailed); 977 return false; 978 } 979 // Set the actions that the threads should each take when resuming 980 for (uint32_t idx=0; idx<num_threads; ++idx) 981 { 982 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 983 if (thread == current_thread) 984 { 985 result.AppendMessageWithFormat ("Resuming thread 0x%4.4" PRIx64 " in process %" PRIu64 "\n", thread->GetID(), process->GetID()); 986 const bool override_suspend = true; 987 thread->SetResumeState (eStateRunning, override_suspend); 988 } 989 else 990 { 991 thread->SetResumeState (eStateSuspended); 992 } 993 } 994 } 995 996 997 StreamString stream; 998 Error error; 999 if (synchronous_execution) 1000 error = process->ResumeSynchronous (&stream); 1001 else 1002 error = process->Resume (); 1003 1004 // We should not be holding the thread list lock when we do this. 1005 if (error.Success()) 1006 { 1007 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); 1008 if (synchronous_execution) 1009 { 1010 // If any state changed events had anything to say, add that to the result 1011 if (stream.GetData()) 1012 result.AppendMessage(stream.GetData()); 1013 1014 result.SetDidChangeProcessState (true); 1015 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1016 } 1017 else 1018 { 1019 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 1020 } 1021 } 1022 else 1023 { 1024 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString()); 1025 result.SetStatus (eReturnStatusFailed); 1026 } 1027 } 1028 else 1029 { 1030 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 1031 StateAsCString(state)); 1032 result.SetStatus (eReturnStatusFailed); 1033 } 1034 1035 return result.Succeeded(); 1036 } 1037 1038 }; 1039 1040 //------------------------------------------------------------------------- 1041 // CommandObjectThreadUntil 1042 //------------------------------------------------------------------------- 1043 1044 class CommandObjectThreadUntil : public CommandObjectParsed 1045 { 1046 public: 1047 1048 class CommandOptions : public Options 1049 { 1050 public: 1051 uint32_t m_thread_idx; 1052 uint32_t m_frame_idx; 1053 1054 CommandOptions (CommandInterpreter &interpreter) : 1055 Options (interpreter), 1056 m_thread_idx(LLDB_INVALID_THREAD_ID), 1057 m_frame_idx(LLDB_INVALID_FRAME_ID) 1058 { 1059 // Keep default values of all options in one place: OptionParsingStarting () 1060 OptionParsingStarting (); 1061 } 1062 1063 ~CommandOptions () override 1064 { 1065 } 1066 1067 Error 1068 SetOptionValue (uint32_t option_idx, const char *option_arg) override 1069 { 1070 Error error; 1071 const int short_option = m_getopt_table[option_idx].val; 1072 1073 switch (short_option) 1074 { 1075 case 'a': 1076 { 1077 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 1078 lldb::addr_t tmp_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); 1079 if (error.Success()) 1080 m_until_addrs.push_back(tmp_addr); 1081 } 1082 break; 1083 case 't': 1084 { 1085 m_thread_idx = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_INDEX32); 1086 if (m_thread_idx == LLDB_INVALID_INDEX32) 1087 { 1088 error.SetErrorStringWithFormat ("invalid thread index '%s'", option_arg); 1089 } 1090 } 1091 break; 1092 case 'f': 1093 { 1094 m_frame_idx = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_FRAME_ID); 1095 if (m_frame_idx == LLDB_INVALID_FRAME_ID) 1096 { 1097 error.SetErrorStringWithFormat ("invalid frame index '%s'", option_arg); 1098 } 1099 } 1100 break; 1101 case 'm': 1102 { 1103 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 1104 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error); 1105 1106 if (error.Success()) 1107 { 1108 if (run_mode == eAllThreads) 1109 m_stop_others = false; 1110 else 1111 m_stop_others = true; 1112 } 1113 } 1114 break; 1115 default: 1116 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1117 break; 1118 1119 } 1120 return error; 1121 } 1122 1123 void 1124 OptionParsingStarting () override 1125 { 1126 m_thread_idx = LLDB_INVALID_THREAD_ID; 1127 m_frame_idx = 0; 1128 m_stop_others = false; 1129 m_until_addrs.clear(); 1130 } 1131 1132 const OptionDefinition* 1133 GetDefinitions () override 1134 { 1135 return g_option_table; 1136 } 1137 1138 uint32_t m_step_thread_idx; 1139 bool m_stop_others; 1140 std::vector<lldb::addr_t> m_until_addrs; 1141 1142 // Options table: Required for subclasses of Options. 1143 1144 static OptionDefinition g_option_table[]; 1145 1146 // Instance variables to hold the values for command options. 1147 }; 1148 1149 CommandObjectThreadUntil (CommandInterpreter &interpreter) : 1150 CommandObjectParsed (interpreter, 1151 "thread until", 1152 "Run the current or specified thread until it reaches a given line number or address or leaves the current function.", 1153 NULL, 1154 eCommandRequiresThread | 1155 eCommandTryTargetAPILock | 1156 eCommandProcessMustBeLaunched | 1157 eCommandProcessMustBePaused ), 1158 m_options (interpreter) 1159 { 1160 CommandArgumentEntry arg; 1161 CommandArgumentData line_num_arg; 1162 1163 // Define the first (and only) variant of this arg. 1164 line_num_arg.arg_type = eArgTypeLineNum; 1165 line_num_arg.arg_repetition = eArgRepeatPlain; 1166 1167 // There is only one variant this argument could be; put it into the argument entry. 1168 arg.push_back (line_num_arg); 1169 1170 // Push the data for the first argument into the m_arguments vector. 1171 m_arguments.push_back (arg); 1172 } 1173 1174 1175 ~CommandObjectThreadUntil () override 1176 { 1177 } 1178 1179 Options * 1180 GetOptions () override 1181 { 1182 return &m_options; 1183 } 1184 1185 protected: 1186 bool 1187 DoExecute (Args& command, CommandReturnObject &result) override 1188 { 1189 bool synchronous_execution = m_interpreter.GetSynchronous (); 1190 1191 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1192 if (target == NULL) 1193 { 1194 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 1195 result.SetStatus (eReturnStatusFailed); 1196 return false; 1197 } 1198 1199 Process *process = m_exe_ctx.GetProcessPtr(); 1200 if (process == NULL) 1201 { 1202 result.AppendError ("need a valid process to step"); 1203 result.SetStatus (eReturnStatusFailed); 1204 1205 } 1206 else 1207 { 1208 Thread *thread = NULL; 1209 std::vector<uint32_t> line_numbers; 1210 1211 if (command.GetArgumentCount() >= 1) 1212 { 1213 size_t num_args = command.GetArgumentCount(); 1214 for (size_t i = 0; i < num_args; i++) 1215 { 1216 uint32_t line_number; 1217 line_number = StringConvert::ToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX); 1218 if (line_number == UINT32_MAX) 1219 { 1220 result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0)); 1221 result.SetStatus (eReturnStatusFailed); 1222 return false; 1223 } 1224 else 1225 line_numbers.push_back(line_number); 1226 } 1227 } 1228 else if (m_options.m_until_addrs.empty()) 1229 { 1230 result.AppendErrorWithFormat ("No line number or address provided:\n%s", GetSyntax()); 1231 result.SetStatus (eReturnStatusFailed); 1232 return false; 1233 } 1234 1235 1236 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) 1237 { 1238 thread = process->GetThreadList().GetSelectedThread().get(); 1239 } 1240 else 1241 { 1242 thread = process->GetThreadList().FindThreadByIndexID(m_options.m_thread_idx).get(); 1243 } 1244 1245 if (thread == NULL) 1246 { 1247 const uint32_t num_threads = process->GetThreadList().GetSize(); 1248 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 1249 m_options.m_thread_idx, 1250 num_threads); 1251 result.SetStatus (eReturnStatusFailed); 1252 return false; 1253 } 1254 1255 const bool abort_other_plans = false; 1256 1257 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get(); 1258 if (frame == NULL) 1259 { 1260 1261 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", 1262 m_options.m_frame_idx, 1263 m_options.m_thread_idx); 1264 result.SetStatus (eReturnStatusFailed); 1265 return false; 1266 } 1267 1268 ThreadPlanSP new_plan_sp; 1269 1270 if (frame->HasDebugInformation ()) 1271 { 1272 // Finally we got here... Translate the given line number to a bunch of addresses: 1273 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit)); 1274 LineTable *line_table = NULL; 1275 if (sc.comp_unit) 1276 line_table = sc.comp_unit->GetLineTable(); 1277 1278 if (line_table == NULL) 1279 { 1280 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n", 1281 m_options.m_frame_idx, m_options.m_thread_idx); 1282 result.SetStatus (eReturnStatusFailed); 1283 return false; 1284 } 1285 1286 LineEntry function_start; 1287 uint32_t index_ptr = 0, end_ptr; 1288 std::vector<addr_t> address_list; 1289 1290 // Find the beginning & end index of the 1291 AddressRange fun_addr_range = sc.function->GetAddressRange(); 1292 Address fun_start_addr = fun_addr_range.GetBaseAddress(); 1293 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr); 1294 1295 Address fun_end_addr(fun_start_addr.GetSection(), 1296 fun_start_addr.GetOffset() + fun_addr_range.GetByteSize()); 1297 1298 bool all_in_function = true; 1299 1300 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr); 1301 1302 for (uint32_t line_number : line_numbers) 1303 { 1304 uint32_t start_idx_ptr = index_ptr; 1305 while (start_idx_ptr <= end_ptr) 1306 { 1307 LineEntry line_entry; 1308 const bool exact = false; 1309 start_idx_ptr = sc.comp_unit->FindLineEntry(start_idx_ptr, line_number, sc.comp_unit, exact, &line_entry); 1310 if (start_idx_ptr == UINT32_MAX) 1311 break; 1312 1313 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target); 1314 if (address != LLDB_INVALID_ADDRESS) 1315 { 1316 if (fun_addr_range.ContainsLoadAddress (address, target)) 1317 address_list.push_back (address); 1318 else 1319 all_in_function = false; 1320 } 1321 start_idx_ptr++; 1322 } 1323 } 1324 1325 for (lldb::addr_t address : m_options.m_until_addrs) 1326 { 1327 if (fun_addr_range.ContainsLoadAddress (address, target)) 1328 address_list.push_back (address); 1329 else 1330 all_in_function = false; 1331 } 1332 1333 if (address_list.size() == 0) 1334 { 1335 if (all_in_function) 1336 result.AppendErrorWithFormat ("No line entries matching until target.\n"); 1337 else 1338 result.AppendErrorWithFormat ("Until target outside of the current function.\n"); 1339 1340 result.SetStatus (eReturnStatusFailed); 1341 return false; 1342 } 1343 1344 new_plan_sp = thread->QueueThreadPlanForStepUntil (abort_other_plans, 1345 &address_list.front(), 1346 address_list.size(), 1347 m_options.m_stop_others, 1348 m_options.m_frame_idx); 1349 // User level plans should be master plans so they can be interrupted (e.g. by hitting a breakpoint) 1350 // and other plans executed by the user (stepping around the breakpoint) and then a "continue" 1351 // will resume the original plan. 1352 new_plan_sp->SetIsMasterPlan (true); 1353 new_plan_sp->SetOkayToDiscard(false); 1354 } 1355 else 1356 { 1357 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", 1358 m_options.m_frame_idx, 1359 m_options.m_thread_idx); 1360 result.SetStatus (eReturnStatusFailed); 1361 return false; 1362 1363 } 1364 1365 1366 1367 process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx); 1368 1369 StreamString stream; 1370 Error error; 1371 if (synchronous_execution) 1372 error = process->ResumeSynchronous (&stream); 1373 else 1374 error = process->Resume (); 1375 1376 if (error.Success()) 1377 { 1378 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); 1379 if (synchronous_execution) 1380 { 1381 // If any state changed events had anything to say, add that to the result 1382 if (stream.GetData()) 1383 result.AppendMessage(stream.GetData()); 1384 1385 result.SetDidChangeProcessState (true); 1386 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1387 } 1388 else 1389 { 1390 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 1391 } 1392 } 1393 else 1394 { 1395 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 1396 result.SetStatus (eReturnStatusFailed); 1397 } 1398 1399 } 1400 return result.Succeeded(); 1401 } 1402 1403 CommandOptions m_options; 1404 1405 }; 1406 1407 OptionDefinition 1408 CommandObjectThreadUntil::CommandOptions::g_option_table[] = 1409 { 1410 { LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"}, 1411 { LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"}, 1412 { LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, NULL, g_duo_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping this one"}, 1413 { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression, "Run until we reach the specified address, or leave the function - can be specified multiple times."}, 1414 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1415 }; 1416 1417 1418 //------------------------------------------------------------------------- 1419 // CommandObjectThreadSelect 1420 //------------------------------------------------------------------------- 1421 1422 class CommandObjectThreadSelect : public CommandObjectParsed 1423 { 1424 public: 1425 1426 CommandObjectThreadSelect (CommandInterpreter &interpreter) : 1427 CommandObjectParsed (interpreter, 1428 "thread select", 1429 "Select a thread as the currently active thread.", 1430 NULL, 1431 eCommandRequiresProcess | 1432 eCommandTryTargetAPILock | 1433 eCommandProcessMustBeLaunched | 1434 eCommandProcessMustBePaused ) 1435 { 1436 CommandArgumentEntry arg; 1437 CommandArgumentData thread_idx_arg; 1438 1439 // Define the first (and only) variant of this arg. 1440 thread_idx_arg.arg_type = eArgTypeThreadIndex; 1441 thread_idx_arg.arg_repetition = eArgRepeatPlain; 1442 1443 // There is only one variant this argument could be; put it into the argument entry. 1444 arg.push_back (thread_idx_arg); 1445 1446 // Push the data for the first argument into the m_arguments vector. 1447 m_arguments.push_back (arg); 1448 } 1449 1450 1451 ~CommandObjectThreadSelect () override 1452 { 1453 } 1454 1455 protected: 1456 bool 1457 DoExecute (Args& command, CommandReturnObject &result) override 1458 { 1459 Process *process = m_exe_ctx.GetProcessPtr(); 1460 if (process == NULL) 1461 { 1462 result.AppendError ("no process"); 1463 result.SetStatus (eReturnStatusFailed); 1464 return false; 1465 } 1466 else if (command.GetArgumentCount() != 1) 1467 { 1468 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1469 result.SetStatus (eReturnStatusFailed); 1470 return false; 1471 } 1472 1473 uint32_t index_id = StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0); 1474 1475 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get(); 1476 if (new_thread == NULL) 1477 { 1478 result.AppendErrorWithFormat ("invalid thread #%s.\n", command.GetArgumentAtIndex(0)); 1479 result.SetStatus (eReturnStatusFailed); 1480 return false; 1481 } 1482 1483 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true); 1484 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1485 1486 return result.Succeeded(); 1487 } 1488 1489 }; 1490 1491 1492 //------------------------------------------------------------------------- 1493 // CommandObjectThreadList 1494 //------------------------------------------------------------------------- 1495 1496 class CommandObjectThreadList : public CommandObjectParsed 1497 { 1498 public: 1499 1500 1501 CommandObjectThreadList (CommandInterpreter &interpreter): 1502 CommandObjectParsed (interpreter, 1503 "thread list", 1504 "Show a summary of all current threads in a process.", 1505 "thread list", 1506 eCommandRequiresProcess | 1507 eCommandTryTargetAPILock | 1508 eCommandProcessMustBeLaunched | 1509 eCommandProcessMustBePaused ) 1510 { 1511 } 1512 1513 ~CommandObjectThreadList() override 1514 { 1515 } 1516 1517 protected: 1518 bool 1519 DoExecute (Args& command, CommandReturnObject &result) override 1520 { 1521 Stream &strm = result.GetOutputStream(); 1522 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1523 Process *process = m_exe_ctx.GetProcessPtr(); 1524 const bool only_threads_with_stop_reason = false; 1525 const uint32_t start_frame = 0; 1526 const uint32_t num_frames = 0; 1527 const uint32_t num_frames_with_source = 0; 1528 process->GetStatus(strm); 1529 process->GetThreadStatus (strm, 1530 only_threads_with_stop_reason, 1531 start_frame, 1532 num_frames, 1533 num_frames_with_source); 1534 return result.Succeeded(); 1535 } 1536 }; 1537 1538 //------------------------------------------------------------------------- 1539 // CommandObjectThreadInfo 1540 //------------------------------------------------------------------------- 1541 1542 class CommandObjectThreadInfo : public CommandObjectIterateOverThreads 1543 { 1544 public: 1545 1546 CommandObjectThreadInfo (CommandInterpreter &interpreter) : 1547 CommandObjectIterateOverThreads (interpreter, 1548 "thread info", 1549 "Show an extended summary of information about thread(s) in a process.", 1550 "thread info", 1551 eCommandRequiresProcess | 1552 eCommandTryTargetAPILock | 1553 eCommandProcessMustBeLaunched | 1554 eCommandProcessMustBePaused), 1555 m_options (interpreter) 1556 { 1557 m_add_return = false; 1558 } 1559 1560 class CommandOptions : public Options 1561 { 1562 public: 1563 1564 CommandOptions (CommandInterpreter &interpreter) : 1565 Options (interpreter) 1566 { 1567 OptionParsingStarting (); 1568 } 1569 1570 void 1571 OptionParsingStarting () override 1572 { 1573 m_json_thread = false; 1574 m_json_stopinfo = false; 1575 } 1576 1577 ~CommandOptions () override 1578 { 1579 } 1580 1581 Error 1582 SetOptionValue (uint32_t option_idx, const char *option_arg) override 1583 { 1584 const int short_option = m_getopt_table[option_idx].val; 1585 Error error; 1586 1587 switch (short_option) 1588 { 1589 case 'j': 1590 m_json_thread = true; 1591 break; 1592 1593 case 's': 1594 m_json_stopinfo = true; 1595 break; 1596 1597 default: 1598 return Error("invalid short option character '%c'", short_option); 1599 1600 } 1601 return error; 1602 } 1603 1604 const OptionDefinition* 1605 GetDefinitions () override 1606 { 1607 return g_option_table; 1608 } 1609 1610 bool m_json_thread; 1611 bool m_json_stopinfo; 1612 1613 static OptionDefinition g_option_table[]; 1614 }; 1615 1616 Options * 1617 GetOptions () override 1618 { 1619 return &m_options; 1620 } 1621 1622 ~CommandObjectThreadInfo () override 1623 { 1624 } 1625 1626 bool 1627 HandleOneThread (Thread &thread, CommandReturnObject &result) override 1628 { 1629 Stream &strm = result.GetOutputStream(); 1630 if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo)) 1631 { 1632 result.AppendErrorWithFormat ("error displaying info for thread: \"%d\"\n", thread.GetIndexID()); 1633 result.SetStatus (eReturnStatusFailed); 1634 return false; 1635 } 1636 return true; 1637 } 1638 1639 CommandOptions m_options; 1640 1641 }; 1642 1643 OptionDefinition 1644 CommandObjectThreadInfo::CommandOptions::g_option_table[] = 1645 { 1646 { LLDB_OPT_SET_ALL, false, "json",'j', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the thread info in JSON format."}, 1647 { LLDB_OPT_SET_ALL, false, "stop-info",'s', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the extended stop info in JSON format."}, 1648 1649 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1650 }; 1651 1652 1653 //------------------------------------------------------------------------- 1654 // CommandObjectThreadReturn 1655 //------------------------------------------------------------------------- 1656 1657 class CommandObjectThreadReturn : public CommandObjectRaw 1658 { 1659 public: 1660 class CommandOptions : public Options 1661 { 1662 public: 1663 1664 CommandOptions (CommandInterpreter &interpreter) : 1665 Options (interpreter), 1666 m_from_expression (false) 1667 { 1668 // Keep default values of all options in one place: OptionParsingStarting () 1669 OptionParsingStarting (); 1670 } 1671 1672 ~CommandOptions () override 1673 { 1674 } 1675 1676 Error 1677 SetOptionValue (uint32_t option_idx, const char *option_arg) override 1678 { 1679 Error error; 1680 const int short_option = m_getopt_table[option_idx].val; 1681 1682 switch (short_option) 1683 { 1684 case 'x': 1685 { 1686 bool success; 1687 bool tmp_value = Args::StringToBoolean (option_arg, false, &success); 1688 if (success) 1689 m_from_expression = tmp_value; 1690 else 1691 { 1692 error.SetErrorStringWithFormat ("invalid boolean value '%s' for 'x' option", option_arg); 1693 } 1694 } 1695 break; 1696 default: 1697 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1698 break; 1699 1700 } 1701 return error; 1702 } 1703 1704 void 1705 OptionParsingStarting () override 1706 { 1707 m_from_expression = false; 1708 } 1709 1710 const OptionDefinition* 1711 GetDefinitions () override 1712 { 1713 return g_option_table; 1714 } 1715 1716 bool m_from_expression; 1717 1718 // Options table: Required for subclasses of Options. 1719 1720 static OptionDefinition g_option_table[]; 1721 1722 // Instance variables to hold the values for command options. 1723 }; 1724 1725 Options * 1726 GetOptions () override 1727 { 1728 return &m_options; 1729 } 1730 1731 CommandObjectThreadReturn (CommandInterpreter &interpreter) : 1732 CommandObjectRaw (interpreter, 1733 "thread return", 1734 "Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value," 1735 " or with the -x option from the innermost function evaluation.", 1736 "thread return", 1737 eCommandRequiresFrame | 1738 eCommandTryTargetAPILock | 1739 eCommandProcessMustBeLaunched | 1740 eCommandProcessMustBePaused ), 1741 m_options (interpreter) 1742 { 1743 CommandArgumentEntry arg; 1744 CommandArgumentData expression_arg; 1745 1746 // Define the first (and only) variant of this arg. 1747 expression_arg.arg_type = eArgTypeExpression; 1748 expression_arg.arg_repetition = eArgRepeatOptional; 1749 1750 // There is only one variant this argument could be; put it into the argument entry. 1751 arg.push_back (expression_arg); 1752 1753 // Push the data for the first argument into the m_arguments vector. 1754 m_arguments.push_back (arg); 1755 1756 1757 } 1758 1759 ~CommandObjectThreadReturn() override 1760 { 1761 } 1762 1763 protected: 1764 1765 bool 1766 DoExecute (const char *command, CommandReturnObject &result) override 1767 { 1768 // I am going to handle this by hand, because I don't want you to have to say: 1769 // "thread return -- -5". 1770 if (command[0] == '-' && command[1] == 'x') 1771 { 1772 if (command && command[2] != '\0') 1773 result.AppendWarning("Return values ignored when returning from user called expressions"); 1774 1775 Thread *thread = m_exe_ctx.GetThreadPtr(); 1776 Error error; 1777 error = thread->UnwindInnermostExpression(); 1778 if (!error.Success()) 1779 { 1780 result.AppendErrorWithFormat ("Unwinding expression failed - %s.", error.AsCString()); 1781 result.SetStatus (eReturnStatusFailed); 1782 } 1783 else 1784 { 1785 bool success = thread->SetSelectedFrameByIndexNoisily (0, result.GetOutputStream()); 1786 if (success) 1787 { 1788 m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ()); 1789 result.SetStatus (eReturnStatusSuccessFinishResult); 1790 } 1791 else 1792 { 1793 result.AppendErrorWithFormat ("Could not select 0th frame after unwinding expression."); 1794 result.SetStatus (eReturnStatusFailed); 1795 } 1796 } 1797 return result.Succeeded(); 1798 } 1799 1800 ValueObjectSP return_valobj_sp; 1801 1802 StackFrameSP frame_sp = m_exe_ctx.GetFrameSP(); 1803 uint32_t frame_idx = frame_sp->GetFrameIndex(); 1804 1805 if (frame_sp->IsInlined()) 1806 { 1807 result.AppendError("Don't know how to return from inlined frames."); 1808 result.SetStatus (eReturnStatusFailed); 1809 return false; 1810 } 1811 1812 if (command && command[0] != '\0') 1813 { 1814 Target *target = m_exe_ctx.GetTargetPtr(); 1815 EvaluateExpressionOptions options; 1816 1817 options.SetUnwindOnError(true); 1818 options.SetUseDynamic(eNoDynamicValues); 1819 1820 ExpressionResults exe_results = eExpressionSetupError; 1821 exe_results = target->EvaluateExpression (command, 1822 frame_sp.get(), 1823 return_valobj_sp, 1824 options); 1825 if (exe_results != eExpressionCompleted) 1826 { 1827 if (return_valobj_sp) 1828 result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString()); 1829 else 1830 result.AppendErrorWithFormat("Unknown error evaluating result expression."); 1831 result.SetStatus (eReturnStatusFailed); 1832 return false; 1833 1834 } 1835 } 1836 1837 Error error; 1838 ThreadSP thread_sp = m_exe_ctx.GetThreadSP(); 1839 const bool broadcast = true; 1840 error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast); 1841 if (!error.Success()) 1842 { 1843 result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString()); 1844 result.SetStatus (eReturnStatusFailed); 1845 return false; 1846 } 1847 1848 result.SetStatus (eReturnStatusSuccessFinishResult); 1849 return true; 1850 } 1851 1852 CommandOptions m_options; 1853 1854 }; 1855 OptionDefinition 1856 CommandObjectThreadReturn::CommandOptions::g_option_table[] = 1857 { 1858 { LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Return from the innermost expression evaluation."}, 1859 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1860 }; 1861 1862 //------------------------------------------------------------------------- 1863 // CommandObjectThreadJump 1864 //------------------------------------------------------------------------- 1865 1866 class CommandObjectThreadJump : public CommandObjectParsed 1867 { 1868 public: 1869 class CommandOptions : public Options 1870 { 1871 public: 1872 1873 CommandOptions (CommandInterpreter &interpreter) : 1874 Options (interpreter) 1875 { 1876 OptionParsingStarting (); 1877 } 1878 1879 void 1880 OptionParsingStarting () override 1881 { 1882 m_filenames.Clear(); 1883 m_line_num = 0; 1884 m_line_offset = 0; 1885 m_load_addr = LLDB_INVALID_ADDRESS; 1886 m_force = false; 1887 } 1888 1889 ~CommandOptions () override 1890 { 1891 } 1892 1893 Error 1894 SetOptionValue (uint32_t option_idx, const char *option_arg) override 1895 { 1896 bool success; 1897 const int short_option = m_getopt_table[option_idx].val; 1898 Error error; 1899 1900 switch (short_option) 1901 { 1902 case 'f': 1903 m_filenames.AppendIfUnique (FileSpec(option_arg, false)); 1904 if (m_filenames.GetSize() > 1) 1905 return Error("only one source file expected."); 1906 break; 1907 case 'l': 1908 m_line_num = StringConvert::ToUInt32 (option_arg, 0, 0, &success); 1909 if (!success || m_line_num == 0) 1910 return Error("invalid line number: '%s'.", option_arg); 1911 break; 1912 case 'b': 1913 m_line_offset = StringConvert::ToSInt32 (option_arg, 0, 0, &success); 1914 if (!success) 1915 return Error("invalid line offset: '%s'.", option_arg); 1916 break; 1917 case 'a': 1918 { 1919 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 1920 m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); 1921 } 1922 break; 1923 case 'r': 1924 m_force = true; 1925 break; 1926 1927 default: 1928 return Error("invalid short option character '%c'", short_option); 1929 1930 } 1931 return error; 1932 } 1933 1934 const OptionDefinition* 1935 GetDefinitions () override 1936 { 1937 return g_option_table; 1938 } 1939 1940 FileSpecList m_filenames; 1941 uint32_t m_line_num; 1942 int32_t m_line_offset; 1943 lldb::addr_t m_load_addr; 1944 bool m_force; 1945 1946 static OptionDefinition g_option_table[]; 1947 }; 1948 1949 Options * 1950 GetOptions () override 1951 { 1952 return &m_options; 1953 } 1954 1955 CommandObjectThreadJump (CommandInterpreter &interpreter) : 1956 CommandObjectParsed (interpreter, 1957 "thread jump", 1958 "Sets the program counter to a new address.", 1959 "thread jump", 1960 eCommandRequiresFrame | 1961 eCommandTryTargetAPILock | 1962 eCommandProcessMustBeLaunched | 1963 eCommandProcessMustBePaused ), 1964 m_options (interpreter) 1965 { 1966 } 1967 1968 ~CommandObjectThreadJump() override 1969 { 1970 } 1971 1972 protected: 1973 1974 bool DoExecute (Args& args, CommandReturnObject &result) override 1975 { 1976 RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); 1977 StackFrame *frame = m_exe_ctx.GetFramePtr(); 1978 Thread *thread = m_exe_ctx.GetThreadPtr(); 1979 Target *target = m_exe_ctx.GetTargetPtr(); 1980 const SymbolContext &sym_ctx = frame->GetSymbolContext (eSymbolContextLineEntry); 1981 1982 if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 1983 { 1984 // Use this address directly. 1985 Address dest = Address(m_options.m_load_addr); 1986 1987 lldb::addr_t callAddr = dest.GetCallableLoadAddress (target); 1988 if (callAddr == LLDB_INVALID_ADDRESS) 1989 { 1990 result.AppendErrorWithFormat ("Invalid destination address."); 1991 result.SetStatus (eReturnStatusFailed); 1992 return false; 1993 } 1994 1995 if (!reg_ctx->SetPC (callAddr)) 1996 { 1997 result.AppendErrorWithFormat ("Error changing PC value for thread %d.", thread->GetIndexID()); 1998 result.SetStatus (eReturnStatusFailed); 1999 return false; 2000 } 2001 } 2002 else 2003 { 2004 // Pick either the absolute line, or work out a relative one. 2005 int32_t line = (int32_t)m_options.m_line_num; 2006 if (line == 0) 2007 line = sym_ctx.line_entry.line + m_options.m_line_offset; 2008 2009 // Try the current file, but override if asked. 2010 FileSpec file = sym_ctx.line_entry.file; 2011 if (m_options.m_filenames.GetSize() == 1) 2012 file = m_options.m_filenames.GetFileSpecAtIndex(0); 2013 2014 if (!file) 2015 { 2016 result.AppendErrorWithFormat ("No source file available for the current location."); 2017 result.SetStatus (eReturnStatusFailed); 2018 return false; 2019 } 2020 2021 std::string warnings; 2022 Error err = thread->JumpToLine (file, line, m_options.m_force, &warnings); 2023 2024 if (err.Fail()) 2025 { 2026 result.SetError (err); 2027 return false; 2028 } 2029 2030 if (!warnings.empty()) 2031 result.AppendWarning (warnings.c_str()); 2032 } 2033 2034 result.SetStatus (eReturnStatusSuccessFinishResult); 2035 return true; 2036 } 2037 2038 CommandOptions m_options; 2039 }; 2040 OptionDefinition 2041 CommandObjectThreadJump::CommandOptions::g_option_table[] = 2042 { 2043 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, 2044 "Specifies the source file to jump to."}, 2045 2046 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum, 2047 "Specifies the line number to jump to."}, 2048 2049 { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, 2050 "Jumps by a relative line offset from the current line."}, 2051 2052 { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression, 2053 "Jumps to a specific address."}, 2054 2055 { LLDB_OPT_SET_1| 2056 LLDB_OPT_SET_2| 2057 LLDB_OPT_SET_3, false, "force",'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,"Allows the PC to leave the current function."}, 2058 2059 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 2060 }; 2061 2062 //------------------------------------------------------------------------- 2063 // Next are the subcommands of CommandObjectMultiwordThreadPlan 2064 //------------------------------------------------------------------------- 2065 2066 2067 //------------------------------------------------------------------------- 2068 // CommandObjectThreadPlanList 2069 //------------------------------------------------------------------------- 2070 class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads 2071 { 2072 public: 2073 2074 class CommandOptions : public Options 2075 { 2076 public: 2077 2078 CommandOptions (CommandInterpreter &interpreter) : 2079 Options(interpreter) 2080 { 2081 // Keep default values of all options in one place: OptionParsingStarting () 2082 OptionParsingStarting (); 2083 } 2084 2085 ~CommandOptions () override 2086 { 2087 } 2088 2089 Error 2090 SetOptionValue (uint32_t option_idx, const char *option_arg) override 2091 { 2092 Error error; 2093 const int short_option = m_getopt_table[option_idx].val; 2094 2095 switch (short_option) 2096 { 2097 case 'i': 2098 { 2099 m_internal = true; 2100 } 2101 break; 2102 case 'v': 2103 { 2104 m_verbose = true; 2105 } 2106 break; 2107 default: 2108 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 2109 break; 2110 2111 } 2112 return error; 2113 } 2114 2115 void 2116 OptionParsingStarting () override 2117 { 2118 m_verbose = false; 2119 m_internal = false; 2120 } 2121 2122 const OptionDefinition* 2123 GetDefinitions () override 2124 { 2125 return g_option_table; 2126 } 2127 2128 // Options table: Required for subclasses of Options. 2129 2130 static OptionDefinition g_option_table[]; 2131 2132 // Instance variables to hold the values for command options. 2133 bool m_verbose; 2134 bool m_internal; 2135 }; 2136 2137 CommandObjectThreadPlanList (CommandInterpreter &interpreter) : 2138 CommandObjectIterateOverThreads (interpreter, 2139 "thread plan list", 2140 "Show thread plans for one or more threads. If no threads are specified, show the " 2141 "currently selected thread. Use the thread-index \"all\" to see all threads.", 2142 NULL, 2143 eCommandRequiresProcess | 2144 eCommandRequiresThread | 2145 eCommandTryTargetAPILock | 2146 eCommandProcessMustBeLaunched | 2147 eCommandProcessMustBePaused ), 2148 m_options(interpreter) 2149 { 2150 } 2151 2152 ~CommandObjectThreadPlanList () override 2153 { 2154 } 2155 2156 Options * 2157 GetOptions () override 2158 { 2159 return &m_options; 2160 } 2161 2162 protected: 2163 bool 2164 HandleOneThread (Thread &thread, CommandReturnObject &result) override 2165 { 2166 Stream &strm = result.GetOutputStream(); 2167 DescriptionLevel desc_level = eDescriptionLevelFull; 2168 if (m_options.m_verbose) 2169 desc_level = eDescriptionLevelVerbose; 2170 2171 thread.DumpThreadPlans (&strm, desc_level, m_options.m_internal, true); 2172 return true; 2173 } 2174 CommandOptions m_options; 2175 }; 2176 2177 OptionDefinition 2178 CommandObjectThreadPlanList::CommandOptions::g_option_table[] = 2179 { 2180 { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display more information about the thread plans"}, 2181 { LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display internal as well as user thread plans"}, 2182 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 2183 }; 2184 2185 class CommandObjectThreadPlanDiscard : public CommandObjectParsed 2186 { 2187 public: 2188 CommandObjectThreadPlanDiscard (CommandInterpreter &interpreter) : 2189 CommandObjectParsed (interpreter, 2190 "thread plan discard", 2191 "Discards thread plans up to and including the plan passed as the command argument." 2192 "Only user visible plans can be discarded, use the index from \"thread plan list\"" 2193 " without the \"-i\" argument.", 2194 NULL, 2195 eCommandRequiresProcess | 2196 eCommandRequiresThread | 2197 eCommandTryTargetAPILock | 2198 eCommandProcessMustBeLaunched | 2199 eCommandProcessMustBePaused ) 2200 { 2201 CommandArgumentEntry arg; 2202 CommandArgumentData plan_index_arg; 2203 2204 // Define the first (and only) variant of this arg. 2205 plan_index_arg.arg_type = eArgTypeUnsignedInteger; 2206 plan_index_arg.arg_repetition = eArgRepeatPlain; 2207 2208 // There is only one variant this argument could be; put it into the argument entry. 2209 arg.push_back (plan_index_arg); 2210 2211 // Push the data for the first argument into the m_arguments vector. 2212 m_arguments.push_back (arg); 2213 } 2214 2215 ~CommandObjectThreadPlanDiscard () override {} 2216 2217 bool 2218 DoExecute (Args& args, CommandReturnObject &result) override 2219 { 2220 Thread *thread = m_exe_ctx.GetThreadPtr(); 2221 if (args.GetArgumentCount() != 1) 2222 { 2223 result.AppendErrorWithFormat("Too many arguments, expected one - the thread plan index - but got %zu.", 2224 args.GetArgumentCount()); 2225 result.SetStatus (eReturnStatusFailed); 2226 return false; 2227 } 2228 2229 bool success; 2230 uint32_t thread_plan_idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success); 2231 if (!success) 2232 { 2233 result.AppendErrorWithFormat("Invalid thread index: \"%s\" - should be unsigned int.", 2234 args.GetArgumentAtIndex(0)); 2235 result.SetStatus (eReturnStatusFailed); 2236 return false; 2237 } 2238 2239 if (thread_plan_idx == 0) 2240 { 2241 result.AppendErrorWithFormat("You wouldn't really want me to discard the base thread plan."); 2242 result.SetStatus (eReturnStatusFailed); 2243 return false; 2244 } 2245 2246 if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) 2247 { 2248 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2249 return true; 2250 } 2251 else 2252 { 2253 result.AppendErrorWithFormat("Could not find User thread plan with index %s.", 2254 args.GetArgumentAtIndex(0)); 2255 result.SetStatus (eReturnStatusFailed); 2256 return false; 2257 } 2258 } 2259 }; 2260 2261 //------------------------------------------------------------------------- 2262 // CommandObjectMultiwordThreadPlan 2263 //------------------------------------------------------------------------- 2264 2265 class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword 2266 { 2267 public: 2268 CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) : 2269 CommandObjectMultiword (interpreter, 2270 "plan", 2271 "A set of subcommands for accessing the thread plans controlling execution control on one or more threads.", 2272 "thread plan <subcommand> [<subcommand objects]") 2273 { 2274 LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadPlanList (interpreter))); 2275 LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter))); 2276 } 2277 2278 ~CommandObjectMultiwordThreadPlan () override {} 2279 2280 2281 }; 2282 2283 //------------------------------------------------------------------------- 2284 // CommandObjectMultiwordThread 2285 //------------------------------------------------------------------------- 2286 2287 CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) : 2288 CommandObjectMultiword (interpreter, 2289 "thread", 2290 "A set of commands for operating on one or more threads within a running process.", 2291 "thread <subcommand> [<subcommand-options>]") 2292 { 2293 LoadSubCommand ("backtrace", CommandObjectSP (new CommandObjectThreadBacktrace (interpreter))); 2294 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter))); 2295 LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter))); 2296 LoadSubCommand ("return", CommandObjectSP (new CommandObjectThreadReturn (interpreter))); 2297 LoadSubCommand ("jump", CommandObjectSP (new CommandObjectThreadJump (interpreter))); 2298 LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter))); 2299 LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter))); 2300 LoadSubCommand ("info", CommandObjectSP (new CommandObjectThreadInfo (interpreter))); 2301 LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2302 interpreter, 2303 "thread step-in", 2304 "Source level single step in specified thread (current thread, if none specified).", 2305 NULL, 2306 eStepTypeInto, 2307 eStepScopeSource))); 2308 2309 LoadSubCommand ("step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2310 interpreter, 2311 "thread step-out", 2312 "Finish executing the function of the currently selected frame and return to its call site in specified thread (current thread, if none specified).", 2313 NULL, 2314 eStepTypeOut, 2315 eStepScopeSource))); 2316 2317 LoadSubCommand ("step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2318 interpreter, 2319 "thread step-over", 2320 "Source level single step in specified thread (current thread, if none specified), stepping over calls.", 2321 NULL, 2322 eStepTypeOver, 2323 eStepScopeSource))); 2324 2325 LoadSubCommand ("step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2326 interpreter, 2327 "thread step-inst", 2328 "Single step one instruction in specified thread (current thread, if none specified).", 2329 NULL, 2330 eStepTypeTrace, 2331 eStepScopeInstruction))); 2332 2333 LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2334 interpreter, 2335 "thread step-inst-over", 2336 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.", 2337 NULL, 2338 eStepTypeTraceOver, 2339 eStepScopeInstruction))); 2340 2341 LoadSubCommand ("step-scripted", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2342 interpreter, 2343 "thread step-scripted", 2344 "Step as instructed by the script class passed in the -C option.", 2345 NULL, 2346 eStepTypeScripted, 2347 eStepScopeSource))); 2348 2349 LoadSubCommand ("plan", CommandObjectSP (new CommandObjectMultiwordThreadPlan(interpreter))); 2350 } 2351 2352 CommandObjectMultiwordThread::~CommandObjectMultiwordThread () 2353 { 2354 } 2355 2356 2357