xref: /llvm-project/lldb/tools/lldb-test/lldb-test.cpp (revision 59d2495fe2c1254f84ad4d2bd61a41e79ff0d44d)
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 }
883 
884 int opts::symtab::handleSymtabCommand(Debugger &Dbg) {
885   if (auto error = validate()) {
886     logAllUnhandledErrors(std::move(error.getValue()), WithColor::error(), "");
887     return 1;
888   }
889 
890   if (!FindSymbolsByRegex.empty()) {
891     ModuleSpec Spec{FileSpec(InputFile)};
892 
893     auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
894     auto *Symtab = ModulePtr->GetSymtab();
895     auto NamePreference = getNamePreference();
896     std::vector<uint32_t> Indexes;
897 
898     Symtab->FindAllSymbolsMatchingRexExAndType(
899         RegularExpression(FindSymbolsByRegex), lldb::eSymbolTypeAny,
900         Symtab::eDebugAny, Symtab::eVisibilityAny, Indexes, NamePreference);
901     for (auto i : Indexes) {
902       auto *symbol = Symtab->SymbolAtIndex(i);
903       if (symbol) {
904         StreamString stream;
905         symbol->Dump(&stream, nullptr, i, NamePreference);
906         outs() << stream.GetString();
907       }
908     }
909   }
910 
911   return 0;
912 }
913 
914 int opts::symbols::dumpSymbols(Debugger &Dbg) {
915   auto ActionOr = getAction();
916   if (!ActionOr) {
917     logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), "");
918     return 1;
919   }
920   auto Action = *ActionOr;
921 
922   outs() << "Module: " << InputFile << "\n";
923   ModuleSpec Spec{FileSpec(InputFile)};
924   StringRef Symbols = SymbolPath.empty() ? InputFile : SymbolPath;
925   Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native);
926 
927   auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
928   SymbolFile *Symfile = ModulePtr->GetSymbolFile();
929   if (!Symfile) {
930     WithColor::error() << "Module has no symbol vendor.\n";
931     return 1;
932   }
933 
934   if (Error E = Action(*ModulePtr)) {
935     WithColor::error() << toString(std::move(E)) << "\n";
936     return 1;
937   }
938 
939   return 0;
940 }
941 
942 static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) {
943   size_t Count = List.GetNumSections(0);
944   if (Count == 0) {
945     Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : "");
946     return;
947   }
948   Printer.formatLine("Showing {0} {1}sections", Count,
949                      is_subsection ? "sub" : "");
950   for (size_t I = 0; I < Count; ++I) {
951     auto S = List.GetSectionAtIndex(I);
952     assert(S);
953     AutoIndent Indent(Printer, 2);
954     Printer.formatLine("Index: {0}", I);
955     Printer.formatLine("ID: {0:x}", S->GetID());
956     Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
957     Printer.formatLine("Type: {0}", S->GetTypeAsCString());
958     Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions()));
959     Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific());
960     Printer.formatLine("VM address: {0:x}", S->GetFileAddress());
961     Printer.formatLine("VM size: {0}", S->GetByteSize());
962     Printer.formatLine("File size: {0}", S->GetFileSize());
963 
964     if (opts::object::SectionContents) {
965       lldb_private::DataExtractor Data;
966       S->GetSectionData(Data);
967       ArrayRef<uint8_t> Bytes(Data.GetDataStart(), Data.GetDataEnd());
968       Printer.formatBinary("Data: ", Bytes, 0);
969     }
970 
971     if (S->GetType() == eSectionTypeContainer)
972       dumpSectionList(Printer, S->GetChildren(), true);
973     Printer.NewLine();
974   }
975 }
976 
977 static int dumpObjectFiles(Debugger &Dbg) {
978   LinePrinter Printer(4, llvm::outs());
979 
980   int HadErrors = 0;
981   for (const auto &File : opts::object::InputFilenames) {
982     ModuleSpec Spec{FileSpec(File)};
983 
984     auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
985 
986     ObjectFile *ObjectPtr = ModulePtr->GetObjectFile();
987     if (!ObjectPtr) {
988       WithColor::error() << File << " not recognised as an object file\n";
989       HadErrors = 1;
990       continue;
991     }
992 
993     // Fetch symbol vendor before we get the section list to give the symbol
994     // vendor a chance to populate it.
995     ModulePtr->GetSymbolFile();
996     SectionList *Sections = ModulePtr->GetSectionList();
997     if (!Sections) {
998       llvm::errs() << "Could not load sections for module " << File << "\n";
999       HadErrors = 1;
1000       continue;
1001     }
1002 
1003     Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName());
1004     Printer.formatLine("Architecture: {0}",
1005                        ModulePtr->GetArchitecture().GetTriple().getTriple());
1006     Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
1007     Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable());
1008     Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped());
1009     Printer.formatLine("Type: {0}", ObjectPtr->GetType());
1010     Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata());
1011     Printer.formatLine("Base VM address: {0:x}",
1012                        ObjectPtr->GetBaseAddress().GetFileAddress());
1013 
1014     dumpSectionList(Printer, *Sections, /*is_subsection*/ false);
1015 
1016     if (opts::object::SectionDependentModules) {
1017       // A non-empty section list ensures a valid object file.
1018       auto Obj = ModulePtr->GetObjectFile();
1019       FileSpecList Files;
1020       auto Count = Obj->GetDependentModules(Files);
1021       Printer.formatLine("Showing {0} dependent module(s)", Count);
1022       for (size_t I = 0; I < Files.GetSize(); ++I) {
1023         AutoIndent Indent(Printer, 2);
1024         Printer.formatLine("Name: {0}",
1025                            Files.GetFileSpecAtIndex(I).GetPath());
1026       }
1027       Printer.NewLine();
1028     }
1029   }
1030   return HadErrors;
1031 }
1032 
1033 bool opts::irmemorymap::evalMalloc(StringRef Line,
1034                                    IRMemoryMapTestState &State) {
1035   // ::= <label> = malloc <size> <alignment>
1036   StringRef Label;
1037   std::tie(Label, Line) = Line.split('=');
1038   if (Line.empty())
1039     return false;
1040   Label = Label.trim();
1041   Line = Line.trim();
1042   size_t Size;
1043   uint8_t Alignment;
1044   int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment);
1045   if (Matches != 2)
1046     return false;
1047 
1048   outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label,
1049                     Size, Alignment);
1050   if (!isPowerOf2_32(Alignment)) {
1051     outs() << "Malloc error: alignment is not a power of 2\n";
1052     exit(1);
1053   }
1054 
1055   IRMemoryMap::AllocationPolicy AP =
1056       UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly
1057                                   : IRMemoryMap::eAllocationPolicyProcessOnly;
1058 
1059   // Issue the malloc in the target process with "-rw" permissions.
1060   const uint32_t Permissions = 0x3;
1061   const bool ZeroMemory = false;
1062   Status ST;
1063   addr_t Addr =
1064       State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST);
1065   if (ST.Fail()) {
1066     outs() << formatv("Malloc error: {0}\n", ST);
1067     return true;
1068   }
1069 
1070   // Print the result of the allocation before checking its validity.
1071   outs() << formatv("Malloc: address = {0:x}\n", Addr);
1072 
1073   // Check that the allocation is aligned.
1074   if (!Addr || Addr % Alignment != 0) {
1075     outs() << "Malloc error: zero or unaligned allocation detected\n";
1076     exit(1);
1077   }
1078 
1079   // In case of Size == 0, we still expect the returned address to be unique and
1080   // non-overlapping.
1081   addr_t EndOfRegion = Addr + std::max<size_t>(Size, 1);
1082   if (State.Allocations.overlaps(Addr, EndOfRegion)) {
1083     auto I = State.Allocations.find(Addr);
1084     outs() << "Malloc error: overlapping allocation detected"
1085            << formatv(", previous allocation at [{0:x}, {1:x})\n", I.start(),
1086                       I.stop());
1087     exit(1);
1088   }
1089 
1090   // Insert the new allocation into the interval map. Use unique allocation
1091   // IDs to inhibit interval coalescing.
1092   static unsigned AllocationID = 0;
1093   State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
1094 
1095   // Store the label -> address mapping.
1096   State.Label2AddrMap[Label] = Addr;
1097 
1098   return true;
1099 }
1100 
1101 bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) {
1102   // ::= free <label>
1103   if (!Line.consume_front("free"))
1104     return false;
1105   StringRef Label = Line.trim();
1106 
1107   outs() << formatv("Command: free({0})\n", Label);
1108   auto LabelIt = State.Label2AddrMap.find(Label);
1109   if (LabelIt == State.Label2AddrMap.end()) {
1110     outs() << "Free error: Invalid allocation label\n";
1111     exit(1);
1112   }
1113 
1114   Status ST;
1115   addr_t Addr = LabelIt->getValue();
1116   State.Map.Free(Addr, ST);
1117   if (ST.Fail()) {
1118     outs() << formatv("Free error: {0}\n", ST);
1119     exit(1);
1120   }
1121 
1122   // Erase the allocation from the live interval map.
1123   auto Interval = State.Allocations.find(Addr);
1124   if (Interval != State.Allocations.end()) {
1125     outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(),
1126                       Interval.stop());
1127     Interval.erase();
1128   }
1129 
1130   return true;
1131 }
1132 
1133 int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
1134   // Set up a Target.
1135   TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target);
1136 
1137   // Set up a Process. In order to allocate memory within a target, this
1138   // process must be alive and must support JIT'ing.
1139   CommandReturnObject Result(/*colors*/ false);
1140   Dbg.SetAsyncExecution(false);
1141   CommandInterpreter &CI = Dbg.GetCommandInterpreter();
1142   auto IssueCmd = [&](const char *Cmd) -> bool {
1143     return CI.HandleCommand(Cmd, eLazyBoolNo, Result);
1144   };
1145   if (!IssueCmd("b main") || !IssueCmd("run")) {
1146     outs() << formatv("Failed: {0}\n", Result.GetErrorData());
1147     exit(1);
1148   }
1149 
1150   ProcessSP Process = Target->GetProcessSP();
1151   if (!Process || !Process->IsAlive() || !Process->CanJIT()) {
1152     outs() << "Cannot use process to test IRMemoryMap\n";
1153     exit(1);
1154   }
1155 
1156   // Set up an IRMemoryMap and associated testing state.
1157   IRMemoryMapTestState State(Target);
1158 
1159   // Parse and apply commands from the command file.
1160   std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile);
1161   StringRef Rest = MB->getBuffer();
1162   while (!Rest.empty()) {
1163     StringRef Line;
1164     std::tie(Line, Rest) = Rest.split('\n');
1165     Line = Line.ltrim().rtrim();
1166 
1167     if (Line.empty() || Line[0] == '#')
1168       continue;
1169 
1170     if (evalMalloc(Line, State))
1171       continue;
1172 
1173     if (evalFree(Line, State))
1174       continue;
1175 
1176     errs() << "Could not parse line: " << Line << "\n";
1177     exit(1);
1178   }
1179   return 0;
1180 }
1181 
1182 int opts::assert::lldb_assert(Debugger &Dbg) {
1183   lldbassert(false && "lldb-test assert");
1184   return 1;
1185 }
1186 
1187 int main(int argc, const char *argv[]) {
1188   StringRef ToolName = argv[0];
1189   sys::PrintStackTraceOnErrorSignal(ToolName);
1190   PrettyStackTraceProgram X(argc, argv);
1191   llvm_shutdown_obj Y;
1192 
1193   cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
1194 
1195   SystemLifetimeManager DebuggerLifetime;
1196   if (auto e = DebuggerLifetime.Initialize(
1197           std::make_unique<SystemInitializerTest>(), nullptr)) {
1198     WithColor::error() << "initialization failed: " << toString(std::move(e))
1199                        << '\n';
1200     return 1;
1201   }
1202 
1203   auto TerminateDebugger =
1204       llvm::make_scope_exit([&] { DebuggerLifetime.Terminate(); });
1205 
1206   auto Dbg = lldb_private::Debugger::CreateInstance();
1207   ModuleList::GetGlobalModuleListProperties().SetEnableExternalLookup(false);
1208   CommandReturnObject Result(/*colors*/ false);
1209   Dbg->GetCommandInterpreter().HandleCommand(
1210       "settings set plugin.process.gdb-remote.packet-timeout 60",
1211       /*add_to_history*/ eLazyBoolNo, Result);
1212   Dbg->GetCommandInterpreter().HandleCommand(
1213       "settings set target.inherit-tcc true",
1214       /*add_to_history*/ eLazyBoolNo, Result);
1215   Dbg->GetCommandInterpreter().HandleCommand(
1216       "settings set target.detach-on-error false",
1217       /*add_to_history*/ eLazyBoolNo, Result);
1218 
1219   if (!opts::Log.empty())
1220     Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, 0, eLogHandlerStream, errs());
1221 
1222   if (opts::BreakpointSubcommand)
1223     return opts::breakpoint::evaluateBreakpoints(*Dbg);
1224   if (opts::ObjectFileSubcommand)
1225     return dumpObjectFiles(*Dbg);
1226   if (opts::SymbolsSubcommand)
1227     return opts::symbols::dumpSymbols(*Dbg);
1228   if (opts::SymTabSubcommand)
1229     return opts::symtab::handleSymtabCommand(*Dbg);
1230   if (opts::IRMemoryMapSubcommand)
1231     return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
1232   if (opts::AssertSubcommand)
1233     return opts::assert::lldb_assert(*Dbg);
1234 
1235   WithColor::error() << "No command specified.\n";
1236   return 1;
1237 }
1238