1 //===-- CommandObjectThread.cpp -------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "CommandObjectThread.h"
15 #include "CommandObjectThreadUtil.h"
16 #include "CommandObjectTrace.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/ValueObject.h"
19 #include "lldb/Host/OptionParser.h"
20 #include "lldb/Interpreter/CommandInterpreter.h"
21 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
22 #include "lldb/Interpreter/CommandReturnObject.h"
23 #include "lldb/Interpreter/OptionArgParser.h"
24 #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
25 #include "lldb/Interpreter/Options.h"
26 #include "lldb/Symbol/CompileUnit.h"
27 #include "lldb/Symbol/Function.h"
28 #include "lldb/Symbol/LineEntry.h"
29 #include "lldb/Symbol/LineTable.h"
30 #include "lldb/Target/Process.h"
31 #include "lldb/Target/RegisterContext.h"
32 #include "lldb/Target/SystemRuntime.h"
33 #include "lldb/Target/Target.h"
34 #include "lldb/Target/Thread.h"
35 #include "lldb/Target/ThreadPlan.h"
36 #include "lldb/Target/ThreadPlanStepInRange.h"
37 #include "lldb/Target/Trace.h"
38 #include "lldb/Target/TraceDumper.h"
39 #include "lldb/Utility/State.h"
42 using namespace lldb_private
;
44 // CommandObjectThreadBacktrace
45 #define LLDB_OPTIONS_thread_backtrace
46 #include "CommandOptions.inc"
48 class CommandObjectThreadBacktrace
: public CommandObjectIterateOverThreads
{
50 class CommandOptions
: public Options
{
53 // Keep default values of all options in one place: OptionParsingStarting
55 OptionParsingStarting(nullptr);
58 ~CommandOptions() override
= default;
60 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
61 ExecutionContext
*execution_context
) override
{
63 const int short_option
= m_getopt_table
[option_idx
].val
;
65 switch (short_option
) {
67 if (option_arg
.getAsInteger(0, m_count
)) {
69 error
.SetErrorStringWithFormat(
70 "invalid integer value for option '%c'", short_option
);
74 if (option_arg
.getAsInteger(0, m_start
))
75 error
.SetErrorStringWithFormat(
76 "invalid integer value for option '%c'", short_option
);
80 m_extended_backtrace
=
81 OptionArgParser::ToBoolean(option_arg
, false, &success
);
83 error
.SetErrorStringWithFormat(
84 "invalid boolean value for option '%c'", short_option
);
87 llvm_unreachable("Unimplemented option");
92 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
95 m_extended_backtrace
= false;
98 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
99 return llvm::ArrayRef(g_thread_backtrace_options
);
102 // Instance variables to hold the values for command options.
105 bool m_extended_backtrace
;
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 "
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.",
120 eCommandRequiresProcess
| eCommandRequiresThread
|
121 eCommandTryTargetAPILock
| eCommandProcessMustBeLaunched
|
122 eCommandProcessMustBePaused
) {}
124 ~CommandObjectThreadBacktrace() override
= default;
126 Options
*GetOptions() override
{ return &m_options
; }
128 std::optional
<std::string
> GetRepeatCommand(Args
¤t_args
,
129 uint32_t idx
) override
{
130 llvm::StringRef
count_opt("--count");
131 llvm::StringRef
start_opt("--start");
133 // If no "count" was provided, we are dumping the entire backtrace, so
134 // there isn't a repeat command. So we search for the count option in
135 // the args, and if we find it, we make a copy and insert or modify the
136 // start option's value to start count indices greater.
138 Args
copy_args(current_args
);
139 size_t num_entries
= copy_args
.GetArgumentCount();
140 // These two point at the index of the option value if found.
141 size_t count_idx
= 0;
142 size_t start_idx
= 0;
143 size_t count_val
= 0;
144 size_t start_val
= 0;
146 for (size_t idx
= 0; idx
< num_entries
; idx
++) {
147 llvm::StringRef arg_string
= copy_args
[idx
].ref();
148 if (arg_string
.equals("-c") || count_opt
.startswith(arg_string
)) {
150 if (idx
== num_entries
)
153 if (copy_args
[idx
].ref().getAsInteger(0, count_val
))
155 } else if (arg_string
.equals("-s") || start_opt
.startswith(arg_string
)) {
157 if (idx
== num_entries
)
160 if (copy_args
[idx
].ref().getAsInteger(0, start_val
))
167 std::string new_start_val
= llvm::formatv("{0}", start_val
+ count_val
);
168 if (start_idx
== 0) {
169 copy_args
.AppendArgument(start_opt
);
170 copy_args
.AppendArgument(new_start_val
);
172 copy_args
.ReplaceArgumentAtIndex(start_idx
, new_start_val
);
174 std::string repeat_command
;
175 if (!copy_args
.GetQuotedCommandString(repeat_command
))
177 return repeat_command
;
181 void DoExtendedBacktrace(Thread
*thread
, CommandReturnObject
&result
) {
182 SystemRuntime
*runtime
= thread
->GetProcess()->GetSystemRuntime();
184 Stream
&strm
= result
.GetOutputStream();
185 const std::vector
<ConstString
> &types
=
186 runtime
->GetExtendedBacktraceTypes();
187 for (auto type
: types
) {
188 ThreadSP ext_thread_sp
= runtime
->GetExtendedBacktraceThread(
189 thread
->shared_from_this(), type
);
190 if (ext_thread_sp
&& ext_thread_sp
->IsValid()) {
191 const uint32_t num_frames_with_source
= 0;
192 const bool stop_format
= false;
194 if (ext_thread_sp
->GetStatus(strm
, m_options
.m_start
,
196 num_frames_with_source
, stop_format
)) {
197 DoExtendedBacktrace(ext_thread_sp
.get(), result
);
204 bool HandleOneThread(lldb::tid_t tid
, CommandReturnObject
&result
) override
{
206 m_exe_ctx
.GetProcessPtr()->GetThreadList().FindThreadByID(tid
);
208 result
.AppendErrorWithFormat(
209 "thread disappeared while computing backtraces: 0x%" PRIx64
"\n",
214 Thread
*thread
= thread_sp
.get();
216 Stream
&strm
= result
.GetOutputStream();
218 // Only dump stack info if we processing unique stacks.
219 const bool only_stacks
= m_unique_stacks
;
221 // Don't show source context when doing backtraces.
222 const uint32_t num_frames_with_source
= 0;
223 const bool stop_format
= true;
224 if (!thread
->GetStatus(strm
, m_options
.m_start
, m_options
.m_count
,
225 num_frames_with_source
, stop_format
, only_stacks
)) {
226 result
.AppendErrorWithFormat(
227 "error displaying backtrace for thread: \"0x%4.4x\"\n",
228 thread
->GetIndexID());
231 if (m_options
.m_extended_backtrace
) {
232 if (!INTERRUPT_REQUESTED(GetDebugger(),
233 "Interrupt skipped extended backtrace")) {
234 DoExtendedBacktrace(thread
, result
);
241 CommandOptions m_options
;
244 enum StepScope
{ eStepScopeSource
, eStepScopeInstruction
};
246 #define LLDB_OPTIONS_thread_step_scope
247 #include "CommandOptions.inc"
249 class ThreadStepScopeOptionGroup
: public OptionGroup
{
251 ThreadStepScopeOptionGroup() {
252 // Keep default values of all options in one place: OptionParsingStarting
254 OptionParsingStarting(nullptr);
257 ~ThreadStepScopeOptionGroup() override
= default;
259 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
260 return llvm::ArrayRef(g_thread_step_scope_options
);
263 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
264 ExecutionContext
*execution_context
) override
{
266 const int short_option
=
267 g_thread_step_scope_options
[option_idx
].short_option
;
269 switch (short_option
) {
272 bool avoid_no_debug
=
273 OptionArgParser::ToBoolean(option_arg
, true, &success
);
275 error
.SetErrorStringWithFormat("invalid boolean value for option '%c'",
278 m_step_in_avoid_no_debug
= avoid_no_debug
? eLazyBoolYes
: eLazyBoolNo
;
284 bool avoid_no_debug
=
285 OptionArgParser::ToBoolean(option_arg
, true, &success
);
287 error
.SetErrorStringWithFormat("invalid boolean value for option '%c'",
290 m_step_out_avoid_no_debug
= avoid_no_debug
? eLazyBoolYes
: eLazyBoolNo
;
295 if (option_arg
.getAsInteger(0, m_step_count
))
296 error
.SetErrorStringWithFormat("invalid step count '%s'",
297 option_arg
.str().c_str());
301 auto enum_values
= GetDefinitions()[option_idx
].enum_values
;
302 m_run_mode
= (lldb::RunMode
)OptionArgParser::ToOptionEnum(
303 option_arg
, enum_values
, eOnlyDuringStepping
, error
);
307 if (option_arg
== "block") {
308 m_end_line_is_block_end
= true;
311 if (option_arg
.getAsInteger(0, m_end_line
))
312 error
.SetErrorStringWithFormat("invalid end line number '%s'",
313 option_arg
.str().c_str());
317 m_avoid_regexp
.clear();
318 m_avoid_regexp
.assign(std::string(option_arg
));
322 m_step_in_target
.clear();
323 m_step_in_target
.assign(std::string(option_arg
));
327 llvm_unreachable("Unimplemented option");
332 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
333 m_step_in_avoid_no_debug
= eLazyBoolCalculate
;
334 m_step_out_avoid_no_debug
= eLazyBoolCalculate
;
335 m_run_mode
= eOnlyDuringStepping
;
337 // Check if we are in Non-Stop mode
339 execution_context
? execution_context
->GetTargetSP() : TargetSP();
340 ProcessSP process_sp
=
341 execution_context
? execution_context
->GetProcessSP() : ProcessSP();
342 if (process_sp
&& process_sp
->GetSteppingRunsAllThreads())
343 m_run_mode
= eAllThreads
;
345 m_avoid_regexp
.clear();
346 m_step_in_target
.clear();
348 m_end_line
= LLDB_INVALID_LINE_NUMBER
;
349 m_end_line_is_block_end
= false;
352 // Instance variables to hold the values for command options.
353 LazyBool m_step_in_avoid_no_debug
;
354 LazyBool m_step_out_avoid_no_debug
;
356 std::string m_avoid_regexp
;
357 std::string m_step_in_target
;
358 uint32_t m_step_count
;
360 bool m_end_line_is_block_end
;
363 class CommandObjectThreadStepWithTypeAndScope
: public CommandObjectParsed
{
365 CommandObjectThreadStepWithTypeAndScope(CommandInterpreter
&interpreter
,
366 const char *name
, const char *help
,
369 StepScope step_scope
)
370 : CommandObjectParsed(interpreter
, name
, help
, syntax
,
371 eCommandRequiresProcess
| eCommandRequiresThread
|
372 eCommandTryTargetAPILock
|
373 eCommandProcessMustBeLaunched
|
374 eCommandProcessMustBePaused
),
375 m_step_type(step_type
), m_step_scope(step_scope
),
376 m_class_options("scripted step") {
377 CommandArgumentEntry arg
;
378 CommandArgumentData thread_id_arg
;
380 // Define the first (and only) variant of this arg.
381 thread_id_arg
.arg_type
= eArgTypeThreadID
;
382 thread_id_arg
.arg_repetition
= eArgRepeatOptional
;
384 // There is only one variant this argument could be; put it into the
386 arg
.push_back(thread_id_arg
);
388 // Push the data for the first argument into the m_arguments vector.
389 m_arguments
.push_back(arg
);
391 if (step_type
== eStepTypeScripted
) {
392 m_all_options
.Append(&m_class_options
, LLDB_OPT_SET_1
| LLDB_OPT_SET_2
,
395 m_all_options
.Append(&m_options
);
396 m_all_options
.Finalize();
399 ~CommandObjectThreadStepWithTypeAndScope() override
= default;
402 HandleArgumentCompletion(CompletionRequest
&request
,
403 OptionElementVector
&opt_element_vector
) override
{
404 if (request
.GetCursorIndex())
407 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
408 GetCommandInterpreter(), lldb::eThreadIndexCompletion
, request
,
412 Options
*GetOptions() override
{ return &m_all_options
; }
415 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
416 Process
*process
= m_exe_ctx
.GetProcessPtr();
417 bool synchronous_execution
= m_interpreter
.GetSynchronous();
419 const uint32_t num_threads
= process
->GetThreadList().GetSize();
420 Thread
*thread
= nullptr;
422 if (command
.GetArgumentCount() == 0) {
423 thread
= GetDefaultThread();
425 if (thread
== nullptr) {
426 result
.AppendError("no selected thread in process");
430 const char *thread_idx_cstr
= command
.GetArgumentAtIndex(0);
431 uint32_t step_thread_idx
;
433 if (!llvm::to_integer(thread_idx_cstr
, step_thread_idx
)) {
434 result
.AppendErrorWithFormat("invalid thread index '%s'.\n",
439 process
->GetThreadList().FindThreadByIndexID(step_thread_idx
).get();
440 if (thread
== nullptr) {
441 result
.AppendErrorWithFormat(
442 "Thread index %u is out of range (valid values are 0 - %u).\n",
443 step_thread_idx
, num_threads
);
448 if (m_step_type
== eStepTypeScripted
) {
449 if (m_class_options
.GetName().empty()) {
450 result
.AppendErrorWithFormat("empty class name for scripted step.");
452 } else if (!GetDebugger().GetScriptInterpreter()->CheckObjectExists(
453 m_class_options
.GetName().c_str())) {
454 result
.AppendErrorWithFormat(
455 "class for scripted step: \"%s\" does not exist.",
456 m_class_options
.GetName().c_str());
461 if (m_options
.m_end_line
!= LLDB_INVALID_LINE_NUMBER
&&
462 m_step_type
!= eStepTypeInto
) {
463 result
.AppendErrorWithFormat(
464 "end line option is only valid for step into");
468 const bool abort_other_plans
= false;
469 const lldb::RunMode stop_other_threads
= m_options
.m_run_mode
;
471 // This is a bit unfortunate, but not all the commands in this command
472 // object support only while stepping, so I use the bool for them.
473 bool bool_stop_other_threads
;
474 if (m_options
.m_run_mode
== eAllThreads
)
475 bool_stop_other_threads
= false;
476 else if (m_options
.m_run_mode
== eOnlyDuringStepping
)
477 bool_stop_other_threads
= (m_step_type
!= eStepTypeOut
);
479 bool_stop_other_threads
= true;
481 ThreadPlanSP new_plan_sp
;
482 Status new_plan_status
;
484 if (m_step_type
== eStepTypeInto
) {
485 StackFrame
*frame
= thread
->GetStackFrameAtIndex(0).get();
486 assert(frame
!= nullptr);
488 if (frame
->HasDebugInformation()) {
490 SymbolContext sc
= frame
->GetSymbolContext(eSymbolContextEverything
);
491 if (m_options
.m_end_line
!= LLDB_INVALID_LINE_NUMBER
) {
493 if (!sc
.GetAddressRangeFromHereToEndLine(m_options
.m_end_line
, range
,
495 result
.AppendErrorWithFormat("invalid end-line option: %s.",
499 } else if (m_options
.m_end_line_is_block_end
) {
501 Block
*block
= frame
->GetSymbolContext(eSymbolContextBlock
).block
;
503 result
.AppendErrorWithFormat("Could not find the current block.");
507 AddressRange block_range
;
508 Address pc_address
= frame
->GetFrameCodeAddress();
509 block
->GetRangeContainingAddress(pc_address
, block_range
);
510 if (!block_range
.GetBaseAddress().IsValid()) {
511 result
.AppendErrorWithFormat(
512 "Could not find the current block address.");
515 lldb::addr_t pc_offset_in_block
=
516 pc_address
.GetFileAddress() -
517 block_range
.GetBaseAddress().GetFileAddress();
518 lldb::addr_t range_length
=
519 block_range
.GetByteSize() - pc_offset_in_block
;
520 range
= AddressRange(pc_address
, range_length
);
522 range
= sc
.line_entry
.range
;
525 new_plan_sp
= thread
->QueueThreadPlanForStepInRange(
526 abort_other_plans
, range
,
527 frame
->GetSymbolContext(eSymbolContextEverything
),
528 m_options
.m_step_in_target
.c_str(), stop_other_threads
,
529 new_plan_status
, m_options
.m_step_in_avoid_no_debug
,
530 m_options
.m_step_out_avoid_no_debug
);
532 if (new_plan_sp
&& !m_options
.m_avoid_regexp
.empty()) {
533 ThreadPlanStepInRange
*step_in_range_plan
=
534 static_cast<ThreadPlanStepInRange
*>(new_plan_sp
.get());
535 step_in_range_plan
->SetAvoidRegexp(m_options
.m_avoid_regexp
.c_str());
538 new_plan_sp
= thread
->QueueThreadPlanForStepSingleInstruction(
539 false, abort_other_plans
, bool_stop_other_threads
, new_plan_status
);
540 } else if (m_step_type
== eStepTypeOver
) {
541 StackFrame
*frame
= thread
->GetStackFrameAtIndex(0).get();
543 if (frame
->HasDebugInformation())
544 new_plan_sp
= thread
->QueueThreadPlanForStepOverRange(
546 frame
->GetSymbolContext(eSymbolContextEverything
).line_entry
,
547 frame
->GetSymbolContext(eSymbolContextEverything
),
548 stop_other_threads
, new_plan_status
,
549 m_options
.m_step_out_avoid_no_debug
);
551 new_plan_sp
= thread
->QueueThreadPlanForStepSingleInstruction(
552 true, abort_other_plans
, bool_stop_other_threads
, new_plan_status
);
553 } else if (m_step_type
== eStepTypeTrace
) {
554 new_plan_sp
= thread
->QueueThreadPlanForStepSingleInstruction(
555 false, abort_other_plans
, bool_stop_other_threads
, new_plan_status
);
556 } else if (m_step_type
== eStepTypeTraceOver
) {
557 new_plan_sp
= thread
->QueueThreadPlanForStepSingleInstruction(
558 true, abort_other_plans
, bool_stop_other_threads
, new_plan_status
);
559 } else if (m_step_type
== eStepTypeOut
) {
560 new_plan_sp
= thread
->QueueThreadPlanForStepOut(
561 abort_other_plans
, nullptr, false, bool_stop_other_threads
, eVoteYes
,
563 thread
->GetSelectedFrameIndex(DoNoSelectMostRelevantFrame
),
564 new_plan_status
, m_options
.m_step_out_avoid_no_debug
);
565 } else if (m_step_type
== eStepTypeScripted
) {
566 new_plan_sp
= thread
->QueueThreadPlanForStepScripted(
567 abort_other_plans
, m_class_options
.GetName().c_str(),
568 m_class_options
.GetStructuredData(), bool_stop_other_threads
,
571 result
.AppendError("step type is not supported");
575 // If we got a new plan, then set it to be a controlling plan (User level
576 // Plans should be controlling plans so that they can be interruptible).
577 // Then resume the process.
580 new_plan_sp
->SetIsControllingPlan(true);
581 new_plan_sp
->SetOkayToDiscard(false);
583 if (m_options
.m_step_count
> 1) {
584 if (!new_plan_sp
->SetIterationCount(m_options
.m_step_count
)) {
585 result
.AppendWarning(
586 "step operation does not support iteration count.");
590 process
->GetThreadList().SetSelectedThreadByID(thread
->GetID());
592 const uint32_t iohandler_id
= process
->GetIOHandlerID();
596 if (synchronous_execution
)
597 error
= process
->ResumeSynchronous(&stream
);
599 error
= process
->Resume();
601 if (!error
.Success()) {
602 result
.AppendMessage(error
.AsCString());
606 // There is a race condition where this thread will return up the call
607 // stack to the main command handler and show an (lldb) prompt before
608 // HandlePrivateEvent (from PrivateStateThread) has a chance to call
609 // PushProcessIOHandler().
610 process
->SyncIOHandler(iohandler_id
, std::chrono::seconds(2));
612 if (synchronous_execution
) {
613 // If any state changed events had anything to say, add that to the
615 if (stream
.GetSize() > 0)
616 result
.AppendMessage(stream
.GetString());
618 process
->GetThreadList().SetSelectedThreadByID(thread
->GetID());
619 result
.SetDidChangeProcessState(true);
620 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
622 result
.SetStatus(eReturnStatusSuccessContinuingNoResult
);
625 result
.SetError(new_plan_status
);
629 StepType m_step_type
;
630 StepScope m_step_scope
;
631 ThreadStepScopeOptionGroup m_options
;
632 OptionGroupPythonClassWithDict m_class_options
;
633 OptionGroupOptions m_all_options
;
636 // CommandObjectThreadContinue
638 class CommandObjectThreadContinue
: public CommandObjectParsed
{
640 CommandObjectThreadContinue(CommandInterpreter
&interpreter
)
641 : CommandObjectParsed(
642 interpreter
, "thread continue",
643 "Continue execution of the current target process. One "
644 "or more threads may be specified, by default all "
647 eCommandRequiresThread
| eCommandTryTargetAPILock
|
648 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {
649 CommandArgumentEntry arg
;
650 CommandArgumentData thread_idx_arg
;
652 // Define the first (and only) variant of this arg.
653 thread_idx_arg
.arg_type
= eArgTypeThreadIndex
;
654 thread_idx_arg
.arg_repetition
= eArgRepeatPlus
;
656 // There is only one variant this argument could be; put it into the
658 arg
.push_back(thread_idx_arg
);
660 // Push the data for the first argument into the m_arguments vector.
661 m_arguments
.push_back(arg
);
664 ~CommandObjectThreadContinue() override
= default;
667 HandleArgumentCompletion(CompletionRequest
&request
,
668 OptionElementVector
&opt_element_vector
) override
{
669 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
670 GetCommandInterpreter(), lldb::eThreadIndexCompletion
, request
,
674 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
675 bool synchronous_execution
= m_interpreter
.GetSynchronous();
677 Process
*process
= m_exe_ctx
.GetProcessPtr();
678 if (process
== nullptr) {
679 result
.AppendError("no process exists. Cannot continue");
683 StateType state
= process
->GetState();
684 if ((state
== eStateCrashed
) || (state
== eStateStopped
) ||
685 (state
== eStateSuspended
)) {
686 const size_t argc
= command
.GetArgumentCount();
688 // These two lines appear at the beginning of both blocks in this
689 // if..else, but that is because we need to release the lock before
690 // calling process->Resume below.
691 std::lock_guard
<std::recursive_mutex
> guard(
692 process
->GetThreadList().GetMutex());
693 const uint32_t num_threads
= process
->GetThreadList().GetSize();
694 std::vector
<Thread
*> resume_threads
;
695 for (auto &entry
: command
.entries()) {
697 if (entry
.ref().getAsInteger(0, thread_idx
)) {
698 result
.AppendErrorWithFormat(
699 "invalid thread index argument: \"%s\".\n", entry
.c_str());
703 process
->GetThreadList().FindThreadByIndexID(thread_idx
).get();
706 resume_threads
.push_back(thread
);
708 result
.AppendErrorWithFormat("invalid thread index %u.\n",
714 if (resume_threads
.empty()) {
715 result
.AppendError("no valid thread indexes were specified");
718 if (resume_threads
.size() == 1)
719 result
.AppendMessageWithFormat("Resuming thread: ");
721 result
.AppendMessageWithFormat("Resuming threads: ");
723 for (uint32_t idx
= 0; idx
< num_threads
; ++idx
) {
725 process
->GetThreadList().GetThreadAtIndex(idx
).get();
726 std::vector
<Thread
*>::iterator this_thread_pos
=
727 find(resume_threads
.begin(), resume_threads
.end(), thread
);
729 if (this_thread_pos
!= resume_threads
.end()) {
730 resume_threads
.erase(this_thread_pos
);
731 if (!resume_threads
.empty())
732 result
.AppendMessageWithFormat("%u, ", thread
->GetIndexID());
734 result
.AppendMessageWithFormat("%u ", thread
->GetIndexID());
736 const bool override_suspend
= true;
737 thread
->SetResumeState(eStateRunning
, override_suspend
);
739 thread
->SetResumeState(eStateSuspended
);
742 result
.AppendMessageWithFormat("in process %" PRIu64
"\n",
746 // These two lines appear at the beginning of both blocks in this
747 // if..else, but that is because we need to release the lock before
748 // calling process->Resume below.
749 std::lock_guard
<std::recursive_mutex
> guard(
750 process
->GetThreadList().GetMutex());
751 const uint32_t num_threads
= process
->GetThreadList().GetSize();
752 Thread
*current_thread
= GetDefaultThread();
753 if (current_thread
== nullptr) {
754 result
.AppendError("the process doesn't have a current thread");
757 // Set the actions that the threads should each take when resuming
758 for (uint32_t idx
= 0; idx
< num_threads
; ++idx
) {
759 Thread
*thread
= process
->GetThreadList().GetThreadAtIndex(idx
).get();
760 if (thread
== current_thread
) {
761 result
.AppendMessageWithFormat("Resuming thread 0x%4.4" PRIx64
762 " in process %" PRIu64
"\n",
763 thread
->GetID(), process
->GetID());
764 const bool override_suspend
= true;
765 thread
->SetResumeState(eStateRunning
, override_suspend
);
767 thread
->SetResumeState(eStateSuspended
);
774 if (synchronous_execution
)
775 error
= process
->ResumeSynchronous(&stream
);
777 error
= process
->Resume();
779 // We should not be holding the thread list lock when we do this.
780 if (error
.Success()) {
781 result
.AppendMessageWithFormat("Process %" PRIu64
" resuming\n",
783 if (synchronous_execution
) {
784 // If any state changed events had anything to say, add that to the
786 if (stream
.GetSize() > 0)
787 result
.AppendMessage(stream
.GetString());
789 result
.SetDidChangeProcessState(true);
790 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
792 result
.SetStatus(eReturnStatusSuccessContinuingNoResult
);
795 result
.AppendErrorWithFormat("Failed to resume process: %s\n",
799 result
.AppendErrorWithFormat(
800 "Process cannot be continued from its current state (%s).\n",
801 StateAsCString(state
));
806 // CommandObjectThreadUntil
808 #define LLDB_OPTIONS_thread_until
809 #include "CommandOptions.inc"
811 class CommandObjectThreadUntil
: public CommandObjectParsed
{
813 class CommandOptions
: public Options
{
815 uint32_t m_thread_idx
= LLDB_INVALID_THREAD_ID
;
816 uint32_t m_frame_idx
= LLDB_INVALID_FRAME_ID
;
819 // Keep default values of all options in one place: OptionParsingStarting
821 OptionParsingStarting(nullptr);
824 ~CommandOptions() override
= default;
826 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
827 ExecutionContext
*execution_context
) override
{
829 const int short_option
= m_getopt_table
[option_idx
].val
;
831 switch (short_option
) {
833 lldb::addr_t tmp_addr
= OptionArgParser::ToAddress(
834 execution_context
, option_arg
, LLDB_INVALID_ADDRESS
, &error
);
836 m_until_addrs
.push_back(tmp_addr
);
839 if (option_arg
.getAsInteger(0, m_thread_idx
)) {
840 m_thread_idx
= LLDB_INVALID_INDEX32
;
841 error
.SetErrorStringWithFormat("invalid thread index '%s'",
842 option_arg
.str().c_str());
846 if (option_arg
.getAsInteger(0, m_frame_idx
)) {
847 m_frame_idx
= LLDB_INVALID_FRAME_ID
;
848 error
.SetErrorStringWithFormat("invalid frame index '%s'",
849 option_arg
.str().c_str());
853 auto enum_values
= GetDefinitions()[option_idx
].enum_values
;
854 lldb::RunMode run_mode
= (lldb::RunMode
)OptionArgParser::ToOptionEnum(
855 option_arg
, enum_values
, eOnlyDuringStepping
, error
);
857 if (error
.Success()) {
858 if (run_mode
== eAllThreads
)
859 m_stop_others
= false;
861 m_stop_others
= true;
865 llvm_unreachable("Unimplemented option");
870 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
871 m_thread_idx
= LLDB_INVALID_THREAD_ID
;
873 m_stop_others
= false;
874 m_until_addrs
.clear();
877 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
878 return llvm::ArrayRef(g_thread_until_options
);
881 uint32_t m_step_thread_idx
= LLDB_INVALID_THREAD_ID
;
882 bool m_stop_others
= false;
883 std::vector
<lldb::addr_t
> m_until_addrs
;
885 // Instance variables to hold the values for command options.
888 CommandObjectThreadUntil(CommandInterpreter
&interpreter
)
889 : CommandObjectParsed(
890 interpreter
, "thread until",
891 "Continue until a line number or address is reached by the "
892 "current or specified thread. Stops when returning from "
893 "the current function as a safety measure. "
894 "The target line number(s) are given as arguments, and if more "
896 " is provided, stepping will stop when the first one is hit.",
898 eCommandRequiresThread
| eCommandTryTargetAPILock
|
899 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {
900 CommandArgumentEntry arg
;
901 CommandArgumentData line_num_arg
;
903 // Define the first (and only) variant of this arg.
904 line_num_arg
.arg_type
= eArgTypeLineNum
;
905 line_num_arg
.arg_repetition
= eArgRepeatPlain
;
907 // There is only one variant this argument could be; put it into the
909 arg
.push_back(line_num_arg
);
911 // Push the data for the first argument into the m_arguments vector.
912 m_arguments
.push_back(arg
);
915 ~CommandObjectThreadUntil() override
= default;
917 Options
*GetOptions() override
{ return &m_options
; }
920 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
921 bool synchronous_execution
= m_interpreter
.GetSynchronous();
923 Target
*target
= &GetSelectedTarget();
925 Process
*process
= m_exe_ctx
.GetProcessPtr();
926 if (process
== nullptr) {
927 result
.AppendError("need a valid process to step");
929 Thread
*thread
= nullptr;
930 std::vector
<uint32_t> line_numbers
;
932 if (command
.GetArgumentCount() >= 1) {
933 size_t num_args
= command
.GetArgumentCount();
934 for (size_t i
= 0; i
< num_args
; i
++) {
935 uint32_t line_number
;
936 if (!llvm::to_integer(command
.GetArgumentAtIndex(i
), line_number
)) {
937 result
.AppendErrorWithFormat("invalid line number: '%s'.\n",
938 command
.GetArgumentAtIndex(i
));
941 line_numbers
.push_back(line_number
);
943 } else if (m_options
.m_until_addrs
.empty()) {
944 result
.AppendErrorWithFormat("No line number or address provided:\n%s",
945 GetSyntax().str().c_str());
949 if (m_options
.m_thread_idx
== LLDB_INVALID_THREAD_ID
) {
950 thread
= GetDefaultThread();
952 thread
= process
->GetThreadList()
953 .FindThreadByIndexID(m_options
.m_thread_idx
)
957 if (thread
== nullptr) {
958 const uint32_t num_threads
= process
->GetThreadList().GetSize();
959 result
.AppendErrorWithFormat(
960 "Thread index %u is out of range (valid values are 0 - %u).\n",
961 m_options
.m_thread_idx
, num_threads
);
965 const bool abort_other_plans
= false;
968 thread
->GetStackFrameAtIndex(m_options
.m_frame_idx
).get();
969 if (frame
== nullptr) {
970 result
.AppendErrorWithFormat(
971 "Frame index %u is out of range for thread id %" PRIu64
".\n",
972 m_options
.m_frame_idx
, thread
->GetID());
976 ThreadPlanSP new_plan_sp
;
977 Status new_plan_status
;
979 if (frame
->HasDebugInformation()) {
980 // Finally we got here... Translate the given line number to a bunch
982 SymbolContext
sc(frame
->GetSymbolContext(eSymbolContextCompUnit
));
983 LineTable
*line_table
= nullptr;
985 line_table
= sc
.comp_unit
->GetLineTable();
987 if (line_table
== nullptr) {
988 result
.AppendErrorWithFormat("Failed to resolve the line table for "
989 "frame %u of thread id %" PRIu64
".\n",
990 m_options
.m_frame_idx
, thread
->GetID());
994 LineEntry function_start
;
995 uint32_t index_ptr
= 0, end_ptr
= UINT32_MAX
;
996 std::vector
<addr_t
> address_list
;
998 // Find the beginning & end index of the function, but first make
1001 result
.AppendErrorWithFormat("Have debug information but no "
1002 "function info - can't get until range.");
1006 AddressRange fun_addr_range
= sc
.function
->GetAddressRange();
1007 Address fun_start_addr
= fun_addr_range
.GetBaseAddress();
1008 line_table
->FindLineEntryByAddress(fun_start_addr
, function_start
,
1011 Address
fun_end_addr(fun_start_addr
.GetSection(),
1012 fun_start_addr
.GetOffset() +
1013 fun_addr_range
.GetByteSize());
1015 bool all_in_function
= true;
1017 line_table
->FindLineEntryByAddress(fun_end_addr
, function_start
,
1020 // Since not all source lines will contribute code, check if we are
1021 // setting the breakpoint on the exact line number or the nearest
1022 // subsequent line number and set breakpoints at all the line table
1023 // entries of the chosen line number (exact or nearest subsequent).
1024 for (uint32_t line_number
: line_numbers
) {
1025 LineEntry line_entry
;
1027 uint32_t start_idx_ptr
= index_ptr
;
1028 start_idx_ptr
= sc
.comp_unit
->FindLineEntry(
1029 index_ptr
, line_number
, nullptr, exact
, &line_entry
);
1030 if (start_idx_ptr
!= UINT32_MAX
)
1031 line_number
= line_entry
.line
;
1033 start_idx_ptr
= index_ptr
;
1034 while (start_idx_ptr
<= end_ptr
) {
1035 start_idx_ptr
= sc
.comp_unit
->FindLineEntry(
1036 start_idx_ptr
, line_number
, nullptr, exact
, &line_entry
);
1037 if (start_idx_ptr
== UINT32_MAX
)
1041 line_entry
.range
.GetBaseAddress().GetLoadAddress(target
);
1042 if (address
!= LLDB_INVALID_ADDRESS
) {
1043 if (fun_addr_range
.ContainsLoadAddress(address
, target
))
1044 address_list
.push_back(address
);
1046 all_in_function
= false;
1052 for (lldb::addr_t address
: m_options
.m_until_addrs
) {
1053 if (fun_addr_range
.ContainsLoadAddress(address
, target
))
1054 address_list
.push_back(address
);
1056 all_in_function
= false;
1059 if (address_list
.empty()) {
1060 if (all_in_function
)
1061 result
.AppendErrorWithFormat(
1062 "No line entries matching until target.\n");
1064 result
.AppendErrorWithFormat(
1065 "Until target outside of the current function.\n");
1070 new_plan_sp
= thread
->QueueThreadPlanForStepUntil(
1071 abort_other_plans
, &address_list
.front(), address_list
.size(),
1072 m_options
.m_stop_others
, m_options
.m_frame_idx
, new_plan_status
);
1074 // User level plans should be controlling plans so they can be
1076 // (e.g. by hitting a breakpoint) and other plans executed by the
1077 // user (stepping around the breakpoint) and then a "continue" will
1078 // resume the original plan.
1079 new_plan_sp
->SetIsControllingPlan(true);
1080 new_plan_sp
->SetOkayToDiscard(false);
1082 result
.SetError(new_plan_status
);
1086 result
.AppendErrorWithFormat("Frame index %u of thread id %" PRIu64
1087 " has no debug information.\n",
1088 m_options
.m_frame_idx
, thread
->GetID());
1092 if (!process
->GetThreadList().SetSelectedThreadByID(thread
->GetID())) {
1093 result
.AppendErrorWithFormat(
1094 "Failed to set the selected thread to thread id %" PRIu64
".\n",
1099 StreamString stream
;
1101 if (synchronous_execution
)
1102 error
= process
->ResumeSynchronous(&stream
);
1104 error
= process
->Resume();
1106 if (error
.Success()) {
1107 result
.AppendMessageWithFormat("Process %" PRIu64
" resuming\n",
1109 if (synchronous_execution
) {
1110 // If any state changed events had anything to say, add that to the
1112 if (stream
.GetSize() > 0)
1113 result
.AppendMessage(stream
.GetString());
1115 result
.SetDidChangeProcessState(true);
1116 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1118 result
.SetStatus(eReturnStatusSuccessContinuingNoResult
);
1121 result
.AppendErrorWithFormat("Failed to resume process: %s.\n",
1127 CommandOptions m_options
;
1130 // CommandObjectThreadSelect
1132 class CommandObjectThreadSelect
: public CommandObjectParsed
{
1134 CommandObjectThreadSelect(CommandInterpreter
&interpreter
)
1135 : CommandObjectParsed(interpreter
, "thread select",
1136 "Change the currently selected thread.", nullptr,
1137 eCommandRequiresProcess
| eCommandTryTargetAPILock
|
1138 eCommandProcessMustBeLaunched
|
1139 eCommandProcessMustBePaused
) {
1140 CommandArgumentEntry arg
;
1141 CommandArgumentData thread_idx_arg
;
1143 // Define the first (and only) variant of this arg.
1144 thread_idx_arg
.arg_type
= eArgTypeThreadIndex
;
1145 thread_idx_arg
.arg_repetition
= eArgRepeatPlain
;
1147 // There is only one variant this argument could be; put it into the
1149 arg
.push_back(thread_idx_arg
);
1151 // Push the data for the first argument into the m_arguments vector.
1152 m_arguments
.push_back(arg
);
1155 ~CommandObjectThreadSelect() override
= default;
1158 HandleArgumentCompletion(CompletionRequest
&request
,
1159 OptionElementVector
&opt_element_vector
) override
{
1160 if (request
.GetCursorIndex())
1163 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1164 GetCommandInterpreter(), lldb::eThreadIndexCompletion
, request
,
1169 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1170 Process
*process
= m_exe_ctx
.GetProcessPtr();
1171 if (process
== nullptr) {
1172 result
.AppendError("no process");
1174 } else if (command
.GetArgumentCount() != 1) {
1175 result
.AppendErrorWithFormat(
1176 "'%s' takes exactly one thread index argument:\nUsage: %s\n",
1177 m_cmd_name
.c_str(), m_cmd_syntax
.c_str());
1182 if (!llvm::to_integer(command
.GetArgumentAtIndex(0), index_id
)) {
1183 result
.AppendErrorWithFormat("Invalid thread index '%s'",
1184 command
.GetArgumentAtIndex(0));
1188 Thread
*new_thread
=
1189 process
->GetThreadList().FindThreadByIndexID(index_id
).get();
1190 if (new_thread
== nullptr) {
1191 result
.AppendErrorWithFormat("invalid thread #%s.\n",
1192 command
.GetArgumentAtIndex(0));
1196 process
->GetThreadList().SetSelectedThreadByID(new_thread
->GetID(), true);
1197 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1201 // CommandObjectThreadList
1203 class CommandObjectThreadList
: public CommandObjectParsed
{
1205 CommandObjectThreadList(CommandInterpreter
&interpreter
)
1206 : CommandObjectParsed(
1207 interpreter
, "thread list",
1208 "Show a summary of each thread in the current target process. "
1209 "Use 'settings set thread-format' to customize the individual "
1212 eCommandRequiresProcess
| eCommandTryTargetAPILock
|
1213 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {}
1215 ~CommandObjectThreadList() override
= default;
1218 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1219 Stream
&strm
= result
.GetOutputStream();
1220 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1221 Process
*process
= m_exe_ctx
.GetProcessPtr();
1222 const bool only_threads_with_stop_reason
= false;
1223 const uint32_t start_frame
= 0;
1224 const uint32_t num_frames
= 0;
1225 const uint32_t num_frames_with_source
= 0;
1226 process
->GetStatus(strm
);
1227 process
->GetThreadStatus(strm
, only_threads_with_stop_reason
, start_frame
,
1228 num_frames
, num_frames_with_source
, false);
1232 // CommandObjectThreadInfo
1233 #define LLDB_OPTIONS_thread_info
1234 #include "CommandOptions.inc"
1236 class CommandObjectThreadInfo
: public CommandObjectIterateOverThreads
{
1238 class CommandOptions
: public Options
{
1240 CommandOptions() { OptionParsingStarting(nullptr); }
1242 ~CommandOptions() override
= default;
1244 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1245 m_json_thread
= false;
1246 m_json_stopinfo
= false;
1249 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1250 ExecutionContext
*execution_context
) override
{
1251 const int short_option
= m_getopt_table
[option_idx
].val
;
1254 switch (short_option
) {
1256 m_json_thread
= true;
1260 m_json_stopinfo
= true;
1264 llvm_unreachable("Unimplemented option");
1269 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1270 return llvm::ArrayRef(g_thread_info_options
);
1274 bool m_json_stopinfo
;
1277 CommandObjectThreadInfo(CommandInterpreter
&interpreter
)
1278 : CommandObjectIterateOverThreads(
1279 interpreter
, "thread info",
1280 "Show an extended summary of one or "
1281 "more threads. Defaults to the "
1284 eCommandRequiresProcess
| eCommandTryTargetAPILock
|
1285 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {
1286 m_add_return
= false;
1289 ~CommandObjectThreadInfo() override
= default;
1292 HandleArgumentCompletion(CompletionRequest
&request
,
1293 OptionElementVector
&opt_element_vector
) override
{
1294 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1295 GetCommandInterpreter(), lldb::eThreadIndexCompletion
, request
,
1299 Options
*GetOptions() override
{ return &m_options
; }
1301 bool HandleOneThread(lldb::tid_t tid
, CommandReturnObject
&result
) override
{
1302 ThreadSP thread_sp
=
1303 m_exe_ctx
.GetProcessPtr()->GetThreadList().FindThreadByID(tid
);
1305 result
.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64
"\n",
1310 Thread
*thread
= thread_sp
.get();
1312 Stream
&strm
= result
.GetOutputStream();
1313 if (!thread
->GetDescription(strm
, eDescriptionLevelFull
,
1314 m_options
.m_json_thread
,
1315 m_options
.m_json_stopinfo
)) {
1316 result
.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n",
1317 thread
->GetIndexID());
1323 CommandOptions m_options
;
1326 // CommandObjectThreadException
1328 class CommandObjectThreadException
: public CommandObjectIterateOverThreads
{
1330 CommandObjectThreadException(CommandInterpreter
&interpreter
)
1331 : CommandObjectIterateOverThreads(
1332 interpreter
, "thread exception",
1333 "Display the current exception object for a thread. Defaults to "
1334 "the current thread.",
1336 eCommandRequiresProcess
| eCommandTryTargetAPILock
|
1337 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {}
1339 ~CommandObjectThreadException() override
= default;
1342 HandleArgumentCompletion(CompletionRequest
&request
,
1343 OptionElementVector
&opt_element_vector
) override
{
1344 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1345 GetCommandInterpreter(), lldb::eThreadIndexCompletion
, request
,
1349 bool HandleOneThread(lldb::tid_t tid
, CommandReturnObject
&result
) override
{
1350 ThreadSP thread_sp
=
1351 m_exe_ctx
.GetProcessPtr()->GetThreadList().FindThreadByID(tid
);
1353 result
.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64
"\n",
1358 Stream
&strm
= result
.GetOutputStream();
1359 ValueObjectSP exception_object_sp
= thread_sp
->GetCurrentException();
1360 if (exception_object_sp
) {
1361 exception_object_sp
->Dump(strm
);
1364 ThreadSP exception_thread_sp
= thread_sp
->GetCurrentExceptionBacktrace();
1365 if (exception_thread_sp
&& exception_thread_sp
->IsValid()) {
1366 const uint32_t num_frames_with_source
= 0;
1367 const bool stop_format
= false;
1368 exception_thread_sp
->GetStatus(strm
, 0, UINT32_MAX
,
1369 num_frames_with_source
, stop_format
);
1376 class CommandObjectThreadSiginfo
: public CommandObjectIterateOverThreads
{
1378 CommandObjectThreadSiginfo(CommandInterpreter
&interpreter
)
1379 : CommandObjectIterateOverThreads(
1380 interpreter
, "thread siginfo",
1381 "Display the current siginfo object for a thread. Defaults to "
1382 "the current thread.",
1384 eCommandRequiresProcess
| eCommandTryTargetAPILock
|
1385 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {}
1387 ~CommandObjectThreadSiginfo() override
= default;
1390 HandleArgumentCompletion(CompletionRequest
&request
,
1391 OptionElementVector
&opt_element_vector
) override
{
1392 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1393 GetCommandInterpreter(), lldb::eThreadIndexCompletion
, request
,
1397 bool HandleOneThread(lldb::tid_t tid
, CommandReturnObject
&result
) override
{
1398 ThreadSP thread_sp
=
1399 m_exe_ctx
.GetProcessPtr()->GetThreadList().FindThreadByID(tid
);
1401 result
.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64
"\n",
1406 Stream
&strm
= result
.GetOutputStream();
1407 if (!thread_sp
->GetDescription(strm
, eDescriptionLevelFull
, false, false)) {
1408 result
.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n",
1409 thread_sp
->GetIndexID());
1412 ValueObjectSP exception_object_sp
= thread_sp
->GetSiginfoValue();
1413 if (exception_object_sp
)
1414 exception_object_sp
->Dump(strm
);
1416 strm
.Printf("(no siginfo)\n");
1423 // CommandObjectThreadReturn
1424 #define LLDB_OPTIONS_thread_return
1425 #include "CommandOptions.inc"
1427 class CommandObjectThreadReturn
: public CommandObjectRaw
{
1429 class CommandOptions
: public Options
{
1432 // Keep default values of all options in one place: OptionParsingStarting
1434 OptionParsingStarting(nullptr);
1437 ~CommandOptions() override
= default;
1439 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1440 ExecutionContext
*execution_context
) override
{
1442 const int short_option
= m_getopt_table
[option_idx
].val
;
1444 switch (short_option
) {
1448 OptionArgParser::ToBoolean(option_arg
, false, &success
);
1450 m_from_expression
= tmp_value
;
1452 error
.SetErrorStringWithFormat(
1453 "invalid boolean value '%s' for 'x' option",
1454 option_arg
.str().c_str());
1458 llvm_unreachable("Unimplemented option");
1463 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1464 m_from_expression
= false;
1467 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1468 return llvm::ArrayRef(g_thread_return_options
);
1471 bool m_from_expression
= false;
1473 // Instance variables to hold the values for command options.
1476 CommandObjectThreadReturn(CommandInterpreter
&interpreter
)
1477 : CommandObjectRaw(interpreter
, "thread return",
1478 "Prematurely return from a stack frame, "
1479 "short-circuiting execution of newer frames "
1480 "and optionally yielding a specified value. Defaults "
1481 "to the exiting the current stack "
1484 eCommandRequiresFrame
| eCommandTryTargetAPILock
|
1485 eCommandProcessMustBeLaunched
|
1486 eCommandProcessMustBePaused
) {
1487 CommandArgumentEntry arg
;
1488 CommandArgumentData expression_arg
;
1490 // Define the first (and only) variant of this arg.
1491 expression_arg
.arg_type
= eArgTypeExpression
;
1492 expression_arg
.arg_repetition
= eArgRepeatOptional
;
1494 // There is only one variant this argument could be; put it into the
1496 arg
.push_back(expression_arg
);
1498 // Push the data for the first argument into the m_arguments vector.
1499 m_arguments
.push_back(arg
);
1502 ~CommandObjectThreadReturn() override
= default;
1504 Options
*GetOptions() override
{ return &m_options
; }
1507 void DoExecute(llvm::StringRef command
,
1508 CommandReturnObject
&result
) override
{
1509 // I am going to handle this by hand, because I don't want you to have to
1511 // "thread return -- -5".
1512 if (command
.startswith("-x")) {
1513 if (command
.size() != 2U)
1514 result
.AppendWarning("Return values ignored when returning from user "
1515 "called expressions");
1517 Thread
*thread
= m_exe_ctx
.GetThreadPtr();
1519 error
= thread
->UnwindInnermostExpression();
1520 if (!error
.Success()) {
1521 result
.AppendErrorWithFormat("Unwinding expression failed - %s.",
1525 thread
->SetSelectedFrameByIndexNoisily(0, result
.GetOutputStream());
1527 m_exe_ctx
.SetFrameSP(
1528 thread
->GetSelectedFrame(DoNoSelectMostRelevantFrame
));
1529 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1531 result
.AppendErrorWithFormat(
1532 "Could not select 0th frame after unwinding expression.");
1538 ValueObjectSP return_valobj_sp
;
1540 StackFrameSP frame_sp
= m_exe_ctx
.GetFrameSP();
1541 uint32_t frame_idx
= frame_sp
->GetFrameIndex();
1543 if (frame_sp
->IsInlined()) {
1544 result
.AppendError("Don't know how to return from inlined frames.");
1548 if (!command
.empty()) {
1549 Target
*target
= m_exe_ctx
.GetTargetPtr();
1550 EvaluateExpressionOptions options
;
1552 options
.SetUnwindOnError(true);
1553 options
.SetUseDynamic(eNoDynamicValues
);
1555 ExpressionResults exe_results
= eExpressionSetupError
;
1556 exe_results
= target
->EvaluateExpression(command
, frame_sp
.get(),
1557 return_valobj_sp
, options
);
1558 if (exe_results
!= eExpressionCompleted
) {
1559 if (return_valobj_sp
)
1560 result
.AppendErrorWithFormat(
1561 "Error evaluating result expression: %s",
1562 return_valobj_sp
->GetError().AsCString());
1564 result
.AppendErrorWithFormat(
1565 "Unknown error evaluating result expression.");
1571 ThreadSP thread_sp
= m_exe_ctx
.GetThreadSP();
1572 const bool broadcast
= true;
1573 error
= thread_sp
->ReturnFromFrame(frame_sp
, return_valobj_sp
, broadcast
);
1574 if (!error
.Success()) {
1575 result
.AppendErrorWithFormat(
1576 "Error returning from frame %d of thread %d: %s.", frame_idx
,
1577 thread_sp
->GetIndexID(), error
.AsCString());
1581 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1584 CommandOptions m_options
;
1587 // CommandObjectThreadJump
1588 #define LLDB_OPTIONS_thread_jump
1589 #include "CommandOptions.inc"
1591 class CommandObjectThreadJump
: public CommandObjectParsed
{
1593 class CommandOptions
: public Options
{
1595 CommandOptions() { OptionParsingStarting(nullptr); }
1597 ~CommandOptions() override
= default;
1599 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1600 m_filenames
.Clear();
1603 m_load_addr
= LLDB_INVALID_ADDRESS
;
1607 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1608 ExecutionContext
*execution_context
) override
{
1609 const int short_option
= m_getopt_table
[option_idx
].val
;
1612 switch (short_option
) {
1614 m_filenames
.AppendIfUnique(FileSpec(option_arg
));
1615 if (m_filenames
.GetSize() > 1)
1616 return Status("only one source file expected.");
1619 if (option_arg
.getAsInteger(0, m_line_num
))
1620 return Status("invalid line number: '%s'.", option_arg
.str().c_str());
1623 if (option_arg
.getAsInteger(0, m_line_offset
))
1624 return Status("invalid line offset: '%s'.", option_arg
.str().c_str());
1627 m_load_addr
= OptionArgParser::ToAddress(execution_context
, option_arg
,
1628 LLDB_INVALID_ADDRESS
, &error
);
1634 llvm_unreachable("Unimplemented option");
1639 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1640 return llvm::ArrayRef(g_thread_jump_options
);
1643 FileSpecList m_filenames
;
1644 uint32_t m_line_num
;
1645 int32_t m_line_offset
;
1646 lldb::addr_t m_load_addr
;
1650 CommandObjectThreadJump(CommandInterpreter
&interpreter
)
1651 : CommandObjectParsed(
1652 interpreter
, "thread jump",
1653 "Sets the program counter to a new address.", "thread jump",
1654 eCommandRequiresFrame
| eCommandTryTargetAPILock
|
1655 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {}
1657 ~CommandObjectThreadJump() override
= default;
1659 Options
*GetOptions() override
{ return &m_options
; }
1662 void DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
1663 RegisterContext
*reg_ctx
= m_exe_ctx
.GetRegisterContext();
1664 StackFrame
*frame
= m_exe_ctx
.GetFramePtr();
1665 Thread
*thread
= m_exe_ctx
.GetThreadPtr();
1666 Target
*target
= m_exe_ctx
.GetTargetPtr();
1667 const SymbolContext
&sym_ctx
=
1668 frame
->GetSymbolContext(eSymbolContextLineEntry
);
1670 if (m_options
.m_load_addr
!= LLDB_INVALID_ADDRESS
) {
1671 // Use this address directly.
1672 Address dest
= Address(m_options
.m_load_addr
);
1674 lldb::addr_t callAddr
= dest
.GetCallableLoadAddress(target
);
1675 if (callAddr
== LLDB_INVALID_ADDRESS
) {
1676 result
.AppendErrorWithFormat("Invalid destination address.");
1680 if (!reg_ctx
->SetPC(callAddr
)) {
1681 result
.AppendErrorWithFormat("Error changing PC value for thread %d.",
1682 thread
->GetIndexID());
1686 // Pick either the absolute line, or work out a relative one.
1687 int32_t line
= (int32_t)m_options
.m_line_num
;
1689 line
= sym_ctx
.line_entry
.line
+ m_options
.m_line_offset
;
1691 // Try the current file, but override if asked.
1692 FileSpec file
= sym_ctx
.line_entry
.file
;
1693 if (m_options
.m_filenames
.GetSize() == 1)
1694 file
= m_options
.m_filenames
.GetFileSpecAtIndex(0);
1697 result
.AppendErrorWithFormat(
1698 "No source file available for the current location.");
1702 std::string warnings
;
1703 Status err
= thread
->JumpToLine(file
, line
, m_options
.m_force
, &warnings
);
1706 result
.SetError(err
);
1710 if (!warnings
.empty())
1711 result
.AppendWarning(warnings
.c_str());
1714 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1717 CommandOptions m_options
;
1720 // Next are the subcommands of CommandObjectMultiwordThreadPlan
1722 // CommandObjectThreadPlanList
1723 #define LLDB_OPTIONS_thread_plan_list
1724 #include "CommandOptions.inc"
1726 class CommandObjectThreadPlanList
: public CommandObjectIterateOverThreads
{
1728 class CommandOptions
: public Options
{
1731 // Keep default values of all options in one place: OptionParsingStarting
1733 OptionParsingStarting(nullptr);
1736 ~CommandOptions() override
= default;
1738 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1739 ExecutionContext
*execution_context
) override
{
1740 const int short_option
= m_getopt_table
[option_idx
].val
;
1742 switch (short_option
) {
1748 if (option_arg
.getAsInteger(0, tid
))
1749 return Status("invalid tid: '%s'.", option_arg
.str().c_str());
1750 m_tids
.push_back(tid
);
1753 m_unreported
= false;
1759 llvm_unreachable("Unimplemented option");
1764 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1767 m_unreported
= true; // The variable is "skip unreported" and we want to
1768 // skip unreported by default.
1772 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1773 return llvm::ArrayRef(g_thread_plan_list_options
);
1776 // Instance variables to hold the values for command options.
1780 std::vector
<lldb::tid_t
> m_tids
;
1783 CommandObjectThreadPlanList(CommandInterpreter
&interpreter
)
1784 : CommandObjectIterateOverThreads(
1785 interpreter
, "thread plan list",
1786 "Show thread plans for one or more threads. If no threads are "
1787 "specified, show the "
1788 "current thread. Use the thread-index \"all\" to see all threads.",
1790 eCommandRequiresProcess
| eCommandRequiresThread
|
1791 eCommandTryTargetAPILock
| eCommandProcessMustBeLaunched
|
1792 eCommandProcessMustBePaused
) {}
1794 ~CommandObjectThreadPlanList() override
= default;
1796 Options
*GetOptions() override
{ return &m_options
; }
1798 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1799 // If we are reporting all threads, dispatch to the Process to do that:
1800 if (command
.GetArgumentCount() == 0 && m_options
.m_tids
.empty()) {
1801 Stream
&strm
= result
.GetOutputStream();
1802 DescriptionLevel desc_level
= m_options
.m_verbose
1803 ? eDescriptionLevelVerbose
1804 : eDescriptionLevelFull
;
1805 m_exe_ctx
.GetProcessPtr()->DumpThreadPlans(
1806 strm
, desc_level
, m_options
.m_internal
, true, m_options
.m_unreported
);
1807 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1810 // Do any TID's that the user may have specified as TID, then do any
1811 // Thread Indexes...
1812 if (!m_options
.m_tids
.empty()) {
1813 Process
*process
= m_exe_ctx
.GetProcessPtr();
1814 StreamString tmp_strm
;
1815 for (lldb::tid_t tid
: m_options
.m_tids
) {
1816 bool success
= process
->DumpThreadPlansForTID(
1817 tmp_strm
, tid
, eDescriptionLevelFull
, m_options
.m_internal
,
1818 true /* condense_trivial */, m_options
.m_unreported
);
1819 // If we didn't find a TID, stop here and return an error.
1821 result
.AppendError("Error dumping plans:");
1822 result
.AppendError(tmp_strm
.GetString());
1825 // Otherwise, add our data to the output:
1826 result
.GetOutputStream() << tmp_strm
.GetString();
1829 return CommandObjectIterateOverThreads::DoExecute(command
, result
);
1834 bool HandleOneThread(lldb::tid_t tid
, CommandReturnObject
&result
) override
{
1835 // If we have already handled this from a -t option, skip it here.
1836 if (llvm::is_contained(m_options
.m_tids
, tid
))
1839 Process
*process
= m_exe_ctx
.GetProcessPtr();
1841 Stream
&strm
= result
.GetOutputStream();
1842 DescriptionLevel desc_level
= eDescriptionLevelFull
;
1843 if (m_options
.m_verbose
)
1844 desc_level
= eDescriptionLevelVerbose
;
1846 process
->DumpThreadPlansForTID(strm
, tid
, desc_level
, m_options
.m_internal
,
1847 true /* condense_trivial */,
1848 m_options
.m_unreported
);
1852 CommandOptions m_options
;
1855 class CommandObjectThreadPlanDiscard
: public CommandObjectParsed
{
1857 CommandObjectThreadPlanDiscard(CommandInterpreter
&interpreter
)
1858 : CommandObjectParsed(interpreter
, "thread plan discard",
1859 "Discards thread plans up to and including the "
1860 "specified index (see 'thread plan list'.) "
1861 "Only user visible plans can be discarded.",
1863 eCommandRequiresProcess
| eCommandRequiresThread
|
1864 eCommandTryTargetAPILock
|
1865 eCommandProcessMustBeLaunched
|
1866 eCommandProcessMustBePaused
) {
1867 CommandArgumentEntry arg
;
1868 CommandArgumentData plan_index_arg
;
1870 // Define the first (and only) variant of this arg.
1871 plan_index_arg
.arg_type
= eArgTypeUnsignedInteger
;
1872 plan_index_arg
.arg_repetition
= eArgRepeatPlain
;
1874 // There is only one variant this argument could be; put it into the
1876 arg
.push_back(plan_index_arg
);
1878 // Push the data for the first argument into the m_arguments vector.
1879 m_arguments
.push_back(arg
);
1882 ~CommandObjectThreadPlanDiscard() override
= default;
1885 HandleArgumentCompletion(CompletionRequest
&request
,
1886 OptionElementVector
&opt_element_vector
) override
{
1887 if (!m_exe_ctx
.HasThreadScope() || request
.GetCursorIndex())
1890 m_exe_ctx
.GetThreadPtr()->AutoCompleteThreadPlans(request
);
1893 void DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
1894 Thread
*thread
= m_exe_ctx
.GetThreadPtr();
1895 if (args
.GetArgumentCount() != 1) {
1896 result
.AppendErrorWithFormat("Too many arguments, expected one - the "
1897 "thread plan index - but got %zu.",
1898 args
.GetArgumentCount());
1902 uint32_t thread_plan_idx
;
1903 if (!llvm::to_integer(args
.GetArgumentAtIndex(0), thread_plan_idx
)) {
1904 result
.AppendErrorWithFormat(
1905 "Invalid thread index: \"%s\" - should be unsigned int.",
1906 args
.GetArgumentAtIndex(0));
1910 if (thread_plan_idx
== 0) {
1911 result
.AppendErrorWithFormat(
1912 "You wouldn't really want me to discard the base thread plan.");
1916 if (thread
->DiscardUserThreadPlansUpToIndex(thread_plan_idx
)) {
1917 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1919 result
.AppendErrorWithFormat(
1920 "Could not find User thread plan with index %s.",
1921 args
.GetArgumentAtIndex(0));
1926 class CommandObjectThreadPlanPrune
: public CommandObjectParsed
{
1928 CommandObjectThreadPlanPrune(CommandInterpreter
&interpreter
)
1929 : CommandObjectParsed(interpreter
, "thread plan prune",
1930 "Removes any thread plans associated with "
1931 "currently unreported threads. "
1932 "Specify one or more TID's to remove, or if no "
1933 "TID's are provides, remove threads for all "
1934 "unreported threads",
1936 eCommandRequiresProcess
|
1937 eCommandTryTargetAPILock
|
1938 eCommandProcessMustBeLaunched
|
1939 eCommandProcessMustBePaused
) {
1940 CommandArgumentEntry arg
;
1941 CommandArgumentData tid_arg
;
1943 // Define the first (and only) variant of this arg.
1944 tid_arg
.arg_type
= eArgTypeThreadID
;
1945 tid_arg
.arg_repetition
= eArgRepeatStar
;
1947 // There is only one variant this argument could be; put it into the
1949 arg
.push_back(tid_arg
);
1951 // Push the data for the first argument into the m_arguments vector.
1952 m_arguments
.push_back(arg
);
1955 ~CommandObjectThreadPlanPrune() override
= default;
1957 void DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
1958 Process
*process
= m_exe_ctx
.GetProcessPtr();
1960 if (args
.GetArgumentCount() == 0) {
1961 process
->PruneThreadPlans();
1962 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1966 const size_t num_args
= args
.GetArgumentCount();
1968 std::lock_guard
<std::recursive_mutex
> guard(
1969 process
->GetThreadList().GetMutex());
1971 for (size_t i
= 0; i
< num_args
; i
++) {
1973 if (!llvm::to_integer(args
.GetArgumentAtIndex(i
), tid
)) {
1974 result
.AppendErrorWithFormat("invalid thread specification: \"%s\"\n",
1975 args
.GetArgumentAtIndex(i
));
1978 if (!process
->PruneThreadPlansForTID(tid
)) {
1979 result
.AppendErrorWithFormat("Could not find unreported tid: \"%s\"\n",
1980 args
.GetArgumentAtIndex(i
));
1984 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1988 // CommandObjectMultiwordThreadPlan
1990 class CommandObjectMultiwordThreadPlan
: public CommandObjectMultiword
{
1992 CommandObjectMultiwordThreadPlan(CommandInterpreter
&interpreter
)
1993 : CommandObjectMultiword(
1994 interpreter
, "plan",
1995 "Commands for managing thread plans that control execution.",
1996 "thread plan <subcommand> [<subcommand objects]") {
1998 "list", CommandObjectSP(new CommandObjectThreadPlanList(interpreter
)));
2001 CommandObjectSP(new CommandObjectThreadPlanDiscard(interpreter
)));
2004 CommandObjectSP(new CommandObjectThreadPlanPrune(interpreter
)));
2007 ~CommandObjectMultiwordThreadPlan() override
= default;
2010 // Next are the subcommands of CommandObjectMultiwordTrace
2012 // CommandObjectTraceExport
2014 class CommandObjectTraceExport
: public CommandObjectMultiword
{
2016 CommandObjectTraceExport(CommandInterpreter
&interpreter
)
2017 : CommandObjectMultiword(
2018 interpreter
, "trace thread export",
2019 "Commands for exporting traces of the threads in the current "
2020 "process to different formats.",
2021 "thread trace export <export-plugin> [<subcommand objects>]") {
2024 for (llvm::StringRef plugin_name
=
2025 PluginManager::GetTraceExporterPluginNameAtIndex(i
);
2026 !plugin_name
.empty();
2027 plugin_name
= PluginManager::GetTraceExporterPluginNameAtIndex(i
++)) {
2028 if (ThreadTraceExportCommandCreator command_creator
=
2029 PluginManager::GetThreadTraceExportCommandCreatorAtIndex(i
)) {
2030 LoadSubCommand(plugin_name
, command_creator(interpreter
));
2036 // CommandObjectTraceStart
2038 class CommandObjectTraceStart
: public CommandObjectTraceProxy
{
2040 CommandObjectTraceStart(CommandInterpreter
&interpreter
)
2041 : CommandObjectTraceProxy(
2042 /*live_debug_session_only=*/true, interpreter
, "thread trace start",
2043 "Start tracing threads with the corresponding trace "
2044 "plug-in for the current process.",
2045 "thread trace start [<trace-options>]") {}
2048 lldb::CommandObjectSP
GetDelegateCommand(Trace
&trace
) override
{
2049 return trace
.GetThreadTraceStartCommand(m_interpreter
);
2053 // CommandObjectTraceStop
2055 class CommandObjectTraceStop
: public CommandObjectMultipleThreads
{
2057 CommandObjectTraceStop(CommandInterpreter
&interpreter
)
2058 : CommandObjectMultipleThreads(
2059 interpreter
, "thread trace stop",
2060 "Stop tracing threads, including the ones traced with the "
2061 "\"process trace start\" command."
2062 "Defaults to the current thread. Thread indices can be "
2063 "specified as arguments.\n Use the thread-index \"all\" to stop "
2065 "for all existing threads.",
2066 "thread trace stop [<thread-index> <thread-index> ...]",
2067 eCommandRequiresProcess
| eCommandTryTargetAPILock
|
2068 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
|
2069 eCommandProcessMustBeTraced
) {}
2071 ~CommandObjectTraceStop() override
= default;
2073 bool DoExecuteOnThreads(Args
&command
, CommandReturnObject
&result
,
2074 llvm::ArrayRef
<lldb::tid_t
> tids
) override
{
2075 ProcessSP process_sp
= m_exe_ctx
.GetProcessSP();
2077 TraceSP trace_sp
= process_sp
->GetTarget().GetTrace();
2079 if (llvm::Error err
= trace_sp
->Stop(tids
))
2080 result
.AppendError(toString(std::move(err
)));
2082 result
.SetStatus(eReturnStatusSuccessFinishResult
);
2084 return result
.Succeeded();
2088 static ThreadSP
GetSingleThreadFromArgs(ExecutionContext
&exe_ctx
, Args
&args
,
2089 CommandReturnObject
&result
) {
2090 if (args
.GetArgumentCount() == 0)
2091 return exe_ctx
.GetThreadSP();
2093 const char *arg
= args
.GetArgumentAtIndex(0);
2094 uint32_t thread_idx
;
2096 if (!llvm::to_integer(arg
, thread_idx
)) {
2097 result
.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", arg
);
2100 ThreadSP thread_sp
=
2101 exe_ctx
.GetProcessRef().GetThreadList().FindThreadByIndexID(thread_idx
);
2103 result
.AppendErrorWithFormat("no thread with index: \"%s\"\n", arg
);
2107 // CommandObjectTraceDumpFunctionCalls
2108 #define LLDB_OPTIONS_thread_trace_dump_function_calls
2109 #include "CommandOptions.inc"
2111 class CommandObjectTraceDumpFunctionCalls
: public CommandObjectParsed
{
2113 class CommandOptions
: public Options
{
2115 CommandOptions() { OptionParsingStarting(nullptr); }
2117 ~CommandOptions() override
= default;
2119 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
2120 ExecutionContext
*execution_context
) override
{
2122 const int short_option
= m_getopt_table
[option_idx
].val
;
2124 switch (short_option
) {
2126 m_dumper_options
.json
= true;
2130 m_dumper_options
.json
= true;
2131 m_dumper_options
.pretty_print_json
= true;
2135 m_output_file
.emplace(option_arg
);
2139 llvm_unreachable("Unimplemented option");
2144 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2145 m_dumper_options
= {};
2146 m_output_file
= std::nullopt
;
2149 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2150 return llvm::ArrayRef(g_thread_trace_dump_function_calls_options
);
2153 static const size_t kDefaultCount
= 20;
2155 // Instance variables to hold the values for command options.
2156 TraceDumperOptions m_dumper_options
;
2157 std::optional
<FileSpec
> m_output_file
;
2160 CommandObjectTraceDumpFunctionCalls(CommandInterpreter
&interpreter
)
2161 : CommandObjectParsed(
2162 interpreter
, "thread trace dump function-calls",
2163 "Dump the traced function-calls for one thread. If no "
2164 "thread is specified, the current thread is used.",
2166 eCommandRequiresProcess
| eCommandRequiresThread
|
2167 eCommandTryTargetAPILock
| eCommandProcessMustBeLaunched
|
2168 eCommandProcessMustBePaused
| eCommandProcessMustBeTraced
) {
2169 CommandArgumentData thread_arg
{eArgTypeThreadIndex
, eArgRepeatOptional
};
2170 m_arguments
.push_back({thread_arg
});
2173 ~CommandObjectTraceDumpFunctionCalls() override
= default;
2175 Options
*GetOptions() override
{ return &m_options
; }
2178 void DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
2179 ThreadSP thread_sp
= GetSingleThreadFromArgs(m_exe_ctx
, args
, result
);
2181 result
.AppendError("invalid thread\n");
2185 llvm::Expected
<TraceCursorSP
> cursor_or_error
=
2186 m_exe_ctx
.GetTargetSP()->GetTrace()->CreateNewCursor(*thread_sp
);
2188 if (!cursor_or_error
) {
2189 result
.AppendError(llvm::toString(cursor_or_error
.takeError()));
2192 TraceCursorSP
&cursor_sp
= *cursor_or_error
;
2194 std::optional
<StreamFile
> out_file
;
2195 if (m_options
.m_output_file
) {
2196 out_file
.emplace(m_options
.m_output_file
->GetPath().c_str(),
2197 File::eOpenOptionWriteOnly
| File::eOpenOptionCanCreate
|
2198 File::eOpenOptionTruncate
);
2201 m_options
.m_dumper_options
.forwards
= true;
2203 TraceDumper
dumper(std::move(cursor_sp
),
2204 out_file
? *out_file
: result
.GetOutputStream(),
2205 m_options
.m_dumper_options
);
2207 dumper
.DumpFunctionCalls();
2210 CommandOptions m_options
;
2213 // CommandObjectTraceDumpInstructions
2214 #define LLDB_OPTIONS_thread_trace_dump_instructions
2215 #include "CommandOptions.inc"
2217 class CommandObjectTraceDumpInstructions
: public CommandObjectParsed
{
2219 class CommandOptions
: public Options
{
2221 CommandOptions() { OptionParsingStarting(nullptr); }
2223 ~CommandOptions() override
= default;
2225 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
2226 ExecutionContext
*execution_context
) override
{
2228 const int short_option
= m_getopt_table
[option_idx
].val
;
2230 switch (short_option
) {
2233 if (option_arg
.empty() || option_arg
.getAsInteger(0, count
) ||
2235 error
.SetErrorStringWithFormat(
2236 "invalid integer value for option '%s'",
2237 option_arg
.str().c_str());
2243 m_count
= std::numeric_limits
<decltype(m_count
)>::max();
2248 if (option_arg
.empty() || option_arg
.getAsInteger(0, skip
) || skip
< 0)
2249 error
.SetErrorStringWithFormat(
2250 "invalid integer value for option '%s'",
2251 option_arg
.str().c_str());
2253 m_dumper_options
.skip
= skip
;
2258 if (option_arg
.empty() || option_arg
.getAsInteger(0, id
))
2259 error
.SetErrorStringWithFormat(
2260 "invalid integer value for option '%s'",
2261 option_arg
.str().c_str());
2263 m_dumper_options
.id
= id
;
2267 m_output_file
.emplace(option_arg
);
2271 m_dumper_options
.raw
= true;
2275 m_dumper_options
.forwards
= true;
2279 m_dumper_options
.show_control_flow_kind
= true;
2283 m_dumper_options
.show_timestamps
= true;
2287 m_dumper_options
.show_events
= true;
2291 m_dumper_options
.json
= true;
2295 m_dumper_options
.pretty_print_json
= true;
2296 m_dumper_options
.json
= true;
2300 m_dumper_options
.only_events
= true;
2301 m_dumper_options
.show_events
= true;
2309 llvm_unreachable("Unimplemented option");
2314 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2315 m_count
= kDefaultCount
;
2317 m_output_file
= std::nullopt
;
2318 m_dumper_options
= {};
2321 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2322 return llvm::ArrayRef(g_thread_trace_dump_instructions_options
);
2325 static const size_t kDefaultCount
= 20;
2327 // Instance variables to hold the values for command options.
2330 std::optional
<FileSpec
> m_output_file
;
2331 TraceDumperOptions m_dumper_options
;
2334 CommandObjectTraceDumpInstructions(CommandInterpreter
&interpreter
)
2335 : CommandObjectParsed(
2336 interpreter
, "thread trace dump instructions",
2337 "Dump the traced instructions for one thread. If no "
2338 "thread is specified, show the current thread.",
2340 eCommandRequiresProcess
| eCommandRequiresThread
|
2341 eCommandTryTargetAPILock
| eCommandProcessMustBeLaunched
|
2342 eCommandProcessMustBePaused
| eCommandProcessMustBeTraced
) {
2343 CommandArgumentData thread_arg
{eArgTypeThreadIndex
, eArgRepeatOptional
};
2344 m_arguments
.push_back({thread_arg
});
2347 ~CommandObjectTraceDumpInstructions() override
= default;
2349 Options
*GetOptions() override
{ return &m_options
; }
2351 std::optional
<std::string
> GetRepeatCommand(Args
¤t_command_args
,
2352 uint32_t index
) override
{
2354 current_command_args
.GetCommandString(cmd
);
2355 if (cmd
.find(" --continue") == std::string::npos
)
2356 cmd
+= " --continue";
2361 void DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
2362 ThreadSP thread_sp
= GetSingleThreadFromArgs(m_exe_ctx
, args
, result
);
2364 result
.AppendError("invalid thread\n");
2368 if (m_options
.m_continue
&& m_last_id
) {
2369 // We set up the options to continue one instruction past where
2370 // the previous iteration stopped.
2371 m_options
.m_dumper_options
.skip
= 1;
2372 m_options
.m_dumper_options
.id
= m_last_id
;
2375 llvm::Expected
<TraceCursorSP
> cursor_or_error
=
2376 m_exe_ctx
.GetTargetSP()->GetTrace()->CreateNewCursor(*thread_sp
);
2378 if (!cursor_or_error
) {
2379 result
.AppendError(llvm::toString(cursor_or_error
.takeError()));
2382 TraceCursorSP
&cursor_sp
= *cursor_or_error
;
2384 if (m_options
.m_dumper_options
.id
&&
2385 !cursor_sp
->HasId(*m_options
.m_dumper_options
.id
)) {
2386 result
.AppendError("invalid instruction id\n");
2390 std::optional
<StreamFile
> out_file
;
2391 if (m_options
.m_output_file
) {
2392 out_file
.emplace(m_options
.m_output_file
->GetPath().c_str(),
2393 File::eOpenOptionWriteOnly
| File::eOpenOptionCanCreate
|
2394 File::eOpenOptionTruncate
);
2397 if (m_options
.m_continue
&& !m_last_id
) {
2398 // We need to stop processing data when we already ran out of instructions
2399 // in a previous command. We can fake this by setting the cursor past the
2400 // end of the trace.
2401 cursor_sp
->Seek(1, lldb::eTraceCursorSeekTypeEnd
);
2404 TraceDumper
dumper(std::move(cursor_sp
),
2405 out_file
? *out_file
: result
.GetOutputStream(),
2406 m_options
.m_dumper_options
);
2408 m_last_id
= dumper
.DumpInstructions(m_options
.m_count
);
2411 CommandOptions m_options
;
2412 // Last traversed id used to continue a repeat command. std::nullopt means
2413 // that all the trace has been consumed.
2414 std::optional
<lldb::user_id_t
> m_last_id
;
2417 // CommandObjectTraceDumpInfo
2418 #define LLDB_OPTIONS_thread_trace_dump_info
2419 #include "CommandOptions.inc"
2421 class CommandObjectTraceDumpInfo
: public CommandObjectIterateOverThreads
{
2423 class CommandOptions
: public Options
{
2425 CommandOptions() { OptionParsingStarting(nullptr); }
2427 ~CommandOptions() override
= default;
2429 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
2430 ExecutionContext
*execution_context
) override
{
2432 const int short_option
= m_getopt_table
[option_idx
].val
;
2434 switch (short_option
) {
2444 llvm_unreachable("Unimplemented option");
2449 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2454 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2455 return llvm::ArrayRef(g_thread_trace_dump_info_options
);
2458 // Instance variables to hold the values for command options.
2463 CommandObjectTraceDumpInfo(CommandInterpreter
&interpreter
)
2464 : CommandObjectIterateOverThreads(
2465 interpreter
, "thread trace dump info",
2466 "Dump the traced information for one or more threads. If no "
2467 "threads are specified, show the current thread. Use the "
2468 "thread-index \"all\" to see all threads.",
2470 eCommandRequiresProcess
| eCommandTryTargetAPILock
|
2471 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
|
2472 eCommandProcessMustBeTraced
) {}
2474 ~CommandObjectTraceDumpInfo() override
= default;
2476 Options
*GetOptions() override
{ return &m_options
; }
2479 bool HandleOneThread(lldb::tid_t tid
, CommandReturnObject
&result
) override
{
2480 const TraceSP
&trace_sp
= m_exe_ctx
.GetTargetSP()->GetTrace();
2481 ThreadSP thread_sp
=
2482 m_exe_ctx
.GetProcessPtr()->GetThreadList().FindThreadByID(tid
);
2483 trace_sp
->DumpTraceInfo(*thread_sp
, result
.GetOutputStream(),
2484 m_options
.m_verbose
, m_options
.m_json
);
2488 CommandOptions m_options
;
2491 // CommandObjectMultiwordTraceDump
2492 class CommandObjectMultiwordTraceDump
: public CommandObjectMultiword
{
2494 CommandObjectMultiwordTraceDump(CommandInterpreter
&interpreter
)
2495 : CommandObjectMultiword(
2496 interpreter
, "dump",
2497 "Commands for displaying trace information of the threads "
2498 "in the current process.",
2499 "thread trace dump <subcommand> [<subcommand objects>]") {
2502 CommandObjectSP(new CommandObjectTraceDumpInstructions(interpreter
)));
2505 CommandObjectSP(new CommandObjectTraceDumpFunctionCalls(interpreter
)));
2507 "info", CommandObjectSP(new CommandObjectTraceDumpInfo(interpreter
)));
2509 ~CommandObjectMultiwordTraceDump() override
= default;
2512 // CommandObjectMultiwordTrace
2513 class CommandObjectMultiwordTrace
: public CommandObjectMultiword
{
2515 CommandObjectMultiwordTrace(CommandInterpreter
&interpreter
)
2516 : CommandObjectMultiword(
2517 interpreter
, "trace",
2518 "Commands for operating on traces of the threads in the current "
2520 "thread trace <subcommand> [<subcommand objects>]") {
2521 LoadSubCommand("dump", CommandObjectSP(new CommandObjectMultiwordTraceDump(
2523 LoadSubCommand("start",
2524 CommandObjectSP(new CommandObjectTraceStart(interpreter
)));
2525 LoadSubCommand("stop",
2526 CommandObjectSP(new CommandObjectTraceStop(interpreter
)));
2527 LoadSubCommand("export",
2528 CommandObjectSP(new CommandObjectTraceExport(interpreter
)));
2531 ~CommandObjectMultiwordTrace() override
= default;
2534 // CommandObjectMultiwordThread
2536 CommandObjectMultiwordThread::CommandObjectMultiwordThread(
2537 CommandInterpreter
&interpreter
)
2538 : CommandObjectMultiword(interpreter
, "thread",
2539 "Commands for operating on "
2540 "one or more threads in "
2541 "the current process.",
2542 "thread <subcommand> [<subcommand-options>]") {
2543 LoadSubCommand("backtrace", CommandObjectSP(new CommandObjectThreadBacktrace(
2545 LoadSubCommand("continue",
2546 CommandObjectSP(new CommandObjectThreadContinue(interpreter
)));
2547 LoadSubCommand("list",
2548 CommandObjectSP(new CommandObjectThreadList(interpreter
)));
2549 LoadSubCommand("return",
2550 CommandObjectSP(new CommandObjectThreadReturn(interpreter
)));
2551 LoadSubCommand("jump",
2552 CommandObjectSP(new CommandObjectThreadJump(interpreter
)));
2553 LoadSubCommand("select",
2554 CommandObjectSP(new CommandObjectThreadSelect(interpreter
)));
2555 LoadSubCommand("until",
2556 CommandObjectSP(new CommandObjectThreadUntil(interpreter
)));
2557 LoadSubCommand("info",
2558 CommandObjectSP(new CommandObjectThreadInfo(interpreter
)));
2559 LoadSubCommand("exception", CommandObjectSP(new CommandObjectThreadException(
2561 LoadSubCommand("siginfo",
2562 CommandObjectSP(new CommandObjectThreadSiginfo(interpreter
)));
2563 LoadSubCommand("step-in",
2564 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2565 interpreter
, "thread step-in",
2566 "Source level single step, stepping into calls. Defaults "
2567 "to current thread unless specified.",
2568 nullptr, eStepTypeInto
, eStepScopeSource
)));
2570 LoadSubCommand("step-out",
2571 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2572 interpreter
, "thread step-out",
2573 "Finish executing the current stack frame and stop after "
2574 "returning. Defaults to current thread unless specified.",
2575 nullptr, eStepTypeOut
, eStepScopeSource
)));
2577 LoadSubCommand("step-over",
2578 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2579 interpreter
, "thread step-over",
2580 "Source level single step, stepping over calls. Defaults "
2581 "to current thread unless specified.",
2582 nullptr, eStepTypeOver
, eStepScopeSource
)));
2584 LoadSubCommand("step-inst",
2585 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2586 interpreter
, "thread step-inst",
2587 "Instruction level single step, stepping into calls. "
2588 "Defaults to current thread unless specified.",
2589 nullptr, eStepTypeTrace
, eStepScopeInstruction
)));
2591 LoadSubCommand("step-inst-over",
2592 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2593 interpreter
, "thread step-inst-over",
2594 "Instruction level single step, stepping over calls. "
2595 "Defaults to current thread unless specified.",
2596 nullptr, eStepTypeTraceOver
, eStepScopeInstruction
)));
2600 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2601 interpreter
, "thread step-scripted",
2602 "Step as instructed by the script class passed in the -C option. "
2603 "You can also specify a dictionary of key (-k) and value (-v) pairs "
2604 "that will be used to populate an SBStructuredData Dictionary, which "
2605 "will be passed to the constructor of the class implementing the "
2606 "scripted step. See the Python Reference for more details.",
2607 nullptr, eStepTypeScripted
, eStepScopeSource
)));
2609 LoadSubCommand("plan", CommandObjectSP(new CommandObjectMultiwordThreadPlan(
2611 LoadSubCommand("trace",
2612 CommandObjectSP(new CommandObjectMultiwordTrace(interpreter
)));
2615 CommandObjectMultiwordThread::~CommandObjectMultiwordThread() = default;