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