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