Bug Summary

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