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