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