Bug Summary

File:build/source/lldb/source/Commands/CommandObjectThread.cpp
Warning:line 1027, column 20
Value stored to 'start_idx_ptr' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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