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