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