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