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