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