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