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