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