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