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