xref: /llvm-project/lldb/tools/lldb-test/lldb-test.cpp (revision d6b90282578f607dc18e23197d9494ebbb899437)
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