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