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