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