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