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