1888a4282SZachary Turner //===- lldb-test.cpp ------------------------------------------ *- C++ --*-===// 2888a4282SZachary Turner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6888a4282SZachary Turner // 7888a4282SZachary Turner //===----------------------------------------------------------------------===// 8888a4282SZachary Turner 9888a4282SZachary Turner #include "FormatUtil.h" 10888a4282SZachary Turner #include "SystemInitializerTest.h" 11888a4282SZachary Turner 12a6d5464cSZachary Turner #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" 138be30215SAlex Langford #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 147c94582fSPavel Labath #include "lldb/Breakpoint/BreakpointLocation.h" 15888a4282SZachary Turner #include "lldb/Core/Debugger.h" 16*d6b90282SAugusto Noronha #include "lldb/Core/Mangled.h" 17888a4282SZachary Turner #include "lldb/Core/Module.h" 18888a4282SZachary Turner #include "lldb/Core/Section.h" 19c1cd8262SVedant Kumar #include "lldb/Expression/IRMemoryMap.h" 20888a4282SZachary Turner #include "lldb/Initialization/SystemLifetimeManager.h" 217c94582fSPavel Labath #include "lldb/Interpreter/CommandInterpreter.h" 227c94582fSPavel Labath #include "lldb/Interpreter/CommandReturnObject.h" 23010edd37SAaron Smith #include "lldb/Symbol/CompileUnit.h" 24010edd37SAaron Smith #include "lldb/Symbol/LineTable.h" 25465eae36SPavel Labath #include "lldb/Symbol/SymbolFile.h" 263aef968eSAugusto Noronha #include "lldb/Symbol/Symtab.h" 27*d6b90282SAugusto Noronha #include "lldb/Symbol/Type.h" 2890b0a534SPavel Labath #include "lldb/Symbol/TypeList.h" 29465eae36SPavel Labath #include "lldb/Symbol/TypeMap.h" 3090b0a534SPavel Labath #include "lldb/Symbol/VariableList.h" 31aa97a89dSAdrian Prantl #include "lldb/Target/Language.h" 32c1cd8262SVedant Kumar #include "lldb/Target/Process.h" 33c1cd8262SVedant Kumar #include "lldb/Target/Target.h" 34888a4282SZachary Turner #include "lldb/Utility/DataExtractor.h" 35e089b5e9SJonas Devlieghere #include "lldb/Utility/LLDBAssert.h" 3662a8254fSPavel Labath #include "lldb/Utility/State.h" 37a6d5464cSZachary Turner #include "lldb/Utility/StreamString.h" 38888a4282SZachary Turner 39c1cd8262SVedant Kumar #include "llvm/ADT/IntervalMap.h" 40e0ea8d87SJonas Devlieghere #include "llvm/ADT/ScopeExit.h" 41888a4282SZachary Turner #include "llvm/ADT/StringRef.h" 42888a4282SZachary Turner #include "llvm/Support/CommandLine.h" 43888a4282SZachary Turner #include "llvm/Support/ManagedStatic.h" 449ea80d25SPavel Labath #include "llvm/Support/MathExtras.h" 457c94582fSPavel Labath #include "llvm/Support/Path.h" 46888a4282SZachary Turner #include "llvm/Support/PrettyStackTrace.h" 47888a4282SZachary Turner #include "llvm/Support/Signals.h" 4890b0a534SPavel Labath #include "llvm/Support/WithColor.h" 495f46982bSShafik Yaghmour 50c1cd8262SVedant Kumar #include <cstdio> 51f190ce62SKazu Hirata #include <optional> 52888a4282SZachary Turner #include <thread> 53888a4282SZachary Turner 54888a4282SZachary Turner using namespace lldb; 55888a4282SZachary Turner using namespace lldb_private; 56888a4282SZachary Turner using namespace llvm; 57888a4282SZachary Turner 58888a4282SZachary Turner namespace opts { 597c94582fSPavel Labath static cl::SubCommand BreakpointSubcommand("breakpoints", 607c94582fSPavel Labath "Test breakpoint resolution"); 6162a7f80aSPavel Labath cl::SubCommand ObjectFileSubcommand("object-file", 6262a7f80aSPavel Labath "Display LLDB object file information"); 63a6d5464cSZachary Turner cl::SubCommand SymbolsSubcommand("symbols", "Dump symbols for an object file"); 643aef968eSAugusto Noronha cl::SubCommand SymTabSubcommand("symtab", 653aef968eSAugusto Noronha "Test symbol table functionality"); 66c1cd8262SVedant Kumar cl::SubCommand IRMemoryMapSubcommand("ir-memory-map", "Test IRMemoryMap"); 67e089b5e9SJonas Devlieghere cl::SubCommand AssertSubcommand("assert", "Test assert handling"); 687e4c84a7SVedant Kumar 69c1cd8262SVedant Kumar cl::opt<std::string> Log("log", cl::desc("Path to a log file"), cl::init(""), 707e4c84a7SVedant Kumar cl::sub(BreakpointSubcommand), 7162a7f80aSPavel Labath cl::sub(ObjectFileSubcommand), 7262a7f80aSPavel Labath cl::sub(SymbolsSubcommand), 733aef968eSAugusto Noronha cl::sub(SymTabSubcommand), 74c1cd8262SVedant Kumar cl::sub(IRMemoryMapSubcommand)); 75c1cd8262SVedant Kumar 76c1cd8262SVedant Kumar /// Create a target using the file pointed to by \p Filename, or abort. 77c1cd8262SVedant Kumar TargetSP createTarget(Debugger &Dbg, const std::string &Filename); 78c1cd8262SVedant Kumar 79c1cd8262SVedant Kumar /// Read \p Filename into a null-terminated buffer, or abort. 80c1cd8262SVedant Kumar std::unique_ptr<MemoryBuffer> openFile(const std::string &Filename); 81888a4282SZachary Turner 827c94582fSPavel Labath namespace breakpoint { 837c94582fSPavel Labath static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"), 847c94582fSPavel Labath cl::Required, cl::sub(BreakpointSubcommand)); 857c94582fSPavel Labath static cl::opt<std::string> CommandFile(cl::Positional, 867c94582fSPavel Labath cl::desc("<command-file>"), 877c94582fSPavel Labath cl::init("-"), 887c94582fSPavel Labath cl::sub(BreakpointSubcommand)); 897c94582fSPavel Labath static cl::opt<bool> Persistent( 907c94582fSPavel Labath "persistent", 917c94582fSPavel Labath cl::desc("Don't automatically remove all breakpoints before each command"), 927c94582fSPavel Labath cl::sub(BreakpointSubcommand)); 937c94582fSPavel Labath 947c94582fSPavel Labath static llvm::StringRef plural(uintmax_t value) { return value == 1 ? "" : "s"; } 957c94582fSPavel Labath static void dumpState(const BreakpointList &List, LinePrinter &P); 967c94582fSPavel Labath static std::string substitute(StringRef Cmd); 9790b0a534SPavel Labath static int evaluateBreakpoints(Debugger &Dbg); 987c94582fSPavel Labath } // namespace breakpoint 997c94582fSPavel Labath 10062a7f80aSPavel Labath namespace object { 101888a4282SZachary Turner cl::opt<bool> SectionContents("contents", 102888a4282SZachary Turner cl::desc("Dump each section's contents"), 10362a7f80aSPavel Labath cl::sub(ObjectFileSubcommand)); 104037ed1beSAaron Smith cl::opt<bool> SectionDependentModules("dep-modules", 105037ed1beSAaron Smith cl::desc("Dump each dependent module"), 106037ed1beSAaron Smith cl::sub(ObjectFileSubcommand)); 107888a4282SZachary Turner cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"), 10862a7f80aSPavel Labath cl::OneOrMore, 10962a7f80aSPavel Labath cl::sub(ObjectFileSubcommand)); 11062a7f80aSPavel Labath } // namespace object 111a6d5464cSZachary Turner 1123aef968eSAugusto Noronha namespace symtab { 1133aef968eSAugusto Noronha 1143aef968eSAugusto Noronha /// The same enum as Mangled::NamePreference but with a default 1153aef968eSAugusto Noronha /// 'None' case. This is needed to disambiguate wheter "ManglingPreference" was 1163aef968eSAugusto Noronha /// explicitly set or not. 1173aef968eSAugusto Noronha enum class ManglingPreference { 1183aef968eSAugusto Noronha None, 1193aef968eSAugusto Noronha Mangled, 1203aef968eSAugusto Noronha Demangled, 1213aef968eSAugusto Noronha MangledWithoutArguments, 1223aef968eSAugusto Noronha }; 1233aef968eSAugusto Noronha 1243aef968eSAugusto Noronha static cl::opt<std::string> FindSymbolsByRegex( 1253aef968eSAugusto Noronha "find-symbols-by-regex", 1263aef968eSAugusto Noronha cl::desc( 1273aef968eSAugusto Noronha "Dump symbols found in the symbol table matching the specified regex."), 1283aef968eSAugusto Noronha cl::sub(SymTabSubcommand)); 1293aef968eSAugusto Noronha 1303aef968eSAugusto Noronha static cl::opt<ManglingPreference> ManglingPreference( 1313aef968eSAugusto Noronha "mangling-preference", 1323aef968eSAugusto Noronha cl::desc("Preference on mangling scheme the regex should match against and " 1333aef968eSAugusto Noronha "dumped."), 1343aef968eSAugusto Noronha cl::values( 1353aef968eSAugusto Noronha clEnumValN(ManglingPreference::Mangled, "mangled", "Prefer mangled"), 1363aef968eSAugusto Noronha clEnumValN(ManglingPreference::Demangled, "demangled", 1373aef968eSAugusto Noronha "Prefer demangled"), 1383aef968eSAugusto Noronha clEnumValN(ManglingPreference::MangledWithoutArguments, 1393aef968eSAugusto Noronha "demangled-without-args", "Prefer mangled without args")), 1403aef968eSAugusto Noronha cl::sub(SymTabSubcommand)); 1413aef968eSAugusto Noronha 1423aef968eSAugusto Noronha static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"), 1433aef968eSAugusto Noronha cl::Required, cl::sub(SymTabSubcommand)); 1443aef968eSAugusto Noronha 1453aef968eSAugusto Noronha /// Validate that the options passed make sense. 1462fe83274SKazu Hirata static std::optional<llvm::Error> validate(); 1473aef968eSAugusto Noronha 1483aef968eSAugusto Noronha /// Transforms the selected mangling preference into a Mangled::NamePreference 1493aef968eSAugusto Noronha static Mangled::NamePreference getNamePreference(); 1503aef968eSAugusto Noronha 1513aef968eSAugusto Noronha static int handleSymtabCommand(Debugger &Dbg); 1523aef968eSAugusto Noronha } // namespace symtab 1533aef968eSAugusto Noronha 154a6d5464cSZachary Turner namespace symbols { 1551cf23e1aSPavel Labath static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"), 1561cf23e1aSPavel Labath cl::Required, cl::sub(SymbolsSubcommand)); 1571cf23e1aSPavel Labath 1581cf23e1aSPavel Labath static cl::opt<std::string> 1591cf23e1aSPavel Labath SymbolPath("symbol-file", 1601cf23e1aSPavel Labath cl::desc("The file from which to fetch symbol information."), 1611cf23e1aSPavel Labath cl::value_desc("file"), cl::sub(SymbolsSubcommand)); 1621cf23e1aSPavel Labath 16390b0a534SPavel Labath enum class FindType { 16490b0a534SPavel Labath None, 16590b0a534SPavel Labath Function, 166398f81b3SAleksandr Urakov Block, 16790b0a534SPavel Labath Namespace, 16890b0a534SPavel Labath Type, 16990b0a534SPavel Labath Variable, 17090b0a534SPavel Labath }; 17190b0a534SPavel Labath static cl::opt<FindType> Find( 17290b0a534SPavel Labath "find", cl::desc("Choose search type:"), 17390b0a534SPavel Labath cl::values( 1749ea80d25SPavel Labath clEnumValN(FindType::None, "none", "No search, just dump the module."), 17590b0a534SPavel Labath clEnumValN(FindType::Function, "function", "Find functions."), 176398f81b3SAleksandr Urakov clEnumValN(FindType::Block, "block", "Find blocks."), 17790b0a534SPavel Labath clEnumValN(FindType::Namespace, "namespace", "Find namespaces."), 17890b0a534SPavel Labath clEnumValN(FindType::Type, "type", "Find types."), 17990b0a534SPavel Labath clEnumValN(FindType::Variable, "variable", "Find global variables.")), 18090b0a534SPavel Labath cl::sub(SymbolsSubcommand)); 18190b0a534SPavel Labath 18290b0a534SPavel Labath static cl::opt<std::string> Name("name", cl::desc("Name to find."), 18390b0a534SPavel Labath cl::sub(SymbolsSubcommand)); 184*d6b90282SAugusto Noronha static cl::opt<std::string> MangledName( 185*d6b90282SAugusto Noronha "mangled-name", 186*d6b90282SAugusto Noronha cl::desc("Mangled name to find. Only compatible when searching types"), 187*d6b90282SAugusto Noronha cl::sub(SymbolsSubcommand)); 18890b0a534SPavel Labath static cl::opt<bool> 18990b0a534SPavel Labath Regex("regex", 190e9264b74SKazuaki Ishizaki cl::desc("Search using regular expressions (available for variables " 19190b0a534SPavel Labath "and functions only)."), 19290b0a534SPavel Labath cl::sub(SymbolsSubcommand)); 19390b0a534SPavel Labath static cl::opt<std::string> 19490b0a534SPavel Labath Context("context", 19590b0a534SPavel Labath cl::desc("Restrict search to the context of the given variable."), 19690b0a534SPavel Labath cl::value_desc("variable"), cl::sub(SymbolsSubcommand)); 19790b0a534SPavel Labath 198260aa0f0SAdrian Prantl static cl::opt<std::string> CompilerContext( 199260aa0f0SAdrian Prantl "compiler-context", 200260aa0f0SAdrian Prantl cl::desc("Specify a compiler context as \"kind:name,...\"."), 201260aa0f0SAdrian Prantl cl::value_desc("context"), cl::sub(SymbolsSubcommand)); 202260aa0f0SAdrian Prantl 203212950fbSPavel Labath static cl::opt<bool> FindInAnyModule( 204212950fbSPavel Labath "find-in-any-module", 205212950fbSPavel Labath cl::desc("If true, the type will be searched for in all modules. Otherwise " 206212950fbSPavel Labath "the modules must be provided in -compiler-context"), 207212950fbSPavel Labath cl::sub(SymbolsSubcommand)); 208212950fbSPavel Labath 209aa97a89dSAdrian Prantl static cl::opt<std::string> 210aa97a89dSAdrian Prantl Language("language", cl::desc("Specify a language type, like C99."), 211aa97a89dSAdrian Prantl cl::value_desc("language"), cl::sub(SymbolsSubcommand)); 212aa97a89dSAdrian Prantl 21390b0a534SPavel Labath static cl::list<FunctionNameType> FunctionNameFlags( 21490b0a534SPavel Labath "function-flags", cl::desc("Function search flags:"), 21590b0a534SPavel Labath cl::values(clEnumValN(eFunctionNameTypeAuto, "auto", 21690b0a534SPavel Labath "Automatically deduce flags based on name."), 21790b0a534SPavel Labath clEnumValN(eFunctionNameTypeFull, "full", "Full function name."), 21890b0a534SPavel Labath clEnumValN(eFunctionNameTypeBase, "base", "Base name."), 21990b0a534SPavel Labath clEnumValN(eFunctionNameTypeMethod, "method", "Method name."), 22090b0a534SPavel Labath clEnumValN(eFunctionNameTypeSelector, "selector", 22190b0a534SPavel Labath "Selector name.")), 22290b0a534SPavel Labath cl::sub(SymbolsSubcommand)); 22390b0a534SPavel Labath static FunctionNameType getFunctionNameFlags() { 22490b0a534SPavel Labath FunctionNameType Result = FunctionNameType(0); 22590b0a534SPavel Labath for (FunctionNameType Flag : FunctionNameFlags) 22690b0a534SPavel Labath Result = FunctionNameType(Result | Flag); 22790b0a534SPavel Labath return Result; 22890b0a534SPavel Labath } 22990b0a534SPavel Labath 230709426b3SAleksandr Urakov static cl::opt<bool> DumpAST("dump-ast", 231709426b3SAleksandr Urakov cl::desc("Dump AST restored from symbols."), 232709426b3SAleksandr Urakov cl::sub(SymbolsSubcommand)); 233681466f5SAdrian Prantl static cl::opt<bool> DumpClangAST( 234681466f5SAdrian Prantl "dump-clang-ast", 235681466f5SAdrian Prantl cl::desc("Dump clang AST restored from symbols. When used on its own this " 236681466f5SAdrian Prantl "will dump the entire AST of all loaded symbols. When combined " 237681466f5SAdrian Prantl "with -find, it changes the presentation of the search results " 238681466f5SAdrian Prantl "from pretty-printing the types to an AST dump."), 2395f46982bSShafik Yaghmour cl::sub(SymbolsSubcommand)); 240709426b3SAleksandr Urakov 241010edd37SAaron Smith static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."), 242010edd37SAaron Smith cl::sub(SymbolsSubcommand)); 243010edd37SAaron Smith 244e6954cb2SPavel Labath static cl::opt<std::string> File("file", 245e6954cb2SPavel Labath cl::desc("File (compile unit) to search."), 246e6954cb2SPavel Labath cl::sub(SymbolsSubcommand)); 2479ea80d25SPavel Labath static cl::opt<int> Line("line", cl::desc("Line to search."), 2489ea80d25SPavel Labath cl::sub(SymbolsSubcommand)); 249e6954cb2SPavel Labath 250465eae36SPavel Labath static Expected<CompilerDeclContext> getDeclContext(SymbolFile &Symfile); 25190b0a534SPavel Labath 25290b0a534SPavel Labath static Error findFunctions(lldb_private::Module &Module); 253398f81b3SAleksandr Urakov static Error findBlocks(lldb_private::Module &Module); 25490b0a534SPavel Labath static Error findNamespaces(lldb_private::Module &Module); 25590b0a534SPavel Labath static Error findTypes(lldb_private::Module &Module); 25690b0a534SPavel Labath static Error findVariables(lldb_private::Module &Module); 25790b0a534SPavel Labath static Error dumpModule(lldb_private::Module &Module); 258709426b3SAleksandr Urakov static Error dumpAST(lldb_private::Module &Module); 259681466f5SAdrian Prantl static Error dumpEntireClangAST(lldb_private::Module &Module); 260010edd37SAaron Smith static Error verify(lldb_private::Module &Module); 26190b0a534SPavel Labath 26238d9ff7aSPavel Labath static Expected<Error (*)(lldb_private::Module &)> getAction(); 26390b0a534SPavel Labath static int dumpSymbols(Debugger &Dbg); 2649ea80d25SPavel Labath } // namespace symbols 265c1cd8262SVedant Kumar 266c1cd8262SVedant Kumar namespace irmemorymap { 267c1cd8262SVedant Kumar static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"), 268c1cd8262SVedant Kumar cl::Required, 269c1cd8262SVedant Kumar cl::sub(IRMemoryMapSubcommand)); 270c1cd8262SVedant Kumar static cl::opt<std::string> CommandFile(cl::Positional, 271c1cd8262SVedant Kumar cl::desc("<command-file>"), 272c1cd8262SVedant Kumar cl::init("-"), 273c1cd8262SVedant Kumar cl::sub(IRMemoryMapSubcommand)); 274f616b9dbSVedant Kumar static cl::opt<bool> UseHostOnlyAllocationPolicy( 275f616b9dbSVedant Kumar "host-only", cl::desc("Use the host-only allocation policy"), 276f616b9dbSVedant Kumar cl::init(false), cl::sub(IRMemoryMapSubcommand)); 277f616b9dbSVedant Kumar 278c1cd8262SVedant Kumar using AllocationT = std::pair<addr_t, addr_t>; 279c1cd8262SVedant Kumar using AddrIntervalMap = 280cc5a6163SVedant Kumar IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>; 281c418b5ccSVedant Kumar 282c418b5ccSVedant Kumar struct IRMemoryMapTestState { 283c418b5ccSVedant Kumar TargetSP Target; 284c418b5ccSVedant Kumar IRMemoryMap Map; 285c418b5ccSVedant Kumar 286c418b5ccSVedant Kumar AddrIntervalMap::Allocator IntervalMapAllocator; 287c418b5ccSVedant Kumar AddrIntervalMap Allocations; 288c418b5ccSVedant Kumar 289c418b5ccSVedant Kumar StringMap<addr_t> Label2AddrMap; 290c418b5ccSVedant Kumar 291c418b5ccSVedant Kumar IRMemoryMapTestState(TargetSP Target) 292c418b5ccSVedant Kumar : Target(Target), Map(Target), Allocations(IntervalMapAllocator) {} 293c418b5ccSVedant Kumar }; 294c418b5ccSVedant Kumar 295c418b5ccSVedant Kumar bool evalMalloc(StringRef Line, IRMemoryMapTestState &State); 296c418b5ccSVedant Kumar bool evalFree(StringRef Line, IRMemoryMapTestState &State); 297c1cd8262SVedant Kumar int evaluateMemoryMapCommands(Debugger &Dbg); 298c1cd8262SVedant Kumar } // namespace irmemorymap 299c1cd8262SVedant Kumar 300e089b5e9SJonas Devlieghere namespace assert { 301e089b5e9SJonas Devlieghere int lldb_assert(Debugger &Dbg); 302e089b5e9SJonas Devlieghere } // namespace assert 303888a4282SZachary Turner } // namespace opts 304888a4282SZachary Turner 305dd958779SGreg Clayton llvm::SmallVector<CompilerContext, 4> parseCompilerContext() { 306dd958779SGreg Clayton llvm::SmallVector<CompilerContext, 4> result; 307260aa0f0SAdrian Prantl if (opts::symbols::CompilerContext.empty()) 308260aa0f0SAdrian Prantl return result; 309260aa0f0SAdrian Prantl 310260aa0f0SAdrian Prantl StringRef str{opts::symbols::CompilerContext}; 311260aa0f0SAdrian Prantl SmallVector<StringRef, 8> entries_str; 312260aa0f0SAdrian Prantl str.split(entries_str, ',', /*maxSplit*/-1, /*keepEmpty=*/false); 313260aa0f0SAdrian Prantl for (auto entry_str : entries_str) { 314260aa0f0SAdrian Prantl StringRef key, value; 315260aa0f0SAdrian Prantl std::tie(key, value) = entry_str.split(':'); 316260aa0f0SAdrian Prantl auto kind = 317260aa0f0SAdrian Prantl StringSwitch<CompilerContextKind>(key) 318260aa0f0SAdrian Prantl .Case("TranslationUnit", CompilerContextKind::TranslationUnit) 319260aa0f0SAdrian Prantl .Case("Module", CompilerContextKind::Module) 320260aa0f0SAdrian Prantl .Case("Namespace", CompilerContextKind::Namespace) 321599ca716SPavel Labath .Case("ClassOrStruct", CompilerContextKind::ClassOrStruct) 322260aa0f0SAdrian Prantl .Case("Union", CompilerContextKind::Union) 323260aa0f0SAdrian Prantl .Case("Function", CompilerContextKind::Function) 324260aa0f0SAdrian Prantl .Case("Variable", CompilerContextKind::Variable) 325330ae19aSAdrian Prantl .Case("Enum", CompilerContextKind::Enum) 326260aa0f0SAdrian Prantl .Case("Typedef", CompilerContextKind::Typedef) 327330ae19aSAdrian Prantl .Case("AnyType", CompilerContextKind::AnyType) 328260aa0f0SAdrian Prantl .Default(CompilerContextKind::Invalid); 329260aa0f0SAdrian Prantl if (value.empty()) { 330260aa0f0SAdrian Prantl WithColor::error() << "compiler context entry has no \"name\"\n"; 331260aa0f0SAdrian Prantl exit(1); 332260aa0f0SAdrian Prantl } 333260aa0f0SAdrian Prantl result.push_back({kind, ConstString{value}}); 334260aa0f0SAdrian Prantl } 33549504674SAdrian Prantl outs() << "Search context: {"; 33649504674SAdrian Prantl lldb_private::StreamString s; 33749504674SAdrian Prantl llvm::interleaveComma(result, s, [&](auto &ctx) { ctx.Dump(s); }); 33849504674SAdrian Prantl outs() << s.GetString().str() << "}\n"; 339260aa0f0SAdrian Prantl 340260aa0f0SAdrian Prantl return result; 341260aa0f0SAdrian Prantl } 342260aa0f0SAdrian Prantl 343e6954cb2SPavel Labath template <typename... Args> 344e6954cb2SPavel Labath static Error make_string_error(const char *Format, Args &&... args) { 345e6954cb2SPavel Labath return llvm::make_error<llvm::StringError>( 346e6954cb2SPavel Labath llvm::formatv(Format, std::forward<Args>(args)...).str(), 347e6954cb2SPavel Labath llvm::inconvertibleErrorCode()); 348e6954cb2SPavel Labath } 349e6954cb2SPavel Labath 350c1cd8262SVedant Kumar TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) { 351c1cd8262SVedant Kumar TargetSP Target; 352f9a07e9fSJonas Devlieghere Status ST = Dbg.GetTargetList().CreateTarget( 353f9a07e9fSJonas Devlieghere Dbg, Filename, /*triple*/ "", eLoadDependentsNo, 354c1cd8262SVedant Kumar /*platform_options*/ nullptr, Target); 355c1cd8262SVedant Kumar if (ST.Fail()) { 356c1cd8262SVedant Kumar errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST); 357c1cd8262SVedant Kumar exit(1); 358c1cd8262SVedant Kumar } 359c1cd8262SVedant Kumar return Target; 360c1cd8262SVedant Kumar } 361c1cd8262SVedant Kumar 362c1cd8262SVedant Kumar std::unique_ptr<MemoryBuffer> opts::openFile(const std::string &Filename) { 363c1cd8262SVedant Kumar auto MB = MemoryBuffer::getFileOrSTDIN(Filename); 364c1cd8262SVedant Kumar if (!MB) { 365c1cd8262SVedant Kumar errs() << formatv("Could not open file '{0}: {1}\n", Filename, 366c1cd8262SVedant Kumar MB.getError().message()); 367c1cd8262SVedant Kumar exit(1); 368c1cd8262SVedant Kumar } 369c1cd8262SVedant Kumar return std::move(*MB); 370c1cd8262SVedant Kumar } 371c1cd8262SVedant Kumar 3727c94582fSPavel Labath void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) { 3737c94582fSPavel Labath P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize())); 3747c94582fSPavel Labath if (List.GetSize() > 0) 3757c94582fSPavel Labath P.formatLine("At least one breakpoint."); 3767c94582fSPavel Labath for (size_t i = 0, e = List.GetSize(); i < e; ++i) { 3777c94582fSPavel Labath BreakpointSP BP = List.GetBreakpointAtIndex(i); 3787c94582fSPavel Labath P.formatLine("Breakpoint ID {0}:", BP->GetID()); 3797c94582fSPavel Labath AutoIndent Indent(P, 2); 3807c94582fSPavel Labath P.formatLine("{0} location{1}.", BP->GetNumLocations(), 3817c94582fSPavel Labath plural(BP->GetNumLocations())); 3827c94582fSPavel Labath if (BP->GetNumLocations() > 0) 3837c94582fSPavel Labath P.formatLine("At least one location."); 3847c94582fSPavel Labath P.formatLine("{0} resolved location{1}.", BP->GetNumResolvedLocations(), 3857c94582fSPavel Labath plural(BP->GetNumResolvedLocations())); 3867c94582fSPavel Labath if (BP->GetNumResolvedLocations() > 0) 3877c94582fSPavel Labath P.formatLine("At least one resolved location."); 3887c94582fSPavel Labath for (size_t l = 0, le = BP->GetNumLocations(); l < le; ++l) { 3897c94582fSPavel Labath BreakpointLocationSP Loc = BP->GetLocationAtIndex(l); 3907c94582fSPavel Labath P.formatLine("Location ID {0}:", Loc->GetID()); 3917c94582fSPavel Labath AutoIndent Indent(P, 2); 3927c94582fSPavel Labath P.formatLine("Enabled: {0}", Loc->IsEnabled()); 3937c94582fSPavel Labath P.formatLine("Resolved: {0}", Loc->IsResolved()); 39408581263SJim Ingham SymbolContext sc; 39508581263SJim Ingham Loc->GetAddress().CalculateSymbolContext(&sc); 39608581263SJim Ingham lldb_private::StreamString S; 39708581263SJim Ingham sc.DumpStopContext(&S, BP->GetTarget().GetProcessSP().get(), 39808581263SJim Ingham Loc->GetAddress(), false, true, false, true, true); 39908581263SJim Ingham P.formatLine("Address: {0}", S.GetString()); 4007c94582fSPavel Labath } 4017c94582fSPavel Labath } 4027c94582fSPavel Labath P.NewLine(); 4037c94582fSPavel Labath } 4047c94582fSPavel Labath 4057c94582fSPavel Labath std::string opts::breakpoint::substitute(StringRef Cmd) { 4067c94582fSPavel Labath std::string Result; 4077c94582fSPavel Labath raw_string_ostream OS(Result); 4087c94582fSPavel Labath while (!Cmd.empty()) { 4097c94582fSPavel Labath switch (Cmd[0]) { 4107c94582fSPavel Labath case '%': 4117c94582fSPavel Labath if (Cmd.consume_front("%p") && (Cmd.empty() || !isalnum(Cmd[0]))) { 412c1cd8262SVedant Kumar OS << sys::path::parent_path(breakpoint::CommandFile); 4137c94582fSPavel Labath break; 4147c94582fSPavel Labath } 41559d2495fSFangrui Song [[fallthrough]]; 4167c94582fSPavel Labath default: 4177c94582fSPavel Labath size_t pos = Cmd.find('%'); 4187c94582fSPavel Labath OS << Cmd.substr(0, pos); 4197c94582fSPavel Labath Cmd = Cmd.substr(pos); 4207c94582fSPavel Labath break; 4217c94582fSPavel Labath } 4227c94582fSPavel Labath } 423d7796855SYoungsuk Kim return Result; 4247c94582fSPavel Labath } 4257c94582fSPavel Labath 42690b0a534SPavel Labath int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) { 427c1cd8262SVedant Kumar TargetSP Target = opts::createTarget(Dbg, breakpoint::Target); 428c1cd8262SVedant Kumar std::unique_ptr<MemoryBuffer> MB = opts::openFile(breakpoint::CommandFile); 4297c94582fSPavel Labath 4307c94582fSPavel Labath LinePrinter P(4, outs()); 431c1cd8262SVedant Kumar StringRef Rest = MB->getBuffer(); 43290b0a534SPavel Labath int HadErrors = 0; 4337c94582fSPavel Labath while (!Rest.empty()) { 4347c94582fSPavel Labath StringRef Line; 4357c94582fSPavel Labath std::tie(Line, Rest) = Rest.split('\n'); 4364447d15aSAdrian McCarthy Line = Line.ltrim().rtrim(); 4377c94582fSPavel Labath if (Line.empty() || Line[0] == '#') 4387c94582fSPavel Labath continue; 4397c94582fSPavel Labath 4407c94582fSPavel Labath if (!Persistent) 4417c94582fSPavel Labath Target->RemoveAllBreakpoints(/*internal_also*/ true); 4427c94582fSPavel Labath 4437c94582fSPavel Labath std::string Command = substitute(Line); 4447c94582fSPavel Labath P.formatLine("Command: {0}", Command); 445de019b88SJonas Devlieghere CommandReturnObject Result(/*colors*/ false); 4467c94582fSPavel Labath if (!Dbg.GetCommandInterpreter().HandleCommand( 4477c94582fSPavel Labath Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) { 448c2750807SAdrian Prantl P.formatLine("Failed: {0}", Result.GetErrorString()); 44990b0a534SPavel Labath HadErrors = 1; 4507c94582fSPavel Labath continue; 4517c94582fSPavel Labath } 4527c94582fSPavel Labath 4537c94582fSPavel Labath dumpState(Target->GetBreakpointList(/*internal*/ false), P); 4547c94582fSPavel Labath } 45590b0a534SPavel Labath return HadErrors; 4567c94582fSPavel Labath } 4577c94582fSPavel Labath 45890b0a534SPavel Labath Expected<CompilerDeclContext> 459465eae36SPavel Labath opts::symbols::getDeclContext(SymbolFile &Symfile) { 46090b0a534SPavel Labath if (Context.empty()) 46190b0a534SPavel Labath return CompilerDeclContext(); 46290b0a534SPavel Labath VariableList List; 463f9568a95SRaphael Isemann Symfile.FindGlobalVariables(ConstString(Context), CompilerDeclContext(), 464f9568a95SRaphael Isemann UINT32_MAX, List); 465e6954cb2SPavel Labath if (List.Empty()) 466e6954cb2SPavel Labath return make_string_error("Context search didn't find a match."); 467e6954cb2SPavel Labath if (List.GetSize() > 1) 468e6954cb2SPavel Labath return make_string_error("Context search found multiple matches."); 46990b0a534SPavel Labath return List.GetVariableAtIndex(0)->GetDeclContext(); 47090b0a534SPavel Labath } 47190b0a534SPavel Labath 472681466f5SAdrian Prantl static lldb::DescriptionLevel GetDescriptionLevel() { 473681466f5SAdrian Prantl return opts::symbols::DumpClangAST ? eDescriptionLevelVerbose : eDescriptionLevelFull; 474681466f5SAdrian Prantl } 475681466f5SAdrian Prantl 47690b0a534SPavel Labath Error opts::symbols::findFunctions(lldb_private::Module &Module) { 477*d6b90282SAugusto Noronha if (!MangledName.empty()) 478*d6b90282SAugusto Noronha return make_string_error("Cannot search functions by mangled name."); 479*d6b90282SAugusto Noronha 480465eae36SPavel Labath SymbolFile &Symfile = *Module.GetSymbolFile(); 48190b0a534SPavel Labath SymbolContextList List; 482fa928458SAdrian Prantl auto compiler_context = parseCompilerContext(); 4839ea80d25SPavel Labath if (!File.empty()) { 4849ea80d25SPavel Labath assert(Line != 0); 4859ea80d25SPavel Labath 4868f3be7a3SJonas Devlieghere FileSpec src_file(File); 4879ea80d25SPavel Labath size_t cu_count = Module.GetNumCompileUnits(); 4889ea80d25SPavel Labath for (size_t i = 0; i < cu_count; i++) { 4899ea80d25SPavel Labath lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i); 4909ea80d25SPavel Labath if (!cu_sp) 4919ea80d25SPavel Labath continue; 4929ea80d25SPavel Labath 4939ea80d25SPavel Labath LineEntry le; 4949ea80d25SPavel Labath cu_sp->FindLineEntry(0, Line, &src_file, false, &le); 4959ea80d25SPavel Labath if (!le.IsValid()) 4969ea80d25SPavel Labath continue; 4978a777920SGreg Clayton const bool include_inlined_functions = false; 4988a777920SGreg Clayton auto addr = 4998a777920SGreg Clayton le.GetSameLineContiguousAddressRange(include_inlined_functions) 5008a777920SGreg Clayton .GetBaseAddress(); 5019ea80d25SPavel Labath if (!addr.IsValid()) 5029ea80d25SPavel Labath continue; 5039ea80d25SPavel Labath 5049ea80d25SPavel Labath SymbolContext sc; 5059ea80d25SPavel Labath uint32_t resolved = 5069ea80d25SPavel Labath addr.CalculateSymbolContext(&sc, eSymbolContextFunction); 5079ea80d25SPavel Labath if (resolved & eSymbolContextFunction) 5089ea80d25SPavel Labath List.Append(sc); 5099ea80d25SPavel Labath } 5109ea80d25SPavel Labath } else if (Regex) { 51190b0a534SPavel Labath RegularExpression RE(Name); 51290b0a534SPavel Labath assert(RE.IsValid()); 5131ad655e2SAdrian Prantl List.Clear(); 5141ad655e2SAdrian Prantl Symfile.FindFunctions(RE, true, List); 515fa928458SAdrian Prantl } else if (!compiler_context.empty()) { 516fa928458SAdrian Prantl List.Clear(); 517fa928458SAdrian Prantl Module.FindFunctions(compiler_context, getFunctionNameFlags(), {}, List); 51890b0a534SPavel Labath } else { 519465eae36SPavel Labath Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile); 52090b0a534SPavel Labath if (!ContextOr) 52190b0a534SPavel Labath return ContextOr.takeError(); 522f9568a95SRaphael Isemann const CompilerDeclContext &ContextPtr = 523f9568a95SRaphael Isemann ContextOr->IsValid() ? *ContextOr : CompilerDeclContext(); 52490b0a534SPavel Labath 5251ad655e2SAdrian Prantl List.Clear(); 52608ce1473SDavid Spickett lldb_private::Module::LookupInfo lookup_info( 52708ce1473SDavid Spickett ConstString(Name), getFunctionNameFlags(), eLanguageTypeUnknown); 5281d2a62afSAlex Langford Symfile.FindFunctions(lookup_info, ContextPtr, true, List); 52990b0a534SPavel Labath } 53090b0a534SPavel Labath outs() << formatv("Found {0} functions:\n", List.GetSize()); 53190b0a534SPavel Labath StreamString Stream; 53290b0a534SPavel Labath List.Dump(&Stream, nullptr); 53390b0a534SPavel Labath outs() << Stream.GetData() << "\n"; 53490b0a534SPavel Labath return Error::success(); 53590b0a534SPavel Labath } 53690b0a534SPavel Labath 537398f81b3SAleksandr Urakov Error opts::symbols::findBlocks(lldb_private::Module &Module) { 538398f81b3SAleksandr Urakov assert(!Regex); 539398f81b3SAleksandr Urakov assert(!File.empty()); 540398f81b3SAleksandr Urakov assert(Line != 0); 541*d6b90282SAugusto Noronha if (!MangledName.empty()) 542*d6b90282SAugusto Noronha return make_string_error("Cannot search blocks by mangled name."); 543398f81b3SAleksandr Urakov 544398f81b3SAleksandr Urakov SymbolContextList List; 545398f81b3SAleksandr Urakov 5468f3be7a3SJonas Devlieghere FileSpec src_file(File); 547398f81b3SAleksandr Urakov size_t cu_count = Module.GetNumCompileUnits(); 548398f81b3SAleksandr Urakov for (size_t i = 0; i < cu_count; i++) { 549398f81b3SAleksandr Urakov lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i); 550398f81b3SAleksandr Urakov if (!cu_sp) 551398f81b3SAleksandr Urakov continue; 552398f81b3SAleksandr Urakov 553398f81b3SAleksandr Urakov LineEntry le; 554398f81b3SAleksandr Urakov cu_sp->FindLineEntry(0, Line, &src_file, false, &le); 555398f81b3SAleksandr Urakov if (!le.IsValid()) 556398f81b3SAleksandr Urakov continue; 5578a777920SGreg Clayton const bool include_inlined_functions = false; 5588a777920SGreg Clayton auto addr = le.GetSameLineContiguousAddressRange(include_inlined_functions) 5598a777920SGreg Clayton .GetBaseAddress(); 560398f81b3SAleksandr Urakov if (!addr.IsValid()) 561398f81b3SAleksandr Urakov continue; 562398f81b3SAleksandr Urakov 563398f81b3SAleksandr Urakov SymbolContext sc; 564398f81b3SAleksandr Urakov uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock); 565398f81b3SAleksandr Urakov if (resolved & eSymbolContextBlock) 566398f81b3SAleksandr Urakov List.Append(sc); 567398f81b3SAleksandr Urakov } 568398f81b3SAleksandr Urakov 569398f81b3SAleksandr Urakov outs() << formatv("Found {0} blocks:\n", List.GetSize()); 570398f81b3SAleksandr Urakov StreamString Stream; 571398f81b3SAleksandr Urakov List.Dump(&Stream, nullptr); 572398f81b3SAleksandr Urakov outs() << Stream.GetData() << "\n"; 573398f81b3SAleksandr Urakov return Error::success(); 574398f81b3SAleksandr Urakov } 575398f81b3SAleksandr Urakov 57690b0a534SPavel Labath Error opts::symbols::findNamespaces(lldb_private::Module &Module) { 577*d6b90282SAugusto Noronha if (!MangledName.empty()) 578*d6b90282SAugusto Noronha return make_string_error("Cannot search namespaces by mangled name."); 579*d6b90282SAugusto Noronha 580465eae36SPavel Labath SymbolFile &Symfile = *Module.GetSymbolFile(); 581465eae36SPavel Labath Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile); 58290b0a534SPavel Labath if (!ContextOr) 58390b0a534SPavel Labath return ContextOr.takeError(); 584f9568a95SRaphael Isemann const CompilerDeclContext &ContextPtr = 585f9568a95SRaphael Isemann ContextOr->IsValid() ? *ContextOr : CompilerDeclContext(); 58690b0a534SPavel Labath 58790b0a534SPavel Labath CompilerDeclContext Result = 588465eae36SPavel Labath Symfile.FindNamespace(ConstString(Name), ContextPtr); 58990b0a534SPavel Labath if (Result) 59090b0a534SPavel Labath outs() << "Found namespace: " 59190b0a534SPavel Labath << Result.GetScopeQualifiedName().GetStringRef() << "\n"; 59290b0a534SPavel Labath else 59390b0a534SPavel Labath outs() << "Namespace not found.\n"; 59490b0a534SPavel Labath return Error::success(); 59590b0a534SPavel Labath } 59690b0a534SPavel Labath 59790b0a534SPavel Labath Error opts::symbols::findTypes(lldb_private::Module &Module) { 598465eae36SPavel Labath SymbolFile &Symfile = *Module.GetSymbolFile(); 599465eae36SPavel Labath Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile); 60090b0a534SPavel Labath if (!ContextOr) 60190b0a534SPavel Labath return ContextOr.takeError(); 602*d6b90282SAugusto Noronha ; 60390b0a534SPavel Labath 604212950fbSPavel Labath TypeQueryOptions Opts = TypeQueryOptions::e_module_search; 605212950fbSPavel Labath if (FindInAnyModule) 606212950fbSPavel Labath Opts |= TypeQueryOptions::e_ignore_modules; 607dd958779SGreg Clayton TypeResults results; 608*d6b90282SAugusto Noronha if (!Name.empty() && !MangledName.empty()) 609*d6b90282SAugusto Noronha return make_string_error("Cannot search by both name and mangled name."); 610*d6b90282SAugusto Noronha 611dd958779SGreg Clayton if (!Name.empty()) { 612dd958779SGreg Clayton if (ContextOr->IsValid()) { 613212950fbSPavel Labath TypeQuery query(*ContextOr, ConstString(Name), Opts); 614aa97a89dSAdrian Prantl if (!Language.empty()) 615dd958779SGreg Clayton query.AddLanguage(Language::GetLanguageTypeFromString(Language)); 616dd958779SGreg Clayton Symfile.FindTypes(query, results); 617dd958779SGreg Clayton } else { 618dd958779SGreg Clayton TypeQuery query(Name); 619dd958779SGreg Clayton if (!Language.empty()) 620dd958779SGreg Clayton query.AddLanguage(Language::GetLanguageTypeFromString(Language)); 621dd958779SGreg Clayton Symfile.FindTypes(query, results); 622dd958779SGreg Clayton } 623*d6b90282SAugusto Noronha } else if (!MangledName.empty()) { 624*d6b90282SAugusto Noronha Opts = TypeQueryOptions::e_search_by_mangled_name; 625*d6b90282SAugusto Noronha if (ContextOr->IsValid()) { 626*d6b90282SAugusto Noronha TypeQuery query(*ContextOr, ConstString(MangledName), Opts); 627*d6b90282SAugusto Noronha if (!Language.empty()) 628*d6b90282SAugusto Noronha query.AddLanguage(Language::GetLanguageTypeFromString(Language)); 629*d6b90282SAugusto Noronha Symfile.FindTypes(query, results); 630*d6b90282SAugusto Noronha } else { 631*d6b90282SAugusto Noronha TypeQuery query(MangledName, Opts); 632*d6b90282SAugusto Noronha if (!Language.empty()) 633*d6b90282SAugusto Noronha query.AddLanguage(Language::GetLanguageTypeFromString(Language)); 634*d6b90282SAugusto Noronha Symfile.FindTypes(query, results); 635*d6b90282SAugusto Noronha } 636*d6b90282SAugusto Noronha 637dd958779SGreg Clayton } else { 638212950fbSPavel Labath TypeQuery query(parseCompilerContext(), Opts); 639dd958779SGreg Clayton if (!Language.empty()) 640dd958779SGreg Clayton query.AddLanguage(Language::GetLanguageTypeFromString(Language)); 641dd958779SGreg Clayton Symfile.FindTypes(query, results); 642dd958779SGreg Clayton } 643dd958779SGreg Clayton outs() << formatv("Found {0} types:\n", results.GetTypeMap().GetSize()); 64490b0a534SPavel Labath StreamString Stream; 645681466f5SAdrian Prantl // Resolve types to force-materialize typedef types. 646dd958779SGreg Clayton for (const auto &type_sp : results.GetTypeMap().Types()) 647dd958779SGreg Clayton type_sp->GetFullCompilerType(); 648dd958779SGreg Clayton results.GetTypeMap().Dump(&Stream, false, GetDescriptionLevel()); 64990b0a534SPavel Labath outs() << Stream.GetData() << "\n"; 65090b0a534SPavel Labath return Error::success(); 65190b0a534SPavel Labath } 65290b0a534SPavel Labath 65390b0a534SPavel Labath Error opts::symbols::findVariables(lldb_private::Module &Module) { 654*d6b90282SAugusto Noronha if (!MangledName.empty()) 655*d6b90282SAugusto Noronha return make_string_error("Cannot search variables by mangled name."); 656*d6b90282SAugusto Noronha 657465eae36SPavel Labath SymbolFile &Symfile = *Module.GetSymbolFile(); 65890b0a534SPavel Labath VariableList List; 65990b0a534SPavel Labath if (Regex) { 66090b0a534SPavel Labath RegularExpression RE(Name); 66190b0a534SPavel Labath assert(RE.IsValid()); 662465eae36SPavel Labath Symfile.FindGlobalVariables(RE, UINT32_MAX, List); 663e6954cb2SPavel Labath } else if (!File.empty()) { 664e6954cb2SPavel Labath CompUnitSP CU; 665e6954cb2SPavel Labath for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) { 666e6954cb2SPavel Labath CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind); 66738870af8SPavel Labath if (!Candidate || 66838870af8SPavel Labath Candidate->GetPrimaryFile().GetFilename().GetStringRef() != File) 669e6954cb2SPavel Labath continue; 670e6954cb2SPavel Labath if (CU) 671e6954cb2SPavel Labath return make_string_error("Multiple compile units for file `{0}` found.", 672e6954cb2SPavel Labath File); 673e6954cb2SPavel Labath CU = std::move(Candidate); 674e6954cb2SPavel Labath } 675e6954cb2SPavel Labath 676e6954cb2SPavel Labath if (!CU) 677e6954cb2SPavel Labath return make_string_error("Compile unit `{0}` not found.", File); 678e6954cb2SPavel Labath 679e6954cb2SPavel Labath List.AddVariables(CU->GetVariableList(true).get()); 68090b0a534SPavel Labath } else { 681465eae36SPavel Labath Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile); 68290b0a534SPavel Labath if (!ContextOr) 68390b0a534SPavel Labath return ContextOr.takeError(); 684f9568a95SRaphael Isemann const CompilerDeclContext &ContextPtr = 685f9568a95SRaphael Isemann ContextOr->IsValid() ? *ContextOr : CompilerDeclContext(); 68690b0a534SPavel Labath 687465eae36SPavel Labath Symfile.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List); 68890b0a534SPavel Labath } 68990b0a534SPavel Labath outs() << formatv("Found {0} variables:\n", List.GetSize()); 69090b0a534SPavel Labath StreamString Stream; 69190b0a534SPavel Labath List.Dump(&Stream, false); 69290b0a534SPavel Labath outs() << Stream.GetData() << "\n"; 69390b0a534SPavel Labath return Error::success(); 69490b0a534SPavel Labath } 69590b0a534SPavel Labath 69690b0a534SPavel Labath Error opts::symbols::dumpModule(lldb_private::Module &Module) { 69790b0a534SPavel Labath StreamString Stream; 69890b0a534SPavel Labath Module.ParseAllDebugSymbols(); 69990b0a534SPavel Labath Module.Dump(&Stream); 70090b0a534SPavel Labath outs() << Stream.GetData() << "\n"; 70190b0a534SPavel Labath return Error::success(); 70290b0a534SPavel Labath } 70390b0a534SPavel Labath 704709426b3SAleksandr Urakov Error opts::symbols::dumpAST(lldb_private::Module &Module) { 705c68925abSZachary Turner Module.ParseAllDebugSymbols(); 706709426b3SAleksandr Urakov 7075f46982bSShafik Yaghmour SymbolFile *symfile = Module.GetSymbolFile(); 708709426b3SAleksandr Urakov if (!symfile) 709709426b3SAleksandr Urakov return make_string_error("Module has no symbol file."); 710709426b3SAleksandr Urakov 7116eaedbb5SAdrian Prantl auto type_system_or_err = 7120e252e38SAlex Langford symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); 7130e252e38SAlex Langford if (!type_system_or_err) 7146e3b0cc2SRaphael Isemann return make_string_error("Can't retrieve TypeSystemClang"); 7150e252e38SAlex Langford 7166eaedbb5SAdrian Prantl auto ts = *type_system_or_err; 7176eaedbb5SAdrian Prantl auto *clang_ast_ctx = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); 718709426b3SAleksandr Urakov if (!clang_ast_ctx) 7196e3b0cc2SRaphael Isemann return make_string_error("Retrieved TypeSystem was not a TypeSystemClang"); 720709426b3SAleksandr Urakov 721f9f49d35SRaphael Isemann clang::ASTContext &ast_ctx = clang_ast_ctx->getASTContext(); 722709426b3SAleksandr Urakov 723f9f49d35SRaphael Isemann clang::TranslationUnitDecl *tu = ast_ctx.getTranslationUnitDecl(); 724709426b3SAleksandr Urakov if (!tu) 725709426b3SAleksandr Urakov return make_string_error("Can't retrieve translation unit declaration."); 726709426b3SAleksandr Urakov 727709426b3SAleksandr Urakov tu->print(outs()); 728709426b3SAleksandr Urakov 729709426b3SAleksandr Urakov return Error::success(); 730709426b3SAleksandr Urakov } 731709426b3SAleksandr Urakov 732681466f5SAdrian Prantl Error opts::symbols::dumpEntireClangAST(lldb_private::Module &Module) { 7335f46982bSShafik Yaghmour Module.ParseAllDebugSymbols(); 7345f46982bSShafik Yaghmour 7355f46982bSShafik Yaghmour SymbolFile *symfile = Module.GetSymbolFile(); 7365f46982bSShafik Yaghmour if (!symfile) 7375f46982bSShafik Yaghmour return make_string_error("Module has no symbol file."); 7385f46982bSShafik Yaghmour 7396eaedbb5SAdrian Prantl auto type_system_or_err = 740c0eeea5dSAdrian Prantl symfile->GetTypeSystemForLanguage(eLanguageTypeObjC_plus_plus); 7415f46982bSShafik Yaghmour if (!type_system_or_err) 7426e3b0cc2SRaphael Isemann return make_string_error("Can't retrieve TypeSystemClang"); 7436eaedbb5SAdrian Prantl auto ts = *type_system_or_err; 7446eaedbb5SAdrian Prantl auto *clang_ast_ctx = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); 7455f46982bSShafik Yaghmour if (!clang_ast_ctx) 7466e3b0cc2SRaphael Isemann return make_string_error("Retrieved TypeSystem was not a TypeSystemClang"); 7475f46982bSShafik Yaghmour 7485f46982bSShafik Yaghmour StreamString Stream; 7495f46982bSShafik Yaghmour clang_ast_ctx->DumpFromSymbolFile(Stream, Name); 7505f46982bSShafik Yaghmour outs() << Stream.GetData() << "\n"; 7515f46982bSShafik Yaghmour 7525f46982bSShafik Yaghmour return Error::success(); 7535f46982bSShafik Yaghmour } 7545f46982bSShafik Yaghmour 755010edd37SAaron Smith Error opts::symbols::verify(lldb_private::Module &Module) { 756465eae36SPavel Labath SymbolFile *symfile = Module.GetSymbolFile(); 757010edd37SAaron Smith if (!symfile) 758e6954cb2SPavel Labath return make_string_error("Module has no symbol file."); 759010edd37SAaron Smith 760010edd37SAaron Smith uint32_t comp_units_count = symfile->GetNumCompileUnits(); 761010edd37SAaron Smith 762010edd37SAaron Smith outs() << "Found " << comp_units_count << " compile units.\n"; 763010edd37SAaron Smith 764010edd37SAaron Smith for (uint32_t i = 0; i < comp_units_count; i++) { 765e0119909SPavel Labath lldb::CompUnitSP comp_unit = symfile->GetCompileUnitAtIndex(i); 766010edd37SAaron Smith if (!comp_unit) 767e9264b74SKazuaki Ishizaki return make_string_error("Cannot parse compile unit {0}.", i); 768010edd37SAaron Smith 76938870af8SPavel Labath outs() << "Processing '" 77038870af8SPavel Labath << comp_unit->GetPrimaryFile().GetFilename().AsCString() 7719ea80d25SPavel Labath << "' compile unit.\n"; 772010edd37SAaron Smith 773010edd37SAaron Smith LineTable *lt = comp_unit->GetLineTable(); 774010edd37SAaron Smith if (!lt) 775e6954cb2SPavel Labath return make_string_error("Can't get a line table of a compile unit."); 776010edd37SAaron Smith 777010edd37SAaron Smith uint32_t count = lt->GetSize(); 778010edd37SAaron Smith 779010edd37SAaron Smith outs() << "The line table contains " << count << " entries.\n"; 780010edd37SAaron Smith 781010edd37SAaron Smith if (count == 0) 782010edd37SAaron Smith continue; 783010edd37SAaron Smith 784010edd37SAaron Smith LineEntry le; 785010edd37SAaron Smith if (!lt->GetLineEntryAtIndex(0, le)) 786e6954cb2SPavel Labath return make_string_error("Can't get a line entry of a compile unit."); 787010edd37SAaron Smith 788010edd37SAaron Smith for (uint32_t i = 1; i < count; i++) { 789010edd37SAaron Smith lldb::addr_t curr_end = 790010edd37SAaron Smith le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize(); 791010edd37SAaron Smith 792010edd37SAaron Smith if (!lt->GetLineEntryAtIndex(i, le)) 793e6954cb2SPavel Labath return make_string_error("Can't get a line entry of a compile unit"); 794010edd37SAaron Smith 795010edd37SAaron Smith if (curr_end > le.range.GetBaseAddress().GetFileAddress()) 796e6954cb2SPavel Labath return make_string_error( 797e6954cb2SPavel Labath "Line table of a compile unit is inconsistent."); 798010edd37SAaron Smith } 799010edd37SAaron Smith } 800010edd37SAaron Smith 801010edd37SAaron Smith outs() << "The symbol information is verified.\n"; 802010edd37SAaron Smith 803010edd37SAaron Smith return Error::success(); 804010edd37SAaron Smith } 805010edd37SAaron Smith 80638d9ff7aSPavel Labath Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() { 807709426b3SAleksandr Urakov if (Verify && DumpAST) 808709426b3SAleksandr Urakov return make_string_error( 809709426b3SAleksandr Urakov "Cannot both verify symbol information and dump AST."); 810709426b3SAleksandr Urakov 811e6954cb2SPavel Labath if (Verify) { 812e6954cb2SPavel Labath if (Find != FindType::None) 813e6954cb2SPavel Labath return make_string_error( 814e6954cb2SPavel Labath "Cannot both search and verify symbol information."); 8159ea80d25SPavel Labath if (Regex || !Context.empty() || !Name.empty() || !File.empty() || 8169ea80d25SPavel Labath Line != 0) 8179ea80d25SPavel Labath return make_string_error( 8189ea80d25SPavel Labath "-regex, -context, -name, -file and -line options are not " 819e6954cb2SPavel Labath "applicable for symbol verification."); 820e6954cb2SPavel Labath return verify; 82190b0a534SPavel Labath } 82290b0a534SPavel Labath 823709426b3SAleksandr Urakov if (DumpAST) { 824709426b3SAleksandr Urakov if (Find != FindType::None) 825037ed1beSAaron Smith return make_string_error("Cannot both search and dump AST."); 826709426b3SAleksandr Urakov if (Regex || !Context.empty() || !Name.empty() || !File.empty() || 827709426b3SAleksandr Urakov Line != 0) 828709426b3SAleksandr Urakov return make_string_error( 829709426b3SAleksandr Urakov "-regex, -context, -name, -file and -line options are not " 830709426b3SAleksandr Urakov "applicable for dumping AST."); 831709426b3SAleksandr Urakov return dumpAST; 832709426b3SAleksandr Urakov } 833709426b3SAleksandr Urakov 8345f46982bSShafik Yaghmour if (DumpClangAST) { 835681466f5SAdrian Prantl if (Find == FindType::None) { 8365f46982bSShafik Yaghmour if (Regex || !Context.empty() || !File.empty() || Line != 0) 8375f46982bSShafik Yaghmour return make_string_error( 8385f46982bSShafik Yaghmour "-regex, -context, -name, -file and -line options are not " 839681466f5SAdrian Prantl "applicable for dumping the entire clang AST. Either combine with " 840681466f5SAdrian Prantl "-find, or use -dump-clang-ast as a standalone option."); 841681466f5SAdrian Prantl return dumpEntireClangAST; 842681466f5SAdrian Prantl } 843681466f5SAdrian Prantl if (Find != FindType::Type) 844681466f5SAdrian Prantl return make_string_error("This combination of -dump-clang-ast and -find " 845681466f5SAdrian Prantl "<kind> is not yet implemented."); 8465f46982bSShafik Yaghmour } 8475f46982bSShafik Yaghmour 848e6954cb2SPavel Labath if (Regex && !Context.empty()) 849e6954cb2SPavel Labath return make_string_error( 850e6954cb2SPavel Labath "Cannot search using both regular expressions and context."); 851e6954cb2SPavel Labath 852e6954cb2SPavel Labath if (Regex && !RegularExpression(Name).IsValid()) 853e6954cb2SPavel Labath return make_string_error("`{0}` is not a valid regular expression.", Name); 854e6954cb2SPavel Labath 855e6954cb2SPavel Labath if (Regex + !Context.empty() + !File.empty() >= 2) 856e6954cb2SPavel Labath return make_string_error( 857e6954cb2SPavel Labath "Only one of -regex, -context and -file may be used simultaneously."); 858e6954cb2SPavel Labath if (Regex && Name.empty()) 859e6954cb2SPavel Labath return make_string_error("-regex used without a -name"); 860e6954cb2SPavel Labath 861212950fbSPavel Labath if (FindInAnyModule && (Find != FindType::Type)) 862212950fbSPavel Labath return make_string_error("-find-in-any-module only works with -find=type"); 863212950fbSPavel Labath 86490b0a534SPavel Labath switch (Find) { 86590b0a534SPavel Labath case FindType::None: 8669ea80d25SPavel Labath if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0) 867e6954cb2SPavel Labath return make_string_error( 868e6954cb2SPavel Labath "Specify search type (-find) to use search options."); 869e6954cb2SPavel Labath return dumpModule; 870e6954cb2SPavel Labath 871e6954cb2SPavel Labath case FindType::Function: 8729ea80d25SPavel Labath if (!File.empty() + (Line != 0) == 1) 8739ea80d25SPavel Labath return make_string_error("Both file name and line number must be " 8749ea80d25SPavel Labath "specified when searching a function " 8759ea80d25SPavel Labath "by file position."); 8769ea80d25SPavel Labath if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2) 8779ea80d25SPavel Labath return make_string_error("Only one of regular expression, function-flags " 8789ea80d25SPavel Labath "and file position may be used simultaneously " 8799ea80d25SPavel Labath "when searching a function."); 880e6954cb2SPavel Labath return findFunctions; 881e6954cb2SPavel Labath 882398f81b3SAleksandr Urakov case FindType::Block: 883398f81b3SAleksandr Urakov if (File.empty() || Line == 0) 884398f81b3SAleksandr Urakov return make_string_error("Both file name and line number must be " 885398f81b3SAleksandr Urakov "specified when searching a block."); 886398f81b3SAleksandr Urakov if (Regex || getFunctionNameFlags() != 0) 887398f81b3SAleksandr Urakov return make_string_error("Cannot use regular expression or " 888398f81b3SAleksandr Urakov "function-flags for searching a block."); 889398f81b3SAleksandr Urakov return findBlocks; 890398f81b3SAleksandr Urakov 891e6954cb2SPavel Labath case FindType::Namespace: 8929ea80d25SPavel Labath if (Regex || !File.empty() || Line != 0) 893e6954cb2SPavel Labath return make_string_error("Cannot search for namespaces using regular " 8949ea80d25SPavel Labath "expressions, file names or line numbers."); 895e6954cb2SPavel Labath return findNamespaces; 896e6954cb2SPavel Labath 897e6954cb2SPavel Labath case FindType::Type: 8989ea80d25SPavel Labath if (Regex || !File.empty() || Line != 0) 899e6954cb2SPavel Labath return make_string_error("Cannot search for types using regular " 9009ea80d25SPavel Labath "expressions, file names or line numbers."); 901260aa0f0SAdrian Prantl if (!Name.empty() && !CompilerContext.empty()) 902260aa0f0SAdrian Prantl return make_string_error("Name is ignored if compiler context present."); 903260aa0f0SAdrian Prantl 904e6954cb2SPavel Labath return findTypes; 905e6954cb2SPavel Labath 906e6954cb2SPavel Labath case FindType::Variable: 9079ea80d25SPavel Labath if (Line != 0) 9089ea80d25SPavel Labath return make_string_error("Cannot search for variables " 9099ea80d25SPavel Labath "using line numbers."); 910e6954cb2SPavel Labath return findVariables; 91190b0a534SPavel Labath } 912709426b3SAleksandr Urakov 913709426b3SAleksandr Urakov llvm_unreachable("Unsupported symbol action."); 914e6954cb2SPavel Labath } 915e6954cb2SPavel Labath 9162fe83274SKazu Hirata std::optional<llvm::Error> opts::symtab::validate() { 9173aef968eSAugusto Noronha if (ManglingPreference != ManglingPreference::None && 9183aef968eSAugusto Noronha FindSymbolsByRegex.empty()) 9193aef968eSAugusto Noronha return make_string_error("Mangling preference set but no regex specified."); 9203aef968eSAugusto Noronha 9213aef968eSAugusto Noronha return {}; 9223aef968eSAugusto Noronha } 9233aef968eSAugusto Noronha 9243aef968eSAugusto Noronha static Mangled::NamePreference opts::symtab::getNamePreference() { 9253aef968eSAugusto Noronha switch (ManglingPreference) { 9263aef968eSAugusto Noronha case ManglingPreference::None: 9273aef968eSAugusto Noronha case ManglingPreference::Mangled: 9283aef968eSAugusto Noronha return Mangled::ePreferMangled; 9293aef968eSAugusto Noronha case ManglingPreference::Demangled: 9303aef968eSAugusto Noronha return Mangled::ePreferDemangled; 9313aef968eSAugusto Noronha case ManglingPreference::MangledWithoutArguments: 9323aef968eSAugusto Noronha return Mangled::ePreferDemangledWithoutArguments; 9333aef968eSAugusto Noronha } 934a5881e8aSMartin Storsjö llvm_unreachable("Fully covered switch above!"); 9353aef968eSAugusto Noronha } 9363aef968eSAugusto Noronha 9373aef968eSAugusto Noronha int opts::symtab::handleSymtabCommand(Debugger &Dbg) { 9383aef968eSAugusto Noronha if (auto error = validate()) { 939f43886e7SFangrui Song logAllUnhandledErrors(std::move(*error), WithColor::error(), ""); 9403aef968eSAugusto Noronha return 1; 9413aef968eSAugusto Noronha } 9423aef968eSAugusto Noronha 9433aef968eSAugusto Noronha if (!FindSymbolsByRegex.empty()) { 9443aef968eSAugusto Noronha ModuleSpec Spec{FileSpec(InputFile)}; 9453aef968eSAugusto Noronha 9463aef968eSAugusto Noronha auto ModulePtr = std::make_shared<lldb_private::Module>(Spec); 9473aef968eSAugusto Noronha auto *Symtab = ModulePtr->GetSymtab(); 9483aef968eSAugusto Noronha auto NamePreference = getNamePreference(); 9493aef968eSAugusto Noronha std::vector<uint32_t> Indexes; 9503aef968eSAugusto Noronha 9513aef968eSAugusto Noronha Symtab->FindAllSymbolsMatchingRexExAndType( 9523aef968eSAugusto Noronha RegularExpression(FindSymbolsByRegex), lldb::eSymbolTypeAny, 9533aef968eSAugusto Noronha Symtab::eDebugAny, Symtab::eVisibilityAny, Indexes, NamePreference); 9543aef968eSAugusto Noronha for (auto i : Indexes) { 9553aef968eSAugusto Noronha auto *symbol = Symtab->SymbolAtIndex(i); 9563aef968eSAugusto Noronha if (symbol) { 9573aef968eSAugusto Noronha StreamString stream; 9583aef968eSAugusto Noronha symbol->Dump(&stream, nullptr, i, NamePreference); 9593aef968eSAugusto Noronha outs() << stream.GetString(); 9603aef968eSAugusto Noronha } 9613aef968eSAugusto Noronha } 9623aef968eSAugusto Noronha } 9633aef968eSAugusto Noronha 9643aef968eSAugusto Noronha return 0; 9653aef968eSAugusto Noronha } 9663aef968eSAugusto Noronha 967e6954cb2SPavel Labath int opts::symbols::dumpSymbols(Debugger &Dbg) { 968e6954cb2SPavel Labath auto ActionOr = getAction(); 969e6954cb2SPavel Labath if (!ActionOr) { 970e6954cb2SPavel Labath logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), ""); 971e6954cb2SPavel Labath return 1; 972e6954cb2SPavel Labath } 973e6954cb2SPavel Labath auto Action = *ActionOr; 97490b0a534SPavel Labath 9751cf23e1aSPavel Labath outs() << "Module: " << InputFile << "\n"; 9761cf23e1aSPavel Labath ModuleSpec Spec{FileSpec(InputFile)}; 9771cf23e1aSPavel Labath StringRef Symbols = SymbolPath.empty() ? InputFile : SymbolPath; 9781cf23e1aSPavel Labath Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native); 979a6d5464cSZachary Turner 980a6d5464cSZachary Turner auto ModulePtr = std::make_shared<lldb_private::Module>(Spec); 981465eae36SPavel Labath SymbolFile *Symfile = ModulePtr->GetSymbolFile(); 982465eae36SPavel Labath if (!Symfile) { 98390b0a534SPavel Labath WithColor::error() << "Module has no symbol vendor.\n"; 9841cf23e1aSPavel Labath return 1; 985a6d5464cSZachary Turner } 986a6d5464cSZachary Turner 98790b0a534SPavel Labath if (Error E = Action(*ModulePtr)) { 98890b0a534SPavel Labath WithColor::error() << toString(std::move(E)) << "\n"; 9891cf23e1aSPavel Labath return 1; 99090b0a534SPavel Labath } 99190b0a534SPavel Labath 9921cf23e1aSPavel Labath return 0; 99390b0a534SPavel Labath } 99490b0a534SPavel Labath 995280d2e81SPavel Labath static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) { 996280d2e81SPavel Labath size_t Count = List.GetNumSections(0); 997280d2e81SPavel Labath if (Count == 0) { 998280d2e81SPavel Labath Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : ""); 999280d2e81SPavel Labath return; 1000280d2e81SPavel Labath } 1001280d2e81SPavel Labath Printer.formatLine("Showing {0} {1}sections", Count, 1002280d2e81SPavel Labath is_subsection ? "sub" : ""); 1003280d2e81SPavel Labath for (size_t I = 0; I < Count; ++I) { 1004280d2e81SPavel Labath auto S = List.GetSectionAtIndex(I); 1005280d2e81SPavel Labath assert(S); 1006280d2e81SPavel Labath AutoIndent Indent(Printer, 2); 1007280d2e81SPavel Labath Printer.formatLine("Index: {0}", I); 10080d38e4fdSPavel Labath Printer.formatLine("ID: {0:x}", S->GetID()); 1009280d2e81SPavel Labath Printer.formatLine("Name: {0}", S->GetName().GetStringRef()); 1010280d2e81SPavel Labath Printer.formatLine("Type: {0}", S->GetTypeAsCString()); 101162a8254fSPavel Labath Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions())); 1012ef8683abSPavel Labath Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific()); 101362a8254fSPavel Labath Printer.formatLine("VM address: {0:x}", S->GetFileAddress()); 1014280d2e81SPavel Labath Printer.formatLine("VM size: {0}", S->GetByteSize()); 1015280d2e81SPavel Labath Printer.formatLine("File size: {0}", S->GetFileSize()); 1016280d2e81SPavel Labath 1017280d2e81SPavel Labath if (opts::object::SectionContents) { 1018f4af9a9dSJonas Devlieghere lldb_private::DataExtractor Data; 1019280d2e81SPavel Labath S->GetSectionData(Data); 1020ea6b95dcSRaphael Isemann ArrayRef<uint8_t> Bytes(Data.GetDataStart(), Data.GetDataEnd()); 1021280d2e81SPavel Labath Printer.formatBinary("Data: ", Bytes, 0); 1022280d2e81SPavel Labath } 1023280d2e81SPavel Labath 1024280d2e81SPavel Labath if (S->GetType() == eSectionTypeContainer) 1025280d2e81SPavel Labath dumpSectionList(Printer, S->GetChildren(), true); 1026280d2e81SPavel Labath Printer.NewLine(); 1027280d2e81SPavel Labath } 1028280d2e81SPavel Labath } 1029280d2e81SPavel Labath 103062a7f80aSPavel Labath static int dumpObjectFiles(Debugger &Dbg) { 1031888a4282SZachary Turner LinePrinter Printer(4, llvm::outs()); 1032888a4282SZachary Turner 103390b0a534SPavel Labath int HadErrors = 0; 103462a7f80aSPavel Labath for (const auto &File : opts::object::InputFilenames) { 10358f3be7a3SJonas Devlieghere ModuleSpec Spec{FileSpec(File)}; 1036888a4282SZachary Turner 1037a6d5464cSZachary Turner auto ModulePtr = std::make_shared<lldb_private::Module>(Spec); 10381f6b2477SPavel Labath 10391f6b2477SPavel Labath ObjectFile *ObjectPtr = ModulePtr->GetObjectFile(); 10401f6b2477SPavel Labath if (!ObjectPtr) { 10411f6b2477SPavel Labath WithColor::error() << File << " not recognised as an object file\n"; 10421f6b2477SPavel Labath HadErrors = 1; 10431f6b2477SPavel Labath continue; 10441f6b2477SPavel Labath } 10451f6b2477SPavel Labath 104696979ceeSPavel Labath // Fetch symbol vendor before we get the section list to give the symbol 104796979ceeSPavel Labath // vendor a chance to populate it. 1048465eae36SPavel Labath ModulePtr->GetSymbolFile(); 1049888a4282SZachary Turner SectionList *Sections = ModulePtr->GetSectionList(); 1050888a4282SZachary Turner if (!Sections) { 1051888a4282SZachary Turner llvm::errs() << "Could not load sections for module " << File << "\n"; 105290b0a534SPavel Labath HadErrors = 1; 1053888a4282SZachary Turner continue; 1054888a4282SZachary Turner } 1055888a4282SZachary Turner 10561f6b2477SPavel Labath Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName()); 105762a7f80aSPavel Labath Printer.formatLine("Architecture: {0}", 105862a7f80aSPavel Labath ModulePtr->GetArchitecture().GetTriple().getTriple()); 105962a7f80aSPavel Labath Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString()); 10601f6b2477SPavel Labath Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable()); 10611f6b2477SPavel Labath Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped()); 10621f6b2477SPavel Labath Printer.formatLine("Type: {0}", ObjectPtr->GetType()); 10631f6b2477SPavel Labath Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata()); 1064976af43bSPavel Labath Printer.formatLine("Base VM address: {0:x}", 1065976af43bSPavel Labath ObjectPtr->GetBaseAddress().GetFileAddress()); 106662a7f80aSPavel Labath 1067280d2e81SPavel Labath dumpSectionList(Printer, *Sections, /*is_subsection*/ false); 1068037ed1beSAaron Smith 1069037ed1beSAaron Smith if (opts::object::SectionDependentModules) { 1070037ed1beSAaron Smith // A non-empty section list ensures a valid object file. 1071037ed1beSAaron Smith auto Obj = ModulePtr->GetObjectFile(); 1072037ed1beSAaron Smith FileSpecList Files; 1073037ed1beSAaron Smith auto Count = Obj->GetDependentModules(Files); 1074037ed1beSAaron Smith Printer.formatLine("Showing {0} dependent module(s)", Count); 1075037ed1beSAaron Smith for (size_t I = 0; I < Files.GetSize(); ++I) { 1076037ed1beSAaron Smith AutoIndent Indent(Printer, 2); 1077037ed1beSAaron Smith Printer.formatLine("Name: {0}", 1078529a3d87SGreg Clayton Files.GetFileSpecAtIndex(I).GetPath()); 1079037ed1beSAaron Smith } 1080037ed1beSAaron Smith Printer.NewLine(); 1081037ed1beSAaron Smith } 1082888a4282SZachary Turner } 108390b0a534SPavel Labath return HadErrors; 1084888a4282SZachary Turner } 1085888a4282SZachary Turner 1086c418b5ccSVedant Kumar bool opts::irmemorymap::evalMalloc(StringRef Line, 1087c418b5ccSVedant Kumar IRMemoryMapTestState &State) { 1088c418b5ccSVedant Kumar // ::= <label> = malloc <size> <alignment> 1089c418b5ccSVedant Kumar StringRef Label; 1090c418b5ccSVedant Kumar std::tie(Label, Line) = Line.split('='); 1091c418b5ccSVedant Kumar if (Line.empty()) 1092c418b5ccSVedant Kumar return false; 1093c418b5ccSVedant Kumar Label = Label.trim(); 1094c418b5ccSVedant Kumar Line = Line.trim(); 1095c1cd8262SVedant Kumar size_t Size; 1096c1cd8262SVedant Kumar uint8_t Alignment; 1097c1cd8262SVedant Kumar int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment); 1098c1cd8262SVedant Kumar if (Matches != 2) 1099c1cd8262SVedant Kumar return false; 1100c1cd8262SVedant Kumar 1101c418b5ccSVedant Kumar outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label, 1102c418b5ccSVedant Kumar Size, Alignment); 1103c1cd8262SVedant Kumar if (!isPowerOf2_32(Alignment)) { 1104c1cd8262SVedant Kumar outs() << "Malloc error: alignment is not a power of 2\n"; 1105c1cd8262SVedant Kumar exit(1); 1106c1cd8262SVedant Kumar } 1107c1cd8262SVedant Kumar 1108f616b9dbSVedant Kumar IRMemoryMap::AllocationPolicy AP = 1109f616b9dbSVedant Kumar UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly 1110f616b9dbSVedant Kumar : IRMemoryMap::eAllocationPolicyProcessOnly; 1111f616b9dbSVedant Kumar 1112c1cd8262SVedant Kumar // Issue the malloc in the target process with "-rw" permissions. 1113c1cd8262SVedant Kumar const uint32_t Permissions = 0x3; 1114c1cd8262SVedant Kumar const bool ZeroMemory = false; 1115c1cd8262SVedant Kumar Status ST; 1116c1cd8262SVedant Kumar addr_t Addr = 1117c418b5ccSVedant Kumar State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST); 1118c1cd8262SVedant Kumar if (ST.Fail()) { 1119c1cd8262SVedant Kumar outs() << formatv("Malloc error: {0}\n", ST); 1120c1cd8262SVedant Kumar return true; 1121c1cd8262SVedant Kumar } 1122c1cd8262SVedant Kumar 1123c1cd8262SVedant Kumar // Print the result of the allocation before checking its validity. 1124c1cd8262SVedant Kumar outs() << formatv("Malloc: address = {0:x}\n", Addr); 1125c1cd8262SVedant Kumar 1126c1cd8262SVedant Kumar // Check that the allocation is aligned. 1127c1cd8262SVedant Kumar if (!Addr || Addr % Alignment != 0) { 1128c1cd8262SVedant Kumar outs() << "Malloc error: zero or unaligned allocation detected\n"; 1129c1cd8262SVedant Kumar exit(1); 1130c1cd8262SVedant Kumar } 1131c1cd8262SVedant Kumar 1132a352ed20SPavel Labath // In case of Size == 0, we still expect the returned address to be unique and 1133a352ed20SPavel Labath // non-overlapping. 1134a352ed20SPavel Labath addr_t EndOfRegion = Addr + std::max<size_t>(Size, 1); 1135a352ed20SPavel Labath if (State.Allocations.overlaps(Addr, EndOfRegion)) { 1136a352ed20SPavel Labath auto I = State.Allocations.find(Addr); 1137c1cd8262SVedant Kumar outs() << "Malloc error: overlapping allocation detected" 1138a352ed20SPavel Labath << formatv(", previous allocation at [{0:x}, {1:x})\n", I.start(), 1139a352ed20SPavel Labath I.stop()); 1140c1cd8262SVedant Kumar exit(1); 1141c1cd8262SVedant Kumar } 1142c1cd8262SVedant Kumar 1143037ed1beSAaron Smith // Insert the new allocation into the interval map. Use unique allocation 1144037ed1beSAaron Smith // IDs to inhibit interval coalescing. 1145cc5a6163SVedant Kumar static unsigned AllocationID = 0; 1146c418b5ccSVedant Kumar State.Allocations.insert(Addr, EndOfRegion, AllocationID++); 1147c418b5ccSVedant Kumar 1148c418b5ccSVedant Kumar // Store the label -> address mapping. 1149c418b5ccSVedant Kumar State.Label2AddrMap[Label] = Addr; 1150cc5a6163SVedant Kumar 1151cc5a6163SVedant Kumar return true; 1152cc5a6163SVedant Kumar } 1153cc5a6163SVedant Kumar 1154c418b5ccSVedant Kumar bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) { 1155c418b5ccSVedant Kumar // ::= free <label> 1156c418b5ccSVedant Kumar if (!Line.consume_front("free")) 1157cc5a6163SVedant Kumar return false; 1158c418b5ccSVedant Kumar StringRef Label = Line.trim(); 1159cc5a6163SVedant Kumar 1160c418b5ccSVedant Kumar outs() << formatv("Command: free({0})\n", Label); 1161c418b5ccSVedant Kumar auto LabelIt = State.Label2AddrMap.find(Label); 1162c418b5ccSVedant Kumar if (LabelIt == State.Label2AddrMap.end()) { 1163c418b5ccSVedant Kumar outs() << "Free error: Invalid allocation label\n"; 1164cc5a6163SVedant Kumar exit(1); 1165cc5a6163SVedant Kumar } 1166cc5a6163SVedant Kumar 1167cc5a6163SVedant Kumar Status ST; 1168c418b5ccSVedant Kumar addr_t Addr = LabelIt->getValue(); 1169c418b5ccSVedant Kumar State.Map.Free(Addr, ST); 1170cc5a6163SVedant Kumar if (ST.Fail()) { 1171cc5a6163SVedant Kumar outs() << formatv("Free error: {0}\n", ST); 1172cc5a6163SVedant Kumar exit(1); 1173cc5a6163SVedant Kumar } 1174cc5a6163SVedant Kumar 1175cc5a6163SVedant Kumar // Erase the allocation from the live interval map. 1176c418b5ccSVedant Kumar auto Interval = State.Allocations.find(Addr); 1177c418b5ccSVedant Kumar if (Interval != State.Allocations.end()) { 1178c418b5ccSVedant Kumar outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(), 1179c418b5ccSVedant Kumar Interval.stop()); 1180c418b5ccSVedant Kumar Interval.erase(); 1181c418b5ccSVedant Kumar } 1182c1cd8262SVedant Kumar 1183c1cd8262SVedant Kumar return true; 1184c1cd8262SVedant Kumar } 1185c1cd8262SVedant Kumar 1186c1cd8262SVedant Kumar int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) { 1187c1cd8262SVedant Kumar // Set up a Target. 1188c1cd8262SVedant Kumar TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target); 1189c1cd8262SVedant Kumar 1190c1cd8262SVedant Kumar // Set up a Process. In order to allocate memory within a target, this 1191c1cd8262SVedant Kumar // process must be alive and must support JIT'ing. 1192de019b88SJonas Devlieghere CommandReturnObject Result(/*colors*/ false); 1193c1cd8262SVedant Kumar Dbg.SetAsyncExecution(false); 1194c1cd8262SVedant Kumar CommandInterpreter &CI = Dbg.GetCommandInterpreter(); 1195c1cd8262SVedant Kumar auto IssueCmd = [&](const char *Cmd) -> bool { 1196c1cd8262SVedant Kumar return CI.HandleCommand(Cmd, eLazyBoolNo, Result); 1197c1cd8262SVedant Kumar }; 1198c1cd8262SVedant Kumar if (!IssueCmd("b main") || !IssueCmd("run")) { 1199c2750807SAdrian Prantl outs() << formatv("Failed: {0}\n", Result.GetErrorString()); 1200c1cd8262SVedant Kumar exit(1); 1201c1cd8262SVedant Kumar } 1202c1cd8262SVedant Kumar 1203c1cd8262SVedant Kumar ProcessSP Process = Target->GetProcessSP(); 1204c1cd8262SVedant Kumar if (!Process || !Process->IsAlive() || !Process->CanJIT()) { 1205c1cd8262SVedant Kumar outs() << "Cannot use process to test IRMemoryMap\n"; 1206c1cd8262SVedant Kumar exit(1); 1207c1cd8262SVedant Kumar } 1208c1cd8262SVedant Kumar 1209c1cd8262SVedant Kumar // Set up an IRMemoryMap and associated testing state. 1210c418b5ccSVedant Kumar IRMemoryMapTestState State(Target); 1211c1cd8262SVedant Kumar 1212c1cd8262SVedant Kumar // Parse and apply commands from the command file. 1213c1cd8262SVedant Kumar std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile); 1214c1cd8262SVedant Kumar StringRef Rest = MB->getBuffer(); 1215c1cd8262SVedant Kumar while (!Rest.empty()) { 1216c1cd8262SVedant Kumar StringRef Line; 1217c1cd8262SVedant Kumar std::tie(Line, Rest) = Rest.split('\n'); 12184447d15aSAdrian McCarthy Line = Line.ltrim().rtrim(); 1219c1cd8262SVedant Kumar 1220c1cd8262SVedant Kumar if (Line.empty() || Line[0] == '#') 1221c1cd8262SVedant Kumar continue; 1222c1cd8262SVedant Kumar 1223c418b5ccSVedant Kumar if (evalMalloc(Line, State)) 1224c1cd8262SVedant Kumar continue; 1225c1cd8262SVedant Kumar 1226c418b5ccSVedant Kumar if (evalFree(Line, State)) 1227cc5a6163SVedant Kumar continue; 1228cc5a6163SVedant Kumar 1229c1cd8262SVedant Kumar errs() << "Could not parse line: " << Line << "\n"; 1230c1cd8262SVedant Kumar exit(1); 1231c1cd8262SVedant Kumar } 1232c1cd8262SVedant Kumar return 0; 1233c1cd8262SVedant Kumar } 1234c1cd8262SVedant Kumar 1235e089b5e9SJonas Devlieghere int opts::assert::lldb_assert(Debugger &Dbg) { 1236e089b5e9SJonas Devlieghere lldbassert(false && "lldb-test assert"); 1237e089b5e9SJonas Devlieghere return 1; 1238e089b5e9SJonas Devlieghere } 1239e089b5e9SJonas Devlieghere 1240888a4282SZachary Turner int main(int argc, const char *argv[]) { 1241888a4282SZachary Turner StringRef ToolName = argv[0]; 1242888a4282SZachary Turner sys::PrintStackTraceOnErrorSignal(ToolName); 1243888a4282SZachary Turner PrettyStackTraceProgram X(argc, argv); 1244888a4282SZachary Turner llvm_shutdown_obj Y; 1245888a4282SZachary Turner 1246888a4282SZachary Turner cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n"); 1247888a4282SZachary Turner 124890b0a534SPavel Labath SystemLifetimeManager DebuggerLifetime; 124915eacd74SJonas Devlieghere if (auto e = DebuggerLifetime.Initialize( 1250a8f3ae7cSJonas Devlieghere std::make_unique<SystemInitializerTest>(), nullptr)) { 125115eacd74SJonas Devlieghere WithColor::error() << "initialization failed: " << toString(std::move(e)) 125215eacd74SJonas Devlieghere << '\n'; 125315eacd74SJonas Devlieghere return 1; 125415eacd74SJonas Devlieghere } 125515eacd74SJonas Devlieghere 1256e0ea8d87SJonas Devlieghere auto TerminateDebugger = 1257e0ea8d87SJonas Devlieghere llvm::make_scope_exit([&] { DebuggerLifetime.Terminate(); }); 1258888a4282SZachary Turner 1259888a4282SZachary Turner auto Dbg = lldb_private::Debugger::CreateInstance(); 12608c82c412SJan Kratochvil ModuleList::GetGlobalModuleListProperties().SetEnableExternalLookup(false); 1261de019b88SJonas Devlieghere CommandReturnObject Result(/*colors*/ false); 12622b389517SJan Kratochvil Dbg->GetCommandInterpreter().HandleCommand( 12632b389517SJan Kratochvil "settings set plugin.process.gdb-remote.packet-timeout 60", 12642b389517SJan Kratochvil /*add_to_history*/ eLazyBoolNo, Result); 126561afdf0aSJonas Devlieghere Dbg->GetCommandInterpreter().HandleCommand( 126661afdf0aSJonas Devlieghere "settings set target.inherit-tcc true", 126761afdf0aSJonas Devlieghere /*add_to_history*/ eLazyBoolNo, Result); 1268d6f5e081SJonas Devlieghere Dbg->GetCommandInterpreter().HandleCommand( 1269d6f5e081SJonas Devlieghere "settings set target.detach-on-error false", 1270d6f5e081SJonas Devlieghere /*add_to_history*/ eLazyBoolNo, Result); 1271888a4282SZachary Turner 1272c1cd8262SVedant Kumar if (!opts::Log.empty()) 1273be265d25SJonas Devlieghere Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, 0, eLogHandlerStream, errs()); 1274c1cd8262SVedant Kumar 12757c94582fSPavel Labath if (opts::BreakpointSubcommand) 127690b0a534SPavel Labath return opts::breakpoint::evaluateBreakpoints(*Dbg); 127762a7f80aSPavel Labath if (opts::ObjectFileSubcommand) 127862a7f80aSPavel Labath return dumpObjectFiles(*Dbg); 127990b0a534SPavel Labath if (opts::SymbolsSubcommand) 128090b0a534SPavel Labath return opts::symbols::dumpSymbols(*Dbg); 12813aef968eSAugusto Noronha if (opts::SymTabSubcommand) 12823aef968eSAugusto Noronha return opts::symtab::handleSymtabCommand(*Dbg); 1283c1cd8262SVedant Kumar if (opts::IRMemoryMapSubcommand) 1284c1cd8262SVedant Kumar return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg); 1285e089b5e9SJonas Devlieghere if (opts::AssertSubcommand) 1286e089b5e9SJonas Devlieghere return opts::assert::lldb_assert(*Dbg); 1287888a4282SZachary Turner 128890b0a534SPavel Labath WithColor::error() << "No command specified.\n"; 128990b0a534SPavel Labath return 1; 1290888a4282SZachary Turner } 1291