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