1 //===- lldb-test.cpp ------------------------------------------ *- C++ --*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "FormatUtil.h"
11 #include "SystemInitializerTest.h"
12 
13 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.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/ClangASTContext.h"
23 #include "lldb/Symbol/ClangASTImporter.h"
24 #include "lldb/Symbol/CompileUnit.h"
25 #include "lldb/Symbol/LineTable.h"
26 #include "lldb/Symbol/SymbolVendor.h"
27 #include "lldb/Symbol/TypeList.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::list<std::string> InputFilenames(cl::Positional,
104                                             cl::desc("<input files>"),
105                                             cl::OneOrMore,
106                                             cl::sub(SymbolsSubcommand));
107 enum class FindType {
108   None,
109   Function,
110   Block,
111   Namespace,
112   Type,
113   Variable,
114 };
115 static cl::opt<FindType> Find(
116     "find", cl::desc("Choose search type:"),
117     cl::values(
118         clEnumValN(FindType::None, "none", "No search, just dump the module."),
119         clEnumValN(FindType::Function, "function", "Find functions."),
120         clEnumValN(FindType::Block, "block", "Find blocks."),
121         clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
122         clEnumValN(FindType::Type, "type", "Find types."),
123         clEnumValN(FindType::Variable, "variable", "Find global variables.")),
124     cl::sub(SymbolsSubcommand));
125 
126 static cl::opt<std::string> Name("name", cl::desc("Name to find."),
127                                  cl::sub(SymbolsSubcommand));
128 static cl::opt<bool>
129     Regex("regex",
130           cl::desc("Search using regular expressions (avaliable for variables "
131                    "and functions only)."),
132           cl::sub(SymbolsSubcommand));
133 static cl::opt<std::string>
134     Context("context",
135             cl::desc("Restrict search to the context of the given variable."),
136             cl::value_desc("variable"), cl::sub(SymbolsSubcommand));
137 
138 static cl::list<FunctionNameType> FunctionNameFlags(
139     "function-flags", cl::desc("Function search flags:"),
140     cl::values(clEnumValN(eFunctionNameTypeAuto, "auto",
141                           "Automatically deduce flags based on name."),
142                clEnumValN(eFunctionNameTypeFull, "full", "Full function name."),
143                clEnumValN(eFunctionNameTypeBase, "base", "Base name."),
144                clEnumValN(eFunctionNameTypeMethod, "method", "Method name."),
145                clEnumValN(eFunctionNameTypeSelector, "selector",
146                           "Selector name.")),
147     cl::sub(SymbolsSubcommand));
148 static FunctionNameType getFunctionNameFlags() {
149   FunctionNameType Result = FunctionNameType(0);
150   for (FunctionNameType Flag : FunctionNameFlags)
151     Result = FunctionNameType(Result | Flag);
152   return Result;
153 }
154 
155 static cl::opt<bool> DumpAST("dump-ast",
156                              cl::desc("Dump AST restored from symbols."),
157                              cl::sub(SymbolsSubcommand));
158 
159 static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
160                             cl::sub(SymbolsSubcommand));
161 
162 static cl::opt<std::string> File("file",
163                                  cl::desc("File (compile unit) to search."),
164                                  cl::sub(SymbolsSubcommand));
165 static cl::opt<int> Line("line", cl::desc("Line to search."),
166                          cl::sub(SymbolsSubcommand));
167 
168 static Expected<CompilerDeclContext> getDeclContext(SymbolVendor &Vendor);
169 
170 static Error findFunctions(lldb_private::Module &Module);
171 static Error findBlocks(lldb_private::Module &Module);
172 static Error findNamespaces(lldb_private::Module &Module);
173 static Error findTypes(lldb_private::Module &Module);
174 static Error findVariables(lldb_private::Module &Module);
175 static Error dumpModule(lldb_private::Module &Module);
176 static Error dumpAST(lldb_private::Module &Module);
177 static Error verify(lldb_private::Module &Module);
178 
179 static Expected<Error (*)(lldb_private::Module &)> getAction();
180 static int dumpSymbols(Debugger &Dbg);
181 } // namespace symbols
182 
183 namespace irmemorymap {
184 static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
185                                    cl::Required,
186                                    cl::sub(IRMemoryMapSubcommand));
187 static cl::opt<std::string> CommandFile(cl::Positional,
188                                         cl::desc("<command-file>"),
189                                         cl::init("-"),
190                                         cl::sub(IRMemoryMapSubcommand));
191 static cl::opt<bool> UseHostOnlyAllocationPolicy(
192     "host-only", cl::desc("Use the host-only allocation policy"),
193     cl::init(false), cl::sub(IRMemoryMapSubcommand));
194 
195 using AllocationT = std::pair<addr_t, addr_t>;
196 using AddrIntervalMap =
197     IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>;
198 
199 struct IRMemoryMapTestState {
200   TargetSP Target;
201   IRMemoryMap Map;
202 
203   AddrIntervalMap::Allocator IntervalMapAllocator;
204   AddrIntervalMap Allocations;
205 
206   StringMap<addr_t> Label2AddrMap;
207 
208   IRMemoryMapTestState(TargetSP Target)
209       : Target(Target), Map(Target), Allocations(IntervalMapAllocator) {}
210 };
211 
212 bool evalMalloc(StringRef Line, IRMemoryMapTestState &State);
213 bool evalFree(StringRef Line, IRMemoryMapTestState &State);
214 int evaluateMemoryMapCommands(Debugger &Dbg);
215 } // namespace irmemorymap
216 
217 } // namespace opts
218 
219 template <typename... Args>
220 static Error make_string_error(const char *Format, Args &&... args) {
221   return llvm::make_error<llvm::StringError>(
222       llvm::formatv(Format, std::forward<Args>(args)...).str(),
223       llvm::inconvertibleErrorCode());
224 }
225 
226 TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) {
227   TargetSP Target;
228   Status ST = Dbg.GetTargetList().CreateTarget(
229       Dbg, Filename, /*triple*/ "", eLoadDependentsNo,
230       /*platform_options*/ nullptr, Target);
231   if (ST.Fail()) {
232     errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST);
233     exit(1);
234   }
235   return Target;
236 }
237 
238 std::unique_ptr<MemoryBuffer> opts::openFile(const std::string &Filename) {
239   auto MB = MemoryBuffer::getFileOrSTDIN(Filename);
240   if (!MB) {
241     errs() << formatv("Could not open file '{0}: {1}\n", Filename,
242                       MB.getError().message());
243     exit(1);
244   }
245   return std::move(*MB);
246 }
247 
248 void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) {
249   P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize()));
250   if (List.GetSize() > 0)
251     P.formatLine("At least one breakpoint.");
252   for (size_t i = 0, e = List.GetSize(); i < e; ++i) {
253     BreakpointSP BP = List.GetBreakpointAtIndex(i);
254     P.formatLine("Breakpoint ID {0}:", BP->GetID());
255     AutoIndent Indent(P, 2);
256     P.formatLine("{0} location{1}.", BP->GetNumLocations(),
257                  plural(BP->GetNumLocations()));
258     if (BP->GetNumLocations() > 0)
259       P.formatLine("At least one location.");
260     P.formatLine("{0} resolved location{1}.", BP->GetNumResolvedLocations(),
261                  plural(BP->GetNumResolvedLocations()));
262     if (BP->GetNumResolvedLocations() > 0)
263       P.formatLine("At least one resolved location.");
264     for (size_t l = 0, le = BP->GetNumLocations(); l < le; ++l) {
265       BreakpointLocationSP Loc = BP->GetLocationAtIndex(l);
266       P.formatLine("Location ID {0}:", Loc->GetID());
267       AutoIndent Indent(P, 2);
268       P.formatLine("Enabled: {0}", Loc->IsEnabled());
269       P.formatLine("Resolved: {0}", Loc->IsResolved());
270       SymbolContext sc;
271       Loc->GetAddress().CalculateSymbolContext(&sc);
272       lldb_private::StreamString S;
273       sc.DumpStopContext(&S, BP->GetTarget().GetProcessSP().get(),
274                          Loc->GetAddress(), false, true, false, true, true);
275       P.formatLine("Address: {0}", S.GetString());
276     }
277   }
278   P.NewLine();
279 }
280 
281 std::string opts::breakpoint::substitute(StringRef Cmd) {
282   std::string Result;
283   raw_string_ostream OS(Result);
284   while (!Cmd.empty()) {
285     switch (Cmd[0]) {
286     case '%':
287       if (Cmd.consume_front("%p") && (Cmd.empty() || !isalnum(Cmd[0]))) {
288         OS << sys::path::parent_path(breakpoint::CommandFile);
289         break;
290       }
291       LLVM_FALLTHROUGH;
292     default:
293       size_t pos = Cmd.find('%');
294       OS << Cmd.substr(0, pos);
295       Cmd = Cmd.substr(pos);
296       break;
297     }
298   }
299   return std::move(OS.str());
300 }
301 
302 int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
303   TargetSP Target = opts::createTarget(Dbg, breakpoint::Target);
304   std::unique_ptr<MemoryBuffer> MB = opts::openFile(breakpoint::CommandFile);
305 
306   LinePrinter P(4, outs());
307   StringRef Rest = MB->getBuffer();
308   int HadErrors = 0;
309   while (!Rest.empty()) {
310     StringRef Line;
311     std::tie(Line, Rest) = Rest.split('\n');
312     Line = Line.ltrim();
313     if (Line.empty() || Line[0] == '#')
314       continue;
315 
316     if (!Persistent)
317       Target->RemoveAllBreakpoints(/*internal_also*/ true);
318 
319     std::string Command = substitute(Line);
320     P.formatLine("Command: {0}", Command);
321     CommandReturnObject Result;
322     if (!Dbg.GetCommandInterpreter().HandleCommand(
323             Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
324       P.formatLine("Failed: {0}", Result.GetErrorData());
325       HadErrors = 1;
326       continue;
327     }
328 
329     dumpState(Target->GetBreakpointList(/*internal*/ false), P);
330   }
331   return HadErrors;
332 }
333 
334 Expected<CompilerDeclContext>
335 opts::symbols::getDeclContext(SymbolVendor &Vendor) {
336   if (Context.empty())
337     return CompilerDeclContext();
338   VariableList List;
339   Vendor.FindGlobalVariables(ConstString(Context), nullptr, UINT32_MAX, List);
340   if (List.Empty())
341     return make_string_error("Context search didn't find a match.");
342   if (List.GetSize() > 1)
343     return make_string_error("Context search found multiple matches.");
344   return List.GetVariableAtIndex(0)->GetDeclContext();
345 }
346 
347 Error opts::symbols::findFunctions(lldb_private::Module &Module) {
348   SymbolVendor &Vendor = *Module.GetSymbolVendor();
349   SymbolContextList List;
350   if (!File.empty()) {
351     assert(Line != 0);
352 
353     FileSpec src_file(File);
354     size_t cu_count = Module.GetNumCompileUnits();
355     for (size_t i = 0; i < cu_count; i++) {
356       lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
357       if (!cu_sp)
358         continue;
359 
360       LineEntry le;
361       cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
362       if (!le.IsValid())
363         continue;
364 
365       auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress();
366       if (!addr.IsValid())
367         continue;
368 
369       SymbolContext sc;
370       uint32_t resolved =
371           addr.CalculateSymbolContext(&sc, eSymbolContextFunction);
372       if (resolved & eSymbolContextFunction)
373         List.Append(sc);
374     }
375   } else if (Regex) {
376     RegularExpression RE(Name);
377     assert(RE.IsValid());
378     Vendor.FindFunctions(RE, true, false, List);
379   } else {
380     Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
381     if (!ContextOr)
382       return ContextOr.takeError();
383     CompilerDeclContext *ContextPtr =
384         ContextOr->IsValid() ? &*ContextOr : nullptr;
385 
386     Vendor.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
387                          true, false, List);
388   }
389   outs() << formatv("Found {0} functions:\n", List.GetSize());
390   StreamString Stream;
391   List.Dump(&Stream, nullptr);
392   outs() << Stream.GetData() << "\n";
393   return Error::success();
394 }
395 
396 Error opts::symbols::findBlocks(lldb_private::Module &Module) {
397   assert(!Regex);
398   assert(!File.empty());
399   assert(Line != 0);
400 
401   SymbolContextList List;
402 
403   FileSpec src_file(File);
404   size_t cu_count = Module.GetNumCompileUnits();
405   for (size_t i = 0; i < cu_count; i++) {
406     lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
407     if (!cu_sp)
408       continue;
409 
410     LineEntry le;
411     cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
412     if (!le.IsValid())
413       continue;
414 
415     auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress();
416     if (!addr.IsValid())
417       continue;
418 
419     SymbolContext sc;
420     uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock);
421     if (resolved & eSymbolContextBlock)
422       List.Append(sc);
423   }
424 
425   outs() << formatv("Found {0} blocks:\n", List.GetSize());
426   StreamString Stream;
427   List.Dump(&Stream, nullptr);
428   outs() << Stream.GetData() << "\n";
429   return Error::success();
430 }
431 
432 Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
433   SymbolVendor &Vendor = *Module.GetSymbolVendor();
434   Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
435   if (!ContextOr)
436     return ContextOr.takeError();
437   CompilerDeclContext *ContextPtr =
438       ContextOr->IsValid() ? &*ContextOr : nullptr;
439 
440   SymbolContext SC;
441   CompilerDeclContext Result =
442       Vendor.FindNamespace(SC, ConstString(Name), ContextPtr);
443   if (Result)
444     outs() << "Found namespace: "
445            << Result.GetScopeQualifiedName().GetStringRef() << "\n";
446   else
447     outs() << "Namespace not found.\n";
448   return Error::success();
449 }
450 
451 Error opts::symbols::findTypes(lldb_private::Module &Module) {
452   SymbolVendor &Vendor = *Module.GetSymbolVendor();
453   Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
454   if (!ContextOr)
455     return ContextOr.takeError();
456   CompilerDeclContext *ContextPtr =
457       ContextOr->IsValid() ? &*ContextOr : nullptr;
458 
459   SymbolContext SC;
460   DenseSet<SymbolFile *> SearchedFiles;
461   TypeMap Map;
462   Vendor.FindTypes(SC, ConstString(Name), ContextPtr, true, UINT32_MAX,
463                    SearchedFiles, Map);
464 
465   outs() << formatv("Found {0} types:\n", Map.GetSize());
466   StreamString Stream;
467   Map.Dump(&Stream, false);
468   outs() << Stream.GetData() << "\n";
469   return Error::success();
470 }
471 
472 Error opts::symbols::findVariables(lldb_private::Module &Module) {
473   SymbolVendor &Vendor = *Module.GetSymbolVendor();
474   VariableList List;
475   if (Regex) {
476     RegularExpression RE(Name);
477     assert(RE.IsValid());
478     Vendor.FindGlobalVariables(RE, UINT32_MAX, List);
479   } else if (!File.empty()) {
480     CompUnitSP CU;
481     for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) {
482       CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind);
483       if (!Candidate || Candidate->GetFilename().GetStringRef() != File)
484         continue;
485       if (CU)
486         return make_string_error("Multiple compile units for file `{0}` found.",
487                                  File);
488       CU = std::move(Candidate);
489     }
490 
491     if (!CU)
492       return make_string_error("Compile unit `{0}` not found.", File);
493 
494     List.AddVariables(CU->GetVariableList(true).get());
495   } else {
496     Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
497     if (!ContextOr)
498       return ContextOr.takeError();
499     CompilerDeclContext *ContextPtr =
500         ContextOr->IsValid() ? &*ContextOr : nullptr;
501 
502     Vendor.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List);
503   }
504   outs() << formatv("Found {0} variables:\n", List.GetSize());
505   StreamString Stream;
506   List.Dump(&Stream, false);
507   outs() << Stream.GetData() << "\n";
508   return Error::success();
509 }
510 
511 Error opts::symbols::dumpModule(lldb_private::Module &Module) {
512   StreamString Stream;
513   Module.ParseAllDebugSymbols();
514   Module.Dump(&Stream);
515   outs() << Stream.GetData() << "\n";
516   return Error::success();
517 }
518 
519 Error opts::symbols::dumpAST(lldb_private::Module &Module) {
520   SymbolVendor &plugin = *Module.GetSymbolVendor();
521 
522   auto symfile = plugin.GetSymbolFile();
523   if (!symfile)
524     return make_string_error("Module has no symbol file.");
525 
526   auto clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
527       symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus));
528   if (!clang_ast_ctx)
529     return make_string_error("Can't retrieve Clang AST context.");
530 
531   auto ast_ctx = clang_ast_ctx->getASTContext();
532   if (!ast_ctx)
533     return make_string_error("Can't retrieve AST context.");
534 
535   auto tu = ast_ctx->getTranslationUnitDecl();
536   if (!tu)
537     return make_string_error("Can't retrieve translation unit declaration.");
538 
539   symfile->ParseDeclsForContext(CompilerDeclContext(
540       clang_ast_ctx, static_cast<clang::DeclContext *>(tu)));
541 
542   tu->print(outs());
543 
544   return Error::success();
545 }
546 
547 Error opts::symbols::verify(lldb_private::Module &Module) {
548   SymbolVendor &plugin = *Module.GetSymbolVendor();
549 
550   SymbolFile *symfile = plugin.GetSymbolFile();
551   if (!symfile)
552     return make_string_error("Module has no symbol file.");
553 
554   uint32_t comp_units_count = symfile->GetNumCompileUnits();
555 
556   outs() << "Found " << comp_units_count << " compile units.\n";
557 
558   for (uint32_t i = 0; i < comp_units_count; i++) {
559     lldb::CompUnitSP comp_unit = symfile->ParseCompileUnitAtIndex(i);
560     if (!comp_unit)
561       return make_string_error("Connot parse compile unit {0}.", i);
562 
563     outs() << "Processing '" << comp_unit->GetFilename().AsCString()
564            << "' compile unit.\n";
565 
566     LineTable *lt = comp_unit->GetLineTable();
567     if (!lt)
568       return make_string_error("Can't get a line table of a compile unit.");
569 
570     uint32_t count = lt->GetSize();
571 
572     outs() << "The line table contains " << count << " entries.\n";
573 
574     if (count == 0)
575       continue;
576 
577     LineEntry le;
578     if (!lt->GetLineEntryAtIndex(0, le))
579       return make_string_error("Can't get a line entry of a compile unit.");
580 
581     for (uint32_t i = 1; i < count; i++) {
582       lldb::addr_t curr_end =
583           le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
584 
585       if (!lt->GetLineEntryAtIndex(i, le))
586         return make_string_error("Can't get a line entry of a compile unit");
587 
588       if (curr_end > le.range.GetBaseAddress().GetFileAddress())
589         return make_string_error(
590             "Line table of a compile unit is inconsistent.");
591     }
592   }
593 
594   outs() << "The symbol information is verified.\n";
595 
596   return Error::success();
597 }
598 
599 Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
600   if (Verify && DumpAST)
601     return make_string_error(
602         "Cannot both verify symbol information and dump AST.");
603 
604   if (Verify) {
605     if (Find != FindType::None)
606       return make_string_error(
607           "Cannot both search and verify symbol information.");
608     if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
609         Line != 0)
610       return make_string_error(
611           "-regex, -context, -name, -file and -line options are not "
612           "applicable for symbol verification.");
613     return verify;
614   }
615 
616   if (DumpAST) {
617     if (Find != FindType::None)
618       return make_string_error("Cannot both search and dump AST.");
619     if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
620         Line != 0)
621       return make_string_error(
622           "-regex, -context, -name, -file and -line options are not "
623           "applicable for dumping AST.");
624     return dumpAST;
625   }
626 
627   if (Regex && !Context.empty())
628     return make_string_error(
629         "Cannot search using both regular expressions and context.");
630 
631   if (Regex && !RegularExpression(Name).IsValid())
632     return make_string_error("`{0}` is not a valid regular expression.", Name);
633 
634   if (Regex + !Context.empty() + !File.empty() >= 2)
635     return make_string_error(
636         "Only one of -regex, -context and -file may be used simultaneously.");
637   if (Regex && Name.empty())
638     return make_string_error("-regex used without a -name");
639 
640   switch (Find) {
641   case FindType::None:
642     if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0)
643       return make_string_error(
644           "Specify search type (-find) to use search options.");
645     return dumpModule;
646 
647   case FindType::Function:
648     if (!File.empty() + (Line != 0) == 1)
649       return make_string_error("Both file name and line number must be "
650                                "specified when searching a function "
651                                "by file position.");
652     if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2)
653       return make_string_error("Only one of regular expression, function-flags "
654                                "and file position may be used simultaneously "
655                                "when searching a function.");
656     return findFunctions;
657 
658   case FindType::Block:
659     if (File.empty() || Line == 0)
660       return make_string_error("Both file name and line number must be "
661                                "specified when searching a block.");
662     if (Regex || getFunctionNameFlags() != 0)
663       return make_string_error("Cannot use regular expression or "
664                                "function-flags for searching a block.");
665     return findBlocks;
666 
667   case FindType::Namespace:
668     if (Regex || !File.empty() || Line != 0)
669       return make_string_error("Cannot search for namespaces using regular "
670                                "expressions, file names or line numbers.");
671     return findNamespaces;
672 
673   case FindType::Type:
674     if (Regex || !File.empty() || Line != 0)
675       return make_string_error("Cannot search for types using regular "
676                                "expressions, file names or line numbers.");
677     return findTypes;
678 
679   case FindType::Variable:
680     if (Line != 0)
681       return make_string_error("Cannot search for variables "
682                                "using line numbers.");
683     return findVariables;
684   }
685 
686   llvm_unreachable("Unsupported symbol action.");
687 }
688 
689 int opts::symbols::dumpSymbols(Debugger &Dbg) {
690   auto ActionOr = getAction();
691   if (!ActionOr) {
692     logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), "");
693     return 1;
694   }
695   auto Action = *ActionOr;
696 
697   int HadErrors = 0;
698   for (const auto &File : InputFilenames) {
699     outs() << "Module: " << File << "\n";
700     ModuleSpec Spec{FileSpec(File)};
701     Spec.GetSymbolFileSpec().SetFile(File, FileSpec::Style::native);
702 
703     auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
704     SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
705     if (!Vendor) {
706       WithColor::error() << "Module has no symbol vendor.\n";
707       HadErrors = 1;
708       continue;
709     }
710 
711     if (Error E = Action(*ModulePtr)) {
712       WithColor::error() << toString(std::move(E)) << "\n";
713       HadErrors = 1;
714     }
715 
716     outs().flush();
717   }
718   return HadErrors;
719 }
720 
721 static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) {
722   size_t Count = List.GetNumSections(0);
723   if (Count == 0) {
724     Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : "");
725     return;
726   }
727   Printer.formatLine("Showing {0} {1}sections", Count,
728                      is_subsection ? "sub" : "");
729   for (size_t I = 0; I < Count; ++I) {
730     auto S = List.GetSectionAtIndex(I);
731     assert(S);
732     AutoIndent Indent(Printer, 2);
733     Printer.formatLine("Index: {0}", I);
734     Printer.formatLine("ID: {0:x}", S->GetID());
735     Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
736     Printer.formatLine("Type: {0}", S->GetTypeAsCString());
737     Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions()));
738     Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific());
739     Printer.formatLine("VM address: {0:x}", S->GetFileAddress());
740     Printer.formatLine("VM size: {0}", S->GetByteSize());
741     Printer.formatLine("File size: {0}", S->GetFileSize());
742 
743     if (opts::object::SectionContents) {
744       DataExtractor Data;
745       S->GetSectionData(Data);
746       ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()};
747       Printer.formatBinary("Data: ", Bytes, 0);
748     }
749 
750     if (S->GetType() == eSectionTypeContainer)
751       dumpSectionList(Printer, S->GetChildren(), true);
752     Printer.NewLine();
753   }
754 }
755 
756 static int dumpObjectFiles(Debugger &Dbg) {
757   LinePrinter Printer(4, llvm::outs());
758 
759   int HadErrors = 0;
760   for (const auto &File : opts::object::InputFilenames) {
761     ModuleSpec Spec{FileSpec(File)};
762 
763     auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
764 
765     ObjectFile *ObjectPtr = ModulePtr->GetObjectFile();
766     if (!ObjectPtr) {
767       WithColor::error() << File << " not recognised as an object file\n";
768       HadErrors = 1;
769       continue;
770     }
771 
772     // Fetch symbol vendor before we get the section list to give the symbol
773     // vendor a chance to populate it.
774     ModulePtr->GetSymbolVendor();
775     SectionList *Sections = ModulePtr->GetSectionList();
776     if (!Sections) {
777       llvm::errs() << "Could not load sections for module " << File << "\n";
778       HadErrors = 1;
779       continue;
780     }
781 
782     Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName());
783     Printer.formatLine("Architecture: {0}",
784                        ModulePtr->GetArchitecture().GetTriple().getTriple());
785     Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
786     Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable());
787     Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped());
788     Printer.formatLine("Type: {0}", ObjectPtr->GetType());
789     Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata());
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();
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 
979   if (!opts::Log.empty())
980     Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, errs());
981 
982   if (opts::BreakpointSubcommand)
983     return opts::breakpoint::evaluateBreakpoints(*Dbg);
984   if (opts::ObjectFileSubcommand)
985     return dumpObjectFiles(*Dbg);
986   if (opts::SymbolsSubcommand)
987     return opts::symbols::dumpSymbols(*Dbg);
988   if (opts::IRMemoryMapSubcommand)
989     return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
990 
991   WithColor::error() << "No command specified.\n";
992   return 1;
993 }
994