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