xref: /openbsd-src/gnu/llvm/lldb/tools/lldb-test/lldb-test.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1061da546Spatrick //===- lldb-test.cpp ------------------------------------------ *- C++ --*-===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "FormatUtil.h"
10061da546Spatrick #include "SystemInitializerTest.h"
11061da546Spatrick 
12061da546Spatrick #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
13dda28197Spatrick #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
14061da546Spatrick #include "lldb/Breakpoint/BreakpointLocation.h"
15061da546Spatrick #include "lldb/Core/Debugger.h"
16061da546Spatrick #include "lldb/Core/Module.h"
17061da546Spatrick #include "lldb/Core/Section.h"
18061da546Spatrick #include "lldb/Expression/IRMemoryMap.h"
19061da546Spatrick #include "lldb/Initialization/SystemLifetimeManager.h"
20061da546Spatrick #include "lldb/Interpreter/CommandInterpreter.h"
21061da546Spatrick #include "lldb/Interpreter/CommandReturnObject.h"
22061da546Spatrick #include "lldb/Symbol/CompileUnit.h"
23061da546Spatrick #include "lldb/Symbol/LineTable.h"
24061da546Spatrick #include "lldb/Symbol/SymbolFile.h"
25*f6aab3d8Srobert #include "lldb/Symbol/Symtab.h"
26061da546Spatrick #include "lldb/Symbol/TypeList.h"
27061da546Spatrick #include "lldb/Symbol/TypeMap.h"
28061da546Spatrick #include "lldb/Symbol/VariableList.h"
29061da546Spatrick #include "lldb/Target/Language.h"
30061da546Spatrick #include "lldb/Target/Process.h"
31061da546Spatrick #include "lldb/Target/Target.h"
32061da546Spatrick #include "lldb/Utility/DataExtractor.h"
33be691f3bSpatrick #include "lldb/Utility/LLDBAssert.h"
34061da546Spatrick #include "lldb/Utility/State.h"
35061da546Spatrick #include "lldb/Utility/StreamString.h"
36061da546Spatrick 
37061da546Spatrick #include "llvm/ADT/IntervalMap.h"
38061da546Spatrick #include "llvm/ADT/ScopeExit.h"
39061da546Spatrick #include "llvm/ADT/StringRef.h"
40061da546Spatrick #include "llvm/Support/CommandLine.h"
41061da546Spatrick #include "llvm/Support/ManagedStatic.h"
42061da546Spatrick #include "llvm/Support/MathExtras.h"
43061da546Spatrick #include "llvm/Support/Path.h"
44061da546Spatrick #include "llvm/Support/PrettyStackTrace.h"
45061da546Spatrick #include "llvm/Support/Signals.h"
46061da546Spatrick #include "llvm/Support/WithColor.h"
47061da546Spatrick 
48061da546Spatrick #include <cstdio>
49*f6aab3d8Srobert #include <optional>
50061da546Spatrick #include <thread>
51061da546Spatrick 
52061da546Spatrick using namespace lldb;
53061da546Spatrick using namespace lldb_private;
54061da546Spatrick using namespace llvm;
55061da546Spatrick 
56061da546Spatrick namespace opts {
57061da546Spatrick static cl::SubCommand BreakpointSubcommand("breakpoints",
58061da546Spatrick                                            "Test breakpoint resolution");
59061da546Spatrick cl::SubCommand ObjectFileSubcommand("object-file",
60061da546Spatrick                                     "Display LLDB object file information");
61061da546Spatrick cl::SubCommand SymbolsSubcommand("symbols", "Dump symbols for an object file");
62*f6aab3d8Srobert cl::SubCommand SymTabSubcommand("symtab",
63*f6aab3d8Srobert                                 "Test symbol table functionality");
64061da546Spatrick cl::SubCommand IRMemoryMapSubcommand("ir-memory-map", "Test IRMemoryMap");
65be691f3bSpatrick cl::SubCommand AssertSubcommand("assert", "Test assert handling");
66061da546Spatrick 
67061da546Spatrick cl::opt<std::string> Log("log", cl::desc("Path to a log file"), cl::init(""),
68061da546Spatrick                          cl::sub(BreakpointSubcommand),
69061da546Spatrick                          cl::sub(ObjectFileSubcommand),
70061da546Spatrick                          cl::sub(SymbolsSubcommand),
71*f6aab3d8Srobert                          cl::sub(SymTabSubcommand),
72061da546Spatrick                          cl::sub(IRMemoryMapSubcommand));
73061da546Spatrick 
74061da546Spatrick /// Create a target using the file pointed to by \p Filename, or abort.
75061da546Spatrick TargetSP createTarget(Debugger &Dbg, const std::string &Filename);
76061da546Spatrick 
77061da546Spatrick /// Read \p Filename into a null-terminated buffer, or abort.
78061da546Spatrick std::unique_ptr<MemoryBuffer> openFile(const std::string &Filename);
79061da546Spatrick 
80061da546Spatrick namespace breakpoint {
81061da546Spatrick static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
82061da546Spatrick                                    cl::Required, cl::sub(BreakpointSubcommand));
83061da546Spatrick static cl::opt<std::string> CommandFile(cl::Positional,
84061da546Spatrick                                         cl::desc("<command-file>"),
85061da546Spatrick                                         cl::init("-"),
86061da546Spatrick                                         cl::sub(BreakpointSubcommand));
87061da546Spatrick static cl::opt<bool> Persistent(
88061da546Spatrick     "persistent",
89061da546Spatrick     cl::desc("Don't automatically remove all breakpoints before each command"),
90061da546Spatrick     cl::sub(BreakpointSubcommand));
91061da546Spatrick 
plural(uintmax_t value)92061da546Spatrick static llvm::StringRef plural(uintmax_t value) { return value == 1 ? "" : "s"; }
93061da546Spatrick static void dumpState(const BreakpointList &List, LinePrinter &P);
94061da546Spatrick static std::string substitute(StringRef Cmd);
95061da546Spatrick static int evaluateBreakpoints(Debugger &Dbg);
96061da546Spatrick } // namespace breakpoint
97061da546Spatrick 
98061da546Spatrick namespace object {
99061da546Spatrick cl::opt<bool> SectionContents("contents",
100061da546Spatrick                               cl::desc("Dump each section's contents"),
101061da546Spatrick                               cl::sub(ObjectFileSubcommand));
102061da546Spatrick cl::opt<bool> SectionDependentModules("dep-modules",
103061da546Spatrick                                       cl::desc("Dump each dependent module"),
104061da546Spatrick                                       cl::sub(ObjectFileSubcommand));
105061da546Spatrick cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
106061da546Spatrick                                      cl::OneOrMore,
107061da546Spatrick                                      cl::sub(ObjectFileSubcommand));
108061da546Spatrick } // namespace object
109061da546Spatrick 
110*f6aab3d8Srobert namespace symtab {
111*f6aab3d8Srobert 
112*f6aab3d8Srobert /// The same enum as Mangled::NamePreference but with a default
113*f6aab3d8Srobert /// 'None' case. This is needed to disambiguate wheter "ManglingPreference" was
114*f6aab3d8Srobert /// explicitly set or not.
115*f6aab3d8Srobert enum class ManglingPreference {
116*f6aab3d8Srobert   None,
117*f6aab3d8Srobert   Mangled,
118*f6aab3d8Srobert   Demangled,
119*f6aab3d8Srobert   MangledWithoutArguments,
120*f6aab3d8Srobert };
121*f6aab3d8Srobert 
122*f6aab3d8Srobert static cl::opt<std::string> FindSymbolsByRegex(
123*f6aab3d8Srobert     "find-symbols-by-regex",
124*f6aab3d8Srobert     cl::desc(
125*f6aab3d8Srobert         "Dump symbols found in the symbol table matching the specified regex."),
126*f6aab3d8Srobert     cl::sub(SymTabSubcommand));
127*f6aab3d8Srobert 
128*f6aab3d8Srobert static cl::opt<ManglingPreference> ManglingPreference(
129*f6aab3d8Srobert     "mangling-preference",
130*f6aab3d8Srobert     cl::desc("Preference on mangling scheme the regex should match against and "
131*f6aab3d8Srobert              "dumped."),
132*f6aab3d8Srobert     cl::values(
133*f6aab3d8Srobert         clEnumValN(ManglingPreference::Mangled, "mangled", "Prefer mangled"),
134*f6aab3d8Srobert         clEnumValN(ManglingPreference::Demangled, "demangled",
135*f6aab3d8Srobert                    "Prefer demangled"),
136*f6aab3d8Srobert         clEnumValN(ManglingPreference::MangledWithoutArguments,
137*f6aab3d8Srobert                    "demangled-without-args", "Prefer mangled without args")),
138*f6aab3d8Srobert     cl::sub(SymTabSubcommand));
139*f6aab3d8Srobert 
140*f6aab3d8Srobert static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
141*f6aab3d8Srobert                                       cl::Required, cl::sub(SymTabSubcommand));
142*f6aab3d8Srobert 
143*f6aab3d8Srobert /// Validate that the options passed make sense.
144*f6aab3d8Srobert static std::optional<llvm::Error> validate();
145*f6aab3d8Srobert 
146*f6aab3d8Srobert /// Transforms the selected mangling preference into a Mangled::NamePreference
147*f6aab3d8Srobert static Mangled::NamePreference getNamePreference();
148*f6aab3d8Srobert 
149*f6aab3d8Srobert static int handleSymtabCommand(Debugger &Dbg);
150*f6aab3d8Srobert } // namespace symtab
151*f6aab3d8Srobert 
152061da546Spatrick namespace symbols {
153061da546Spatrick static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
154061da546Spatrick                                       cl::Required, cl::sub(SymbolsSubcommand));
155061da546Spatrick 
156061da546Spatrick static cl::opt<std::string>
157061da546Spatrick     SymbolPath("symbol-file",
158061da546Spatrick                cl::desc("The file from which to fetch symbol information."),
159061da546Spatrick                cl::value_desc("file"), cl::sub(SymbolsSubcommand));
160061da546Spatrick 
161061da546Spatrick enum class FindType {
162061da546Spatrick   None,
163061da546Spatrick   Function,
164061da546Spatrick   Block,
165061da546Spatrick   Namespace,
166061da546Spatrick   Type,
167061da546Spatrick   Variable,
168061da546Spatrick };
169061da546Spatrick static cl::opt<FindType> Find(
170061da546Spatrick     "find", cl::desc("Choose search type:"),
171061da546Spatrick     cl::values(
172061da546Spatrick         clEnumValN(FindType::None, "none", "No search, just dump the module."),
173061da546Spatrick         clEnumValN(FindType::Function, "function", "Find functions."),
174061da546Spatrick         clEnumValN(FindType::Block, "block", "Find blocks."),
175061da546Spatrick         clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
176061da546Spatrick         clEnumValN(FindType::Type, "type", "Find types."),
177061da546Spatrick         clEnumValN(FindType::Variable, "variable", "Find global variables.")),
178061da546Spatrick     cl::sub(SymbolsSubcommand));
179061da546Spatrick 
180061da546Spatrick static cl::opt<std::string> Name("name", cl::desc("Name to find."),
181061da546Spatrick                                  cl::sub(SymbolsSubcommand));
182061da546Spatrick static cl::opt<bool>
183061da546Spatrick     Regex("regex",
184dda28197Spatrick           cl::desc("Search using regular expressions (available for variables "
185061da546Spatrick                    "and functions only)."),
186061da546Spatrick           cl::sub(SymbolsSubcommand));
187061da546Spatrick static cl::opt<std::string>
188061da546Spatrick     Context("context",
189061da546Spatrick             cl::desc("Restrict search to the context of the given variable."),
190061da546Spatrick             cl::value_desc("variable"), cl::sub(SymbolsSubcommand));
191061da546Spatrick 
192061da546Spatrick static cl::opt<std::string> CompilerContext(
193061da546Spatrick     "compiler-context",
194061da546Spatrick     cl::desc("Specify a compiler context as \"kind:name,...\"."),
195061da546Spatrick     cl::value_desc("context"), cl::sub(SymbolsSubcommand));
196061da546Spatrick 
197061da546Spatrick static cl::opt<std::string>
198061da546Spatrick     Language("language", cl::desc("Specify a language type, like C99."),
199061da546Spatrick              cl::value_desc("language"), cl::sub(SymbolsSubcommand));
200061da546Spatrick 
201061da546Spatrick static cl::list<FunctionNameType> FunctionNameFlags(
202061da546Spatrick     "function-flags", cl::desc("Function search flags:"),
203061da546Spatrick     cl::values(clEnumValN(eFunctionNameTypeAuto, "auto",
204061da546Spatrick                           "Automatically deduce flags based on name."),
205061da546Spatrick                clEnumValN(eFunctionNameTypeFull, "full", "Full function name."),
206061da546Spatrick                clEnumValN(eFunctionNameTypeBase, "base", "Base name."),
207061da546Spatrick                clEnumValN(eFunctionNameTypeMethod, "method", "Method name."),
208061da546Spatrick                clEnumValN(eFunctionNameTypeSelector, "selector",
209061da546Spatrick                           "Selector name.")),
210061da546Spatrick     cl::sub(SymbolsSubcommand));
getFunctionNameFlags()211061da546Spatrick static FunctionNameType getFunctionNameFlags() {
212061da546Spatrick   FunctionNameType Result = FunctionNameType(0);
213061da546Spatrick   for (FunctionNameType Flag : FunctionNameFlags)
214061da546Spatrick     Result = FunctionNameType(Result | Flag);
215061da546Spatrick   return Result;
216061da546Spatrick }
217061da546Spatrick 
218061da546Spatrick static cl::opt<bool> DumpAST("dump-ast",
219061da546Spatrick                              cl::desc("Dump AST restored from symbols."),
220061da546Spatrick                              cl::sub(SymbolsSubcommand));
221dda28197Spatrick static cl::opt<bool> DumpClangAST(
222dda28197Spatrick     "dump-clang-ast",
223dda28197Spatrick     cl::desc("Dump clang AST restored from symbols. When used on its own this "
224dda28197Spatrick              "will dump the entire AST of all loaded symbols. When combined "
225dda28197Spatrick              "with -find, it changes the presentation of the search results "
226dda28197Spatrick              "from pretty-printing the types to an AST dump."),
227061da546Spatrick     cl::sub(SymbolsSubcommand));
228061da546Spatrick 
229061da546Spatrick static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
230061da546Spatrick                             cl::sub(SymbolsSubcommand));
231061da546Spatrick 
232061da546Spatrick static cl::opt<std::string> File("file",
233061da546Spatrick                                  cl::desc("File (compile unit) to search."),
234061da546Spatrick                                  cl::sub(SymbolsSubcommand));
235061da546Spatrick static cl::opt<int> Line("line", cl::desc("Line to search."),
236061da546Spatrick                          cl::sub(SymbolsSubcommand));
237061da546Spatrick 
238061da546Spatrick static Expected<CompilerDeclContext> getDeclContext(SymbolFile &Symfile);
239061da546Spatrick 
240061da546Spatrick static Error findFunctions(lldb_private::Module &Module);
241061da546Spatrick static Error findBlocks(lldb_private::Module &Module);
242061da546Spatrick static Error findNamespaces(lldb_private::Module &Module);
243061da546Spatrick static Error findTypes(lldb_private::Module &Module);
244061da546Spatrick static Error findVariables(lldb_private::Module &Module);
245061da546Spatrick static Error dumpModule(lldb_private::Module &Module);
246061da546Spatrick static Error dumpAST(lldb_private::Module &Module);
247dda28197Spatrick static Error dumpEntireClangAST(lldb_private::Module &Module);
248061da546Spatrick static Error verify(lldb_private::Module &Module);
249061da546Spatrick 
250061da546Spatrick static Expected<Error (*)(lldb_private::Module &)> getAction();
251061da546Spatrick static int dumpSymbols(Debugger &Dbg);
252061da546Spatrick } // namespace symbols
253061da546Spatrick 
254061da546Spatrick namespace irmemorymap {
255061da546Spatrick static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
256061da546Spatrick                                    cl::Required,
257061da546Spatrick                                    cl::sub(IRMemoryMapSubcommand));
258061da546Spatrick static cl::opt<std::string> CommandFile(cl::Positional,
259061da546Spatrick                                         cl::desc("<command-file>"),
260061da546Spatrick                                         cl::init("-"),
261061da546Spatrick                                         cl::sub(IRMemoryMapSubcommand));
262061da546Spatrick static cl::opt<bool> UseHostOnlyAllocationPolicy(
263061da546Spatrick     "host-only", cl::desc("Use the host-only allocation policy"),
264061da546Spatrick     cl::init(false), cl::sub(IRMemoryMapSubcommand));
265061da546Spatrick 
266061da546Spatrick using AllocationT = std::pair<addr_t, addr_t>;
267061da546Spatrick using AddrIntervalMap =
268061da546Spatrick     IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>;
269061da546Spatrick 
270061da546Spatrick struct IRMemoryMapTestState {
271061da546Spatrick   TargetSP Target;
272061da546Spatrick   IRMemoryMap Map;
273061da546Spatrick 
274061da546Spatrick   AddrIntervalMap::Allocator IntervalMapAllocator;
275061da546Spatrick   AddrIntervalMap Allocations;
276061da546Spatrick 
277061da546Spatrick   StringMap<addr_t> Label2AddrMap;
278061da546Spatrick 
IRMemoryMapTestStateopts::irmemorymap::IRMemoryMapTestState279061da546Spatrick   IRMemoryMapTestState(TargetSP Target)
280061da546Spatrick       : Target(Target), Map(Target), Allocations(IntervalMapAllocator) {}
281061da546Spatrick };
282061da546Spatrick 
283061da546Spatrick bool evalMalloc(StringRef Line, IRMemoryMapTestState &State);
284061da546Spatrick bool evalFree(StringRef Line, IRMemoryMapTestState &State);
285061da546Spatrick int evaluateMemoryMapCommands(Debugger &Dbg);
286061da546Spatrick } // namespace irmemorymap
287061da546Spatrick 
288be691f3bSpatrick namespace assert {
289be691f3bSpatrick int lldb_assert(Debugger &Dbg);
290be691f3bSpatrick } // namespace assert
291061da546Spatrick } // namespace opts
292061da546Spatrick 
parseCompilerContext()293061da546Spatrick std::vector<CompilerContext> parseCompilerContext() {
294061da546Spatrick   std::vector<CompilerContext> result;
295061da546Spatrick   if (opts::symbols::CompilerContext.empty())
296061da546Spatrick     return result;
297061da546Spatrick 
298061da546Spatrick   StringRef str{opts::symbols::CompilerContext};
299061da546Spatrick   SmallVector<StringRef, 8> entries_str;
300061da546Spatrick   str.split(entries_str, ',', /*maxSplit*/-1, /*keepEmpty=*/false);
301061da546Spatrick   for (auto entry_str : entries_str) {
302061da546Spatrick     StringRef key, value;
303061da546Spatrick     std::tie(key, value) = entry_str.split(':');
304061da546Spatrick     auto kind =
305061da546Spatrick         StringSwitch<CompilerContextKind>(key)
306061da546Spatrick             .Case("TranslationUnit", CompilerContextKind::TranslationUnit)
307061da546Spatrick             .Case("Module", CompilerContextKind::Module)
308061da546Spatrick             .Case("Namespace", CompilerContextKind::Namespace)
309061da546Spatrick             .Case("Class", CompilerContextKind::Class)
310061da546Spatrick             .Case("Struct", CompilerContextKind::Struct)
311061da546Spatrick             .Case("Union", CompilerContextKind::Union)
312061da546Spatrick             .Case("Function", CompilerContextKind::Function)
313061da546Spatrick             .Case("Variable", CompilerContextKind::Variable)
314061da546Spatrick             .Case("Enum", CompilerContextKind::Enum)
315061da546Spatrick             .Case("Typedef", CompilerContextKind::Typedef)
316061da546Spatrick             .Case("AnyModule", CompilerContextKind::AnyModule)
317061da546Spatrick             .Case("AnyType", CompilerContextKind::AnyType)
318061da546Spatrick             .Default(CompilerContextKind::Invalid);
319061da546Spatrick     if (value.empty()) {
320061da546Spatrick       WithColor::error() << "compiler context entry has no \"name\"\n";
321061da546Spatrick       exit(1);
322061da546Spatrick     }
323061da546Spatrick     result.push_back({kind, ConstString{value}});
324061da546Spatrick   }
325061da546Spatrick   outs() << "Search context: {\n";
326061da546Spatrick   for (auto entry: result)
327061da546Spatrick     entry.Dump();
328061da546Spatrick   outs() << "}\n";
329061da546Spatrick 
330061da546Spatrick   return result;
331061da546Spatrick }
332061da546Spatrick 
333061da546Spatrick template <typename... Args>
make_string_error(const char * Format,Args &&...args)334061da546Spatrick static Error make_string_error(const char *Format, Args &&... args) {
335061da546Spatrick   return llvm::make_error<llvm::StringError>(
336061da546Spatrick       llvm::formatv(Format, std::forward<Args>(args)...).str(),
337061da546Spatrick       llvm::inconvertibleErrorCode());
338061da546Spatrick }
339061da546Spatrick 
createTarget(Debugger & Dbg,const std::string & Filename)340061da546Spatrick TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) {
341061da546Spatrick   TargetSP Target;
342061da546Spatrick   Status ST = Dbg.GetTargetList().CreateTarget(
343061da546Spatrick       Dbg, Filename, /*triple*/ "", eLoadDependentsNo,
344061da546Spatrick       /*platform_options*/ nullptr, Target);
345061da546Spatrick   if (ST.Fail()) {
346061da546Spatrick     errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST);
347061da546Spatrick     exit(1);
348061da546Spatrick   }
349061da546Spatrick   return Target;
350061da546Spatrick }
351061da546Spatrick 
openFile(const std::string & Filename)352061da546Spatrick std::unique_ptr<MemoryBuffer> opts::openFile(const std::string &Filename) {
353061da546Spatrick   auto MB = MemoryBuffer::getFileOrSTDIN(Filename);
354061da546Spatrick   if (!MB) {
355061da546Spatrick     errs() << formatv("Could not open file '{0}: {1}\n", Filename,
356061da546Spatrick                       MB.getError().message());
357061da546Spatrick     exit(1);
358061da546Spatrick   }
359061da546Spatrick   return std::move(*MB);
360061da546Spatrick }
361061da546Spatrick 
dumpState(const BreakpointList & List,LinePrinter & P)362061da546Spatrick void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) {
363061da546Spatrick   P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize()));
364061da546Spatrick   if (List.GetSize() > 0)
365061da546Spatrick     P.formatLine("At least one breakpoint.");
366061da546Spatrick   for (size_t i = 0, e = List.GetSize(); i < e; ++i) {
367061da546Spatrick     BreakpointSP BP = List.GetBreakpointAtIndex(i);
368061da546Spatrick     P.formatLine("Breakpoint ID {0}:", BP->GetID());
369061da546Spatrick     AutoIndent Indent(P, 2);
370061da546Spatrick     P.formatLine("{0} location{1}.", BP->GetNumLocations(),
371061da546Spatrick                  plural(BP->GetNumLocations()));
372061da546Spatrick     if (BP->GetNumLocations() > 0)
373061da546Spatrick       P.formatLine("At least one location.");
374061da546Spatrick     P.formatLine("{0} resolved location{1}.", BP->GetNumResolvedLocations(),
375061da546Spatrick                  plural(BP->GetNumResolvedLocations()));
376061da546Spatrick     if (BP->GetNumResolvedLocations() > 0)
377061da546Spatrick       P.formatLine("At least one resolved location.");
378061da546Spatrick     for (size_t l = 0, le = BP->GetNumLocations(); l < le; ++l) {
379061da546Spatrick       BreakpointLocationSP Loc = BP->GetLocationAtIndex(l);
380061da546Spatrick       P.formatLine("Location ID {0}:", Loc->GetID());
381061da546Spatrick       AutoIndent Indent(P, 2);
382061da546Spatrick       P.formatLine("Enabled: {0}", Loc->IsEnabled());
383061da546Spatrick       P.formatLine("Resolved: {0}", Loc->IsResolved());
384061da546Spatrick       SymbolContext sc;
385061da546Spatrick       Loc->GetAddress().CalculateSymbolContext(&sc);
386061da546Spatrick       lldb_private::StreamString S;
387061da546Spatrick       sc.DumpStopContext(&S, BP->GetTarget().GetProcessSP().get(),
388061da546Spatrick                          Loc->GetAddress(), false, true, false, true, true);
389061da546Spatrick       P.formatLine("Address: {0}", S.GetString());
390061da546Spatrick     }
391061da546Spatrick   }
392061da546Spatrick   P.NewLine();
393061da546Spatrick }
394061da546Spatrick 
substitute(StringRef Cmd)395061da546Spatrick std::string opts::breakpoint::substitute(StringRef Cmd) {
396061da546Spatrick   std::string Result;
397061da546Spatrick   raw_string_ostream OS(Result);
398061da546Spatrick   while (!Cmd.empty()) {
399061da546Spatrick     switch (Cmd[0]) {
400061da546Spatrick     case '%':
401061da546Spatrick       if (Cmd.consume_front("%p") && (Cmd.empty() || !isalnum(Cmd[0]))) {
402061da546Spatrick         OS << sys::path::parent_path(breakpoint::CommandFile);
403061da546Spatrick         break;
404061da546Spatrick       }
405*f6aab3d8Srobert       [[fallthrough]];
406061da546Spatrick     default:
407061da546Spatrick       size_t pos = Cmd.find('%');
408061da546Spatrick       OS << Cmd.substr(0, pos);
409061da546Spatrick       Cmd = Cmd.substr(pos);
410061da546Spatrick       break;
411061da546Spatrick     }
412061da546Spatrick   }
413061da546Spatrick   return std::move(OS.str());
414061da546Spatrick }
415061da546Spatrick 
evaluateBreakpoints(Debugger & Dbg)416061da546Spatrick int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
417061da546Spatrick   TargetSP Target = opts::createTarget(Dbg, breakpoint::Target);
418061da546Spatrick   std::unique_ptr<MemoryBuffer> MB = opts::openFile(breakpoint::CommandFile);
419061da546Spatrick 
420061da546Spatrick   LinePrinter P(4, outs());
421061da546Spatrick   StringRef Rest = MB->getBuffer();
422061da546Spatrick   int HadErrors = 0;
423061da546Spatrick   while (!Rest.empty()) {
424061da546Spatrick     StringRef Line;
425061da546Spatrick     std::tie(Line, Rest) = Rest.split('\n');
426061da546Spatrick     Line = Line.ltrim().rtrim();
427061da546Spatrick     if (Line.empty() || Line[0] == '#')
428061da546Spatrick       continue;
429061da546Spatrick 
430061da546Spatrick     if (!Persistent)
431061da546Spatrick       Target->RemoveAllBreakpoints(/*internal_also*/ true);
432061da546Spatrick 
433061da546Spatrick     std::string Command = substitute(Line);
434061da546Spatrick     P.formatLine("Command: {0}", Command);
435dda28197Spatrick     CommandReturnObject Result(/*colors*/ false);
436061da546Spatrick     if (!Dbg.GetCommandInterpreter().HandleCommand(
437061da546Spatrick             Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
438061da546Spatrick       P.formatLine("Failed: {0}", Result.GetErrorData());
439061da546Spatrick       HadErrors = 1;
440061da546Spatrick       continue;
441061da546Spatrick     }
442061da546Spatrick 
443061da546Spatrick     dumpState(Target->GetBreakpointList(/*internal*/ false), P);
444061da546Spatrick   }
445061da546Spatrick   return HadErrors;
446061da546Spatrick }
447061da546Spatrick 
448061da546Spatrick Expected<CompilerDeclContext>
getDeclContext(SymbolFile & Symfile)449061da546Spatrick opts::symbols::getDeclContext(SymbolFile &Symfile) {
450061da546Spatrick   if (Context.empty())
451061da546Spatrick     return CompilerDeclContext();
452061da546Spatrick   VariableList List;
453dda28197Spatrick   Symfile.FindGlobalVariables(ConstString(Context), CompilerDeclContext(),
454dda28197Spatrick                               UINT32_MAX, List);
455061da546Spatrick   if (List.Empty())
456061da546Spatrick     return make_string_error("Context search didn't find a match.");
457061da546Spatrick   if (List.GetSize() > 1)
458061da546Spatrick     return make_string_error("Context search found multiple matches.");
459061da546Spatrick   return List.GetVariableAtIndex(0)->GetDeclContext();
460061da546Spatrick }
461061da546Spatrick 
GetDescriptionLevel()462dda28197Spatrick static lldb::DescriptionLevel GetDescriptionLevel() {
463dda28197Spatrick   return opts::symbols::DumpClangAST ? eDescriptionLevelVerbose : eDescriptionLevelFull;
464dda28197Spatrick }
465dda28197Spatrick 
findFunctions(lldb_private::Module & Module)466061da546Spatrick Error opts::symbols::findFunctions(lldb_private::Module &Module) {
467061da546Spatrick   SymbolFile &Symfile = *Module.GetSymbolFile();
468061da546Spatrick   SymbolContextList List;
469061da546Spatrick   if (!File.empty()) {
470061da546Spatrick     assert(Line != 0);
471061da546Spatrick 
472061da546Spatrick     FileSpec src_file(File);
473061da546Spatrick     size_t cu_count = Module.GetNumCompileUnits();
474061da546Spatrick     for (size_t i = 0; i < cu_count; i++) {
475061da546Spatrick       lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
476061da546Spatrick       if (!cu_sp)
477061da546Spatrick         continue;
478061da546Spatrick 
479061da546Spatrick       LineEntry le;
480061da546Spatrick       cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
481061da546Spatrick       if (!le.IsValid())
482061da546Spatrick         continue;
483061da546Spatrick       const bool include_inlined_functions = false;
484061da546Spatrick       auto addr =
485061da546Spatrick           le.GetSameLineContiguousAddressRange(include_inlined_functions)
486061da546Spatrick               .GetBaseAddress();
487061da546Spatrick       if (!addr.IsValid())
488061da546Spatrick         continue;
489061da546Spatrick 
490061da546Spatrick       SymbolContext sc;
491061da546Spatrick       uint32_t resolved =
492061da546Spatrick           addr.CalculateSymbolContext(&sc, eSymbolContextFunction);
493061da546Spatrick       if (resolved & eSymbolContextFunction)
494061da546Spatrick         List.Append(sc);
495061da546Spatrick     }
496061da546Spatrick   } else if (Regex) {
497061da546Spatrick     RegularExpression RE(Name);
498061da546Spatrick     assert(RE.IsValid());
499061da546Spatrick     List.Clear();
500061da546Spatrick     Symfile.FindFunctions(RE, true, List);
501061da546Spatrick   } else {
502061da546Spatrick     Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
503061da546Spatrick     if (!ContextOr)
504061da546Spatrick       return ContextOr.takeError();
505dda28197Spatrick     const CompilerDeclContext &ContextPtr =
506dda28197Spatrick         ContextOr->IsValid() ? *ContextOr : CompilerDeclContext();
507061da546Spatrick 
508061da546Spatrick     List.Clear();
509*f6aab3d8Srobert     Module::LookupInfo lookup_info(ConstString(Name), getFunctionNameFlags(),
510*f6aab3d8Srobert                                    eLanguageTypeUnknown);
511*f6aab3d8Srobert     Symfile.FindFunctions(lookup_info, ContextPtr, true, List);
512061da546Spatrick   }
513061da546Spatrick   outs() << formatv("Found {0} functions:\n", List.GetSize());
514061da546Spatrick   StreamString Stream;
515061da546Spatrick   List.Dump(&Stream, nullptr);
516061da546Spatrick   outs() << Stream.GetData() << "\n";
517061da546Spatrick   return Error::success();
518061da546Spatrick }
519061da546Spatrick 
findBlocks(lldb_private::Module & Module)520061da546Spatrick Error opts::symbols::findBlocks(lldb_private::Module &Module) {
521061da546Spatrick   assert(!Regex);
522061da546Spatrick   assert(!File.empty());
523061da546Spatrick   assert(Line != 0);
524061da546Spatrick 
525061da546Spatrick   SymbolContextList List;
526061da546Spatrick 
527061da546Spatrick   FileSpec src_file(File);
528061da546Spatrick   size_t cu_count = Module.GetNumCompileUnits();
529061da546Spatrick   for (size_t i = 0; i < cu_count; i++) {
530061da546Spatrick     lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
531061da546Spatrick     if (!cu_sp)
532061da546Spatrick       continue;
533061da546Spatrick 
534061da546Spatrick     LineEntry le;
535061da546Spatrick     cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
536061da546Spatrick     if (!le.IsValid())
537061da546Spatrick       continue;
538061da546Spatrick     const bool include_inlined_functions = false;
539061da546Spatrick     auto addr = le.GetSameLineContiguousAddressRange(include_inlined_functions)
540061da546Spatrick                     .GetBaseAddress();
541061da546Spatrick     if (!addr.IsValid())
542061da546Spatrick       continue;
543061da546Spatrick 
544061da546Spatrick     SymbolContext sc;
545061da546Spatrick     uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock);
546061da546Spatrick     if (resolved & eSymbolContextBlock)
547061da546Spatrick       List.Append(sc);
548061da546Spatrick   }
549061da546Spatrick 
550061da546Spatrick   outs() << formatv("Found {0} blocks:\n", List.GetSize());
551061da546Spatrick   StreamString Stream;
552061da546Spatrick   List.Dump(&Stream, nullptr);
553061da546Spatrick   outs() << Stream.GetData() << "\n";
554061da546Spatrick   return Error::success();
555061da546Spatrick }
556061da546Spatrick 
findNamespaces(lldb_private::Module & Module)557061da546Spatrick Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
558061da546Spatrick   SymbolFile &Symfile = *Module.GetSymbolFile();
559061da546Spatrick   Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
560061da546Spatrick   if (!ContextOr)
561061da546Spatrick     return ContextOr.takeError();
562dda28197Spatrick   const CompilerDeclContext &ContextPtr =
563dda28197Spatrick       ContextOr->IsValid() ? *ContextOr : CompilerDeclContext();
564061da546Spatrick 
565061da546Spatrick   CompilerDeclContext Result =
566061da546Spatrick       Symfile.FindNamespace(ConstString(Name), ContextPtr);
567061da546Spatrick   if (Result)
568061da546Spatrick     outs() << "Found namespace: "
569061da546Spatrick            << Result.GetScopeQualifiedName().GetStringRef() << "\n";
570061da546Spatrick   else
571061da546Spatrick     outs() << "Namespace not found.\n";
572061da546Spatrick   return Error::success();
573061da546Spatrick }
574061da546Spatrick 
findTypes(lldb_private::Module & Module)575061da546Spatrick Error opts::symbols::findTypes(lldb_private::Module &Module) {
576061da546Spatrick   SymbolFile &Symfile = *Module.GetSymbolFile();
577061da546Spatrick   Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
578061da546Spatrick   if (!ContextOr)
579061da546Spatrick     return ContextOr.takeError();
580dda28197Spatrick   const CompilerDeclContext &ContextPtr =
581dda28197Spatrick       ContextOr->IsValid() ? *ContextOr : CompilerDeclContext();
582061da546Spatrick 
583061da546Spatrick   LanguageSet languages;
584061da546Spatrick   if (!Language.empty())
585061da546Spatrick     languages.Insert(Language::GetLanguageTypeFromString(Language));
586061da546Spatrick 
587061da546Spatrick   DenseSet<SymbolFile *> SearchedFiles;
588061da546Spatrick   TypeMap Map;
589061da546Spatrick   if (!Name.empty())
590061da546Spatrick     Symfile.FindTypes(ConstString(Name), ContextPtr, UINT32_MAX, SearchedFiles,
591061da546Spatrick                       Map);
592061da546Spatrick   else
593061da546Spatrick     Module.FindTypes(parseCompilerContext(), languages, SearchedFiles, Map);
594061da546Spatrick 
595061da546Spatrick   outs() << formatv("Found {0} types:\n", Map.GetSize());
596061da546Spatrick   StreamString Stream;
597dda28197Spatrick   // Resolve types to force-materialize typedef types.
598dda28197Spatrick   Map.ForEach([&](TypeSP &type) {
599dda28197Spatrick     type->GetFullCompilerType();
600dda28197Spatrick     return false;
601dda28197Spatrick   });
602dda28197Spatrick   Map.Dump(&Stream, false, GetDescriptionLevel());
603061da546Spatrick   outs() << Stream.GetData() << "\n";
604061da546Spatrick   return Error::success();
605061da546Spatrick }
606061da546Spatrick 
findVariables(lldb_private::Module & Module)607061da546Spatrick Error opts::symbols::findVariables(lldb_private::Module &Module) {
608061da546Spatrick   SymbolFile &Symfile = *Module.GetSymbolFile();
609061da546Spatrick   VariableList List;
610061da546Spatrick   if (Regex) {
611061da546Spatrick     RegularExpression RE(Name);
612061da546Spatrick     assert(RE.IsValid());
613061da546Spatrick     Symfile.FindGlobalVariables(RE, UINT32_MAX, List);
614061da546Spatrick   } else if (!File.empty()) {
615061da546Spatrick     CompUnitSP CU;
616061da546Spatrick     for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) {
617061da546Spatrick       CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind);
618061da546Spatrick       if (!Candidate ||
619061da546Spatrick           Candidate->GetPrimaryFile().GetFilename().GetStringRef() != File)
620061da546Spatrick         continue;
621061da546Spatrick       if (CU)
622061da546Spatrick         return make_string_error("Multiple compile units for file `{0}` found.",
623061da546Spatrick                                  File);
624061da546Spatrick       CU = std::move(Candidate);
625061da546Spatrick     }
626061da546Spatrick 
627061da546Spatrick     if (!CU)
628061da546Spatrick       return make_string_error("Compile unit `{0}` not found.", File);
629061da546Spatrick 
630061da546Spatrick     List.AddVariables(CU->GetVariableList(true).get());
631061da546Spatrick   } else {
632061da546Spatrick     Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
633061da546Spatrick     if (!ContextOr)
634061da546Spatrick       return ContextOr.takeError();
635dda28197Spatrick     const CompilerDeclContext &ContextPtr =
636dda28197Spatrick         ContextOr->IsValid() ? *ContextOr : CompilerDeclContext();
637061da546Spatrick 
638061da546Spatrick     Symfile.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List);
639061da546Spatrick   }
640061da546Spatrick   outs() << formatv("Found {0} variables:\n", List.GetSize());
641061da546Spatrick   StreamString Stream;
642061da546Spatrick   List.Dump(&Stream, false);
643061da546Spatrick   outs() << Stream.GetData() << "\n";
644061da546Spatrick   return Error::success();
645061da546Spatrick }
646061da546Spatrick 
dumpModule(lldb_private::Module & Module)647061da546Spatrick Error opts::symbols::dumpModule(lldb_private::Module &Module) {
648061da546Spatrick   StreamString Stream;
649061da546Spatrick   Module.ParseAllDebugSymbols();
650061da546Spatrick   Module.Dump(&Stream);
651061da546Spatrick   outs() << Stream.GetData() << "\n";
652061da546Spatrick   return Error::success();
653061da546Spatrick }
654061da546Spatrick 
dumpAST(lldb_private::Module & Module)655061da546Spatrick Error opts::symbols::dumpAST(lldb_private::Module &Module) {
656061da546Spatrick   Module.ParseAllDebugSymbols();
657061da546Spatrick 
658061da546Spatrick   SymbolFile *symfile = Module.GetSymbolFile();
659061da546Spatrick   if (!symfile)
660061da546Spatrick     return make_string_error("Module has no symbol file.");
661061da546Spatrick 
662*f6aab3d8Srobert   auto type_system_or_err =
663061da546Spatrick       symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
664061da546Spatrick   if (!type_system_or_err)
665dda28197Spatrick     return make_string_error("Can't retrieve TypeSystemClang");
666061da546Spatrick 
667*f6aab3d8Srobert   auto ts = *type_system_or_err;
668*f6aab3d8Srobert   auto *clang_ast_ctx = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
669061da546Spatrick   if (!clang_ast_ctx)
670dda28197Spatrick     return make_string_error("Retrieved TypeSystem was not a TypeSystemClang");
671061da546Spatrick 
672061da546Spatrick   clang::ASTContext &ast_ctx = clang_ast_ctx->getASTContext();
673061da546Spatrick 
674061da546Spatrick   clang::TranslationUnitDecl *tu = ast_ctx.getTranslationUnitDecl();
675061da546Spatrick   if (!tu)
676061da546Spatrick     return make_string_error("Can't retrieve translation unit declaration.");
677061da546Spatrick 
678061da546Spatrick   tu->print(outs());
679061da546Spatrick 
680061da546Spatrick   return Error::success();
681061da546Spatrick }
682061da546Spatrick 
dumpEntireClangAST(lldb_private::Module & Module)683dda28197Spatrick Error opts::symbols::dumpEntireClangAST(lldb_private::Module &Module) {
684061da546Spatrick   Module.ParseAllDebugSymbols();
685061da546Spatrick 
686061da546Spatrick   SymbolFile *symfile = Module.GetSymbolFile();
687061da546Spatrick   if (!symfile)
688061da546Spatrick     return make_string_error("Module has no symbol file.");
689061da546Spatrick 
690*f6aab3d8Srobert   auto type_system_or_err =
691061da546Spatrick       symfile->GetTypeSystemForLanguage(eLanguageTypeObjC_plus_plus);
692061da546Spatrick   if (!type_system_or_err)
693dda28197Spatrick     return make_string_error("Can't retrieve TypeSystemClang");
694*f6aab3d8Srobert   auto ts = *type_system_or_err;
695*f6aab3d8Srobert   auto *clang_ast_ctx = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
696061da546Spatrick   if (!clang_ast_ctx)
697dda28197Spatrick     return make_string_error("Retrieved TypeSystem was not a TypeSystemClang");
698061da546Spatrick 
699061da546Spatrick   StreamString Stream;
700061da546Spatrick   clang_ast_ctx->DumpFromSymbolFile(Stream, Name);
701061da546Spatrick   outs() << Stream.GetData() << "\n";
702061da546Spatrick 
703061da546Spatrick   return Error::success();
704061da546Spatrick }
705061da546Spatrick 
verify(lldb_private::Module & Module)706061da546Spatrick Error opts::symbols::verify(lldb_private::Module &Module) {
707061da546Spatrick   SymbolFile *symfile = Module.GetSymbolFile();
708061da546Spatrick   if (!symfile)
709061da546Spatrick     return make_string_error("Module has no symbol file.");
710061da546Spatrick 
711061da546Spatrick   uint32_t comp_units_count = symfile->GetNumCompileUnits();
712061da546Spatrick 
713061da546Spatrick   outs() << "Found " << comp_units_count << " compile units.\n";
714061da546Spatrick 
715061da546Spatrick   for (uint32_t i = 0; i < comp_units_count; i++) {
716061da546Spatrick     lldb::CompUnitSP comp_unit = symfile->GetCompileUnitAtIndex(i);
717061da546Spatrick     if (!comp_unit)
718dda28197Spatrick       return make_string_error("Cannot parse compile unit {0}.", i);
719061da546Spatrick 
720061da546Spatrick     outs() << "Processing '"
721061da546Spatrick            << comp_unit->GetPrimaryFile().GetFilename().AsCString()
722061da546Spatrick            << "' compile unit.\n";
723061da546Spatrick 
724061da546Spatrick     LineTable *lt = comp_unit->GetLineTable();
725061da546Spatrick     if (!lt)
726061da546Spatrick       return make_string_error("Can't get a line table of a compile unit.");
727061da546Spatrick 
728061da546Spatrick     uint32_t count = lt->GetSize();
729061da546Spatrick 
730061da546Spatrick     outs() << "The line table contains " << count << " entries.\n";
731061da546Spatrick 
732061da546Spatrick     if (count == 0)
733061da546Spatrick       continue;
734061da546Spatrick 
735061da546Spatrick     LineEntry le;
736061da546Spatrick     if (!lt->GetLineEntryAtIndex(0, le))
737061da546Spatrick       return make_string_error("Can't get a line entry of a compile unit.");
738061da546Spatrick 
739061da546Spatrick     for (uint32_t i = 1; i < count; i++) {
740061da546Spatrick       lldb::addr_t curr_end =
741061da546Spatrick           le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
742061da546Spatrick 
743061da546Spatrick       if (!lt->GetLineEntryAtIndex(i, le))
744061da546Spatrick         return make_string_error("Can't get a line entry of a compile unit");
745061da546Spatrick 
746061da546Spatrick       if (curr_end > le.range.GetBaseAddress().GetFileAddress())
747061da546Spatrick         return make_string_error(
748061da546Spatrick             "Line table of a compile unit is inconsistent.");
749061da546Spatrick     }
750061da546Spatrick   }
751061da546Spatrick 
752061da546Spatrick   outs() << "The symbol information is verified.\n";
753061da546Spatrick 
754061da546Spatrick   return Error::success();
755061da546Spatrick }
756061da546Spatrick 
getAction()757061da546Spatrick Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
758061da546Spatrick   if (Verify && DumpAST)
759061da546Spatrick     return make_string_error(
760061da546Spatrick         "Cannot both verify symbol information and dump AST.");
761061da546Spatrick 
762061da546Spatrick   if (Verify) {
763061da546Spatrick     if (Find != FindType::None)
764061da546Spatrick       return make_string_error(
765061da546Spatrick           "Cannot both search and verify symbol information.");
766061da546Spatrick     if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
767061da546Spatrick         Line != 0)
768061da546Spatrick       return make_string_error(
769061da546Spatrick           "-regex, -context, -name, -file and -line options are not "
770061da546Spatrick           "applicable for symbol verification.");
771061da546Spatrick     return verify;
772061da546Spatrick   }
773061da546Spatrick 
774061da546Spatrick   if (DumpAST) {
775061da546Spatrick     if (Find != FindType::None)
776061da546Spatrick       return make_string_error("Cannot both search and dump AST.");
777061da546Spatrick     if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
778061da546Spatrick         Line != 0)
779061da546Spatrick       return make_string_error(
780061da546Spatrick           "-regex, -context, -name, -file and -line options are not "
781061da546Spatrick           "applicable for dumping AST.");
782061da546Spatrick     return dumpAST;
783061da546Spatrick   }
784061da546Spatrick 
785061da546Spatrick   if (DumpClangAST) {
786dda28197Spatrick     if (Find == FindType::None) {
787061da546Spatrick       if (Regex || !Context.empty() || !File.empty() || Line != 0)
788061da546Spatrick         return make_string_error(
789061da546Spatrick             "-regex, -context, -name, -file and -line options are not "
790dda28197Spatrick             "applicable for dumping the entire clang AST. Either combine with "
791dda28197Spatrick             "-find, or use -dump-clang-ast as a standalone option.");
792dda28197Spatrick       return dumpEntireClangAST;
793dda28197Spatrick     }
794dda28197Spatrick     if (Find != FindType::Type)
795dda28197Spatrick       return make_string_error("This combination of -dump-clang-ast and -find "
796dda28197Spatrick                                "<kind> is not yet implemented.");
797061da546Spatrick   }
798061da546Spatrick 
799061da546Spatrick   if (Regex && !Context.empty())
800061da546Spatrick     return make_string_error(
801061da546Spatrick         "Cannot search using both regular expressions and context.");
802061da546Spatrick 
803061da546Spatrick   if (Regex && !RegularExpression(Name).IsValid())
804061da546Spatrick     return make_string_error("`{0}` is not a valid regular expression.", Name);
805061da546Spatrick 
806061da546Spatrick   if (Regex + !Context.empty() + !File.empty() >= 2)
807061da546Spatrick     return make_string_error(
808061da546Spatrick         "Only one of -regex, -context and -file may be used simultaneously.");
809061da546Spatrick   if (Regex && Name.empty())
810061da546Spatrick     return make_string_error("-regex used without a -name");
811061da546Spatrick 
812061da546Spatrick   switch (Find) {
813061da546Spatrick   case FindType::None:
814061da546Spatrick     if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0)
815061da546Spatrick       return make_string_error(
816061da546Spatrick           "Specify search type (-find) to use search options.");
817061da546Spatrick     return dumpModule;
818061da546Spatrick 
819061da546Spatrick   case FindType::Function:
820061da546Spatrick     if (!File.empty() + (Line != 0) == 1)
821061da546Spatrick       return make_string_error("Both file name and line number must be "
822061da546Spatrick                                "specified when searching a function "
823061da546Spatrick                                "by file position.");
824061da546Spatrick     if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2)
825061da546Spatrick       return make_string_error("Only one of regular expression, function-flags "
826061da546Spatrick                                "and file position may be used simultaneously "
827061da546Spatrick                                "when searching a function.");
828061da546Spatrick     return findFunctions;
829061da546Spatrick 
830061da546Spatrick   case FindType::Block:
831061da546Spatrick     if (File.empty() || Line == 0)
832061da546Spatrick       return make_string_error("Both file name and line number must be "
833061da546Spatrick                                "specified when searching a block.");
834061da546Spatrick     if (Regex || getFunctionNameFlags() != 0)
835061da546Spatrick       return make_string_error("Cannot use regular expression or "
836061da546Spatrick                                "function-flags for searching a block.");
837061da546Spatrick     return findBlocks;
838061da546Spatrick 
839061da546Spatrick   case FindType::Namespace:
840061da546Spatrick     if (Regex || !File.empty() || Line != 0)
841061da546Spatrick       return make_string_error("Cannot search for namespaces using regular "
842061da546Spatrick                                "expressions, file names or line numbers.");
843061da546Spatrick     return findNamespaces;
844061da546Spatrick 
845061da546Spatrick   case FindType::Type:
846061da546Spatrick     if (Regex || !File.empty() || Line != 0)
847061da546Spatrick       return make_string_error("Cannot search for types using regular "
848061da546Spatrick                                "expressions, file names or line numbers.");
849061da546Spatrick     if (!Name.empty() && !CompilerContext.empty())
850061da546Spatrick       return make_string_error("Name is ignored if compiler context present.");
851061da546Spatrick 
852061da546Spatrick     return findTypes;
853061da546Spatrick 
854061da546Spatrick   case FindType::Variable:
855061da546Spatrick     if (Line != 0)
856061da546Spatrick       return make_string_error("Cannot search for variables "
857061da546Spatrick                                "using line numbers.");
858061da546Spatrick     return findVariables;
859061da546Spatrick   }
860061da546Spatrick 
861061da546Spatrick   llvm_unreachable("Unsupported symbol action.");
862061da546Spatrick }
863061da546Spatrick 
validate()864*f6aab3d8Srobert std::optional<llvm::Error> opts::symtab::validate() {
865*f6aab3d8Srobert   if (ManglingPreference != ManglingPreference::None &&
866*f6aab3d8Srobert       FindSymbolsByRegex.empty())
867*f6aab3d8Srobert     return make_string_error("Mangling preference set but no regex specified.");
868*f6aab3d8Srobert 
869*f6aab3d8Srobert   return {};
870*f6aab3d8Srobert }
871*f6aab3d8Srobert 
getNamePreference()872*f6aab3d8Srobert static Mangled::NamePreference opts::symtab::getNamePreference() {
873*f6aab3d8Srobert   switch (ManglingPreference) {
874*f6aab3d8Srobert   case ManglingPreference::None:
875*f6aab3d8Srobert   case ManglingPreference::Mangled:
876*f6aab3d8Srobert     return Mangled::ePreferMangled;
877*f6aab3d8Srobert   case ManglingPreference::Demangled:
878*f6aab3d8Srobert     return Mangled::ePreferDemangled;
879*f6aab3d8Srobert   case ManglingPreference::MangledWithoutArguments:
880*f6aab3d8Srobert     return Mangled::ePreferDemangledWithoutArguments;
881*f6aab3d8Srobert   }
882*f6aab3d8Srobert   llvm_unreachable("Fully covered switch above!");
883*f6aab3d8Srobert }
884*f6aab3d8Srobert 
handleSymtabCommand(Debugger & Dbg)885*f6aab3d8Srobert int opts::symtab::handleSymtabCommand(Debugger &Dbg) {
886*f6aab3d8Srobert   if (auto error = validate()) {
887*f6aab3d8Srobert     logAllUnhandledErrors(std::move(*error), WithColor::error(), "");
888*f6aab3d8Srobert     return 1;
889*f6aab3d8Srobert   }
890*f6aab3d8Srobert 
891*f6aab3d8Srobert   if (!FindSymbolsByRegex.empty()) {
892*f6aab3d8Srobert     ModuleSpec Spec{FileSpec(InputFile)};
893*f6aab3d8Srobert 
894*f6aab3d8Srobert     auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
895*f6aab3d8Srobert     auto *Symtab = ModulePtr->GetSymtab();
896*f6aab3d8Srobert     auto NamePreference = getNamePreference();
897*f6aab3d8Srobert     std::vector<uint32_t> Indexes;
898*f6aab3d8Srobert 
899*f6aab3d8Srobert     Symtab->FindAllSymbolsMatchingRexExAndType(
900*f6aab3d8Srobert         RegularExpression(FindSymbolsByRegex), lldb::eSymbolTypeAny,
901*f6aab3d8Srobert         Symtab::eDebugAny, Symtab::eVisibilityAny, Indexes, NamePreference);
902*f6aab3d8Srobert     for (auto i : Indexes) {
903*f6aab3d8Srobert       auto *symbol = Symtab->SymbolAtIndex(i);
904*f6aab3d8Srobert       if (symbol) {
905*f6aab3d8Srobert         StreamString stream;
906*f6aab3d8Srobert         symbol->Dump(&stream, nullptr, i, NamePreference);
907*f6aab3d8Srobert         outs() << stream.GetString();
908*f6aab3d8Srobert       }
909*f6aab3d8Srobert     }
910*f6aab3d8Srobert   }
911*f6aab3d8Srobert 
912*f6aab3d8Srobert   return 0;
913*f6aab3d8Srobert }
914*f6aab3d8Srobert 
dumpSymbols(Debugger & Dbg)915061da546Spatrick int opts::symbols::dumpSymbols(Debugger &Dbg) {
916061da546Spatrick   auto ActionOr = getAction();
917061da546Spatrick   if (!ActionOr) {
918061da546Spatrick     logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), "");
919061da546Spatrick     return 1;
920061da546Spatrick   }
921061da546Spatrick   auto Action = *ActionOr;
922061da546Spatrick 
923061da546Spatrick   outs() << "Module: " << InputFile << "\n";
924061da546Spatrick   ModuleSpec Spec{FileSpec(InputFile)};
925061da546Spatrick   StringRef Symbols = SymbolPath.empty() ? InputFile : SymbolPath;
926061da546Spatrick   Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native);
927061da546Spatrick 
928061da546Spatrick   auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
929061da546Spatrick   SymbolFile *Symfile = ModulePtr->GetSymbolFile();
930061da546Spatrick   if (!Symfile) {
931061da546Spatrick     WithColor::error() << "Module has no symbol vendor.\n";
932061da546Spatrick     return 1;
933061da546Spatrick   }
934061da546Spatrick 
935061da546Spatrick   if (Error E = Action(*ModulePtr)) {
936061da546Spatrick     WithColor::error() << toString(std::move(E)) << "\n";
937061da546Spatrick     return 1;
938061da546Spatrick   }
939061da546Spatrick 
940061da546Spatrick   return 0;
941061da546Spatrick }
942061da546Spatrick 
dumpSectionList(LinePrinter & Printer,const SectionList & List,bool is_subsection)943061da546Spatrick static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) {
944061da546Spatrick   size_t Count = List.GetNumSections(0);
945061da546Spatrick   if (Count == 0) {
946061da546Spatrick     Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : "");
947061da546Spatrick     return;
948061da546Spatrick   }
949061da546Spatrick   Printer.formatLine("Showing {0} {1}sections", Count,
950061da546Spatrick                      is_subsection ? "sub" : "");
951061da546Spatrick   for (size_t I = 0; I < Count; ++I) {
952061da546Spatrick     auto S = List.GetSectionAtIndex(I);
953061da546Spatrick     assert(S);
954061da546Spatrick     AutoIndent Indent(Printer, 2);
955061da546Spatrick     Printer.formatLine("Index: {0}", I);
956061da546Spatrick     Printer.formatLine("ID: {0:x}", S->GetID());
957061da546Spatrick     Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
958061da546Spatrick     Printer.formatLine("Type: {0}", S->GetTypeAsCString());
959061da546Spatrick     Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions()));
960061da546Spatrick     Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific());
961061da546Spatrick     Printer.formatLine("VM address: {0:x}", S->GetFileAddress());
962061da546Spatrick     Printer.formatLine("VM size: {0}", S->GetByteSize());
963061da546Spatrick     Printer.formatLine("File size: {0}", S->GetFileSize());
964061da546Spatrick 
965061da546Spatrick     if (opts::object::SectionContents) {
966061da546Spatrick       lldb_private::DataExtractor Data;
967061da546Spatrick       S->GetSectionData(Data);
968dda28197Spatrick       ArrayRef<uint8_t> Bytes(Data.GetDataStart(), Data.GetDataEnd());
969061da546Spatrick       Printer.formatBinary("Data: ", Bytes, 0);
970061da546Spatrick     }
971061da546Spatrick 
972061da546Spatrick     if (S->GetType() == eSectionTypeContainer)
973061da546Spatrick       dumpSectionList(Printer, S->GetChildren(), true);
974061da546Spatrick     Printer.NewLine();
975061da546Spatrick   }
976061da546Spatrick }
977061da546Spatrick 
dumpObjectFiles(Debugger & Dbg)978061da546Spatrick static int dumpObjectFiles(Debugger &Dbg) {
979061da546Spatrick   LinePrinter Printer(4, llvm::outs());
980061da546Spatrick 
981061da546Spatrick   int HadErrors = 0;
982061da546Spatrick   for (const auto &File : opts::object::InputFilenames) {
983061da546Spatrick     ModuleSpec Spec{FileSpec(File)};
984061da546Spatrick 
985061da546Spatrick     auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
986061da546Spatrick 
987061da546Spatrick     ObjectFile *ObjectPtr = ModulePtr->GetObjectFile();
988061da546Spatrick     if (!ObjectPtr) {
989061da546Spatrick       WithColor::error() << File << " not recognised as an object file\n";
990061da546Spatrick       HadErrors = 1;
991061da546Spatrick       continue;
992061da546Spatrick     }
993061da546Spatrick 
994061da546Spatrick     // Fetch symbol vendor before we get the section list to give the symbol
995061da546Spatrick     // vendor a chance to populate it.
996061da546Spatrick     ModulePtr->GetSymbolFile();
997061da546Spatrick     SectionList *Sections = ModulePtr->GetSectionList();
998061da546Spatrick     if (!Sections) {
999061da546Spatrick       llvm::errs() << "Could not load sections for module " << File << "\n";
1000061da546Spatrick       HadErrors = 1;
1001061da546Spatrick       continue;
1002061da546Spatrick     }
1003061da546Spatrick 
1004061da546Spatrick     Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName());
1005061da546Spatrick     Printer.formatLine("Architecture: {0}",
1006061da546Spatrick                        ModulePtr->GetArchitecture().GetTriple().getTriple());
1007061da546Spatrick     Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
1008061da546Spatrick     Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable());
1009061da546Spatrick     Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped());
1010061da546Spatrick     Printer.formatLine("Type: {0}", ObjectPtr->GetType());
1011061da546Spatrick     Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata());
1012061da546Spatrick     Printer.formatLine("Base VM address: {0:x}",
1013061da546Spatrick                        ObjectPtr->GetBaseAddress().GetFileAddress());
1014061da546Spatrick 
1015061da546Spatrick     dumpSectionList(Printer, *Sections, /*is_subsection*/ false);
1016061da546Spatrick 
1017061da546Spatrick     if (opts::object::SectionDependentModules) {
1018061da546Spatrick       // A non-empty section list ensures a valid object file.
1019061da546Spatrick       auto Obj = ModulePtr->GetObjectFile();
1020061da546Spatrick       FileSpecList Files;
1021061da546Spatrick       auto Count = Obj->GetDependentModules(Files);
1022061da546Spatrick       Printer.formatLine("Showing {0} dependent module(s)", Count);
1023061da546Spatrick       for (size_t I = 0; I < Files.GetSize(); ++I) {
1024061da546Spatrick         AutoIndent Indent(Printer, 2);
1025061da546Spatrick         Printer.formatLine("Name: {0}",
1026*f6aab3d8Srobert                            Files.GetFileSpecAtIndex(I).GetPath());
1027061da546Spatrick       }
1028061da546Spatrick       Printer.NewLine();
1029061da546Spatrick     }
1030061da546Spatrick   }
1031061da546Spatrick   return HadErrors;
1032061da546Spatrick }
1033061da546Spatrick 
evalMalloc(StringRef Line,IRMemoryMapTestState & State)1034061da546Spatrick bool opts::irmemorymap::evalMalloc(StringRef Line,
1035061da546Spatrick                                    IRMemoryMapTestState &State) {
1036061da546Spatrick   // ::= <label> = malloc <size> <alignment>
1037061da546Spatrick   StringRef Label;
1038061da546Spatrick   std::tie(Label, Line) = Line.split('=');
1039061da546Spatrick   if (Line.empty())
1040061da546Spatrick     return false;
1041061da546Spatrick   Label = Label.trim();
1042061da546Spatrick   Line = Line.trim();
1043061da546Spatrick   size_t Size;
1044061da546Spatrick   uint8_t Alignment;
1045061da546Spatrick   int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment);
1046061da546Spatrick   if (Matches != 2)
1047061da546Spatrick     return false;
1048061da546Spatrick 
1049061da546Spatrick   outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label,
1050061da546Spatrick                     Size, Alignment);
1051061da546Spatrick   if (!isPowerOf2_32(Alignment)) {
1052061da546Spatrick     outs() << "Malloc error: alignment is not a power of 2\n";
1053061da546Spatrick     exit(1);
1054061da546Spatrick   }
1055061da546Spatrick 
1056061da546Spatrick   IRMemoryMap::AllocationPolicy AP =
1057061da546Spatrick       UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly
1058061da546Spatrick                                   : IRMemoryMap::eAllocationPolicyProcessOnly;
1059061da546Spatrick 
1060061da546Spatrick   // Issue the malloc in the target process with "-rw" permissions.
1061061da546Spatrick   const uint32_t Permissions = 0x3;
1062061da546Spatrick   const bool ZeroMemory = false;
1063061da546Spatrick   Status ST;
1064061da546Spatrick   addr_t Addr =
1065061da546Spatrick       State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST);
1066061da546Spatrick   if (ST.Fail()) {
1067061da546Spatrick     outs() << formatv("Malloc error: {0}\n", ST);
1068061da546Spatrick     return true;
1069061da546Spatrick   }
1070061da546Spatrick 
1071061da546Spatrick   // Print the result of the allocation before checking its validity.
1072061da546Spatrick   outs() << formatv("Malloc: address = {0:x}\n", Addr);
1073061da546Spatrick 
1074061da546Spatrick   // Check that the allocation is aligned.
1075061da546Spatrick   if (!Addr || Addr % Alignment != 0) {
1076061da546Spatrick     outs() << "Malloc error: zero or unaligned allocation detected\n";
1077061da546Spatrick     exit(1);
1078061da546Spatrick   }
1079061da546Spatrick 
1080061da546Spatrick   // In case of Size == 0, we still expect the returned address to be unique and
1081061da546Spatrick   // non-overlapping.
1082061da546Spatrick   addr_t EndOfRegion = Addr + std::max<size_t>(Size, 1);
1083061da546Spatrick   if (State.Allocations.overlaps(Addr, EndOfRegion)) {
1084061da546Spatrick     auto I = State.Allocations.find(Addr);
1085061da546Spatrick     outs() << "Malloc error: overlapping allocation detected"
1086061da546Spatrick            << formatv(", previous allocation at [{0:x}, {1:x})\n", I.start(),
1087061da546Spatrick                       I.stop());
1088061da546Spatrick     exit(1);
1089061da546Spatrick   }
1090061da546Spatrick 
1091061da546Spatrick   // Insert the new allocation into the interval map. Use unique allocation
1092061da546Spatrick   // IDs to inhibit interval coalescing.
1093061da546Spatrick   static unsigned AllocationID = 0;
1094061da546Spatrick   State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
1095061da546Spatrick 
1096061da546Spatrick   // Store the label -> address mapping.
1097061da546Spatrick   State.Label2AddrMap[Label] = Addr;
1098061da546Spatrick 
1099061da546Spatrick   return true;
1100061da546Spatrick }
1101061da546Spatrick 
evalFree(StringRef Line,IRMemoryMapTestState & State)1102061da546Spatrick bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) {
1103061da546Spatrick   // ::= free <label>
1104061da546Spatrick   if (!Line.consume_front("free"))
1105061da546Spatrick     return false;
1106061da546Spatrick   StringRef Label = Line.trim();
1107061da546Spatrick 
1108061da546Spatrick   outs() << formatv("Command: free({0})\n", Label);
1109061da546Spatrick   auto LabelIt = State.Label2AddrMap.find(Label);
1110061da546Spatrick   if (LabelIt == State.Label2AddrMap.end()) {
1111061da546Spatrick     outs() << "Free error: Invalid allocation label\n";
1112061da546Spatrick     exit(1);
1113061da546Spatrick   }
1114061da546Spatrick 
1115061da546Spatrick   Status ST;
1116061da546Spatrick   addr_t Addr = LabelIt->getValue();
1117061da546Spatrick   State.Map.Free(Addr, ST);
1118061da546Spatrick   if (ST.Fail()) {
1119061da546Spatrick     outs() << formatv("Free error: {0}\n", ST);
1120061da546Spatrick     exit(1);
1121061da546Spatrick   }
1122061da546Spatrick 
1123061da546Spatrick   // Erase the allocation from the live interval map.
1124061da546Spatrick   auto Interval = State.Allocations.find(Addr);
1125061da546Spatrick   if (Interval != State.Allocations.end()) {
1126061da546Spatrick     outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(),
1127061da546Spatrick                       Interval.stop());
1128061da546Spatrick     Interval.erase();
1129061da546Spatrick   }
1130061da546Spatrick 
1131061da546Spatrick   return true;
1132061da546Spatrick }
1133061da546Spatrick 
evaluateMemoryMapCommands(Debugger & Dbg)1134061da546Spatrick int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
1135061da546Spatrick   // Set up a Target.
1136061da546Spatrick   TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target);
1137061da546Spatrick 
1138061da546Spatrick   // Set up a Process. In order to allocate memory within a target, this
1139061da546Spatrick   // process must be alive and must support JIT'ing.
1140dda28197Spatrick   CommandReturnObject Result(/*colors*/ false);
1141061da546Spatrick   Dbg.SetAsyncExecution(false);
1142061da546Spatrick   CommandInterpreter &CI = Dbg.GetCommandInterpreter();
1143061da546Spatrick   auto IssueCmd = [&](const char *Cmd) -> bool {
1144061da546Spatrick     return CI.HandleCommand(Cmd, eLazyBoolNo, Result);
1145061da546Spatrick   };
1146061da546Spatrick   if (!IssueCmd("b main") || !IssueCmd("run")) {
1147061da546Spatrick     outs() << formatv("Failed: {0}\n", Result.GetErrorData());
1148061da546Spatrick     exit(1);
1149061da546Spatrick   }
1150061da546Spatrick 
1151061da546Spatrick   ProcessSP Process = Target->GetProcessSP();
1152061da546Spatrick   if (!Process || !Process->IsAlive() || !Process->CanJIT()) {
1153061da546Spatrick     outs() << "Cannot use process to test IRMemoryMap\n";
1154061da546Spatrick     exit(1);
1155061da546Spatrick   }
1156061da546Spatrick 
1157061da546Spatrick   // Set up an IRMemoryMap and associated testing state.
1158061da546Spatrick   IRMemoryMapTestState State(Target);
1159061da546Spatrick 
1160061da546Spatrick   // Parse and apply commands from the command file.
1161061da546Spatrick   std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile);
1162061da546Spatrick   StringRef Rest = MB->getBuffer();
1163061da546Spatrick   while (!Rest.empty()) {
1164061da546Spatrick     StringRef Line;
1165061da546Spatrick     std::tie(Line, Rest) = Rest.split('\n');
1166061da546Spatrick     Line = Line.ltrim().rtrim();
1167061da546Spatrick 
1168061da546Spatrick     if (Line.empty() || Line[0] == '#')
1169061da546Spatrick       continue;
1170061da546Spatrick 
1171061da546Spatrick     if (evalMalloc(Line, State))
1172061da546Spatrick       continue;
1173061da546Spatrick 
1174061da546Spatrick     if (evalFree(Line, State))
1175061da546Spatrick       continue;
1176061da546Spatrick 
1177061da546Spatrick     errs() << "Could not parse line: " << Line << "\n";
1178061da546Spatrick     exit(1);
1179061da546Spatrick   }
1180061da546Spatrick   return 0;
1181061da546Spatrick }
1182061da546Spatrick 
lldb_assert(Debugger & Dbg)1183be691f3bSpatrick int opts::assert::lldb_assert(Debugger &Dbg) {
1184be691f3bSpatrick   lldbassert(false && "lldb-test assert");
1185be691f3bSpatrick   return 1;
1186be691f3bSpatrick }
1187be691f3bSpatrick 
main(int argc,const char * argv[])1188061da546Spatrick int main(int argc, const char *argv[]) {
1189061da546Spatrick   StringRef ToolName = argv[0];
1190061da546Spatrick   sys::PrintStackTraceOnErrorSignal(ToolName);
1191061da546Spatrick   PrettyStackTraceProgram X(argc, argv);
1192061da546Spatrick   llvm_shutdown_obj Y;
1193061da546Spatrick 
1194061da546Spatrick   cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
1195061da546Spatrick 
1196061da546Spatrick   SystemLifetimeManager DebuggerLifetime;
1197061da546Spatrick   if (auto e = DebuggerLifetime.Initialize(
1198061da546Spatrick           std::make_unique<SystemInitializerTest>(), nullptr)) {
1199061da546Spatrick     WithColor::error() << "initialization failed: " << toString(std::move(e))
1200061da546Spatrick                        << '\n';
1201061da546Spatrick     return 1;
1202061da546Spatrick   }
1203061da546Spatrick 
1204061da546Spatrick   auto TerminateDebugger =
1205061da546Spatrick       llvm::make_scope_exit([&] { DebuggerLifetime.Terminate(); });
1206061da546Spatrick 
1207061da546Spatrick   auto Dbg = lldb_private::Debugger::CreateInstance();
1208061da546Spatrick   ModuleList::GetGlobalModuleListProperties().SetEnableExternalLookup(false);
1209dda28197Spatrick   CommandReturnObject Result(/*colors*/ false);
1210061da546Spatrick   Dbg->GetCommandInterpreter().HandleCommand(
1211061da546Spatrick       "settings set plugin.process.gdb-remote.packet-timeout 60",
1212061da546Spatrick       /*add_to_history*/ eLazyBoolNo, Result);
1213be691f3bSpatrick   Dbg->GetCommandInterpreter().HandleCommand(
1214be691f3bSpatrick       "settings set target.inherit-tcc true",
1215be691f3bSpatrick       /*add_to_history*/ eLazyBoolNo, Result);
1216be691f3bSpatrick   Dbg->GetCommandInterpreter().HandleCommand(
1217be691f3bSpatrick       "settings set target.detach-on-error false",
1218be691f3bSpatrick       /*add_to_history*/ eLazyBoolNo, Result);
1219061da546Spatrick 
1220061da546Spatrick   if (!opts::Log.empty())
1221*f6aab3d8Srobert     Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, 0, eLogHandlerStream, errs());
1222061da546Spatrick 
1223061da546Spatrick   if (opts::BreakpointSubcommand)
1224061da546Spatrick     return opts::breakpoint::evaluateBreakpoints(*Dbg);
1225061da546Spatrick   if (opts::ObjectFileSubcommand)
1226061da546Spatrick     return dumpObjectFiles(*Dbg);
1227061da546Spatrick   if (opts::SymbolsSubcommand)
1228061da546Spatrick     return opts::symbols::dumpSymbols(*Dbg);
1229*f6aab3d8Srobert   if (opts::SymTabSubcommand)
1230*f6aab3d8Srobert     return opts::symtab::handleSymtabCommand(*Dbg);
1231061da546Spatrick   if (opts::IRMemoryMapSubcommand)
1232061da546Spatrick     return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
1233be691f3bSpatrick   if (opts::AssertSubcommand)
1234be691f3bSpatrick     return opts::assert::lldb_assert(*Dbg);
1235061da546Spatrick 
1236061da546Spatrick   WithColor::error() << "No command specified.\n";
1237061da546Spatrick   return 1;
1238061da546Spatrick }
1239