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("ClassOrStruct", CompilerContextKind::ClassOrStruct) 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: {"; 325 lldb_private::StreamString s; 326 llvm::interleaveComma(result, s, [&](auto &ctx) { ctx.Dump(s); }); 327 outs() << s.GetString().str() << "}\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 auto compiler_context = parseCompilerContext(); 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 if (!compiler_context.empty()) { 502 List.Clear(); 503 Module.FindFunctions(compiler_context, getFunctionNameFlags(), {}, List); 504 } else { 505 Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile); 506 if (!ContextOr) 507 return ContextOr.takeError(); 508 const CompilerDeclContext &ContextPtr = 509 ContextOr->IsValid() ? *ContextOr : CompilerDeclContext(); 510 511 List.Clear(); 512 Module::LookupInfo lookup_info(ConstString(Name), getFunctionNameFlags(), 513 eLanguageTypeUnknown); 514 Symfile.FindFunctions(lookup_info, ContextPtr, true, List); 515 } 516 outs() << formatv("Found {0} functions:\n", List.GetSize()); 517 StreamString Stream; 518 List.Dump(&Stream, nullptr); 519 outs() << Stream.GetData() << "\n"; 520 return Error::success(); 521 } 522 523 Error opts::symbols::findBlocks(lldb_private::Module &Module) { 524 assert(!Regex); 525 assert(!File.empty()); 526 assert(Line != 0); 527 528 SymbolContextList List; 529 530 FileSpec src_file(File); 531 size_t cu_count = Module.GetNumCompileUnits(); 532 for (size_t i = 0; i < cu_count; i++) { 533 lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i); 534 if (!cu_sp) 535 continue; 536 537 LineEntry le; 538 cu_sp->FindLineEntry(0, Line, &src_file, false, &le); 539 if (!le.IsValid()) 540 continue; 541 const bool include_inlined_functions = false; 542 auto addr = le.GetSameLineContiguousAddressRange(include_inlined_functions) 543 .GetBaseAddress(); 544 if (!addr.IsValid()) 545 continue; 546 547 SymbolContext sc; 548 uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock); 549 if (resolved & eSymbolContextBlock) 550 List.Append(sc); 551 } 552 553 outs() << formatv("Found {0} blocks:\n", List.GetSize()); 554 StreamString Stream; 555 List.Dump(&Stream, nullptr); 556 outs() << Stream.GetData() << "\n"; 557 return Error::success(); 558 } 559 560 Error opts::symbols::findNamespaces(lldb_private::Module &Module) { 561 SymbolFile &Symfile = *Module.GetSymbolFile(); 562 Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile); 563 if (!ContextOr) 564 return ContextOr.takeError(); 565 const CompilerDeclContext &ContextPtr = 566 ContextOr->IsValid() ? *ContextOr : CompilerDeclContext(); 567 568 CompilerDeclContext Result = 569 Symfile.FindNamespace(ConstString(Name), ContextPtr); 570 if (Result) 571 outs() << "Found namespace: " 572 << Result.GetScopeQualifiedName().GetStringRef() << "\n"; 573 else 574 outs() << "Namespace not found.\n"; 575 return Error::success(); 576 } 577 578 Error opts::symbols::findTypes(lldb_private::Module &Module) { 579 SymbolFile &Symfile = *Module.GetSymbolFile(); 580 Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile); 581 if (!ContextOr) 582 return ContextOr.takeError(); 583 584 TypeResults results; 585 if (!Name.empty()) { 586 if (ContextOr->IsValid()) { 587 TypeQuery query(*ContextOr, ConstString(Name), 588 TypeQueryOptions::e_module_search); 589 if (!Language.empty()) 590 query.AddLanguage(Language::GetLanguageTypeFromString(Language)); 591 Symfile.FindTypes(query, results); 592 } else { 593 TypeQuery query(Name); 594 if (!Language.empty()) 595 query.AddLanguage(Language::GetLanguageTypeFromString(Language)); 596 Symfile.FindTypes(query, results); 597 } 598 } else { 599 TypeQuery query(parseCompilerContext(), TypeQueryOptions::e_module_search); 600 if (!Language.empty()) 601 query.AddLanguage(Language::GetLanguageTypeFromString(Language)); 602 Symfile.FindTypes(query, results); 603 } 604 outs() << formatv("Found {0} types:\n", results.GetTypeMap().GetSize()); 605 StreamString Stream; 606 // Resolve types to force-materialize typedef types. 607 for (const auto &type_sp : results.GetTypeMap().Types()) 608 type_sp->GetFullCompilerType(); 609 results.GetTypeMap().Dump(&Stream, false, GetDescriptionLevel()); 610 outs() << Stream.GetData() << "\n"; 611 return Error::success(); 612 } 613 614 Error opts::symbols::findVariables(lldb_private::Module &Module) { 615 SymbolFile &Symfile = *Module.GetSymbolFile(); 616 VariableList List; 617 if (Regex) { 618 RegularExpression RE(Name); 619 assert(RE.IsValid()); 620 Symfile.FindGlobalVariables(RE, UINT32_MAX, List); 621 } else if (!File.empty()) { 622 CompUnitSP CU; 623 for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) { 624 CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind); 625 if (!Candidate || 626 Candidate->GetPrimaryFile().GetFilename().GetStringRef() != File) 627 continue; 628 if (CU) 629 return make_string_error("Multiple compile units for file `{0}` found.", 630 File); 631 CU = std::move(Candidate); 632 } 633 634 if (!CU) 635 return make_string_error("Compile unit `{0}` not found.", File); 636 637 List.AddVariables(CU->GetVariableList(true).get()); 638 } else { 639 Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile); 640 if (!ContextOr) 641 return ContextOr.takeError(); 642 const CompilerDeclContext &ContextPtr = 643 ContextOr->IsValid() ? *ContextOr : CompilerDeclContext(); 644 645 Symfile.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List); 646 } 647 outs() << formatv("Found {0} variables:\n", List.GetSize()); 648 StreamString Stream; 649 List.Dump(&Stream, false); 650 outs() << Stream.GetData() << "\n"; 651 return Error::success(); 652 } 653 654 Error opts::symbols::dumpModule(lldb_private::Module &Module) { 655 StreamString Stream; 656 Module.ParseAllDebugSymbols(); 657 Module.Dump(&Stream); 658 outs() << Stream.GetData() << "\n"; 659 return Error::success(); 660 } 661 662 Error opts::symbols::dumpAST(lldb_private::Module &Module) { 663 Module.ParseAllDebugSymbols(); 664 665 SymbolFile *symfile = Module.GetSymbolFile(); 666 if (!symfile) 667 return make_string_error("Module has no symbol file."); 668 669 auto type_system_or_err = 670 symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); 671 if (!type_system_or_err) 672 return make_string_error("Can't retrieve TypeSystemClang"); 673 674 auto ts = *type_system_or_err; 675 auto *clang_ast_ctx = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); 676 if (!clang_ast_ctx) 677 return make_string_error("Retrieved TypeSystem was not a TypeSystemClang"); 678 679 clang::ASTContext &ast_ctx = clang_ast_ctx->getASTContext(); 680 681 clang::TranslationUnitDecl *tu = ast_ctx.getTranslationUnitDecl(); 682 if (!tu) 683 return make_string_error("Can't retrieve translation unit declaration."); 684 685 tu->print(outs()); 686 687 return Error::success(); 688 } 689 690 Error opts::symbols::dumpEntireClangAST(lldb_private::Module &Module) { 691 Module.ParseAllDebugSymbols(); 692 693 SymbolFile *symfile = Module.GetSymbolFile(); 694 if (!symfile) 695 return make_string_error("Module has no symbol file."); 696 697 auto type_system_or_err = 698 symfile->GetTypeSystemForLanguage(eLanguageTypeObjC_plus_plus); 699 if (!type_system_or_err) 700 return make_string_error("Can't retrieve TypeSystemClang"); 701 auto ts = *type_system_or_err; 702 auto *clang_ast_ctx = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); 703 if (!clang_ast_ctx) 704 return make_string_error("Retrieved TypeSystem was not a TypeSystemClang"); 705 706 StreamString Stream; 707 clang_ast_ctx->DumpFromSymbolFile(Stream, Name); 708 outs() << Stream.GetData() << "\n"; 709 710 return Error::success(); 711 } 712 713 Error opts::symbols::verify(lldb_private::Module &Module) { 714 SymbolFile *symfile = Module.GetSymbolFile(); 715 if (!symfile) 716 return make_string_error("Module has no symbol file."); 717 718 uint32_t comp_units_count = symfile->GetNumCompileUnits(); 719 720 outs() << "Found " << comp_units_count << " compile units.\n"; 721 722 for (uint32_t i = 0; i < comp_units_count; i++) { 723 lldb::CompUnitSP comp_unit = symfile->GetCompileUnitAtIndex(i); 724 if (!comp_unit) 725 return make_string_error("Cannot parse compile unit {0}.", i); 726 727 outs() << "Processing '" 728 << comp_unit->GetPrimaryFile().GetFilename().AsCString() 729 << "' compile unit.\n"; 730 731 LineTable *lt = comp_unit->GetLineTable(); 732 if (!lt) 733 return make_string_error("Can't get a line table of a compile unit."); 734 735 uint32_t count = lt->GetSize(); 736 737 outs() << "The line table contains " << count << " entries.\n"; 738 739 if (count == 0) 740 continue; 741 742 LineEntry le; 743 if (!lt->GetLineEntryAtIndex(0, le)) 744 return make_string_error("Can't get a line entry of a compile unit."); 745 746 for (uint32_t i = 1; i < count; i++) { 747 lldb::addr_t curr_end = 748 le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize(); 749 750 if (!lt->GetLineEntryAtIndex(i, le)) 751 return make_string_error("Can't get a line entry of a compile unit"); 752 753 if (curr_end > le.range.GetBaseAddress().GetFileAddress()) 754 return make_string_error( 755 "Line table of a compile unit is inconsistent."); 756 } 757 } 758 759 outs() << "The symbol information is verified.\n"; 760 761 return Error::success(); 762 } 763 764 Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() { 765 if (Verify && DumpAST) 766 return make_string_error( 767 "Cannot both verify symbol information and dump AST."); 768 769 if (Verify) { 770 if (Find != FindType::None) 771 return make_string_error( 772 "Cannot both search and verify symbol information."); 773 if (Regex || !Context.empty() || !Name.empty() || !File.empty() || 774 Line != 0) 775 return make_string_error( 776 "-regex, -context, -name, -file and -line options are not " 777 "applicable for symbol verification."); 778 return verify; 779 } 780 781 if (DumpAST) { 782 if (Find != FindType::None) 783 return make_string_error("Cannot both search and dump AST."); 784 if (Regex || !Context.empty() || !Name.empty() || !File.empty() || 785 Line != 0) 786 return make_string_error( 787 "-regex, -context, -name, -file and -line options are not " 788 "applicable for dumping AST."); 789 return dumpAST; 790 } 791 792 if (DumpClangAST) { 793 if (Find == FindType::None) { 794 if (Regex || !Context.empty() || !File.empty() || Line != 0) 795 return make_string_error( 796 "-regex, -context, -name, -file and -line options are not " 797 "applicable for dumping the entire clang AST. Either combine with " 798 "-find, or use -dump-clang-ast as a standalone option."); 799 return dumpEntireClangAST; 800 } 801 if (Find != FindType::Type) 802 return make_string_error("This combination of -dump-clang-ast and -find " 803 "<kind> is not yet implemented."); 804 } 805 806 if (Regex && !Context.empty()) 807 return make_string_error( 808 "Cannot search using both regular expressions and context."); 809 810 if (Regex && !RegularExpression(Name).IsValid()) 811 return make_string_error("`{0}` is not a valid regular expression.", Name); 812 813 if (Regex + !Context.empty() + !File.empty() >= 2) 814 return make_string_error( 815 "Only one of -regex, -context and -file may be used simultaneously."); 816 if (Regex && Name.empty()) 817 return make_string_error("-regex used without a -name"); 818 819 switch (Find) { 820 case FindType::None: 821 if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0) 822 return make_string_error( 823 "Specify search type (-find) to use search options."); 824 return dumpModule; 825 826 case FindType::Function: 827 if (!File.empty() + (Line != 0) == 1) 828 return make_string_error("Both file name and line number must be " 829 "specified when searching a function " 830 "by file position."); 831 if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2) 832 return make_string_error("Only one of regular expression, function-flags " 833 "and file position may be used simultaneously " 834 "when searching a function."); 835 return findFunctions; 836 837 case FindType::Block: 838 if (File.empty() || Line == 0) 839 return make_string_error("Both file name and line number must be " 840 "specified when searching a block."); 841 if (Regex || getFunctionNameFlags() != 0) 842 return make_string_error("Cannot use regular expression or " 843 "function-flags for searching a block."); 844 return findBlocks; 845 846 case FindType::Namespace: 847 if (Regex || !File.empty() || Line != 0) 848 return make_string_error("Cannot search for namespaces using regular " 849 "expressions, file names or line numbers."); 850 return findNamespaces; 851 852 case FindType::Type: 853 if (Regex || !File.empty() || Line != 0) 854 return make_string_error("Cannot search for types using regular " 855 "expressions, file names or line numbers."); 856 if (!Name.empty() && !CompilerContext.empty()) 857 return make_string_error("Name is ignored if compiler context present."); 858 859 return findTypes; 860 861 case FindType::Variable: 862 if (Line != 0) 863 return make_string_error("Cannot search for variables " 864 "using line numbers."); 865 return findVariables; 866 } 867 868 llvm_unreachable("Unsupported symbol action."); 869 } 870 871 std::optional<llvm::Error> opts::symtab::validate() { 872 if (ManglingPreference != ManglingPreference::None && 873 FindSymbolsByRegex.empty()) 874 return make_string_error("Mangling preference set but no regex specified."); 875 876 return {}; 877 } 878 879 static Mangled::NamePreference opts::symtab::getNamePreference() { 880 switch (ManglingPreference) { 881 case ManglingPreference::None: 882 case ManglingPreference::Mangled: 883 return Mangled::ePreferMangled; 884 case ManglingPreference::Demangled: 885 return Mangled::ePreferDemangled; 886 case ManglingPreference::MangledWithoutArguments: 887 return Mangled::ePreferDemangledWithoutArguments; 888 } 889 llvm_unreachable("Fully covered switch above!"); 890 } 891 892 int opts::symtab::handleSymtabCommand(Debugger &Dbg) { 893 if (auto error = validate()) { 894 logAllUnhandledErrors(std::move(*error), WithColor::error(), ""); 895 return 1; 896 } 897 898 if (!FindSymbolsByRegex.empty()) { 899 ModuleSpec Spec{FileSpec(InputFile)}; 900 901 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec); 902 auto *Symtab = ModulePtr->GetSymtab(); 903 auto NamePreference = getNamePreference(); 904 std::vector<uint32_t> Indexes; 905 906 Symtab->FindAllSymbolsMatchingRexExAndType( 907 RegularExpression(FindSymbolsByRegex), lldb::eSymbolTypeAny, 908 Symtab::eDebugAny, Symtab::eVisibilityAny, Indexes, NamePreference); 909 for (auto i : Indexes) { 910 auto *symbol = Symtab->SymbolAtIndex(i); 911 if (symbol) { 912 StreamString stream; 913 symbol->Dump(&stream, nullptr, i, NamePreference); 914 outs() << stream.GetString(); 915 } 916 } 917 } 918 919 return 0; 920 } 921 922 int opts::symbols::dumpSymbols(Debugger &Dbg) { 923 auto ActionOr = getAction(); 924 if (!ActionOr) { 925 logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), ""); 926 return 1; 927 } 928 auto Action = *ActionOr; 929 930 outs() << "Module: " << InputFile << "\n"; 931 ModuleSpec Spec{FileSpec(InputFile)}; 932 StringRef Symbols = SymbolPath.empty() ? InputFile : SymbolPath; 933 Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native); 934 935 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec); 936 SymbolFile *Symfile = ModulePtr->GetSymbolFile(); 937 if (!Symfile) { 938 WithColor::error() << "Module has no symbol vendor.\n"; 939 return 1; 940 } 941 942 if (Error E = Action(*ModulePtr)) { 943 WithColor::error() << toString(std::move(E)) << "\n"; 944 return 1; 945 } 946 947 return 0; 948 } 949 950 static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) { 951 size_t Count = List.GetNumSections(0); 952 if (Count == 0) { 953 Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : ""); 954 return; 955 } 956 Printer.formatLine("Showing {0} {1}sections", Count, 957 is_subsection ? "sub" : ""); 958 for (size_t I = 0; I < Count; ++I) { 959 auto S = List.GetSectionAtIndex(I); 960 assert(S); 961 AutoIndent Indent(Printer, 2); 962 Printer.formatLine("Index: {0}", I); 963 Printer.formatLine("ID: {0:x}", S->GetID()); 964 Printer.formatLine("Name: {0}", S->GetName().GetStringRef()); 965 Printer.formatLine("Type: {0}", S->GetTypeAsCString()); 966 Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions())); 967 Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific()); 968 Printer.formatLine("VM address: {0:x}", S->GetFileAddress()); 969 Printer.formatLine("VM size: {0}", S->GetByteSize()); 970 Printer.formatLine("File size: {0}", S->GetFileSize()); 971 972 if (opts::object::SectionContents) { 973 lldb_private::DataExtractor Data; 974 S->GetSectionData(Data); 975 ArrayRef<uint8_t> Bytes(Data.GetDataStart(), Data.GetDataEnd()); 976 Printer.formatBinary("Data: ", Bytes, 0); 977 } 978 979 if (S->GetType() == eSectionTypeContainer) 980 dumpSectionList(Printer, S->GetChildren(), true); 981 Printer.NewLine(); 982 } 983 } 984 985 static int dumpObjectFiles(Debugger &Dbg) { 986 LinePrinter Printer(4, llvm::outs()); 987 988 int HadErrors = 0; 989 for (const auto &File : opts::object::InputFilenames) { 990 ModuleSpec Spec{FileSpec(File)}; 991 992 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec); 993 994 ObjectFile *ObjectPtr = ModulePtr->GetObjectFile(); 995 if (!ObjectPtr) { 996 WithColor::error() << File << " not recognised as an object file\n"; 997 HadErrors = 1; 998 continue; 999 } 1000 1001 // Fetch symbol vendor before we get the section list to give the symbol 1002 // vendor a chance to populate it. 1003 ModulePtr->GetSymbolFile(); 1004 SectionList *Sections = ModulePtr->GetSectionList(); 1005 if (!Sections) { 1006 llvm::errs() << "Could not load sections for module " << File << "\n"; 1007 HadErrors = 1; 1008 continue; 1009 } 1010 1011 Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName()); 1012 Printer.formatLine("Architecture: {0}", 1013 ModulePtr->GetArchitecture().GetTriple().getTriple()); 1014 Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString()); 1015 Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable()); 1016 Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped()); 1017 Printer.formatLine("Type: {0}", ObjectPtr->GetType()); 1018 Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata()); 1019 Printer.formatLine("Base VM address: {0:x}", 1020 ObjectPtr->GetBaseAddress().GetFileAddress()); 1021 1022 dumpSectionList(Printer, *Sections, /*is_subsection*/ false); 1023 1024 if (opts::object::SectionDependentModules) { 1025 // A non-empty section list ensures a valid object file. 1026 auto Obj = ModulePtr->GetObjectFile(); 1027 FileSpecList Files; 1028 auto Count = Obj->GetDependentModules(Files); 1029 Printer.formatLine("Showing {0} dependent module(s)", Count); 1030 for (size_t I = 0; I < Files.GetSize(); ++I) { 1031 AutoIndent Indent(Printer, 2); 1032 Printer.formatLine("Name: {0}", 1033 Files.GetFileSpecAtIndex(I).GetPath()); 1034 } 1035 Printer.NewLine(); 1036 } 1037 } 1038 return HadErrors; 1039 } 1040 1041 bool opts::irmemorymap::evalMalloc(StringRef Line, 1042 IRMemoryMapTestState &State) { 1043 // ::= <label> = malloc <size> <alignment> 1044 StringRef Label; 1045 std::tie(Label, Line) = Line.split('='); 1046 if (Line.empty()) 1047 return false; 1048 Label = Label.trim(); 1049 Line = Line.trim(); 1050 size_t Size; 1051 uint8_t Alignment; 1052 int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment); 1053 if (Matches != 2) 1054 return false; 1055 1056 outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label, 1057 Size, Alignment); 1058 if (!isPowerOf2_32(Alignment)) { 1059 outs() << "Malloc error: alignment is not a power of 2\n"; 1060 exit(1); 1061 } 1062 1063 IRMemoryMap::AllocationPolicy AP = 1064 UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly 1065 : IRMemoryMap::eAllocationPolicyProcessOnly; 1066 1067 // Issue the malloc in the target process with "-rw" permissions. 1068 const uint32_t Permissions = 0x3; 1069 const bool ZeroMemory = false; 1070 Status ST; 1071 addr_t Addr = 1072 State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST); 1073 if (ST.Fail()) { 1074 outs() << formatv("Malloc error: {0}\n", ST); 1075 return true; 1076 } 1077 1078 // Print the result of the allocation before checking its validity. 1079 outs() << formatv("Malloc: address = {0:x}\n", Addr); 1080 1081 // Check that the allocation is aligned. 1082 if (!Addr || Addr % Alignment != 0) { 1083 outs() << "Malloc error: zero or unaligned allocation detected\n"; 1084 exit(1); 1085 } 1086 1087 // In case of Size == 0, we still expect the returned address to be unique and 1088 // non-overlapping. 1089 addr_t EndOfRegion = Addr + std::max<size_t>(Size, 1); 1090 if (State.Allocations.overlaps(Addr, EndOfRegion)) { 1091 auto I = State.Allocations.find(Addr); 1092 outs() << "Malloc error: overlapping allocation detected" 1093 << formatv(", previous allocation at [{0:x}, {1:x})\n", I.start(), 1094 I.stop()); 1095 exit(1); 1096 } 1097 1098 // Insert the new allocation into the interval map. Use unique allocation 1099 // IDs to inhibit interval coalescing. 1100 static unsigned AllocationID = 0; 1101 State.Allocations.insert(Addr, EndOfRegion, AllocationID++); 1102 1103 // Store the label -> address mapping. 1104 State.Label2AddrMap[Label] = Addr; 1105 1106 return true; 1107 } 1108 1109 bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) { 1110 // ::= free <label> 1111 if (!Line.consume_front("free")) 1112 return false; 1113 StringRef Label = Line.trim(); 1114 1115 outs() << formatv("Command: free({0})\n", Label); 1116 auto LabelIt = State.Label2AddrMap.find(Label); 1117 if (LabelIt == State.Label2AddrMap.end()) { 1118 outs() << "Free error: Invalid allocation label\n"; 1119 exit(1); 1120 } 1121 1122 Status ST; 1123 addr_t Addr = LabelIt->getValue(); 1124 State.Map.Free(Addr, ST); 1125 if (ST.Fail()) { 1126 outs() << formatv("Free error: {0}\n", ST); 1127 exit(1); 1128 } 1129 1130 // Erase the allocation from the live interval map. 1131 auto Interval = State.Allocations.find(Addr); 1132 if (Interval != State.Allocations.end()) { 1133 outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(), 1134 Interval.stop()); 1135 Interval.erase(); 1136 } 1137 1138 return true; 1139 } 1140 1141 int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) { 1142 // Set up a Target. 1143 TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target); 1144 1145 // Set up a Process. In order to allocate memory within a target, this 1146 // process must be alive and must support JIT'ing. 1147 CommandReturnObject Result(/*colors*/ false); 1148 Dbg.SetAsyncExecution(false); 1149 CommandInterpreter &CI = Dbg.GetCommandInterpreter(); 1150 auto IssueCmd = [&](const char *Cmd) -> bool { 1151 return CI.HandleCommand(Cmd, eLazyBoolNo, Result); 1152 }; 1153 if (!IssueCmd("b main") || !IssueCmd("run")) { 1154 outs() << formatv("Failed: {0}\n", Result.GetErrorData()); 1155 exit(1); 1156 } 1157 1158 ProcessSP Process = Target->GetProcessSP(); 1159 if (!Process || !Process->IsAlive() || !Process->CanJIT()) { 1160 outs() << "Cannot use process to test IRMemoryMap\n"; 1161 exit(1); 1162 } 1163 1164 // Set up an IRMemoryMap and associated testing state. 1165 IRMemoryMapTestState State(Target); 1166 1167 // Parse and apply commands from the command file. 1168 std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile); 1169 StringRef Rest = MB->getBuffer(); 1170 while (!Rest.empty()) { 1171 StringRef Line; 1172 std::tie(Line, Rest) = Rest.split('\n'); 1173 Line = Line.ltrim().rtrim(); 1174 1175 if (Line.empty() || Line[0] == '#') 1176 continue; 1177 1178 if (evalMalloc(Line, State)) 1179 continue; 1180 1181 if (evalFree(Line, State)) 1182 continue; 1183 1184 errs() << "Could not parse line: " << Line << "\n"; 1185 exit(1); 1186 } 1187 return 0; 1188 } 1189 1190 int opts::assert::lldb_assert(Debugger &Dbg) { 1191 lldbassert(false && "lldb-test assert"); 1192 return 1; 1193 } 1194 1195 int main(int argc, const char *argv[]) { 1196 StringRef ToolName = argv[0]; 1197 sys::PrintStackTraceOnErrorSignal(ToolName); 1198 PrettyStackTraceProgram X(argc, argv); 1199 llvm_shutdown_obj Y; 1200 1201 cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n"); 1202 1203 SystemLifetimeManager DebuggerLifetime; 1204 if (auto e = DebuggerLifetime.Initialize( 1205 std::make_unique<SystemInitializerTest>(), nullptr)) { 1206 WithColor::error() << "initialization failed: " << toString(std::move(e)) 1207 << '\n'; 1208 return 1; 1209 } 1210 1211 auto TerminateDebugger = 1212 llvm::make_scope_exit([&] { DebuggerLifetime.Terminate(); }); 1213 1214 auto Dbg = lldb_private::Debugger::CreateInstance(); 1215 ModuleList::GetGlobalModuleListProperties().SetEnableExternalLookup(false); 1216 CommandReturnObject Result(/*colors*/ false); 1217 Dbg->GetCommandInterpreter().HandleCommand( 1218 "settings set plugin.process.gdb-remote.packet-timeout 60", 1219 /*add_to_history*/ eLazyBoolNo, Result); 1220 Dbg->GetCommandInterpreter().HandleCommand( 1221 "settings set target.inherit-tcc true", 1222 /*add_to_history*/ eLazyBoolNo, Result); 1223 Dbg->GetCommandInterpreter().HandleCommand( 1224 "settings set target.detach-on-error false", 1225 /*add_to_history*/ eLazyBoolNo, Result); 1226 1227 if (!opts::Log.empty()) 1228 Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, 0, eLogHandlerStream, errs()); 1229 1230 if (opts::BreakpointSubcommand) 1231 return opts::breakpoint::evaluateBreakpoints(*Dbg); 1232 if (opts::ObjectFileSubcommand) 1233 return dumpObjectFiles(*Dbg); 1234 if (opts::SymbolsSubcommand) 1235 return opts::symbols::dumpSymbols(*Dbg); 1236 if (opts::SymTabSubcommand) 1237 return opts::symtab::handleSymtabCommand(*Dbg); 1238 if (opts::IRMemoryMapSubcommand) 1239 return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg); 1240 if (opts::AssertSubcommand) 1241 return opts::assert::lldb_assert(*Dbg); 1242 1243 WithColor::error() << "No command specified.\n"; 1244 return 1; 1245 } 1246