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