xref: /llvm-project/lldb/tools/lldb-test/lldb-test.cpp (revision 3aef968ec3faada22319aaa3530776974082d2d5)
1 //===- lldb-test.cpp ------------------------------------------ *- C++ --*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "FormatUtil.h"
10 #include "SystemInitializerTest.h"
11 
12 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
13 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
14 #include "lldb/Breakpoint/BreakpointLocation.h"
15 #include "lldb/Core/Debugger.h"
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/Section.h"
18 #include "lldb/Expression/IRMemoryMap.h"
19 #include "lldb/Initialization/SystemLifetimeManager.h"
20 #include "lldb/Interpreter/CommandInterpreter.h"
21 #include "lldb/Interpreter/CommandReturnObject.h"
22 #include "lldb/Symbol/CompileUnit.h"
23 #include "lldb/Symbol/LineTable.h"
24 #include "lldb/Symbol/SymbolFile.h"
25 #include "lldb/Symbol/Symtab.h"
26 #include "lldb/Symbol/TypeList.h"
27 #include "lldb/Symbol/TypeMap.h"
28 #include "lldb/Symbol/VariableList.h"
29 #include "lldb/Target/Language.h"
30 #include "lldb/Target/Process.h"
31 #include "lldb/Target/Target.h"
32 #include "lldb/Utility/DataExtractor.h"
33 #include "lldb/Utility/LLDBAssert.h"
34 #include "lldb/Utility/State.h"
35 #include "lldb/Utility/StreamString.h"
36 
37 #include "llvm/ADT/IntervalMap.h"
38 #include "llvm/ADT/ScopeExit.h"
39 #include "llvm/ADT/StringRef.h"
40 #include "llvm/Support/CommandLine.h"
41 #include "llvm/Support/ManagedStatic.h"
42 #include "llvm/Support/MathExtras.h"
43 #include "llvm/Support/Path.h"
44 #include "llvm/Support/PrettyStackTrace.h"
45 #include "llvm/Support/Signals.h"
46 #include "llvm/Support/WithColor.h"
47 
48 #include <cstdio>
49 #include <thread>
50 
51 using namespace lldb;
52 using namespace lldb_private;
53 using namespace llvm;
54 
55 namespace opts {
56 static cl::SubCommand BreakpointSubcommand("breakpoints",
57                                            "Test breakpoint resolution");
58 cl::SubCommand ObjectFileSubcommand("object-file",
59                                     "Display LLDB object file information");
60 cl::SubCommand SymbolsSubcommand("symbols", "Dump symbols for an object file");
61 cl::SubCommand SymTabSubcommand("symtab",
62                                 "Test symbol table functionality");
63 cl::SubCommand IRMemoryMapSubcommand("ir-memory-map", "Test IRMemoryMap");
64 cl::SubCommand AssertSubcommand("assert", "Test assert handling");
65 
66 cl::opt<std::string> Log("log", cl::desc("Path to a log file"), cl::init(""),
67                          cl::sub(BreakpointSubcommand),
68                          cl::sub(ObjectFileSubcommand),
69                          cl::sub(SymbolsSubcommand),
70                          cl::sub(SymTabSubcommand),
71                          cl::sub(IRMemoryMapSubcommand));
72 
73 /// Create a target using the file pointed to by \p Filename, or abort.
74 TargetSP createTarget(Debugger &Dbg, const std::string &Filename);
75 
76 /// Read \p Filename into a null-terminated buffer, or abort.
77 std::unique_ptr<MemoryBuffer> openFile(const std::string &Filename);
78 
79 namespace breakpoint {
80 static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
81                                    cl::Required, cl::sub(BreakpointSubcommand));
82 static cl::opt<std::string> CommandFile(cl::Positional,
83                                         cl::desc("<command-file>"),
84                                         cl::init("-"),
85                                         cl::sub(BreakpointSubcommand));
86 static cl::opt<bool> Persistent(
87     "persistent",
88     cl::desc("Don't automatically remove all breakpoints before each command"),
89     cl::sub(BreakpointSubcommand));
90 
91 static llvm::StringRef plural(uintmax_t value) { return value == 1 ? "" : "s"; }
92 static void dumpState(const BreakpointList &List, LinePrinter &P);
93 static std::string substitute(StringRef Cmd);
94 static int evaluateBreakpoints(Debugger &Dbg);
95 } // namespace breakpoint
96 
97 namespace object {
98 cl::opt<bool> SectionContents("contents",
99                               cl::desc("Dump each section's contents"),
100                               cl::sub(ObjectFileSubcommand));
101 cl::opt<bool> SectionDependentModules("dep-modules",
102                                       cl::desc("Dump each dependent module"),
103                                       cl::sub(ObjectFileSubcommand));
104 cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
105                                      cl::OneOrMore,
106                                      cl::sub(ObjectFileSubcommand));
107 } // namespace object
108 
109 namespace symtab {
110 
111 /// The same enum as Mangled::NamePreference but with a default
112 /// 'None' case. This is needed to disambiguate wheter "ManglingPreference" was
113 /// explicitly set or not.
114 enum class ManglingPreference {
115   None,
116   Mangled,
117   Demangled,
118   MangledWithoutArguments,
119 };
120 
121 static cl::opt<std::string> FindSymbolsByRegex(
122     "find-symbols-by-regex",
123     cl::desc(
124         "Dump symbols found in the symbol table matching the specified regex."),
125     cl::sub(SymTabSubcommand));
126 
127 static cl::opt<ManglingPreference> ManglingPreference(
128     "mangling-preference",
129     cl::desc("Preference on mangling scheme the regex should match against and "
130              "dumped."),
131     cl::values(
132         clEnumValN(ManglingPreference::Mangled, "mangled", "Prefer mangled"),
133         clEnumValN(ManglingPreference::Demangled, "demangled",
134                    "Prefer demangled"),
135         clEnumValN(ManglingPreference::MangledWithoutArguments,
136                    "demangled-without-args", "Prefer mangled without args")),
137     cl::sub(SymTabSubcommand));
138 
139 static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
140                                       cl::Required, cl::sub(SymTabSubcommand));
141 
142 /// Validate that the options passed make sense.
143 static llvm::Optional<llvm::Error> validate();
144 
145 /// Transforms the selected mangling preference into a Mangled::NamePreference
146 static Mangled::NamePreference getNamePreference();
147 
148 static int handleSymtabCommand(Debugger &Dbg);
149 } // namespace symtab
150 
151 namespace symbols {
152 static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
153                                       cl::Required, cl::sub(SymbolsSubcommand));
154 
155 static cl::opt<std::string>
156     SymbolPath("symbol-file",
157                cl::desc("The file from which to fetch symbol information."),
158                cl::value_desc("file"), cl::sub(SymbolsSubcommand));
159 
160 enum class FindType {
161   None,
162   Function,
163   Block,
164   Namespace,
165   Type,
166   Variable,
167 };
168 static cl::opt<FindType> Find(
169     "find", cl::desc("Choose search type:"),
170     cl::values(
171         clEnumValN(FindType::None, "none", "No search, just dump the module."),
172         clEnumValN(FindType::Function, "function", "Find functions."),
173         clEnumValN(FindType::Block, "block", "Find blocks."),
174         clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
175         clEnumValN(FindType::Type, "type", "Find types."),
176         clEnumValN(FindType::Variable, "variable", "Find global variables.")),
177     cl::sub(SymbolsSubcommand));
178 
179 static cl::opt<std::string> Name("name", cl::desc("Name to find."),
180                                  cl::sub(SymbolsSubcommand));
181 static cl::opt<bool>
182     Regex("regex",
183           cl::desc("Search using regular expressions (available for variables "
184                    "and functions only)."),
185           cl::sub(SymbolsSubcommand));
186 static cl::opt<std::string>
187     Context("context",
188             cl::desc("Restrict search to the context of the given variable."),
189             cl::value_desc("variable"), cl::sub(SymbolsSubcommand));
190 
191 static cl::opt<std::string> CompilerContext(
192     "compiler-context",
193     cl::desc("Specify a compiler context as \"kind:name,...\"."),
194     cl::value_desc("context"), cl::sub(SymbolsSubcommand));
195 
196 static cl::opt<std::string>
197     Language("language", cl::desc("Specify a language type, like C99."),
198              cl::value_desc("language"), cl::sub(SymbolsSubcommand));
199 
200 static cl::list<FunctionNameType> FunctionNameFlags(
201     "function-flags", cl::desc("Function search flags:"),
202     cl::values(clEnumValN(eFunctionNameTypeAuto, "auto",
203                           "Automatically deduce flags based on name."),
204                clEnumValN(eFunctionNameTypeFull, "full", "Full function name."),
205                clEnumValN(eFunctionNameTypeBase, "base", "Base name."),
206                clEnumValN(eFunctionNameTypeMethod, "method", "Method name."),
207                clEnumValN(eFunctionNameTypeSelector, "selector",
208                           "Selector name.")),
209     cl::sub(SymbolsSubcommand));
210 static FunctionNameType getFunctionNameFlags() {
211   FunctionNameType Result = FunctionNameType(0);
212   for (FunctionNameType Flag : FunctionNameFlags)
213     Result = FunctionNameType(Result | Flag);
214   return Result;
215 }
216 
217 static cl::opt<bool> DumpAST("dump-ast",
218                              cl::desc("Dump AST restored from symbols."),
219                              cl::sub(SymbolsSubcommand));
220 static cl::opt<bool> DumpClangAST(
221     "dump-clang-ast",
222     cl::desc("Dump clang AST restored from symbols. When used on its own this "
223              "will dump the entire AST of all loaded symbols. When combined "
224              "with -find, it changes the presentation of the search results "
225              "from pretty-printing the types to an AST dump."),
226     cl::sub(SymbolsSubcommand));
227 
228 static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
229                             cl::sub(SymbolsSubcommand));
230 
231 static cl::opt<std::string> File("file",
232                                  cl::desc("File (compile unit) to search."),
233                                  cl::sub(SymbolsSubcommand));
234 static cl::opt<int> Line("line", cl::desc("Line to search."),
235                          cl::sub(SymbolsSubcommand));
236 
237 static Expected<CompilerDeclContext> getDeclContext(SymbolFile &Symfile);
238 
239 static Error findFunctions(lldb_private::Module &Module);
240 static Error findBlocks(lldb_private::Module &Module);
241 static Error findNamespaces(lldb_private::Module &Module);
242 static Error findTypes(lldb_private::Module &Module);
243 static Error findVariables(lldb_private::Module &Module);
244 static Error dumpModule(lldb_private::Module &Module);
245 static Error dumpAST(lldb_private::Module &Module);
246 static Error dumpEntireClangAST(lldb_private::Module &Module);
247 static Error verify(lldb_private::Module &Module);
248 
249 static Expected<Error (*)(lldb_private::Module &)> getAction();
250 static int dumpSymbols(Debugger &Dbg);
251 } // namespace symbols
252 
253 namespace irmemorymap {
254 static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
255                                    cl::Required,
256                                    cl::sub(IRMemoryMapSubcommand));
257 static cl::opt<std::string> CommandFile(cl::Positional,
258                                         cl::desc("<command-file>"),
259                                         cl::init("-"),
260                                         cl::sub(IRMemoryMapSubcommand));
261 static cl::opt<bool> UseHostOnlyAllocationPolicy(
262     "host-only", cl::desc("Use the host-only allocation policy"),
263     cl::init(false), cl::sub(IRMemoryMapSubcommand));
264 
265 using AllocationT = std::pair<addr_t, addr_t>;
266 using AddrIntervalMap =
267     IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>;
268 
269 struct IRMemoryMapTestState {
270   TargetSP Target;
271   IRMemoryMap Map;
272 
273   AddrIntervalMap::Allocator IntervalMapAllocator;
274   AddrIntervalMap Allocations;
275 
276   StringMap<addr_t> Label2AddrMap;
277 
278   IRMemoryMapTestState(TargetSP Target)
279       : Target(Target), Map(Target), Allocations(IntervalMapAllocator) {}
280 };
281 
282 bool evalMalloc(StringRef Line, IRMemoryMapTestState &State);
283 bool evalFree(StringRef Line, IRMemoryMapTestState &State);
284 int evaluateMemoryMapCommands(Debugger &Dbg);
285 } // namespace irmemorymap
286 
287 namespace assert {
288 int lldb_assert(Debugger &Dbg);
289 } // namespace assert
290 } // namespace opts
291 
292 std::vector<CompilerContext> parseCompilerContext() {
293   std::vector<CompilerContext> result;
294   if (opts::symbols::CompilerContext.empty())
295     return result;
296 
297   StringRef str{opts::symbols::CompilerContext};
298   SmallVector<StringRef, 8> entries_str;
299   str.split(entries_str, ',', /*maxSplit*/-1, /*keepEmpty=*/false);
300   for (auto entry_str : entries_str) {
301     StringRef key, value;
302     std::tie(key, value) = entry_str.split(':');
303     auto kind =
304         StringSwitch<CompilerContextKind>(key)
305             .Case("TranslationUnit", CompilerContextKind::TranslationUnit)
306             .Case("Module", CompilerContextKind::Module)
307             .Case("Namespace", CompilerContextKind::Namespace)
308             .Case("Class", CompilerContextKind::Class)
309             .Case("Struct", CompilerContextKind::Struct)
310             .Case("Union", CompilerContextKind::Union)
311             .Case("Function", CompilerContextKind::Function)
312             .Case("Variable", CompilerContextKind::Variable)
313             .Case("Enum", CompilerContextKind::Enum)
314             .Case("Typedef", CompilerContextKind::Typedef)
315             .Case("AnyModule", CompilerContextKind::AnyModule)
316             .Case("AnyType", CompilerContextKind::AnyType)
317             .Default(CompilerContextKind::Invalid);
318     if (value.empty()) {
319       WithColor::error() << "compiler context entry has no \"name\"\n";
320       exit(1);
321     }
322     result.push_back({kind, ConstString{value}});
323   }
324   outs() << "Search context: {\n";
325   for (auto entry: result)
326     entry.Dump();
327   outs() << "}\n";
328 
329   return result;
330 }
331 
332 template <typename... Args>
333 static Error make_string_error(const char *Format, Args &&... args) {
334   return llvm::make_error<llvm::StringError>(
335       llvm::formatv(Format, std::forward<Args>(args)...).str(),
336       llvm::inconvertibleErrorCode());
337 }
338 
339 TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) {
340   TargetSP Target;
341   Status ST = Dbg.GetTargetList().CreateTarget(
342       Dbg, Filename, /*triple*/ "", eLoadDependentsNo,
343       /*platform_options*/ nullptr, Target);
344   if (ST.Fail()) {
345     errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST);
346     exit(1);
347   }
348   return Target;
349 }
350 
351 std::unique_ptr<MemoryBuffer> opts::openFile(const std::string &Filename) {
352   auto MB = MemoryBuffer::getFileOrSTDIN(Filename);
353   if (!MB) {
354     errs() << formatv("Could not open file '{0}: {1}\n", Filename,
355                       MB.getError().message());
356     exit(1);
357   }
358   return std::move(*MB);
359 }
360 
361 void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) {
362   P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize()));
363   if (List.GetSize() > 0)
364     P.formatLine("At least one breakpoint.");
365   for (size_t i = 0, e = List.GetSize(); i < e; ++i) {
366     BreakpointSP BP = List.GetBreakpointAtIndex(i);
367     P.formatLine("Breakpoint ID {0}:", BP->GetID());
368     AutoIndent Indent(P, 2);
369     P.formatLine("{0} location{1}.", BP->GetNumLocations(),
370                  plural(BP->GetNumLocations()));
371     if (BP->GetNumLocations() > 0)
372       P.formatLine("At least one location.");
373     P.formatLine("{0} resolved location{1}.", BP->GetNumResolvedLocations(),
374                  plural(BP->GetNumResolvedLocations()));
375     if (BP->GetNumResolvedLocations() > 0)
376       P.formatLine("At least one resolved location.");
377     for (size_t l = 0, le = BP->GetNumLocations(); l < le; ++l) {
378       BreakpointLocationSP Loc = BP->GetLocationAtIndex(l);
379       P.formatLine("Location ID {0}:", Loc->GetID());
380       AutoIndent Indent(P, 2);
381       P.formatLine("Enabled: {0}", Loc->IsEnabled());
382       P.formatLine("Resolved: {0}", Loc->IsResolved());
383       SymbolContext sc;
384       Loc->GetAddress().CalculateSymbolContext(&sc);
385       lldb_private::StreamString S;
386       sc.DumpStopContext(&S, BP->GetTarget().GetProcessSP().get(),
387                          Loc->GetAddress(), false, true, false, true, true);
388       P.formatLine("Address: {0}", S.GetString());
389     }
390   }
391   P.NewLine();
392 }
393 
394 std::string opts::breakpoint::substitute(StringRef Cmd) {
395   std::string Result;
396   raw_string_ostream OS(Result);
397   while (!Cmd.empty()) {
398     switch (Cmd[0]) {
399     case '%':
400       if (Cmd.consume_front("%p") && (Cmd.empty() || !isalnum(Cmd[0]))) {
401         OS << sys::path::parent_path(breakpoint::CommandFile);
402         break;
403       }
404       LLVM_FALLTHROUGH;
405     default:
406       size_t pos = Cmd.find('%');
407       OS << Cmd.substr(0, pos);
408       Cmd = Cmd.substr(pos);
409       break;
410     }
411   }
412   return std::move(OS.str());
413 }
414 
415 int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
416   TargetSP Target = opts::createTarget(Dbg, breakpoint::Target);
417   std::unique_ptr<MemoryBuffer> MB = opts::openFile(breakpoint::CommandFile);
418 
419   LinePrinter P(4, outs());
420   StringRef Rest = MB->getBuffer();
421   int HadErrors = 0;
422   while (!Rest.empty()) {
423     StringRef Line;
424     std::tie(Line, Rest) = Rest.split('\n');
425     Line = Line.ltrim().rtrim();
426     if (Line.empty() || Line[0] == '#')
427       continue;
428 
429     if (!Persistent)
430       Target->RemoveAllBreakpoints(/*internal_also*/ true);
431 
432     std::string Command = substitute(Line);
433     P.formatLine("Command: {0}", Command);
434     CommandReturnObject Result(/*colors*/ false);
435     if (!Dbg.GetCommandInterpreter().HandleCommand(
436             Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
437       P.formatLine("Failed: {0}", Result.GetErrorData());
438       HadErrors = 1;
439       continue;
440     }
441 
442     dumpState(Target->GetBreakpointList(/*internal*/ false), P);
443   }
444   return HadErrors;
445 }
446 
447 Expected<CompilerDeclContext>
448 opts::symbols::getDeclContext(SymbolFile &Symfile) {
449   if (Context.empty())
450     return CompilerDeclContext();
451   VariableList List;
452   Symfile.FindGlobalVariables(ConstString(Context), CompilerDeclContext(),
453                               UINT32_MAX, List);
454   if (List.Empty())
455     return make_string_error("Context search didn't find a match.");
456   if (List.GetSize() > 1)
457     return make_string_error("Context search found multiple matches.");
458   return List.GetVariableAtIndex(0)->GetDeclContext();
459 }
460 
461 static lldb::DescriptionLevel GetDescriptionLevel() {
462   return opts::symbols::DumpClangAST ? eDescriptionLevelVerbose : eDescriptionLevelFull;
463 }
464 
465 Error opts::symbols::findFunctions(lldb_private::Module &Module) {
466   SymbolFile &Symfile = *Module.GetSymbolFile();
467   SymbolContextList List;
468   if (!File.empty()) {
469     assert(Line != 0);
470 
471     FileSpec src_file(File);
472     size_t cu_count = Module.GetNumCompileUnits();
473     for (size_t i = 0; i < cu_count; i++) {
474       lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
475       if (!cu_sp)
476         continue;
477 
478       LineEntry le;
479       cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
480       if (!le.IsValid())
481         continue;
482       const bool include_inlined_functions = false;
483       auto addr =
484           le.GetSameLineContiguousAddressRange(include_inlined_functions)
485               .GetBaseAddress();
486       if (!addr.IsValid())
487         continue;
488 
489       SymbolContext sc;
490       uint32_t resolved =
491           addr.CalculateSymbolContext(&sc, eSymbolContextFunction);
492       if (resolved & eSymbolContextFunction)
493         List.Append(sc);
494     }
495   } else if (Regex) {
496     RegularExpression RE(Name);
497     assert(RE.IsValid());
498     List.Clear();
499     Symfile.FindFunctions(RE, true, List);
500   } else {
501     Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
502     if (!ContextOr)
503       return ContextOr.takeError();
504     const CompilerDeclContext &ContextPtr =
505         ContextOr->IsValid() ? *ContextOr : CompilerDeclContext();
506 
507     List.Clear();
508     Symfile.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
509                          true, List);
510   }
511   outs() << formatv("Found {0} functions:\n", List.GetSize());
512   StreamString Stream;
513   List.Dump(&Stream, nullptr);
514   outs() << Stream.GetData() << "\n";
515   return Error::success();
516 }
517 
518 Error opts::symbols::findBlocks(lldb_private::Module &Module) {
519   assert(!Regex);
520   assert(!File.empty());
521   assert(Line != 0);
522 
523   SymbolContextList List;
524 
525   FileSpec src_file(File);
526   size_t cu_count = Module.GetNumCompileUnits();
527   for (size_t i = 0; i < cu_count; i++) {
528     lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
529     if (!cu_sp)
530       continue;
531 
532     LineEntry le;
533     cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
534     if (!le.IsValid())
535       continue;
536     const bool include_inlined_functions = false;
537     auto addr = le.GetSameLineContiguousAddressRange(include_inlined_functions)
538                     .GetBaseAddress();
539     if (!addr.IsValid())
540       continue;
541 
542     SymbolContext sc;
543     uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock);
544     if (resolved & eSymbolContextBlock)
545       List.Append(sc);
546   }
547 
548   outs() << formatv("Found {0} blocks:\n", List.GetSize());
549   StreamString Stream;
550   List.Dump(&Stream, nullptr);
551   outs() << Stream.GetData() << "\n";
552   return Error::success();
553 }
554 
555 Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
556   SymbolFile &Symfile = *Module.GetSymbolFile();
557   Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
558   if (!ContextOr)
559     return ContextOr.takeError();
560   const CompilerDeclContext &ContextPtr =
561       ContextOr->IsValid() ? *ContextOr : CompilerDeclContext();
562 
563   CompilerDeclContext Result =
564       Symfile.FindNamespace(ConstString(Name), ContextPtr);
565   if (Result)
566     outs() << "Found namespace: "
567            << Result.GetScopeQualifiedName().GetStringRef() << "\n";
568   else
569     outs() << "Namespace not found.\n";
570   return Error::success();
571 }
572 
573 Error opts::symbols::findTypes(lldb_private::Module &Module) {
574   SymbolFile &Symfile = *Module.GetSymbolFile();
575   Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
576   if (!ContextOr)
577     return ContextOr.takeError();
578   const CompilerDeclContext &ContextPtr =
579       ContextOr->IsValid() ? *ContextOr : CompilerDeclContext();
580 
581   LanguageSet languages;
582   if (!Language.empty())
583     languages.Insert(Language::GetLanguageTypeFromString(Language));
584 
585   DenseSet<SymbolFile *> SearchedFiles;
586   TypeMap Map;
587   if (!Name.empty())
588     Symfile.FindTypes(ConstString(Name), ContextPtr, UINT32_MAX, SearchedFiles,
589                       Map);
590   else
591     Module.FindTypes(parseCompilerContext(), languages, SearchedFiles, Map);
592 
593   outs() << formatv("Found {0} types:\n", Map.GetSize());
594   StreamString Stream;
595   // Resolve types to force-materialize typedef types.
596   Map.ForEach([&](TypeSP &type) {
597     type->GetFullCompilerType();
598     return false;
599   });
600   Map.Dump(&Stream, false, GetDescriptionLevel());
601   outs() << Stream.GetData() << "\n";
602   return Error::success();
603 }
604 
605 Error opts::symbols::findVariables(lldb_private::Module &Module) {
606   SymbolFile &Symfile = *Module.GetSymbolFile();
607   VariableList List;
608   if (Regex) {
609     RegularExpression RE(Name);
610     assert(RE.IsValid());
611     Symfile.FindGlobalVariables(RE, UINT32_MAX, List);
612   } else if (!File.empty()) {
613     CompUnitSP CU;
614     for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) {
615       CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind);
616       if (!Candidate ||
617           Candidate->GetPrimaryFile().GetFilename().GetStringRef() != File)
618         continue;
619       if (CU)
620         return make_string_error("Multiple compile units for file `{0}` found.",
621                                  File);
622       CU = std::move(Candidate);
623     }
624 
625     if (!CU)
626       return make_string_error("Compile unit `{0}` not found.", File);
627 
628     List.AddVariables(CU->GetVariableList(true).get());
629   } else {
630     Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
631     if (!ContextOr)
632       return ContextOr.takeError();
633     const CompilerDeclContext &ContextPtr =
634         ContextOr->IsValid() ? *ContextOr : CompilerDeclContext();
635 
636     Symfile.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List);
637   }
638   outs() << formatv("Found {0} variables:\n", List.GetSize());
639   StreamString Stream;
640   List.Dump(&Stream, false);
641   outs() << Stream.GetData() << "\n";
642   return Error::success();
643 }
644 
645 Error opts::symbols::dumpModule(lldb_private::Module &Module) {
646   StreamString Stream;
647   Module.ParseAllDebugSymbols();
648   Module.Dump(&Stream);
649   outs() << Stream.GetData() << "\n";
650   return Error::success();
651 }
652 
653 Error opts::symbols::dumpAST(lldb_private::Module &Module) {
654   Module.ParseAllDebugSymbols();
655 
656   SymbolFile *symfile = Module.GetSymbolFile();
657   if (!symfile)
658     return make_string_error("Module has no symbol file.");
659 
660   llvm::Expected<TypeSystem &> type_system_or_err =
661       symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
662   if (!type_system_or_err)
663     return make_string_error("Can't retrieve TypeSystemClang");
664 
665   auto *clang_ast_ctx =
666       llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get());
667   if (!clang_ast_ctx)
668     return make_string_error("Retrieved TypeSystem was not a TypeSystemClang");
669 
670   clang::ASTContext &ast_ctx = clang_ast_ctx->getASTContext();
671 
672   clang::TranslationUnitDecl *tu = ast_ctx.getTranslationUnitDecl();
673   if (!tu)
674     return make_string_error("Can't retrieve translation unit declaration.");
675 
676   tu->print(outs());
677 
678   return Error::success();
679 }
680 
681 Error opts::symbols::dumpEntireClangAST(lldb_private::Module &Module) {
682   Module.ParseAllDebugSymbols();
683 
684   SymbolFile *symfile = Module.GetSymbolFile();
685   if (!symfile)
686     return make_string_error("Module has no symbol file.");
687 
688   llvm::Expected<TypeSystem &> type_system_or_err =
689       symfile->GetTypeSystemForLanguage(eLanguageTypeObjC_plus_plus);
690   if (!type_system_or_err)
691     return make_string_error("Can't retrieve TypeSystemClang");
692 
693   auto *clang_ast_ctx =
694       llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get());
695   if (!clang_ast_ctx)
696     return make_string_error("Retrieved TypeSystem was not a TypeSystemClang");
697 
698   StreamString Stream;
699   clang_ast_ctx->DumpFromSymbolFile(Stream, Name);
700   outs() << Stream.GetData() << "\n";
701 
702   return Error::success();
703 }
704 
705 Error opts::symbols::verify(lldb_private::Module &Module) {
706   SymbolFile *symfile = Module.GetSymbolFile();
707   if (!symfile)
708     return make_string_error("Module has no symbol file.");
709 
710   uint32_t comp_units_count = symfile->GetNumCompileUnits();
711 
712   outs() << "Found " << comp_units_count << " compile units.\n";
713 
714   for (uint32_t i = 0; i < comp_units_count; i++) {
715     lldb::CompUnitSP comp_unit = symfile->GetCompileUnitAtIndex(i);
716     if (!comp_unit)
717       return make_string_error("Cannot parse compile unit {0}.", i);
718 
719     outs() << "Processing '"
720            << comp_unit->GetPrimaryFile().GetFilename().AsCString()
721            << "' compile unit.\n";
722 
723     LineTable *lt = comp_unit->GetLineTable();
724     if (!lt)
725       return make_string_error("Can't get a line table of a compile unit.");
726 
727     uint32_t count = lt->GetSize();
728 
729     outs() << "The line table contains " << count << " entries.\n";
730 
731     if (count == 0)
732       continue;
733 
734     LineEntry le;
735     if (!lt->GetLineEntryAtIndex(0, le))
736       return make_string_error("Can't get a line entry of a compile unit.");
737 
738     for (uint32_t i = 1; i < count; i++) {
739       lldb::addr_t curr_end =
740           le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
741 
742       if (!lt->GetLineEntryAtIndex(i, le))
743         return make_string_error("Can't get a line entry of a compile unit");
744 
745       if (curr_end > le.range.GetBaseAddress().GetFileAddress())
746         return make_string_error(
747             "Line table of a compile unit is inconsistent.");
748     }
749   }
750 
751   outs() << "The symbol information is verified.\n";
752 
753   return Error::success();
754 }
755 
756 Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
757   if (Verify && DumpAST)
758     return make_string_error(
759         "Cannot both verify symbol information and dump AST.");
760 
761   if (Verify) {
762     if (Find != FindType::None)
763       return make_string_error(
764           "Cannot both search and verify symbol information.");
765     if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
766         Line != 0)
767       return make_string_error(
768           "-regex, -context, -name, -file and -line options are not "
769           "applicable for symbol verification.");
770     return verify;
771   }
772 
773   if (DumpAST) {
774     if (Find != FindType::None)
775       return make_string_error("Cannot both search and dump AST.");
776     if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
777         Line != 0)
778       return make_string_error(
779           "-regex, -context, -name, -file and -line options are not "
780           "applicable for dumping AST.");
781     return dumpAST;
782   }
783 
784   if (DumpClangAST) {
785     if (Find == FindType::None) {
786       if (Regex || !Context.empty() || !File.empty() || Line != 0)
787         return make_string_error(
788             "-regex, -context, -name, -file and -line options are not "
789             "applicable for dumping the entire clang AST. Either combine with "
790             "-find, or use -dump-clang-ast as a standalone option.");
791       return dumpEntireClangAST;
792     }
793     if (Find != FindType::Type)
794       return make_string_error("This combination of -dump-clang-ast and -find "
795                                "<kind> is not yet implemented.");
796   }
797 
798   if (Regex && !Context.empty())
799     return make_string_error(
800         "Cannot search using both regular expressions and context.");
801 
802   if (Regex && !RegularExpression(Name).IsValid())
803     return make_string_error("`{0}` is not a valid regular expression.", Name);
804 
805   if (Regex + !Context.empty() + !File.empty() >= 2)
806     return make_string_error(
807         "Only one of -regex, -context and -file may be used simultaneously.");
808   if (Regex && Name.empty())
809     return make_string_error("-regex used without a -name");
810 
811   switch (Find) {
812   case FindType::None:
813     if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0)
814       return make_string_error(
815           "Specify search type (-find) to use search options.");
816     return dumpModule;
817 
818   case FindType::Function:
819     if (!File.empty() + (Line != 0) == 1)
820       return make_string_error("Both file name and line number must be "
821                                "specified when searching a function "
822                                "by file position.");
823     if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2)
824       return make_string_error("Only one of regular expression, function-flags "
825                                "and file position may be used simultaneously "
826                                "when searching a function.");
827     return findFunctions;
828 
829   case FindType::Block:
830     if (File.empty() || Line == 0)
831       return make_string_error("Both file name and line number must be "
832                                "specified when searching a block.");
833     if (Regex || getFunctionNameFlags() != 0)
834       return make_string_error("Cannot use regular expression or "
835                                "function-flags for searching a block.");
836     return findBlocks;
837 
838   case FindType::Namespace:
839     if (Regex || !File.empty() || Line != 0)
840       return make_string_error("Cannot search for namespaces using regular "
841                                "expressions, file names or line numbers.");
842     return findNamespaces;
843 
844   case FindType::Type:
845     if (Regex || !File.empty() || Line != 0)
846       return make_string_error("Cannot search for types using regular "
847                                "expressions, file names or line numbers.");
848     if (!Name.empty() && !CompilerContext.empty())
849       return make_string_error("Name is ignored if compiler context present.");
850 
851     return findTypes;
852 
853   case FindType::Variable:
854     if (Line != 0)
855       return make_string_error("Cannot search for variables "
856                                "using line numbers.");
857     return findVariables;
858   }
859 
860   llvm_unreachable("Unsupported symbol action.");
861 }
862 
863 llvm::Optional<llvm::Error> opts::symtab::validate() {
864   if (ManglingPreference != ManglingPreference::None &&
865       FindSymbolsByRegex.empty())
866     return make_string_error("Mangling preference set but no regex specified.");
867 
868   return {};
869 }
870 
871 static Mangled::NamePreference opts::symtab::getNamePreference() {
872   switch (ManglingPreference) {
873   case ManglingPreference::None:
874   case ManglingPreference::Mangled:
875     return Mangled::ePreferMangled;
876   case ManglingPreference::Demangled:
877     return Mangled::ePreferDemangled;
878   case ManglingPreference::MangledWithoutArguments:
879     return Mangled::ePreferDemangledWithoutArguments;
880   }
881 }
882 
883 int opts::symtab::handleSymtabCommand(Debugger &Dbg) {
884   if (auto error = validate()) {
885     logAllUnhandledErrors(std::move(error.getValue()), WithColor::error(), "");
886     return 1;
887   }
888 
889   if (!FindSymbolsByRegex.empty()) {
890     ModuleSpec Spec{FileSpec(InputFile)};
891 
892     auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
893     auto *Symtab = ModulePtr->GetSymtab();
894     auto NamePreference = getNamePreference();
895     std::vector<uint32_t> Indexes;
896 
897     Symtab->FindAllSymbolsMatchingRexExAndType(
898         RegularExpression(FindSymbolsByRegex), lldb::eSymbolTypeAny,
899         Symtab::eDebugAny, Symtab::eVisibilityAny, Indexes, NamePreference);
900     for (auto i : Indexes) {
901       auto *symbol = Symtab->SymbolAtIndex(i);
902       if (symbol) {
903         StreamString stream;
904         symbol->Dump(&stream, nullptr, i, NamePreference);
905         outs() << stream.GetString();
906       }
907     }
908   }
909 
910   return 0;
911 }
912 
913 int opts::symbols::dumpSymbols(Debugger &Dbg) {
914   auto ActionOr = getAction();
915   if (!ActionOr) {
916     logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), "");
917     return 1;
918   }
919   auto Action = *ActionOr;
920 
921   outs() << "Module: " << InputFile << "\n";
922   ModuleSpec Spec{FileSpec(InputFile)};
923   StringRef Symbols = SymbolPath.empty() ? InputFile : SymbolPath;
924   Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native);
925 
926   auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
927   SymbolFile *Symfile = ModulePtr->GetSymbolFile();
928   if (!Symfile) {
929     WithColor::error() << "Module has no symbol vendor.\n";
930     return 1;
931   }
932 
933   if (Error E = Action(*ModulePtr)) {
934     WithColor::error() << toString(std::move(E)) << "\n";
935     return 1;
936   }
937 
938   return 0;
939 }
940 
941 static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) {
942   size_t Count = List.GetNumSections(0);
943   if (Count == 0) {
944     Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : "");
945     return;
946   }
947   Printer.formatLine("Showing {0} {1}sections", Count,
948                      is_subsection ? "sub" : "");
949   for (size_t I = 0; I < Count; ++I) {
950     auto S = List.GetSectionAtIndex(I);
951     assert(S);
952     AutoIndent Indent(Printer, 2);
953     Printer.formatLine("Index: {0}", I);
954     Printer.formatLine("ID: {0:x}", S->GetID());
955     Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
956     Printer.formatLine("Type: {0}", S->GetTypeAsCString());
957     Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions()));
958     Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific());
959     Printer.formatLine("VM address: {0:x}", S->GetFileAddress());
960     Printer.formatLine("VM size: {0}", S->GetByteSize());
961     Printer.formatLine("File size: {0}", S->GetFileSize());
962 
963     if (opts::object::SectionContents) {
964       lldb_private::DataExtractor Data;
965       S->GetSectionData(Data);
966       ArrayRef<uint8_t> Bytes(Data.GetDataStart(), Data.GetDataEnd());
967       Printer.formatBinary("Data: ", Bytes, 0);
968     }
969 
970     if (S->GetType() == eSectionTypeContainer)
971       dumpSectionList(Printer, S->GetChildren(), true);
972     Printer.NewLine();
973   }
974 }
975 
976 static int dumpObjectFiles(Debugger &Dbg) {
977   LinePrinter Printer(4, llvm::outs());
978 
979   int HadErrors = 0;
980   for (const auto &File : opts::object::InputFilenames) {
981     ModuleSpec Spec{FileSpec(File)};
982 
983     auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
984 
985     ObjectFile *ObjectPtr = ModulePtr->GetObjectFile();
986     if (!ObjectPtr) {
987       WithColor::error() << File << " not recognised as an object file\n";
988       HadErrors = 1;
989       continue;
990     }
991 
992     // Fetch symbol vendor before we get the section list to give the symbol
993     // vendor a chance to populate it.
994     ModulePtr->GetSymbolFile();
995     SectionList *Sections = ModulePtr->GetSectionList();
996     if (!Sections) {
997       llvm::errs() << "Could not load sections for module " << File << "\n";
998       HadErrors = 1;
999       continue;
1000     }
1001 
1002     Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName());
1003     Printer.formatLine("Architecture: {0}",
1004                        ModulePtr->GetArchitecture().GetTriple().getTriple());
1005     Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
1006     Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable());
1007     Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped());
1008     Printer.formatLine("Type: {0}", ObjectPtr->GetType());
1009     Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata());
1010     Printer.formatLine("Base VM address: {0:x}",
1011                        ObjectPtr->GetBaseAddress().GetFileAddress());
1012 
1013     dumpSectionList(Printer, *Sections, /*is_subsection*/ false);
1014 
1015     if (opts::object::SectionDependentModules) {
1016       // A non-empty section list ensures a valid object file.
1017       auto Obj = ModulePtr->GetObjectFile();
1018       FileSpecList Files;
1019       auto Count = Obj->GetDependentModules(Files);
1020       Printer.formatLine("Showing {0} dependent module(s)", Count);
1021       for (size_t I = 0; I < Files.GetSize(); ++I) {
1022         AutoIndent Indent(Printer, 2);
1023         Printer.formatLine("Name: {0}",
1024                            Files.GetFileSpecAtIndex(I).GetPath());
1025       }
1026       Printer.NewLine();
1027     }
1028   }
1029   return HadErrors;
1030 }
1031 
1032 bool opts::irmemorymap::evalMalloc(StringRef Line,
1033                                    IRMemoryMapTestState &State) {
1034   // ::= <label> = malloc <size> <alignment>
1035   StringRef Label;
1036   std::tie(Label, Line) = Line.split('=');
1037   if (Line.empty())
1038     return false;
1039   Label = Label.trim();
1040   Line = Line.trim();
1041   size_t Size;
1042   uint8_t Alignment;
1043   int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment);
1044   if (Matches != 2)
1045     return false;
1046 
1047   outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label,
1048                     Size, Alignment);
1049   if (!isPowerOf2_32(Alignment)) {
1050     outs() << "Malloc error: alignment is not a power of 2\n";
1051     exit(1);
1052   }
1053 
1054   IRMemoryMap::AllocationPolicy AP =
1055       UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly
1056                                   : IRMemoryMap::eAllocationPolicyProcessOnly;
1057 
1058   // Issue the malloc in the target process with "-rw" permissions.
1059   const uint32_t Permissions = 0x3;
1060   const bool ZeroMemory = false;
1061   Status ST;
1062   addr_t Addr =
1063       State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST);
1064   if (ST.Fail()) {
1065     outs() << formatv("Malloc error: {0}\n", ST);
1066     return true;
1067   }
1068 
1069   // Print the result of the allocation before checking its validity.
1070   outs() << formatv("Malloc: address = {0:x}\n", Addr);
1071 
1072   // Check that the allocation is aligned.
1073   if (!Addr || Addr % Alignment != 0) {
1074     outs() << "Malloc error: zero or unaligned allocation detected\n";
1075     exit(1);
1076   }
1077 
1078   // In case of Size == 0, we still expect the returned address to be unique and
1079   // non-overlapping.
1080   addr_t EndOfRegion = Addr + std::max<size_t>(Size, 1);
1081   if (State.Allocations.overlaps(Addr, EndOfRegion)) {
1082     auto I = State.Allocations.find(Addr);
1083     outs() << "Malloc error: overlapping allocation detected"
1084            << formatv(", previous allocation at [{0:x}, {1:x})\n", I.start(),
1085                       I.stop());
1086     exit(1);
1087   }
1088 
1089   // Insert the new allocation into the interval map. Use unique allocation
1090   // IDs to inhibit interval coalescing.
1091   static unsigned AllocationID = 0;
1092   State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
1093 
1094   // Store the label -> address mapping.
1095   State.Label2AddrMap[Label] = Addr;
1096 
1097   return true;
1098 }
1099 
1100 bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) {
1101   // ::= free <label>
1102   if (!Line.consume_front("free"))
1103     return false;
1104   StringRef Label = Line.trim();
1105 
1106   outs() << formatv("Command: free({0})\n", Label);
1107   auto LabelIt = State.Label2AddrMap.find(Label);
1108   if (LabelIt == State.Label2AddrMap.end()) {
1109     outs() << "Free error: Invalid allocation label\n";
1110     exit(1);
1111   }
1112 
1113   Status ST;
1114   addr_t Addr = LabelIt->getValue();
1115   State.Map.Free(Addr, ST);
1116   if (ST.Fail()) {
1117     outs() << formatv("Free error: {0}\n", ST);
1118     exit(1);
1119   }
1120 
1121   // Erase the allocation from the live interval map.
1122   auto Interval = State.Allocations.find(Addr);
1123   if (Interval != State.Allocations.end()) {
1124     outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(),
1125                       Interval.stop());
1126     Interval.erase();
1127   }
1128 
1129   return true;
1130 }
1131 
1132 int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
1133   // Set up a Target.
1134   TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target);
1135 
1136   // Set up a Process. In order to allocate memory within a target, this
1137   // process must be alive and must support JIT'ing.
1138   CommandReturnObject Result(/*colors*/ false);
1139   Dbg.SetAsyncExecution(false);
1140   CommandInterpreter &CI = Dbg.GetCommandInterpreter();
1141   auto IssueCmd = [&](const char *Cmd) -> bool {
1142     return CI.HandleCommand(Cmd, eLazyBoolNo, Result);
1143   };
1144   if (!IssueCmd("b main") || !IssueCmd("run")) {
1145     outs() << formatv("Failed: {0}\n", Result.GetErrorData());
1146     exit(1);
1147   }
1148 
1149   ProcessSP Process = Target->GetProcessSP();
1150   if (!Process || !Process->IsAlive() || !Process->CanJIT()) {
1151     outs() << "Cannot use process to test IRMemoryMap\n";
1152     exit(1);
1153   }
1154 
1155   // Set up an IRMemoryMap and associated testing state.
1156   IRMemoryMapTestState State(Target);
1157 
1158   // Parse and apply commands from the command file.
1159   std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile);
1160   StringRef Rest = MB->getBuffer();
1161   while (!Rest.empty()) {
1162     StringRef Line;
1163     std::tie(Line, Rest) = Rest.split('\n');
1164     Line = Line.ltrim().rtrim();
1165 
1166     if (Line.empty() || Line[0] == '#')
1167       continue;
1168 
1169     if (evalMalloc(Line, State))
1170       continue;
1171 
1172     if (evalFree(Line, State))
1173       continue;
1174 
1175     errs() << "Could not parse line: " << Line << "\n";
1176     exit(1);
1177   }
1178   return 0;
1179 }
1180 
1181 int opts::assert::lldb_assert(Debugger &Dbg) {
1182   lldbassert(false && "lldb-test assert");
1183   return 1;
1184 }
1185 
1186 int main(int argc, const char *argv[]) {
1187   StringRef ToolName = argv[0];
1188   sys::PrintStackTraceOnErrorSignal(ToolName);
1189   PrettyStackTraceProgram X(argc, argv);
1190   llvm_shutdown_obj Y;
1191 
1192   cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
1193 
1194   SystemLifetimeManager DebuggerLifetime;
1195   if (auto e = DebuggerLifetime.Initialize(
1196           std::make_unique<SystemInitializerTest>(), nullptr)) {
1197     WithColor::error() << "initialization failed: " << toString(std::move(e))
1198                        << '\n';
1199     return 1;
1200   }
1201 
1202   auto TerminateDebugger =
1203       llvm::make_scope_exit([&] { DebuggerLifetime.Terminate(); });
1204 
1205   auto Dbg = lldb_private::Debugger::CreateInstance();
1206   ModuleList::GetGlobalModuleListProperties().SetEnableExternalLookup(false);
1207   CommandReturnObject Result(/*colors*/ false);
1208   Dbg->GetCommandInterpreter().HandleCommand(
1209       "settings set plugin.process.gdb-remote.packet-timeout 60",
1210       /*add_to_history*/ eLazyBoolNo, Result);
1211   Dbg->GetCommandInterpreter().HandleCommand(
1212       "settings set target.inherit-tcc true",
1213       /*add_to_history*/ eLazyBoolNo, Result);
1214   Dbg->GetCommandInterpreter().HandleCommand(
1215       "settings set target.detach-on-error false",
1216       /*add_to_history*/ eLazyBoolNo, Result);
1217 
1218   if (!opts::Log.empty())
1219     Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, 0, eLogHandlerStream, errs());
1220 
1221   if (opts::BreakpointSubcommand)
1222     return opts::breakpoint::evaluateBreakpoints(*Dbg);
1223   if (opts::ObjectFileSubcommand)
1224     return dumpObjectFiles(*Dbg);
1225   if (opts::SymbolsSubcommand)
1226     return opts::symbols::dumpSymbols(*Dbg);
1227   if (opts::SymTabSubcommand)
1228     return opts::symtab::handleSymtabCommand(*Dbg);
1229   if (opts::IRMemoryMapSubcommand)
1230     return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
1231   if (opts::AssertSubcommand)
1232     return opts::assert::lldb_assert(*Dbg);
1233 
1234   WithColor::error() << "No command specified.\n";
1235   return 1;
1236 }
1237