blob: 112c2fa87640443e9fc66f039a2cacffd7654426 [file] [log] [blame]
Zachary Turner888a4282017-12-01 00:52:51 +00001//===- lldb-test.cpp ------------------------------------------ *- C++ --*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Zachary Turner888a4282017-12-01 00:52:51 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "FormatUtil.h"
10#include "SystemInitializerTest.h"
11
Zachary Turnera6d54642017-12-02 00:15:29 +000012#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
Pavel Labath7c945822018-02-26 18:50:16 +000013#include "lldb/Breakpoint/BreakpointLocation.h"
Zachary Turner888a4282017-12-01 00:52:51 +000014#include "lldb/Core/Debugger.h"
15#include "lldb/Core/Module.h"
16#include "lldb/Core/Section.h"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000017#include "lldb/Expression/IRMemoryMap.h"
Zachary Turner888a4282017-12-01 00:52:51 +000018#include "lldb/Initialization/SystemLifetimeManager.h"
Pavel Labath7c945822018-02-26 18:50:16 +000019#include "lldb/Interpreter/CommandInterpreter.h"
20#include "lldb/Interpreter/CommandReturnObject.h"
Zachary Turnera6d54642017-12-02 00:15:29 +000021#include "lldb/Symbol/ClangASTContext.h"
22#include "lldb/Symbol/ClangASTImporter.h"
Aaron Smith010edd32018-06-08 02:45:25 +000023#include "lldb/Symbol/CompileUnit.h"
24#include "lldb/Symbol/LineTable.h"
Pavel Labath465eae32019-08-06 09:12:42 +000025#include "lldb/Symbol/SymbolFile.h"
Pavel Labath90b0a532018-05-03 10:57:16 +000026#include "lldb/Symbol/TypeList.h"
Pavel Labath465eae32019-08-06 09:12:42 +000027#include "lldb/Symbol/TypeMap.h"
Pavel Labath90b0a532018-05-03 10:57:16 +000028#include "lldb/Symbol/VariableList.h"
Adrian Prantlaa97a892019-08-22 21:45:58 +000029#include "lldb/Target/Language.h"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000030#include "lldb/Target/Process.h"
31#include "lldb/Target/Target.h"
Zachary Turner888a4282017-12-01 00:52:51 +000032#include "lldb/Utility/DataExtractor.h"
Pavel Labath62a82542018-12-15 13:45:38 +000033#include "lldb/Utility/State.h"
Zachary Turnera6d54642017-12-02 00:15:29 +000034#include "lldb/Utility/StreamString.h"
Zachary Turner888a4282017-12-01 00:52:51 +000035
Vedant Kumarc1cd8262018-05-30 19:39:10 +000036#include "llvm/ADT/IntervalMap.h"
Jonas Devliegheree0ea8d82019-09-10 00:20:50 +000037#include "llvm/ADT/ScopeExit.h"
Zachary Turner888a4282017-12-01 00:52:51 +000038#include "llvm/ADT/StringRef.h"
39#include "llvm/Support/CommandLine.h"
40#include "llvm/Support/ManagedStatic.h"
Pavel Labath9ea80d22018-06-28 10:03:42 +000041#include "llvm/Support/MathExtras.h"
Pavel Labath7c945822018-02-26 18:50:16 +000042#include "llvm/Support/Path.h"
Zachary Turner888a4282017-12-01 00:52:51 +000043#include "llvm/Support/PrettyStackTrace.h"
44#include "llvm/Support/Signals.h"
Pavel Labath90b0a532018-05-03 10:57:16 +000045#include "llvm/Support/WithColor.h"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000046#include <cstdio>
Zachary Turner888a4282017-12-01 00:52:51 +000047#include <thread>
48
49using namespace lldb;
50using namespace lldb_private;
51using namespace llvm;
52
53namespace opts {
Pavel Labath7c945822018-02-26 18:50:16 +000054static cl::SubCommand BreakpointSubcommand("breakpoints",
55 "Test breakpoint resolution");
Pavel Labath62a7f802018-06-29 12:15:54 +000056cl::SubCommand ObjectFileSubcommand("object-file",
57 "Display LLDB object file information");
Zachary Turnera6d54642017-12-02 00:15:29 +000058cl::SubCommand SymbolsSubcommand("symbols", "Dump symbols for an object file");
Vedant Kumarc1cd8262018-05-30 19:39:10 +000059cl::SubCommand IRMemoryMapSubcommand("ir-memory-map", "Test IRMemoryMap");
Vedant Kumar7e4c84a2018-05-31 22:09:00 +000060
Vedant Kumarc1cd8262018-05-30 19:39:10 +000061cl::opt<std::string> Log("log", cl::desc("Path to a log file"), cl::init(""),
Vedant Kumar7e4c84a2018-05-31 22:09:00 +000062 cl::sub(BreakpointSubcommand),
Pavel Labath62a7f802018-06-29 12:15:54 +000063 cl::sub(ObjectFileSubcommand),
64 cl::sub(SymbolsSubcommand),
Vedant Kumarc1cd8262018-05-30 19:39:10 +000065 cl::sub(IRMemoryMapSubcommand));
66
67/// Create a target using the file pointed to by \p Filename, or abort.
68TargetSP createTarget(Debugger &Dbg, const std::string &Filename);
69
70/// Read \p Filename into a null-terminated buffer, or abort.
71std::unique_ptr<MemoryBuffer> openFile(const std::string &Filename);
Zachary Turner888a4282017-12-01 00:52:51 +000072
Pavel Labath7c945822018-02-26 18:50:16 +000073namespace breakpoint {
74static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
75 cl::Required, cl::sub(BreakpointSubcommand));
76static cl::opt<std::string> CommandFile(cl::Positional,
77 cl::desc("<command-file>"),
78 cl::init("-"),
79 cl::sub(BreakpointSubcommand));
80static cl::opt<bool> Persistent(
81 "persistent",
82 cl::desc("Don't automatically remove all breakpoints before each command"),
83 cl::sub(BreakpointSubcommand));
84
85static llvm::StringRef plural(uintmax_t value) { return value == 1 ? "" : "s"; }
86static void dumpState(const BreakpointList &List, LinePrinter &P);
87static std::string substitute(StringRef Cmd);
Pavel Labath90b0a532018-05-03 10:57:16 +000088static int evaluateBreakpoints(Debugger &Dbg);
Pavel Labath7c945822018-02-26 18:50:16 +000089} // namespace breakpoint
90
Pavel Labath62a7f802018-06-29 12:15:54 +000091namespace object {
Zachary Turner888a4282017-12-01 00:52:51 +000092cl::opt<bool> SectionContents("contents",
93 cl::desc("Dump each section's contents"),
Pavel Labath62a7f802018-06-29 12:15:54 +000094 cl::sub(ObjectFileSubcommand));
Aaron Smith037ed1b2018-12-06 21:36:39 +000095cl::opt<bool> SectionDependentModules("dep-modules",
96 cl::desc("Dump each dependent module"),
97 cl::sub(ObjectFileSubcommand));
Zachary Turner888a4282017-12-01 00:52:51 +000098cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
Pavel Labath62a7f802018-06-29 12:15:54 +000099 cl::OneOrMore,
100 cl::sub(ObjectFileSubcommand));
101} // namespace object
Zachary Turnera6d54642017-12-02 00:15:29 +0000102
103namespace symbols {
Pavel Labath1cf23e12019-01-11 11:17:51 +0000104static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
105 cl::Required, cl::sub(SymbolsSubcommand));
106
107static cl::opt<std::string>
108 SymbolPath("symbol-file",
109 cl::desc("The file from which to fetch symbol information."),
110 cl::value_desc("file"), cl::sub(SymbolsSubcommand));
111
Pavel Labath90b0a532018-05-03 10:57:16 +0000112enum class FindType {
113 None,
114 Function,
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000115 Block,
Pavel Labath90b0a532018-05-03 10:57:16 +0000116 Namespace,
117 Type,
118 Variable,
119};
120static cl::opt<FindType> Find(
121 "find", cl::desc("Choose search type:"),
122 cl::values(
Pavel Labath9ea80d22018-06-28 10:03:42 +0000123 clEnumValN(FindType::None, "none", "No search, just dump the module."),
Pavel Labath90b0a532018-05-03 10:57:16 +0000124 clEnumValN(FindType::Function, "function", "Find functions."),
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000125 clEnumValN(FindType::Block, "block", "Find blocks."),
Pavel Labath90b0a532018-05-03 10:57:16 +0000126 clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
127 clEnumValN(FindType::Type, "type", "Find types."),
128 clEnumValN(FindType::Variable, "variable", "Find global variables.")),
129 cl::sub(SymbolsSubcommand));
130
131static cl::opt<std::string> Name("name", cl::desc("Name to find."),
132 cl::sub(SymbolsSubcommand));
133static cl::opt<bool>
134 Regex("regex",
135 cl::desc("Search using regular expressions (avaliable for variables "
136 "and functions only)."),
137 cl::sub(SymbolsSubcommand));
138static cl::opt<std::string>
139 Context("context",
140 cl::desc("Restrict search to the context of the given variable."),
141 cl::value_desc("variable"), cl::sub(SymbolsSubcommand));
142
Adrian Prantl260aa0f2019-08-20 16:44:25 +0000143static cl::opt<std::string> CompilerContext(
144 "compiler-context",
145 cl::desc("Specify a compiler context as \"kind:name,...\"."),
146 cl::value_desc("context"), cl::sub(SymbolsSubcommand));
147
Adrian Prantlaa97a892019-08-22 21:45:58 +0000148static cl::opt<std::string>
149 Language("language", cl::desc("Specify a language type, like C99."),
150 cl::value_desc("language"), cl::sub(SymbolsSubcommand));
151
Pavel Labath90b0a532018-05-03 10:57:16 +0000152static cl::list<FunctionNameType> FunctionNameFlags(
153 "function-flags", cl::desc("Function search flags:"),
154 cl::values(clEnumValN(eFunctionNameTypeAuto, "auto",
155 "Automatically deduce flags based on name."),
156 clEnumValN(eFunctionNameTypeFull, "full", "Full function name."),
157 clEnumValN(eFunctionNameTypeBase, "base", "Base name."),
158 clEnumValN(eFunctionNameTypeMethod, "method", "Method name."),
159 clEnumValN(eFunctionNameTypeSelector, "selector",
160 "Selector name.")),
161 cl::sub(SymbolsSubcommand));
162static FunctionNameType getFunctionNameFlags() {
163 FunctionNameType Result = FunctionNameType(0);
164 for (FunctionNameType Flag : FunctionNameFlags)
165 Result = FunctionNameType(Result | Flag);
166 return Result;
167}
168
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000169static cl::opt<bool> DumpAST("dump-ast",
170 cl::desc("Dump AST restored from symbols."),
171 cl::sub(SymbolsSubcommand));
172
Aaron Smith010edd32018-06-08 02:45:25 +0000173static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
174 cl::sub(SymbolsSubcommand));
175
Pavel Labathe6954cb2018-06-12 12:57:36 +0000176static cl::opt<std::string> File("file",
177 cl::desc("File (compile unit) to search."),
178 cl::sub(SymbolsSubcommand));
Pavel Labath9ea80d22018-06-28 10:03:42 +0000179static cl::opt<int> Line("line", cl::desc("Line to search."),
180 cl::sub(SymbolsSubcommand));
Pavel Labathe6954cb2018-06-12 12:57:36 +0000181
Pavel Labath465eae32019-08-06 09:12:42 +0000182static Expected<CompilerDeclContext> getDeclContext(SymbolFile &Symfile);
Pavel Labath90b0a532018-05-03 10:57:16 +0000183
184static Error findFunctions(lldb_private::Module &Module);
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000185static Error findBlocks(lldb_private::Module &Module);
Pavel Labath90b0a532018-05-03 10:57:16 +0000186static Error findNamespaces(lldb_private::Module &Module);
187static Error findTypes(lldb_private::Module &Module);
188static Error findVariables(lldb_private::Module &Module);
189static Error dumpModule(lldb_private::Module &Module);
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000190static Error dumpAST(lldb_private::Module &Module);
Aaron Smith010edd32018-06-08 02:45:25 +0000191static Error verify(lldb_private::Module &Module);
Pavel Labath90b0a532018-05-03 10:57:16 +0000192
Pavel Labath38d9ff72018-06-12 13:26:43 +0000193static Expected<Error (*)(lldb_private::Module &)> getAction();
Pavel Labath90b0a532018-05-03 10:57:16 +0000194static int dumpSymbols(Debugger &Dbg);
Pavel Labath9ea80d22018-06-28 10:03:42 +0000195} // namespace symbols
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000196
197namespace irmemorymap {
198static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
199 cl::Required,
200 cl::sub(IRMemoryMapSubcommand));
201static cl::opt<std::string> CommandFile(cl::Positional,
202 cl::desc("<command-file>"),
203 cl::init("-"),
204 cl::sub(IRMemoryMapSubcommand));
Vedant Kumarf616b9d2018-05-31 22:09:00 +0000205static cl::opt<bool> UseHostOnlyAllocationPolicy(
206 "host-only", cl::desc("Use the host-only allocation policy"),
207 cl::init(false), cl::sub(IRMemoryMapSubcommand));
208
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000209using AllocationT = std::pair<addr_t, addr_t>;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000210using AddrIntervalMap =
Pavel Labath9ea80d22018-06-28 10:03:42 +0000211 IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000212
213struct IRMemoryMapTestState {
214 TargetSP Target;
215 IRMemoryMap Map;
216
217 AddrIntervalMap::Allocator IntervalMapAllocator;
218 AddrIntervalMap Allocations;
219
220 StringMap<addr_t> Label2AddrMap;
221
222 IRMemoryMapTestState(TargetSP Target)
223 : Target(Target), Map(Target), Allocations(IntervalMapAllocator) {}
224};
225
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000226bool evalMalloc(StringRef Line, IRMemoryMapTestState &State);
227bool evalFree(StringRef Line, IRMemoryMapTestState &State);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000228int evaluateMemoryMapCommands(Debugger &Dbg);
229} // namespace irmemorymap
230
Zachary Turner888a4282017-12-01 00:52:51 +0000231} // namespace opts
232
Adrian Prantl260aa0f2019-08-20 16:44:25 +0000233std::vector<CompilerContext> parseCompilerContext() {
234 std::vector<CompilerContext> result;
235 if (opts::symbols::CompilerContext.empty())
236 return result;
237
238 StringRef str{opts::symbols::CompilerContext};
239 SmallVector<StringRef, 8> entries_str;
240 str.split(entries_str, ',', /*maxSplit*/-1, /*keepEmpty=*/false);
241 for (auto entry_str : entries_str) {
242 StringRef key, value;
243 std::tie(key, value) = entry_str.split(':');
244 auto kind =
245 StringSwitch<CompilerContextKind>(key)
246 .Case("TranslationUnit", CompilerContextKind::TranslationUnit)
247 .Case("Module", CompilerContextKind::Module)
248 .Case("Namespace", CompilerContextKind::Namespace)
249 .Case("Class", CompilerContextKind::Class)
Adrian Prantl330ae19a2019-08-21 18:06:56 +0000250 .Case("Struct", CompilerContextKind::Struct)
Adrian Prantl260aa0f2019-08-20 16:44:25 +0000251 .Case("Union", CompilerContextKind::Union)
252 .Case("Function", CompilerContextKind::Function)
253 .Case("Variable", CompilerContextKind::Variable)
Adrian Prantl330ae19a2019-08-21 18:06:56 +0000254 .Case("Enum", CompilerContextKind::Enum)
Adrian Prantl260aa0f2019-08-20 16:44:25 +0000255 .Case("Typedef", CompilerContextKind::Typedef)
Adrian Prantl330ae19a2019-08-21 18:06:56 +0000256 .Case("AnyModule", CompilerContextKind::AnyModule)
257 .Case("AnyType", CompilerContextKind::AnyType)
Adrian Prantl260aa0f2019-08-20 16:44:25 +0000258 .Default(CompilerContextKind::Invalid);
259 if (value.empty()) {
260 WithColor::error() << "compiler context entry has no \"name\"\n";
261 exit(1);
262 }
263 result.push_back({kind, ConstString{value}});
264 }
265 outs() << "Search context: {\n";
266 for (auto entry: result)
267 entry.Dump();
268 outs() << "}\n";
269
270 return result;
271}
272
Pavel Labathe6954cb2018-06-12 12:57:36 +0000273template <typename... Args>
274static Error make_string_error(const char *Format, Args &&... args) {
275 return llvm::make_error<llvm::StringError>(
276 llvm::formatv(Format, std::forward<Args>(args)...).str(),
277 llvm::inconvertibleErrorCode());
278}
279
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000280TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) {
281 TargetSP Target;
Jonas Devliegheref9a07e92018-09-20 09:09:05 +0000282 Status ST = Dbg.GetTargetList().CreateTarget(
283 Dbg, Filename, /*triple*/ "", eLoadDependentsNo,
284 /*platform_options*/ nullptr, Target);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000285 if (ST.Fail()) {
286 errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST);
287 exit(1);
288 }
289 return Target;
290}
291
292std::unique_ptr<MemoryBuffer> opts::openFile(const std::string &Filename) {
293 auto MB = MemoryBuffer::getFileOrSTDIN(Filename);
294 if (!MB) {
295 errs() << formatv("Could not open file '{0}: {1}\n", Filename,
296 MB.getError().message());
297 exit(1);
298 }
299 return std::move(*MB);
300}
301
Pavel Labath7c945822018-02-26 18:50:16 +0000302void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) {
303 P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize()));
304 if (List.GetSize() > 0)
305 P.formatLine("At least one breakpoint.");
306 for (size_t i = 0, e = List.GetSize(); i < e; ++i) {
307 BreakpointSP BP = List.GetBreakpointAtIndex(i);
308 P.formatLine("Breakpoint ID {0}:", BP->GetID());
309 AutoIndent Indent(P, 2);
310 P.formatLine("{0} location{1}.", BP->GetNumLocations(),
311 plural(BP->GetNumLocations()));
312 if (BP->GetNumLocations() > 0)
313 P.formatLine("At least one location.");
314 P.formatLine("{0} resolved location{1}.", BP->GetNumResolvedLocations(),
315 plural(BP->GetNumResolvedLocations()));
316 if (BP->GetNumResolvedLocations() > 0)
317 P.formatLine("At least one resolved location.");
318 for (size_t l = 0, le = BP->GetNumLocations(); l < le; ++l) {
319 BreakpointLocationSP Loc = BP->GetLocationAtIndex(l);
320 P.formatLine("Location ID {0}:", Loc->GetID());
321 AutoIndent Indent(P, 2);
322 P.formatLine("Enabled: {0}", Loc->IsEnabled());
323 P.formatLine("Resolved: {0}", Loc->IsResolved());
Jim Ingham08581262018-03-12 21:17:04 +0000324 SymbolContext sc;
325 Loc->GetAddress().CalculateSymbolContext(&sc);
326 lldb_private::StreamString S;
327 sc.DumpStopContext(&S, BP->GetTarget().GetProcessSP().get(),
328 Loc->GetAddress(), false, true, false, true, true);
329 P.formatLine("Address: {0}", S.GetString());
Pavel Labath7c945822018-02-26 18:50:16 +0000330 }
331 }
332 P.NewLine();
333}
334
335std::string opts::breakpoint::substitute(StringRef Cmd) {
336 std::string Result;
337 raw_string_ostream OS(Result);
338 while (!Cmd.empty()) {
339 switch (Cmd[0]) {
340 case '%':
341 if (Cmd.consume_front("%p") && (Cmd.empty() || !isalnum(Cmd[0]))) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000342 OS << sys::path::parent_path(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000343 break;
344 }
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000345 LLVM_FALLTHROUGH;
Pavel Labath7c945822018-02-26 18:50:16 +0000346 default:
347 size_t pos = Cmd.find('%');
348 OS << Cmd.substr(0, pos);
349 Cmd = Cmd.substr(pos);
350 break;
351 }
352 }
353 return std::move(OS.str());
354}
355
Pavel Labath90b0a532018-05-03 10:57:16 +0000356int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000357 TargetSP Target = opts::createTarget(Dbg, breakpoint::Target);
358 std::unique_ptr<MemoryBuffer> MB = opts::openFile(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000359
360 LinePrinter P(4, outs());
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000361 StringRef Rest = MB->getBuffer();
Pavel Labath90b0a532018-05-03 10:57:16 +0000362 int HadErrors = 0;
Pavel Labath7c945822018-02-26 18:50:16 +0000363 while (!Rest.empty()) {
364 StringRef Line;
365 std::tie(Line, Rest) = Rest.split('\n');
Adrian McCarthy4447d152019-06-07 21:13:30 +0000366 Line = Line.ltrim().rtrim();
Pavel Labath7c945822018-02-26 18:50:16 +0000367 if (Line.empty() || Line[0] == '#')
368 continue;
369
370 if (!Persistent)
371 Target->RemoveAllBreakpoints(/*internal_also*/ true);
372
373 std::string Command = substitute(Line);
374 P.formatLine("Command: {0}", Command);
375 CommandReturnObject Result;
376 if (!Dbg.GetCommandInterpreter().HandleCommand(
377 Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
378 P.formatLine("Failed: {0}", Result.GetErrorData());
Pavel Labath90b0a532018-05-03 10:57:16 +0000379 HadErrors = 1;
Pavel Labath7c945822018-02-26 18:50:16 +0000380 continue;
381 }
382
383 dumpState(Target->GetBreakpointList(/*internal*/ false), P);
384 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000385 return HadErrors;
Pavel Labath7c945822018-02-26 18:50:16 +0000386}
387
Pavel Labath90b0a532018-05-03 10:57:16 +0000388Expected<CompilerDeclContext>
Pavel Labath465eae32019-08-06 09:12:42 +0000389opts::symbols::getDeclContext(SymbolFile &Symfile) {
Pavel Labath90b0a532018-05-03 10:57:16 +0000390 if (Context.empty())
391 return CompilerDeclContext();
392 VariableList List;
Pavel Labath465eae32019-08-06 09:12:42 +0000393 Symfile.FindGlobalVariables(ConstString(Context), nullptr, UINT32_MAX, List);
Pavel Labathe6954cb2018-06-12 12:57:36 +0000394 if (List.Empty())
395 return make_string_error("Context search didn't find a match.");
396 if (List.GetSize() > 1)
397 return make_string_error("Context search found multiple matches.");
Pavel Labath90b0a532018-05-03 10:57:16 +0000398 return List.GetVariableAtIndex(0)->GetDeclContext();
399}
400
401Error opts::symbols::findFunctions(lldb_private::Module &Module) {
Pavel Labath465eae32019-08-06 09:12:42 +0000402 SymbolFile &Symfile = *Module.GetSymbolFile();
Pavel Labath90b0a532018-05-03 10:57:16 +0000403 SymbolContextList List;
Pavel Labath9ea80d22018-06-28 10:03:42 +0000404 if (!File.empty()) {
405 assert(Line != 0);
406
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000407 FileSpec src_file(File);
Pavel Labath9ea80d22018-06-28 10:03:42 +0000408 size_t cu_count = Module.GetNumCompileUnits();
409 for (size_t i = 0; i < cu_count; i++) {
410 lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
411 if (!cu_sp)
412 continue;
413
414 LineEntry le;
415 cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
416 if (!le.IsValid())
417 continue;
Greg Clayton8a777922019-05-06 20:01:21 +0000418 const bool include_inlined_functions = false;
419 auto addr =
420 le.GetSameLineContiguousAddressRange(include_inlined_functions)
421 .GetBaseAddress();
Pavel Labath9ea80d22018-06-28 10:03:42 +0000422 if (!addr.IsValid())
423 continue;
424
425 SymbolContext sc;
426 uint32_t resolved =
427 addr.CalculateSymbolContext(&sc, eSymbolContextFunction);
428 if (resolved & eSymbolContextFunction)
429 List.Append(sc);
430 }
431 } else if (Regex) {
Pavel Labath90b0a532018-05-03 10:57:16 +0000432 RegularExpression RE(Name);
433 assert(RE.IsValid());
Pavel Labath465eae32019-08-06 09:12:42 +0000434 Symfile.FindFunctions(RE, true, false, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000435 } else {
Pavel Labath465eae32019-08-06 09:12:42 +0000436 Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
Pavel Labath90b0a532018-05-03 10:57:16 +0000437 if (!ContextOr)
438 return ContextOr.takeError();
439 CompilerDeclContext *ContextPtr =
440 ContextOr->IsValid() ? &*ContextOr : nullptr;
441
Pavel Labath465eae32019-08-06 09:12:42 +0000442 Symfile.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
Pavel Labath9ea80d22018-06-28 10:03:42 +0000443 true, false, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000444 }
445 outs() << formatv("Found {0} functions:\n", List.GetSize());
446 StreamString Stream;
447 List.Dump(&Stream, nullptr);
448 outs() << Stream.GetData() << "\n";
449 return Error::success();
450}
451
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000452Error opts::symbols::findBlocks(lldb_private::Module &Module) {
453 assert(!Regex);
454 assert(!File.empty());
455 assert(Line != 0);
456
457 SymbolContextList List;
458
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000459 FileSpec src_file(File);
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000460 size_t cu_count = Module.GetNumCompileUnits();
461 for (size_t i = 0; i < cu_count; i++) {
462 lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
463 if (!cu_sp)
464 continue;
465
466 LineEntry le;
467 cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
468 if (!le.IsValid())
469 continue;
Greg Clayton8a777922019-05-06 20:01:21 +0000470 const bool include_inlined_functions = false;
471 auto addr = le.GetSameLineContiguousAddressRange(include_inlined_functions)
472 .GetBaseAddress();
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000473 if (!addr.IsValid())
474 continue;
475
476 SymbolContext sc;
477 uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock);
478 if (resolved & eSymbolContextBlock)
479 List.Append(sc);
480 }
481
482 outs() << formatv("Found {0} blocks:\n", List.GetSize());
483 StreamString Stream;
484 List.Dump(&Stream, nullptr);
485 outs() << Stream.GetData() << "\n";
486 return Error::success();
487}
488
Pavel Labath90b0a532018-05-03 10:57:16 +0000489Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
Pavel Labath465eae32019-08-06 09:12:42 +0000490 SymbolFile &Symfile = *Module.GetSymbolFile();
491 Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
Pavel Labath90b0a532018-05-03 10:57:16 +0000492 if (!ContextOr)
493 return ContextOr.takeError();
494 CompilerDeclContext *ContextPtr =
495 ContextOr->IsValid() ? &*ContextOr : nullptr;
496
Pavel Labath90b0a532018-05-03 10:57:16 +0000497 CompilerDeclContext Result =
Pavel Labath465eae32019-08-06 09:12:42 +0000498 Symfile.FindNamespace(ConstString(Name), ContextPtr);
Pavel Labath90b0a532018-05-03 10:57:16 +0000499 if (Result)
500 outs() << "Found namespace: "
501 << Result.GetScopeQualifiedName().GetStringRef() << "\n";
502 else
503 outs() << "Namespace not found.\n";
504 return Error::success();
505}
506
507Error opts::symbols::findTypes(lldb_private::Module &Module) {
Pavel Labath465eae32019-08-06 09:12:42 +0000508 SymbolFile &Symfile = *Module.GetSymbolFile();
509 Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
Pavel Labath90b0a532018-05-03 10:57:16 +0000510 if (!ContextOr)
511 return ContextOr.takeError();
512 CompilerDeclContext *ContextPtr =
513 ContextOr->IsValid() ? &*ContextOr : nullptr;
514
Adrian Prantlaa97a892019-08-22 21:45:58 +0000515 LanguageSet languages;
516 if (!Language.empty())
517 languages.Insert(Language::GetLanguageTypeFromString(Language));
518
Pavel Labath90b0a532018-05-03 10:57:16 +0000519 DenseSet<SymbolFile *> SearchedFiles;
520 TypeMap Map;
Adrian Prantl260aa0f2019-08-20 16:44:25 +0000521 if (!Name.empty())
Adrian Prantld4d428e2019-09-30 16:42:28 +0000522 Symfile.FindTypes(ConstString(Name), ContextPtr, UINT32_MAX, SearchedFiles,
523 Map);
Adrian Prantl260aa0f2019-08-20 16:44:25 +0000524 else
Adrian Prantld4d428e2019-09-30 16:42:28 +0000525 Module.FindTypes(parseCompilerContext(), languages, Map);
Pavel Labath90b0a532018-05-03 10:57:16 +0000526
527 outs() << formatv("Found {0} types:\n", Map.GetSize());
528 StreamString Stream;
529 Map.Dump(&Stream, false);
530 outs() << Stream.GetData() << "\n";
531 return Error::success();
532}
533
534Error opts::symbols::findVariables(lldb_private::Module &Module) {
Pavel Labath465eae32019-08-06 09:12:42 +0000535 SymbolFile &Symfile = *Module.GetSymbolFile();
Pavel Labath90b0a532018-05-03 10:57:16 +0000536 VariableList List;
537 if (Regex) {
538 RegularExpression RE(Name);
539 assert(RE.IsValid());
Pavel Labath465eae32019-08-06 09:12:42 +0000540 Symfile.FindGlobalVariables(RE, UINT32_MAX, List);
Pavel Labathe6954cb2018-06-12 12:57:36 +0000541 } else if (!File.empty()) {
542 CompUnitSP CU;
543 for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) {
544 CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind);
545 if (!Candidate || Candidate->GetFilename().GetStringRef() != File)
546 continue;
547 if (CU)
548 return make_string_error("Multiple compile units for file `{0}` found.",
549 File);
550 CU = std::move(Candidate);
551 }
552
553 if (!CU)
554 return make_string_error("Compile unit `{0}` not found.", File);
555
556 List.AddVariables(CU->GetVariableList(true).get());
Pavel Labath90b0a532018-05-03 10:57:16 +0000557 } else {
Pavel Labath465eae32019-08-06 09:12:42 +0000558 Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
Pavel Labath90b0a532018-05-03 10:57:16 +0000559 if (!ContextOr)
560 return ContextOr.takeError();
561 CompilerDeclContext *ContextPtr =
562 ContextOr->IsValid() ? &*ContextOr : nullptr;
563
Pavel Labath465eae32019-08-06 09:12:42 +0000564 Symfile.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000565 }
566 outs() << formatv("Found {0} variables:\n", List.GetSize());
567 StreamString Stream;
568 List.Dump(&Stream, false);
569 outs() << Stream.GetData() << "\n";
570 return Error::success();
571}
572
573Error opts::symbols::dumpModule(lldb_private::Module &Module) {
574 StreamString Stream;
575 Module.ParseAllDebugSymbols();
576 Module.Dump(&Stream);
577 outs() << Stream.GetData() << "\n";
578 return Error::success();
579}
580
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000581Error opts::symbols::dumpAST(lldb_private::Module &Module) {
Pavel Labath465eae32019-08-06 09:12:42 +0000582 Module.ParseAllDebugSymbols();
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000583
Pavel Labath465eae32019-08-06 09:12:42 +0000584 auto symfile = Module.GetSymbolFile();
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000585 if (!symfile)
586 return make_string_error("Module has no symbol file.");
587
Alex Langford0e252e32019-07-30 22:12:34 +0000588 auto type_system_or_err =
589 symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
590 if (!type_system_or_err)
591 return make_string_error("Can't retrieve ClangASTContext");
592
593 auto *clang_ast_ctx =
594 llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get());
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000595 if (!clang_ast_ctx)
Alex Langford0e252e32019-07-30 22:12:34 +0000596 return make_string_error("Retrieved TypeSystem was not a ClangASTContext");
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000597
598 auto ast_ctx = clang_ast_ctx->getASTContext();
599 if (!ast_ctx)
600 return make_string_error("Can't retrieve AST context.");
601
602 auto tu = ast_ctx->getTranslationUnitDecl();
603 if (!tu)
604 return make_string_error("Can't retrieve translation unit declaration.");
605
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000606 tu->print(outs());
607
608 return Error::success();
609}
610
Aaron Smith010edd32018-06-08 02:45:25 +0000611Error opts::symbols::verify(lldb_private::Module &Module) {
Pavel Labath465eae32019-08-06 09:12:42 +0000612 SymbolFile *symfile = Module.GetSymbolFile();
Aaron Smith010edd32018-06-08 02:45:25 +0000613 if (!symfile)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000614 return make_string_error("Module has no symbol file.");
Aaron Smith010edd32018-06-08 02:45:25 +0000615
616 uint32_t comp_units_count = symfile->GetNumCompileUnits();
617
618 outs() << "Found " << comp_units_count << " compile units.\n";
619
620 for (uint32_t i = 0; i < comp_units_count; i++) {
Pavel Labathe0119902019-07-23 09:24:02 +0000621 lldb::CompUnitSP comp_unit = symfile->GetCompileUnitAtIndex(i);
Aaron Smith010edd32018-06-08 02:45:25 +0000622 if (!comp_unit)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000623 return make_string_error("Connot parse compile unit {0}.", i);
Aaron Smith010edd32018-06-08 02:45:25 +0000624
Pavel Labath9ea80d22018-06-28 10:03:42 +0000625 outs() << "Processing '" << comp_unit->GetFilename().AsCString()
626 << "' compile unit.\n";
Aaron Smith010edd32018-06-08 02:45:25 +0000627
628 LineTable *lt = comp_unit->GetLineTable();
629 if (!lt)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000630 return make_string_error("Can't get a line table of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000631
632 uint32_t count = lt->GetSize();
633
634 outs() << "The line table contains " << count << " entries.\n";
635
636 if (count == 0)
637 continue;
638
639 LineEntry le;
640 if (!lt->GetLineEntryAtIndex(0, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000641 return make_string_error("Can't get a line entry of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000642
643 for (uint32_t i = 1; i < count; i++) {
644 lldb::addr_t curr_end =
Pavel Labath9ea80d22018-06-28 10:03:42 +0000645 le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
Aaron Smith010edd32018-06-08 02:45:25 +0000646
647 if (!lt->GetLineEntryAtIndex(i, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000648 return make_string_error("Can't get a line entry of a compile unit");
Aaron Smith010edd32018-06-08 02:45:25 +0000649
650 if (curr_end > le.range.GetBaseAddress().GetFileAddress())
Pavel Labathe6954cb2018-06-12 12:57:36 +0000651 return make_string_error(
652 "Line table of a compile unit is inconsistent.");
Aaron Smith010edd32018-06-08 02:45:25 +0000653 }
654 }
655
656 outs() << "The symbol information is verified.\n";
657
658 return Error::success();
659}
660
Pavel Labath38d9ff72018-06-12 13:26:43 +0000661Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000662 if (Verify && DumpAST)
663 return make_string_error(
664 "Cannot both verify symbol information and dump AST.");
665
Pavel Labathe6954cb2018-06-12 12:57:36 +0000666 if (Verify) {
667 if (Find != FindType::None)
668 return make_string_error(
669 "Cannot both search and verify symbol information.");
Pavel Labath9ea80d22018-06-28 10:03:42 +0000670 if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
671 Line != 0)
672 return make_string_error(
673 "-regex, -context, -name, -file and -line options are not "
674 "applicable for symbol verification.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000675 return verify;
Pavel Labath90b0a532018-05-03 10:57:16 +0000676 }
677
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000678 if (DumpAST) {
679 if (Find != FindType::None)
Aaron Smith037ed1b2018-12-06 21:36:39 +0000680 return make_string_error("Cannot both search and dump AST.");
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000681 if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
682 Line != 0)
683 return make_string_error(
684 "-regex, -context, -name, -file and -line options are not "
685 "applicable for dumping AST.");
686 return dumpAST;
687 }
688
Pavel Labathe6954cb2018-06-12 12:57:36 +0000689 if (Regex && !Context.empty())
690 return make_string_error(
691 "Cannot search using both regular expressions and context.");
692
693 if (Regex && !RegularExpression(Name).IsValid())
694 return make_string_error("`{0}` is not a valid regular expression.", Name);
695
696 if (Regex + !Context.empty() + !File.empty() >= 2)
697 return make_string_error(
698 "Only one of -regex, -context and -file may be used simultaneously.");
699 if (Regex && Name.empty())
700 return make_string_error("-regex used without a -name");
701
702 switch (Find) {
703 case FindType::None:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000704 if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000705 return make_string_error(
706 "Specify search type (-find) to use search options.");
707 return dumpModule;
708
709 case FindType::Function:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000710 if (!File.empty() + (Line != 0) == 1)
711 return make_string_error("Both file name and line number must be "
712 "specified when searching a function "
713 "by file position.");
714 if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2)
715 return make_string_error("Only one of regular expression, function-flags "
716 "and file position may be used simultaneously "
717 "when searching a function.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000718 return findFunctions;
719
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000720 case FindType::Block:
721 if (File.empty() || Line == 0)
722 return make_string_error("Both file name and line number must be "
723 "specified when searching a block.");
724 if (Regex || getFunctionNameFlags() != 0)
725 return make_string_error("Cannot use regular expression or "
726 "function-flags for searching a block.");
727 return findBlocks;
728
Pavel Labathe6954cb2018-06-12 12:57:36 +0000729 case FindType::Namespace:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000730 if (Regex || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000731 return make_string_error("Cannot search for namespaces using regular "
Pavel Labath9ea80d22018-06-28 10:03:42 +0000732 "expressions, file names or line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000733 return findNamespaces;
734
735 case FindType::Type:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000736 if (Regex || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000737 return make_string_error("Cannot search for types using regular "
Pavel Labath9ea80d22018-06-28 10:03:42 +0000738 "expressions, file names or line numbers.");
Adrian Prantl260aa0f2019-08-20 16:44:25 +0000739 if (!Name.empty() && !CompilerContext.empty())
740 return make_string_error("Name is ignored if compiler context present.");
741
Pavel Labathe6954cb2018-06-12 12:57:36 +0000742 return findTypes;
743
744 case FindType::Variable:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000745 if (Line != 0)
746 return make_string_error("Cannot search for variables "
747 "using line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000748 return findVariables;
749 }
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000750
751 llvm_unreachable("Unsupported symbol action.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000752}
753
754int opts::symbols::dumpSymbols(Debugger &Dbg) {
755 auto ActionOr = getAction();
756 if (!ActionOr) {
757 logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), "");
758 return 1;
759 }
760 auto Action = *ActionOr;
Pavel Labath90b0a532018-05-03 10:57:16 +0000761
Pavel Labath1cf23e12019-01-11 11:17:51 +0000762 outs() << "Module: " << InputFile << "\n";
763 ModuleSpec Spec{FileSpec(InputFile)};
764 StringRef Symbols = SymbolPath.empty() ? InputFile : SymbolPath;
765 Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native);
Zachary Turnera6d54642017-12-02 00:15:29 +0000766
Pavel Labath1cf23e12019-01-11 11:17:51 +0000767 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
Pavel Labath465eae32019-08-06 09:12:42 +0000768 SymbolFile *Symfile = ModulePtr->GetSymbolFile();
769 if (!Symfile) {
Pavel Labath1cf23e12019-01-11 11:17:51 +0000770 WithColor::error() << "Module has no symbol vendor.\n";
771 return 1;
Zachary Turnera6d54642017-12-02 00:15:29 +0000772 }
Pavel Labath1cf23e12019-01-11 11:17:51 +0000773
774 if (Error E = Action(*ModulePtr)) {
775 WithColor::error() << toString(std::move(E)) << "\n";
776 return 1;
777 }
778
779 return 0;
Zachary Turnera6d54642017-12-02 00:15:29 +0000780}
781
Pavel Labath280d2e82018-12-12 12:35:25 +0000782static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) {
783 size_t Count = List.GetNumSections(0);
784 if (Count == 0) {
785 Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : "");
786 return;
787 }
788 Printer.formatLine("Showing {0} {1}sections", Count,
789 is_subsection ? "sub" : "");
790 for (size_t I = 0; I < Count; ++I) {
791 auto S = List.GetSectionAtIndex(I);
792 assert(S);
793 AutoIndent Indent(Printer, 2);
794 Printer.formatLine("Index: {0}", I);
Pavel Labath0d38e4f2018-12-18 15:56:45 +0000795 Printer.formatLine("ID: {0:x}", S->GetID());
Pavel Labath280d2e82018-12-12 12:35:25 +0000796 Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
797 Printer.formatLine("Type: {0}", S->GetTypeAsCString());
Pavel Labath62a82542018-12-15 13:45:38 +0000798 Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions()));
Pavel Labathef8683a2018-12-12 15:46:18 +0000799 Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific());
Pavel Labath62a82542018-12-15 13:45:38 +0000800 Printer.formatLine("VM address: {0:x}", S->GetFileAddress());
Pavel Labath280d2e82018-12-12 12:35:25 +0000801 Printer.formatLine("VM size: {0}", S->GetByteSize());
802 Printer.formatLine("File size: {0}", S->GetFileSize());
803
804 if (opts::object::SectionContents) {
Jonas Devliegheref4af9a92019-07-11 20:26:53 +0000805 lldb_private::DataExtractor Data;
Pavel Labath280d2e82018-12-12 12:35:25 +0000806 S->GetSectionData(Data);
807 ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()};
808 Printer.formatBinary("Data: ", Bytes, 0);
809 }
810
811 if (S->GetType() == eSectionTypeContainer)
812 dumpSectionList(Printer, S->GetChildren(), true);
813 Printer.NewLine();
814 }
815}
816
Pavel Labath62a7f802018-06-29 12:15:54 +0000817static int dumpObjectFiles(Debugger &Dbg) {
Zachary Turner888a4282017-12-01 00:52:51 +0000818 LinePrinter Printer(4, llvm::outs());
819
Pavel Labath90b0a532018-05-03 10:57:16 +0000820 int HadErrors = 0;
Pavel Labath62a7f802018-06-29 12:15:54 +0000821 for (const auto &File : opts::object::InputFilenames) {
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000822 ModuleSpec Spec{FileSpec(File)};
Zachary Turner888a4282017-12-01 00:52:51 +0000823
Zachary Turnera6d54642017-12-02 00:15:29 +0000824 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
Pavel Labath1f6b2472018-12-10 17:16:38 +0000825
826 ObjectFile *ObjectPtr = ModulePtr->GetObjectFile();
827 if (!ObjectPtr) {
828 WithColor::error() << File << " not recognised as an object file\n";
829 HadErrors = 1;
830 continue;
831 }
832
Pavel Labath96979ce2018-03-06 15:56:20 +0000833 // Fetch symbol vendor before we get the section list to give the symbol
834 // vendor a chance to populate it.
Pavel Labath465eae32019-08-06 09:12:42 +0000835 ModulePtr->GetSymbolFile();
Zachary Turner888a4282017-12-01 00:52:51 +0000836 SectionList *Sections = ModulePtr->GetSectionList();
837 if (!Sections) {
838 llvm::errs() << "Could not load sections for module " << File << "\n";
Pavel Labath90b0a532018-05-03 10:57:16 +0000839 HadErrors = 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000840 continue;
841 }
842
Pavel Labath1f6b2472018-12-10 17:16:38 +0000843 Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName());
Pavel Labath62a7f802018-06-29 12:15:54 +0000844 Printer.formatLine("Architecture: {0}",
845 ModulePtr->GetArchitecture().GetTriple().getTriple());
846 Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
Pavel Labath1f6b2472018-12-10 17:16:38 +0000847 Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable());
848 Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped());
849 Printer.formatLine("Type: {0}", ObjectPtr->GetType());
850 Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata());
Pavel Labath976af432019-01-10 09:32:31 +0000851 Printer.formatLine("Base VM address: {0:x}",
852 ObjectPtr->GetBaseAddress().GetFileAddress());
Pavel Labath62a7f802018-06-29 12:15:54 +0000853
Pavel Labath280d2e82018-12-12 12:35:25 +0000854 dumpSectionList(Printer, *Sections, /*is_subsection*/ false);
Aaron Smith037ed1b2018-12-06 21:36:39 +0000855
856 if (opts::object::SectionDependentModules) {
857 // A non-empty section list ensures a valid object file.
858 auto Obj = ModulePtr->GetObjectFile();
859 FileSpecList Files;
860 auto Count = Obj->GetDependentModules(Files);
861 Printer.formatLine("Showing {0} dependent module(s)", Count);
862 for (size_t I = 0; I < Files.GetSize(); ++I) {
863 AutoIndent Indent(Printer, 2);
864 Printer.formatLine("Name: {0}",
865 Files.GetFileSpecAtIndex(I).GetCString());
866 }
867 Printer.NewLine();
868 }
Zachary Turner888a4282017-12-01 00:52:51 +0000869 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000870 return HadErrors;
Zachary Turner888a4282017-12-01 00:52:51 +0000871}
872
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000873bool opts::irmemorymap::evalMalloc(StringRef Line,
874 IRMemoryMapTestState &State) {
875 // ::= <label> = malloc <size> <alignment>
876 StringRef Label;
877 std::tie(Label, Line) = Line.split('=');
878 if (Line.empty())
879 return false;
880 Label = Label.trim();
881 Line = Line.trim();
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000882 size_t Size;
883 uint8_t Alignment;
884 int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment);
885 if (Matches != 2)
886 return false;
887
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000888 outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label,
889 Size, Alignment);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000890 if (!isPowerOf2_32(Alignment)) {
891 outs() << "Malloc error: alignment is not a power of 2\n";
892 exit(1);
893 }
894
Vedant Kumarf616b9d2018-05-31 22:09:00 +0000895 IRMemoryMap::AllocationPolicy AP =
896 UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly
897 : IRMemoryMap::eAllocationPolicyProcessOnly;
898
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000899 // Issue the malloc in the target process with "-rw" permissions.
900 const uint32_t Permissions = 0x3;
901 const bool ZeroMemory = false;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000902 Status ST;
903 addr_t Addr =
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000904 State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000905 if (ST.Fail()) {
906 outs() << formatv("Malloc error: {0}\n", ST);
907 return true;
908 }
909
910 // Print the result of the allocation before checking its validity.
911 outs() << formatv("Malloc: address = {0:x}\n", Addr);
912
913 // Check that the allocation is aligned.
914 if (!Addr || Addr % Alignment != 0) {
915 outs() << "Malloc error: zero or unaligned allocation detected\n";
916 exit(1);
917 }
918
Pavel Labatha352ed22018-12-27 09:32:04 +0000919 // In case of Size == 0, we still expect the returned address to be unique and
920 // non-overlapping.
921 addr_t EndOfRegion = Addr + std::max<size_t>(Size, 1);
922 if (State.Allocations.overlaps(Addr, EndOfRegion)) {
923 auto I = State.Allocations.find(Addr);
924 outs() << "Malloc error: overlapping allocation detected"
925 << formatv(", previous allocation at [{0:x}, {1:x})\n", I.start(),
926 I.stop());
927 exit(1);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000928 }
929
Aaron Smith037ed1b2018-12-06 21:36:39 +0000930 // Insert the new allocation into the interval map. Use unique allocation
931 // IDs to inhibit interval coalescing.
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000932 static unsigned AllocationID = 0;
Pavel Labatha352ed22018-12-27 09:32:04 +0000933 State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000934
935 // Store the label -> address mapping.
936 State.Label2AddrMap[Label] = Addr;
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000937
938 return true;
939}
940
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000941bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) {
942 // ::= free <label>
943 if (!Line.consume_front("free"))
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000944 return false;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000945 StringRef Label = Line.trim();
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000946
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000947 outs() << formatv("Command: free({0})\n", Label);
948 auto LabelIt = State.Label2AddrMap.find(Label);
949 if (LabelIt == State.Label2AddrMap.end()) {
950 outs() << "Free error: Invalid allocation label\n";
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000951 exit(1);
952 }
953
954 Status ST;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000955 addr_t Addr = LabelIt->getValue();
956 State.Map.Free(Addr, ST);
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000957 if (ST.Fail()) {
958 outs() << formatv("Free error: {0}\n", ST);
959 exit(1);
960 }
961
962 // Erase the allocation from the live interval map.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000963 auto Interval = State.Allocations.find(Addr);
964 if (Interval != State.Allocations.end()) {
965 outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(),
966 Interval.stop());
967 Interval.erase();
968 }
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000969
970 return true;
971}
972
973int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
974 // Set up a Target.
975 TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target);
976
977 // Set up a Process. In order to allocate memory within a target, this
978 // process must be alive and must support JIT'ing.
979 CommandReturnObject Result;
980 Dbg.SetAsyncExecution(false);
981 CommandInterpreter &CI = Dbg.GetCommandInterpreter();
982 auto IssueCmd = [&](const char *Cmd) -> bool {
983 return CI.HandleCommand(Cmd, eLazyBoolNo, Result);
984 };
985 if (!IssueCmd("b main") || !IssueCmd("run")) {
986 outs() << formatv("Failed: {0}\n", Result.GetErrorData());
987 exit(1);
988 }
989
990 ProcessSP Process = Target->GetProcessSP();
991 if (!Process || !Process->IsAlive() || !Process->CanJIT()) {
992 outs() << "Cannot use process to test IRMemoryMap\n";
993 exit(1);
994 }
995
996 // Set up an IRMemoryMap and associated testing state.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000997 IRMemoryMapTestState State(Target);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000998
999 // Parse and apply commands from the command file.
1000 std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile);
1001 StringRef Rest = MB->getBuffer();
1002 while (!Rest.empty()) {
1003 StringRef Line;
1004 std::tie(Line, Rest) = Rest.split('\n');
Adrian McCarthy4447d152019-06-07 21:13:30 +00001005 Line = Line.ltrim().rtrim();
Vedant Kumarc1cd8262018-05-30 19:39:10 +00001006
1007 if (Line.empty() || Line[0] == '#')
1008 continue;
1009
Vedant Kumarc418b5c2018-06-04 17:11:15 +00001010 if (evalMalloc(Line, State))
Vedant Kumarc1cd8262018-05-30 19:39:10 +00001011 continue;
1012
Vedant Kumarc418b5c2018-06-04 17:11:15 +00001013 if (evalFree(Line, State))
Vedant Kumarcc5a6162018-05-31 22:09:01 +00001014 continue;
1015
Vedant Kumarc1cd8262018-05-30 19:39:10 +00001016 errs() << "Could not parse line: " << Line << "\n";
1017 exit(1);
1018 }
1019 return 0;
1020}
1021
Zachary Turner888a4282017-12-01 00:52:51 +00001022int main(int argc, const char *argv[]) {
1023 StringRef ToolName = argv[0];
1024 sys::PrintStackTraceOnErrorSignal(ToolName);
1025 PrettyStackTraceProgram X(argc, argv);
1026 llvm_shutdown_obj Y;
1027
1028 cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
1029
Pavel Labath90b0a532018-05-03 10:57:16 +00001030 SystemLifetimeManager DebuggerLifetime;
Jonas Devlieghere15eacd72018-12-03 17:28:29 +00001031 if (auto e = DebuggerLifetime.Initialize(
Jonas Devliegherea8f3ae72019-08-14 22:19:23 +00001032 std::make_unique<SystemInitializerTest>(), nullptr)) {
Jonas Devlieghere15eacd72018-12-03 17:28:29 +00001033 WithColor::error() << "initialization failed: " << toString(std::move(e))
1034 << '\n';
1035 return 1;
1036 }
1037
Jonas Devliegheree0ea8d82019-09-10 00:20:50 +00001038 auto TerminateDebugger =
1039 llvm::make_scope_exit([&] { DebuggerLifetime.Terminate(); });
Zachary Turner888a4282017-12-01 00:52:51 +00001040
1041 auto Dbg = lldb_private::Debugger::CreateInstance();
Jan Kratochvil8c82c412019-06-17 14:46:17 +00001042 ModuleList::GetGlobalModuleListProperties().SetEnableExternalLookup(false);
Jan Kratochvil2b389512019-07-29 16:10:16 +00001043 CommandReturnObject Result;
1044 Dbg->GetCommandInterpreter().HandleCommand(
1045 "settings set plugin.process.gdb-remote.packet-timeout 60",
1046 /*add_to_history*/ eLazyBoolNo, Result);
Zachary Turner888a4282017-12-01 00:52:51 +00001047
Vedant Kumarc1cd8262018-05-30 19:39:10 +00001048 if (!opts::Log.empty())
1049 Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, errs());
1050
Pavel Labath7c945822018-02-26 18:50:16 +00001051 if (opts::BreakpointSubcommand)
Pavel Labath90b0a532018-05-03 10:57:16 +00001052 return opts::breakpoint::evaluateBreakpoints(*Dbg);
Pavel Labath62a7f802018-06-29 12:15:54 +00001053 if (opts::ObjectFileSubcommand)
1054 return dumpObjectFiles(*Dbg);
Pavel Labath90b0a532018-05-03 10:57:16 +00001055 if (opts::SymbolsSubcommand)
1056 return opts::symbols::dumpSymbols(*Dbg);
Vedant Kumarc1cd8262018-05-30 19:39:10 +00001057 if (opts::IRMemoryMapSubcommand)
1058 return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
Zachary Turner888a4282017-12-01 00:52:51 +00001059
Pavel Labath90b0a532018-05-03 10:57:16 +00001060 WithColor::error() << "No command specified.\n";
1061 return 1;
Zachary Turner888a4282017-12-01 00:52:51 +00001062}