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/Host/OptionParser.h"
19 #include "lldb/Interpreter/CommandInterpreter.h"
20 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
21 #include "lldb/Interpreter/CommandReturnObject.h"
22 #include "lldb/Interpreter/OptionArgParser.h"
23 #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
24 #include "lldb/Interpreter/Options.h"
25 #include "lldb/Symbol/CompileUnit.h"
26 #include "lldb/Symbol/Function.h"
27 #include "lldb/Symbol/LineEntry.h"
28 #include "lldb/Symbol/LineTable.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/RegisterContext.h"
31 #include "lldb/Target/SystemRuntime.h"
32 #include "lldb/Target/Target.h"
33 #include "lldb/Target/Thread.h"
34 #include "lldb/Target/ThreadPlan.h"
35 #include "lldb/Target/ThreadPlanStepInRange.h"
36 #include "lldb/Target/Trace.h"
37 #include "lldb/Target/TraceDumper.h"
38 #include "lldb/Utility/State.h"
39 #include "lldb/ValueObject/ValueObject.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
= Status::FromErrorStringWithFormat(
70 "invalid integer value for option '%c': %s", short_option
,
73 // A count of 0 means all frames.
78 if (option_arg
.getAsInteger(0, m_start
))
79 error
= Status::FromErrorStringWithFormat(
80 "invalid integer value for option '%c': %s", short_option
,
85 m_extended_backtrace
=
86 OptionArgParser::ToBoolean(option_arg
, false, &success
);
88 error
= Status::FromErrorStringWithFormat(
89 "invalid boolean value for option '%c': %s", short_option
,
93 m_filtered_backtrace
= false;
96 llvm_unreachable("Unimplemented option");
101 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
102 m_count
= UINT32_MAX
;
104 m_extended_backtrace
= false;
105 m_filtered_backtrace
= true;
108 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
109 return llvm::ArrayRef(g_thread_backtrace_options
);
112 // Instance variables to hold the values for command options.
115 bool m_extended_backtrace
;
116 bool m_filtered_backtrace
;
119 CommandObjectThreadBacktrace(CommandInterpreter
&interpreter
)
120 : CommandObjectIterateOverThreads(
121 interpreter
, "thread backtrace",
122 "Show backtraces of thread call stacks. Defaults to the current "
123 "thread, thread indexes can be specified as arguments.\n"
124 "Use the thread-index \"all\" to see all threads.\n"
125 "Use the thread-index \"unique\" to see threads grouped by unique "
127 "Use 'settings set frame-format' to customize the printing of "
128 "frames in the backtrace and 'settings set thread-format' to "
129 "customize the thread header.\n"
130 "Customizable frame recognizers may filter out less interesting "
131 "frames, which results in gaps in the numbering. "
132 "Use '-u' to see all frames.",
134 eCommandRequiresProcess
| eCommandRequiresThread
|
135 eCommandTryTargetAPILock
| eCommandProcessMustBeLaunched
|
136 eCommandProcessMustBePaused
) {}
138 ~CommandObjectThreadBacktrace() override
= default;
140 Options
*GetOptions() override
{ return &m_options
; }
142 std::optional
<std::string
> GetRepeatCommand(Args
¤t_args
,
143 uint32_t index
) override
{
144 llvm::StringRef
count_opt("--count");
145 llvm::StringRef
start_opt("--start");
147 // If no "count" was provided, we are dumping the entire backtrace, so
148 // there isn't a repeat command. So we search for the count option in
149 // the args, and if we find it, we make a copy and insert or modify the
150 // start option's value to start count indices greater.
152 Args
copy_args(current_args
);
153 size_t num_entries
= copy_args
.GetArgumentCount();
154 // These two point at the index of the option value if found.
155 size_t count_idx
= 0;
156 size_t start_idx
= 0;
157 size_t count_val
= 0;
158 size_t start_val
= 0;
160 for (size_t idx
= 0; idx
< num_entries
; idx
++) {
161 llvm::StringRef arg_string
= copy_args
[idx
].ref();
162 if (arg_string
== "-c" || count_opt
.starts_with(arg_string
)) {
164 if (idx
== num_entries
)
167 if (copy_args
[idx
].ref().getAsInteger(0, count_val
))
169 } else if (arg_string
== "-s" || start_opt
.starts_with(arg_string
)) {
171 if (idx
== num_entries
)
174 if (copy_args
[idx
].ref().getAsInteger(0, start_val
))
181 std::string new_start_val
= llvm::formatv("{0}", start_val
+ count_val
);
182 if (start_idx
== 0) {
183 copy_args
.AppendArgument(start_opt
);
184 copy_args
.AppendArgument(new_start_val
);
186 copy_args
.ReplaceArgumentAtIndex(start_idx
, new_start_val
);
188 std::string repeat_command
;
189 if (!copy_args
.GetQuotedCommandString(repeat_command
))
191 return repeat_command
;
195 void DoExtendedBacktrace(Thread
*thread
, CommandReturnObject
&result
) {
196 SystemRuntime
*runtime
= thread
->GetProcess()->GetSystemRuntime();
198 Stream
&strm
= result
.GetOutputStream();
199 const std::vector
<ConstString
> &types
=
200 runtime
->GetExtendedBacktraceTypes();
201 for (auto type
: types
) {
202 ThreadSP ext_thread_sp
= runtime
->GetExtendedBacktraceThread(
203 thread
->shared_from_this(), type
);
204 if (ext_thread_sp
&& ext_thread_sp
->IsValid()) {
205 const uint32_t num_frames_with_source
= 0;
206 const bool stop_format
= false;
208 if (ext_thread_sp
->GetStatus(strm
, m_options
.m_start
,
210 num_frames_with_source
, stop_format
,
211 !m_options
.m_filtered_backtrace
)) {
212 DoExtendedBacktrace(ext_thread_sp
.get(), result
);
219 bool HandleOneThread(lldb::tid_t tid
, CommandReturnObject
&result
) override
{
221 m_exe_ctx
.GetProcessPtr()->GetThreadList().FindThreadByID(tid
);
223 result
.AppendErrorWithFormat(
224 "thread disappeared while computing backtraces: 0x%" PRIx64
"\n",
229 Thread
*thread
= thread_sp
.get();
231 Stream
&strm
= result
.GetOutputStream();
233 // Only dump stack info if we processing unique stacks.
234 const bool only_stacks
= m_unique_stacks
;
236 // Don't show source context when doing backtraces.
237 const uint32_t num_frames_with_source
= 0;
238 const bool stop_format
= true;
239 if (!thread
->GetStatus(strm
, m_options
.m_start
, m_options
.m_count
,
240 num_frames_with_source
, stop_format
,
241 !m_options
.m_filtered_backtrace
, only_stacks
)) {
242 result
.AppendErrorWithFormat(
243 "error displaying backtrace for thread: \"0x%4.4x\"\n",
244 thread
->GetIndexID());
247 if (m_options
.m_extended_backtrace
) {
248 if (!INTERRUPT_REQUESTED(GetDebugger(),
249 "Interrupt skipped extended backtrace")) {
250 DoExtendedBacktrace(thread
, result
);
257 CommandOptions m_options
;
260 #define LLDB_OPTIONS_thread_step_scope
261 #include "CommandOptions.inc"
263 class ThreadStepScopeOptionGroup
: public OptionGroup
{
265 ThreadStepScopeOptionGroup() {
266 // Keep default values of all options in one place: OptionParsingStarting
268 OptionParsingStarting(nullptr);
271 ~ThreadStepScopeOptionGroup() override
= default;
273 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
274 return llvm::ArrayRef(g_thread_step_scope_options
);
277 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
278 ExecutionContext
*execution_context
) override
{
280 const int short_option
=
281 g_thread_step_scope_options
[option_idx
].short_option
;
283 switch (short_option
) {
286 bool avoid_no_debug
=
287 OptionArgParser::ToBoolean(option_arg
, true, &success
);
289 error
= Status::FromErrorStringWithFormat(
290 "invalid boolean value for option '%c': %s", short_option
,
293 m_step_in_avoid_no_debug
= avoid_no_debug
? eLazyBoolYes
: eLazyBoolNo
;
299 bool avoid_no_debug
=
300 OptionArgParser::ToBoolean(option_arg
, true, &success
);
302 error
= Status::FromErrorStringWithFormat(
303 "invalid boolean value for option '%c': %s", short_option
,
306 m_step_out_avoid_no_debug
= avoid_no_debug
? eLazyBoolYes
: eLazyBoolNo
;
311 if (option_arg
.getAsInteger(0, m_step_count
))
312 error
= Status::FromErrorStringWithFormat(
313 "invalid integer value for option '%c': %s", short_option
,
318 auto enum_values
= GetDefinitions()[option_idx
].enum_values
;
319 m_run_mode
= (lldb::RunMode
)OptionArgParser::ToOptionEnum(
320 option_arg
, enum_values
, eOnlyDuringStepping
, error
);
324 if (option_arg
== "block") {
325 m_end_line_is_block_end
= true;
328 if (option_arg
.getAsInteger(0, m_end_line
))
329 error
= Status::FromErrorStringWithFormat(
330 "invalid end line number '%s'", option_arg
.str().c_str());
334 m_avoid_regexp
.clear();
335 m_avoid_regexp
.assign(std::string(option_arg
));
339 m_step_in_target
.clear();
340 m_step_in_target
.assign(std::string(option_arg
));
344 llvm_unreachable("Unimplemented option");
349 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
350 m_step_in_avoid_no_debug
= eLazyBoolCalculate
;
351 m_step_out_avoid_no_debug
= eLazyBoolCalculate
;
352 m_run_mode
= eOnlyDuringStepping
;
354 // Check if we are in Non-Stop mode
356 execution_context
? execution_context
->GetTargetSP() : TargetSP();
357 ProcessSP process_sp
=
358 execution_context
? execution_context
->GetProcessSP() : ProcessSP();
359 if (process_sp
&& process_sp
->GetSteppingRunsAllThreads())
360 m_run_mode
= eAllThreads
;
362 m_avoid_regexp
.clear();
363 m_step_in_target
.clear();
365 m_end_line
= LLDB_INVALID_LINE_NUMBER
;
366 m_end_line_is_block_end
= false;
369 // Instance variables to hold the values for command options.
370 LazyBool m_step_in_avoid_no_debug
;
371 LazyBool m_step_out_avoid_no_debug
;
373 std::string m_avoid_regexp
;
374 std::string m_step_in_target
;
375 uint32_t m_step_count
;
377 bool m_end_line_is_block_end
;
380 class CommandObjectThreadStepWithTypeAndScope
: public CommandObjectParsed
{
382 CommandObjectThreadStepWithTypeAndScope(CommandInterpreter
&interpreter
,
383 const char *name
, const char *help
,
386 : CommandObjectParsed(interpreter
, name
, help
, syntax
,
387 eCommandRequiresProcess
| eCommandRequiresThread
|
388 eCommandTryTargetAPILock
|
389 eCommandProcessMustBeLaunched
|
390 eCommandProcessMustBePaused
),
391 m_step_type(step_type
), m_class_options("scripted step") {
392 AddSimpleArgumentList(eArgTypeThreadIndex
, eArgRepeatOptional
);
394 if (step_type
== eStepTypeScripted
) {
395 m_all_options
.Append(&m_class_options
, LLDB_OPT_SET_1
| LLDB_OPT_SET_2
,
398 m_all_options
.Append(&m_options
);
399 m_all_options
.Finalize();
402 ~CommandObjectThreadStepWithTypeAndScope() override
= default;
405 HandleArgumentCompletion(CompletionRequest
&request
,
406 OptionElementVector
&opt_element_vector
) override
{
407 if (request
.GetCursorIndex())
409 CommandObject::HandleArgumentCompletion(request
, opt_element_vector
);
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 sc
.GetAddressRangeFromHereToEndLine(m_options
.m_end_line
, range
);
495 result
.AppendErrorWithFormatv("invalid end-line option: {0}.",
496 llvm::toString(std::move(err
)));
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(std::move(new_plan_status
));
629 StepType m_step_type
;
630 ThreadStepScopeOptionGroup m_options
;
631 OptionGroupPythonClassWithDict m_class_options
;
632 OptionGroupOptions m_all_options
;
635 // CommandObjectThreadContinue
637 class CommandObjectThreadContinue
: public CommandObjectParsed
{
639 CommandObjectThreadContinue(CommandInterpreter
&interpreter
)
640 : CommandObjectParsed(
641 interpreter
, "thread continue",
642 "Continue execution of the current target process. One "
643 "or more threads may be specified, by default all "
646 eCommandRequiresThread
| eCommandTryTargetAPILock
|
647 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {
648 AddSimpleArgumentList(eArgTypeThreadIndex
, eArgRepeatPlus
);
651 ~CommandObjectThreadContinue() override
= default;
653 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
654 bool synchronous_execution
= m_interpreter
.GetSynchronous();
656 Process
*process
= m_exe_ctx
.GetProcessPtr();
657 if (process
== nullptr) {
658 result
.AppendError("no process exists. Cannot continue");
662 StateType state
= process
->GetState();
663 if ((state
== eStateCrashed
) || (state
== eStateStopped
) ||
664 (state
== eStateSuspended
)) {
665 const size_t argc
= command
.GetArgumentCount();
667 // These two lines appear at the beginning of both blocks in this
668 // if..else, but that is because we need to release the lock before
669 // calling process->Resume below.
670 std::lock_guard
<std::recursive_mutex
> guard(
671 process
->GetThreadList().GetMutex());
672 const uint32_t num_threads
= process
->GetThreadList().GetSize();
673 std::vector
<Thread
*> resume_threads
;
674 for (auto &entry
: command
.entries()) {
676 if (entry
.ref().getAsInteger(0, thread_idx
)) {
677 result
.AppendErrorWithFormat(
678 "invalid thread index argument: \"%s\".\n", entry
.c_str());
682 process
->GetThreadList().FindThreadByIndexID(thread_idx
).get();
685 resume_threads
.push_back(thread
);
687 result
.AppendErrorWithFormat("invalid thread index %u.\n",
693 if (resume_threads
.empty()) {
694 result
.AppendError("no valid thread indexes were specified");
697 if (resume_threads
.size() == 1)
698 result
.AppendMessageWithFormat("Resuming thread: ");
700 result
.AppendMessageWithFormat("Resuming threads: ");
702 for (uint32_t idx
= 0; idx
< num_threads
; ++idx
) {
704 process
->GetThreadList().GetThreadAtIndex(idx
).get();
705 std::vector
<Thread
*>::iterator this_thread_pos
=
706 find(resume_threads
.begin(), resume_threads
.end(), thread
);
708 if (this_thread_pos
!= resume_threads
.end()) {
709 resume_threads
.erase(this_thread_pos
);
710 if (!resume_threads
.empty())
711 result
.AppendMessageWithFormat("%u, ", thread
->GetIndexID());
713 result
.AppendMessageWithFormat("%u ", thread
->GetIndexID());
715 const bool override_suspend
= true;
716 thread
->SetResumeState(eStateRunning
, override_suspend
);
718 thread
->SetResumeState(eStateSuspended
);
721 result
.AppendMessageWithFormat("in process %" PRIu64
"\n",
725 // These two lines appear at the beginning of both blocks in this
726 // if..else, but that is because we need to release the lock before
727 // calling process->Resume below.
728 std::lock_guard
<std::recursive_mutex
> guard(
729 process
->GetThreadList().GetMutex());
730 const uint32_t num_threads
= process
->GetThreadList().GetSize();
731 Thread
*current_thread
= GetDefaultThread();
732 if (current_thread
== nullptr) {
733 result
.AppendError("the process doesn't have a current thread");
736 // Set the actions that the threads should each take when resuming
737 for (uint32_t idx
= 0; idx
< num_threads
; ++idx
) {
738 Thread
*thread
= process
->GetThreadList().GetThreadAtIndex(idx
).get();
739 if (thread
== current_thread
) {
740 result
.AppendMessageWithFormat("Resuming thread 0x%4.4" PRIx64
741 " in process %" PRIu64
"\n",
742 thread
->GetID(), process
->GetID());
743 const bool override_suspend
= true;
744 thread
->SetResumeState(eStateRunning
, override_suspend
);
746 thread
->SetResumeState(eStateSuspended
);
753 if (synchronous_execution
)
754 error
= process
->ResumeSynchronous(&stream
);
756 error
= process
->Resume();
758 // We should not be holding the thread list lock when we do this.
759 if (error
.Success()) {
760 result
.AppendMessageWithFormat("Process %" PRIu64
" resuming\n",
762 if (synchronous_execution
) {
763 // If any state changed events had anything to say, add that to the
765 if (stream
.GetSize() > 0)
766 result
.AppendMessage(stream
.GetString());
768 result
.SetDidChangeProcessState(true);
769 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
771 result
.SetStatus(eReturnStatusSuccessContinuingNoResult
);
774 result
.AppendErrorWithFormat("Failed to resume process: %s\n",
778 result
.AppendErrorWithFormat(
779 "Process cannot be continued from its current state (%s).\n",
780 StateAsCString(state
));
785 // CommandObjectThreadUntil
787 #define LLDB_OPTIONS_thread_until
788 #include "CommandOptions.inc"
790 class CommandObjectThreadUntil
: public CommandObjectParsed
{
792 class CommandOptions
: public Options
{
794 uint32_t m_thread_idx
= LLDB_INVALID_THREAD_ID
;
795 uint32_t m_frame_idx
= LLDB_INVALID_FRAME_ID
;
798 // Keep default values of all options in one place: OptionParsingStarting
800 OptionParsingStarting(nullptr);
803 ~CommandOptions() override
= default;
805 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
806 ExecutionContext
*execution_context
) override
{
808 const int short_option
= m_getopt_table
[option_idx
].val
;
810 switch (short_option
) {
812 lldb::addr_t tmp_addr
= OptionArgParser::ToAddress(
813 execution_context
, option_arg
, LLDB_INVALID_ADDRESS
, &error
);
815 m_until_addrs
.push_back(tmp_addr
);
818 if (option_arg
.getAsInteger(0, m_thread_idx
)) {
819 m_thread_idx
= LLDB_INVALID_INDEX32
;
820 error
= Status::FromErrorStringWithFormat("invalid thread index '%s'",
821 option_arg
.str().c_str());
825 if (option_arg
.getAsInteger(0, m_frame_idx
)) {
826 m_frame_idx
= LLDB_INVALID_FRAME_ID
;
827 error
= Status::FromErrorStringWithFormat("invalid frame index '%s'",
828 option_arg
.str().c_str());
832 auto enum_values
= GetDefinitions()[option_idx
].enum_values
;
833 lldb::RunMode run_mode
= (lldb::RunMode
)OptionArgParser::ToOptionEnum(
834 option_arg
, enum_values
, eOnlyDuringStepping
, error
);
836 if (error
.Success()) {
837 if (run_mode
== eAllThreads
)
838 m_stop_others
= false;
840 m_stop_others
= true;
844 llvm_unreachable("Unimplemented option");
849 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
850 m_thread_idx
= LLDB_INVALID_THREAD_ID
;
852 m_stop_others
= false;
853 m_until_addrs
.clear();
856 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
857 return llvm::ArrayRef(g_thread_until_options
);
860 uint32_t m_step_thread_idx
= LLDB_INVALID_THREAD_ID
;
861 bool m_stop_others
= false;
862 std::vector
<lldb::addr_t
> m_until_addrs
;
864 // Instance variables to hold the values for command options.
867 CommandObjectThreadUntil(CommandInterpreter
&interpreter
)
868 : CommandObjectParsed(
869 interpreter
, "thread until",
870 "Continue until a line number or address is reached by the "
871 "current or specified thread. Stops when returning from "
872 "the current function as a safety measure. "
873 "The target line number(s) are given as arguments, and if more "
875 " is provided, stepping will stop when the first one is hit.",
877 eCommandRequiresThread
| eCommandTryTargetAPILock
|
878 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {
879 AddSimpleArgumentList(eArgTypeLineNum
);
882 ~CommandObjectThreadUntil() override
= default;
884 Options
*GetOptions() override
{ return &m_options
; }
887 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
888 bool synchronous_execution
= m_interpreter
.GetSynchronous();
890 Target
*target
= &GetTarget();
892 Process
*process
= m_exe_ctx
.GetProcessPtr();
893 if (process
== nullptr) {
894 result
.AppendError("need a valid process to step");
896 Thread
*thread
= nullptr;
897 std::vector
<uint32_t> line_numbers
;
899 if (command
.GetArgumentCount() >= 1) {
900 size_t num_args
= command
.GetArgumentCount();
901 for (size_t i
= 0; i
< num_args
; i
++) {
902 uint32_t line_number
;
903 if (!llvm::to_integer(command
.GetArgumentAtIndex(i
), line_number
)) {
904 result
.AppendErrorWithFormat("invalid line number: '%s'.\n",
905 command
.GetArgumentAtIndex(i
));
908 line_numbers
.push_back(line_number
);
910 } else if (m_options
.m_until_addrs
.empty()) {
911 result
.AppendErrorWithFormat("No line number or address provided:\n%s",
912 GetSyntax().str().c_str());
916 if (m_options
.m_thread_idx
== LLDB_INVALID_THREAD_ID
) {
917 thread
= GetDefaultThread();
919 thread
= process
->GetThreadList()
920 .FindThreadByIndexID(m_options
.m_thread_idx
)
924 if (thread
== nullptr) {
925 const uint32_t num_threads
= process
->GetThreadList().GetSize();
926 result
.AppendErrorWithFormat(
927 "Thread index %u is out of range (valid values are 0 - %u).\n",
928 m_options
.m_thread_idx
, num_threads
);
932 const bool abort_other_plans
= false;
935 thread
->GetStackFrameAtIndex(m_options
.m_frame_idx
).get();
936 if (frame
== nullptr) {
937 result
.AppendErrorWithFormat(
938 "Frame index %u is out of range for thread id %" PRIu64
".\n",
939 m_options
.m_frame_idx
, thread
->GetID());
943 ThreadPlanSP new_plan_sp
;
944 Status new_plan_status
;
946 if (frame
->HasDebugInformation()) {
947 // Finally we got here... Translate the given line number to a bunch
949 SymbolContext
sc(frame
->GetSymbolContext(eSymbolContextCompUnit
));
950 LineTable
*line_table
= nullptr;
952 line_table
= sc
.comp_unit
->GetLineTable();
954 if (line_table
== nullptr) {
955 result
.AppendErrorWithFormat("Failed to resolve the line table for "
956 "frame %u of thread id %" PRIu64
".\n",
957 m_options
.m_frame_idx
, thread
->GetID());
961 LineEntry function_start
;
962 uint32_t index_ptr
= 0, end_ptr
= UINT32_MAX
;
963 std::vector
<addr_t
> address_list
;
965 // Find the beginning & end index of the function, but first make
968 result
.AppendErrorWithFormat("Have debug information but no "
969 "function info - can't get until range.");
973 AddressRange fun_addr_range
= sc
.function
->GetAddressRange();
974 Address fun_start_addr
= fun_addr_range
.GetBaseAddress();
975 line_table
->FindLineEntryByAddress(fun_start_addr
, function_start
,
978 Address
fun_end_addr(fun_start_addr
.GetSection(),
979 fun_start_addr
.GetOffset() +
980 fun_addr_range
.GetByteSize());
982 bool all_in_function
= true;
984 line_table
->FindLineEntryByAddress(fun_end_addr
, function_start
,
987 // Since not all source lines will contribute code, check if we are
988 // setting the breakpoint on the exact line number or the nearest
989 // subsequent line number and set breakpoints at all the line table
990 // entries of the chosen line number (exact or nearest subsequent).
991 for (uint32_t line_number
: line_numbers
) {
992 LineEntry line_entry
;
994 uint32_t start_idx_ptr
= index_ptr
;
995 start_idx_ptr
= sc
.comp_unit
->FindLineEntry(
996 index_ptr
, line_number
, nullptr, exact
, &line_entry
);
997 if (start_idx_ptr
!= UINT32_MAX
)
998 line_number
= line_entry
.line
;
1000 start_idx_ptr
= index_ptr
;
1001 while (start_idx_ptr
<= end_ptr
) {
1002 start_idx_ptr
= sc
.comp_unit
->FindLineEntry(
1003 start_idx_ptr
, line_number
, nullptr, exact
, &line_entry
);
1004 if (start_idx_ptr
== UINT32_MAX
)
1008 line_entry
.range
.GetBaseAddress().GetLoadAddress(target
);
1009 if (address
!= LLDB_INVALID_ADDRESS
) {
1010 if (fun_addr_range
.ContainsLoadAddress(address
, target
))
1011 address_list
.push_back(address
);
1013 all_in_function
= false;
1019 for (lldb::addr_t address
: m_options
.m_until_addrs
) {
1020 if (fun_addr_range
.ContainsLoadAddress(address
, target
))
1021 address_list
.push_back(address
);
1023 all_in_function
= false;
1026 if (address_list
.empty()) {
1027 if (all_in_function
)
1028 result
.AppendErrorWithFormat(
1029 "No line entries matching until target.\n");
1031 result
.AppendErrorWithFormat(
1032 "Until target outside of the current function.\n");
1037 new_plan_sp
= thread
->QueueThreadPlanForStepUntil(
1038 abort_other_plans
, &address_list
.front(), address_list
.size(),
1039 m_options
.m_stop_others
, m_options
.m_frame_idx
, new_plan_status
);
1041 // User level plans should be controlling plans so they can be
1043 // (e.g. by hitting a breakpoint) and other plans executed by the
1044 // user (stepping around the breakpoint) and then a "continue" will
1045 // resume the original plan.
1046 new_plan_sp
->SetIsControllingPlan(true);
1047 new_plan_sp
->SetOkayToDiscard(false);
1049 result
.SetError(std::move(new_plan_status
));
1053 result
.AppendErrorWithFormat("Frame index %u of thread id %" PRIu64
1054 " has no debug information.\n",
1055 m_options
.m_frame_idx
, thread
->GetID());
1059 if (!process
->GetThreadList().SetSelectedThreadByID(thread
->GetID())) {
1060 result
.AppendErrorWithFormat(
1061 "Failed to set the selected thread to thread id %" PRIu64
".\n",
1066 StreamString stream
;
1068 if (synchronous_execution
)
1069 error
= process
->ResumeSynchronous(&stream
);
1071 error
= process
->Resume();
1073 if (error
.Success()) {
1074 result
.AppendMessageWithFormat("Process %" PRIu64
" resuming\n",
1076 if (synchronous_execution
) {
1077 // If any state changed events had anything to say, add that to the
1079 if (stream
.GetSize() > 0)
1080 result
.AppendMessage(stream
.GetString());
1082 result
.SetDidChangeProcessState(true);
1083 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1085 result
.SetStatus(eReturnStatusSuccessContinuingNoResult
);
1088 result
.AppendErrorWithFormat("Failed to resume process: %s.\n",
1094 CommandOptions m_options
;
1097 // CommandObjectThreadSelect
1099 #define LLDB_OPTIONS_thread_select
1100 #include "CommandOptions.inc"
1102 class CommandObjectThreadSelect
: public CommandObjectParsed
{
1104 class OptionGroupThreadSelect
: public OptionGroup
{
1106 OptionGroupThreadSelect() { OptionParsingStarting(nullptr); }
1108 ~OptionGroupThreadSelect() override
= default;
1110 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1111 m_thread_id
= LLDB_INVALID_THREAD_ID
;
1114 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1115 ExecutionContext
*execution_context
) override
{
1116 const int short_option
= g_thread_select_options
[option_idx
].short_option
;
1117 switch (short_option
) {
1119 if (option_arg
.getAsInteger(0, m_thread_id
)) {
1120 m_thread_id
= LLDB_INVALID_THREAD_ID
;
1121 return Status::FromErrorStringWithFormat("Invalid thread ID: '%s'.",
1122 option_arg
.str().c_str());
1128 llvm_unreachable("Unimplemented option");
1134 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1135 return llvm::ArrayRef(g_thread_select_options
);
1138 lldb::tid_t m_thread_id
;
1141 CommandObjectThreadSelect(CommandInterpreter
&interpreter
)
1142 : CommandObjectParsed(interpreter
, "thread select",
1143 "Change the currently selected thread.",
1144 "thread select <thread-index> (or -t <thread-id>)",
1145 eCommandRequiresProcess
| eCommandTryTargetAPILock
|
1146 eCommandProcessMustBeLaunched
|
1147 eCommandProcessMustBePaused
) {
1148 CommandArgumentEntry arg
;
1149 CommandArgumentData thread_idx_arg
;
1151 // Define the first (and only) variant of this arg.
1152 thread_idx_arg
.arg_type
= eArgTypeThreadIndex
;
1153 thread_idx_arg
.arg_repetition
= eArgRepeatPlain
;
1154 thread_idx_arg
.arg_opt_set_association
= LLDB_OPT_SET_1
;
1156 // There is only one variant this argument could be; put it into the
1158 arg
.push_back(thread_idx_arg
);
1160 // Push the data for the first argument into the m_arguments vector.
1161 m_arguments
.push_back(arg
);
1163 m_option_group
.Append(&m_options
, LLDB_OPT_SET_ALL
, LLDB_OPT_SET_2
);
1164 m_option_group
.Finalize();
1167 ~CommandObjectThreadSelect() override
= default;
1170 HandleArgumentCompletion(CompletionRequest
&request
,
1171 OptionElementVector
&opt_element_vector
) override
{
1172 if (request
.GetCursorIndex())
1175 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1176 GetCommandInterpreter(), lldb::eThreadIndexCompletion
, request
,
1180 Options
*GetOptions() override
{ return &m_option_group
; }
1183 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1184 Process
*process
= m_exe_ctx
.GetProcessPtr();
1185 if (process
== nullptr) {
1186 result
.AppendError("no process");
1188 } else if (m_options
.m_thread_id
== LLDB_INVALID_THREAD_ID
&&
1189 command
.GetArgumentCount() != 1) {
1190 result
.AppendErrorWithFormat(
1191 "'%s' takes exactly one thread index argument, or a thread ID "
1192 "option:\nUsage: %s\n",
1193 m_cmd_name
.c_str(), m_cmd_syntax
.c_str());
1195 } else if (m_options
.m_thread_id
!= LLDB_INVALID_THREAD_ID
&&
1196 command
.GetArgumentCount() != 0) {
1197 result
.AppendErrorWithFormat("'%s' cannot take both a thread ID option "
1198 "and a thread index argument:\nUsage: %s\n",
1199 m_cmd_name
.c_str(), m_cmd_syntax
.c_str());
1203 Thread
*new_thread
= nullptr;
1204 if (command
.GetArgumentCount() == 1) {
1206 if (!llvm::to_integer(command
.GetArgumentAtIndex(0), index_id
)) {
1207 result
.AppendErrorWithFormat("Invalid thread index '%s'",
1208 command
.GetArgumentAtIndex(0));
1211 new_thread
= process
->GetThreadList().FindThreadByIndexID(index_id
).get();
1212 if (new_thread
== nullptr) {
1213 result
.AppendErrorWithFormat("Invalid thread index #%s.\n",
1214 command
.GetArgumentAtIndex(0));
1219 process
->GetThreadList().FindThreadByID(m_options
.m_thread_id
).get();
1220 if (new_thread
== nullptr) {
1221 result
.AppendErrorWithFormat("Invalid thread ID %" PRIu64
".\n",
1222 m_options
.m_thread_id
);
1227 process
->GetThreadList().SetSelectedThreadByID(new_thread
->GetID(), true);
1228 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1231 OptionGroupThreadSelect m_options
;
1232 OptionGroupOptions m_option_group
;
1235 // CommandObjectThreadList
1237 class CommandObjectThreadList
: public CommandObjectParsed
{
1239 CommandObjectThreadList(CommandInterpreter
&interpreter
)
1240 : CommandObjectParsed(
1241 interpreter
, "thread list",
1242 "Show a summary of each thread in the current target process. "
1243 "Use 'settings set thread-format' to customize the individual "
1246 eCommandRequiresProcess
| eCommandTryTargetAPILock
|
1247 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {}
1249 ~CommandObjectThreadList() override
= default;
1252 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1253 Stream
&strm
= result
.GetOutputStream();
1254 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1255 Process
*process
= m_exe_ctx
.GetProcessPtr();
1256 const bool only_threads_with_stop_reason
= false;
1257 const uint32_t start_frame
= 0;
1258 const uint32_t num_frames
= 0;
1259 const uint32_t num_frames_with_source
= 0;
1260 process
->GetStatus(strm
);
1261 process
->GetThreadStatus(strm
, only_threads_with_stop_reason
, start_frame
,
1262 num_frames
, num_frames_with_source
, false);
1266 // CommandObjectThreadInfo
1267 #define LLDB_OPTIONS_thread_info
1268 #include "CommandOptions.inc"
1270 class CommandObjectThreadInfo
: public CommandObjectIterateOverThreads
{
1272 class CommandOptions
: public Options
{
1274 CommandOptions() { OptionParsingStarting(nullptr); }
1276 ~CommandOptions() override
= default;
1278 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1279 m_json_thread
= false;
1280 m_json_stopinfo
= false;
1283 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1284 ExecutionContext
*execution_context
) override
{
1285 const int short_option
= m_getopt_table
[option_idx
].val
;
1288 switch (short_option
) {
1290 m_json_thread
= true;
1294 m_json_stopinfo
= true;
1298 llvm_unreachable("Unimplemented option");
1303 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1304 return llvm::ArrayRef(g_thread_info_options
);
1308 bool m_json_stopinfo
;
1311 CommandObjectThreadInfo(CommandInterpreter
&interpreter
)
1312 : CommandObjectIterateOverThreads(
1313 interpreter
, "thread info",
1314 "Show an extended summary of one or "
1315 "more threads. Defaults to the "
1318 eCommandRequiresProcess
| eCommandTryTargetAPILock
|
1319 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {
1320 m_add_return
= false;
1323 ~CommandObjectThreadInfo() override
= default;
1326 HandleArgumentCompletion(CompletionRequest
&request
,
1327 OptionElementVector
&opt_element_vector
) override
{
1328 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1329 GetCommandInterpreter(), lldb::eThreadIndexCompletion
, request
,
1333 Options
*GetOptions() override
{ return &m_options
; }
1335 bool HandleOneThread(lldb::tid_t tid
, CommandReturnObject
&result
) override
{
1336 ThreadSP thread_sp
=
1337 m_exe_ctx
.GetProcessPtr()->GetThreadList().FindThreadByID(tid
);
1339 result
.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64
"\n",
1344 Thread
*thread
= thread_sp
.get();
1346 Stream
&strm
= result
.GetOutputStream();
1347 if (!thread
->GetDescription(strm
, eDescriptionLevelFull
,
1348 m_options
.m_json_thread
,
1349 m_options
.m_json_stopinfo
)) {
1350 result
.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n",
1351 thread
->GetIndexID());
1357 CommandOptions m_options
;
1360 // CommandObjectThreadException
1362 class CommandObjectThreadException
: public CommandObjectIterateOverThreads
{
1364 CommandObjectThreadException(CommandInterpreter
&interpreter
)
1365 : CommandObjectIterateOverThreads(
1366 interpreter
, "thread exception",
1367 "Display the current exception object for a thread. Defaults to "
1368 "the current thread.",
1370 eCommandRequiresProcess
| eCommandTryTargetAPILock
|
1371 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {}
1373 ~CommandObjectThreadException() override
= default;
1376 HandleArgumentCompletion(CompletionRequest
&request
,
1377 OptionElementVector
&opt_element_vector
) override
{
1378 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1379 GetCommandInterpreter(), lldb::eThreadIndexCompletion
, request
,
1383 bool HandleOneThread(lldb::tid_t tid
, CommandReturnObject
&result
) override
{
1384 ThreadSP thread_sp
=
1385 m_exe_ctx
.GetProcessPtr()->GetThreadList().FindThreadByID(tid
);
1387 result
.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64
"\n",
1392 Stream
&strm
= result
.GetOutputStream();
1393 ValueObjectSP exception_object_sp
= thread_sp
->GetCurrentException();
1394 if (exception_object_sp
) {
1395 if (llvm::Error error
= exception_object_sp
->Dump(strm
)) {
1396 result
.AppendError(toString(std::move(error
)));
1401 ThreadSP exception_thread_sp
= thread_sp
->GetCurrentExceptionBacktrace();
1402 if (exception_thread_sp
&& exception_thread_sp
->IsValid()) {
1403 const uint32_t num_frames_with_source
= 0;
1404 const bool stop_format
= false;
1405 exception_thread_sp
->GetStatus(strm
, 0, UINT32_MAX
,
1406 num_frames_with_source
, stop_format
,
1407 /*filtered*/ false);
1414 class CommandObjectThreadSiginfo
: public CommandObjectIterateOverThreads
{
1416 CommandObjectThreadSiginfo(CommandInterpreter
&interpreter
)
1417 : CommandObjectIterateOverThreads(
1418 interpreter
, "thread siginfo",
1419 "Display the current siginfo object for a thread. Defaults to "
1420 "the current thread.",
1422 eCommandRequiresProcess
| eCommandTryTargetAPILock
|
1423 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {}
1425 ~CommandObjectThreadSiginfo() override
= default;
1428 HandleArgumentCompletion(CompletionRequest
&request
,
1429 OptionElementVector
&opt_element_vector
) override
{
1430 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1431 GetCommandInterpreter(), lldb::eThreadIndexCompletion
, request
,
1435 bool HandleOneThread(lldb::tid_t tid
, CommandReturnObject
&result
) override
{
1436 ThreadSP thread_sp
=
1437 m_exe_ctx
.GetProcessPtr()->GetThreadList().FindThreadByID(tid
);
1439 result
.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64
"\n",
1444 Stream
&strm
= result
.GetOutputStream();
1445 if (!thread_sp
->GetDescription(strm
, eDescriptionLevelFull
, false, false)) {
1446 result
.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n",
1447 thread_sp
->GetIndexID());
1450 ValueObjectSP exception_object_sp
= thread_sp
->GetSiginfoValue();
1451 if (exception_object_sp
) {
1452 if (llvm::Error error
= exception_object_sp
->Dump(strm
)) {
1453 result
.AppendError(toString(std::move(error
)));
1457 strm
.Printf("(no siginfo)\n");
1464 // CommandObjectThreadReturn
1465 #define LLDB_OPTIONS_thread_return
1466 #include "CommandOptions.inc"
1468 class CommandObjectThreadReturn
: public CommandObjectRaw
{
1470 class CommandOptions
: public Options
{
1473 // Keep default values of all options in one place: OptionParsingStarting
1475 OptionParsingStarting(nullptr);
1478 ~CommandOptions() override
= default;
1480 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1481 ExecutionContext
*execution_context
) override
{
1483 const int short_option
= m_getopt_table
[option_idx
].val
;
1485 switch (short_option
) {
1489 OptionArgParser::ToBoolean(option_arg
, false, &success
);
1491 m_from_expression
= tmp_value
;
1493 error
= Status::FromErrorStringWithFormat(
1494 "invalid boolean value '%s' for 'x' option",
1495 option_arg
.str().c_str());
1499 llvm_unreachable("Unimplemented option");
1504 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1505 m_from_expression
= false;
1508 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1509 return llvm::ArrayRef(g_thread_return_options
);
1512 bool m_from_expression
= false;
1514 // Instance variables to hold the values for command options.
1517 CommandObjectThreadReturn(CommandInterpreter
&interpreter
)
1518 : CommandObjectRaw(interpreter
, "thread return",
1519 "Prematurely return from a stack frame, "
1520 "short-circuiting execution of newer frames "
1521 "and optionally yielding a specified value. Defaults "
1522 "to the exiting the current stack "
1525 eCommandRequiresFrame
| eCommandTryTargetAPILock
|
1526 eCommandProcessMustBeLaunched
|
1527 eCommandProcessMustBePaused
) {
1528 AddSimpleArgumentList(eArgTypeExpression
, eArgRepeatOptional
);
1531 ~CommandObjectThreadReturn() override
= default;
1533 Options
*GetOptions() override
{ return &m_options
; }
1536 void DoExecute(llvm::StringRef command
,
1537 CommandReturnObject
&result
) override
{
1538 // I am going to handle this by hand, because I don't want you to have to
1540 // "thread return -- -5".
1541 if (command
.starts_with("-x")) {
1542 if (command
.size() != 2U)
1543 result
.AppendWarning("Return values ignored when returning from user "
1544 "called expressions");
1546 Thread
*thread
= m_exe_ctx
.GetThreadPtr();
1548 error
= thread
->UnwindInnermostExpression();
1549 if (!error
.Success()) {
1550 result
.AppendErrorWithFormat("Unwinding expression failed - %s.",
1554 thread
->SetSelectedFrameByIndexNoisily(0, result
.GetOutputStream());
1556 m_exe_ctx
.SetFrameSP(
1557 thread
->GetSelectedFrame(DoNoSelectMostRelevantFrame
));
1558 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1560 result
.AppendErrorWithFormat(
1561 "Could not select 0th frame after unwinding expression.");
1567 ValueObjectSP return_valobj_sp
;
1569 StackFrameSP frame_sp
= m_exe_ctx
.GetFrameSP();
1570 uint32_t frame_idx
= frame_sp
->GetFrameIndex();
1572 if (frame_sp
->IsInlined()) {
1573 result
.AppendError("Don't know how to return from inlined frames.");
1577 if (!command
.empty()) {
1578 Target
*target
= m_exe_ctx
.GetTargetPtr();
1579 EvaluateExpressionOptions options
;
1581 options
.SetUnwindOnError(true);
1582 options
.SetUseDynamic(eNoDynamicValues
);
1584 ExpressionResults exe_results
= eExpressionSetupError
;
1585 exe_results
= target
->EvaluateExpression(command
, frame_sp
.get(),
1586 return_valobj_sp
, options
);
1587 if (exe_results
!= eExpressionCompleted
) {
1588 if (return_valobj_sp
)
1589 result
.AppendErrorWithFormat(
1590 "Error evaluating result expression: %s",
1591 return_valobj_sp
->GetError().AsCString());
1593 result
.AppendErrorWithFormat(
1594 "Unknown error evaluating result expression.");
1600 ThreadSP thread_sp
= m_exe_ctx
.GetThreadSP();
1601 const bool broadcast
= true;
1602 error
= thread_sp
->ReturnFromFrame(frame_sp
, return_valobj_sp
, broadcast
);
1603 if (!error
.Success()) {
1604 result
.AppendErrorWithFormat(
1605 "Error returning from frame %d of thread %d: %s.", frame_idx
,
1606 thread_sp
->GetIndexID(), error
.AsCString());
1610 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1613 CommandOptions m_options
;
1616 // CommandObjectThreadJump
1617 #define LLDB_OPTIONS_thread_jump
1618 #include "CommandOptions.inc"
1620 class CommandObjectThreadJump
: public CommandObjectParsed
{
1622 class CommandOptions
: public Options
{
1624 CommandOptions() { OptionParsingStarting(nullptr); }
1626 ~CommandOptions() override
= default;
1628 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1629 m_filenames
.Clear();
1632 m_load_addr
= LLDB_INVALID_ADDRESS
;
1636 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1637 ExecutionContext
*execution_context
) override
{
1638 const int short_option
= m_getopt_table
[option_idx
].val
;
1641 switch (short_option
) {
1643 m_filenames
.AppendIfUnique(FileSpec(option_arg
));
1644 if (m_filenames
.GetSize() > 1)
1645 return Status::FromErrorString("only one source file expected.");
1648 if (option_arg
.getAsInteger(0, m_line_num
))
1649 return Status::FromErrorStringWithFormat("invalid line number: '%s'.",
1650 option_arg
.str().c_str());
1653 if (option_arg
.getAsInteger(0, m_line_offset
))
1654 return Status::FromErrorStringWithFormat("invalid line offset: '%s'.",
1655 option_arg
.str().c_str());
1658 m_load_addr
= OptionArgParser::ToAddress(execution_context
, option_arg
,
1659 LLDB_INVALID_ADDRESS
, &error
);
1665 llvm_unreachable("Unimplemented option");
1670 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1671 return llvm::ArrayRef(g_thread_jump_options
);
1674 FileSpecList m_filenames
;
1675 uint32_t m_line_num
;
1676 int32_t m_line_offset
;
1677 lldb::addr_t m_load_addr
;
1681 CommandObjectThreadJump(CommandInterpreter
&interpreter
)
1682 : CommandObjectParsed(
1683 interpreter
, "thread jump",
1684 "Sets the program counter to a new address.", "thread jump",
1685 eCommandRequiresFrame
| eCommandTryTargetAPILock
|
1686 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {}
1688 ~CommandObjectThreadJump() override
= default;
1690 Options
*GetOptions() override
{ return &m_options
; }
1693 void DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
1694 RegisterContext
*reg_ctx
= m_exe_ctx
.GetRegisterContext();
1695 StackFrame
*frame
= m_exe_ctx
.GetFramePtr();
1696 Thread
*thread
= m_exe_ctx
.GetThreadPtr();
1697 Target
*target
= m_exe_ctx
.GetTargetPtr();
1698 const SymbolContext
&sym_ctx
=
1699 frame
->GetSymbolContext(eSymbolContextLineEntry
);
1701 if (m_options
.m_load_addr
!= LLDB_INVALID_ADDRESS
) {
1702 // Use this address directly.
1703 Address dest
= Address(m_options
.m_load_addr
);
1705 lldb::addr_t callAddr
= dest
.GetCallableLoadAddress(target
);
1706 if (callAddr
== LLDB_INVALID_ADDRESS
) {
1707 result
.AppendErrorWithFormat("Invalid destination address.");
1711 if (!reg_ctx
->SetPC(callAddr
)) {
1712 result
.AppendErrorWithFormat("Error changing PC value for thread %d.",
1713 thread
->GetIndexID());
1717 // Pick either the absolute line, or work out a relative one.
1718 int32_t line
= (int32_t)m_options
.m_line_num
;
1720 line
= sym_ctx
.line_entry
.line
+ m_options
.m_line_offset
;
1722 // Try the current file, but override if asked.
1723 FileSpec file
= sym_ctx
.line_entry
.GetFile();
1724 if (m_options
.m_filenames
.GetSize() == 1)
1725 file
= m_options
.m_filenames
.GetFileSpecAtIndex(0);
1728 result
.AppendErrorWithFormat(
1729 "No source file available for the current location.");
1733 std::string warnings
;
1734 Status err
= thread
->JumpToLine(file
, line
, m_options
.m_force
, &warnings
);
1737 result
.SetError(std::move(err
));
1741 if (!warnings
.empty())
1742 result
.AppendWarning(warnings
.c_str());
1745 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1748 CommandOptions m_options
;
1751 // Next are the subcommands of CommandObjectMultiwordThreadPlan
1753 // CommandObjectThreadPlanList
1754 #define LLDB_OPTIONS_thread_plan_list
1755 #include "CommandOptions.inc"
1757 class CommandObjectThreadPlanList
: public CommandObjectIterateOverThreads
{
1759 class CommandOptions
: public Options
{
1762 // Keep default values of all options in one place: OptionParsingStarting
1764 OptionParsingStarting(nullptr);
1767 ~CommandOptions() override
= default;
1769 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1770 ExecutionContext
*execution_context
) override
{
1771 const int short_option
= m_getopt_table
[option_idx
].val
;
1773 switch (short_option
) {
1779 if (option_arg
.getAsInteger(0, tid
))
1780 return Status::FromErrorStringWithFormat("invalid tid: '%s'.",
1781 option_arg
.str().c_str());
1782 m_tids
.push_back(tid
);
1785 m_unreported
= false;
1791 llvm_unreachable("Unimplemented option");
1796 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1799 m_unreported
= true; // The variable is "skip unreported" and we want to
1800 // skip unreported by default.
1804 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1805 return llvm::ArrayRef(g_thread_plan_list_options
);
1808 // Instance variables to hold the values for command options.
1812 std::vector
<lldb::tid_t
> m_tids
;
1815 CommandObjectThreadPlanList(CommandInterpreter
&interpreter
)
1816 : CommandObjectIterateOverThreads(
1817 interpreter
, "thread plan list",
1818 "Show thread plans for one or more threads. If no threads are "
1819 "specified, show the "
1820 "current thread. Use the thread-index \"all\" to see all threads.",
1822 eCommandRequiresProcess
| eCommandRequiresThread
|
1823 eCommandTryTargetAPILock
| eCommandProcessMustBeLaunched
|
1824 eCommandProcessMustBePaused
) {}
1826 ~CommandObjectThreadPlanList() override
= default;
1828 Options
*GetOptions() override
{ return &m_options
; }
1830 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1831 // If we are reporting all threads, dispatch to the Process to do that:
1832 if (command
.GetArgumentCount() == 0 && m_options
.m_tids
.empty()) {
1833 Stream
&strm
= result
.GetOutputStream();
1834 DescriptionLevel desc_level
= m_options
.m_verbose
1835 ? eDescriptionLevelVerbose
1836 : eDescriptionLevelFull
;
1837 m_exe_ctx
.GetProcessPtr()->DumpThreadPlans(
1838 strm
, desc_level
, m_options
.m_internal
, true, m_options
.m_unreported
);
1839 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1842 // Do any TID's that the user may have specified as TID, then do any
1843 // Thread Indexes...
1844 if (!m_options
.m_tids
.empty()) {
1845 Process
*process
= m_exe_ctx
.GetProcessPtr();
1846 StreamString tmp_strm
;
1847 for (lldb::tid_t tid
: m_options
.m_tids
) {
1848 bool success
= process
->DumpThreadPlansForTID(
1849 tmp_strm
, tid
, eDescriptionLevelFull
, m_options
.m_internal
,
1850 true /* condense_trivial */, m_options
.m_unreported
);
1851 // If we didn't find a TID, stop here and return an error.
1853 result
.AppendError("Error dumping plans:");
1854 result
.AppendError(tmp_strm
.GetString());
1857 // Otherwise, add our data to the output:
1858 result
.GetOutputStream() << tmp_strm
.GetString();
1861 return CommandObjectIterateOverThreads::DoExecute(command
, result
);
1866 bool HandleOneThread(lldb::tid_t tid
, CommandReturnObject
&result
) override
{
1867 // If we have already handled this from a -t option, skip it here.
1868 if (llvm::is_contained(m_options
.m_tids
, tid
))
1871 Process
*process
= m_exe_ctx
.GetProcessPtr();
1873 Stream
&strm
= result
.GetOutputStream();
1874 DescriptionLevel desc_level
= eDescriptionLevelFull
;
1875 if (m_options
.m_verbose
)
1876 desc_level
= eDescriptionLevelVerbose
;
1878 process
->DumpThreadPlansForTID(strm
, tid
, desc_level
, m_options
.m_internal
,
1879 true /* condense_trivial */,
1880 m_options
.m_unreported
);
1884 CommandOptions m_options
;
1887 class CommandObjectThreadPlanDiscard
: public CommandObjectParsed
{
1889 CommandObjectThreadPlanDiscard(CommandInterpreter
&interpreter
)
1890 : CommandObjectParsed(interpreter
, "thread plan discard",
1891 "Discards thread plans up to and including the "
1892 "specified index (see 'thread plan list'.) "
1893 "Only user visible plans can be discarded.",
1895 eCommandRequiresProcess
| eCommandRequiresThread
|
1896 eCommandTryTargetAPILock
|
1897 eCommandProcessMustBeLaunched
|
1898 eCommandProcessMustBePaused
) {
1899 AddSimpleArgumentList(eArgTypeUnsignedInteger
);
1902 ~CommandObjectThreadPlanDiscard() override
= default;
1905 HandleArgumentCompletion(CompletionRequest
&request
,
1906 OptionElementVector
&opt_element_vector
) override
{
1907 if (!m_exe_ctx
.HasThreadScope() || request
.GetCursorIndex())
1910 m_exe_ctx
.GetThreadPtr()->AutoCompleteThreadPlans(request
);
1913 void DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
1914 Thread
*thread
= m_exe_ctx
.GetThreadPtr();
1915 if (args
.GetArgumentCount() != 1) {
1916 result
.AppendErrorWithFormat("Too many arguments, expected one - the "
1917 "thread plan index - but got %zu.",
1918 args
.GetArgumentCount());
1922 uint32_t thread_plan_idx
;
1923 if (!llvm::to_integer(args
.GetArgumentAtIndex(0), thread_plan_idx
)) {
1924 result
.AppendErrorWithFormat(
1925 "Invalid thread index: \"%s\" - should be unsigned int.",
1926 args
.GetArgumentAtIndex(0));
1930 if (thread_plan_idx
== 0) {
1931 result
.AppendErrorWithFormat(
1932 "You wouldn't really want me to discard the base thread plan.");
1936 if (thread
->DiscardUserThreadPlansUpToIndex(thread_plan_idx
)) {
1937 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1939 result
.AppendErrorWithFormat(
1940 "Could not find User thread plan with index %s.",
1941 args
.GetArgumentAtIndex(0));
1946 class CommandObjectThreadPlanPrune
: public CommandObjectParsed
{
1948 CommandObjectThreadPlanPrune(CommandInterpreter
&interpreter
)
1949 : CommandObjectParsed(interpreter
, "thread plan prune",
1950 "Removes any thread plans associated with "
1951 "currently unreported threads. "
1952 "Specify one or more TID's to remove, or if no "
1953 "TID's are provides, remove threads for all "
1954 "unreported threads",
1956 eCommandRequiresProcess
|
1957 eCommandTryTargetAPILock
|
1958 eCommandProcessMustBeLaunched
|
1959 eCommandProcessMustBePaused
) {
1960 AddSimpleArgumentList(eArgTypeThreadID
, eArgRepeatStar
);
1963 ~CommandObjectThreadPlanPrune() override
= default;
1965 void DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
1966 Process
*process
= m_exe_ctx
.GetProcessPtr();
1968 if (args
.GetArgumentCount() == 0) {
1969 process
->PruneThreadPlans();
1970 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1974 const size_t num_args
= args
.GetArgumentCount();
1976 std::lock_guard
<std::recursive_mutex
> guard(
1977 process
->GetThreadList().GetMutex());
1979 for (size_t i
= 0; i
< num_args
; i
++) {
1981 if (!llvm::to_integer(args
.GetArgumentAtIndex(i
), tid
)) {
1982 result
.AppendErrorWithFormat("invalid thread specification: \"%s\"\n",
1983 args
.GetArgumentAtIndex(i
));
1986 if (!process
->PruneThreadPlansForTID(tid
)) {
1987 result
.AppendErrorWithFormat("Could not find unreported tid: \"%s\"\n",
1988 args
.GetArgumentAtIndex(i
));
1992 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1996 // CommandObjectMultiwordThreadPlan
1998 class CommandObjectMultiwordThreadPlan
: public CommandObjectMultiword
{
2000 CommandObjectMultiwordThreadPlan(CommandInterpreter
&interpreter
)
2001 : CommandObjectMultiword(
2002 interpreter
, "plan",
2003 "Commands for managing thread plans that control execution.",
2004 "thread plan <subcommand> [<subcommand objects]") {
2006 "list", CommandObjectSP(new CommandObjectThreadPlanList(interpreter
)));
2009 CommandObjectSP(new CommandObjectThreadPlanDiscard(interpreter
)));
2012 CommandObjectSP(new CommandObjectThreadPlanPrune(interpreter
)));
2015 ~CommandObjectMultiwordThreadPlan() override
= default;
2018 // Next are the subcommands of CommandObjectMultiwordTrace
2020 // CommandObjectTraceExport
2022 class CommandObjectTraceExport
: public CommandObjectMultiword
{
2024 CommandObjectTraceExport(CommandInterpreter
&interpreter
)
2025 : CommandObjectMultiword(
2026 interpreter
, "trace thread export",
2027 "Commands for exporting traces of the threads in the current "
2028 "process to different formats.",
2029 "thread trace export <export-plugin> [<subcommand objects>]") {
2032 for (llvm::StringRef plugin_name
=
2033 PluginManager::GetTraceExporterPluginNameAtIndex(i
);
2034 !plugin_name
.empty();
2035 plugin_name
= PluginManager::GetTraceExporterPluginNameAtIndex(i
++)) {
2036 if (ThreadTraceExportCommandCreator command_creator
=
2037 PluginManager::GetThreadTraceExportCommandCreatorAtIndex(i
)) {
2038 LoadSubCommand(plugin_name
, command_creator(interpreter
));
2044 // CommandObjectTraceStart
2046 class CommandObjectTraceStart
: public CommandObjectTraceProxy
{
2048 CommandObjectTraceStart(CommandInterpreter
&interpreter
)
2049 : CommandObjectTraceProxy(
2050 /*live_debug_session_only=*/true, interpreter
, "thread trace start",
2051 "Start tracing threads with the corresponding trace "
2052 "plug-in for the current process.",
2053 "thread trace start [<trace-options>]") {}
2056 lldb::CommandObjectSP
GetDelegateCommand(Trace
&trace
) override
{
2057 return trace
.GetThreadTraceStartCommand(m_interpreter
);
2061 // CommandObjectTraceStop
2063 class CommandObjectTraceStop
: public CommandObjectMultipleThreads
{
2065 CommandObjectTraceStop(CommandInterpreter
&interpreter
)
2066 : CommandObjectMultipleThreads(
2067 interpreter
, "thread trace stop",
2068 "Stop tracing threads, including the ones traced with the "
2069 "\"process trace start\" command."
2070 "Defaults to the current thread. Thread indices can be "
2071 "specified as arguments.\n Use the thread-index \"all\" to stop "
2073 "for all existing threads.",
2074 "thread trace stop [<thread-index> <thread-index> ...]",
2075 eCommandRequiresProcess
| eCommandTryTargetAPILock
|
2076 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
|
2077 eCommandProcessMustBeTraced
) {}
2079 ~CommandObjectTraceStop() override
= default;
2081 bool DoExecuteOnThreads(Args
&command
, CommandReturnObject
&result
,
2082 llvm::ArrayRef
<lldb::tid_t
> tids
) override
{
2083 ProcessSP process_sp
= m_exe_ctx
.GetProcessSP();
2085 TraceSP trace_sp
= process_sp
->GetTarget().GetTrace();
2087 if (llvm::Error err
= trace_sp
->Stop(tids
))
2088 result
.AppendError(toString(std::move(err
)));
2090 result
.SetStatus(eReturnStatusSuccessFinishResult
);
2092 return result
.Succeeded();
2096 static ThreadSP
GetSingleThreadFromArgs(ExecutionContext
&exe_ctx
, Args
&args
,
2097 CommandReturnObject
&result
) {
2098 if (args
.GetArgumentCount() == 0)
2099 return exe_ctx
.GetThreadSP();
2101 const char *arg
= args
.GetArgumentAtIndex(0);
2102 uint32_t thread_idx
;
2104 if (!llvm::to_integer(arg
, thread_idx
)) {
2105 result
.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", arg
);
2108 ThreadSP thread_sp
=
2109 exe_ctx
.GetProcessRef().GetThreadList().FindThreadByIndexID(thread_idx
);
2111 result
.AppendErrorWithFormat("no thread with index: \"%s\"\n", arg
);
2115 // CommandObjectTraceDumpFunctionCalls
2116 #define LLDB_OPTIONS_thread_trace_dump_function_calls
2117 #include "CommandOptions.inc"
2119 class CommandObjectTraceDumpFunctionCalls
: public CommandObjectParsed
{
2121 class CommandOptions
: public Options
{
2123 CommandOptions() { OptionParsingStarting(nullptr); }
2125 ~CommandOptions() override
= default;
2127 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
2128 ExecutionContext
*execution_context
) override
{
2130 const int short_option
= m_getopt_table
[option_idx
].val
;
2132 switch (short_option
) {
2134 m_dumper_options
.json
= true;
2138 m_dumper_options
.json
= true;
2139 m_dumper_options
.pretty_print_json
= true;
2143 m_output_file
.emplace(option_arg
);
2147 llvm_unreachable("Unimplemented option");
2152 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2153 m_dumper_options
= {};
2154 m_output_file
= std::nullopt
;
2157 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2158 return llvm::ArrayRef(g_thread_trace_dump_function_calls_options
);
2161 static const size_t kDefaultCount
= 20;
2163 // Instance variables to hold the values for command options.
2164 TraceDumperOptions m_dumper_options
;
2165 std::optional
<FileSpec
> m_output_file
;
2168 CommandObjectTraceDumpFunctionCalls(CommandInterpreter
&interpreter
)
2169 : CommandObjectParsed(
2170 interpreter
, "thread trace dump function-calls",
2171 "Dump the traced function-calls for one thread. If no "
2172 "thread is specified, the current thread is used.",
2174 eCommandRequiresProcess
| eCommandRequiresThread
|
2175 eCommandTryTargetAPILock
| eCommandProcessMustBeLaunched
|
2176 eCommandProcessMustBePaused
| eCommandProcessMustBeTraced
) {
2177 AddSimpleArgumentList(eArgTypeThreadIndex
, eArgRepeatOptional
);
2180 ~CommandObjectTraceDumpFunctionCalls() override
= default;
2182 Options
*GetOptions() override
{ return &m_options
; }
2185 void DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
2186 ThreadSP thread_sp
= GetSingleThreadFromArgs(m_exe_ctx
, args
, result
);
2188 result
.AppendError("invalid thread\n");
2192 llvm::Expected
<TraceCursorSP
> cursor_or_error
=
2193 m_exe_ctx
.GetTargetSP()->GetTrace()->CreateNewCursor(*thread_sp
);
2195 if (!cursor_or_error
) {
2196 result
.AppendError(llvm::toString(cursor_or_error
.takeError()));
2199 TraceCursorSP
&cursor_sp
= *cursor_or_error
;
2201 std::optional
<StreamFile
> out_file
;
2202 if (m_options
.m_output_file
) {
2203 out_file
.emplace(m_options
.m_output_file
->GetPath().c_str(),
2204 File::eOpenOptionWriteOnly
| File::eOpenOptionCanCreate
|
2205 File::eOpenOptionTruncate
);
2208 m_options
.m_dumper_options
.forwards
= true;
2210 TraceDumper
dumper(std::move(cursor_sp
),
2211 out_file
? *out_file
: result
.GetOutputStream(),
2212 m_options
.m_dumper_options
);
2214 dumper
.DumpFunctionCalls();
2217 CommandOptions m_options
;
2220 // CommandObjectTraceDumpInstructions
2221 #define LLDB_OPTIONS_thread_trace_dump_instructions
2222 #include "CommandOptions.inc"
2224 class CommandObjectTraceDumpInstructions
: public CommandObjectParsed
{
2226 class CommandOptions
: public Options
{
2228 CommandOptions() { OptionParsingStarting(nullptr); }
2230 ~CommandOptions() override
= default;
2232 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
2233 ExecutionContext
*execution_context
) override
{
2235 const int short_option
= m_getopt_table
[option_idx
].val
;
2237 switch (short_option
) {
2240 if (option_arg
.empty() || option_arg
.getAsInteger(0, count
) ||
2242 error
= Status::FromErrorStringWithFormat(
2243 "invalid integer value for option '%s'",
2244 option_arg
.str().c_str());
2250 m_count
= std::numeric_limits
<decltype(m_count
)>::max();
2255 if (option_arg
.empty() || option_arg
.getAsInteger(0, skip
) || skip
< 0)
2256 error
= Status::FromErrorStringWithFormat(
2257 "invalid integer value for option '%s'",
2258 option_arg
.str().c_str());
2260 m_dumper_options
.skip
= skip
;
2265 if (option_arg
.empty() || option_arg
.getAsInteger(0, id
))
2266 error
= Status::FromErrorStringWithFormat(
2267 "invalid integer value for option '%s'",
2268 option_arg
.str().c_str());
2270 m_dumper_options
.id
= id
;
2274 m_output_file
.emplace(option_arg
);
2278 m_dumper_options
.raw
= true;
2282 m_dumper_options
.forwards
= true;
2286 m_dumper_options
.show_control_flow_kind
= true;
2290 m_dumper_options
.show_timestamps
= true;
2294 m_dumper_options
.show_events
= true;
2298 m_dumper_options
.json
= true;
2302 m_dumper_options
.pretty_print_json
= true;
2303 m_dumper_options
.json
= true;
2307 m_dumper_options
.only_events
= true;
2308 m_dumper_options
.show_events
= true;
2316 llvm_unreachable("Unimplemented option");
2321 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2322 m_count
= kDefaultCount
;
2324 m_output_file
= std::nullopt
;
2325 m_dumper_options
= {};
2328 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2329 return llvm::ArrayRef(g_thread_trace_dump_instructions_options
);
2332 static const size_t kDefaultCount
= 20;
2334 // Instance variables to hold the values for command options.
2337 std::optional
<FileSpec
> m_output_file
;
2338 TraceDumperOptions m_dumper_options
;
2341 CommandObjectTraceDumpInstructions(CommandInterpreter
&interpreter
)
2342 : CommandObjectParsed(
2343 interpreter
, "thread trace dump instructions",
2344 "Dump the traced instructions for one thread. If no "
2345 "thread is specified, show the current thread.",
2347 eCommandRequiresProcess
| eCommandRequiresThread
|
2348 eCommandTryTargetAPILock
| eCommandProcessMustBeLaunched
|
2349 eCommandProcessMustBePaused
| eCommandProcessMustBeTraced
) {
2350 AddSimpleArgumentList(eArgTypeThreadIndex
, eArgRepeatOptional
);
2353 ~CommandObjectTraceDumpInstructions() override
= default;
2355 Options
*GetOptions() override
{ return &m_options
; }
2357 std::optional
<std::string
> GetRepeatCommand(Args
¤t_command_args
,
2358 uint32_t index
) override
{
2360 current_command_args
.GetCommandString(cmd
);
2361 if (cmd
.find(" --continue") == std::string::npos
)
2362 cmd
+= " --continue";
2367 void DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
2368 ThreadSP thread_sp
= GetSingleThreadFromArgs(m_exe_ctx
, args
, result
);
2370 result
.AppendError("invalid thread\n");
2374 if (m_options
.m_continue
&& m_last_id
) {
2375 // We set up the options to continue one instruction past where
2376 // the previous iteration stopped.
2377 m_options
.m_dumper_options
.skip
= 1;
2378 m_options
.m_dumper_options
.id
= m_last_id
;
2381 llvm::Expected
<TraceCursorSP
> cursor_or_error
=
2382 m_exe_ctx
.GetTargetSP()->GetTrace()->CreateNewCursor(*thread_sp
);
2384 if (!cursor_or_error
) {
2385 result
.AppendError(llvm::toString(cursor_or_error
.takeError()));
2388 TraceCursorSP
&cursor_sp
= *cursor_or_error
;
2390 if (m_options
.m_dumper_options
.id
&&
2391 !cursor_sp
->HasId(*m_options
.m_dumper_options
.id
)) {
2392 result
.AppendError("invalid instruction id\n");
2396 std::optional
<StreamFile
> out_file
;
2397 if (m_options
.m_output_file
) {
2398 out_file
.emplace(m_options
.m_output_file
->GetPath().c_str(),
2399 File::eOpenOptionWriteOnly
| File::eOpenOptionCanCreate
|
2400 File::eOpenOptionTruncate
);
2403 if (m_options
.m_continue
&& !m_last_id
) {
2404 // We need to stop processing data when we already ran out of instructions
2405 // in a previous command. We can fake this by setting the cursor past the
2406 // end of the trace.
2407 cursor_sp
->Seek(1, lldb::eTraceCursorSeekTypeEnd
);
2410 TraceDumper
dumper(std::move(cursor_sp
),
2411 out_file
? *out_file
: result
.GetOutputStream(),
2412 m_options
.m_dumper_options
);
2414 m_last_id
= dumper
.DumpInstructions(m_options
.m_count
);
2417 CommandOptions m_options
;
2418 // Last traversed id used to continue a repeat command. std::nullopt means
2419 // that all the trace has been consumed.
2420 std::optional
<lldb::user_id_t
> m_last_id
;
2423 // CommandObjectTraceDumpInfo
2424 #define LLDB_OPTIONS_thread_trace_dump_info
2425 #include "CommandOptions.inc"
2427 class CommandObjectTraceDumpInfo
: public CommandObjectIterateOverThreads
{
2429 class CommandOptions
: public Options
{
2431 CommandOptions() { OptionParsingStarting(nullptr); }
2433 ~CommandOptions() override
= default;
2435 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
2436 ExecutionContext
*execution_context
) override
{
2438 const int short_option
= m_getopt_table
[option_idx
].val
;
2440 switch (short_option
) {
2450 llvm_unreachable("Unimplemented option");
2455 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2460 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2461 return llvm::ArrayRef(g_thread_trace_dump_info_options
);
2464 // Instance variables to hold the values for command options.
2469 CommandObjectTraceDumpInfo(CommandInterpreter
&interpreter
)
2470 : CommandObjectIterateOverThreads(
2471 interpreter
, "thread trace dump info",
2472 "Dump the traced information for one or more threads. If no "
2473 "threads are specified, show the current thread. Use the "
2474 "thread-index \"all\" to see all threads.",
2476 eCommandRequiresProcess
| eCommandTryTargetAPILock
|
2477 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
|
2478 eCommandProcessMustBeTraced
) {}
2480 ~CommandObjectTraceDumpInfo() override
= default;
2482 Options
*GetOptions() override
{ return &m_options
; }
2485 bool HandleOneThread(lldb::tid_t tid
, CommandReturnObject
&result
) override
{
2486 const TraceSP
&trace_sp
= m_exe_ctx
.GetTargetSP()->GetTrace();
2487 ThreadSP thread_sp
=
2488 m_exe_ctx
.GetProcessPtr()->GetThreadList().FindThreadByID(tid
);
2489 trace_sp
->DumpTraceInfo(*thread_sp
, result
.GetOutputStream(),
2490 m_options
.m_verbose
, m_options
.m_json
);
2494 CommandOptions m_options
;
2497 // CommandObjectMultiwordTraceDump
2498 class CommandObjectMultiwordTraceDump
: public CommandObjectMultiword
{
2500 CommandObjectMultiwordTraceDump(CommandInterpreter
&interpreter
)
2501 : CommandObjectMultiword(
2502 interpreter
, "dump",
2503 "Commands for displaying trace information of the threads "
2504 "in the current process.",
2505 "thread trace dump <subcommand> [<subcommand objects>]") {
2508 CommandObjectSP(new CommandObjectTraceDumpInstructions(interpreter
)));
2511 CommandObjectSP(new CommandObjectTraceDumpFunctionCalls(interpreter
)));
2513 "info", CommandObjectSP(new CommandObjectTraceDumpInfo(interpreter
)));
2515 ~CommandObjectMultiwordTraceDump() override
= default;
2518 // CommandObjectMultiwordTrace
2519 class CommandObjectMultiwordTrace
: public CommandObjectMultiword
{
2521 CommandObjectMultiwordTrace(CommandInterpreter
&interpreter
)
2522 : CommandObjectMultiword(
2523 interpreter
, "trace",
2524 "Commands for operating on traces of the threads in the current "
2526 "thread trace <subcommand> [<subcommand objects>]") {
2527 LoadSubCommand("dump", CommandObjectSP(new CommandObjectMultiwordTraceDump(
2529 LoadSubCommand("start",
2530 CommandObjectSP(new CommandObjectTraceStart(interpreter
)));
2531 LoadSubCommand("stop",
2532 CommandObjectSP(new CommandObjectTraceStop(interpreter
)));
2533 LoadSubCommand("export",
2534 CommandObjectSP(new CommandObjectTraceExport(interpreter
)));
2537 ~CommandObjectMultiwordTrace() override
= default;
2540 // CommandObjectMultiwordThread
2542 CommandObjectMultiwordThread::CommandObjectMultiwordThread(
2543 CommandInterpreter
&interpreter
)
2544 : CommandObjectMultiword(interpreter
, "thread",
2545 "Commands for operating on "
2546 "one or more threads in "
2547 "the current process.",
2548 "thread <subcommand> [<subcommand-options>]") {
2549 LoadSubCommand("backtrace", CommandObjectSP(new CommandObjectThreadBacktrace(
2551 LoadSubCommand("continue",
2552 CommandObjectSP(new CommandObjectThreadContinue(interpreter
)));
2553 LoadSubCommand("list",
2554 CommandObjectSP(new CommandObjectThreadList(interpreter
)));
2555 LoadSubCommand("return",
2556 CommandObjectSP(new CommandObjectThreadReturn(interpreter
)));
2557 LoadSubCommand("jump",
2558 CommandObjectSP(new CommandObjectThreadJump(interpreter
)));
2559 LoadSubCommand("select",
2560 CommandObjectSP(new CommandObjectThreadSelect(interpreter
)));
2561 LoadSubCommand("until",
2562 CommandObjectSP(new CommandObjectThreadUntil(interpreter
)));
2563 LoadSubCommand("info",
2564 CommandObjectSP(new CommandObjectThreadInfo(interpreter
)));
2565 LoadSubCommand("exception", CommandObjectSP(new CommandObjectThreadException(
2567 LoadSubCommand("siginfo",
2568 CommandObjectSP(new CommandObjectThreadSiginfo(interpreter
)));
2569 LoadSubCommand("step-in",
2570 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2571 interpreter
, "thread step-in",
2572 "Source level single step, stepping into calls. Defaults "
2573 "to current thread unless specified.",
2574 nullptr, eStepTypeInto
)));
2576 LoadSubCommand("step-out",
2577 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2578 interpreter
, "thread step-out",
2579 "Finish executing the current stack frame and stop after "
2580 "returning. Defaults to current thread unless specified.",
2581 nullptr, eStepTypeOut
)));
2583 LoadSubCommand("step-over",
2584 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2585 interpreter
, "thread step-over",
2586 "Source level single step, stepping over calls. Defaults "
2587 "to current thread unless specified.",
2588 nullptr, eStepTypeOver
)));
2590 LoadSubCommand("step-inst",
2591 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2592 interpreter
, "thread step-inst",
2593 "Instruction level single step, stepping into calls. "
2594 "Defaults to current thread unless specified.",
2595 nullptr, eStepTypeTrace
)));
2597 LoadSubCommand("step-inst-over",
2598 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2599 interpreter
, "thread step-inst-over",
2600 "Instruction level single step, stepping over calls. "
2601 "Defaults to current thread unless specified.",
2602 nullptr, eStepTypeTraceOver
)));
2606 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2607 interpreter
, "thread step-scripted",
2608 "Step as instructed by the script class passed in the -C option. "
2609 "You can also specify a dictionary of key (-k) and value (-v) pairs "
2610 "that will be used to populate an SBStructuredData Dictionary, which "
2611 "will be passed to the constructor of the class implementing the "
2612 "scripted step. See the Python Reference for more details.",
2613 nullptr, eStepTypeScripted
)));
2615 LoadSubCommand("plan", CommandObjectSP(new CommandObjectMultiwordThreadPlan(
2617 LoadSubCommand("trace",
2618 CommandObjectSP(new CommandObjectMultiwordTrace(interpreter
)));
2621 CommandObjectMultiwordThread::~CommandObjectMultiwordThread() = default;