xref: /llvm-project/lldb/tools/lldb-test/lldb-test.cpp (revision c38bc421b1268ca371cdbb54e470d758968ce67a)
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       [[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     Module::LookupInfo lookup_info(ConstString(Name), getFunctionNameFlags(),
509                                    eLanguageTypeUnknown);
510     Symfile.FindFunctions(lookup_info, ContextPtr, true, List);
511   }
512   outs() << formatv("Found {0} functions:\n", List.GetSize());
513   StreamString Stream;
514   List.Dump(&Stream, nullptr);
515   outs() << Stream.GetData() << "\n";
516   return Error::success();
517 }
518 
519 Error opts::symbols::findBlocks(lldb_private::Module &Module) {
520   assert(!Regex);
521   assert(!File.empty());
522   assert(Line != 0);
523 
524   SymbolContextList List;
525 
526   FileSpec src_file(File);
527   size_t cu_count = Module.GetNumCompileUnits();
528   for (size_t i = 0; i < cu_count; i++) {
529     lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
530     if (!cu_sp)
531       continue;
532 
533     LineEntry le;
534     cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
535     if (!le.IsValid())
536       continue;
537     const bool include_inlined_functions = false;
538     auto addr = le.GetSameLineContiguousAddressRange(include_inlined_functions)
539                     .GetBaseAddress();
540     if (!addr.IsValid())
541       continue;
542 
543     SymbolContext sc;
544     uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock);
545     if (resolved & eSymbolContextBlock)
546       List.Append(sc);
547   }
548 
549   outs() << formatv("Found {0} blocks:\n", List.GetSize());
550   StreamString Stream;
551   List.Dump(&Stream, nullptr);
552   outs() << Stream.GetData() << "\n";
553   return Error::success();
554 }
555 
556 Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
557   SymbolFile &Symfile = *Module.GetSymbolFile();
558   Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
559   if (!ContextOr)
560     return ContextOr.takeError();
561   const CompilerDeclContext &ContextPtr =
562       ContextOr->IsValid() ? *ContextOr : CompilerDeclContext();
563 
564   CompilerDeclContext Result =
565       Symfile.FindNamespace(ConstString(Name), ContextPtr);
566   if (Result)
567     outs() << "Found namespace: "
568            << Result.GetScopeQualifiedName().GetStringRef() << "\n";
569   else
570     outs() << "Namespace not found.\n";
571   return Error::success();
572 }
573 
574 Error opts::symbols::findTypes(lldb_private::Module &Module) {
575   SymbolFile &Symfile = *Module.GetSymbolFile();
576   Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
577   if (!ContextOr)
578     return ContextOr.takeError();
579   const CompilerDeclContext &ContextPtr =
580       ContextOr->IsValid() ? *ContextOr : CompilerDeclContext();
581 
582   LanguageSet languages;
583   if (!Language.empty())
584     languages.Insert(Language::GetLanguageTypeFromString(Language));
585 
586   DenseSet<SymbolFile *> SearchedFiles;
587   TypeMap Map;
588   if (!Name.empty())
589     Symfile.FindTypes(ConstString(Name), ContextPtr, UINT32_MAX, SearchedFiles,
590                       Map);
591   else
592     Module.FindTypes(parseCompilerContext(), languages, SearchedFiles, Map);
593 
594   outs() << formatv("Found {0} types:\n", Map.GetSize());
595   StreamString Stream;
596   // Resolve types to force-materialize typedef types.
597   Map.ForEach([&](TypeSP &type) {
598     type->GetFullCompilerType();
599     return false;
600   });
601   Map.Dump(&Stream, false, GetDescriptionLevel());
602   outs() << Stream.GetData() << "\n";
603   return Error::success();
604 }
605 
606 Error opts::symbols::findVariables(lldb_private::Module &Module) {
607   SymbolFile &Symfile = *Module.GetSymbolFile();
608   VariableList List;
609   if (Regex) {
610     RegularExpression RE(Name);
611     assert(RE.IsValid());
612     Symfile.FindGlobalVariables(RE, UINT32_MAX, List);
613   } else if (!File.empty()) {
614     CompUnitSP CU;
615     for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) {
616       CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind);
617       if (!Candidate ||
618           Candidate->GetPrimaryFile().GetFilename().GetStringRef() != File)
619         continue;
620       if (CU)
621         return make_string_error("Multiple compile units for file `{0}` found.",
622                                  File);
623       CU = std::move(Candidate);
624     }
625 
626     if (!CU)
627       return make_string_error("Compile unit `{0}` not found.", File);
628 
629     List.AddVariables(CU->GetVariableList(true).get());
630   } else {
631     Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
632     if (!ContextOr)
633       return ContextOr.takeError();
634     const CompilerDeclContext &ContextPtr =
635         ContextOr->IsValid() ? *ContextOr : CompilerDeclContext();
636 
637     Symfile.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List);
638   }
639   outs() << formatv("Found {0} variables:\n", List.GetSize());
640   StreamString Stream;
641   List.Dump(&Stream, false);
642   outs() << Stream.GetData() << "\n";
643   return Error::success();
644 }
645 
646 Error opts::symbols::dumpModule(lldb_private::Module &Module) {
647   StreamString Stream;
648   Module.ParseAllDebugSymbols();
649   Module.Dump(&Stream);
650   outs() << Stream.GetData() << "\n";
651   return Error::success();
652 }
653 
654 Error opts::symbols::dumpAST(lldb_private::Module &Module) {
655   Module.ParseAllDebugSymbols();
656 
657   SymbolFile *symfile = Module.GetSymbolFile();
658   if (!symfile)
659     return make_string_error("Module has no symbol file.");
660 
661   llvm::Expected<TypeSystem &> type_system_or_err =
662       symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
663   if (!type_system_or_err)
664     return make_string_error("Can't retrieve TypeSystemClang");
665 
666   auto *clang_ast_ctx =
667       llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get());
668   if (!clang_ast_ctx)
669     return make_string_error("Retrieved TypeSystem was not a TypeSystemClang");
670 
671   clang::ASTContext &ast_ctx = clang_ast_ctx->getASTContext();
672 
673   clang::TranslationUnitDecl *tu = ast_ctx.getTranslationUnitDecl();
674   if (!tu)
675     return make_string_error("Can't retrieve translation unit declaration.");
676 
677   tu->print(outs());
678 
679   return Error::success();
680 }
681 
682 Error opts::symbols::dumpEntireClangAST(lldb_private::Module &Module) {
683   Module.ParseAllDebugSymbols();
684 
685   SymbolFile *symfile = Module.GetSymbolFile();
686   if (!symfile)
687     return make_string_error("Module has no symbol file.");
688 
689   llvm::Expected<TypeSystem &> type_system_or_err =
690       symfile->GetTypeSystemForLanguage(eLanguageTypeObjC_plus_plus);
691   if (!type_system_or_err)
692     return make_string_error("Can't retrieve TypeSystemClang");
693 
694   auto *clang_ast_ctx =
695       llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get());
696   if (!clang_ast_ctx)
697     return make_string_error("Retrieved TypeSystem was not a TypeSystemClang");
698 
699   StreamString Stream;
700   clang_ast_ctx->DumpFromSymbolFile(Stream, Name);
701   outs() << Stream.GetData() << "\n";
702 
703   return Error::success();
704 }
705 
706 Error opts::symbols::verify(lldb_private::Module &Module) {
707   SymbolFile *symfile = Module.GetSymbolFile();
708   if (!symfile)
709     return make_string_error("Module has no symbol file.");
710 
711   uint32_t comp_units_count = symfile->GetNumCompileUnits();
712 
713   outs() << "Found " << comp_units_count << " compile units.\n";
714 
715   for (uint32_t i = 0; i < comp_units_count; i++) {
716     lldb::CompUnitSP comp_unit = symfile->GetCompileUnitAtIndex(i);
717     if (!comp_unit)
718       return make_string_error("Cannot parse compile unit {0}.", i);
719 
720     outs() << "Processing '"
721            << comp_unit->GetPrimaryFile().GetFilename().AsCString()
722            << "' compile unit.\n";
723 
724     LineTable *lt = comp_unit->GetLineTable();
725     if (!lt)
726       return make_string_error("Can't get a line table of a compile unit.");
727 
728     uint32_t count = lt->GetSize();
729 
730     outs() << "The line table contains " << count << " entries.\n";
731 
732     if (count == 0)
733       continue;
734 
735     LineEntry le;
736     if (!lt->GetLineEntryAtIndex(0, le))
737       return make_string_error("Can't get a line entry of a compile unit.");
738 
739     for (uint32_t i = 1; i < count; i++) {
740       lldb::addr_t curr_end =
741           le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
742 
743       if (!lt->GetLineEntryAtIndex(i, le))
744         return make_string_error("Can't get a line entry of a compile unit");
745 
746       if (curr_end > le.range.GetBaseAddress().GetFileAddress())
747         return make_string_error(
748             "Line table of a compile unit is inconsistent.");
749     }
750   }
751 
752   outs() << "The symbol information is verified.\n";
753 
754   return Error::success();
755 }
756 
757 Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
758   if (Verify && DumpAST)
759     return make_string_error(
760         "Cannot both verify symbol information and dump AST.");
761 
762   if (Verify) {
763     if (Find != FindType::None)
764       return make_string_error(
765           "Cannot both search and verify symbol information.");
766     if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
767         Line != 0)
768       return make_string_error(
769           "-regex, -context, -name, -file and -line options are not "
770           "applicable for symbol verification.");
771     return verify;
772   }
773 
774   if (DumpAST) {
775     if (Find != FindType::None)
776       return make_string_error("Cannot both search and dump AST.");
777     if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
778         Line != 0)
779       return make_string_error(
780           "-regex, -context, -name, -file and -line options are not "
781           "applicable for dumping AST.");
782     return dumpAST;
783   }
784 
785   if (DumpClangAST) {
786     if (Find == FindType::None) {
787       if (Regex || !Context.empty() || !File.empty() || Line != 0)
788         return make_string_error(
789             "-regex, -context, -name, -file and -line options are not "
790             "applicable for dumping the entire clang AST. Either combine with "
791             "-find, or use -dump-clang-ast as a standalone option.");
792       return dumpEntireClangAST;
793     }
794     if (Find != FindType::Type)
795       return make_string_error("This combination of -dump-clang-ast and -find "
796                                "<kind> is not yet implemented.");
797   }
798 
799   if (Regex && !Context.empty())
800     return make_string_error(
801         "Cannot search using both regular expressions and context.");
802 
803   if (Regex && !RegularExpression(Name).IsValid())
804     return make_string_error("`{0}` is not a valid regular expression.", Name);
805 
806   if (Regex + !Context.empty() + !File.empty() >= 2)
807     return make_string_error(
808         "Only one of -regex, -context and -file may be used simultaneously.");
809   if (Regex && Name.empty())
810     return make_string_error("-regex used without a -name");
811 
812   switch (Find) {
813   case FindType::None:
814     if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0)
815       return make_string_error(
816           "Specify search type (-find) to use search options.");
817     return dumpModule;
818 
819   case FindType::Function:
820     if (!File.empty() + (Line != 0) == 1)
821       return make_string_error("Both file name and line number must be "
822                                "specified when searching a function "
823                                "by file position.");
824     if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2)
825       return make_string_error("Only one of regular expression, function-flags "
826                                "and file position may be used simultaneously "
827                                "when searching a function.");
828     return findFunctions;
829 
830   case FindType::Block:
831     if (File.empty() || Line == 0)
832       return make_string_error("Both file name and line number must be "
833                                "specified when searching a block.");
834     if (Regex || getFunctionNameFlags() != 0)
835       return make_string_error("Cannot use regular expression or "
836                                "function-flags for searching a block.");
837     return findBlocks;
838 
839   case FindType::Namespace:
840     if (Regex || !File.empty() || Line != 0)
841       return make_string_error("Cannot search for namespaces using regular "
842                                "expressions, file names or line numbers.");
843     return findNamespaces;
844 
845   case FindType::Type:
846     if (Regex || !File.empty() || Line != 0)
847       return make_string_error("Cannot search for types using regular "
848                                "expressions, file names or line numbers.");
849     if (!Name.empty() && !CompilerContext.empty())
850       return make_string_error("Name is ignored if compiler context present.");
851 
852     return findTypes;
853 
854   case FindType::Variable:
855     if (Line != 0)
856       return make_string_error("Cannot search for variables "
857                                "using line numbers.");
858     return findVariables;
859   }
860 
861   llvm_unreachable("Unsupported symbol action.");
862 }
863 
864 llvm::Optional<llvm::Error> opts::symtab::validate() {
865   if (ManglingPreference != ManglingPreference::None &&
866       FindSymbolsByRegex.empty())
867     return make_string_error("Mangling preference set but no regex specified.");
868 
869   return {};
870 }
871 
872 static Mangled::NamePreference opts::symtab::getNamePreference() {
873   switch (ManglingPreference) {
874   case ManglingPreference::None:
875   case ManglingPreference::Mangled:
876     return Mangled::ePreferMangled;
877   case ManglingPreference::Demangled:
878     return Mangled::ePreferDemangled;
879   case ManglingPreference::MangledWithoutArguments:
880     return Mangled::ePreferDemangledWithoutArguments;
881   }
882   llvm_unreachable("Fully covered switch above!");
883 }
884 
885 int opts::symtab::handleSymtabCommand(Debugger &Dbg) {
886   if (auto error = validate()) {
887     logAllUnhandledErrors(std::move(error.value()), WithColor::error(), "");
888     return 1;
889   }
890 
891   if (!FindSymbolsByRegex.empty()) {
892     ModuleSpec Spec{FileSpec(InputFile)};
893 
894     auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
895     auto *Symtab = ModulePtr->GetSymtab();
896     auto NamePreference = getNamePreference();
897     std::vector<uint32_t> Indexes;
898 
899     Symtab->FindAllSymbolsMatchingRexExAndType(
900         RegularExpression(FindSymbolsByRegex), lldb::eSymbolTypeAny,
901         Symtab::eDebugAny, Symtab::eVisibilityAny, Indexes, NamePreference);
902     for (auto i : Indexes) {
903       auto *symbol = Symtab->SymbolAtIndex(i);
904       if (symbol) {
905         StreamString stream;
906         symbol->Dump(&stream, nullptr, i, NamePreference);
907         outs() << stream.GetString();
908       }
909     }
910   }
911 
912   return 0;
913 }
914 
915 int opts::symbols::dumpSymbols(Debugger &Dbg) {
916   auto ActionOr = getAction();
917   if (!ActionOr) {
918     logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), "");
919     return 1;
920   }
921   auto Action = *ActionOr;
922 
923   outs() << "Module: " << InputFile << "\n";
924   ModuleSpec Spec{FileSpec(InputFile)};
925   StringRef Symbols = SymbolPath.empty() ? InputFile : SymbolPath;
926   Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native);
927 
928   auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
929   SymbolFile *Symfile = ModulePtr->GetSymbolFile();
930   if (!Symfile) {
931     WithColor::error() << "Module has no symbol vendor.\n";
932     return 1;
933   }
934 
935   if (Error E = Action(*ModulePtr)) {
936     WithColor::error() << toString(std::move(E)) << "\n";
937     return 1;
938   }
939 
940   return 0;
941 }
942 
943 static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) {
944   size_t Count = List.GetNumSections(0);
945   if (Count == 0) {
946     Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : "");
947     return;
948   }
949   Printer.formatLine("Showing {0} {1}sections", Count,
950                      is_subsection ? "sub" : "");
951   for (size_t I = 0; I < Count; ++I) {
952     auto S = List.GetSectionAtIndex(I);
953     assert(S);
954     AutoIndent Indent(Printer, 2);
955     Printer.formatLine("Index: {0}", I);
956     Printer.formatLine("ID: {0:x}", S->GetID());
957     Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
958     Printer.formatLine("Type: {0}", S->GetTypeAsCString());
959     Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions()));
960     Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific());
961     Printer.formatLine("VM address: {0:x}", S->GetFileAddress());
962     Printer.formatLine("VM size: {0}", S->GetByteSize());
963     Printer.formatLine("File size: {0}", S->GetFileSize());
964 
965     if (opts::object::SectionContents) {
966       lldb_private::DataExtractor Data;
967       S->GetSectionData(Data);
968       ArrayRef<uint8_t> Bytes(Data.GetDataStart(), Data.GetDataEnd());
969       Printer.formatBinary("Data: ", Bytes, 0);
970     }
971 
972     if (S->GetType() == eSectionTypeContainer)
973       dumpSectionList(Printer, S->GetChildren(), true);
974     Printer.NewLine();
975   }
976 }
977 
978 static int dumpObjectFiles(Debugger &Dbg) {
979   LinePrinter Printer(4, llvm::outs());
980 
981   int HadErrors = 0;
982   for (const auto &File : opts::object::InputFilenames) {
983     ModuleSpec Spec{FileSpec(File)};
984 
985     auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
986 
987     ObjectFile *ObjectPtr = ModulePtr->GetObjectFile();
988     if (!ObjectPtr) {
989       WithColor::error() << File << " not recognised as an object file\n";
990       HadErrors = 1;
991       continue;
992     }
993 
994     // Fetch symbol vendor before we get the section list to give the symbol
995     // vendor a chance to populate it.
996     ModulePtr->GetSymbolFile();
997     SectionList *Sections = ModulePtr->GetSectionList();
998     if (!Sections) {
999       llvm::errs() << "Could not load sections for module " << File << "\n";
1000       HadErrors = 1;
1001       continue;
1002     }
1003 
1004     Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName());
1005     Printer.formatLine("Architecture: {0}",
1006                        ModulePtr->GetArchitecture().GetTriple().getTriple());
1007     Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
1008     Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable());
1009     Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped());
1010     Printer.formatLine("Type: {0}", ObjectPtr->GetType());
1011     Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata());
1012     Printer.formatLine("Base VM address: {0:x}",
1013                        ObjectPtr->GetBaseAddress().GetFileAddress());
1014 
1015     dumpSectionList(Printer, *Sections, /*is_subsection*/ false);
1016 
1017     if (opts::object::SectionDependentModules) {
1018       // A non-empty section list ensures a valid object file.
1019       auto Obj = ModulePtr->GetObjectFile();
1020       FileSpecList Files;
1021       auto Count = Obj->GetDependentModules(Files);
1022       Printer.formatLine("Showing {0} dependent module(s)", Count);
1023       for (size_t I = 0; I < Files.GetSize(); ++I) {
1024         AutoIndent Indent(Printer, 2);
1025         Printer.formatLine("Name: {0}",
1026                            Files.GetFileSpecAtIndex(I).GetPath());
1027       }
1028       Printer.NewLine();
1029     }
1030   }
1031   return HadErrors;
1032 }
1033 
1034 bool opts::irmemorymap::evalMalloc(StringRef Line,
1035                                    IRMemoryMapTestState &State) {
1036   // ::= <label> = malloc <size> <alignment>
1037   StringRef Label;
1038   std::tie(Label, Line) = Line.split('=');
1039   if (Line.empty())
1040     return false;
1041   Label = Label.trim();
1042   Line = Line.trim();
1043   size_t Size;
1044   uint8_t Alignment;
1045   int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment);
1046   if (Matches != 2)
1047     return false;
1048 
1049   outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label,
1050                     Size, Alignment);
1051   if (!isPowerOf2_32(Alignment)) {
1052     outs() << "Malloc error: alignment is not a power of 2\n";
1053     exit(1);
1054   }
1055 
1056   IRMemoryMap::AllocationPolicy AP =
1057       UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly
1058                                   : IRMemoryMap::eAllocationPolicyProcessOnly;
1059 
1060   // Issue the malloc in the target process with "-rw" permissions.
1061   const uint32_t Permissions = 0x3;
1062   const bool ZeroMemory = false;
1063   Status ST;
1064   addr_t Addr =
1065       State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST);
1066   if (ST.Fail()) {
1067     outs() << formatv("Malloc error: {0}\n", ST);
1068     return true;
1069   }
1070 
1071   // Print the result of the allocation before checking its validity.
1072   outs() << formatv("Malloc: address = {0:x}\n", Addr);
1073 
1074   // Check that the allocation is aligned.
1075   if (!Addr || Addr % Alignment != 0) {
1076     outs() << "Malloc error: zero or unaligned allocation detected\n";
1077     exit(1);
1078   }
1079 
1080   // In case of Size == 0, we still expect the returned address to be unique and
1081   // non-overlapping.
1082   addr_t EndOfRegion = Addr + std::max<size_t>(Size, 1);
1083   if (State.Allocations.overlaps(Addr, EndOfRegion)) {
1084     auto I = State.Allocations.find(Addr);
1085     outs() << "Malloc error: overlapping allocation detected"
1086            << formatv(", previous allocation at [{0:x}, {1:x})\n", I.start(),
1087                       I.stop());
1088     exit(1);
1089   }
1090 
1091   // Insert the new allocation into the interval map. Use unique allocation
1092   // IDs to inhibit interval coalescing.
1093   static unsigned AllocationID = 0;
1094   State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
1095 
1096   // Store the label -> address mapping.
1097   State.Label2AddrMap[Label] = Addr;
1098 
1099   return true;
1100 }
1101 
1102 bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) {
1103   // ::= free <label>
1104   if (!Line.consume_front("free"))
1105     return false;
1106   StringRef Label = Line.trim();
1107 
1108   outs() << formatv("Command: free({0})\n", Label);
1109   auto LabelIt = State.Label2AddrMap.find(Label);
1110   if (LabelIt == State.Label2AddrMap.end()) {
1111     outs() << "Free error: Invalid allocation label\n";
1112     exit(1);
1113   }
1114 
1115   Status ST;
1116   addr_t Addr = LabelIt->getValue();
1117   State.Map.Free(Addr, ST);
1118   if (ST.Fail()) {
1119     outs() << formatv("Free error: {0}\n", ST);
1120     exit(1);
1121   }
1122 
1123   // Erase the allocation from the live interval map.
1124   auto Interval = State.Allocations.find(Addr);
1125   if (Interval != State.Allocations.end()) {
1126     outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(),
1127                       Interval.stop());
1128     Interval.erase();
1129   }
1130 
1131   return true;
1132 }
1133 
1134 int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
1135   // Set up a Target.
1136   TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target);
1137 
1138   // Set up a Process. In order to allocate memory within a target, this
1139   // process must be alive and must support JIT'ing.
1140   CommandReturnObject Result(/*colors*/ false);
1141   Dbg.SetAsyncExecution(false);
1142   CommandInterpreter &CI = Dbg.GetCommandInterpreter();
1143   auto IssueCmd = [&](const char *Cmd) -> bool {
1144     return CI.HandleCommand(Cmd, eLazyBoolNo, Result);
1145   };
1146   if (!IssueCmd("b main") || !IssueCmd("run")) {
1147     outs() << formatv("Failed: {0}\n", Result.GetErrorData());
1148     exit(1);
1149   }
1150 
1151   ProcessSP Process = Target->GetProcessSP();
1152   if (!Process || !Process->IsAlive() || !Process->CanJIT()) {
1153     outs() << "Cannot use process to test IRMemoryMap\n";
1154     exit(1);
1155   }
1156 
1157   // Set up an IRMemoryMap and associated testing state.
1158   IRMemoryMapTestState State(Target);
1159 
1160   // Parse and apply commands from the command file.
1161   std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile);
1162   StringRef Rest = MB->getBuffer();
1163   while (!Rest.empty()) {
1164     StringRef Line;
1165     std::tie(Line, Rest) = Rest.split('\n');
1166     Line = Line.ltrim().rtrim();
1167 
1168     if (Line.empty() || Line[0] == '#')
1169       continue;
1170 
1171     if (evalMalloc(Line, State))
1172       continue;
1173 
1174     if (evalFree(Line, State))
1175       continue;
1176 
1177     errs() << "Could not parse line: " << Line << "\n";
1178     exit(1);
1179   }
1180   return 0;
1181 }
1182 
1183 int opts::assert::lldb_assert(Debugger &Dbg) {
1184   lldbassert(false && "lldb-test assert");
1185   return 1;
1186 }
1187 
1188 int main(int argc, const char *argv[]) {
1189   StringRef ToolName = argv[0];
1190   sys::PrintStackTraceOnErrorSignal(ToolName);
1191   PrettyStackTraceProgram X(argc, argv);
1192   llvm_shutdown_obj Y;
1193 
1194   cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
1195 
1196   SystemLifetimeManager DebuggerLifetime;
1197   if (auto e = DebuggerLifetime.Initialize(
1198           std::make_unique<SystemInitializerTest>(), nullptr)) {
1199     WithColor::error() << "initialization failed: " << toString(std::move(e))
1200                        << '\n';
1201     return 1;
1202   }
1203 
1204   auto TerminateDebugger =
1205       llvm::make_scope_exit([&] { DebuggerLifetime.Terminate(); });
1206 
1207   auto Dbg = lldb_private::Debugger::CreateInstance();
1208   ModuleList::GetGlobalModuleListProperties().SetEnableExternalLookup(false);
1209   CommandReturnObject Result(/*colors*/ false);
1210   Dbg->GetCommandInterpreter().HandleCommand(
1211       "settings set plugin.process.gdb-remote.packet-timeout 60",
1212       /*add_to_history*/ eLazyBoolNo, Result);
1213   Dbg->GetCommandInterpreter().HandleCommand(
1214       "settings set target.inherit-tcc true",
1215       /*add_to_history*/ eLazyBoolNo, Result);
1216   Dbg->GetCommandInterpreter().HandleCommand(
1217       "settings set target.detach-on-error false",
1218       /*add_to_history*/ eLazyBoolNo, Result);
1219 
1220   if (!opts::Log.empty())
1221     Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, 0, eLogHandlerStream, errs());
1222 
1223   if (opts::BreakpointSubcommand)
1224     return opts::breakpoint::evaluateBreakpoints(*Dbg);
1225   if (opts::ObjectFileSubcommand)
1226     return dumpObjectFiles(*Dbg);
1227   if (opts::SymbolsSubcommand)
1228     return opts::symbols::dumpSymbols(*Dbg);
1229   if (opts::SymTabSubcommand)
1230     return opts::symtab::handleSymtabCommand(*Dbg);
1231   if (opts::IRMemoryMapSubcommand)
1232     return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
1233   if (opts::AssertSubcommand)
1234     return opts::assert::lldb_assert(*Dbg);
1235 
1236   WithColor::error() << "No command specified.\n";
1237   return 1;
1238 }
1239