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