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