1//===-- CommandObjectTarget.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 "CommandObjectTarget.h"
10
11#include "lldb/Core/Address.h"
12#include "lldb/Core/Debugger.h"
13#include "lldb/Core/IOHandler.h"
14#include "lldb/Core/Module.h"
15#include "lldb/Core/ModuleSpec.h"
16#include "lldb/Core/PluginManager.h"
17#include "lldb/Core/Section.h"
18#include "lldb/DataFormatters/ValueObjectPrinter.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/OptionGroupArchitecture.h"
25#include "lldb/Interpreter/OptionGroupBoolean.h"
26#include "lldb/Interpreter/OptionGroupFile.h"
27#include "lldb/Interpreter/OptionGroupFormat.h"
28#include "lldb/Interpreter/OptionGroupPlatform.h"
29#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
30#include "lldb/Interpreter/OptionGroupString.h"
31#include "lldb/Interpreter/OptionGroupUInt64.h"
32#include "lldb/Interpreter/OptionGroupUUID.h"
33#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
34#include "lldb/Interpreter/OptionGroupVariable.h"
35#include "lldb/Interpreter/Options.h"
36#include "lldb/Symbol/CompileUnit.h"
37#include "lldb/Symbol/FuncUnwinders.h"
38#include "lldb/Symbol/LineTable.h"
39#include "lldb/Symbol/ObjectFile.h"
40#include "lldb/Symbol/SymbolFile.h"
41#include "lldb/Symbol/UnwindPlan.h"
42#include "lldb/Symbol/VariableList.h"
43#include "lldb/Target/ABI.h"
44#include "lldb/Target/Process.h"
45#include "lldb/Target/RegisterContext.h"
46#include "lldb/Target/SectionLoadList.h"
47#include "lldb/Target/StackFrame.h"
48#include "lldb/Target/Thread.h"
49#include "lldb/Target/ThreadSpec.h"
50#include "lldb/Utility/Args.h"
51#include "lldb/Utility/ConstString.h"
52#include "lldb/Utility/FileSpec.h"
53#include "lldb/Utility/LLDBLog.h"
54#include "lldb/Utility/State.h"
55#include "lldb/Utility/Stream.h"
56#include "lldb/Utility/StructuredData.h"
57#include "lldb/Utility/Timer.h"
58#include "lldb/ValueObject/ValueObjectVariable.h"
59#include "lldb/lldb-enumerations.h"
60#include "lldb/lldb-forward.h"
61#include "lldb/lldb-private-enumerations.h"
62
63#include "clang/Frontend/CompilerInstance.h"
64#include "clang/Frontend/CompilerInvocation.h"
65#include "clang/Frontend/FrontendActions.h"
66#include "clang/Serialization/ObjectFilePCHContainerReader.h"
67#include "llvm/ADT/ScopeExit.h"
68#include "llvm/ADT/StringRef.h"
69#include "llvm/Support/FileSystem.h"
70#include "llvm/Support/FormatAdapters.h"
71
72
73using namespace lldb;
74using namespace lldb_private;
75
76static void DumpTargetInfo(uint32_t target_idx, Target *target,
77 const char *prefix_cstr,
78 bool show_stopped_process_status, Stream &strm) {
79 const ArchSpec &target_arch = target->GetArchitecture();
80
81 Module *exe_module = target->GetExecutableModulePointer();
82 char exe_path[PATH_MAX];
83 bool exe_valid = false;
84 if (exe_module)
85 exe_valid = exe_module->GetFileSpec().GetPath(path: exe_path, max_path_length: sizeof(exe_path));
86
87 if (!exe_valid)
88 ::strcpy(dest: exe_path, src: "<none>");
89
90 std::string formatted_label = "";
91 const std::string &label = target->GetLabel();
92 if (!label.empty()) {
93 formatted_label = " (" + label + ")";
94 }
95
96 strm.Printf(format: "%starget #%u%s: %s", prefix_cstr ? prefix_cstr : "", target_idx,
97 formatted_label.data(), exe_path);
98
99 uint32_t properties = 0;
100 if (target_arch.IsValid()) {
101 strm.Printf(format: " ( arch=");
102 target_arch.DumpTriple(s&: strm.AsRawOstream());
103 properties++;
104 }
105 PlatformSP platform_sp(target->GetPlatform());
106 if (platform_sp)
107 strm.Format(format: "{0}platform={1}", args: properties++ > 0 ? ", " : " ( ",
108 args: platform_sp->GetName());
109
110 ProcessSP process_sp(target->GetProcessSP());
111 bool show_process_status = false;
112 if (process_sp) {
113 lldb::pid_t pid = process_sp->GetID();
114 StateType state = process_sp->GetState();
115 if (show_stopped_process_status)
116 show_process_status = StateIsStoppedState(state, must_exist: true);
117 const char *state_cstr = StateAsCString(state);
118 if (pid != LLDB_INVALID_PROCESS_ID)
119 strm.Printf(format: "%spid=%" PRIu64, properties++ > 0 ? ", " : " ( ", pid);
120 strm.Printf(format: "%sstate=%s", properties++ > 0 ? ", " : " ( ", state_cstr);
121 }
122 if (properties > 0)
123 strm.PutCString(cstr: " )\n");
124 else
125 strm.EOL();
126 if (show_process_status) {
127 const bool only_threads_with_stop_reason = true;
128 const uint32_t start_frame = 0;
129 const uint32_t num_frames = 1;
130 const uint32_t num_frames_with_source = 1;
131 const bool stop_format = false;
132 process_sp->GetStatus(ostrm&: strm);
133 process_sp->GetThreadStatus(ostrm&: strm, only_threads_with_stop_reason,
134 start_frame, num_frames, num_frames_with_source,
135 stop_format);
136 }
137}
138
139static uint32_t DumpTargetList(TargetList &target_list,
140 bool show_stopped_process_status, Stream &strm) {
141 const uint32_t num_targets = target_list.GetNumTargets();
142 if (num_targets) {
143 TargetSP selected_target_sp(target_list.GetSelectedTarget());
144 strm.PutCString(cstr: "Current targets:\n");
145 for (uint32_t i = 0; i < num_targets; ++i) {
146 TargetSP target_sp(target_list.GetTargetAtIndex(index: i));
147 if (target_sp) {
148 bool is_selected = target_sp.get() == selected_target_sp.get();
149 DumpTargetInfo(target_idx: i, target: target_sp.get(), prefix_cstr: is_selected ? "* " : " ",
150 show_stopped_process_status, strm);
151 }
152 }
153 }
154 return num_targets;
155}
156
157#define LLDB_OPTIONS_target_dependents
158#include "CommandOptions.inc"
159
160class OptionGroupDependents : public OptionGroup {
161public:
162 OptionGroupDependents() = default;
163
164 ~OptionGroupDependents() override = default;
165
166 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
167 return llvm::ArrayRef(g_target_dependents_options);
168 }
169
170 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
171 ExecutionContext *execution_context) override {
172 Status error;
173
174 // For compatibility no value means don't load dependents.
175 if (option_value.empty()) {
176 m_load_dependent_files = eLoadDependentsNo;
177 return error;
178 }
179
180 const char short_option =
181 g_target_dependents_options[option_idx].short_option;
182 if (short_option == 'd') {
183 LoadDependentFiles tmp_load_dependents;
184 tmp_load_dependents = (LoadDependentFiles)OptionArgParser::ToOptionEnum(
185 s: option_value, enum_values: g_target_dependents_options[option_idx].enum_values, fail_value: 0,
186 error);
187 if (error.Success())
188 m_load_dependent_files = tmp_load_dependents;
189 } else {
190 error = Status::FromErrorStringWithFormat(
191 format: "unrecognized short option '%c'", short_option);
192 }
193
194 return error;
195 }
196
197 Status SetOptionValue(uint32_t, const char *, ExecutionContext *) = delete;
198
199 void OptionParsingStarting(ExecutionContext *execution_context) override {
200 m_load_dependent_files = eLoadDependentsDefault;
201 }
202
203 LoadDependentFiles m_load_dependent_files;
204
205private:
206 OptionGroupDependents(const OptionGroupDependents &) = delete;
207 const OptionGroupDependents &
208 operator=(const OptionGroupDependents &) = delete;
209};
210
211#pragma mark CommandObjectTargetCreate
212
213class CommandObjectTargetCreate : public CommandObjectParsed {
214public:
215 CommandObjectTargetCreate(CommandInterpreter &interpreter)
216 : CommandObjectParsed(
217 interpreter, "target create",
218 "Create a target using the argument as the main executable.",
219 nullptr),
220 m_platform_options(true), // Include the --platform option.
221 m_core_file(LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename,
222 "Fullpath to a core file to use for this target."),
223 m_label(LLDB_OPT_SET_1, false, "label", 'l', 0, eArgTypeName,
224 "Optional name for this target.", nullptr),
225 m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
226 eArgTypeFilename,
227 "Fullpath to a stand alone debug "
228 "symbols file for when debug symbols "
229 "are not in the executable."),
230 m_remote_file(
231 LLDB_OPT_SET_1, false, "remote-file", 'r', 0, eArgTypeFilename,
232 "Fullpath to the file on the remote host if debugging remotely.") {
233
234 AddSimpleArgumentList(arg_type: eArgTypeFilename);
235
236 m_option_group.Append(group: &m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
237 m_option_group.Append(group: &m_platform_options, LLDB_OPT_SET_ALL, dst_mask: 1);
238 m_option_group.Append(group: &m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
239 m_option_group.Append(group: &m_label, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
240 m_option_group.Append(group: &m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
241 m_option_group.Append(group: &m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
242 m_option_group.Append(group: &m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
243 m_option_group.Finalize();
244 }
245
246 ~CommandObjectTargetCreate() override = default;
247
248 Options *GetOptions() override { return &m_option_group; }
249
250protected:
251 void DoExecute(Args &command, CommandReturnObject &result) override {
252 const size_t argc = command.GetArgumentCount();
253 FileSpec core_file(m_core_file.GetOptionValue().GetCurrentValue());
254 FileSpec remote_file(m_remote_file.GetOptionValue().GetCurrentValue());
255
256 if (core_file) {
257 auto file = FileSystem::Instance().Open(
258 file_spec: core_file, options: lldb_private::File::eOpenOptionReadOnly);
259
260 if (!file) {
261 result.AppendErrorWithFormatv(format: "Cannot open '{0}': {1}.",
262 args: core_file.GetPath(),
263 args: llvm::toString(E: file.takeError()));
264 return;
265 }
266 }
267
268 if (argc == 1 || core_file || remote_file) {
269 FileSpec symfile(m_symbol_file.GetOptionValue().GetCurrentValue());
270 if (symfile) {
271 auto file = FileSystem::Instance().Open(
272 file_spec: symfile, options: lldb_private::File::eOpenOptionReadOnly);
273
274 if (!file) {
275 result.AppendErrorWithFormatv(format: "Cannot open '{0}': {1}.",
276 args: symfile.GetPath(),
277 args: llvm::toString(E: file.takeError()));
278 return;
279 }
280 }
281
282 const char *file_path = command.GetArgumentAtIndex(idx: 0);
283 LLDB_SCOPED_TIMERF("(lldb) target create '%s'", file_path);
284
285 bool must_set_platform_path = false;
286
287 Debugger &debugger = GetDebugger();
288
289 TargetSP target_sp;
290 llvm::StringRef arch_cstr = m_arch_option.GetArchitectureName();
291 Status error(debugger.GetTargetList().CreateTarget(
292 debugger, user_exe_path: file_path, triple_str: arch_cstr,
293 get_dependent_modules: m_add_dependents.m_load_dependent_files, platform_options: &m_platform_options,
294 target_sp));
295
296 if (!target_sp) {
297 result.AppendError(in_string: error.AsCString());
298 return;
299 }
300
301 const llvm::StringRef label =
302 m_label.GetOptionValue().GetCurrentValueAsRef();
303 if (!label.empty()) {
304 if (auto E = target_sp->SetLabel(label))
305 result.SetError(std::move(E));
306 return;
307 }
308
309 auto on_error = llvm::make_scope_exit(
310 F: [&target_list = debugger.GetTargetList(), &target_sp]() {
311 target_list.DeleteTarget(target_sp);
312 });
313
314 // Only get the platform after we create the target because we might
315 // have switched platforms depending on what the arguments were to
316 // CreateTarget() we can't rely on the selected platform.
317
318 PlatformSP platform_sp = target_sp->GetPlatform();
319
320 FileSpec file_spec;
321 if (file_path) {
322 file_spec.SetFile(path: file_path, style: FileSpec::Style::native);
323 FileSystem::Instance().Resolve(file_spec);
324
325 // Try to resolve the exe based on PATH and/or platform-specific
326 // suffixes, but only if using the host platform.
327 if (platform_sp && platform_sp->IsHost() &&
328 !FileSystem::Instance().Exists(file_spec))
329 FileSystem::Instance().ResolveExecutableLocation(file_spec);
330 }
331
332 if (remote_file) {
333 if (platform_sp) {
334 // I have a remote file.. two possible cases
335 if (file_spec && FileSystem::Instance().Exists(file_spec)) {
336 // if the remote file does not exist, push it there
337 if (!platform_sp->GetFileExists(file_spec: remote_file)) {
338 Status err = platform_sp->PutFile(source: file_spec, destination: remote_file);
339 if (err.Fail()) {
340 result.AppendError(in_string: err.AsCString());
341 return;
342 }
343 }
344 } else {
345 // there is no local file and we need one
346 // in order to make the remote ---> local transfer we need a
347 // platform
348 // TODO: if the user has passed in a --platform argument, use it
349 // to fetch the right platform
350 if (file_path) {
351 // copy the remote file to the local file
352 Status err = platform_sp->GetFile(source: remote_file, destination: file_spec);
353 if (err.Fail()) {
354 result.AppendError(in_string: err.AsCString());
355 return;
356 }
357 } else {
358 // If the remote file exists, we can debug reading that out of
359 // memory. If the platform is already connected to an lldb-server
360 // then we can at least check the file exists remotely. Otherwise
361 // we'll just have to trust that it will be there when we do
362 // process connect.
363 // I don't do this for the host platform because it seems odd to
364 // support supplying a remote file but no local file for a local
365 // debug session.
366 if (platform_sp->IsHost()) {
367 result.AppendError(in_string: "Supply a local file, not a remote file, "
368 "when debugging on the host.");
369 return;
370 }
371 if (platform_sp->IsConnected() && !platform_sp->GetFileExists(file_spec: remote_file)) {
372 result.AppendError(in_string: "remote --> local transfer without local "
373 "path is not implemented yet");
374 return;
375 }
376 // Since there's only a remote file, we need to set the executable
377 // file spec to the remote one.
378 ProcessLaunchInfo launch_info = target_sp->GetProcessLaunchInfo();
379 launch_info.SetExecutableFile(exe_file: FileSpec(remote_file), add_exe_file_as_first_arg: true);
380 target_sp->SetProcessLaunchInfo(launch_info);
381 }
382 }
383 } else {
384 result.AppendError(in_string: "no platform found for target");
385 return;
386 }
387 }
388
389 if (symfile || remote_file) {
390 ModuleSP module_sp(target_sp->GetExecutableModule());
391 if (module_sp) {
392 if (symfile)
393 module_sp->SetSymbolFileFileSpec(symfile);
394 if (remote_file) {
395 std::string remote_path = remote_file.GetPath();
396 target_sp->SetArg0(remote_path.c_str());
397 module_sp->SetPlatformFileSpec(remote_file);
398 }
399 }
400 }
401
402 if (must_set_platform_path) {
403 ModuleSpec main_module_spec(file_spec);
404 ModuleSP module_sp =
405 target_sp->GetOrCreateModule(module_spec: main_module_spec, notify: true /* notify */);
406 if (module_sp)
407 module_sp->SetPlatformFileSpec(remote_file);
408 }
409
410 if (core_file) {
411 FileSpec core_file_dir;
412 core_file_dir.SetDirectory(core_file.GetDirectory());
413 target_sp->AppendExecutableSearchPaths(core_file_dir);
414
415 ProcessSP process_sp(target_sp->CreateProcess(
416 listener_sp: GetDebugger().GetListener(), plugin_name: llvm::StringRef(), crash_file: &core_file, can_connect: false));
417
418 if (process_sp) {
419 // Seems weird that we Launch a core file, but that is what we
420 // do!
421 error = process_sp->LoadCore();
422
423 if (error.Fail()) {
424 result.AppendError(in_string: error.AsCString(default_error_str: "unknown core file format"));
425 return;
426 } else {
427 result.AppendMessageWithFormatv(
428 format: "Core file '{0}' ({1}) was loaded.\n", args: core_file.GetPath(),
429 args: target_sp->GetArchitecture().GetArchitectureName());
430 result.SetStatus(eReturnStatusSuccessFinishNoResult);
431 on_error.release();
432 }
433 } else {
434 result.AppendErrorWithFormatv(format: "Unknown core file format '{0}'\n",
435 args: core_file.GetPath());
436 }
437 } else {
438 result.AppendMessageWithFormat(
439 format: "Current executable set to '%s' (%s).\n",
440 file_spec.GetPath().c_str(),
441 target_sp->GetArchitecture().GetArchitectureName());
442 result.SetStatus(eReturnStatusSuccessFinishNoResult);
443 on_error.release();
444 }
445 } else {
446 result.AppendErrorWithFormat(format: "'%s' takes exactly one executable path "
447 "argument, or use the --core option.\n",
448 m_cmd_name.c_str());
449 }
450 }
451
452private:
453 OptionGroupOptions m_option_group;
454 OptionGroupArchitecture m_arch_option;
455 OptionGroupPlatform m_platform_options;
456 OptionGroupFile m_core_file;
457 OptionGroupString m_label;
458 OptionGroupFile m_symbol_file;
459 OptionGroupFile m_remote_file;
460 OptionGroupDependents m_add_dependents;
461};
462
463#pragma mark CommandObjectTargetList
464
465class CommandObjectTargetList : public CommandObjectParsed {
466public:
467 CommandObjectTargetList(CommandInterpreter &interpreter)
468 : CommandObjectParsed(
469 interpreter, "target list",
470 "List all current targets in the current debug session.", nullptr) {
471 }
472
473 ~CommandObjectTargetList() override = default;
474
475protected:
476 void DoExecute(Args &args, CommandReturnObject &result) override {
477 Stream &strm = result.GetOutputStream();
478
479 bool show_stopped_process_status = false;
480 if (DumpTargetList(target_list&: GetDebugger().GetTargetList(),
481 show_stopped_process_status, strm) == 0) {
482 strm.PutCString(cstr: "No targets.\n");
483 }
484 result.SetStatus(eReturnStatusSuccessFinishResult);
485 }
486};
487
488#pragma mark CommandObjectTargetSelect
489
490class CommandObjectTargetSelect : public CommandObjectParsed {
491public:
492 CommandObjectTargetSelect(CommandInterpreter &interpreter)
493 : CommandObjectParsed(
494 interpreter, "target select",
495 "Select a target as the current target by target index.", nullptr) {
496 AddSimpleArgumentList(arg_type: eArgTypeTargetID);
497 }
498
499 ~CommandObjectTargetSelect() override = default;
500
501protected:
502 void DoExecute(Args &args, CommandReturnObject &result) override {
503 if (args.GetArgumentCount() == 1) {
504 const char *target_identifier = args.GetArgumentAtIndex(idx: 0);
505 uint32_t target_idx = LLDB_INVALID_INDEX32;
506 TargetList &target_list = GetDebugger().GetTargetList();
507 const uint32_t num_targets = target_list.GetNumTargets();
508 if (llvm::to_integer(S: target_identifier, Num&: target_idx)) {
509 if (target_idx < num_targets) {
510 target_list.SetSelectedTarget(target_idx);
511 Stream &strm = result.GetOutputStream();
512 bool show_stopped_process_status = false;
513 DumpTargetList(target_list, show_stopped_process_status, strm);
514 result.SetStatus(eReturnStatusSuccessFinishResult);
515 } else {
516 if (num_targets > 0) {
517 result.AppendErrorWithFormat(
518 format: "index %u is out of range, valid target indexes are 0 - %u\n",
519 target_idx, num_targets - 1);
520 } else {
521 result.AppendErrorWithFormat(
522 format: "index %u is out of range since there are no active targets\n",
523 target_idx);
524 }
525 }
526 } else {
527 for (size_t i = 0; i < num_targets; i++) {
528 if (TargetSP target_sp = target_list.GetTargetAtIndex(index: i)) {
529 const std::string &label = target_sp->GetLabel();
530 if (!label.empty() && label == target_identifier) {
531 target_idx = i;
532 break;
533 }
534 }
535 }
536
537 if (target_idx != LLDB_INVALID_INDEX32) {
538 target_list.SetSelectedTarget(target_idx);
539 Stream &strm = result.GetOutputStream();
540 bool show_stopped_process_status = false;
541 DumpTargetList(target_list, show_stopped_process_status, strm);
542 result.SetStatus(eReturnStatusSuccessFinishResult);
543 } else {
544 result.AppendErrorWithFormat(format: "invalid index string value '%s'\n",
545 target_identifier);
546 }
547 }
548 } else {
549 result.AppendError(
550 in_string: "'target select' takes a single argument: a target index\n");
551 }
552 }
553};
554
555#pragma mark CommandObjectTargetDelete
556
557class CommandObjectTargetDelete : public CommandObjectParsed {
558public:
559 CommandObjectTargetDelete(CommandInterpreter &interpreter)
560 : CommandObjectParsed(interpreter, "target delete",
561 "Delete one or more targets by target index.",
562 nullptr),
563 m_all_option(LLDB_OPT_SET_1, false, "all", 'a', "Delete all targets.",
564 false, true),
565 m_cleanup_option(
566 LLDB_OPT_SET_1, false, "clean", 'c',
567 "Perform extra cleanup to minimize memory consumption after "
568 "deleting the target. "
569 "By default, LLDB will keep in memory any modules previously "
570 "loaded by the target as well "
571 "as all of its debug info. Specifying --clean will unload all of "
572 "these shared modules and "
573 "cause them to be reparsed again the next time the target is run",
574 false, true) {
575 m_option_group.Append(group: &m_all_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
576 m_option_group.Append(group: &m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
577 m_option_group.Finalize();
578 AddSimpleArgumentList(arg_type: eArgTypeTargetID, repetition_type: eArgRepeatStar);
579 }
580
581 ~CommandObjectTargetDelete() override = default;
582
583 Options *GetOptions() override { return &m_option_group; }
584
585protected:
586 void DoExecute(Args &args, CommandReturnObject &result) override {
587 const size_t argc = args.GetArgumentCount();
588 std::vector<TargetSP> delete_target_list;
589 TargetList &target_list = GetDebugger().GetTargetList();
590 TargetSP target_sp;
591
592 if (m_all_option.GetOptionValue()) {
593 for (size_t i = 0; i < target_list.GetNumTargets(); ++i)
594 delete_target_list.push_back(x: target_list.GetTargetAtIndex(index: i));
595 } else if (argc > 0) {
596 const uint32_t num_targets = target_list.GetNumTargets();
597 // Bail out if don't have any targets.
598 if (num_targets == 0) {
599 result.AppendError(in_string: "no targets to delete");
600 return;
601 }
602
603 for (auto &entry : args.entries()) {
604 uint32_t target_idx;
605 if (entry.ref().getAsInteger(Radix: 0, Result&: target_idx)) {
606 result.AppendErrorWithFormat(format: "invalid target index '%s'\n",
607 entry.c_str());
608 return;
609 }
610 if (target_idx < num_targets) {
611 target_sp = target_list.GetTargetAtIndex(index: target_idx);
612 if (target_sp) {
613 delete_target_list.push_back(x: target_sp);
614 continue;
615 }
616 }
617 if (num_targets > 1)
618 result.AppendErrorWithFormat(format: "target index %u is out of range, valid "
619 "target indexes are 0 - %u\n",
620 target_idx, num_targets - 1);
621 else
622 result.AppendErrorWithFormat(
623 format: "target index %u is out of range, the only valid index is 0\n",
624 target_idx);
625
626 return;
627 }
628 } else {
629 target_sp = target_list.GetSelectedTarget();
630 if (!target_sp) {
631 result.AppendErrorWithFormat(format: "no target is currently selected\n");
632 return;
633 }
634 delete_target_list.push_back(x: target_sp);
635 }
636
637 const size_t num_targets_to_delete = delete_target_list.size();
638 for (size_t idx = 0; idx < num_targets_to_delete; ++idx) {
639 target_sp = delete_target_list[idx];
640 target_list.DeleteTarget(target_sp);
641 target_sp->Destroy();
642 }
643 // If "--clean" was specified, prune any orphaned shared modules from the
644 // global shared module list
645 if (m_cleanup_option.GetOptionValue()) {
646 const bool mandatory = true;
647 ModuleList::RemoveOrphanSharedModules(mandatory);
648 }
649 result.GetOutputStream().Printf(format: "%u targets deleted.\n",
650 (uint32_t)num_targets_to_delete);
651 result.SetStatus(eReturnStatusSuccessFinishResult);
652 }
653
654 OptionGroupOptions m_option_group;
655 OptionGroupBoolean m_all_option;
656 OptionGroupBoolean m_cleanup_option;
657};
658
659class CommandObjectTargetShowLaunchEnvironment : public CommandObjectParsed {
660public:
661 CommandObjectTargetShowLaunchEnvironment(CommandInterpreter &interpreter)
662 : CommandObjectParsed(
663 interpreter, "target show-launch-environment",
664 "Shows the environment being passed to the process when launched, "
665 "taking info account 3 settings: target.env-vars, "
666 "target.inherit-env and target.unset-env-vars.",
667 nullptr, eCommandRequiresTarget) {}
668
669 ~CommandObjectTargetShowLaunchEnvironment() override = default;
670
671protected:
672 void DoExecute(Args &args, CommandReturnObject &result) override {
673 Target *target = m_exe_ctx.GetTargetPtr();
674 Environment env = target->GetEnvironment();
675
676 std::vector<Environment::value_type *> env_vector;
677 env_vector.reserve(n: env.size());
678 for (auto &KV : env)
679 env_vector.push_back(x: &KV);
680 std::sort(first: env_vector.begin(), last: env_vector.end(),
681 comp: [](Environment::value_type *a, Environment::value_type *b) {
682 return a->first() < b->first();
683 });
684
685 auto &strm = result.GetOutputStream();
686 for (auto &KV : env_vector)
687 strm.Format(format: "{0}={1}\n", args: KV->first(), args&: KV->second);
688
689 result.SetStatus(eReturnStatusSuccessFinishResult);
690 }
691};
692
693#pragma mark CommandObjectTargetVariable
694
695class CommandObjectTargetVariable : public CommandObjectParsed {
696 static const uint32_t SHORT_OPTION_FILE = 0x66696c65; // 'file'
697 static const uint32_t SHORT_OPTION_SHLB = 0x73686c62; // 'shlb'
698
699public:
700 CommandObjectTargetVariable(CommandInterpreter &interpreter)
701 : CommandObjectParsed(interpreter, "target variable",
702 "Read global variables for the current target, "
703 "before or while running a process.",
704 nullptr, eCommandRequiresTarget),
705 m_option_variable(false), // Don't include frame options
706 m_option_format(eFormatDefault),
707 m_option_compile_units(LLDB_OPT_SET_1, false, "file", SHORT_OPTION_FILE,
708 0, eArgTypeFilename,
709 "A basename or fullpath to a file that contains "
710 "global variables. This option can be "
711 "specified multiple times."),
712 m_option_shared_libraries(
713 LLDB_OPT_SET_1, false, "shlib", SHORT_OPTION_SHLB, 0,
714 eArgTypeFilename,
715 "A basename or fullpath to a shared library to use in the search "
716 "for global "
717 "variables. This option can be specified multiple times.") {
718 AddSimpleArgumentList(arg_type: eArgTypeVarName, repetition_type: eArgRepeatPlus);
719
720 m_option_group.Append(group: &m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
721 m_option_group.Append(group: &m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
722 m_option_group.Append(group: &m_option_format,
723 src_mask: OptionGroupFormat::OPTION_GROUP_FORMAT |
724 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
725 LLDB_OPT_SET_1);
726 m_option_group.Append(group: &m_option_compile_units, LLDB_OPT_SET_ALL,
727 LLDB_OPT_SET_1);
728 m_option_group.Append(group: &m_option_shared_libraries, LLDB_OPT_SET_ALL,
729 LLDB_OPT_SET_1);
730 m_option_group.Finalize();
731 }
732
733 ~CommandObjectTargetVariable() override = default;
734
735 void DumpValueObject(Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp,
736 const char *root_name) {
737 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions());
738
739 if (!valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() &&
740 valobj_sp->IsRuntimeSupportValue())
741 return;
742
743 switch (var_sp->GetScope()) {
744 case eValueTypeVariableGlobal:
745 if (m_option_variable.show_scope)
746 s.PutCString(cstr: "GLOBAL: ");
747 break;
748
749 case eValueTypeVariableStatic:
750 if (m_option_variable.show_scope)
751 s.PutCString(cstr: "STATIC: ");
752 break;
753
754 case eValueTypeVariableArgument:
755 if (m_option_variable.show_scope)
756 s.PutCString(cstr: " ARG: ");
757 break;
758
759 case eValueTypeVariableLocal:
760 if (m_option_variable.show_scope)
761 s.PutCString(cstr: " LOCAL: ");
762 break;
763
764 case eValueTypeVariableThreadLocal:
765 if (m_option_variable.show_scope)
766 s.PutCString(cstr: "THREAD: ");
767 break;
768
769 default:
770 break;
771 }
772
773 if (m_option_variable.show_decl) {
774 bool show_fullpaths = false;
775 bool show_module = true;
776 if (var_sp->DumpDeclaration(s: &s, show_fullpaths, show_module))
777 s.PutCString(cstr: ": ");
778 }
779
780 const Format format = m_option_format.GetFormat();
781 if (format != eFormatDefault)
782 options.SetFormat(format);
783
784 options.SetRootValueObjectName(root_name);
785
786 if (llvm::Error error = valobj_sp->Dump(s, options))
787 s << "error: " << toString(E: std::move(error));
788 }
789
790 static size_t GetVariableCallback(void *baton, const char *name,
791 VariableList &variable_list) {
792 size_t old_size = variable_list.GetSize();
793 Target *target = static_cast<Target *>(baton);
794 if (target)
795 target->GetImages().FindGlobalVariables(name: ConstString(name), UINT32_MAX,
796 variable_list);
797 return variable_list.GetSize() - old_size;
798 }
799
800 Options *GetOptions() override { return &m_option_group; }
801
802protected:
803 void DumpGlobalVariableList(const ExecutionContext &exe_ctx,
804 const SymbolContext &sc,
805 const VariableList &variable_list,
806 CommandReturnObject &result) {
807 Stream &s = result.GetOutputStream();
808 if (variable_list.Empty())
809 return;
810 if (sc.module_sp) {
811 if (sc.comp_unit) {
812 s.Format(format: "Global variables for {0} in {1}:\n",
813 args: sc.comp_unit->GetPrimaryFile(), args: sc.module_sp->GetFileSpec());
814 } else {
815 s.Printf(format: "Global variables for %s\n",
816 sc.module_sp->GetFileSpec().GetPath().c_str());
817 }
818 } else if (sc.comp_unit) {
819 s.Format(format: "Global variables for {0}\n", args: sc.comp_unit->GetPrimaryFile());
820 }
821
822 for (VariableSP var_sp : variable_list) {
823 if (!var_sp)
824 continue;
825 ValueObjectSP valobj_sp(ValueObjectVariable::Create(
826 exe_scope: exe_ctx.GetBestExecutionContextScope(), var_sp));
827
828 if (valobj_sp) {
829 result.GetValueObjectList().Append(val_obj_sp: valobj_sp);
830 DumpValueObject(s, var_sp, valobj_sp, root_name: var_sp->GetName().GetCString());
831 }
832 }
833 }
834
835 void DoExecute(Args &args, CommandReturnObject &result) override {
836 Target *target = m_exe_ctx.GetTargetPtr();
837 const size_t argc = args.GetArgumentCount();
838
839 if (argc > 0) {
840 for (const Args::ArgEntry &arg : args) {
841 VariableList variable_list;
842 ValueObjectList valobj_list;
843
844 size_t matches = 0;
845 bool use_var_name = false;
846 if (m_option_variable.use_regex) {
847 RegularExpression regex(arg.ref());
848 if (!regex.IsValid()) {
849 result.GetErrorStream().Printf(
850 format: "error: invalid regular expression: '%s'\n", arg.c_str());
851 return;
852 }
853 use_var_name = true;
854 target->GetImages().FindGlobalVariables(regex, UINT32_MAX,
855 variable_list);
856 matches = variable_list.GetSize();
857 } else {
858 Status error(Variable::GetValuesForVariableExpressionPath(
859 variable_expr_path: arg.c_str(), scope: m_exe_ctx.GetBestExecutionContextScope(),
860 callback: GetVariableCallback, baton: target, variable_list, valobj_list));
861 matches = variable_list.GetSize();
862 }
863
864 if (matches == 0) {
865 result.AppendErrorWithFormat(format: "can't find global variable '%s'",
866 arg.c_str());
867 return;
868 } else {
869 for (uint32_t global_idx = 0; global_idx < matches; ++global_idx) {
870 VariableSP var_sp(variable_list.GetVariableAtIndex(idx: global_idx));
871 if (var_sp) {
872 ValueObjectSP valobj_sp(
873 valobj_list.GetValueObjectAtIndex(idx: global_idx));
874 if (!valobj_sp)
875 valobj_sp = ValueObjectVariable::Create(
876 exe_scope: m_exe_ctx.GetBestExecutionContextScope(), var_sp);
877
878 if (valobj_sp)
879 DumpValueObject(s&: result.GetOutputStream(), var_sp, valobj_sp,
880 root_name: use_var_name ? var_sp->GetName().GetCString()
881 : arg.c_str());
882 }
883 }
884 }
885 }
886 } else {
887 const FileSpecList &compile_units =
888 m_option_compile_units.GetOptionValue().GetCurrentValue();
889 const FileSpecList &shlibs =
890 m_option_shared_libraries.GetOptionValue().GetCurrentValue();
891 SymbolContextList sc_list;
892 const size_t num_compile_units = compile_units.GetSize();
893 const size_t num_shlibs = shlibs.GetSize();
894 if (num_compile_units == 0 && num_shlibs == 0) {
895 bool success = false;
896 StackFrame *frame = m_exe_ctx.GetFramePtr();
897 CompileUnit *comp_unit = nullptr;
898 if (frame) {
899 SymbolContext sc = frame->GetSymbolContext(resolve_scope: eSymbolContextCompUnit);
900 comp_unit = sc.comp_unit;
901 if (sc.comp_unit) {
902 const bool can_create = true;
903 VariableListSP comp_unit_varlist_sp(
904 sc.comp_unit->GetVariableList(can_create));
905 if (comp_unit_varlist_sp) {
906 size_t count = comp_unit_varlist_sp->GetSize();
907 if (count > 0) {
908 DumpGlobalVariableList(exe_ctx: m_exe_ctx, sc, variable_list: *comp_unit_varlist_sp,
909 result);
910 success = true;
911 }
912 }
913 }
914 }
915 if (!success) {
916 if (frame) {
917 if (comp_unit)
918 result.AppendErrorWithFormatv(
919 format: "no global variables in current compile unit: {0}\n",
920 args: comp_unit->GetPrimaryFile());
921 else
922 result.AppendErrorWithFormat(
923 format: "no debug information for frame %u\n",
924 frame->GetFrameIndex());
925 } else
926 result.AppendError(in_string: "'target variable' takes one or more global "
927 "variable names as arguments\n");
928 }
929 } else {
930 SymbolContextList sc_list;
931 // We have one or more compile unit or shlib
932 if (num_shlibs > 0) {
933 for (size_t shlib_idx = 0; shlib_idx < num_shlibs; ++shlib_idx) {
934 const FileSpec module_file(shlibs.GetFileSpecAtIndex(idx: shlib_idx));
935 ModuleSpec module_spec(module_file);
936
937 ModuleSP module_sp(
938 target->GetImages().FindFirstModule(module_spec));
939 if (module_sp) {
940 if (num_compile_units > 0) {
941 for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
942 module_sp->FindCompileUnits(
943 path: compile_units.GetFileSpecAtIndex(idx: cu_idx), sc_list);
944 } else {
945 SymbolContext sc;
946 sc.module_sp = module_sp;
947 sc_list.Append(sc);
948 }
949 } else {
950 // Didn't find matching shlib/module in target...
951 result.AppendErrorWithFormat(
952 format: "target doesn't contain the specified shared library: %s\n",
953 module_file.GetPath().c_str());
954 }
955 }
956 } else {
957 // No shared libraries, we just want to find globals for the compile
958 // units files that were specified
959 for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
960 target->GetImages().FindCompileUnits(
961 path: compile_units.GetFileSpecAtIndex(idx: cu_idx), sc_list);
962 }
963
964 for (const SymbolContext &sc : sc_list) {
965 if (sc.comp_unit) {
966 const bool can_create = true;
967 VariableListSP comp_unit_varlist_sp(
968 sc.comp_unit->GetVariableList(can_create));
969 if (comp_unit_varlist_sp)
970 DumpGlobalVariableList(exe_ctx: m_exe_ctx, sc, variable_list: *comp_unit_varlist_sp,
971 result);
972 } else if (sc.module_sp) {
973 // Get all global variables for this module
974 lldb_private::RegularExpression all_globals_regex(
975 llvm::StringRef(".")); // Any global with at least one character
976 VariableList variable_list;
977 sc.module_sp->FindGlobalVariables(regex: all_globals_regex, UINT32_MAX,
978 variable_list);
979 DumpGlobalVariableList(exe_ctx: m_exe_ctx, sc, variable_list, result);
980 }
981 }
982 }
983 }
984
985 m_interpreter.PrintWarningsIfNecessary(s&: result.GetOutputStream(),
986 cmd_name: m_cmd_name);
987 }
988
989 OptionGroupOptions m_option_group;
990 OptionGroupVariable m_option_variable;
991 OptionGroupFormat m_option_format;
992 OptionGroupFileList m_option_compile_units;
993 OptionGroupFileList m_option_shared_libraries;
994 OptionGroupValueObjectDisplay m_varobj_options;
995};
996
997#pragma mark CommandObjectTargetModulesSearchPathsAdd
998
999class CommandObjectTargetModulesSearchPathsAdd : public CommandObjectParsed {
1000public:
1001 CommandObjectTargetModulesSearchPathsAdd(CommandInterpreter &interpreter)
1002 : CommandObjectParsed(interpreter, "target modules search-paths add",
1003 "Add new image search paths substitution pairs to "
1004 "the current target.",
1005 nullptr, eCommandRequiresTarget) {
1006 CommandArgumentEntry arg;
1007 CommandArgumentData old_prefix_arg;
1008 CommandArgumentData new_prefix_arg;
1009
1010 // Define the first variant of this arg pair.
1011 old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
1012 old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1013
1014 // Define the first variant of this arg pair.
1015 new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
1016 new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1017
1018 // There are two required arguments that must always occur together, i.e.
1019 // an argument "pair". Because they must always occur together, they are
1020 // treated as two variants of one argument rather than two independent
1021 // arguments. Push them both into the first argument position for
1022 // m_arguments...
1023
1024 arg.push_back(x: old_prefix_arg);
1025 arg.push_back(x: new_prefix_arg);
1026
1027 m_arguments.push_back(x: arg);
1028 }
1029
1030 ~CommandObjectTargetModulesSearchPathsAdd() override = default;
1031
1032protected:
1033 void DoExecute(Args &command, CommandReturnObject &result) override {
1034 Target &target = GetTarget();
1035 const size_t argc = command.GetArgumentCount();
1036 if (argc & 1) {
1037 result.AppendError(in_string: "add requires an even number of arguments\n");
1038 } else {
1039 for (size_t i = 0; i < argc; i += 2) {
1040 const char *from = command.GetArgumentAtIndex(idx: i);
1041 const char *to = command.GetArgumentAtIndex(idx: i + 1);
1042
1043 if (from[0] && to[0]) {
1044 Log *log = GetLog(mask: LLDBLog::Host);
1045 if (log) {
1046 LLDB_LOGF(log,
1047 "target modules search path adding ImageSearchPath "
1048 "pair: '%s' -> '%s'",
1049 from, to);
1050 }
1051 bool last_pair = ((argc - i) == 2);
1052 target.GetImageSearchPathList().Append(
1053 path: from, replacement: to, notify: last_pair); // Notify if this is the last pair
1054 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1055 } else {
1056 if (from[0])
1057 result.AppendError(in_string: "<path-prefix> can't be empty\n");
1058 else
1059 result.AppendError(in_string: "<new-path-prefix> can't be empty\n");
1060 }
1061 }
1062 }
1063 }
1064};
1065
1066#pragma mark CommandObjectTargetModulesSearchPathsClear
1067
1068class CommandObjectTargetModulesSearchPathsClear : public CommandObjectParsed {
1069public:
1070 CommandObjectTargetModulesSearchPathsClear(CommandInterpreter &interpreter)
1071 : CommandObjectParsed(interpreter, "target modules search-paths clear",
1072 "Clear all current image search path substitution "
1073 "pairs from the current target.",
1074 "target modules search-paths clear",
1075 eCommandRequiresTarget) {}
1076
1077 ~CommandObjectTargetModulesSearchPathsClear() override = default;
1078
1079protected:
1080 void DoExecute(Args &command, CommandReturnObject &result) override {
1081 Target &target = GetTarget();
1082 bool notify = true;
1083 target.GetImageSearchPathList().Clear(notify);
1084 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1085 }
1086};
1087
1088#pragma mark CommandObjectTargetModulesSearchPathsInsert
1089
1090class CommandObjectTargetModulesSearchPathsInsert : public CommandObjectParsed {
1091public:
1092 CommandObjectTargetModulesSearchPathsInsert(CommandInterpreter &interpreter)
1093 : CommandObjectParsed(interpreter, "target modules search-paths insert",
1094 "Insert a new image search path substitution pair "
1095 "into the current target at the specified index.",
1096 nullptr, eCommandRequiresTarget) {
1097 CommandArgumentEntry arg1;
1098 CommandArgumentEntry arg2;
1099 CommandArgumentData index_arg;
1100 CommandArgumentData old_prefix_arg;
1101 CommandArgumentData new_prefix_arg;
1102
1103 // Define the first and only variant of this arg.
1104 index_arg.arg_type = eArgTypeIndex;
1105 index_arg.arg_repetition = eArgRepeatPlain;
1106
1107 // Put the one and only variant into the first arg for m_arguments:
1108 arg1.push_back(x: index_arg);
1109
1110 // Define the first variant of this arg pair.
1111 old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
1112 old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1113
1114 // Define the first variant of this arg pair.
1115 new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
1116 new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1117
1118 // There are two required arguments that must always occur together, i.e.
1119 // an argument "pair". Because they must always occur together, they are
1120 // treated as two variants of one argument rather than two independent
1121 // arguments. Push them both into the same argument position for
1122 // m_arguments...
1123
1124 arg2.push_back(x: old_prefix_arg);
1125 arg2.push_back(x: new_prefix_arg);
1126
1127 // Add arguments to m_arguments.
1128 m_arguments.push_back(x: arg1);
1129 m_arguments.push_back(x: arg2);
1130 }
1131
1132 ~CommandObjectTargetModulesSearchPathsInsert() override = default;
1133
1134 void
1135 HandleArgumentCompletion(CompletionRequest &request,
1136 OptionElementVector &opt_element_vector) override {
1137 if (!m_exe_ctx.HasTargetScope() || request.GetCursorIndex() != 0)
1138 return;
1139
1140 Target *target = m_exe_ctx.GetTargetPtr();
1141 const PathMappingList &list = target->GetImageSearchPathList();
1142 const size_t num = list.GetSize();
1143 ConstString old_path, new_path;
1144 for (size_t i = 0; i < num; ++i) {
1145 if (!list.GetPathsAtIndex(idx: i, path&: old_path, new_path))
1146 break;
1147 StreamString strm;
1148 strm << old_path << " -> " << new_path;
1149 request.TryCompleteCurrentArg(completion: std::to_string(val: i), description: strm.GetString());
1150 }
1151 }
1152
1153protected:
1154 void DoExecute(Args &command, CommandReturnObject &result) override {
1155 Target &target = GetTarget();
1156 size_t argc = command.GetArgumentCount();
1157 // check for at least 3 arguments and an odd number of parameters
1158 if (argc >= 3 && argc & 1) {
1159 uint32_t insert_idx;
1160
1161 if (!llvm::to_integer(S: command.GetArgumentAtIndex(idx: 0), Num&: insert_idx)) {
1162 result.AppendErrorWithFormat(
1163 format: "<index> parameter is not an integer: '%s'.\n",
1164 command.GetArgumentAtIndex(idx: 0));
1165 return;
1166 }
1167
1168 // shift off the index
1169 command.Shift();
1170 argc = command.GetArgumentCount();
1171
1172 for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) {
1173 const char *from = command.GetArgumentAtIndex(idx: i);
1174 const char *to = command.GetArgumentAtIndex(idx: i + 1);
1175
1176 if (from[0] && to[0]) {
1177 bool last_pair = ((argc - i) == 2);
1178 target.GetImageSearchPathList().Insert(path: from, replacement: to, insert_idx,
1179 notify: last_pair);
1180 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1181 } else {
1182 if (from[0])
1183 result.AppendError(in_string: "<path-prefix> can't be empty\n");
1184 else
1185 result.AppendError(in_string: "<new-path-prefix> can't be empty\n");
1186 return;
1187 }
1188 }
1189 } else {
1190 result.AppendError(in_string: "insert requires at least three arguments\n");
1191 }
1192 }
1193};
1194
1195#pragma mark CommandObjectTargetModulesSearchPathsList
1196
1197class CommandObjectTargetModulesSearchPathsList : public CommandObjectParsed {
1198public:
1199 CommandObjectTargetModulesSearchPathsList(CommandInterpreter &interpreter)
1200 : CommandObjectParsed(interpreter, "target modules search-paths list",
1201 "List all current image search path substitution "
1202 "pairs in the current target.",
1203 "target modules search-paths list",
1204 eCommandRequiresTarget) {}
1205
1206 ~CommandObjectTargetModulesSearchPathsList() override = default;
1207
1208protected:
1209 void DoExecute(Args &command, CommandReturnObject &result) override {
1210 Target &target = GetTarget();
1211 target.GetImageSearchPathList().Dump(s: &result.GetOutputStream());
1212 result.SetStatus(eReturnStatusSuccessFinishResult);
1213 }
1214};
1215
1216#pragma mark CommandObjectTargetModulesSearchPathsQuery
1217
1218class CommandObjectTargetModulesSearchPathsQuery : public CommandObjectParsed {
1219public:
1220 CommandObjectTargetModulesSearchPathsQuery(CommandInterpreter &interpreter)
1221 : CommandObjectParsed(
1222 interpreter, "target modules search-paths query",
1223 "Transform a path using the first applicable image search path.",
1224 nullptr, eCommandRequiresTarget) {
1225 AddSimpleArgumentList(arg_type: eArgTypeDirectoryName);
1226 }
1227
1228 ~CommandObjectTargetModulesSearchPathsQuery() override = default;
1229
1230protected:
1231 void DoExecute(Args &command, CommandReturnObject &result) override {
1232 Target &target = GetTarget();
1233 if (command.GetArgumentCount() != 1) {
1234 result.AppendError(in_string: "query requires one argument\n");
1235 return;
1236 }
1237
1238 ConstString orig(command.GetArgumentAtIndex(idx: 0));
1239 ConstString transformed;
1240 if (target.GetImageSearchPathList().RemapPath(path: orig, new_path&: transformed))
1241 result.GetOutputStream().Printf(format: "%s\n", transformed.GetCString());
1242 else
1243 result.GetOutputStream().Printf(format: "%s\n", orig.GetCString());
1244
1245 result.SetStatus(eReturnStatusSuccessFinishResult);
1246 }
1247};
1248
1249// Static Helper functions
1250static void DumpModuleArchitecture(Stream &strm, Module *module,
1251 bool full_triple, uint32_t width) {
1252 if (module) {
1253 StreamString arch_strm;
1254
1255 if (full_triple)
1256 module->GetArchitecture().DumpTriple(s&: arch_strm.AsRawOstream());
1257 else
1258 arch_strm.PutCString(cstr: module->GetArchitecture().GetArchitectureName());
1259 std::string arch_str = std::string(arch_strm.GetString());
1260
1261 if (width)
1262 strm.Printf(format: "%-*s", width, arch_str.c_str());
1263 else
1264 strm.PutCString(cstr: arch_str);
1265 }
1266}
1267
1268static void DumpModuleUUID(Stream &strm, Module *module) {
1269 if (module && module->GetUUID().IsValid())
1270 module->GetUUID().Dump(s&: strm);
1271 else
1272 strm.PutCString(cstr: " ");
1273}
1274
1275static uint32_t DumpCompileUnitLineTable(CommandInterpreter &interpreter,
1276 Stream &strm, Module *module,
1277 const FileSpec &file_spec,
1278 lldb::DescriptionLevel desc_level) {
1279 uint32_t num_matches = 0;
1280 if (module) {
1281 SymbolContextList sc_list;
1282 num_matches = module->ResolveSymbolContextsForFileSpec(
1283 file_spec, line: 0, check_inlines: false, resolve_scope: eSymbolContextCompUnit, sc_list);
1284
1285 bool first_module = true;
1286 for (const SymbolContext &sc : sc_list) {
1287 if (!first_module)
1288 strm << "\n\n";
1289
1290 strm << "Line table for " << sc.comp_unit->GetPrimaryFile() << " in `"
1291 << module->GetFileSpec().GetFilename() << "\n";
1292 LineTable *line_table = sc.comp_unit->GetLineTable();
1293 if (line_table)
1294 line_table->GetDescription(
1295 s: &strm, target: interpreter.GetExecutionContext().GetTargetPtr(),
1296 level: desc_level);
1297 else
1298 strm << "No line table";
1299
1300 first_module = false;
1301 }
1302 }
1303 return num_matches;
1304}
1305
1306static void DumpFullpath(Stream &strm, const FileSpec *file_spec_ptr,
1307 uint32_t width) {
1308 if (file_spec_ptr) {
1309 if (width > 0) {
1310 std::string fullpath = file_spec_ptr->GetPath();
1311 strm.Printf(format: "%-*s", width, fullpath.c_str());
1312 return;
1313 } else {
1314 file_spec_ptr->Dump(s&: strm.AsRawOstream());
1315 return;
1316 }
1317 }
1318 // Keep the width spacing correct if things go wrong...
1319 if (width > 0)
1320 strm.Printf(format: "%-*s", width, "");
1321}
1322
1323static void DumpDirectory(Stream &strm, const FileSpec *file_spec_ptr,
1324 uint32_t width) {
1325 if (file_spec_ptr) {
1326 if (width > 0)
1327 strm.Printf(format: "%-*s", width, file_spec_ptr->GetDirectory().AsCString(value_if_empty: ""));
1328 else
1329 file_spec_ptr->GetDirectory().Dump(s: &strm);
1330 return;
1331 }
1332 // Keep the width spacing correct if things go wrong...
1333 if (width > 0)
1334 strm.Printf(format: "%-*s", width, "");
1335}
1336
1337static void DumpBasename(Stream &strm, const FileSpec *file_spec_ptr,
1338 uint32_t width) {
1339 if (file_spec_ptr) {
1340 if (width > 0)
1341 strm.Printf(format: "%-*s", width, file_spec_ptr->GetFilename().AsCString(value_if_empty: ""));
1342 else
1343 file_spec_ptr->GetFilename().Dump(s: &strm);
1344 return;
1345 }
1346 // Keep the width spacing correct if things go wrong...
1347 if (width > 0)
1348 strm.Printf(format: "%-*s", width, "");
1349}
1350
1351static size_t DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) {
1352 std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
1353 const size_t num_modules = module_list.GetSize();
1354 if (num_modules == 0)
1355 return 0;
1356
1357 size_t num_dumped = 0;
1358 strm.Format(format: "Dumping headers for {0} module(s).\n", args: num_modules);
1359 strm.IndentMore();
1360 for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
1361 if (module_sp) {
1362 if (num_dumped++ > 0) {
1363 strm.EOL();
1364 strm.EOL();
1365 }
1366 ObjectFile *objfile = module_sp->GetObjectFile();
1367 if (objfile)
1368 objfile->Dump(s: &strm);
1369 else {
1370 strm.Format(format: "No object file for module: {0:F}\n",
1371 args: module_sp->GetFileSpec());
1372 }
1373 }
1374 }
1375 strm.IndentLess();
1376 return num_dumped;
1377}
1378
1379static void DumpModuleSymtab(CommandInterpreter &interpreter, Stream &strm,
1380 Module *module, SortOrder sort_order,
1381 Mangled::NamePreference name_preference) {
1382 if (!module)
1383 return;
1384 if (Symtab *symtab = module->GetSymtab())
1385 symtab->Dump(s: &strm, target: interpreter.GetExecutionContext().GetTargetPtr(),
1386 sort_type: sort_order, name_preference);
1387}
1388
1389static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm,
1390 Module *module) {
1391 if (module) {
1392 SectionList *section_list = module->GetSectionList();
1393 if (section_list) {
1394 strm.Printf(format: "Sections for '%s' (%s):\n",
1395 module->GetSpecificationDescription().c_str(),
1396 module->GetArchitecture().GetArchitectureName());
1397 section_list->Dump(s&: strm.AsRawOstream(), indent: strm.GetIndentLevel() + 2,
1398 target: interpreter.GetExecutionContext().GetTargetPtr(), show_header: true,
1399 UINT32_MAX);
1400 }
1401 }
1402}
1403
1404static bool DumpModuleSymbolFile(Stream &strm, Module *module) {
1405 if (module) {
1406 if (SymbolFile *symbol_file = module->GetSymbolFile(can_create: true)) {
1407 symbol_file->Dump(s&: strm);
1408 return true;
1409 }
1410 }
1411 return false;
1412}
1413
1414static bool GetSeparateDebugInfoList(StructuredData::Array &list,
1415 Module *module, bool errors_only,
1416 bool load_all_debug_info) {
1417 if (module) {
1418 if (SymbolFile *symbol_file = module->GetSymbolFile(/*can_create=*/true)) {
1419 StructuredData::Dictionary d;
1420 if (symbol_file->GetSeparateDebugInfo(d, errors_only,
1421 load_all_debug_info)) {
1422 list.AddItem(
1423 item: std::make_shared<StructuredData::Dictionary>(args: std::move(d)));
1424 return true;
1425 }
1426 }
1427 }
1428 return false;
1429}
1430
1431static void DumpDwoFilesTable(Stream &strm,
1432 StructuredData::Array &dwo_listings) {
1433 strm.PutCString(cstr: "Dwo ID Err Dwo Path");
1434 strm.EOL();
1435 strm.PutCString(
1436 cstr: "------------------ --- -----------------------------------------");
1437 strm.EOL();
1438 dwo_listings.ForEach(foreach_callback: [&strm](StructuredData::Object *dwo) {
1439 StructuredData::Dictionary *dict = dwo->GetAsDictionary();
1440 if (!dict)
1441 return false;
1442
1443 uint64_t dwo_id;
1444 if (dict->GetValueForKeyAsInteger(key: "dwo_id", result&: dwo_id))
1445 strm.Printf(format: "0x%16.16" PRIx64 " ", dwo_id);
1446 else
1447 strm.Printf(format: "0x???????????????? ");
1448
1449 llvm::StringRef error;
1450 if (dict->GetValueForKeyAsString(key: "error", result&: error))
1451 strm << "E " << error;
1452 else {
1453 llvm::StringRef resolved_dwo_path;
1454 if (dict->GetValueForKeyAsString(key: "resolved_dwo_path",
1455 result&: resolved_dwo_path)) {
1456 strm << " " << resolved_dwo_path;
1457 if (resolved_dwo_path.ends_with(Suffix: ".dwp")) {
1458 llvm::StringRef dwo_name;
1459 if (dict->GetValueForKeyAsString(key: "dwo_name", result&: dwo_name))
1460 strm << "(" << dwo_name << ")";
1461 }
1462 }
1463 }
1464 strm.EOL();
1465 return true;
1466 });
1467}
1468
1469static void DumpOsoFilesTable(Stream &strm,
1470 StructuredData::Array &oso_listings) {
1471 strm.PutCString(cstr: "Mod Time Err Oso Path");
1472 strm.EOL();
1473 strm.PutCString(cstr: "------------------ --- ---------------------");
1474 strm.EOL();
1475 oso_listings.ForEach(foreach_callback: [&strm](StructuredData::Object *oso) {
1476 StructuredData::Dictionary *dict = oso->GetAsDictionary();
1477 if (!dict)
1478 return false;
1479
1480 uint32_t oso_mod_time;
1481 if (dict->GetValueForKeyAsInteger(key: "oso_mod_time", result&: oso_mod_time))
1482 strm.Printf(format: "0x%16.16" PRIx32 " ", oso_mod_time);
1483
1484 llvm::StringRef error;
1485 if (dict->GetValueForKeyAsString(key: "error", result&: error))
1486 strm << "E " << error;
1487 else {
1488 llvm::StringRef oso_path;
1489 if (dict->GetValueForKeyAsString(key: "oso_path", result&: oso_path))
1490 strm << " " << oso_path;
1491 }
1492 strm.EOL();
1493 return true;
1494 });
1495}
1496
1497static void
1498DumpAddress(ExecutionContextScope *exe_scope, const Address &so_addr,
1499 bool verbose, bool all_ranges, Stream &strm,
1500 std::optional<Stream::HighlightSettings> settings = std::nullopt) {
1501 strm.IndentMore();
1502 strm.Indent(s: " Address: ");
1503 so_addr.Dump(s: &strm, exe_scope, style: Address::DumpStyleModuleWithFileAddress);
1504 strm.PutCString(cstr: " (");
1505 so_addr.Dump(s: &strm, exe_scope, style: Address::DumpStyleSectionNameOffset);
1506 strm.PutCString(cstr: ")\n");
1507 strm.Indent(s: " Summary: ");
1508 const uint32_t save_indent = strm.GetIndentLevel();
1509 strm.SetIndentLevel(save_indent + 13);
1510 so_addr.Dump(s: &strm, exe_scope, style: Address::DumpStyleResolvedDescription,
1511 fallback_style: Address::DumpStyleInvalid, UINT32_MAX, all_ranges: false, settings);
1512 strm.SetIndentLevel(save_indent);
1513 // Print out detailed address information when verbose is enabled
1514 if (verbose) {
1515 strm.EOL();
1516 so_addr.Dump(s: &strm, exe_scope, style: Address::DumpStyleDetailedSymbolContext,
1517 fallback_style: Address::DumpStyleInvalid, UINT32_MAX, all_ranges, settings);
1518 }
1519 strm.IndentLess();
1520}
1521
1522static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm,
1523 Module *module, uint32_t resolve_mask,
1524 lldb::addr_t raw_addr, lldb::addr_t offset,
1525 bool verbose, bool all_ranges) {
1526 if (module) {
1527 lldb::addr_t addr = raw_addr - offset;
1528 Address so_addr;
1529 SymbolContext sc;
1530 Target *target = interpreter.GetExecutionContext().GetTargetPtr();
1531 if (target && target->HasLoadedSections()) {
1532 if (!target->ResolveLoadAddress(load_addr: addr, so_addr))
1533 return false;
1534 else if (so_addr.GetModule().get() != module)
1535 return false;
1536 } else {
1537 if (!module->ResolveFileAddress(vm_addr: addr, so_addr))
1538 return false;
1539 }
1540
1541 ExecutionContextScope *exe_scope =
1542 interpreter.GetExecutionContext().GetBestExecutionContextScope();
1543 DumpAddress(exe_scope, so_addr, verbose, all_ranges, strm);
1544 return true;
1545 }
1546
1547 return false;
1548}
1549
1550static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
1551 Stream &strm, Module *module,
1552 const char *name, bool name_is_regex,
1553 bool verbose, bool all_ranges) {
1554 if (!module)
1555 return 0;
1556
1557 Symtab *symtab = module->GetSymtab();
1558 if (!symtab)
1559 return 0;
1560
1561 SymbolContext sc;
1562 const bool use_color = interpreter.GetDebugger().GetUseColor();
1563 std::vector<uint32_t> match_indexes;
1564 ConstString symbol_name(name);
1565 uint32_t num_matches = 0;
1566 if (name_is_regex) {
1567 RegularExpression name_regexp(symbol_name.GetStringRef());
1568 num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType(
1569 regex: name_regexp, symbol_type: eSymbolTypeAny, indexes&: match_indexes);
1570 } else {
1571 num_matches =
1572 symtab->AppendSymbolIndexesWithName(symbol_name, matches&: match_indexes);
1573 }
1574
1575 if (num_matches > 0) {
1576 strm.Indent();
1577 strm.Printf(format: "%u symbols match %s'%s' in ", num_matches,
1578 name_is_regex ? "the regular expression " : "", name);
1579 DumpFullpath(strm, file_spec_ptr: &module->GetFileSpec(), width: 0);
1580 strm.PutCString(cstr: ":\n");
1581 strm.IndentMore();
1582 Stream::HighlightSettings settings(
1583 name, interpreter.GetDebugger().GetRegexMatchAnsiPrefix(),
1584 interpreter.GetDebugger().GetRegexMatchAnsiSuffix());
1585 for (uint32_t i = 0; i < num_matches; ++i) {
1586 Symbol *symbol = symtab->SymbolAtIndex(idx: match_indexes[i]);
1587 if (symbol) {
1588 if (symbol->ValueIsAddress()) {
1589 DumpAddress(
1590 exe_scope: interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1591 so_addr: symbol->GetAddressRef(), verbose, all_ranges, strm,
1592 settings: use_color && name_is_regex
1593 ? std::optional<Stream::HighlightSettings>{settings}
1594 : std::nullopt);
1595 strm.EOL();
1596 } else {
1597 strm.IndentMore();
1598 strm.Indent(s: " Name: ");
1599 strm.PutCStringColorHighlighted(
1600 text: symbol->GetDisplayName().GetStringRef(),
1601 settings: use_color && name_is_regex
1602 ? std::optional<Stream::HighlightSettings>{settings}
1603 : std::nullopt);
1604 strm.EOL();
1605 strm.Indent(s: " Value: ");
1606 strm.Printf(format: "0x%16.16" PRIx64 "\n", symbol->GetRawValue());
1607 if (symbol->GetByteSizeIsValid()) {
1608 strm.Indent(s: " Size: ");
1609 strm.Printf(format: "0x%16.16" PRIx64 "\n", symbol->GetByteSize());
1610 }
1611 strm.IndentLess();
1612 }
1613 }
1614 }
1615 strm.IndentLess();
1616 }
1617 return num_matches;
1618}
1619
1620static void DumpSymbolContextList(
1621 ExecutionContextScope *exe_scope, Stream &strm,
1622 const SymbolContextList &sc_list, bool verbose, bool all_ranges,
1623 std::optional<Stream::HighlightSettings> settings = std::nullopt) {
1624 strm.IndentMore();
1625 bool first_module = true;
1626 for (const SymbolContext &sc : sc_list) {
1627 if (!first_module)
1628 strm.EOL();
1629
1630 Address addr;
1631 if (sc.line_entry.IsValid())
1632 addr = sc.line_entry.range.GetBaseAddress();
1633 else if (sc.block && sc.block->GetContainingInlinedBlock())
1634 sc.block->GetContainingInlinedBlock()->GetStartAddress(addr);
1635 else
1636 addr = sc.GetFunctionOrSymbolAddress();
1637
1638 DumpAddress(exe_scope, so_addr: addr, verbose, all_ranges, strm, settings);
1639 first_module = false;
1640 }
1641 strm.IndentLess();
1642}
1643
1644static size_t LookupFunctionInModule(CommandInterpreter &interpreter,
1645 Stream &strm, Module *module,
1646 const char *name, bool name_is_regex,
1647 const ModuleFunctionSearchOptions &options,
1648 bool verbose, bool all_ranges) {
1649 if (module && name && name[0]) {
1650 SymbolContextList sc_list;
1651 size_t num_matches = 0;
1652 if (name_is_regex) {
1653 RegularExpression function_name_regex((llvm::StringRef(name)));
1654 module->FindFunctions(regex: function_name_regex, options, sc_list);
1655 } else {
1656 ConstString function_name(name);
1657 module->FindFunctions(name: function_name, parent_decl_ctx: CompilerDeclContext(),
1658 name_type_mask: eFunctionNameTypeAuto, options, sc_list);
1659 }
1660 num_matches = sc_list.GetSize();
1661 if (num_matches) {
1662 strm.Indent();
1663 strm.Printf(format: "%" PRIu64 " match%s found in ", (uint64_t)num_matches,
1664 num_matches > 1 ? "es" : "");
1665 DumpFullpath(strm, file_spec_ptr: &module->GetFileSpec(), width: 0);
1666 strm.PutCString(cstr: ":\n");
1667 DumpSymbolContextList(
1668 exe_scope: interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1669 strm, sc_list, verbose, all_ranges);
1670 }
1671 return num_matches;
1672 }
1673 return 0;
1674}
1675
1676static size_t LookupTypeInModule(Target *target,
1677 CommandInterpreter &interpreter, Stream &strm,
1678 Module *module, const char *name_cstr,
1679 bool name_is_regex) {
1680 if (module && name_cstr && name_cstr[0]) {
1681 TypeQuery query(name_cstr);
1682 TypeResults results;
1683 module->FindTypes(query, results);
1684
1685 TypeList type_list;
1686 SymbolContext sc;
1687 if (module)
1688 sc.module_sp = module->shared_from_this();
1689 // Sort the type results and put the results that matched in \a module
1690 // first if \a module was specified.
1691 sc.SortTypeList(type_map&: results.GetTypeMap(), type_list);
1692 if (type_list.Empty())
1693 return 0;
1694
1695 const uint64_t num_matches = type_list.GetSize();
1696
1697 strm.Indent();
1698 strm.Printf(format: "%" PRIu64 " match%s found in ", num_matches,
1699 num_matches > 1 ? "es" : "");
1700 DumpFullpath(strm, file_spec_ptr: &module->GetFileSpec(), width: 0);
1701 strm.PutCString(cstr: ":\n");
1702 for (TypeSP type_sp : type_list.Types()) {
1703 if (!type_sp)
1704 continue;
1705 // Resolve the clang type so that any forward references to types
1706 // that haven't yet been parsed will get parsed.
1707 type_sp->GetFullCompilerType();
1708 type_sp->GetDescription(s: &strm, level: eDescriptionLevelFull, show_name: true, exe_scope: target);
1709 // Print all typedef chains
1710 TypeSP typedef_type_sp(type_sp);
1711 TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1712 while (typedefed_type_sp) {
1713 strm.EOL();
1714 strm.Printf(format: " typedef '%s': ",
1715 typedef_type_sp->GetName().GetCString());
1716 typedefed_type_sp->GetFullCompilerType();
1717 typedefed_type_sp->GetDescription(s: &strm, level: eDescriptionLevelFull, show_name: true,
1718 exe_scope: target);
1719 typedef_type_sp = typedefed_type_sp;
1720 typedefed_type_sp = typedef_type_sp->GetTypedefType();
1721 }
1722 strm.EOL();
1723 }
1724 return type_list.GetSize();
1725 }
1726 return 0;
1727}
1728
1729static size_t LookupTypeHere(Target *target, CommandInterpreter &interpreter,
1730 Stream &strm, Module &module,
1731 const char *name_cstr, bool name_is_regex) {
1732 TypeQuery query(name_cstr);
1733 TypeResults results;
1734 module.FindTypes(query, results);
1735 TypeList type_list;
1736 SymbolContext sc;
1737 sc.module_sp = module.shared_from_this();
1738 sc.SortTypeList(type_map&: results.GetTypeMap(), type_list);
1739 if (type_list.Empty())
1740 return 0;
1741
1742 strm.Indent();
1743 strm.PutCString(cstr: "Best match found in ");
1744 DumpFullpath(strm, file_spec_ptr: &module.GetFileSpec(), width: 0);
1745 strm.PutCString(cstr: ":\n");
1746
1747 TypeSP type_sp(type_list.GetTypeAtIndex(idx: 0));
1748 if (type_sp) {
1749 // Resolve the clang type so that any forward references to types that
1750 // haven't yet been parsed will get parsed.
1751 type_sp->GetFullCompilerType();
1752 type_sp->GetDescription(s: &strm, level: eDescriptionLevelFull, show_name: true, exe_scope: target);
1753 // Print all typedef chains.
1754 TypeSP typedef_type_sp(type_sp);
1755 TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1756 while (typedefed_type_sp) {
1757 strm.EOL();
1758 strm.Printf(format: " typedef '%s': ",
1759 typedef_type_sp->GetName().GetCString());
1760 typedefed_type_sp->GetFullCompilerType();
1761 typedefed_type_sp->GetDescription(s: &strm, level: eDescriptionLevelFull, show_name: true,
1762 exe_scope: target);
1763 typedef_type_sp = typedefed_type_sp;
1764 typedefed_type_sp = typedef_type_sp->GetTypedefType();
1765 }
1766 }
1767 strm.EOL();
1768 return type_list.GetSize();
1769}
1770
1771static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter,
1772 Stream &strm, Module *module,
1773 const FileSpec &file_spec,
1774 uint32_t line, bool check_inlines,
1775 bool verbose, bool all_ranges) {
1776 if (module && file_spec) {
1777 SymbolContextList sc_list;
1778 const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(
1779 file_spec, line, check_inlines, resolve_scope: eSymbolContextEverything, sc_list);
1780 if (num_matches > 0) {
1781 strm.Indent();
1782 strm.Printf(format: "%u match%s found in ", num_matches,
1783 num_matches > 1 ? "es" : "");
1784 strm << file_spec;
1785 if (line > 0)
1786 strm.Printf(format: ":%u", line);
1787 strm << " in ";
1788 DumpFullpath(strm, file_spec_ptr: &module->GetFileSpec(), width: 0);
1789 strm.PutCString(cstr: ":\n");
1790 DumpSymbolContextList(
1791 exe_scope: interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1792 strm, sc_list, verbose, all_ranges);
1793 return num_matches;
1794 }
1795 }
1796 return 0;
1797}
1798
1799static size_t FindModulesByName(Target *target, const char *module_name,
1800 ModuleList &module_list,
1801 bool check_global_list) {
1802 FileSpec module_file_spec(module_name);
1803 ModuleSpec module_spec(module_file_spec);
1804
1805 const size_t initial_size = module_list.GetSize();
1806
1807 if (check_global_list) {
1808 // Check the global list
1809 std::lock_guard<std::recursive_mutex> guard(
1810 Module::GetAllocationModuleCollectionMutex());
1811 const size_t num_modules = Module::GetNumberAllocatedModules();
1812 ModuleSP module_sp;
1813 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
1814 Module *module = Module::GetAllocatedModuleAtIndex(idx: image_idx);
1815
1816 if (module) {
1817 if (module->MatchesModuleSpec(module_ref: module_spec)) {
1818 module_sp = module->shared_from_this();
1819 module_list.AppendIfNeeded(new_module: module_sp);
1820 }
1821 }
1822 }
1823 } else {
1824 if (target) {
1825 target->GetImages().FindModules(module_spec, matching_module_list&: module_list);
1826 const size_t num_matches = module_list.GetSize();
1827
1828 // Not found in our module list for our target, check the main shared
1829 // module list in case it is a extra file used somewhere else
1830 if (num_matches == 0) {
1831 module_spec.GetArchitecture() = target->GetArchitecture();
1832 ModuleList::FindSharedModules(module_spec, matching_module_list&: module_list);
1833 }
1834 } else {
1835 ModuleList::FindSharedModules(module_spec, matching_module_list&: module_list);
1836 }
1837 }
1838
1839 return module_list.GetSize() - initial_size;
1840}
1841
1842#pragma mark CommandObjectTargetModulesModuleAutoComplete
1843
1844// A base command object class that can auto complete with module file
1845// paths
1846
1847class CommandObjectTargetModulesModuleAutoComplete
1848 : public CommandObjectParsed {
1849public:
1850 CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter &interpreter,
1851 const char *name,
1852 const char *help,
1853 const char *syntax,
1854 uint32_t flags = 0)
1855 : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1856 AddSimpleArgumentList(arg_type: eArgTypeFilename, repetition_type: eArgRepeatStar);
1857 }
1858
1859 ~CommandObjectTargetModulesModuleAutoComplete() override = default;
1860
1861 void
1862 HandleArgumentCompletion(CompletionRequest &request,
1863 OptionElementVector &opt_element_vector) override {
1864 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1865 interpreter&: GetCommandInterpreter(), completion_mask: lldb::eModuleCompletion, request, searcher: nullptr);
1866 }
1867};
1868
1869#pragma mark CommandObjectTargetModulesSourceFileAutoComplete
1870
1871// A base command object class that can auto complete with module source
1872// file paths
1873
1874class CommandObjectTargetModulesSourceFileAutoComplete
1875 : public CommandObjectParsed {
1876public:
1877 CommandObjectTargetModulesSourceFileAutoComplete(
1878 CommandInterpreter &interpreter, const char *name, const char *help,
1879 const char *syntax, uint32_t flags)
1880 : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1881 AddSimpleArgumentList(arg_type: eArgTypeSourceFile, repetition_type: eArgRepeatPlus);
1882 }
1883
1884 ~CommandObjectTargetModulesSourceFileAutoComplete() override = default;
1885
1886 void
1887 HandleArgumentCompletion(CompletionRequest &request,
1888 OptionElementVector &opt_element_vector) override {
1889 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1890 interpreter&: GetCommandInterpreter(), completion_mask: lldb::eSourceFileCompletion, request, searcher: nullptr);
1891 }
1892};
1893
1894#pragma mark CommandObjectTargetModulesDumpObjfile
1895
1896class CommandObjectTargetModulesDumpObjfile
1897 : public CommandObjectTargetModulesModuleAutoComplete {
1898public:
1899 CommandObjectTargetModulesDumpObjfile(CommandInterpreter &interpreter)
1900 : CommandObjectTargetModulesModuleAutoComplete(
1901 interpreter, "target modules dump objfile",
1902 "Dump the object file headers from one or more target modules.",
1903 nullptr, eCommandRequiresTarget) {}
1904
1905 ~CommandObjectTargetModulesDumpObjfile() override = default;
1906
1907protected:
1908 void DoExecute(Args &command, CommandReturnObject &result) override {
1909 Target &target = GetTarget();
1910
1911 uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize();
1912 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
1913 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
1914
1915 size_t num_dumped = 0;
1916 if (command.GetArgumentCount() == 0) {
1917 // Dump all headers for all modules images
1918 num_dumped = DumpModuleObjfileHeaders(strm&: result.GetOutputStream(),
1919 module_list&: target.GetImages());
1920 if (num_dumped == 0) {
1921 result.AppendError(in_string: "the target has no associated executable images");
1922 }
1923 } else {
1924 // Find the modules that match the basename or full path.
1925 ModuleList module_list;
1926 const char *arg_cstr;
1927 for (int arg_idx = 0;
1928 (arg_cstr = command.GetArgumentAtIndex(idx: arg_idx)) != nullptr;
1929 ++arg_idx) {
1930 size_t num_matched =
1931 FindModulesByName(target: &target, module_name: arg_cstr, module_list, check_global_list: true);
1932 if (num_matched == 0) {
1933 result.AppendWarningWithFormat(
1934 format: "Unable to find an image that matches '%s'.\n", arg_cstr);
1935 }
1936 }
1937 // Dump all the modules we found.
1938 num_dumped =
1939 DumpModuleObjfileHeaders(strm&: result.GetOutputStream(), module_list);
1940 }
1941
1942 if (num_dumped > 0) {
1943 result.SetStatus(eReturnStatusSuccessFinishResult);
1944 } else {
1945 result.AppendError(in_string: "no matching executable images found");
1946 }
1947 }
1948};
1949
1950#define LLDB_OPTIONS_target_modules_dump_symtab
1951#include "CommandOptions.inc"
1952
1953class CommandObjectTargetModulesDumpSymtab
1954 : public CommandObjectTargetModulesModuleAutoComplete {
1955public:
1956 CommandObjectTargetModulesDumpSymtab(CommandInterpreter &interpreter)
1957 : CommandObjectTargetModulesModuleAutoComplete(
1958 interpreter, "target modules dump symtab",
1959 "Dump the symbol table from one or more target modules.", nullptr,
1960 eCommandRequiresTarget) {}
1961
1962 ~CommandObjectTargetModulesDumpSymtab() override = default;
1963
1964 Options *GetOptions() override { return &m_options; }
1965
1966 class CommandOptions : public Options {
1967 public:
1968 CommandOptions() = default;
1969
1970 ~CommandOptions() override = default;
1971
1972 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1973 ExecutionContext *execution_context) override {
1974 Status error;
1975 const int short_option = m_getopt_table[option_idx].val;
1976
1977 switch (short_option) {
1978 case 'm':
1979 m_prefer_mangled.SetCurrentValue(true);
1980 m_prefer_mangled.SetOptionWasSet();
1981 break;
1982
1983 case 's':
1984 m_sort_order = (SortOrder)OptionArgParser::ToOptionEnum(
1985 s: option_arg, enum_values: GetDefinitions()[option_idx].enum_values,
1986 fail_value: eSortOrderNone, error);
1987 break;
1988
1989 default:
1990 llvm_unreachable("Unimplemented option");
1991 }
1992 return error;
1993 }
1994
1995 void OptionParsingStarting(ExecutionContext *execution_context) override {
1996 m_sort_order = eSortOrderNone;
1997 m_prefer_mangled.Clear();
1998 }
1999
2000 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2001 return llvm::ArrayRef(g_target_modules_dump_symtab_options);
2002 }
2003
2004 SortOrder m_sort_order = eSortOrderNone;
2005 OptionValueBoolean m_prefer_mangled = {false, false};
2006 };
2007
2008protected:
2009 void DoExecute(Args &command, CommandReturnObject &result) override {
2010 Target &target = GetTarget();
2011 uint32_t num_dumped = 0;
2012 Mangled::NamePreference name_preference =
2013 (m_options.m_prefer_mangled ? Mangled::ePreferMangled
2014 : Mangled::ePreferDemangled);
2015
2016 uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize();
2017 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2018 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2019
2020 if (command.GetArgumentCount() == 0) {
2021 // Dump all sections for all modules images
2022 const ModuleList &module_list = target.GetImages();
2023 std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
2024 const size_t num_modules = module_list.GetSize();
2025 if (num_modules > 0) {
2026 result.GetOutputStream().Format(
2027 format: "Dumping symbol table for {0} modules.\n", args: num_modules);
2028 for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
2029 if (num_dumped > 0) {
2030 result.GetOutputStream().EOL();
2031 result.GetOutputStream().EOL();
2032 }
2033 if (INTERRUPT_REQUESTED(GetDebugger(),
2034 "Interrupted in dump all symtabs with {0} "
2035 "of {1} dumped.", num_dumped, num_modules))
2036 break;
2037
2038 num_dumped++;
2039 DumpModuleSymtab(interpreter&: m_interpreter, strm&: result.GetOutputStream(),
2040 module: module_sp.get(), sort_order: m_options.m_sort_order,
2041 name_preference);
2042 }
2043 } else {
2044 result.AppendError(in_string: "the target has no associated executable images");
2045 return;
2046 }
2047 } else {
2048 // Dump specified images (by basename or fullpath)
2049 const char *arg_cstr;
2050 for (int arg_idx = 0;
2051 (arg_cstr = command.GetArgumentAtIndex(idx: arg_idx)) != nullptr;
2052 ++arg_idx) {
2053 ModuleList module_list;
2054 const size_t num_matches =
2055 FindModulesByName(target: &target, module_name: arg_cstr, module_list, check_global_list: true);
2056 if (num_matches > 0) {
2057 for (ModuleSP module_sp : module_list.Modules()) {
2058 if (module_sp) {
2059 if (num_dumped > 0) {
2060 result.GetOutputStream().EOL();
2061 result.GetOutputStream().EOL();
2062 }
2063 if (INTERRUPT_REQUESTED(GetDebugger(),
2064 "Interrupted in dump symtab list with {0} of {1} dumped.",
2065 num_dumped, num_matches))
2066 break;
2067
2068 num_dumped++;
2069 DumpModuleSymtab(interpreter&: m_interpreter, strm&: result.GetOutputStream(),
2070 module: module_sp.get(), sort_order: m_options.m_sort_order,
2071 name_preference);
2072 }
2073 }
2074 } else
2075 result.AppendWarningWithFormat(
2076 format: "Unable to find an image that matches '%s'.\n", arg_cstr);
2077 }
2078 }
2079
2080 if (num_dumped > 0)
2081 result.SetStatus(eReturnStatusSuccessFinishResult);
2082 else {
2083 result.AppendError(in_string: "no matching executable images found");
2084 }
2085 }
2086
2087 CommandOptions m_options;
2088};
2089
2090#pragma mark CommandObjectTargetModulesDumpSections
2091
2092// Image section dumping command
2093
2094class CommandObjectTargetModulesDumpSections
2095 : public CommandObjectTargetModulesModuleAutoComplete {
2096public:
2097 CommandObjectTargetModulesDumpSections(CommandInterpreter &interpreter)
2098 : CommandObjectTargetModulesModuleAutoComplete(
2099 interpreter, "target modules dump sections",
2100 "Dump the sections from one or more target modules.",
2101 //"target modules dump sections [<file1> ...]")
2102 nullptr, eCommandRequiresTarget) {}
2103
2104 ~CommandObjectTargetModulesDumpSections() override = default;
2105
2106protected:
2107 void DoExecute(Args &command, CommandReturnObject &result) override {
2108 Target &target = GetTarget();
2109 uint32_t num_dumped = 0;
2110
2111 uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize();
2112 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2113 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2114
2115 if (command.GetArgumentCount() == 0) {
2116 // Dump all sections for all modules images
2117 const size_t num_modules = target.GetImages().GetSize();
2118 if (num_modules == 0) {
2119 result.AppendError(in_string: "the target has no associated executable images");
2120 return;
2121 }
2122
2123 result.GetOutputStream().Format(format: "Dumping sections for {0} modules.\n",
2124 args: num_modules);
2125 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2126 if (INTERRUPT_REQUESTED(GetDebugger(),
2127 "Interrupted in dump all sections with {0} of {1} dumped",
2128 image_idx, num_modules))
2129 break;
2130
2131 num_dumped++;
2132 DumpModuleSections(
2133 interpreter&: m_interpreter, strm&: result.GetOutputStream(),
2134 module: target.GetImages().GetModulePointerAtIndex(idx: image_idx));
2135 }
2136 } else {
2137 // Dump specified images (by basename or fullpath)
2138 const char *arg_cstr;
2139 for (int arg_idx = 0;
2140 (arg_cstr = command.GetArgumentAtIndex(idx: arg_idx)) != nullptr;
2141 ++arg_idx) {
2142 ModuleList module_list;
2143 const size_t num_matches =
2144 FindModulesByName(target: &target, module_name: arg_cstr, module_list, check_global_list: true);
2145 if (num_matches > 0) {
2146 for (size_t i = 0; i < num_matches; ++i) {
2147 if (INTERRUPT_REQUESTED(GetDebugger(),
2148 "Interrupted in dump section list with {0} of {1} dumped.",
2149 i, num_matches))
2150 break;
2151
2152 Module *module = module_list.GetModulePointerAtIndex(idx: i);
2153 if (module) {
2154 num_dumped++;
2155 DumpModuleSections(interpreter&: m_interpreter, strm&: result.GetOutputStream(),
2156 module);
2157 }
2158 }
2159 } else {
2160 // Check the global list
2161 std::lock_guard<std::recursive_mutex> guard(
2162 Module::GetAllocationModuleCollectionMutex());
2163
2164 result.AppendWarningWithFormat(
2165 format: "Unable to find an image that matches '%s'.\n", arg_cstr);
2166 }
2167 }
2168 }
2169
2170 if (num_dumped > 0)
2171 result.SetStatus(eReturnStatusSuccessFinishResult);
2172 else {
2173 result.AppendError(in_string: "no matching executable images found");
2174 }
2175 }
2176};
2177
2178class CommandObjectTargetModulesDumpClangPCMInfo : public CommandObjectParsed {
2179public:
2180 CommandObjectTargetModulesDumpClangPCMInfo(CommandInterpreter &interpreter)
2181 : CommandObjectParsed(
2182 interpreter, "target modules dump pcm-info",
2183 "Dump information about the given clang module (pcm).") {
2184 // Take a single file argument.
2185 AddSimpleArgumentList(arg_type: eArgTypeFilename);
2186 }
2187
2188 ~CommandObjectTargetModulesDumpClangPCMInfo() override = default;
2189
2190protected:
2191 void DoExecute(Args &command, CommandReturnObject &result) override {
2192 if (command.GetArgumentCount() != 1) {
2193 result.AppendErrorWithFormat(format: "'%s' takes exactly one pcm path argument.",
2194 m_cmd_name.c_str());
2195 return;
2196 }
2197
2198 const char *pcm_path = command.GetArgumentAtIndex(idx: 0);
2199 const FileSpec pcm_file{pcm_path};
2200
2201 if (pcm_file.GetFileNameExtension() != ".pcm") {
2202 result.AppendError(in_string: "file must have a .pcm extension");
2203 return;
2204 }
2205
2206 if (!FileSystem::Instance().Exists(file_spec: pcm_file)) {
2207 result.AppendError(in_string: "pcm file does not exist");
2208 return;
2209 }
2210
2211 const char *clang_args[] = {"clang", pcm_path};
2212 clang::CompilerInstance compiler(clang::createInvocation(Args: clang_args));
2213 compiler.createDiagnostics(VFS&: *FileSystem::Instance().GetVirtualFileSystem());
2214
2215 // Pass empty deleter to not attempt to free memory that was allocated
2216 // outside of the current scope, possibly statically.
2217 std::shared_ptr<llvm::raw_ostream> Out(
2218 &result.GetOutputStream().AsRawOstream(), [](llvm::raw_ostream *) {});
2219 clang::DumpModuleInfoAction dump_module_info(Out);
2220 // DumpModuleInfoAction requires ObjectFilePCHContainerReader.
2221 compiler.getPCHContainerOperations()->registerReader(
2222 Reader: std::make_unique<clang::ObjectFilePCHContainerReader>());
2223
2224 if (compiler.ExecuteAction(Act&: dump_module_info))
2225 result.SetStatus(eReturnStatusSuccessFinishResult);
2226 }
2227};
2228
2229#pragma mark CommandObjectTargetModulesDumpClangAST
2230
2231// Clang AST dumping command
2232
2233class CommandObjectTargetModulesDumpClangAST
2234 : public CommandObjectTargetModulesModuleAutoComplete {
2235public:
2236 CommandObjectTargetModulesDumpClangAST(CommandInterpreter &interpreter)
2237 : CommandObjectTargetModulesModuleAutoComplete(
2238 interpreter, "target modules dump ast",
2239 "Dump the clang ast for a given module's symbol file.",
2240 "target modules dump ast [--filter <name>] [<file1> ...]",
2241 eCommandRequiresTarget),
2242 m_filter(LLDB_OPT_SET_1, false, "filter", 'f', 0, eArgTypeName,
2243 "Dump only the decls whose names contain the specified filter "
2244 "string.",
2245 /*default_value=*/"") {
2246 m_option_group.Append(group: &m_filter, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2247 m_option_group.Finalize();
2248 }
2249
2250 Options *GetOptions() override { return &m_option_group; }
2251
2252 ~CommandObjectTargetModulesDumpClangAST() override = default;
2253
2254 OptionGroupOptions m_option_group;
2255 OptionGroupString m_filter;
2256
2257protected:
2258 void DoExecute(Args &command, CommandReturnObject &result) override {
2259 Target &target = GetTarget();
2260
2261 const ModuleList &module_list = target.GetImages();
2262 const size_t num_modules = module_list.GetSize();
2263 if (num_modules == 0) {
2264 result.AppendError(in_string: "the target has no associated executable images");
2265 return;
2266 }
2267
2268 llvm::StringRef filter = m_filter.GetOptionValue().GetCurrentValueAsRef();
2269
2270 if (command.GetArgumentCount() == 0) {
2271 // Dump all ASTs for all modules images
2272 result.GetOutputStream().Format(format: "Dumping clang ast for {0} modules.\n",
2273 args: num_modules);
2274 for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
2275 if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted dumping clang ast"))
2276 break;
2277 if (SymbolFile *sf = module_sp->GetSymbolFile())
2278 sf->DumpClangAST(s&: result.GetOutputStream(), filter);
2279 }
2280 result.SetStatus(eReturnStatusSuccessFinishResult);
2281 return;
2282 }
2283
2284 // Dump specified ASTs (by basename or fullpath)
2285 for (const Args::ArgEntry &arg : command.entries()) {
2286 ModuleList module_list;
2287 const size_t num_matches =
2288 FindModulesByName(target: &target, module_name: arg.c_str(), module_list, check_global_list: true);
2289 if (num_matches == 0) {
2290 // Check the global list
2291 std::lock_guard<std::recursive_mutex> guard(
2292 Module::GetAllocationModuleCollectionMutex());
2293
2294 result.AppendWarningWithFormat(
2295 format: "Unable to find an image that matches '%s'.\n", arg.c_str());
2296 continue;
2297 }
2298
2299 for (size_t i = 0; i < num_matches; ++i) {
2300 if (INTERRUPT_REQUESTED(GetDebugger(),
2301 "Interrupted in dump clang ast list with {0} of {1} dumped.",
2302 i, num_matches))
2303 break;
2304
2305 Module *m = module_list.GetModulePointerAtIndex(idx: i);
2306 if (SymbolFile *sf = m->GetSymbolFile())
2307 sf->DumpClangAST(s&: result.GetOutputStream(), filter);
2308 }
2309 }
2310 result.SetStatus(eReturnStatusSuccessFinishResult);
2311 }
2312};
2313
2314#pragma mark CommandObjectTargetModulesDumpSymfile
2315
2316// Image debug symbol dumping command
2317
2318class CommandObjectTargetModulesDumpSymfile
2319 : public CommandObjectTargetModulesModuleAutoComplete {
2320public:
2321 CommandObjectTargetModulesDumpSymfile(CommandInterpreter &interpreter)
2322 : CommandObjectTargetModulesModuleAutoComplete(
2323 interpreter, "target modules dump symfile",
2324 "Dump the debug symbol file for one or more target modules.",
2325 //"target modules dump symfile [<file1> ...]")
2326 nullptr, eCommandRequiresTarget) {}
2327
2328 ~CommandObjectTargetModulesDumpSymfile() override = default;
2329
2330protected:
2331 void DoExecute(Args &command, CommandReturnObject &result) override {
2332 Target &target = GetTarget();
2333 uint32_t num_dumped = 0;
2334
2335 uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize();
2336 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2337 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2338
2339 if (command.GetArgumentCount() == 0) {
2340 // Dump all sections for all modules images
2341 const ModuleList &target_modules = target.GetImages();
2342 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2343 const size_t num_modules = target_modules.GetSize();
2344 if (num_modules == 0) {
2345 result.AppendError(in_string: "the target has no associated executable images");
2346 return;
2347 }
2348 result.GetOutputStream().Format(
2349 format: "Dumping debug symbols for {0} modules.\n", args: num_modules);
2350 for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
2351 if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dumping all "
2352 "debug symbols with {0} of {1} modules dumped",
2353 num_dumped, num_modules))
2354 break;
2355
2356 if (DumpModuleSymbolFile(strm&: result.GetOutputStream(), module: module_sp.get()))
2357 num_dumped++;
2358 }
2359 } else {
2360 // Dump specified images (by basename or fullpath)
2361 const char *arg_cstr;
2362 for (int arg_idx = 0;
2363 (arg_cstr = command.GetArgumentAtIndex(idx: arg_idx)) != nullptr;
2364 ++arg_idx) {
2365 ModuleList module_list;
2366 const size_t num_matches =
2367 FindModulesByName(target: &target, module_name: arg_cstr, module_list, check_global_list: true);
2368 if (num_matches > 0) {
2369 for (size_t i = 0; i < num_matches; ++i) {
2370 if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted dumping {0} "
2371 "of {1} requested modules",
2372 i, num_matches))
2373 break;
2374 Module *module = module_list.GetModulePointerAtIndex(idx: i);
2375 if (module) {
2376 if (DumpModuleSymbolFile(strm&: result.GetOutputStream(), module))
2377 num_dumped++;
2378 }
2379 }
2380 } else
2381 result.AppendWarningWithFormat(
2382 format: "Unable to find an image that matches '%s'.\n", arg_cstr);
2383 }
2384 }
2385
2386 if (num_dumped > 0)
2387 result.SetStatus(eReturnStatusSuccessFinishResult);
2388 else {
2389 result.AppendError(in_string: "no matching executable images found");
2390 }
2391 }
2392};
2393
2394#pragma mark CommandObjectTargetModulesDumpLineTable
2395#define LLDB_OPTIONS_target_modules_dump
2396#include "CommandOptions.inc"
2397
2398// Image debug line table dumping command
2399
2400class CommandObjectTargetModulesDumpLineTable
2401 : public CommandObjectTargetModulesSourceFileAutoComplete {
2402public:
2403 CommandObjectTargetModulesDumpLineTable(CommandInterpreter &interpreter)
2404 : CommandObjectTargetModulesSourceFileAutoComplete(
2405 interpreter, "target modules dump line-table",
2406 "Dump the line table for one or more compilation units.", nullptr,
2407 eCommandRequiresTarget) {}
2408
2409 ~CommandObjectTargetModulesDumpLineTable() override = default;
2410
2411 Options *GetOptions() override { return &m_options; }
2412
2413protected:
2414 void DoExecute(Args &command, CommandReturnObject &result) override {
2415 Target *target = m_exe_ctx.GetTargetPtr();
2416 uint32_t total_num_dumped = 0;
2417
2418 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2419 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2420 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2421
2422 if (command.GetArgumentCount() == 0) {
2423 result.AppendError(in_string: "file option must be specified.");
2424 return;
2425 } else {
2426 // Dump specified images (by basename or fullpath)
2427 const char *arg_cstr;
2428 for (int arg_idx = 0;
2429 (arg_cstr = command.GetArgumentAtIndex(idx: arg_idx)) != nullptr;
2430 ++arg_idx) {
2431 FileSpec file_spec(arg_cstr);
2432
2433 const ModuleList &target_modules = target->GetImages();
2434 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2435 size_t num_modules = target_modules.GetSize();
2436 if (num_modules > 0) {
2437 uint32_t num_dumped = 0;
2438 for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
2439 if (INTERRUPT_REQUESTED(GetDebugger(),
2440 "Interrupted in dump all line tables with "
2441 "{0} of {1} dumped", num_dumped,
2442 num_modules))
2443 break;
2444
2445 if (DumpCompileUnitLineTable(
2446 interpreter&: m_interpreter, strm&: result.GetOutputStream(), module: module_sp.get(),
2447 file_spec,
2448 desc_level: m_options.m_verbose ? eDescriptionLevelFull
2449 : eDescriptionLevelBrief))
2450 num_dumped++;
2451 }
2452 if (num_dumped == 0)
2453 result.AppendWarningWithFormat(
2454 format: "No source filenames matched '%s'.\n", arg_cstr);
2455 else
2456 total_num_dumped += num_dumped;
2457 }
2458 }
2459 }
2460
2461 if (total_num_dumped > 0)
2462 result.SetStatus(eReturnStatusSuccessFinishResult);
2463 else {
2464 result.AppendError(in_string: "no source filenames matched any command arguments");
2465 }
2466 }
2467
2468 class CommandOptions : public Options {
2469 public:
2470 CommandOptions() { OptionParsingStarting(execution_context: nullptr); }
2471
2472 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2473 ExecutionContext *execution_context) override {
2474 assert(option_idx == 0 && "We only have one option.");
2475 m_verbose = true;
2476
2477 return Status();
2478 }
2479
2480 void OptionParsingStarting(ExecutionContext *execution_context) override {
2481 m_verbose = false;
2482 }
2483
2484 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2485 return llvm::ArrayRef(g_target_modules_dump_options);
2486 }
2487
2488 bool m_verbose;
2489 };
2490
2491 CommandOptions m_options;
2492};
2493
2494#pragma mark CommandObjectTargetModulesDumpSeparateDebugInfoFiles
2495#define LLDB_OPTIONS_target_modules_dump_separate_debug_info
2496#include "CommandOptions.inc"
2497
2498// Image debug separate debug info dumping command
2499
2500class CommandObjectTargetModulesDumpSeparateDebugInfoFiles
2501 : public CommandObjectTargetModulesModuleAutoComplete {
2502public:
2503 CommandObjectTargetModulesDumpSeparateDebugInfoFiles(
2504 CommandInterpreter &interpreter)
2505 : CommandObjectTargetModulesModuleAutoComplete(
2506 interpreter, "target modules dump separate-debug-info",
2507 "List the separate debug info symbol files for one or more target "
2508 "modules.",
2509 nullptr, eCommandRequiresTarget) {}
2510
2511 ~CommandObjectTargetModulesDumpSeparateDebugInfoFiles() override = default;
2512
2513 Options *GetOptions() override { return &m_options; }
2514
2515 class CommandOptions : public Options {
2516 public:
2517 CommandOptions() = default;
2518
2519 ~CommandOptions() override = default;
2520
2521 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2522 ExecutionContext *execution_context) override {
2523 Status error;
2524 const int short_option = m_getopt_table[option_idx].val;
2525
2526 switch (short_option) {
2527 case 'f':
2528 m_load_all_debug_info.SetCurrentValue(true);
2529 m_load_all_debug_info.SetOptionWasSet();
2530 break;
2531 case 'j':
2532 m_json.SetCurrentValue(true);
2533 m_json.SetOptionWasSet();
2534 break;
2535 case 'e':
2536 m_errors_only.SetCurrentValue(true);
2537 m_errors_only.SetOptionWasSet();
2538 break;
2539 default:
2540 llvm_unreachable("Unimplemented option");
2541 }
2542 return error;
2543 }
2544
2545 void OptionParsingStarting(ExecutionContext *execution_context) override {
2546 m_json.Clear();
2547 m_errors_only.Clear();
2548 m_load_all_debug_info.Clear();
2549 }
2550
2551 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2552 return llvm::ArrayRef(g_target_modules_dump_separate_debug_info_options);
2553 }
2554
2555 OptionValueBoolean m_json = false;
2556 OptionValueBoolean m_errors_only = false;
2557 OptionValueBoolean m_load_all_debug_info = false;
2558 };
2559
2560protected:
2561 void DoExecute(Args &command, CommandReturnObject &result) override {
2562 Target &target = GetTarget();
2563 uint32_t num_dumped = 0;
2564
2565 uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize();
2566 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2567 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2568
2569 StructuredData::Array separate_debug_info_lists_by_module;
2570 if (command.GetArgumentCount() == 0) {
2571 // Dump all sections for all modules images
2572 const ModuleList &target_modules = target.GetImages();
2573 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2574 const size_t num_modules = target_modules.GetSize();
2575 if (num_modules == 0) {
2576 result.AppendError(in_string: "the target has no associated executable images");
2577 return;
2578 }
2579 for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
2580 if (INTERRUPT_REQUESTED(
2581 GetDebugger(),
2582 "Interrupted in dumping all "
2583 "separate debug info with {0} of {1} modules dumped",
2584 num_dumped, num_modules))
2585 break;
2586
2587 if (GetSeparateDebugInfoList(list&: separate_debug_info_lists_by_module,
2588 module: module_sp.get(),
2589 errors_only: bool(m_options.m_errors_only),
2590 load_all_debug_info: bool(m_options.m_load_all_debug_info)))
2591 num_dumped++;
2592 }
2593 } else {
2594 // Dump specified images (by basename or fullpath)
2595 const char *arg_cstr;
2596 for (int arg_idx = 0;
2597 (arg_cstr = command.GetArgumentAtIndex(idx: arg_idx)) != nullptr;
2598 ++arg_idx) {
2599 ModuleList module_list;
2600 const size_t num_matches =
2601 FindModulesByName(target: &target, module_name: arg_cstr, module_list, check_global_list: true);
2602 if (num_matches > 0) {
2603 for (size_t i = 0; i < num_matches; ++i) {
2604 if (INTERRUPT_REQUESTED(GetDebugger(),
2605 "Interrupted dumping {0} "
2606 "of {1} requested modules",
2607 i, num_matches))
2608 break;
2609 Module *module = module_list.GetModulePointerAtIndex(idx: i);
2610 if (GetSeparateDebugInfoList(list&: separate_debug_info_lists_by_module,
2611 module, errors_only: bool(m_options.m_errors_only),
2612 load_all_debug_info: bool(m_options.m_load_all_debug_info)))
2613 num_dumped++;
2614 }
2615 } else
2616 result.AppendWarningWithFormat(
2617 format: "Unable to find an image that matches '%s'.\n", arg_cstr);
2618 }
2619 }
2620
2621 if (num_dumped > 0) {
2622 Stream &strm = result.GetOutputStream();
2623 // Display the debug info files in some format.
2624 if (m_options.m_json) {
2625 // JSON format
2626 separate_debug_info_lists_by_module.Dump(s&: strm,
2627 /*pretty_print=*/true);
2628 } else {
2629 // Human-readable table format
2630 separate_debug_info_lists_by_module.ForEach(
2631 foreach_callback: [&result, &strm](StructuredData::Object *obj) {
2632 if (!obj) {
2633 return false;
2634 }
2635
2636 // Each item in `separate_debug_info_lists_by_module` should be a
2637 // valid structured data dictionary.
2638 StructuredData::Dictionary *separate_debug_info_list =
2639 obj->GetAsDictionary();
2640 if (!separate_debug_info_list) {
2641 return false;
2642 }
2643
2644 llvm::StringRef type;
2645 llvm::StringRef symfile;
2646 StructuredData::Array *files;
2647 if (!(separate_debug_info_list->GetValueForKeyAsString(key: "type",
2648 result&: type) &&
2649 separate_debug_info_list->GetValueForKeyAsString(key: "symfile",
2650 result&: symfile) &&
2651 separate_debug_info_list->GetValueForKeyAsArray(
2652 key: "separate-debug-info-files", result&: files))) {
2653 assert(false);
2654 }
2655
2656 strm << "Symbol file: " << symfile;
2657 strm.EOL();
2658 strm << "Type: \"" << type << "\"";
2659 strm.EOL();
2660 if (type == "dwo") {
2661 DumpDwoFilesTable(strm, dwo_listings&: *files);
2662 } else if (type == "oso") {
2663 DumpOsoFilesTable(strm, oso_listings&: *files);
2664 } else {
2665 result.AppendWarningWithFormat(
2666 format: "Found unsupported debug info type '%s'.\n",
2667 type.str().c_str());
2668 }
2669 return true;
2670 });
2671 }
2672 result.SetStatus(eReturnStatusSuccessFinishResult);
2673 } else {
2674 result.AppendError(in_string: "no matching executable images found");
2675 }
2676 }
2677
2678 CommandOptions m_options;
2679};
2680
2681#pragma mark CommandObjectTargetModulesDump
2682
2683// Dump multi-word command for target modules
2684
2685class CommandObjectTargetModulesDump : public CommandObjectMultiword {
2686public:
2687 // Constructors and Destructors
2688 CommandObjectTargetModulesDump(CommandInterpreter &interpreter)
2689 : CommandObjectMultiword(
2690 interpreter, "target modules dump",
2691 "Commands for dumping information about one or more target "
2692 "modules.",
2693 "target modules dump "
2694 "[objfile|symtab|sections|ast|symfile|line-table|pcm-info|separate-"
2695 "debug-info] "
2696 "[<file1> <file2> ...]") {
2697 LoadSubCommand(cmd_name: "objfile",
2698 command_obj: CommandObjectSP(
2699 new CommandObjectTargetModulesDumpObjfile(interpreter)));
2700 LoadSubCommand(
2701 cmd_name: "symtab",
2702 command_obj: CommandObjectSP(new CommandObjectTargetModulesDumpSymtab(interpreter)));
2703 LoadSubCommand(cmd_name: "sections",
2704 command_obj: CommandObjectSP(new CommandObjectTargetModulesDumpSections(
2705 interpreter)));
2706 LoadSubCommand(cmd_name: "symfile",
2707 command_obj: CommandObjectSP(
2708 new CommandObjectTargetModulesDumpSymfile(interpreter)));
2709 LoadSubCommand(
2710 cmd_name: "ast", command_obj: CommandObjectSP(
2711 new CommandObjectTargetModulesDumpClangAST(interpreter)));
2712 LoadSubCommand(cmd_name: "line-table",
2713 command_obj: CommandObjectSP(new CommandObjectTargetModulesDumpLineTable(
2714 interpreter)));
2715 LoadSubCommand(
2716 cmd_name: "pcm-info",
2717 command_obj: CommandObjectSP(
2718 new CommandObjectTargetModulesDumpClangPCMInfo(interpreter)));
2719 LoadSubCommand(cmd_name: "separate-debug-info",
2720 command_obj: CommandObjectSP(
2721 new CommandObjectTargetModulesDumpSeparateDebugInfoFiles(
2722 interpreter)));
2723 }
2724
2725 ~CommandObjectTargetModulesDump() override = default;
2726};
2727
2728class CommandObjectTargetModulesAdd : public CommandObjectParsed {
2729public:
2730 CommandObjectTargetModulesAdd(CommandInterpreter &interpreter)
2731 : CommandObjectParsed(interpreter, "target modules add",
2732 "Add a new module to the current target's modules.",
2733 "target modules add [<module>]",
2734 eCommandRequiresTarget),
2735 m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
2736 eArgTypeFilename,
2737 "Fullpath to a stand alone debug "
2738 "symbols file for when debug symbols "
2739 "are not in the executable.") {
2740 m_option_group.Append(group: &m_uuid_option_group, LLDB_OPT_SET_ALL,
2741 LLDB_OPT_SET_1);
2742 m_option_group.Append(group: &m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2743 m_option_group.Finalize();
2744 AddSimpleArgumentList(arg_type: eArgTypePath, repetition_type: eArgRepeatStar);
2745 }
2746
2747 ~CommandObjectTargetModulesAdd() override = default;
2748
2749 Options *GetOptions() override { return &m_option_group; }
2750
2751protected:
2752 OptionGroupOptions m_option_group;
2753 OptionGroupUUID m_uuid_option_group;
2754 OptionGroupFile m_symbol_file;
2755
2756 void DoExecute(Args &args, CommandReturnObject &result) override {
2757 Target &target = GetTarget();
2758 bool flush = false;
2759
2760 const size_t argc = args.GetArgumentCount();
2761 if (argc == 0) {
2762 if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2763 // We are given a UUID only, go locate the file
2764 ModuleSpec module_spec;
2765 module_spec.GetUUID() =
2766 m_uuid_option_group.GetOptionValue().GetCurrentValue();
2767 if (m_symbol_file.GetOptionValue().OptionWasSet())
2768 module_spec.GetSymbolFileSpec() =
2769 m_symbol_file.GetOptionValue().GetCurrentValue();
2770 Status error;
2771 if (PluginManager::DownloadObjectAndSymbolFile(module_spec, error)) {
2772 ModuleSP module_sp(
2773 target.GetOrCreateModule(module_spec, notify: true /* notify */));
2774 if (module_sp) {
2775 result.SetStatus(eReturnStatusSuccessFinishResult);
2776 return;
2777 } else {
2778 StreamString strm;
2779 module_spec.GetUUID().Dump(s&: strm);
2780 if (module_spec.GetFileSpec()) {
2781 if (module_spec.GetSymbolFileSpec()) {
2782 result.AppendErrorWithFormat(
2783 format: "Unable to create the executable or symbol file with "
2784 "UUID %s with path %s and symbol file %s",
2785 strm.GetData(), module_spec.GetFileSpec().GetPath().c_str(),
2786 module_spec.GetSymbolFileSpec().GetPath().c_str());
2787 } else {
2788 result.AppendErrorWithFormat(
2789 format: "Unable to create the executable or symbol file with "
2790 "UUID %s with path %s",
2791 strm.GetData(),
2792 module_spec.GetFileSpec().GetPath().c_str());
2793 }
2794 } else {
2795 result.AppendErrorWithFormat(format: "Unable to create the executable "
2796 "or symbol file with UUID %s",
2797 strm.GetData());
2798 }
2799 return;
2800 }
2801 } else {
2802 StreamString strm;
2803 module_spec.GetUUID().Dump(s&: strm);
2804 result.AppendErrorWithFormat(
2805 format: "Unable to locate the executable or symbol file with UUID %s",
2806 strm.GetData());
2807 result.SetError(std::move(error));
2808 return;
2809 }
2810 } else {
2811 result.AppendError(
2812 in_string: "one or more executable image paths must be specified");
2813 return;
2814 }
2815 } else {
2816 for (auto &entry : args.entries()) {
2817 if (entry.ref().empty())
2818 continue;
2819
2820 FileSpec file_spec(entry.ref());
2821 if (FileSystem::Instance().Exists(file_spec)) {
2822 ModuleSpec module_spec(file_spec);
2823 if (m_uuid_option_group.GetOptionValue().OptionWasSet())
2824 module_spec.GetUUID() =
2825 m_uuid_option_group.GetOptionValue().GetCurrentValue();
2826 if (m_symbol_file.GetOptionValue().OptionWasSet())
2827 module_spec.GetSymbolFileSpec() =
2828 m_symbol_file.GetOptionValue().GetCurrentValue();
2829 if (!module_spec.GetArchitecture().IsValid())
2830 module_spec.GetArchitecture() = target.GetArchitecture();
2831 Status error;
2832 ModuleSP module_sp(
2833 target.GetOrCreateModule(module_spec, notify: true /* notify */, error_ptr: &error));
2834 if (!module_sp) {
2835 const char *error_cstr = error.AsCString();
2836 if (error_cstr)
2837 result.AppendError(in_string: error_cstr);
2838 else
2839 result.AppendErrorWithFormat(format: "unsupported module: %s",
2840 entry.c_str());
2841 return;
2842 } else {
2843 flush = true;
2844 }
2845 result.SetStatus(eReturnStatusSuccessFinishResult);
2846 } else {
2847 std::string resolved_path = file_spec.GetPath();
2848 if (resolved_path != entry.ref()) {
2849 result.AppendErrorWithFormat(
2850 format: "invalid module path '%s' with resolved path '%s'\n",
2851 entry.ref().str().c_str(), resolved_path.c_str());
2852 break;
2853 }
2854 result.AppendErrorWithFormat(format: "invalid module path '%s'\n",
2855 entry.c_str());
2856 break;
2857 }
2858 }
2859 }
2860
2861 if (flush) {
2862 ProcessSP process = target.GetProcessSP();
2863 if (process)
2864 process->Flush();
2865 }
2866 }
2867};
2868
2869class CommandObjectTargetModulesLoad
2870 : public CommandObjectTargetModulesModuleAutoComplete {
2871public:
2872 CommandObjectTargetModulesLoad(CommandInterpreter &interpreter)
2873 : CommandObjectTargetModulesModuleAutoComplete(
2874 interpreter, "target modules load",
2875 "Set the load addresses for one or more sections in a target "
2876 "module.",
2877 "target modules load [--file <module> --uuid <uuid>] <sect-name> "
2878 "<address> [<sect-name> <address> ....]",
2879 eCommandRequiresTarget),
2880 m_file_option(LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName,
2881 "Fullpath or basename for module to load.", ""),
2882 m_load_option(LLDB_OPT_SET_1, false, "load", 'l',
2883 "Write file contents to the memory.", false, true),
2884 m_pc_option(LLDB_OPT_SET_1, false, "set-pc-to-entry", 'p',
2885 "Set PC to the entry point."
2886 " Only applicable with '--load' option.",
2887 false, true),
2888 m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset,
2889 "Set the load address for all sections to be the "
2890 "virtual address in the file plus the offset.",
2891 0) {
2892 m_option_group.Append(group: &m_uuid_option_group, LLDB_OPT_SET_ALL,
2893 LLDB_OPT_SET_1);
2894 m_option_group.Append(group: &m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2895 m_option_group.Append(group: &m_load_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2896 m_option_group.Append(group: &m_pc_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2897 m_option_group.Append(group: &m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2898 m_option_group.Finalize();
2899 }
2900
2901 ~CommandObjectTargetModulesLoad() override = default;
2902
2903 Options *GetOptions() override { return &m_option_group; }
2904
2905protected:
2906 void DoExecute(Args &args, CommandReturnObject &result) override {
2907 Target &target = GetTarget();
2908 const bool load = m_load_option.GetOptionValue().GetCurrentValue();
2909 const bool set_pc = m_pc_option.GetOptionValue().GetCurrentValue();
2910
2911 const size_t argc = args.GetArgumentCount();
2912 ModuleSpec module_spec;
2913 bool search_using_module_spec = false;
2914
2915 // Allow "load" option to work without --file or --uuid option.
2916 if (load) {
2917 if (!m_file_option.GetOptionValue().OptionWasSet() &&
2918 !m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2919 ModuleList &module_list = target.GetImages();
2920 if (module_list.GetSize() == 1) {
2921 search_using_module_spec = true;
2922 module_spec.GetFileSpec() =
2923 module_list.GetModuleAtIndex(idx: 0)->GetFileSpec();
2924 }
2925 }
2926 }
2927
2928 if (m_file_option.GetOptionValue().OptionWasSet()) {
2929 search_using_module_spec = true;
2930 const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue();
2931 const bool use_global_module_list = true;
2932 ModuleList module_list;
2933 const size_t num_matches = FindModulesByName(
2934 target: &target, module_name: arg_cstr, module_list, check_global_list: use_global_module_list);
2935 if (num_matches == 1) {
2936 module_spec.GetFileSpec() =
2937 module_list.GetModuleAtIndex(idx: 0)->GetFileSpec();
2938 } else if (num_matches > 1) {
2939 search_using_module_spec = false;
2940 result.AppendErrorWithFormat(
2941 format: "more than 1 module matched by name '%s'\n", arg_cstr);
2942 } else {
2943 search_using_module_spec = false;
2944 result.AppendErrorWithFormat(format: "no object file for module '%s'\n",
2945 arg_cstr);
2946 }
2947 }
2948
2949 if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2950 search_using_module_spec = true;
2951 module_spec.GetUUID() =
2952 m_uuid_option_group.GetOptionValue().GetCurrentValue();
2953 }
2954
2955 if (search_using_module_spec) {
2956 ModuleList matching_modules;
2957 target.GetImages().FindModules(module_spec, matching_module_list&: matching_modules);
2958 const size_t num_matches = matching_modules.GetSize();
2959
2960 char path[PATH_MAX];
2961 if (num_matches == 1) {
2962 Module *module = matching_modules.GetModulePointerAtIndex(idx: 0);
2963 if (module) {
2964 ObjectFile *objfile = module->GetObjectFile();
2965 if (objfile) {
2966 SectionList *section_list = module->GetSectionList();
2967 if (section_list) {
2968 bool changed = false;
2969 if (argc == 0) {
2970 if (m_slide_option.GetOptionValue().OptionWasSet()) {
2971 const addr_t slide =
2972 m_slide_option.GetOptionValue().GetCurrentValue();
2973 const bool slide_is_offset = true;
2974 module->SetLoadAddress(target, value: slide, value_is_offset: slide_is_offset,
2975 changed);
2976 } else {
2977 result.AppendError(in_string: "one or more section name + load "
2978 "address pair must be specified");
2979 return;
2980 }
2981 } else {
2982 if (m_slide_option.GetOptionValue().OptionWasSet()) {
2983 result.AppendError(in_string: "The \"--slide <offset>\" option can't "
2984 "be used in conjunction with setting "
2985 "section load addresses.\n");
2986 return;
2987 }
2988
2989 for (size_t i = 0; i < argc; i += 2) {
2990 const char *sect_name = args.GetArgumentAtIndex(idx: i);
2991 const char *load_addr_cstr = args.GetArgumentAtIndex(idx: i + 1);
2992 if (sect_name && load_addr_cstr) {
2993 ConstString const_sect_name(sect_name);
2994 addr_t load_addr;
2995 if (llvm::to_integer(S: load_addr_cstr, Num&: load_addr)) {
2996 SectionSP section_sp(
2997 section_list->FindSectionByName(section_dstr: const_sect_name));
2998 if (section_sp) {
2999 if (section_sp->IsThreadSpecific()) {
3000 result.AppendErrorWithFormat(
3001 format: "thread specific sections are not yet "
3002 "supported (section '%s')\n",
3003 sect_name);
3004 break;
3005 } else {
3006 if (target.SetSectionLoadAddress(section: section_sp,
3007 load_addr))
3008 changed = true;
3009 result.AppendMessageWithFormat(
3010 format: "section '%s' loaded at 0x%" PRIx64 "\n",
3011 sect_name, load_addr);
3012 }
3013 } else {
3014 result.AppendErrorWithFormat(format: "no section found that "
3015 "matches the section "
3016 "name '%s'\n",
3017 sect_name);
3018 break;
3019 }
3020 } else {
3021 result.AppendErrorWithFormat(
3022 format: "invalid load address string '%s'\n", load_addr_cstr);
3023 break;
3024 }
3025 } else {
3026 if (sect_name)
3027 result.AppendError(in_string: "section names must be followed by "
3028 "a load address.\n");
3029 else
3030 result.AppendError(in_string: "one or more section name + load "
3031 "address pair must be specified.\n");
3032 break;
3033 }
3034 }
3035 }
3036
3037 if (changed) {
3038 target.ModulesDidLoad(module_list&: matching_modules);
3039 Process *process = m_exe_ctx.GetProcessPtr();
3040 if (process)
3041 process->Flush();
3042 }
3043 if (load) {
3044 ProcessSP process = target.CalculateProcess();
3045 Address file_entry = objfile->GetEntryPointAddress();
3046 if (!process) {
3047 result.AppendError(in_string: "No process");
3048 return;
3049 }
3050 if (set_pc && !file_entry.IsValid()) {
3051 result.AppendError(in_string: "No entry address in object file");
3052 return;
3053 }
3054 std::vector<ObjectFile::LoadableData> loadables(
3055 objfile->GetLoadableData(target));
3056 if (loadables.size() == 0) {
3057 result.AppendError(in_string: "No loadable sections");
3058 return;
3059 }
3060 Status error = process->WriteObjectFile(entries: std::move(loadables));
3061 if (error.Fail()) {
3062 result.AppendError(in_string: error.AsCString());
3063 return;
3064 }
3065 if (set_pc) {
3066 ThreadList &thread_list = process->GetThreadList();
3067 RegisterContextSP reg_context(
3068 thread_list.GetSelectedThread()->GetRegisterContext());
3069 addr_t file_entry_addr = file_entry.GetLoadAddress(target: &target);
3070 if (!reg_context->SetPC(file_entry_addr)) {
3071 result.AppendErrorWithFormat(format: "failed to set PC value to "
3072 "0x%" PRIx64 "\n",
3073 file_entry_addr);
3074 }
3075 }
3076 }
3077 } else {
3078 module->GetFileSpec().GetPath(path, max_path_length: sizeof(path));
3079 result.AppendErrorWithFormat(format: "no sections in object file '%s'\n",
3080 path);
3081 }
3082 } else {
3083 module->GetFileSpec().GetPath(path, max_path_length: sizeof(path));
3084 result.AppendErrorWithFormat(format: "no object file for module '%s'\n",
3085 path);
3086 }
3087 } else {
3088 FileSpec *module_spec_file = module_spec.GetFileSpecPtr();
3089 if (module_spec_file) {
3090 module_spec_file->GetPath(path, max_path_length: sizeof(path));
3091 result.AppendErrorWithFormat(format: "invalid module '%s'.\n", path);
3092 } else
3093 result.AppendError(in_string: "no module spec");
3094 }
3095 } else {
3096 std::string uuid_str;
3097
3098 if (module_spec.GetFileSpec())
3099 module_spec.GetFileSpec().GetPath(path, max_path_length: sizeof(path));
3100 else
3101 path[0] = '\0';
3102
3103 if (module_spec.GetUUIDPtr())
3104 uuid_str = module_spec.GetUUID().GetAsString();
3105 if (num_matches > 1) {
3106 result.AppendErrorWithFormat(
3107 format: "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "",
3108 path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str());
3109 for (size_t i = 0; i < num_matches; ++i) {
3110 if (matching_modules.GetModulePointerAtIndex(idx: i)
3111 ->GetFileSpec()
3112 .GetPath(path, max_path_length: sizeof(path)))
3113 result.AppendMessageWithFormat(format: "%s\n", path);
3114 }
3115 } else {
3116 result.AppendErrorWithFormat(
3117 format: "no modules were found that match%s%s%s%s.\n",
3118 path[0] ? " file=" : "", path, !uuid_str.empty() ? " uuid=" : "",
3119 uuid_str.c_str());
3120 }
3121 }
3122 } else {
3123 result.AppendError(in_string: "either the \"--file <module>\" or the \"--uuid "
3124 "<uuid>\" option must be specified.\n");
3125 }
3126 }
3127
3128 OptionGroupOptions m_option_group;
3129 OptionGroupUUID m_uuid_option_group;
3130 OptionGroupString m_file_option;
3131 OptionGroupBoolean m_load_option;
3132 OptionGroupBoolean m_pc_option;
3133 OptionGroupUInt64 m_slide_option;
3134};
3135
3136#pragma mark CommandObjectTargetModulesList
3137// List images with associated information
3138#define LLDB_OPTIONS_target_modules_list
3139#include "CommandOptions.inc"
3140
3141class CommandObjectTargetModulesList : public CommandObjectParsed {
3142public:
3143 class CommandOptions : public Options {
3144 public:
3145 CommandOptions() = default;
3146
3147 ~CommandOptions() override = default;
3148
3149 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3150 ExecutionContext *execution_context) override {
3151 Status error;
3152
3153 const int short_option = m_getopt_table[option_idx].val;
3154 if (short_option == 'g') {
3155 m_use_global_module_list = true;
3156 } else if (short_option == 'a') {
3157 m_module_addr = OptionArgParser::ToAddress(
3158 exe_ctx: execution_context, s: option_arg, LLDB_INVALID_ADDRESS, error_ptr: &error);
3159 } else {
3160 unsigned long width = 0;
3161 option_arg.getAsInteger(Radix: 0, Result&: width);
3162 m_format_array.push_back(x: std::make_pair(x: short_option, y&: width));
3163 }
3164 return error;
3165 }
3166
3167 void OptionParsingStarting(ExecutionContext *execution_context) override {
3168 m_format_array.clear();
3169 m_use_global_module_list = false;
3170 m_module_addr = LLDB_INVALID_ADDRESS;
3171 }
3172
3173 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3174 return llvm::ArrayRef(g_target_modules_list_options);
3175 }
3176
3177 // Instance variables to hold the values for command options.
3178 typedef std::vector<std::pair<char, uint32_t>> FormatWidthCollection;
3179 FormatWidthCollection m_format_array;
3180 bool m_use_global_module_list = false;
3181 lldb::addr_t m_module_addr = LLDB_INVALID_ADDRESS;
3182 };
3183
3184 CommandObjectTargetModulesList(CommandInterpreter &interpreter)
3185 : CommandObjectParsed(
3186 interpreter, "target modules list",
3187 "List current executable and dependent shared library images.") {
3188 AddSimpleArgumentList(arg_type: eArgTypeModule, repetition_type: eArgRepeatStar);
3189 }
3190
3191 ~CommandObjectTargetModulesList() override = default;
3192
3193 Options *GetOptions() override { return &m_options; }
3194
3195protected:
3196 void DoExecute(Args &command, CommandReturnObject &result) override {
3197 Target &target = GetTarget();
3198 const bool use_global_module_list = m_options.m_use_global_module_list;
3199 // Define a local module list here to ensure it lives longer than any
3200 // "locker" object which might lock its contents below (through the
3201 // "module_list_ptr" variable).
3202 ModuleList module_list;
3203 uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize();
3204 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
3205 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
3206 // Dump all sections for all modules images
3207 Stream &strm = result.GetOutputStream();
3208
3209 if (m_options.m_module_addr != LLDB_INVALID_ADDRESS) {
3210 Address module_address;
3211 if (module_address.SetLoadAddress(load_addr: m_options.m_module_addr, target: &target)) {
3212 ModuleSP module_sp(module_address.GetModule());
3213 if (module_sp) {
3214 PrintModule(target, module: module_sp.get(), indent: 0, strm);
3215 result.SetStatus(eReturnStatusSuccessFinishResult);
3216 } else {
3217 result.AppendErrorWithFormat(
3218 format: "Couldn't find module matching address: 0x%" PRIx64 ".",
3219 m_options.m_module_addr);
3220 }
3221 } else {
3222 result.AppendErrorWithFormat(
3223 format: "Couldn't find module containing address: 0x%" PRIx64 ".",
3224 m_options.m_module_addr);
3225 }
3226 return;
3227 }
3228
3229 size_t num_modules = 0;
3230
3231 // This locker will be locked on the mutex in module_list_ptr if it is
3232 // non-nullptr. Otherwise it will lock the
3233 // AllocationModuleCollectionMutex when accessing the global module list
3234 // directly.
3235 std::unique_lock<std::recursive_mutex> guard(
3236 Module::GetAllocationModuleCollectionMutex(), std::defer_lock);
3237
3238 const ModuleList *module_list_ptr = nullptr;
3239 const size_t argc = command.GetArgumentCount();
3240 if (argc == 0) {
3241 if (use_global_module_list) {
3242 guard.lock();
3243 num_modules = Module::GetNumberAllocatedModules();
3244 } else {
3245 module_list_ptr = &target.GetImages();
3246 }
3247 } else {
3248 for (const Args::ArgEntry &arg : command) {
3249 // Dump specified images (by basename or fullpath)
3250 const size_t num_matches = FindModulesByName(
3251 target: &target, module_name: arg.c_str(), module_list, check_global_list: use_global_module_list);
3252 if (num_matches == 0) {
3253 if (argc == 1) {
3254 result.AppendErrorWithFormat(format: "no modules found that match '%s'",
3255 arg.c_str());
3256 return;
3257 }
3258 }
3259 }
3260
3261 module_list_ptr = &module_list;
3262 }
3263
3264 std::unique_lock<std::recursive_mutex> lock;
3265 if (module_list_ptr != nullptr) {
3266 lock =
3267 std::unique_lock<std::recursive_mutex>(module_list_ptr->GetMutex());
3268
3269 num_modules = module_list_ptr->GetSize();
3270 }
3271
3272 if (num_modules > 0) {
3273 for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
3274 ModuleSP module_sp;
3275 Module *module;
3276 if (module_list_ptr) {
3277 module_sp = module_list_ptr->GetModuleAtIndexUnlocked(idx: image_idx);
3278 module = module_sp.get();
3279 } else {
3280 module = Module::GetAllocatedModuleAtIndex(idx: image_idx);
3281 module_sp = module->shared_from_this();
3282 }
3283
3284 const size_t indent = strm.Printf(format: "[%3u] ", image_idx);
3285 PrintModule(target, module, indent, strm);
3286 }
3287 result.SetStatus(eReturnStatusSuccessFinishResult);
3288 } else {
3289 if (argc) {
3290 if (use_global_module_list)
3291 result.AppendError(
3292 in_string: "the global module list has no matching modules");
3293 else
3294 result.AppendError(in_string: "the target has no matching modules");
3295 } else {
3296 if (use_global_module_list)
3297 result.AppendError(in_string: "the global module list is empty");
3298 else
3299 result.AppendError(
3300 in_string: "the target has no associated executable images");
3301 }
3302 return;
3303 }
3304 }
3305
3306 void PrintModule(Target &target, Module *module, int indent, Stream &strm) {
3307 if (module == nullptr) {
3308 strm.PutCString(cstr: "Null module");
3309 return;
3310 }
3311
3312 bool dump_object_name = false;
3313 if (m_options.m_format_array.empty()) {
3314 m_options.m_format_array.push_back(x: std::make_pair(x: 'u', y: 0));
3315 m_options.m_format_array.push_back(x: std::make_pair(x: 'h', y: 0));
3316 m_options.m_format_array.push_back(x: std::make_pair(x: 'f', y: 0));
3317 m_options.m_format_array.push_back(x: std::make_pair(x: 'S', y: 0));
3318 }
3319 const size_t num_entries = m_options.m_format_array.size();
3320 bool print_space = false;
3321 for (size_t i = 0; i < num_entries; ++i) {
3322 if (print_space)
3323 strm.PutChar(ch: ' ');
3324 print_space = true;
3325 const char format_char = m_options.m_format_array[i].first;
3326 uint32_t width = m_options.m_format_array[i].second;
3327 switch (format_char) {
3328 case 'A':
3329 DumpModuleArchitecture(strm, module, full_triple: false, width);
3330 break;
3331
3332 case 't':
3333 DumpModuleArchitecture(strm, module, full_triple: true, width);
3334 break;
3335
3336 case 'f':
3337 DumpFullpath(strm, file_spec_ptr: &module->GetFileSpec(), width);
3338 dump_object_name = true;
3339 break;
3340
3341 case 'd':
3342 DumpDirectory(strm, file_spec_ptr: &module->GetFileSpec(), width);
3343 break;
3344
3345 case 'b':
3346 DumpBasename(strm, file_spec_ptr: &module->GetFileSpec(), width);
3347 dump_object_name = true;
3348 break;
3349
3350 case 'h':
3351 case 'o':
3352 // Image header address
3353 {
3354 uint32_t addr_nibble_width =
3355 target.GetArchitecture().GetAddressByteSize() * 2;
3356
3357 ObjectFile *objfile = module->GetObjectFile();
3358 if (objfile) {
3359 Address base_addr(objfile->GetBaseAddress());
3360 if (base_addr.IsValid()) {
3361 if (target.HasLoadedSections()) {
3362 lldb::addr_t load_addr = base_addr.GetLoadAddress(target: &target);
3363 if (load_addr == LLDB_INVALID_ADDRESS) {
3364 base_addr.Dump(s: &strm, exe_scope: &target,
3365 style: Address::DumpStyleModuleWithFileAddress,
3366 fallback_style: Address::DumpStyleFileAddress);
3367 } else {
3368 if (format_char == 'o') {
3369 // Show the offset of slide for the image
3370 strm.Printf(format: "0x%*.*" PRIx64, addr_nibble_width,
3371 addr_nibble_width,
3372 load_addr - base_addr.GetFileAddress());
3373 } else {
3374 // Show the load address of the image
3375 strm.Printf(format: "0x%*.*" PRIx64, addr_nibble_width,
3376 addr_nibble_width, load_addr);
3377 }
3378 }
3379 break;
3380 }
3381 // The address was valid, but the image isn't loaded, output the
3382 // address in an appropriate format
3383 base_addr.Dump(s: &strm, exe_scope: &target, style: Address::DumpStyleFileAddress);
3384 break;
3385 }
3386 }
3387 strm.Printf(format: "%*s", addr_nibble_width + 2, "");
3388 }
3389 break;
3390
3391 case 'r': {
3392 size_t ref_count = 0;
3393 char in_shared_cache = 'Y';
3394
3395 ModuleSP module_sp(module->shared_from_this());
3396 if (!ModuleList::ModuleIsInCache(module_ptr: module))
3397 in_shared_cache = 'N';
3398 if (module_sp) {
3399 // Take one away to make sure we don't count our local "module_sp"
3400 ref_count = module_sp.use_count() - 1;
3401 }
3402 if (width)
3403 strm.Printf(format: "{%c %*" PRIu64 "}", in_shared_cache, width, (uint64_t)ref_count);
3404 else
3405 strm.Printf(format: "{%c %" PRIu64 "}", in_shared_cache, (uint64_t)ref_count);
3406 } break;
3407
3408 case 's':
3409 case 'S': {
3410 if (const SymbolFile *symbol_file = module->GetSymbolFile()) {
3411 const FileSpec symfile_spec =
3412 symbol_file->GetObjectFile()->GetFileSpec();
3413 if (format_char == 'S') {
3414 // Dump symbol file only if different from module file
3415 if (!symfile_spec || symfile_spec == module->GetFileSpec()) {
3416 print_space = false;
3417 break;
3418 }
3419 // Add a newline and indent past the index
3420 strm.Printf(format: "\n%*s", indent, "");
3421 }
3422 DumpFullpath(strm, file_spec_ptr: &symfile_spec, width);
3423 dump_object_name = true;
3424 break;
3425 }
3426 strm.Printf(format: "%.*s", width, "<NONE>");
3427 } break;
3428
3429 case 'm':
3430 strm.Format(format: "{0:%c}", args: llvm::fmt_align(Item: module->GetModificationTime(),
3431 Where: llvm::AlignStyle::Left, Amount: width));
3432 break;
3433
3434 case 'p':
3435 strm.Printf(format: "%p", static_cast<void *>(module));
3436 break;
3437
3438 case 'u':
3439 DumpModuleUUID(strm, module);
3440 break;
3441
3442 default:
3443 break;
3444 }
3445 }
3446 if (dump_object_name) {
3447 const char *object_name = module->GetObjectName().GetCString();
3448 if (object_name)
3449 strm.Printf(format: "(%s)", object_name);
3450 }
3451 strm.EOL();
3452 }
3453
3454 CommandOptions m_options;
3455};
3456
3457#pragma mark CommandObjectTargetModulesShowUnwind
3458
3459// Lookup unwind information in images
3460#define LLDB_OPTIONS_target_modules_show_unwind
3461#include "CommandOptions.inc"
3462
3463class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed {
3464public:
3465 enum {
3466 eLookupTypeInvalid = -1,
3467 eLookupTypeAddress = 0,
3468 eLookupTypeSymbol,
3469 eLookupTypeFunction,
3470 eLookupTypeFunctionOrSymbol,
3471 kNumLookupTypes
3472 };
3473
3474 class CommandOptions : public Options {
3475 public:
3476 CommandOptions() = default;
3477
3478 ~CommandOptions() override = default;
3479
3480 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3481 ExecutionContext *execution_context) override {
3482 Status error;
3483
3484 const int short_option = m_getopt_table[option_idx].val;
3485
3486 switch (short_option) {
3487 case 'a': {
3488 m_str = std::string(option_arg);
3489 m_type = eLookupTypeAddress;
3490 m_addr = OptionArgParser::ToAddress(exe_ctx: execution_context, s: option_arg,
3491 LLDB_INVALID_ADDRESS, error_ptr: &error);
3492 if (m_addr == LLDB_INVALID_ADDRESS)
3493 error = Status::FromErrorStringWithFormat(
3494 format: "invalid address string '%s'", option_arg.str().c_str());
3495 break;
3496 }
3497
3498 case 'n':
3499 m_str = std::string(option_arg);
3500 m_type = eLookupTypeFunctionOrSymbol;
3501 break;
3502
3503 case 'c':
3504 bool value, success;
3505 value = OptionArgParser::ToBoolean(s: option_arg, fail_value: false, success_ptr: &success);
3506 if (success) {
3507 m_cached = value;
3508 } else {
3509 return Status::FromErrorStringWithFormatv(
3510 format: "invalid boolean value '%s' passed for -c option", args&: option_arg);
3511 }
3512 break;
3513
3514 default:
3515 llvm_unreachable("Unimplemented option");
3516 }
3517
3518 return error;
3519 }
3520
3521 void OptionParsingStarting(ExecutionContext *execution_context) override {
3522 m_type = eLookupTypeInvalid;
3523 m_str.clear();
3524 m_addr = LLDB_INVALID_ADDRESS;
3525 m_cached = false;
3526 }
3527
3528 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3529 return llvm::ArrayRef(g_target_modules_show_unwind_options);
3530 }
3531
3532 // Instance variables to hold the values for command options.
3533
3534 int m_type = eLookupTypeInvalid; // Should be a eLookupTypeXXX enum after
3535 // parsing options
3536 std::string m_str; // Holds name lookup
3537 lldb::addr_t m_addr = LLDB_INVALID_ADDRESS; // Holds the address to lookup
3538 bool m_cached = true;
3539 };
3540
3541 CommandObjectTargetModulesShowUnwind(CommandInterpreter &interpreter)
3542 : CommandObjectParsed(
3543 interpreter, "target modules show-unwind",
3544 "Show synthesized unwind instructions for a function.", nullptr,
3545 eCommandRequiresTarget | eCommandRequiresProcess |
3546 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
3547
3548 ~CommandObjectTargetModulesShowUnwind() override = default;
3549
3550 Options *GetOptions() override { return &m_options; }
3551
3552protected:
3553 void DoExecute(Args &command, CommandReturnObject &result) override {
3554 Target *target = m_exe_ctx.GetTargetPtr();
3555 Process *process = m_exe_ctx.GetProcessPtr();
3556 ABI *abi = nullptr;
3557 if (process)
3558 abi = process->GetABI().get();
3559
3560 if (process == nullptr) {
3561 result.AppendError(
3562 in_string: "You must have a process running to use this command.");
3563 return;
3564 }
3565
3566 ThreadList threads(process->GetThreadList());
3567 if (threads.GetSize() == 0) {
3568 result.AppendError(in_string: "The process must be paused to use this command.");
3569 return;
3570 }
3571
3572 ThreadSP thread(threads.GetThreadAtIndex(idx: 0));
3573 if (!thread) {
3574 result.AppendError(in_string: "The process must be paused to use this command.");
3575 return;
3576 }
3577
3578 SymbolContextList sc_list;
3579
3580 if (m_options.m_type == eLookupTypeFunctionOrSymbol) {
3581 ConstString function_name(m_options.m_str.c_str());
3582 ModuleFunctionSearchOptions function_options;
3583 function_options.include_symbols = true;
3584 function_options.include_inlines = false;
3585 target->GetImages().FindFunctions(name: function_name, name_type_mask: eFunctionNameTypeAuto,
3586 options: function_options, sc_list);
3587 } else if (m_options.m_type == eLookupTypeAddress && target) {
3588 Address addr;
3589 if (target->ResolveLoadAddress(load_addr: m_options.m_addr, so_addr&: addr)) {
3590 SymbolContext sc;
3591 ModuleSP module_sp(addr.GetModule());
3592 module_sp->ResolveSymbolContextForAddress(so_addr: addr,
3593 resolve_scope: eSymbolContextEverything, sc);
3594 if (sc.function || sc.symbol) {
3595 sc_list.Append(sc);
3596 }
3597 }
3598 } else {
3599 result.AppendError(
3600 in_string: "address-expression or function name option must be specified.");
3601 return;
3602 }
3603
3604 if (sc_list.GetSize() == 0) {
3605 result.AppendErrorWithFormat(format: "no unwind data found that matches '%s'.",
3606 m_options.m_str.c_str());
3607 return;
3608 }
3609
3610 for (const SymbolContext &sc : sc_list) {
3611 if (sc.symbol == nullptr && sc.function == nullptr)
3612 continue;
3613 if (!sc.module_sp || sc.module_sp->GetObjectFile() == nullptr)
3614 continue;
3615 Address addr = sc.GetFunctionOrSymbolAddress();
3616 if (!addr.IsValid())
3617 continue;
3618 ConstString funcname(sc.GetFunctionName());
3619 if (funcname.IsEmpty())
3620 continue;
3621 addr_t start_addr = addr.GetLoadAddress(target);
3622 if (abi)
3623 start_addr = abi->FixCodeAddress(pc: start_addr);
3624
3625 UnwindTable &uw_table = sc.module_sp->GetUnwindTable();
3626 FuncUnwindersSP func_unwinders_sp =
3627 m_options.m_cached
3628 ? uw_table.GetFuncUnwindersContainingAddress(addr: start_addr, sc)
3629 : uw_table.GetUncachedFuncUnwindersContainingAddress(addr: start_addr,
3630 sc);
3631 if (!func_unwinders_sp)
3632 continue;
3633
3634 result.GetOutputStream().Printf(
3635 format: "UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n",
3636 sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(),
3637 funcname.AsCString(), start_addr);
3638
3639 Args args;
3640 target->GetUserSpecifiedTrapHandlerNames(args);
3641 size_t count = args.GetArgumentCount();
3642 for (size_t i = 0; i < count; i++) {
3643 const char *trap_func_name = args.GetArgumentAtIndex(idx: i);
3644 if (strcmp(s1: funcname.GetCString(), s2: trap_func_name) == 0)
3645 result.GetOutputStream().Printf(
3646 format: "This function is "
3647 "treated as a trap handler function via user setting.\n");
3648 }
3649 PlatformSP platform_sp(target->GetPlatform());
3650 if (platform_sp) {
3651 const std::vector<ConstString> trap_handler_names(
3652 platform_sp->GetTrapHandlerSymbolNames());
3653 for (ConstString trap_name : trap_handler_names) {
3654 if (trap_name == funcname) {
3655 result.GetOutputStream().Printf(
3656 format: "This function's "
3657 "name is listed by the platform as a trap handler.\n");
3658 }
3659 }
3660 }
3661
3662 result.GetOutputStream().Printf(format: "\n");
3663
3664 if (std::shared_ptr<const UnwindPlan> plan_sp =
3665 func_unwinders_sp->GetUnwindPlanAtNonCallSite(target&: *target, thread&: *thread)) {
3666 result.GetOutputStream().Printf(
3667 format: "Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n",
3668 plan_sp->GetSourceName().AsCString());
3669 }
3670 if (std::shared_ptr<const UnwindPlan> plan_sp =
3671 func_unwinders_sp->GetUnwindPlanAtCallSite(target&: *target, thread&: *thread)) {
3672 result.GetOutputStream().Printf(
3673 format: "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n",
3674 plan_sp->GetSourceName().AsCString());
3675 }
3676 if (std::shared_ptr<const UnwindPlan> plan_sp =
3677 func_unwinders_sp->GetUnwindPlanFastUnwind(target&: *target, thread&: *thread)) {
3678 result.GetOutputStream().Printf(format: "Fast UnwindPlan is '%s'\n",
3679 plan_sp->GetSourceName().AsCString());
3680 }
3681
3682 result.GetOutputStream().Printf(format: "\n");
3683
3684 if (std::shared_ptr<const UnwindPlan> plan_sp =
3685 func_unwinders_sp->GetAssemblyUnwindPlan(target&: *target, thread&: *thread)) {
3686 result.GetOutputStream().Printf(
3687 format: "Assembly language inspection UnwindPlan:\n");
3688 plan_sp->Dump(s&: result.GetOutputStream(), thread: thread.get(),
3689 LLDB_INVALID_ADDRESS);
3690 result.GetOutputStream().Printf(format: "\n");
3691 }
3692
3693 if (std::shared_ptr<const UnwindPlan> plan_sp =
3694 func_unwinders_sp->GetObjectFileUnwindPlan(target&: *target)) {
3695 result.GetOutputStream().Printf(format: "object file UnwindPlan:\n");
3696 plan_sp->Dump(s&: result.GetOutputStream(), thread: thread.get(),
3697 LLDB_INVALID_ADDRESS);
3698 result.GetOutputStream().Printf(format: "\n");
3699 }
3700
3701 if (std::shared_ptr<const UnwindPlan> plan_sp =
3702 func_unwinders_sp->GetObjectFileAugmentedUnwindPlan(target&: *target,
3703 thread&: *thread)) {
3704 result.GetOutputStream().Printf(format: "object file augmented UnwindPlan:\n");
3705 plan_sp->Dump(s&: result.GetOutputStream(), thread: thread.get(),
3706 LLDB_INVALID_ADDRESS);
3707 result.GetOutputStream().Printf(format: "\n");
3708 }
3709
3710 if (std::shared_ptr<const UnwindPlan> plan_sp =
3711 func_unwinders_sp->GetEHFrameUnwindPlan(target&: *target)) {
3712 result.GetOutputStream().Printf(format: "eh_frame UnwindPlan:\n");
3713 plan_sp->Dump(s&: result.GetOutputStream(), thread: thread.get(),
3714 LLDB_INVALID_ADDRESS);
3715 result.GetOutputStream().Printf(format: "\n");
3716 }
3717
3718 if (std::shared_ptr<const UnwindPlan> plan_sp =
3719 func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(target&: *target,
3720 thread&: *thread)) {
3721 result.GetOutputStream().Printf(format: "eh_frame augmented UnwindPlan:\n");
3722 plan_sp->Dump(s&: result.GetOutputStream(), thread: thread.get(),
3723 LLDB_INVALID_ADDRESS);
3724 result.GetOutputStream().Printf(format: "\n");
3725 }
3726
3727 if (std::shared_ptr<const UnwindPlan> plan_sp =
3728 func_unwinders_sp->GetDebugFrameUnwindPlan(target&: *target)) {
3729 result.GetOutputStream().Printf(format: "debug_frame UnwindPlan:\n");
3730 plan_sp->Dump(s&: result.GetOutputStream(), thread: thread.get(),
3731 LLDB_INVALID_ADDRESS);
3732 result.GetOutputStream().Printf(format: "\n");
3733 }
3734
3735 if (std::shared_ptr<const UnwindPlan> plan_sp =
3736 func_unwinders_sp->GetDebugFrameAugmentedUnwindPlan(target&: *target,
3737 thread&: *thread)) {
3738 result.GetOutputStream().Printf(format: "debug_frame augmented UnwindPlan:\n");
3739 plan_sp->Dump(s&: result.GetOutputStream(), thread: thread.get(),
3740 LLDB_INVALID_ADDRESS);
3741 result.GetOutputStream().Printf(format: "\n");
3742 }
3743
3744 if (std::shared_ptr<const UnwindPlan> plan_sp =
3745 func_unwinders_sp->GetArmUnwindUnwindPlan(target&: *target)) {
3746 result.GetOutputStream().Printf(format: "ARM.exidx unwind UnwindPlan:\n");
3747 plan_sp->Dump(s&: result.GetOutputStream(), thread: thread.get(),
3748 LLDB_INVALID_ADDRESS);
3749 result.GetOutputStream().Printf(format: "\n");
3750 }
3751
3752 if (std::shared_ptr<const UnwindPlan> plan_sp =
3753 func_unwinders_sp->GetSymbolFileUnwindPlan(thread&: *thread)) {
3754 result.GetOutputStream().Printf(format: "Symbol file UnwindPlan:\n");
3755 plan_sp->Dump(s&: result.GetOutputStream(), thread: thread.get(),
3756 LLDB_INVALID_ADDRESS);
3757 result.GetOutputStream().Printf(format: "\n");
3758 }
3759
3760 if (std::shared_ptr<const UnwindPlan> plan_sp =
3761 func_unwinders_sp->GetCompactUnwindUnwindPlan(target&: *target)) {
3762 result.GetOutputStream().Printf(format: "Compact unwind UnwindPlan:\n");
3763 plan_sp->Dump(s&: result.GetOutputStream(), thread: thread.get(),
3764 LLDB_INVALID_ADDRESS);
3765 result.GetOutputStream().Printf(format: "\n");
3766 }
3767
3768 if (std::shared_ptr<const UnwindPlan> plan_sp =
3769 func_unwinders_sp->GetUnwindPlanFastUnwind(target&: *target, thread&: *thread)) {
3770 result.GetOutputStream().Printf(format: "Fast UnwindPlan:\n");
3771 plan_sp->Dump(s&: result.GetOutputStream(), thread: thread.get(),
3772 LLDB_INVALID_ADDRESS);
3773 result.GetOutputStream().Printf(format: "\n");
3774 }
3775
3776 ABISP abi_sp = process->GetABI();
3777 if (abi_sp) {
3778 if (UnwindPlanSP plan_sp = abi_sp->CreateDefaultUnwindPlan()) {
3779 result.GetOutputStream().Printf(format: "Arch default UnwindPlan:\n");
3780 plan_sp->Dump(s&: result.GetOutputStream(), thread: thread.get(),
3781 LLDB_INVALID_ADDRESS);
3782 result.GetOutputStream().Printf(format: "\n");
3783 }
3784
3785 if (UnwindPlanSP plan_sp = abi_sp->CreateFunctionEntryUnwindPlan()) {
3786 result.GetOutputStream().Printf(
3787 format: "Arch default at entry point UnwindPlan:\n");
3788 plan_sp->Dump(s&: result.GetOutputStream(), thread: thread.get(),
3789 LLDB_INVALID_ADDRESS);
3790 result.GetOutputStream().Printf(format: "\n");
3791 }
3792 }
3793
3794 result.GetOutputStream().Printf(format: "\n");
3795 }
3796 }
3797
3798 CommandOptions m_options;
3799};
3800
3801// Lookup information in images
3802#define LLDB_OPTIONS_target_modules_lookup
3803#include "CommandOptions.inc"
3804
3805class CommandObjectTargetModulesLookup : public CommandObjectParsed {
3806public:
3807 enum {
3808 eLookupTypeInvalid = -1,
3809 eLookupTypeAddress = 0,
3810 eLookupTypeSymbol,
3811 eLookupTypeFileLine, // Line is optional
3812 eLookupTypeFunction,
3813 eLookupTypeFunctionOrSymbol,
3814 eLookupTypeType,
3815 kNumLookupTypes
3816 };
3817
3818 class CommandOptions : public Options {
3819 public:
3820 CommandOptions() { OptionParsingStarting(execution_context: nullptr); }
3821
3822 ~CommandOptions() override = default;
3823
3824 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3825 ExecutionContext *execution_context) override {
3826 Status error;
3827
3828 const int short_option = m_getopt_table[option_idx].val;
3829
3830 switch (short_option) {
3831 case 'a': {
3832 m_type = eLookupTypeAddress;
3833 m_addr = OptionArgParser::ToAddress(exe_ctx: execution_context, s: option_arg,
3834 LLDB_INVALID_ADDRESS, error_ptr: &error);
3835 } break;
3836
3837 case 'o':
3838 if (option_arg.getAsInteger(Radix: 0, Result&: m_offset))
3839 error = Status::FromErrorStringWithFormat(
3840 format: "invalid offset string '%s'", option_arg.str().c_str());
3841 break;
3842
3843 case 's':
3844 m_str = std::string(option_arg);
3845 m_type = eLookupTypeSymbol;
3846 break;
3847
3848 case 'f':
3849 m_file.SetFile(path: option_arg, style: FileSpec::Style::native);
3850 m_type = eLookupTypeFileLine;
3851 break;
3852
3853 case 'i':
3854 m_include_inlines = false;
3855 break;
3856
3857 case 'l':
3858 if (option_arg.getAsInteger(Radix: 0, Result&: m_line_number))
3859 error = Status::FromErrorStringWithFormat(
3860 format: "invalid line number string '%s'", option_arg.str().c_str());
3861 else if (m_line_number == 0)
3862 error = Status::FromErrorString(str: "zero is an invalid line number");
3863 m_type = eLookupTypeFileLine;
3864 break;
3865
3866 case 'F':
3867 m_str = std::string(option_arg);
3868 m_type = eLookupTypeFunction;
3869 break;
3870
3871 case 'n':
3872 m_str = std::string(option_arg);
3873 m_type = eLookupTypeFunctionOrSymbol;
3874 break;
3875
3876 case 't':
3877 m_str = std::string(option_arg);
3878 m_type = eLookupTypeType;
3879 break;
3880
3881 case 'v':
3882 m_verbose = true;
3883 break;
3884
3885 case 'A':
3886 m_print_all = true;
3887 break;
3888
3889 case 'r':
3890 m_use_regex = true;
3891 break;
3892
3893 case '\x01':
3894 m_all_ranges = true;
3895 break;
3896 default:
3897 llvm_unreachable("Unimplemented option");
3898 }
3899
3900 return error;
3901 }
3902
3903 void OptionParsingStarting(ExecutionContext *execution_context) override {
3904 m_type = eLookupTypeInvalid;
3905 m_str.clear();
3906 m_file.Clear();
3907 m_addr = LLDB_INVALID_ADDRESS;
3908 m_offset = 0;
3909 m_line_number = 0;
3910 m_use_regex = false;
3911 m_include_inlines = true;
3912 m_all_ranges = false;
3913 m_verbose = false;
3914 m_print_all = false;
3915 }
3916
3917 Status OptionParsingFinished(ExecutionContext *execution_context) override {
3918 Status status;
3919 if (m_all_ranges && !m_verbose) {
3920 status =
3921 Status::FromErrorString(str: "--show-variable-ranges must be used in "
3922 "conjunction with --verbose.");
3923 }
3924 return status;
3925 }
3926
3927 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3928 return llvm::ArrayRef(g_target_modules_lookup_options);
3929 }
3930
3931 int m_type; // Should be a eLookupTypeXXX enum after parsing options
3932 std::string m_str; // Holds name lookup
3933 FileSpec m_file; // Files for file lookups
3934 lldb::addr_t m_addr; // Holds the address to lookup
3935 lldb::addr_t
3936 m_offset; // Subtract this offset from m_addr before doing lookups.
3937 uint32_t m_line_number; // Line number for file+line lookups
3938 bool m_use_regex; // Name lookups in m_str are regular expressions.
3939 bool m_include_inlines; // Check for inline entries when looking up by
3940 // file/line.
3941 bool m_all_ranges; // Print all ranges or single range.
3942 bool m_verbose; // Enable verbose lookup info
3943 bool m_print_all; // Print all matches, even in cases where there's a best
3944 // match.
3945 };
3946
3947 CommandObjectTargetModulesLookup(CommandInterpreter &interpreter)
3948 : CommandObjectParsed(interpreter, "target modules lookup",
3949 "Look up information within executable and "
3950 "dependent shared library images.",
3951 nullptr, eCommandRequiresTarget) {
3952 AddSimpleArgumentList(arg_type: eArgTypeFilename, repetition_type: eArgRepeatStar);
3953 }
3954
3955 ~CommandObjectTargetModulesLookup() override = default;
3956
3957 Options *GetOptions() override { return &m_options; }
3958
3959 bool LookupHere(CommandInterpreter &interpreter, CommandReturnObject &result,
3960 bool &syntax_error) {
3961 switch (m_options.m_type) {
3962 case eLookupTypeAddress:
3963 case eLookupTypeFileLine:
3964 case eLookupTypeFunction:
3965 case eLookupTypeFunctionOrSymbol:
3966 case eLookupTypeSymbol:
3967 default:
3968 return false;
3969 case eLookupTypeType:
3970 break;
3971 }
3972
3973 StackFrameSP frame = m_exe_ctx.GetFrameSP();
3974
3975 if (!frame)
3976 return false;
3977
3978 const SymbolContext &sym_ctx(frame->GetSymbolContext(resolve_scope: eSymbolContextModule));
3979
3980 if (!sym_ctx.module_sp)
3981 return false;
3982
3983 switch (m_options.m_type) {
3984 default:
3985 return false;
3986 case eLookupTypeType:
3987 if (!m_options.m_str.empty()) {
3988 if (LookupTypeHere(target: &GetTarget(), interpreter&: m_interpreter,
3989 strm&: result.GetOutputStream(), module&: *sym_ctx.module_sp,
3990 name_cstr: m_options.m_str.c_str(), name_is_regex: m_options.m_use_regex)) {
3991 result.SetStatus(eReturnStatusSuccessFinishResult);
3992 return true;
3993 }
3994 }
3995 break;
3996 }
3997
3998 return false;
3999 }
4000
4001 bool LookupInModule(CommandInterpreter &interpreter, Module *module,
4002 CommandReturnObject &result, bool &syntax_error) {
4003 switch (m_options.m_type) {
4004 case eLookupTypeAddress:
4005 if (m_options.m_addr != LLDB_INVALID_ADDRESS) {
4006 if (LookupAddressInModule(
4007 interpreter&: m_interpreter, strm&: result.GetOutputStream(), module,
4008 resolve_mask: eSymbolContextEverything |
4009 (m_options.m_verbose
4010 ? static_cast<int>(eSymbolContextVariable)
4011 : 0),
4012 raw_addr: m_options.m_addr, offset: m_options.m_offset, verbose: m_options.m_verbose,
4013 all_ranges: m_options.m_all_ranges)) {
4014 result.SetStatus(eReturnStatusSuccessFinishResult);
4015 return true;
4016 }
4017 }
4018 break;
4019
4020 case eLookupTypeSymbol:
4021 if (!m_options.m_str.empty()) {
4022 if (LookupSymbolInModule(interpreter&: m_interpreter, strm&: result.GetOutputStream(),
4023 module, name: m_options.m_str.c_str(),
4024 name_is_regex: m_options.m_use_regex, verbose: m_options.m_verbose,
4025 all_ranges: m_options.m_all_ranges)) {
4026 result.SetStatus(eReturnStatusSuccessFinishResult);
4027 return true;
4028 }
4029 }
4030 break;
4031
4032 case eLookupTypeFileLine:
4033 if (m_options.m_file) {
4034 if (LookupFileAndLineInModule(
4035 interpreter&: m_interpreter, strm&: result.GetOutputStream(), module,
4036 file_spec: m_options.m_file, line: m_options.m_line_number,
4037 check_inlines: m_options.m_include_inlines, verbose: m_options.m_verbose,
4038 all_ranges: m_options.m_all_ranges)) {
4039 result.SetStatus(eReturnStatusSuccessFinishResult);
4040 return true;
4041 }
4042 }
4043 break;
4044
4045 case eLookupTypeFunctionOrSymbol:
4046 case eLookupTypeFunction:
4047 if (!m_options.m_str.empty()) {
4048 ModuleFunctionSearchOptions function_options;
4049 function_options.include_symbols =
4050 m_options.m_type == eLookupTypeFunctionOrSymbol;
4051 function_options.include_inlines = m_options.m_include_inlines;
4052
4053 if (LookupFunctionInModule(interpreter&: m_interpreter, strm&: result.GetOutputStream(),
4054 module, name: m_options.m_str.c_str(),
4055 name_is_regex: m_options.m_use_regex, options: function_options,
4056 verbose: m_options.m_verbose,
4057 all_ranges: m_options.m_all_ranges)) {
4058 result.SetStatus(eReturnStatusSuccessFinishResult);
4059 return true;
4060 }
4061 }
4062 break;
4063
4064 case eLookupTypeType:
4065 if (!m_options.m_str.empty()) {
4066 if (LookupTypeInModule(
4067 target: &GetTarget(), interpreter&: m_interpreter, strm&: result.GetOutputStream(), module,
4068 name_cstr: m_options.m_str.c_str(), name_is_regex: m_options.m_use_regex)) {
4069 result.SetStatus(eReturnStatusSuccessFinishResult);
4070 return true;
4071 }
4072 }
4073 break;
4074
4075 default:
4076 m_options.GenerateOptionUsage(
4077 strm&: result.GetErrorStream(), cmd&: *this,
4078 screen_width: GetCommandInterpreter().GetDebugger().GetTerminalWidth());
4079 syntax_error = true;
4080 break;
4081 }
4082
4083 result.SetStatus(eReturnStatusFailed);
4084 return false;
4085 }
4086
4087protected:
4088 void DoExecute(Args &command, CommandReturnObject &result) override {
4089 Target &target = GetTarget();
4090 bool syntax_error = false;
4091 uint32_t i;
4092 uint32_t num_successful_lookups = 0;
4093 uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize();
4094 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
4095 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
4096 // Dump all sections for all modules images
4097
4098 if (command.GetArgumentCount() == 0) {
4099 // Where it is possible to look in the current symbol context first,
4100 // try that. If this search was successful and --all was not passed,
4101 // don't print anything else.
4102 if (LookupHere(interpreter&: m_interpreter, result, syntax_error)) {
4103 result.GetOutputStream().EOL();
4104 num_successful_lookups++;
4105 if (!m_options.m_print_all) {
4106 result.SetStatus(eReturnStatusSuccessFinishResult);
4107 return;
4108 }
4109 }
4110
4111 // Dump all sections for all other modules
4112
4113 const ModuleList &target_modules = target.GetImages();
4114 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
4115 if (target_modules.GetSize() == 0) {
4116 result.AppendError(in_string: "the target has no associated executable images");
4117 return;
4118 }
4119
4120 for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
4121 if (LookupInModule(interpreter&: m_interpreter, module: module_sp.get(), result,
4122 syntax_error)) {
4123 result.GetOutputStream().EOL();
4124 num_successful_lookups++;
4125 }
4126 }
4127 } else {
4128 // Dump specified images (by basename or fullpath)
4129 const char *arg_cstr;
4130 for (i = 0; (arg_cstr = command.GetArgumentAtIndex(idx: i)) != nullptr &&
4131 !syntax_error;
4132 ++i) {
4133 ModuleList module_list;
4134 const size_t num_matches =
4135 FindModulesByName(target: &target, module_name: arg_cstr, module_list, check_global_list: false);
4136 if (num_matches > 0) {
4137 for (size_t j = 0; j < num_matches; ++j) {
4138 Module *module = module_list.GetModulePointerAtIndex(idx: j);
4139 if (module) {
4140 if (LookupInModule(interpreter&: m_interpreter, module, result, syntax_error)) {
4141 result.GetOutputStream().EOL();
4142 num_successful_lookups++;
4143 }
4144 }
4145 }
4146 } else
4147 result.AppendWarningWithFormat(
4148 format: "Unable to find an image that matches '%s'.\n", arg_cstr);
4149 }
4150 }
4151
4152 if (num_successful_lookups > 0)
4153 result.SetStatus(eReturnStatusSuccessFinishResult);
4154 else
4155 result.SetStatus(eReturnStatusFailed);
4156 }
4157
4158 CommandOptions m_options;
4159};
4160
4161#pragma mark CommandObjectMultiwordImageSearchPaths
4162
4163// CommandObjectMultiwordImageSearchPaths
4164
4165class CommandObjectTargetModulesImageSearchPaths
4166 : public CommandObjectMultiword {
4167public:
4168 CommandObjectTargetModulesImageSearchPaths(CommandInterpreter &interpreter)
4169 : CommandObjectMultiword(
4170 interpreter, "target modules search-paths",
4171 "Commands for managing module search paths for a target.",
4172 "target modules search-paths <subcommand> [<subcommand-options>]") {
4173 LoadSubCommand(
4174 cmd_name: "add", command_obj: CommandObjectSP(
4175 new CommandObjectTargetModulesSearchPathsAdd(interpreter)));
4176 LoadSubCommand(
4177 cmd_name: "clear", command_obj: CommandObjectSP(new CommandObjectTargetModulesSearchPathsClear(
4178 interpreter)));
4179 LoadSubCommand(
4180 cmd_name: "insert",
4181 command_obj: CommandObjectSP(
4182 new CommandObjectTargetModulesSearchPathsInsert(interpreter)));
4183 LoadSubCommand(
4184 cmd_name: "list", command_obj: CommandObjectSP(new CommandObjectTargetModulesSearchPathsList(
4185 interpreter)));
4186 LoadSubCommand(
4187 cmd_name: "query", command_obj: CommandObjectSP(new CommandObjectTargetModulesSearchPathsQuery(
4188 interpreter)));
4189 }
4190
4191 ~CommandObjectTargetModulesImageSearchPaths() override = default;
4192};
4193
4194#pragma mark CommandObjectTargetModules
4195
4196// CommandObjectTargetModules
4197
4198class CommandObjectTargetModules : public CommandObjectMultiword {
4199public:
4200 // Constructors and Destructors
4201 CommandObjectTargetModules(CommandInterpreter &interpreter)
4202 : CommandObjectMultiword(interpreter, "target modules",
4203 "Commands for accessing information for one or "
4204 "more target modules.",
4205 "target modules <sub-command> ...") {
4206 LoadSubCommand(
4207 cmd_name: "add", command_obj: CommandObjectSP(new CommandObjectTargetModulesAdd(interpreter)));
4208 LoadSubCommand(cmd_name: "load", command_obj: CommandObjectSP(new CommandObjectTargetModulesLoad(
4209 interpreter)));
4210 LoadSubCommand(cmd_name: "dump", command_obj: CommandObjectSP(new CommandObjectTargetModulesDump(
4211 interpreter)));
4212 LoadSubCommand(cmd_name: "list", command_obj: CommandObjectSP(new CommandObjectTargetModulesList(
4213 interpreter)));
4214 LoadSubCommand(
4215 cmd_name: "lookup",
4216 command_obj: CommandObjectSP(new CommandObjectTargetModulesLookup(interpreter)));
4217 LoadSubCommand(
4218 cmd_name: "search-paths",
4219 command_obj: CommandObjectSP(
4220 new CommandObjectTargetModulesImageSearchPaths(interpreter)));
4221 LoadSubCommand(
4222 cmd_name: "show-unwind",
4223 command_obj: CommandObjectSP(new CommandObjectTargetModulesShowUnwind(interpreter)));
4224 }
4225
4226 ~CommandObjectTargetModules() override = default;
4227
4228private:
4229 // For CommandObjectTargetModules only
4230 CommandObjectTargetModules(const CommandObjectTargetModules &) = delete;
4231 const CommandObjectTargetModules &
4232 operator=(const CommandObjectTargetModules &) = delete;
4233};
4234
4235class CommandObjectTargetSymbolsAdd : public CommandObjectParsed {
4236public:
4237 CommandObjectTargetSymbolsAdd(CommandInterpreter &interpreter)
4238 : CommandObjectParsed(
4239 interpreter, "target symbols add",
4240 "Add a debug symbol file to one of the target's current modules by "
4241 "specifying a path to a debug symbols file or by using the options "
4242 "to specify a module.",
4243 "target symbols add <cmd-options> [<symfile>]",
4244 eCommandRequiresTarget),
4245 m_file_option(
4246 LLDB_OPT_SET_1, false, "shlib", 's', lldb::eModuleCompletion,
4247 eArgTypeShlibName,
4248 "Locate the debug symbols for the shared library specified by "
4249 "name."),
4250 m_current_frame_option(
4251 LLDB_OPT_SET_2, false, "frame", 'F',
4252 "Locate the debug symbols for the currently selected frame.", false,
4253 true),
4254 m_current_stack_option(LLDB_OPT_SET_2, false, "stack", 'S',
4255 "Locate the debug symbols for every frame in "
4256 "the current call stack.",
4257 false, true)
4258
4259 {
4260 m_option_group.Append(group: &m_uuid_option_group, LLDB_OPT_SET_ALL,
4261 LLDB_OPT_SET_1);
4262 m_option_group.Append(group: &m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
4263 m_option_group.Append(group: &m_current_frame_option, LLDB_OPT_SET_2,
4264 LLDB_OPT_SET_2);
4265 m_option_group.Append(group: &m_current_stack_option, LLDB_OPT_SET_2,
4266 LLDB_OPT_SET_2);
4267 m_option_group.Finalize();
4268 AddSimpleArgumentList(arg_type: eArgTypeFilename);
4269 }
4270
4271 ~CommandObjectTargetSymbolsAdd() override = default;
4272
4273 Options *GetOptions() override { return &m_option_group; }
4274
4275protected:
4276 bool AddModuleSymbols(Target *target, ModuleSpec &module_spec, bool &flush,
4277 CommandReturnObject &result) {
4278 const FileSpec &symbol_fspec = module_spec.GetSymbolFileSpec();
4279 if (!symbol_fspec) {
4280 result.AppendError(
4281 in_string: "one or more executable image paths must be specified");
4282 return false;
4283 }
4284
4285 char symfile_path[PATH_MAX];
4286 symbol_fspec.GetPath(path: symfile_path, max_path_length: sizeof(symfile_path));
4287
4288 if (!module_spec.GetUUID().IsValid()) {
4289 if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec())
4290 module_spec.GetFileSpec().SetFilename(symbol_fspec.GetFilename());
4291 }
4292
4293 // Now module_spec represents a symbol file for a module that might exist
4294 // in the current target. Let's find possible matches.
4295 ModuleList matching_modules;
4296
4297 // First extract all module specs from the symbol file
4298 lldb_private::ModuleSpecList symfile_module_specs;
4299 if (ObjectFile::GetModuleSpecifications(file: module_spec.GetSymbolFileSpec(),
4300 file_offset: 0, file_size: 0, specs&: symfile_module_specs)) {
4301 // Now extract the module spec that matches the target architecture
4302 ModuleSpec target_arch_module_spec;
4303 ModuleSpec symfile_module_spec;
4304 target_arch_module_spec.GetArchitecture() = target->GetArchitecture();
4305 if (symfile_module_specs.FindMatchingModuleSpec(module_spec: target_arch_module_spec,
4306 match_module_spec&: symfile_module_spec)) {
4307 if (symfile_module_spec.GetUUID().IsValid()) {
4308 // It has a UUID, look for this UUID in the target modules
4309 ModuleSpec symfile_uuid_module_spec;
4310 symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID();
4311 target->GetImages().FindModules(module_spec: symfile_uuid_module_spec,
4312 matching_module_list&: matching_modules);
4313 }
4314 }
4315
4316 if (matching_modules.IsEmpty()) {
4317 // No matches yet. Iterate through the module specs to find a UUID
4318 // value that we can match up to an image in our target.
4319 const size_t num_symfile_module_specs = symfile_module_specs.GetSize();
4320 for (size_t i = 0;
4321 i < num_symfile_module_specs && matching_modules.IsEmpty(); ++i) {
4322 if (symfile_module_specs.GetModuleSpecAtIndex(
4323 i, module_spec&: symfile_module_spec)) {
4324 if (symfile_module_spec.GetUUID().IsValid()) {
4325 // It has a UUID. Look for this UUID in the target modules.
4326 ModuleSpec symfile_uuid_module_spec;
4327 symfile_uuid_module_spec.GetUUID() =
4328 symfile_module_spec.GetUUID();
4329 target->GetImages().FindModules(module_spec: symfile_uuid_module_spec,
4330 matching_module_list&: matching_modules);
4331 }
4332 }
4333 }
4334 }
4335 }
4336
4337 // Just try to match up the file by basename if we have no matches at
4338 // this point. For example, module foo might have symbols in foo.debug.
4339 if (matching_modules.IsEmpty())
4340 target->GetImages().FindModules(module_spec, matching_module_list&: matching_modules);
4341
4342 while (matching_modules.IsEmpty()) {
4343 ConstString filename_no_extension(
4344 module_spec.GetFileSpec().GetFileNameStrippingExtension());
4345 // Empty string returned, let's bail
4346 if (!filename_no_extension)
4347 break;
4348
4349 // Check if there was no extension to strip and the basename is the same
4350 if (filename_no_extension == module_spec.GetFileSpec().GetFilename())
4351 break;
4352
4353 // Replace basename with one fewer extension
4354 module_spec.GetFileSpec().SetFilename(filename_no_extension);
4355 target->GetImages().FindModules(module_spec, matching_module_list&: matching_modules);
4356 }
4357
4358 if (matching_modules.GetSize() > 1) {
4359 result.AppendErrorWithFormat(format: "multiple modules match symbol file '%s', "
4360 "use the --uuid option to resolve the "
4361 "ambiguity.\n",
4362 symfile_path);
4363 return false;
4364 }
4365
4366 if (matching_modules.GetSize() == 1) {
4367 ModuleSP module_sp(matching_modules.GetModuleAtIndex(idx: 0));
4368
4369 // The module has not yet created its symbol vendor, we can just give
4370 // the existing target module the symfile path to use for when it
4371 // decides to create it!
4372 module_sp->SetSymbolFileFileSpec(symbol_fspec);
4373
4374 SymbolFile *symbol_file =
4375 module_sp->GetSymbolFile(can_create: true, feedback_strm: &result.GetErrorStream());
4376 if (symbol_file) {
4377 ObjectFile *object_file = symbol_file->GetObjectFile();
4378 if (object_file && object_file->GetFileSpec() == symbol_fspec) {
4379 // Provide feedback that the symfile has been successfully added.
4380 const FileSpec &module_fs = module_sp->GetFileSpec();
4381 result.AppendMessageWithFormat(
4382 format: "symbol file '%s' has been added to '%s'\n", symfile_path,
4383 module_fs.GetPath().c_str());
4384
4385 // Let clients know something changed in the module if it is
4386 // currently loaded
4387 ModuleList module_list;
4388 module_list.Append(module_sp);
4389 target->SymbolsDidLoad(module_list);
4390
4391 // Make sure we load any scripting resources that may be embedded
4392 // in the debug info files in case the platform supports that.
4393 Status error;
4394 StreamString feedback_stream;
4395 module_sp->LoadScriptingResourceInTarget(target, error,
4396 feedback_stream);
4397 if (error.Fail() && error.AsCString())
4398 result.AppendWarningWithFormat(
4399 format: "unable to load scripting data for module %s - error "
4400 "reported was %s",
4401 module_sp->GetFileSpec()
4402 .GetFileNameStrippingExtension()
4403 .GetCString(),
4404 error.AsCString());
4405 else if (feedback_stream.GetSize())
4406 result.AppendWarning(in_string: feedback_stream.GetData());
4407
4408 flush = true;
4409 result.SetStatus(eReturnStatusSuccessFinishResult);
4410 return true;
4411 }
4412 }
4413 // Clear the symbol file spec if anything went wrong
4414 module_sp->SetSymbolFileFileSpec(FileSpec());
4415 }
4416
4417 StreamString ss_symfile_uuid;
4418 if (module_spec.GetUUID().IsValid()) {
4419 ss_symfile_uuid << " (";
4420 module_spec.GetUUID().Dump(s&: ss_symfile_uuid);
4421 ss_symfile_uuid << ')';
4422 }
4423 result.AppendErrorWithFormat(
4424 format: "symbol file '%s'%s does not match any existing module%s\n",
4425 symfile_path, ss_symfile_uuid.GetData(),
4426 !llvm::sys::fs::is_regular_file(Path: symbol_fspec.GetPath())
4427 ? "\n please specify the full path to the symbol file"
4428 : "");
4429 return false;
4430 }
4431
4432 bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
4433 CommandReturnObject &result, bool &flush) {
4434 Status error;
4435 if (PluginManager::DownloadObjectAndSymbolFile(module_spec, error)) {
4436 if (module_spec.GetSymbolFileSpec())
4437 return AddModuleSymbols(target: m_exe_ctx.GetTargetPtr(), module_spec, flush,
4438 result);
4439 } else {
4440 result.SetError(std::move(error));
4441 }
4442 return false;
4443 }
4444
4445 bool AddSymbolsForUUID(CommandReturnObject &result, bool &flush) {
4446 assert(m_uuid_option_group.GetOptionValue().OptionWasSet());
4447
4448 ModuleSpec module_spec;
4449 module_spec.GetUUID() =
4450 m_uuid_option_group.GetOptionValue().GetCurrentValue();
4451
4452 if (!DownloadObjectAndSymbolFile(module_spec, result, flush)) {
4453 StreamString error_strm;
4454 error_strm.PutCString(cstr: "unable to find debug symbols for UUID ");
4455 module_spec.GetUUID().Dump(s&: error_strm);
4456 result.AppendError(in_string: error_strm.GetString());
4457 return false;
4458 }
4459
4460 return true;
4461 }
4462
4463 bool AddSymbolsForFile(CommandReturnObject &result, bool &flush) {
4464 assert(m_file_option.GetOptionValue().OptionWasSet());
4465
4466 ModuleSpec module_spec;
4467 module_spec.GetFileSpec() =
4468 m_file_option.GetOptionValue().GetCurrentValue();
4469
4470 Target *target = m_exe_ctx.GetTargetPtr();
4471 ModuleSP module_sp(target->GetImages().FindFirstModule(module_spec));
4472 if (module_sp) {
4473 module_spec.GetFileSpec() = module_sp->GetFileSpec();
4474 module_spec.GetPlatformFileSpec() = module_sp->GetPlatformFileSpec();
4475 module_spec.GetUUID() = module_sp->GetUUID();
4476 module_spec.GetArchitecture() = module_sp->GetArchitecture();
4477 } else {
4478 module_spec.GetArchitecture() = target->GetArchitecture();
4479 }
4480
4481 if (!DownloadObjectAndSymbolFile(module_spec, result, flush)) {
4482 StreamString error_strm;
4483 error_strm.PutCString(
4484 cstr: "unable to find debug symbols for the executable file ");
4485 error_strm << module_spec.GetFileSpec();
4486 result.AppendError(in_string: error_strm.GetString());
4487 return false;
4488 }
4489
4490 return true;
4491 }
4492
4493 bool AddSymbolsForFrame(CommandReturnObject &result, bool &flush) {
4494 assert(m_current_frame_option.GetOptionValue().OptionWasSet());
4495
4496 Process *process = m_exe_ctx.GetProcessPtr();
4497 if (!process) {
4498 result.AppendError(
4499 in_string: "a process must exist in order to use the --frame option");
4500 return false;
4501 }
4502
4503 const StateType process_state = process->GetState();
4504 if (!StateIsStoppedState(state: process_state, must_exist: true)) {
4505 result.AppendErrorWithFormat(format: "process is not stopped: %s",
4506 StateAsCString(state: process_state));
4507 return false;
4508 }
4509
4510 StackFrame *frame = m_exe_ctx.GetFramePtr();
4511 if (!frame) {
4512 result.AppendError(in_string: "invalid current frame");
4513 return false;
4514 }
4515
4516 ModuleSP frame_module_sp(
4517 frame->GetSymbolContext(resolve_scope: eSymbolContextModule).module_sp);
4518 if (!frame_module_sp) {
4519 result.AppendError(in_string: "frame has no module");
4520 return false;
4521 }
4522
4523 ModuleSpec module_spec;
4524 module_spec.GetUUID() = frame_module_sp->GetUUID();
4525 module_spec.GetArchitecture() = frame_module_sp->GetArchitecture();
4526 module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec();
4527
4528 if (!DownloadObjectAndSymbolFile(module_spec, result, flush)) {
4529 result.AppendError(in_string: "unable to find debug symbols for the current frame");
4530 return false;
4531 }
4532
4533 return true;
4534 }
4535
4536 bool AddSymbolsForStack(CommandReturnObject &result, bool &flush) {
4537 assert(m_current_stack_option.GetOptionValue().OptionWasSet());
4538
4539 Process *process = m_exe_ctx.GetProcessPtr();
4540 if (!process) {
4541 result.AppendError(
4542 in_string: "a process must exist in order to use the --stack option");
4543 return false;
4544 }
4545
4546 const StateType process_state = process->GetState();
4547 if (!StateIsStoppedState(state: process_state, must_exist: true)) {
4548 result.AppendErrorWithFormat(format: "process is not stopped: %s",
4549 StateAsCString(state: process_state));
4550 return false;
4551 }
4552
4553 Thread *thread = m_exe_ctx.GetThreadPtr();
4554 if (!thread) {
4555 result.AppendError(in_string: "invalid current thread");
4556 return false;
4557 }
4558
4559 bool symbols_found = false;
4560 uint32_t frame_count = thread->GetStackFrameCount();
4561 for (uint32_t i = 0; i < frame_count; ++i) {
4562 lldb::StackFrameSP frame_sp = thread->GetStackFrameAtIndex(idx: i);
4563
4564 ModuleSP frame_module_sp(
4565 frame_sp->GetSymbolContext(resolve_scope: eSymbolContextModule).module_sp);
4566 if (!frame_module_sp)
4567 continue;
4568
4569 ModuleSpec module_spec;
4570 module_spec.GetUUID() = frame_module_sp->GetUUID();
4571 module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec();
4572 module_spec.GetArchitecture() = frame_module_sp->GetArchitecture();
4573
4574 bool current_frame_flush = false;
4575 if (DownloadObjectAndSymbolFile(module_spec, result, flush&: current_frame_flush))
4576 symbols_found = true;
4577 flush |= current_frame_flush;
4578 }
4579
4580 if (!symbols_found) {
4581 result.AppendError(
4582 in_string: "unable to find debug symbols in the current call stack");
4583 return false;
4584 }
4585
4586 return true;
4587 }
4588
4589 void DoExecute(Args &args, CommandReturnObject &result) override {
4590 Target *target = m_exe_ctx.GetTargetPtr();
4591 result.SetStatus(eReturnStatusFailed);
4592 bool flush = false;
4593 ModuleSpec module_spec;
4594 const bool uuid_option_set =
4595 m_uuid_option_group.GetOptionValue().OptionWasSet();
4596 const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet();
4597 const bool frame_option_set =
4598 m_current_frame_option.GetOptionValue().OptionWasSet();
4599 const bool stack_option_set =
4600 m_current_stack_option.GetOptionValue().OptionWasSet();
4601 const size_t argc = args.GetArgumentCount();
4602
4603 if (argc == 0) {
4604 if (uuid_option_set)
4605 AddSymbolsForUUID(result, flush);
4606 else if (file_option_set)
4607 AddSymbolsForFile(result, flush);
4608 else if (frame_option_set)
4609 AddSymbolsForFrame(result, flush);
4610 else if (stack_option_set)
4611 AddSymbolsForStack(result, flush);
4612 else
4613 result.AppendError(in_string: "one or more symbol file paths must be specified, "
4614 "or options must be specified");
4615 } else {
4616 if (uuid_option_set) {
4617 result.AppendError(in_string: "specify either one or more paths to symbol files "
4618 "or use the --uuid option without arguments");
4619 } else if (frame_option_set) {
4620 result.AppendError(in_string: "specify either one or more paths to symbol files "
4621 "or use the --frame option without arguments");
4622 } else if (file_option_set && argc > 1) {
4623 result.AppendError(in_string: "specify at most one symbol file path when "
4624 "--shlib option is set");
4625 } else {
4626 PlatformSP platform_sp(target->GetPlatform());
4627
4628 for (auto &entry : args.entries()) {
4629 if (!entry.ref().empty()) {
4630 auto &symbol_file_spec = module_spec.GetSymbolFileSpec();
4631 symbol_file_spec.SetFile(path: entry.ref(), style: FileSpec::Style::native);
4632 FileSystem::Instance().Resolve(file_spec&: symbol_file_spec);
4633 if (file_option_set) {
4634 module_spec.GetFileSpec() =
4635 m_file_option.GetOptionValue().GetCurrentValue();
4636 }
4637 if (platform_sp) {
4638 FileSpec symfile_spec;
4639 if (platform_sp
4640 ->ResolveSymbolFile(target&: *target, sym_spec: module_spec, sym_file&: symfile_spec)
4641 .Success())
4642 module_spec.GetSymbolFileSpec() = symfile_spec;
4643 }
4644
4645 bool symfile_exists =
4646 FileSystem::Instance().Exists(file_spec: module_spec.GetSymbolFileSpec());
4647
4648 if (symfile_exists) {
4649 if (!AddModuleSymbols(target, module_spec, flush, result))
4650 break;
4651 } else {
4652 std::string resolved_symfile_path =
4653 module_spec.GetSymbolFileSpec().GetPath();
4654 if (resolved_symfile_path != entry.ref()) {
4655 result.AppendErrorWithFormat(
4656 format: "invalid module path '%s' with resolved path '%s'\n",
4657 entry.c_str(), resolved_symfile_path.c_str());
4658 break;
4659 }
4660 result.AppendErrorWithFormat(format: "invalid module path '%s'\n",
4661 entry.c_str());
4662 break;
4663 }
4664 }
4665 }
4666 }
4667 }
4668
4669 if (flush) {
4670 Process *process = m_exe_ctx.GetProcessPtr();
4671 if (process)
4672 process->Flush();
4673 }
4674 }
4675
4676 OptionGroupOptions m_option_group;
4677 OptionGroupUUID m_uuid_option_group;
4678 OptionGroupFile m_file_option;
4679 OptionGroupBoolean m_current_frame_option;
4680 OptionGroupBoolean m_current_stack_option;
4681};
4682
4683#pragma mark CommandObjectTargetSymbols
4684
4685// CommandObjectTargetSymbols
4686
4687class CommandObjectTargetSymbols : public CommandObjectMultiword {
4688public:
4689 // Constructors and Destructors
4690 CommandObjectTargetSymbols(CommandInterpreter &interpreter)
4691 : CommandObjectMultiword(
4692 interpreter, "target symbols",
4693 "Commands for adding and managing debug symbol files.",
4694 "target symbols <sub-command> ...") {
4695 LoadSubCommand(
4696 cmd_name: "add", command_obj: CommandObjectSP(new CommandObjectTargetSymbolsAdd(interpreter)));
4697 }
4698
4699 ~CommandObjectTargetSymbols() override = default;
4700
4701private:
4702 // For CommandObjectTargetModules only
4703 CommandObjectTargetSymbols(const CommandObjectTargetSymbols &) = delete;
4704 const CommandObjectTargetSymbols &
4705 operator=(const CommandObjectTargetSymbols &) = delete;
4706};
4707
4708#pragma mark CommandObjectTargetStopHookAdd
4709
4710// CommandObjectTargetStopHookAdd
4711#define LLDB_OPTIONS_target_stop_hook_add
4712#include "CommandOptions.inc"
4713
4714class CommandObjectTargetStopHookAdd : public CommandObjectParsed,
4715 public IOHandlerDelegateMultiline {
4716public:
4717 class CommandOptions : public OptionGroup {
4718 public:
4719 CommandOptions() : m_line_end(UINT_MAX) {}
4720
4721 ~CommandOptions() override = default;
4722
4723 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
4724 return llvm::ArrayRef(g_target_stop_hook_add_options);
4725 }
4726
4727 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
4728 ExecutionContext *execution_context) override {
4729 Status error;
4730 const int short_option =
4731 g_target_stop_hook_add_options[option_idx].short_option;
4732
4733 switch (short_option) {
4734 case 'c':
4735 m_class_name = std::string(option_arg);
4736 m_sym_ctx_specified = true;
4737 break;
4738
4739 case 'e':
4740 if (option_arg.getAsInteger(Radix: 0, Result&: m_line_end)) {
4741 error = Status::FromErrorStringWithFormat(
4742 format: "invalid end line number: \"%s\"", option_arg.str().c_str());
4743 break;
4744 }
4745 m_sym_ctx_specified = true;
4746 break;
4747
4748 case 'G': {
4749 bool value, success;
4750 value = OptionArgParser::ToBoolean(s: option_arg, fail_value: false, success_ptr: &success);
4751 if (success) {
4752 m_auto_continue = value;
4753 } else
4754 error = Status::FromErrorStringWithFormat(
4755 format: "invalid boolean value '%s' passed for -G option",
4756 option_arg.str().c_str());
4757 } break;
4758 case 'l':
4759 if (option_arg.getAsInteger(Radix: 0, Result&: m_line_start)) {
4760 error = Status::FromErrorStringWithFormat(
4761 format: "invalid start line number: \"%s\"", option_arg.str().c_str());
4762 break;
4763 }
4764 m_sym_ctx_specified = true;
4765 break;
4766
4767 case 'i':
4768 m_no_inlines = true;
4769 break;
4770
4771 case 'n':
4772 m_function_name = std::string(option_arg);
4773 m_func_name_type_mask |= eFunctionNameTypeAuto;
4774 m_sym_ctx_specified = true;
4775 break;
4776
4777 case 'f':
4778 m_file_name = std::string(option_arg);
4779 m_sym_ctx_specified = true;
4780 break;
4781
4782 case 's':
4783 m_module_name = std::string(option_arg);
4784 m_sym_ctx_specified = true;
4785 break;
4786
4787 case 't':
4788 if (option_arg.getAsInteger(Radix: 0, Result&: m_thread_id))
4789 error = Status::FromErrorStringWithFormat(
4790 format: "invalid thread id string '%s'", option_arg.str().c_str());
4791 m_thread_specified = true;
4792 break;
4793
4794 case 'T':
4795 m_thread_name = std::string(option_arg);
4796 m_thread_specified = true;
4797 break;
4798
4799 case 'q':
4800 m_queue_name = std::string(option_arg);
4801 m_thread_specified = true;
4802 break;
4803
4804 case 'x':
4805 if (option_arg.getAsInteger(Radix: 0, Result&: m_thread_index))
4806 error = Status::FromErrorStringWithFormat(
4807 format: "invalid thread index string '%s'", option_arg.str().c_str());
4808 m_thread_specified = true;
4809 break;
4810
4811 case 'o':
4812 m_use_one_liner = true;
4813 m_one_liner.push_back(x: std::string(option_arg));
4814 break;
4815
4816 case 'I': {
4817 bool value, success;
4818 value = OptionArgParser::ToBoolean(s: option_arg, fail_value: false, success_ptr: &success);
4819 if (success)
4820 m_at_initial_stop = value;
4821 else
4822 error = Status::FromErrorStringWithFormat(
4823 format: "invalid boolean value '%s' passed for -F option",
4824 option_arg.str().c_str());
4825 } break;
4826
4827 default:
4828 llvm_unreachable("Unimplemented option");
4829 }
4830 return error;
4831 }
4832
4833 void OptionParsingStarting(ExecutionContext *execution_context) override {
4834 m_class_name.clear();
4835 m_function_name.clear();
4836 m_line_start = 0;
4837 m_line_end = LLDB_INVALID_LINE_NUMBER;
4838 m_file_name.clear();
4839 m_module_name.clear();
4840 m_func_name_type_mask = eFunctionNameTypeAuto;
4841 m_thread_id = LLDB_INVALID_THREAD_ID;
4842 m_thread_index = UINT32_MAX;
4843 m_thread_name.clear();
4844 m_queue_name.clear();
4845
4846 m_no_inlines = false;
4847 m_sym_ctx_specified = false;
4848 m_thread_specified = false;
4849
4850 m_use_one_liner = false;
4851 m_one_liner.clear();
4852 m_auto_continue = false;
4853 m_at_initial_stop = true;
4854 }
4855
4856 std::string m_class_name;
4857 std::string m_function_name;
4858 uint32_t m_line_start = 0;
4859 uint32_t m_line_end = LLDB_INVALID_LINE_NUMBER;
4860 std::string m_file_name;
4861 std::string m_module_name;
4862 uint32_t m_func_name_type_mask =
4863 eFunctionNameTypeAuto; // A pick from lldb::FunctionNameType.
4864 lldb::tid_t m_thread_id = LLDB_INVALID_THREAD_ID;
4865 uint32_t m_thread_index = UINT32_MAX;
4866 std::string m_thread_name;
4867 std::string m_queue_name;
4868 bool m_sym_ctx_specified = false;
4869 bool m_no_inlines = false;
4870 bool m_thread_specified = false;
4871 // Instance variables to hold the values for one_liner options.
4872 bool m_use_one_liner = false;
4873 std::vector<std::string> m_one_liner;
4874 bool m_at_initial_stop;
4875
4876 bool m_auto_continue = false;
4877 };
4878
4879 CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter)
4880 : CommandObjectParsed(interpreter, "target stop-hook add",
4881 "Add a hook to be executed when the target stops."
4882 "The hook can either be a list of commands or an "
4883 "appropriately defined Python class. You can also "
4884 "add filters so the hook only runs a certain stop "
4885 "points.",
4886 "target stop-hook add"),
4887 IOHandlerDelegateMultiline("DONE",
4888 IOHandlerDelegate::Completion::LLDBCommand),
4889 m_python_class_options("scripted stop-hook", true, 'P') {
4890 SetHelpLong(
4891 R"(
4892Command Based stop-hooks:
4893-------------------------
4894 Stop hooks can run a list of lldb commands by providing one or more
4895 --one-liner options. The commands will get run in the order they are added.
4896 Or you can provide no commands, in which case you will enter a command editor
4897 where you can enter the commands to be run.
4898
4899Python Based Stop Hooks:
4900------------------------
4901 Stop hooks can be implemented with a suitably defined Python class, whose name
4902 is passed in the --python-class option.
4903
4904 When the stop hook is added, the class is initialized by calling:
4905
4906 def __init__(self, target, extra_args, internal_dict):
4907
4908 target: The target that the stop hook is being added to.
4909 extra_args: An SBStructuredData Dictionary filled with the -key -value
4910 option pairs passed to the command.
4911 dict: An implementation detail provided by lldb.
4912
4913 Then when the stop-hook triggers, lldb will run the 'handle_stop' method.
4914 The method has the signature:
4915
4916 def handle_stop(self, exe_ctx, stream):
4917
4918 exe_ctx: An SBExecutionContext for the thread that has stopped.
4919 stream: An SBStream, anything written to this stream will be printed in the
4920 the stop message when the process stops.
4921
4922 Return Value: The method returns "should_stop". If should_stop is false
4923 from all the stop hook executions on threads that stopped
4924 with a reason, then the process will continue. Note that this
4925 will happen only after all the stop hooks are run.
4926
4927Filter Options:
4928---------------
4929 Stop hooks can be set to always run, or to only run when the stopped thread
4930 matches the filter options passed on the command line. The available filter
4931 options include a shared library or a thread or queue specification,
4932 a line range in a source file, a function name or a class name.
4933 )");
4934 m_all_options.Append(group: &m_python_class_options,
4935 LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
4936 LLDB_OPT_SET_FROM_TO(4, 6));
4937 m_all_options.Append(group: &m_options);
4938 m_all_options.Finalize();
4939 }
4940
4941 ~CommandObjectTargetStopHookAdd() override = default;
4942
4943 Options *GetOptions() override { return &m_all_options; }
4944
4945protected:
4946 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
4947 if (interactive) {
4948 if (lldb::LockableStreamFileSP output_sp =
4949 io_handler.GetOutputStreamFileSP()) {
4950 LockedStreamFile locked_stream = output_sp->Lock();
4951 locked_stream.PutCString(
4952 cstr: "Enter your stop hook command(s). Type 'DONE' to end.\n");
4953 }
4954 }
4955 }
4956
4957 void IOHandlerInputComplete(IOHandler &io_handler,
4958 std::string &line) override {
4959 if (m_stop_hook_sp) {
4960 if (line.empty()) {
4961 if (lldb::LockableStreamFileSP error_sp =
4962 io_handler.GetErrorStreamFileSP()) {
4963 LockedStreamFile locked_stream = error_sp->Lock();
4964 locked_stream.Printf(format: "error: stop hook #%" PRIu64
4965 " aborted, no commands.\n",
4966 m_stop_hook_sp->GetID());
4967 }
4968 GetTarget().UndoCreateStopHook(uid: m_stop_hook_sp->GetID());
4969 } else {
4970 // The IOHandler editor is only for command lines stop hooks:
4971 Target::StopHookCommandLine *hook_ptr =
4972 static_cast<Target::StopHookCommandLine *>(m_stop_hook_sp.get());
4973
4974 hook_ptr->SetActionFromString(line);
4975 if (lldb::LockableStreamFileSP output_sp =
4976 io_handler.GetOutputStreamFileSP()) {
4977 LockedStreamFile locked_stream = output_sp->Lock();
4978 locked_stream.Printf(format: "Stop hook #%" PRIu64 " added.\n",
4979 m_stop_hook_sp->GetID());
4980 }
4981 }
4982 m_stop_hook_sp.reset();
4983 }
4984 io_handler.SetIsDone(true);
4985 }
4986
4987 void DoExecute(Args &command, CommandReturnObject &result) override {
4988 m_stop_hook_sp.reset();
4989
4990 Target &target = GetTarget();
4991 Target::StopHookSP new_hook_sp =
4992 target.CreateStopHook(kind: m_python_class_options.GetName().empty() ?
4993 Target::StopHook::StopHookKind::CommandBased
4994 : Target::StopHook::StopHookKind::ScriptBased);
4995
4996 // First step, make the specifier.
4997 std::unique_ptr<SymbolContextSpecifier> specifier_up;
4998 if (m_options.m_sym_ctx_specified) {
4999 specifier_up = std::make_unique<SymbolContextSpecifier>(
5000 args: GetDebugger().GetSelectedTarget());
5001
5002 if (!m_options.m_module_name.empty()) {
5003 specifier_up->AddSpecification(
5004 spec_string: m_options.m_module_name.c_str(),
5005 type: SymbolContextSpecifier::eModuleSpecified);
5006 }
5007
5008 if (!m_options.m_class_name.empty()) {
5009 specifier_up->AddSpecification(
5010 spec_string: m_options.m_class_name.c_str(),
5011 type: SymbolContextSpecifier::eClassOrNamespaceSpecified);
5012 }
5013
5014 if (!m_options.m_file_name.empty()) {
5015 specifier_up->AddSpecification(spec_string: m_options.m_file_name.c_str(),
5016 type: SymbolContextSpecifier::eFileSpecified);
5017 }
5018
5019 if (m_options.m_line_start != 0) {
5020 specifier_up->AddLineSpecification(
5021 line_no: m_options.m_line_start,
5022 type: SymbolContextSpecifier::eLineStartSpecified);
5023 }
5024
5025 if (m_options.m_line_end != UINT_MAX) {
5026 specifier_up->AddLineSpecification(
5027 line_no: m_options.m_line_end, type: SymbolContextSpecifier::eLineEndSpecified);
5028 }
5029
5030 if (!m_options.m_function_name.empty()) {
5031 specifier_up->AddSpecification(
5032 spec_string: m_options.m_function_name.c_str(),
5033 type: SymbolContextSpecifier::eFunctionSpecified);
5034 }
5035 }
5036
5037 if (specifier_up)
5038 new_hook_sp->SetSpecifier(specifier_up.release());
5039
5040 // Should we run at the initial stop:
5041 new_hook_sp->SetRunAtInitialStop(m_options.m_at_initial_stop);
5042
5043 // Next see if any of the thread options have been entered:
5044
5045 if (m_options.m_thread_specified) {
5046 ThreadSpec *thread_spec = new ThreadSpec();
5047
5048 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) {
5049 thread_spec->SetTID(m_options.m_thread_id);
5050 }
5051
5052 if (m_options.m_thread_index != UINT32_MAX)
5053 thread_spec->SetIndex(m_options.m_thread_index);
5054
5055 if (!m_options.m_thread_name.empty())
5056 thread_spec->SetName(m_options.m_thread_name.c_str());
5057
5058 if (!m_options.m_queue_name.empty())
5059 thread_spec->SetQueueName(m_options.m_queue_name.c_str());
5060
5061 new_hook_sp->SetThreadSpecifier(thread_spec);
5062 }
5063
5064 new_hook_sp->SetAutoContinue(m_options.m_auto_continue);
5065 if (m_options.m_use_one_liner) {
5066 // This is a command line stop hook:
5067 Target::StopHookCommandLine *hook_ptr =
5068 static_cast<Target::StopHookCommandLine *>(new_hook_sp.get());
5069 hook_ptr->SetActionFromStrings(m_options.m_one_liner);
5070 result.AppendMessageWithFormat(format: "Stop hook #%" PRIu64 " added.\n",
5071 new_hook_sp->GetID());
5072 } else if (!m_python_class_options.GetName().empty()) {
5073 // This is a scripted stop hook:
5074 Target::StopHookScripted *hook_ptr =
5075 static_cast<Target::StopHookScripted *>(new_hook_sp.get());
5076 Status error = hook_ptr->SetScriptCallback(
5077 class_name: m_python_class_options.GetName(),
5078 extra_args_sp: m_python_class_options.GetStructuredData());
5079 if (error.Success())
5080 result.AppendMessageWithFormat(format: "Stop hook #%" PRIu64 " added.\n",
5081 new_hook_sp->GetID());
5082 else {
5083 // FIXME: Set the stop hook ID counter back.
5084 result.AppendErrorWithFormat(format: "Couldn't add stop hook: %s",
5085 error.AsCString());
5086 target.UndoCreateStopHook(uid: new_hook_sp->GetID());
5087 return;
5088 }
5089 } else {
5090 m_stop_hook_sp = new_hook_sp;
5091 m_interpreter.GetLLDBCommandsFromIOHandler(prompt: "> ", // Prompt
5092 delegate&: *this); // IOHandlerDelegate
5093 }
5094 result.SetStatus(eReturnStatusSuccessFinishNoResult);
5095 }
5096
5097private:
5098 CommandOptions m_options;
5099 OptionGroupPythonClassWithDict m_python_class_options;
5100 OptionGroupOptions m_all_options;
5101
5102 Target::StopHookSP m_stop_hook_sp;
5103};
5104
5105#pragma mark CommandObjectTargetStopHookDelete
5106
5107// CommandObjectTargetStopHookDelete
5108
5109class CommandObjectTargetStopHookDelete : public CommandObjectParsed {
5110public:
5111 CommandObjectTargetStopHookDelete(CommandInterpreter &interpreter)
5112 : CommandObjectParsed(interpreter, "target stop-hook delete",
5113 "Delete a stop-hook.",
5114 "target stop-hook delete [<idx>]") {
5115 AddSimpleArgumentList(arg_type: eArgTypeStopHookID, repetition_type: eArgRepeatStar);
5116 }
5117
5118 ~CommandObjectTargetStopHookDelete() override = default;
5119
5120 void
5121 HandleArgumentCompletion(CompletionRequest &request,
5122 OptionElementVector &opt_element_vector) override {
5123 if (request.GetCursorIndex())
5124 return;
5125 CommandObject::HandleArgumentCompletion(request, opt_element_vector);
5126 }
5127
5128protected:
5129 void DoExecute(Args &command, CommandReturnObject &result) override {
5130 Target &target = GetTarget();
5131 // FIXME: see if we can use the breakpoint id style parser?
5132 size_t num_args = command.GetArgumentCount();
5133 if (num_args == 0) {
5134 if (!m_interpreter.Confirm(message: "Delete all stop hooks?", default_answer: true)) {
5135 result.SetStatus(eReturnStatusFailed);
5136 return;
5137 } else {
5138 target.RemoveAllStopHooks();
5139 }
5140 } else {
5141 for (size_t i = 0; i < num_args; i++) {
5142 lldb::user_id_t user_id;
5143 if (!llvm::to_integer(S: command.GetArgumentAtIndex(idx: i), Num&: user_id)) {
5144 result.AppendErrorWithFormat(format: "invalid stop hook id: \"%s\".\n",
5145 command.GetArgumentAtIndex(idx: i));
5146 return;
5147 }
5148 if (!target.RemoveStopHookByID(uid: user_id)) {
5149 result.AppendErrorWithFormat(format: "unknown stop hook id: \"%s\".\n",
5150 command.GetArgumentAtIndex(idx: i));
5151 return;
5152 }
5153 }
5154 }
5155 result.SetStatus(eReturnStatusSuccessFinishNoResult);
5156 }
5157};
5158
5159#pragma mark CommandObjectTargetStopHookEnableDisable
5160
5161// CommandObjectTargetStopHookEnableDisable
5162
5163class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed {
5164public:
5165 CommandObjectTargetStopHookEnableDisable(CommandInterpreter &interpreter,
5166 bool enable, const char *name,
5167 const char *help, const char *syntax)
5168 : CommandObjectParsed(interpreter, name, help, syntax), m_enable(enable) {
5169 AddSimpleArgumentList(arg_type: eArgTypeStopHookID, repetition_type: eArgRepeatStar);
5170 }
5171
5172 ~CommandObjectTargetStopHookEnableDisable() override = default;
5173
5174 void
5175 HandleArgumentCompletion(CompletionRequest &request,
5176 OptionElementVector &opt_element_vector) override {
5177 if (request.GetCursorIndex())
5178 return;
5179 CommandObject::HandleArgumentCompletion(request, opt_element_vector);
5180 }
5181
5182protected:
5183 void DoExecute(Args &command, CommandReturnObject &result) override {
5184 Target &target = GetTarget();
5185 // FIXME: see if we can use the breakpoint id style parser?
5186 size_t num_args = command.GetArgumentCount();
5187 bool success;
5188
5189 if (num_args == 0) {
5190 target.SetAllStopHooksActiveState(m_enable);
5191 } else {
5192 for (size_t i = 0; i < num_args; i++) {
5193 lldb::user_id_t user_id;
5194 if (!llvm::to_integer(S: command.GetArgumentAtIndex(idx: i), Num&: user_id)) {
5195 result.AppendErrorWithFormat(format: "invalid stop hook id: \"%s\".\n",
5196 command.GetArgumentAtIndex(idx: i));
5197 return;
5198 }
5199 success = target.SetStopHookActiveStateByID(uid: user_id, active_state: m_enable);
5200 if (!success) {
5201 result.AppendErrorWithFormat(format: "unknown stop hook id: \"%s\".\n",
5202 command.GetArgumentAtIndex(idx: i));
5203 return;
5204 }
5205 }
5206 }
5207 result.SetStatus(eReturnStatusSuccessFinishNoResult);
5208 }
5209
5210private:
5211 bool m_enable;
5212};
5213
5214#pragma mark CommandObjectTargetStopHookList
5215
5216// CommandObjectTargetStopHookList
5217
5218class CommandObjectTargetStopHookList : public CommandObjectParsed {
5219public:
5220 CommandObjectTargetStopHookList(CommandInterpreter &interpreter)
5221 : CommandObjectParsed(interpreter, "target stop-hook list",
5222 "List all stop-hooks.", "target stop-hook list") {}
5223
5224 ~CommandObjectTargetStopHookList() override = default;
5225
5226protected:
5227 void DoExecute(Args &command, CommandReturnObject &result) override {
5228 Target &target = GetTarget();
5229
5230 size_t num_hooks = target.GetNumStopHooks();
5231 if (num_hooks == 0) {
5232 result.GetOutputStream().PutCString(cstr: "No stop hooks.\n");
5233 } else {
5234 for (size_t i = 0; i < num_hooks; i++) {
5235 Target::StopHookSP this_hook = target.GetStopHookAtIndex(index: i);
5236 if (i > 0)
5237 result.GetOutputStream().PutCString(cstr: "\n");
5238 this_hook->GetDescription(s&: result.GetOutputStream(),
5239 level: eDescriptionLevelFull);
5240 }
5241 }
5242 result.SetStatus(eReturnStatusSuccessFinishResult);
5243 }
5244};
5245
5246#pragma mark CommandObjectMultiwordTargetStopHooks
5247
5248// CommandObjectMultiwordTargetStopHooks
5249
5250class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword {
5251public:
5252 CommandObjectMultiwordTargetStopHooks(CommandInterpreter &interpreter)
5253 : CommandObjectMultiword(
5254 interpreter, "target stop-hook",
5255 "Commands for operating on debugger target stop-hooks.",
5256 "target stop-hook <subcommand> [<subcommand-options>]") {
5257 LoadSubCommand(cmd_name: "add", command_obj: CommandObjectSP(
5258 new CommandObjectTargetStopHookAdd(interpreter)));
5259 LoadSubCommand(
5260 cmd_name: "delete",
5261 command_obj: CommandObjectSP(new CommandObjectTargetStopHookDelete(interpreter)));
5262 LoadSubCommand(cmd_name: "disable",
5263 command_obj: CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
5264 interpreter, false, "target stop-hook disable [<id>]",
5265 "Disable a stop-hook.", "target stop-hook disable")));
5266 LoadSubCommand(cmd_name: "enable",
5267 command_obj: CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
5268 interpreter, true, "target stop-hook enable [<id>]",
5269 "Enable a stop-hook.", "target stop-hook enable")));
5270 LoadSubCommand(cmd_name: "list", command_obj: CommandObjectSP(new CommandObjectTargetStopHookList(
5271 interpreter)));
5272 }
5273
5274 ~CommandObjectMultiwordTargetStopHooks() override = default;
5275};
5276
5277#pragma mark CommandObjectTargetDumpTypesystem
5278
5279/// Dumps the TypeSystem of the selected Target.
5280class CommandObjectTargetDumpTypesystem : public CommandObjectParsed {
5281public:
5282 CommandObjectTargetDumpTypesystem(CommandInterpreter &interpreter)
5283 : CommandObjectParsed(
5284 interpreter, "target dump typesystem",
5285 "Dump the state of the target's internal type system. Intended to "
5286 "be used for debugging LLDB itself.",
5287 nullptr, eCommandRequiresTarget) {}
5288
5289 ~CommandObjectTargetDumpTypesystem() override = default;
5290
5291protected:
5292 void DoExecute(Args &command, CommandReturnObject &result) override {
5293 // Go over every scratch TypeSystem and dump to the command output.
5294 for (lldb::TypeSystemSP ts : GetTarget().GetScratchTypeSystems())
5295 if (ts)
5296 ts->Dump(output&: result.GetOutputStream().AsRawOstream(), filter: "");
5297
5298 result.SetStatus(eReturnStatusSuccessFinishResult);
5299 }
5300};
5301
5302#pragma mark CommandObjectTargetDumpSectionLoadList
5303
5304/// Dumps the SectionLoadList of the selected Target.
5305class CommandObjectTargetDumpSectionLoadList : public CommandObjectParsed {
5306public:
5307 CommandObjectTargetDumpSectionLoadList(CommandInterpreter &interpreter)
5308 : CommandObjectParsed(
5309 interpreter, "target dump section-load-list",
5310 "Dump the state of the target's internal section load list. "
5311 "Intended to be used for debugging LLDB itself.",
5312 nullptr, eCommandRequiresTarget) {}
5313
5314 ~CommandObjectTargetDumpSectionLoadList() override = default;
5315
5316protected:
5317 void DoExecute(Args &command, CommandReturnObject &result) override {
5318 Target &target = GetTarget();
5319 target.DumpSectionLoadList(s&: result.GetOutputStream());
5320 result.SetStatus(eReturnStatusSuccessFinishResult);
5321 }
5322};
5323
5324#pragma mark CommandObjectTargetDump
5325
5326/// Multi-word command for 'target dump'.
5327class CommandObjectTargetDump : public CommandObjectMultiword {
5328public:
5329 // Constructors and Destructors
5330 CommandObjectTargetDump(CommandInterpreter &interpreter)
5331 : CommandObjectMultiword(
5332 interpreter, "target dump",
5333 "Commands for dumping information about the target.",
5334 "target dump [typesystem|section-load-list]") {
5335 LoadSubCommand(
5336 cmd_name: "typesystem",
5337 command_obj: CommandObjectSP(new CommandObjectTargetDumpTypesystem(interpreter)));
5338 LoadSubCommand(cmd_name: "section-load-list",
5339 command_obj: CommandObjectSP(new CommandObjectTargetDumpSectionLoadList(
5340 interpreter)));
5341 }
5342
5343 ~CommandObjectTargetDump() override = default;
5344};
5345
5346#pragma mark CommandObjectMultiwordTarget
5347
5348// CommandObjectMultiwordTarget
5349
5350CommandObjectMultiwordTarget::CommandObjectMultiwordTarget(
5351 CommandInterpreter &interpreter)
5352 : CommandObjectMultiword(interpreter, "target",
5353 "Commands for operating on debugger targets.",
5354 "target <subcommand> [<subcommand-options>]") {
5355 LoadSubCommand(cmd_name: "create",
5356 command_obj: CommandObjectSP(new CommandObjectTargetCreate(interpreter)));
5357 LoadSubCommand(cmd_name: "delete",
5358 command_obj: CommandObjectSP(new CommandObjectTargetDelete(interpreter)));
5359 LoadSubCommand(cmd_name: "dump",
5360 command_obj: CommandObjectSP(new CommandObjectTargetDump(interpreter)));
5361 LoadSubCommand(cmd_name: "list",
5362 command_obj: CommandObjectSP(new CommandObjectTargetList(interpreter)));
5363 LoadSubCommand(cmd_name: "select",
5364 command_obj: CommandObjectSP(new CommandObjectTargetSelect(interpreter)));
5365 LoadSubCommand(cmd_name: "show-launch-environment",
5366 command_obj: CommandObjectSP(new CommandObjectTargetShowLaunchEnvironment(
5367 interpreter)));
5368 LoadSubCommand(
5369 cmd_name: "stop-hook",
5370 command_obj: CommandObjectSP(new CommandObjectMultiwordTargetStopHooks(interpreter)));
5371 LoadSubCommand(cmd_name: "modules",
5372 command_obj: CommandObjectSP(new CommandObjectTargetModules(interpreter)));
5373 LoadSubCommand(cmd_name: "symbols",
5374 command_obj: CommandObjectSP(new CommandObjectTargetSymbols(interpreter)));
5375 LoadSubCommand(cmd_name: "variable",
5376 command_obj: CommandObjectSP(new CommandObjectTargetVariable(interpreter)));
5377}
5378
5379CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget() = default;
5380

source code of lldb/source/Commands/CommandObjectTarget.cpp