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