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