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