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