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