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 } 883 884 int opts::symtab::handleSymtabCommand(Debugger &Dbg) { 885 if (auto error = validate()) { 886 logAllUnhandledErrors(std::move(error.getValue()), WithColor::error(), ""); 887 return 1; 888 } 889 890 if (!FindSymbolsByRegex.empty()) { 891 ModuleSpec Spec{FileSpec(InputFile)}; 892 893 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec); 894 auto *Symtab = ModulePtr->GetSymtab(); 895 auto NamePreference = getNamePreference(); 896 std::vector<uint32_t> Indexes; 897 898 Symtab->FindAllSymbolsMatchingRexExAndType( 899 RegularExpression(FindSymbolsByRegex), lldb::eSymbolTypeAny, 900 Symtab::eDebugAny, Symtab::eVisibilityAny, Indexes, NamePreference); 901 for (auto i : Indexes) { 902 auto *symbol = Symtab->SymbolAtIndex(i); 903 if (symbol) { 904 StreamString stream; 905 symbol->Dump(&stream, nullptr, i, NamePreference); 906 outs() << stream.GetString(); 907 } 908 } 909 } 910 911 return 0; 912 } 913 914 int opts::symbols::dumpSymbols(Debugger &Dbg) { 915 auto ActionOr = getAction(); 916 if (!ActionOr) { 917 logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), ""); 918 return 1; 919 } 920 auto Action = *ActionOr; 921 922 outs() << "Module: " << InputFile << "\n"; 923 ModuleSpec Spec{FileSpec(InputFile)}; 924 StringRef Symbols = SymbolPath.empty() ? InputFile : SymbolPath; 925 Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native); 926 927 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec); 928 SymbolFile *Symfile = ModulePtr->GetSymbolFile(); 929 if (!Symfile) { 930 WithColor::error() << "Module has no symbol vendor.\n"; 931 return 1; 932 } 933 934 if (Error E = Action(*ModulePtr)) { 935 WithColor::error() << toString(std::move(E)) << "\n"; 936 return 1; 937 } 938 939 return 0; 940 } 941 942 static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) { 943 size_t Count = List.GetNumSections(0); 944 if (Count == 0) { 945 Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : ""); 946 return; 947 } 948 Printer.formatLine("Showing {0} {1}sections", Count, 949 is_subsection ? "sub" : ""); 950 for (size_t I = 0; I < Count; ++I) { 951 auto S = List.GetSectionAtIndex(I); 952 assert(S); 953 AutoIndent Indent(Printer, 2); 954 Printer.formatLine("Index: {0}", I); 955 Printer.formatLine("ID: {0:x}", S->GetID()); 956 Printer.formatLine("Name: {0}", S->GetName().GetStringRef()); 957 Printer.formatLine("Type: {0}", S->GetTypeAsCString()); 958 Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions())); 959 Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific()); 960 Printer.formatLine("VM address: {0:x}", S->GetFileAddress()); 961 Printer.formatLine("VM size: {0}", S->GetByteSize()); 962 Printer.formatLine("File size: {0}", S->GetFileSize()); 963 964 if (opts::object::SectionContents) { 965 lldb_private::DataExtractor Data; 966 S->GetSectionData(Data); 967 ArrayRef<uint8_t> Bytes(Data.GetDataStart(), Data.GetDataEnd()); 968 Printer.formatBinary("Data: ", Bytes, 0); 969 } 970 971 if (S->GetType() == eSectionTypeContainer) 972 dumpSectionList(Printer, S->GetChildren(), true); 973 Printer.NewLine(); 974 } 975 } 976 977 static int dumpObjectFiles(Debugger &Dbg) { 978 LinePrinter Printer(4, llvm::outs()); 979 980 int HadErrors = 0; 981 for (const auto &File : opts::object::InputFilenames) { 982 ModuleSpec Spec{FileSpec(File)}; 983 984 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec); 985 986 ObjectFile *ObjectPtr = ModulePtr->GetObjectFile(); 987 if (!ObjectPtr) { 988 WithColor::error() << File << " not recognised as an object file\n"; 989 HadErrors = 1; 990 continue; 991 } 992 993 // Fetch symbol vendor before we get the section list to give the symbol 994 // vendor a chance to populate it. 995 ModulePtr->GetSymbolFile(); 996 SectionList *Sections = ModulePtr->GetSectionList(); 997 if (!Sections) { 998 llvm::errs() << "Could not load sections for module " << File << "\n"; 999 HadErrors = 1; 1000 continue; 1001 } 1002 1003 Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName()); 1004 Printer.formatLine("Architecture: {0}", 1005 ModulePtr->GetArchitecture().GetTriple().getTriple()); 1006 Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString()); 1007 Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable()); 1008 Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped()); 1009 Printer.formatLine("Type: {0}", ObjectPtr->GetType()); 1010 Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata()); 1011 Printer.formatLine("Base VM address: {0:x}", 1012 ObjectPtr->GetBaseAddress().GetFileAddress()); 1013 1014 dumpSectionList(Printer, *Sections, /*is_subsection*/ false); 1015 1016 if (opts::object::SectionDependentModules) { 1017 // A non-empty section list ensures a valid object file. 1018 auto Obj = ModulePtr->GetObjectFile(); 1019 FileSpecList Files; 1020 auto Count = Obj->GetDependentModules(Files); 1021 Printer.formatLine("Showing {0} dependent module(s)", Count); 1022 for (size_t I = 0; I < Files.GetSize(); ++I) { 1023 AutoIndent Indent(Printer, 2); 1024 Printer.formatLine("Name: {0}", 1025 Files.GetFileSpecAtIndex(I).GetPath()); 1026 } 1027 Printer.NewLine(); 1028 } 1029 } 1030 return HadErrors; 1031 } 1032 1033 bool opts::irmemorymap::evalMalloc(StringRef Line, 1034 IRMemoryMapTestState &State) { 1035 // ::= <label> = malloc <size> <alignment> 1036 StringRef Label; 1037 std::tie(Label, Line) = Line.split('='); 1038 if (Line.empty()) 1039 return false; 1040 Label = Label.trim(); 1041 Line = Line.trim(); 1042 size_t Size; 1043 uint8_t Alignment; 1044 int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment); 1045 if (Matches != 2) 1046 return false; 1047 1048 outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label, 1049 Size, Alignment); 1050 if (!isPowerOf2_32(Alignment)) { 1051 outs() << "Malloc error: alignment is not a power of 2\n"; 1052 exit(1); 1053 } 1054 1055 IRMemoryMap::AllocationPolicy AP = 1056 UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly 1057 : IRMemoryMap::eAllocationPolicyProcessOnly; 1058 1059 // Issue the malloc in the target process with "-rw" permissions. 1060 const uint32_t Permissions = 0x3; 1061 const bool ZeroMemory = false; 1062 Status ST; 1063 addr_t Addr = 1064 State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST); 1065 if (ST.Fail()) { 1066 outs() << formatv("Malloc error: {0}\n", ST); 1067 return true; 1068 } 1069 1070 // Print the result of the allocation before checking its validity. 1071 outs() << formatv("Malloc: address = {0:x}\n", Addr); 1072 1073 // Check that the allocation is aligned. 1074 if (!Addr || Addr % Alignment != 0) { 1075 outs() << "Malloc error: zero or unaligned allocation detected\n"; 1076 exit(1); 1077 } 1078 1079 // In case of Size == 0, we still expect the returned address to be unique and 1080 // non-overlapping. 1081 addr_t EndOfRegion = Addr + std::max<size_t>(Size, 1); 1082 if (State.Allocations.overlaps(Addr, EndOfRegion)) { 1083 auto I = State.Allocations.find(Addr); 1084 outs() << "Malloc error: overlapping allocation detected" 1085 << formatv(", previous allocation at [{0:x}, {1:x})\n", I.start(), 1086 I.stop()); 1087 exit(1); 1088 } 1089 1090 // Insert the new allocation into the interval map. Use unique allocation 1091 // IDs to inhibit interval coalescing. 1092 static unsigned AllocationID = 0; 1093 State.Allocations.insert(Addr, EndOfRegion, AllocationID++); 1094 1095 // Store the label -> address mapping. 1096 State.Label2AddrMap[Label] = Addr; 1097 1098 return true; 1099 } 1100 1101 bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) { 1102 // ::= free <label> 1103 if (!Line.consume_front("free")) 1104 return false; 1105 StringRef Label = Line.trim(); 1106 1107 outs() << formatv("Command: free({0})\n", Label); 1108 auto LabelIt = State.Label2AddrMap.find(Label); 1109 if (LabelIt == State.Label2AddrMap.end()) { 1110 outs() << "Free error: Invalid allocation label\n"; 1111 exit(1); 1112 } 1113 1114 Status ST; 1115 addr_t Addr = LabelIt->getValue(); 1116 State.Map.Free(Addr, ST); 1117 if (ST.Fail()) { 1118 outs() << formatv("Free error: {0}\n", ST); 1119 exit(1); 1120 } 1121 1122 // Erase the allocation from the live interval map. 1123 auto Interval = State.Allocations.find(Addr); 1124 if (Interval != State.Allocations.end()) { 1125 outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(), 1126 Interval.stop()); 1127 Interval.erase(); 1128 } 1129 1130 return true; 1131 } 1132 1133 int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) { 1134 // Set up a Target. 1135 TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target); 1136 1137 // Set up a Process. In order to allocate memory within a target, this 1138 // process must be alive and must support JIT'ing. 1139 CommandReturnObject Result(/*colors*/ false); 1140 Dbg.SetAsyncExecution(false); 1141 CommandInterpreter &CI = Dbg.GetCommandInterpreter(); 1142 auto IssueCmd = [&](const char *Cmd) -> bool { 1143 return CI.HandleCommand(Cmd, eLazyBoolNo, Result); 1144 }; 1145 if (!IssueCmd("b main") || !IssueCmd("run")) { 1146 outs() << formatv("Failed: {0}\n", Result.GetErrorData()); 1147 exit(1); 1148 } 1149 1150 ProcessSP Process = Target->GetProcessSP(); 1151 if (!Process || !Process->IsAlive() || !Process->CanJIT()) { 1152 outs() << "Cannot use process to test IRMemoryMap\n"; 1153 exit(1); 1154 } 1155 1156 // Set up an IRMemoryMap and associated testing state. 1157 IRMemoryMapTestState State(Target); 1158 1159 // Parse and apply commands from the command file. 1160 std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile); 1161 StringRef Rest = MB->getBuffer(); 1162 while (!Rest.empty()) { 1163 StringRef Line; 1164 std::tie(Line, Rest) = Rest.split('\n'); 1165 Line = Line.ltrim().rtrim(); 1166 1167 if (Line.empty() || Line[0] == '#') 1168 continue; 1169 1170 if (evalMalloc(Line, State)) 1171 continue; 1172 1173 if (evalFree(Line, State)) 1174 continue; 1175 1176 errs() << "Could not parse line: " << Line << "\n"; 1177 exit(1); 1178 } 1179 return 0; 1180 } 1181 1182 int opts::assert::lldb_assert(Debugger &Dbg) { 1183 lldbassert(false && "lldb-test assert"); 1184 return 1; 1185 } 1186 1187 int main(int argc, const char *argv[]) { 1188 StringRef ToolName = argv[0]; 1189 sys::PrintStackTraceOnErrorSignal(ToolName); 1190 PrettyStackTraceProgram X(argc, argv); 1191 llvm_shutdown_obj Y; 1192 1193 cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n"); 1194 1195 SystemLifetimeManager DebuggerLifetime; 1196 if (auto e = DebuggerLifetime.Initialize( 1197 std::make_unique<SystemInitializerTest>(), nullptr)) { 1198 WithColor::error() << "initialization failed: " << toString(std::move(e)) 1199 << '\n'; 1200 return 1; 1201 } 1202 1203 auto TerminateDebugger = 1204 llvm::make_scope_exit([&] { DebuggerLifetime.Terminate(); }); 1205 1206 auto Dbg = lldb_private::Debugger::CreateInstance(); 1207 ModuleList::GetGlobalModuleListProperties().SetEnableExternalLookup(false); 1208 CommandReturnObject Result(/*colors*/ false); 1209 Dbg->GetCommandInterpreter().HandleCommand( 1210 "settings set plugin.process.gdb-remote.packet-timeout 60", 1211 /*add_to_history*/ eLazyBoolNo, Result); 1212 Dbg->GetCommandInterpreter().HandleCommand( 1213 "settings set target.inherit-tcc true", 1214 /*add_to_history*/ eLazyBoolNo, Result); 1215 Dbg->GetCommandInterpreter().HandleCommand( 1216 "settings set target.detach-on-error false", 1217 /*add_to_history*/ eLazyBoolNo, Result); 1218 1219 if (!opts::Log.empty()) 1220 Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, 0, eLogHandlerStream, errs()); 1221 1222 if (opts::BreakpointSubcommand) 1223 return opts::breakpoint::evaluateBreakpoints(*Dbg); 1224 if (opts::ObjectFileSubcommand) 1225 return dumpObjectFiles(*Dbg); 1226 if (opts::SymbolsSubcommand) 1227 return opts::symbols::dumpSymbols(*Dbg); 1228 if (opts::SymTabSubcommand) 1229 return opts::symtab::handleSymtabCommand(*Dbg); 1230 if (opts::IRMemoryMapSubcommand) 1231 return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg); 1232 if (opts::AssertSubcommand) 1233 return opts::assert::lldb_assert(*Dbg); 1234 1235 WithColor::error() << "No command specified.\n"; 1236 return 1; 1237 } 1238