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