blob: 29dd7cb99cf08cc717440480872ae8f32c97f0af [file] [log] [blame]
Zachary Turner888a4282017-12-01 00:52:51 +00001//===- lldb-test.cpp ------------------------------------------ *- C++ --*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "FormatUtil.h"
11#include "SystemInitializerTest.h"
12
Zachary Turnera6d54642017-12-02 00:15:29 +000013#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
Pavel Labath7c945822018-02-26 18:50:16 +000014#include "lldb/Breakpoint/BreakpointLocation.h"
Zachary Turner888a4282017-12-01 00:52:51 +000015#include "lldb/Core/Debugger.h"
16#include "lldb/Core/Module.h"
17#include "lldb/Core/Section.h"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000018#include "lldb/Expression/IRMemoryMap.h"
Zachary Turner888a4282017-12-01 00:52:51 +000019#include "lldb/Initialization/SystemLifetimeManager.h"
Pavel Labath7c945822018-02-26 18:50:16 +000020#include "lldb/Interpreter/CommandInterpreter.h"
21#include "lldb/Interpreter/CommandReturnObject.h"
Zachary Turnera6d54642017-12-02 00:15:29 +000022#include "lldb/Symbol/ClangASTContext.h"
23#include "lldb/Symbol/ClangASTImporter.h"
Aaron Smith010edd32018-06-08 02:45:25 +000024#include "lldb/Symbol/CompileUnit.h"
25#include "lldb/Symbol/LineTable.h"
Pavel Labath90b0a532018-05-03 10:57:16 +000026#include "lldb/Symbol/SymbolVendor.h"
27#include "lldb/Symbol/TypeList.h"
28#include "lldb/Symbol/VariableList.h"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000029#include "lldb/Target/Process.h"
30#include "lldb/Target/Target.h"
Pavel Labath90b0a532018-05-03 10:57:16 +000031#include "lldb/Utility/CleanUp.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"
Zachary Turner888a4282017-12-01 00:52:51 +000037#include "llvm/ADT/StringRef.h"
38#include "llvm/Support/CommandLine.h"
39#include "llvm/Support/ManagedStatic.h"
Pavel Labath9ea80d22018-06-28 10:03:42 +000040#include "llvm/Support/MathExtras.h"
Pavel Labath7c945822018-02-26 18:50:16 +000041#include "llvm/Support/Path.h"
Zachary Turner888a4282017-12-01 00:52:51 +000042#include "llvm/Support/PrettyStackTrace.h"
43#include "llvm/Support/Signals.h"
Pavel Labath90b0a532018-05-03 10:57:16 +000044#include "llvm/Support/WithColor.h"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000045#include <cstdio>
Zachary Turner888a4282017-12-01 00:52:51 +000046#include <thread>
47
48using namespace lldb;
49using namespace lldb_private;
50using namespace llvm;
51
52namespace opts {
Pavel Labath7c945822018-02-26 18:50:16 +000053static cl::SubCommand BreakpointSubcommand("breakpoints",
54 "Test breakpoint resolution");
Pavel Labath62a7f802018-06-29 12:15:54 +000055cl::SubCommand ObjectFileSubcommand("object-file",
56 "Display LLDB object file information");
Zachary Turnera6d54642017-12-02 00:15:29 +000057cl::SubCommand SymbolsSubcommand("symbols", "Dump symbols for an object file");
Vedant Kumarc1cd8262018-05-30 19:39:10 +000058cl::SubCommand IRMemoryMapSubcommand("ir-memory-map", "Test IRMemoryMap");
Vedant Kumar7e4c84a2018-05-31 22:09:00 +000059
Vedant Kumarc1cd8262018-05-30 19:39:10 +000060cl::opt<std::string> Log("log", cl::desc("Path to a log file"), cl::init(""),
Vedant Kumar7e4c84a2018-05-31 22:09:00 +000061 cl::sub(BreakpointSubcommand),
Pavel Labath62a7f802018-06-29 12:15:54 +000062 cl::sub(ObjectFileSubcommand),
63 cl::sub(SymbolsSubcommand),
Vedant Kumarc1cd8262018-05-30 19:39:10 +000064 cl::sub(IRMemoryMapSubcommand));
65
66/// Create a target using the file pointed to by \p Filename, or abort.
67TargetSP createTarget(Debugger &Dbg, const std::string &Filename);
68
69/// Read \p Filename into a null-terminated buffer, or abort.
70std::unique_ptr<MemoryBuffer> openFile(const std::string &Filename);
Zachary Turner888a4282017-12-01 00:52:51 +000071
Pavel Labath7c945822018-02-26 18:50:16 +000072namespace breakpoint {
73static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
74 cl::Required, cl::sub(BreakpointSubcommand));
75static cl::opt<std::string> CommandFile(cl::Positional,
76 cl::desc("<command-file>"),
77 cl::init("-"),
78 cl::sub(BreakpointSubcommand));
79static cl::opt<bool> Persistent(
80 "persistent",
81 cl::desc("Don't automatically remove all breakpoints before each command"),
82 cl::sub(BreakpointSubcommand));
83
84static llvm::StringRef plural(uintmax_t value) { return value == 1 ? "" : "s"; }
85static void dumpState(const BreakpointList &List, LinePrinter &P);
86static std::string substitute(StringRef Cmd);
Pavel Labath90b0a532018-05-03 10:57:16 +000087static int evaluateBreakpoints(Debugger &Dbg);
Pavel Labath7c945822018-02-26 18:50:16 +000088} // namespace breakpoint
89
Pavel Labath62a7f802018-06-29 12:15:54 +000090namespace object {
Zachary Turner888a4282017-12-01 00:52:51 +000091cl::opt<bool> SectionContents("contents",
92 cl::desc("Dump each section's contents"),
Pavel Labath62a7f802018-06-29 12:15:54 +000093 cl::sub(ObjectFileSubcommand));
Aaron Smith037ed1b2018-12-06 21:36:39 +000094cl::opt<bool> SectionDependentModules("dep-modules",
95 cl::desc("Dump each dependent module"),
96 cl::sub(ObjectFileSubcommand));
Zachary Turner888a4282017-12-01 00:52:51 +000097cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
Pavel Labath62a7f802018-06-29 12:15:54 +000098 cl::OneOrMore,
99 cl::sub(ObjectFileSubcommand));
100} // namespace object
Zachary Turnera6d54642017-12-02 00:15:29 +0000101
102namespace symbols {
Pavel Labath1cf23e12019-01-11 11:17:51 +0000103static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
104 cl::Required, cl::sub(SymbolsSubcommand));
105
106static cl::opt<std::string>
107 SymbolPath("symbol-file",
108 cl::desc("The file from which to fetch symbol information."),
109 cl::value_desc("file"), cl::sub(SymbolsSubcommand));
110
Pavel Labath90b0a532018-05-03 10:57:16 +0000111enum class FindType {
112 None,
113 Function,
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000114 Block,
Pavel Labath90b0a532018-05-03 10:57:16 +0000115 Namespace,
116 Type,
117 Variable,
118};
119static cl::opt<FindType> Find(
120 "find", cl::desc("Choose search type:"),
121 cl::values(
Pavel Labath9ea80d22018-06-28 10:03:42 +0000122 clEnumValN(FindType::None, "none", "No search, just dump the module."),
Pavel Labath90b0a532018-05-03 10:57:16 +0000123 clEnumValN(FindType::Function, "function", "Find functions."),
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000124 clEnumValN(FindType::Block, "block", "Find blocks."),
Pavel Labath90b0a532018-05-03 10:57:16 +0000125 clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
126 clEnumValN(FindType::Type, "type", "Find types."),
127 clEnumValN(FindType::Variable, "variable", "Find global variables.")),
128 cl::sub(SymbolsSubcommand));
129
130static cl::opt<std::string> Name("name", cl::desc("Name to find."),
131 cl::sub(SymbolsSubcommand));
132static cl::opt<bool>
133 Regex("regex",
134 cl::desc("Search using regular expressions (avaliable for variables "
135 "and functions only)."),
136 cl::sub(SymbolsSubcommand));
137static cl::opt<std::string>
138 Context("context",
139 cl::desc("Restrict search to the context of the given variable."),
140 cl::value_desc("variable"), cl::sub(SymbolsSubcommand));
141
142static cl::list<FunctionNameType> FunctionNameFlags(
143 "function-flags", cl::desc("Function search flags:"),
144 cl::values(clEnumValN(eFunctionNameTypeAuto, "auto",
145 "Automatically deduce flags based on name."),
146 clEnumValN(eFunctionNameTypeFull, "full", "Full function name."),
147 clEnumValN(eFunctionNameTypeBase, "base", "Base name."),
148 clEnumValN(eFunctionNameTypeMethod, "method", "Method name."),
149 clEnumValN(eFunctionNameTypeSelector, "selector",
150 "Selector name.")),
151 cl::sub(SymbolsSubcommand));
152static FunctionNameType getFunctionNameFlags() {
153 FunctionNameType Result = FunctionNameType(0);
154 for (FunctionNameType Flag : FunctionNameFlags)
155 Result = FunctionNameType(Result | Flag);
156 return Result;
157}
158
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000159static cl::opt<bool> DumpAST("dump-ast",
160 cl::desc("Dump AST restored from symbols."),
161 cl::sub(SymbolsSubcommand));
162
Aaron Smith010edd32018-06-08 02:45:25 +0000163static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
164 cl::sub(SymbolsSubcommand));
165
Pavel Labathe6954cb2018-06-12 12:57:36 +0000166static cl::opt<std::string> File("file",
167 cl::desc("File (compile unit) to search."),
168 cl::sub(SymbolsSubcommand));
Pavel Labath9ea80d22018-06-28 10:03:42 +0000169static cl::opt<int> Line("line", cl::desc("Line to search."),
170 cl::sub(SymbolsSubcommand));
Pavel Labathe6954cb2018-06-12 12:57:36 +0000171
Pavel Labath90b0a532018-05-03 10:57:16 +0000172static Expected<CompilerDeclContext> getDeclContext(SymbolVendor &Vendor);
173
174static Error findFunctions(lldb_private::Module &Module);
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000175static Error findBlocks(lldb_private::Module &Module);
Pavel Labath90b0a532018-05-03 10:57:16 +0000176static Error findNamespaces(lldb_private::Module &Module);
177static Error findTypes(lldb_private::Module &Module);
178static Error findVariables(lldb_private::Module &Module);
179static Error dumpModule(lldb_private::Module &Module);
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000180static Error dumpAST(lldb_private::Module &Module);
Aaron Smith010edd32018-06-08 02:45:25 +0000181static Error verify(lldb_private::Module &Module);
Pavel Labath90b0a532018-05-03 10:57:16 +0000182
Pavel Labath38d9ff72018-06-12 13:26:43 +0000183static Expected<Error (*)(lldb_private::Module &)> getAction();
Pavel Labath90b0a532018-05-03 10:57:16 +0000184static int dumpSymbols(Debugger &Dbg);
Pavel Labath9ea80d22018-06-28 10:03:42 +0000185} // namespace symbols
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000186
187namespace irmemorymap {
188static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
189 cl::Required,
190 cl::sub(IRMemoryMapSubcommand));
191static cl::opt<std::string> CommandFile(cl::Positional,
192 cl::desc("<command-file>"),
193 cl::init("-"),
194 cl::sub(IRMemoryMapSubcommand));
Vedant Kumarf616b9d2018-05-31 22:09:00 +0000195static cl::opt<bool> UseHostOnlyAllocationPolicy(
196 "host-only", cl::desc("Use the host-only allocation policy"),
197 cl::init(false), cl::sub(IRMemoryMapSubcommand));
198
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000199using AllocationT = std::pair<addr_t, addr_t>;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000200using AddrIntervalMap =
Pavel Labath9ea80d22018-06-28 10:03:42 +0000201 IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000202
203struct IRMemoryMapTestState {
204 TargetSP Target;
205 IRMemoryMap Map;
206
207 AddrIntervalMap::Allocator IntervalMapAllocator;
208 AddrIntervalMap Allocations;
209
210 StringMap<addr_t> Label2AddrMap;
211
212 IRMemoryMapTestState(TargetSP Target)
213 : Target(Target), Map(Target), Allocations(IntervalMapAllocator) {}
214};
215
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000216bool evalMalloc(StringRef Line, IRMemoryMapTestState &State);
217bool evalFree(StringRef Line, IRMemoryMapTestState &State);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000218int evaluateMemoryMapCommands(Debugger &Dbg);
219} // namespace irmemorymap
220
Zachary Turner888a4282017-12-01 00:52:51 +0000221} // namespace opts
222
Pavel Labathe6954cb2018-06-12 12:57:36 +0000223template <typename... Args>
224static Error make_string_error(const char *Format, Args &&... args) {
225 return llvm::make_error<llvm::StringError>(
226 llvm::formatv(Format, std::forward<Args>(args)...).str(),
227 llvm::inconvertibleErrorCode());
228}
229
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000230TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) {
231 TargetSP Target;
Jonas Devliegheref9a07e92018-09-20 09:09:05 +0000232 Status ST = Dbg.GetTargetList().CreateTarget(
233 Dbg, Filename, /*triple*/ "", eLoadDependentsNo,
234 /*platform_options*/ nullptr, Target);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000235 if (ST.Fail()) {
236 errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST);
237 exit(1);
238 }
239 return Target;
240}
241
242std::unique_ptr<MemoryBuffer> opts::openFile(const std::string &Filename) {
243 auto MB = MemoryBuffer::getFileOrSTDIN(Filename);
244 if (!MB) {
245 errs() << formatv("Could not open file '{0}: {1}\n", Filename,
246 MB.getError().message());
247 exit(1);
248 }
249 return std::move(*MB);
250}
251
Pavel Labath7c945822018-02-26 18:50:16 +0000252void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) {
253 P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize()));
254 if (List.GetSize() > 0)
255 P.formatLine("At least one breakpoint.");
256 for (size_t i = 0, e = List.GetSize(); i < e; ++i) {
257 BreakpointSP BP = List.GetBreakpointAtIndex(i);
258 P.formatLine("Breakpoint ID {0}:", BP->GetID());
259 AutoIndent Indent(P, 2);
260 P.formatLine("{0} location{1}.", BP->GetNumLocations(),
261 plural(BP->GetNumLocations()));
262 if (BP->GetNumLocations() > 0)
263 P.formatLine("At least one location.");
264 P.formatLine("{0} resolved location{1}.", BP->GetNumResolvedLocations(),
265 plural(BP->GetNumResolvedLocations()));
266 if (BP->GetNumResolvedLocations() > 0)
267 P.formatLine("At least one resolved location.");
268 for (size_t l = 0, le = BP->GetNumLocations(); l < le; ++l) {
269 BreakpointLocationSP Loc = BP->GetLocationAtIndex(l);
270 P.formatLine("Location ID {0}:", Loc->GetID());
271 AutoIndent Indent(P, 2);
272 P.formatLine("Enabled: {0}", Loc->IsEnabled());
273 P.formatLine("Resolved: {0}", Loc->IsResolved());
Jim Ingham08581262018-03-12 21:17:04 +0000274 SymbolContext sc;
275 Loc->GetAddress().CalculateSymbolContext(&sc);
276 lldb_private::StreamString S;
277 sc.DumpStopContext(&S, BP->GetTarget().GetProcessSP().get(),
278 Loc->GetAddress(), false, true, false, true, true);
279 P.formatLine("Address: {0}", S.GetString());
Pavel Labath7c945822018-02-26 18:50:16 +0000280 }
281 }
282 P.NewLine();
283}
284
285std::string opts::breakpoint::substitute(StringRef Cmd) {
286 std::string Result;
287 raw_string_ostream OS(Result);
288 while (!Cmd.empty()) {
289 switch (Cmd[0]) {
290 case '%':
291 if (Cmd.consume_front("%p") && (Cmd.empty() || !isalnum(Cmd[0]))) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000292 OS << sys::path::parent_path(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000293 break;
294 }
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000295 LLVM_FALLTHROUGH;
Pavel Labath7c945822018-02-26 18:50:16 +0000296 default:
297 size_t pos = Cmd.find('%');
298 OS << Cmd.substr(0, pos);
299 Cmd = Cmd.substr(pos);
300 break;
301 }
302 }
303 return std::move(OS.str());
304}
305
Pavel Labath90b0a532018-05-03 10:57:16 +0000306int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000307 TargetSP Target = opts::createTarget(Dbg, breakpoint::Target);
308 std::unique_ptr<MemoryBuffer> MB = opts::openFile(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000309
310 LinePrinter P(4, outs());
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000311 StringRef Rest = MB->getBuffer();
Pavel Labath90b0a532018-05-03 10:57:16 +0000312 int HadErrors = 0;
Pavel Labath7c945822018-02-26 18:50:16 +0000313 while (!Rest.empty()) {
314 StringRef Line;
315 std::tie(Line, Rest) = Rest.split('\n');
316 Line = Line.ltrim();
317 if (Line.empty() || Line[0] == '#')
318 continue;
319
320 if (!Persistent)
321 Target->RemoveAllBreakpoints(/*internal_also*/ true);
322
323 std::string Command = substitute(Line);
324 P.formatLine("Command: {0}", Command);
325 CommandReturnObject Result;
326 if (!Dbg.GetCommandInterpreter().HandleCommand(
327 Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
328 P.formatLine("Failed: {0}", Result.GetErrorData());
Pavel Labath90b0a532018-05-03 10:57:16 +0000329 HadErrors = 1;
Pavel Labath7c945822018-02-26 18:50:16 +0000330 continue;
331 }
332
333 dumpState(Target->GetBreakpointList(/*internal*/ false), P);
334 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000335 return HadErrors;
Pavel Labath7c945822018-02-26 18:50:16 +0000336}
337
Pavel Labath90b0a532018-05-03 10:57:16 +0000338Expected<CompilerDeclContext>
339opts::symbols::getDeclContext(SymbolVendor &Vendor) {
340 if (Context.empty())
341 return CompilerDeclContext();
342 VariableList List;
Pavel Labath34cda142018-05-31 09:46:26 +0000343 Vendor.FindGlobalVariables(ConstString(Context), nullptr, UINT32_MAX, List);
Pavel Labathe6954cb2018-06-12 12:57:36 +0000344 if (List.Empty())
345 return make_string_error("Context search didn't find a match.");
346 if (List.GetSize() > 1)
347 return make_string_error("Context search found multiple matches.");
Pavel Labath90b0a532018-05-03 10:57:16 +0000348 return List.GetVariableAtIndex(0)->GetDeclContext();
349}
350
351Error opts::symbols::findFunctions(lldb_private::Module &Module) {
352 SymbolVendor &Vendor = *Module.GetSymbolVendor();
353 SymbolContextList List;
Pavel Labath9ea80d22018-06-28 10:03:42 +0000354 if (!File.empty()) {
355 assert(Line != 0);
356
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000357 FileSpec src_file(File);
Pavel Labath9ea80d22018-06-28 10:03:42 +0000358 size_t cu_count = Module.GetNumCompileUnits();
359 for (size_t i = 0; i < cu_count; i++) {
360 lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
361 if (!cu_sp)
362 continue;
363
364 LineEntry le;
365 cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
366 if (!le.IsValid())
367 continue;
368
369 auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress();
370 if (!addr.IsValid())
371 continue;
372
373 SymbolContext sc;
374 uint32_t resolved =
375 addr.CalculateSymbolContext(&sc, eSymbolContextFunction);
376 if (resolved & eSymbolContextFunction)
377 List.Append(sc);
378 }
379 } else if (Regex) {
Pavel Labath90b0a532018-05-03 10:57:16 +0000380 RegularExpression RE(Name);
381 assert(RE.IsValid());
382 Vendor.FindFunctions(RE, true, false, List);
383 } else {
384 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
385 if (!ContextOr)
386 return ContextOr.takeError();
387 CompilerDeclContext *ContextPtr =
388 ContextOr->IsValid() ? &*ContextOr : nullptr;
389
390 Vendor.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
Pavel Labath9ea80d22018-06-28 10:03:42 +0000391 true, false, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000392 }
393 outs() << formatv("Found {0} functions:\n", List.GetSize());
394 StreamString Stream;
395 List.Dump(&Stream, nullptr);
396 outs() << Stream.GetData() << "\n";
397 return Error::success();
398}
399
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000400Error opts::symbols::findBlocks(lldb_private::Module &Module) {
401 assert(!Regex);
402 assert(!File.empty());
403 assert(Line != 0);
404
405 SymbolContextList List;
406
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000407 FileSpec src_file(File);
Aleksandr Urakov398f81b2018-08-29 07:26:11 +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;
418
419 auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress();
420 if (!addr.IsValid())
421 continue;
422
423 SymbolContext sc;
424 uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock);
425 if (resolved & eSymbolContextBlock)
426 List.Append(sc);
427 }
428
429 outs() << formatv("Found {0} blocks:\n", List.GetSize());
430 StreamString Stream;
431 List.Dump(&Stream, nullptr);
432 outs() << Stream.GetData() << "\n";
433 return Error::success();
434}
435
Pavel Labath90b0a532018-05-03 10:57:16 +0000436Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
437 SymbolVendor &Vendor = *Module.GetSymbolVendor();
438 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
439 if (!ContextOr)
440 return ContextOr.takeError();
441 CompilerDeclContext *ContextPtr =
442 ContextOr->IsValid() ? &*ContextOr : nullptr;
443
444 SymbolContext SC;
445 CompilerDeclContext Result =
446 Vendor.FindNamespace(SC, ConstString(Name), ContextPtr);
447 if (Result)
448 outs() << "Found namespace: "
449 << Result.GetScopeQualifiedName().GetStringRef() << "\n";
450 else
451 outs() << "Namespace not found.\n";
452 return Error::success();
453}
454
455Error opts::symbols::findTypes(lldb_private::Module &Module) {
456 SymbolVendor &Vendor = *Module.GetSymbolVendor();
457 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
458 if (!ContextOr)
459 return ContextOr.takeError();
460 CompilerDeclContext *ContextPtr =
461 ContextOr->IsValid() ? &*ContextOr : nullptr;
462
463 SymbolContext SC;
464 DenseSet<SymbolFile *> SearchedFiles;
465 TypeMap Map;
466 Vendor.FindTypes(SC, ConstString(Name), ContextPtr, true, UINT32_MAX,
Pavel Labath9ea80d22018-06-28 10:03:42 +0000467 SearchedFiles, Map);
Pavel Labath90b0a532018-05-03 10:57:16 +0000468
469 outs() << formatv("Found {0} types:\n", Map.GetSize());
470 StreamString Stream;
471 Map.Dump(&Stream, false);
472 outs() << Stream.GetData() << "\n";
473 return Error::success();
474}
475
476Error opts::symbols::findVariables(lldb_private::Module &Module) {
477 SymbolVendor &Vendor = *Module.GetSymbolVendor();
478 VariableList List;
479 if (Regex) {
480 RegularExpression RE(Name);
481 assert(RE.IsValid());
Pavel Labath34cda142018-05-31 09:46:26 +0000482 Vendor.FindGlobalVariables(RE, UINT32_MAX, List);
Pavel Labathe6954cb2018-06-12 12:57:36 +0000483 } else if (!File.empty()) {
484 CompUnitSP CU;
485 for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) {
486 CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind);
487 if (!Candidate || Candidate->GetFilename().GetStringRef() != File)
488 continue;
489 if (CU)
490 return make_string_error("Multiple compile units for file `{0}` found.",
491 File);
492 CU = std::move(Candidate);
493 }
494
495 if (!CU)
496 return make_string_error("Compile unit `{0}` not found.", File);
497
498 List.AddVariables(CU->GetVariableList(true).get());
Pavel Labath90b0a532018-05-03 10:57:16 +0000499 } else {
500 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
501 if (!ContextOr)
502 return ContextOr.takeError();
503 CompilerDeclContext *ContextPtr =
504 ContextOr->IsValid() ? &*ContextOr : nullptr;
505
Pavel Labath34cda142018-05-31 09:46:26 +0000506 Vendor.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000507 }
508 outs() << formatv("Found {0} variables:\n", List.GetSize());
509 StreamString Stream;
510 List.Dump(&Stream, false);
511 outs() << Stream.GetData() << "\n";
512 return Error::success();
513}
514
515Error opts::symbols::dumpModule(lldb_private::Module &Module) {
516 StreamString Stream;
517 Module.ParseAllDebugSymbols();
518 Module.Dump(&Stream);
519 outs() << Stream.GetData() << "\n";
520 return Error::success();
521}
522
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000523Error opts::symbols::dumpAST(lldb_private::Module &Module) {
524 SymbolVendor &plugin = *Module.GetSymbolVendor();
Zachary Turnerc68925a2019-01-09 21:20:44 +0000525 Module.ParseAllDebugSymbols();
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000526
527 auto symfile = plugin.GetSymbolFile();
528 if (!symfile)
529 return make_string_error("Module has no symbol file.");
530
531 auto clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
532 symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus));
533 if (!clang_ast_ctx)
534 return make_string_error("Can't retrieve Clang AST context.");
535
536 auto ast_ctx = clang_ast_ctx->getASTContext();
537 if (!ast_ctx)
538 return make_string_error("Can't retrieve AST context.");
539
540 auto tu = ast_ctx->getTranslationUnitDecl();
541 if (!tu)
542 return make_string_error("Can't retrieve translation unit declaration.");
543
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000544 tu->print(outs());
545
546 return Error::success();
547}
548
Aaron Smith010edd32018-06-08 02:45:25 +0000549Error opts::symbols::verify(lldb_private::Module &Module) {
Pavel Labathe6954cb2018-06-12 12:57:36 +0000550 SymbolVendor &plugin = *Module.GetSymbolVendor();
Aaron Smith010edd32018-06-08 02:45:25 +0000551
Pavel Labathe6954cb2018-06-12 12:57:36 +0000552 SymbolFile *symfile = plugin.GetSymbolFile();
Aaron Smith010edd32018-06-08 02:45:25 +0000553 if (!symfile)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000554 return make_string_error("Module has no symbol file.");
Aaron Smith010edd32018-06-08 02:45:25 +0000555
556 uint32_t comp_units_count = symfile->GetNumCompileUnits();
557
558 outs() << "Found " << comp_units_count << " compile units.\n";
559
560 for (uint32_t i = 0; i < comp_units_count; i++) {
561 lldb::CompUnitSP comp_unit = symfile->ParseCompileUnitAtIndex(i);
562 if (!comp_unit)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000563 return make_string_error("Connot parse compile unit {0}.", i);
Aaron Smith010edd32018-06-08 02:45:25 +0000564
Pavel Labath9ea80d22018-06-28 10:03:42 +0000565 outs() << "Processing '" << comp_unit->GetFilename().AsCString()
566 << "' compile unit.\n";
Aaron Smith010edd32018-06-08 02:45:25 +0000567
568 LineTable *lt = comp_unit->GetLineTable();
569 if (!lt)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000570 return make_string_error("Can't get a line table of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000571
572 uint32_t count = lt->GetSize();
573
574 outs() << "The line table contains " << count << " entries.\n";
575
576 if (count == 0)
577 continue;
578
579 LineEntry le;
580 if (!lt->GetLineEntryAtIndex(0, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000581 return make_string_error("Can't get a line entry of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000582
583 for (uint32_t i = 1; i < count; i++) {
584 lldb::addr_t curr_end =
Pavel Labath9ea80d22018-06-28 10:03:42 +0000585 le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
Aaron Smith010edd32018-06-08 02:45:25 +0000586
587 if (!lt->GetLineEntryAtIndex(i, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000588 return make_string_error("Can't get a line entry of a compile unit");
Aaron Smith010edd32018-06-08 02:45:25 +0000589
590 if (curr_end > le.range.GetBaseAddress().GetFileAddress())
Pavel Labathe6954cb2018-06-12 12:57:36 +0000591 return make_string_error(
592 "Line table of a compile unit is inconsistent.");
Aaron Smith010edd32018-06-08 02:45:25 +0000593 }
594 }
595
596 outs() << "The symbol information is verified.\n";
597
598 return Error::success();
599}
600
Pavel Labath38d9ff72018-06-12 13:26:43 +0000601Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000602 if (Verify && DumpAST)
603 return make_string_error(
604 "Cannot both verify symbol information and dump AST.");
605
Pavel Labathe6954cb2018-06-12 12:57:36 +0000606 if (Verify) {
607 if (Find != FindType::None)
608 return make_string_error(
609 "Cannot both search and verify symbol information.");
Pavel Labath9ea80d22018-06-28 10:03:42 +0000610 if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
611 Line != 0)
612 return make_string_error(
613 "-regex, -context, -name, -file and -line options are not "
614 "applicable for symbol verification.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000615 return verify;
Pavel Labath90b0a532018-05-03 10:57:16 +0000616 }
617
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000618 if (DumpAST) {
619 if (Find != FindType::None)
Aaron Smith037ed1b2018-12-06 21:36:39 +0000620 return make_string_error("Cannot both search and dump AST.");
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000621 if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
622 Line != 0)
623 return make_string_error(
624 "-regex, -context, -name, -file and -line options are not "
625 "applicable for dumping AST.");
626 return dumpAST;
627 }
628
Pavel Labathe6954cb2018-06-12 12:57:36 +0000629 if (Regex && !Context.empty())
630 return make_string_error(
631 "Cannot search using both regular expressions and context.");
632
633 if (Regex && !RegularExpression(Name).IsValid())
634 return make_string_error("`{0}` is not a valid regular expression.", Name);
635
636 if (Regex + !Context.empty() + !File.empty() >= 2)
637 return make_string_error(
638 "Only one of -regex, -context and -file may be used simultaneously.");
639 if (Regex && Name.empty())
640 return make_string_error("-regex used without a -name");
641
642 switch (Find) {
643 case FindType::None:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000644 if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000645 return make_string_error(
646 "Specify search type (-find) to use search options.");
647 return dumpModule;
648
649 case FindType::Function:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000650 if (!File.empty() + (Line != 0) == 1)
651 return make_string_error("Both file name and line number must be "
652 "specified when searching a function "
653 "by file position.");
654 if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2)
655 return make_string_error("Only one of regular expression, function-flags "
656 "and file position may be used simultaneously "
657 "when searching a function.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000658 return findFunctions;
659
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000660 case FindType::Block:
661 if (File.empty() || Line == 0)
662 return make_string_error("Both file name and line number must be "
663 "specified when searching a block.");
664 if (Regex || getFunctionNameFlags() != 0)
665 return make_string_error("Cannot use regular expression or "
666 "function-flags for searching a block.");
667 return findBlocks;
668
Pavel Labathe6954cb2018-06-12 12:57:36 +0000669 case FindType::Namespace:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000670 if (Regex || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000671 return make_string_error("Cannot search for namespaces using regular "
Pavel Labath9ea80d22018-06-28 10:03:42 +0000672 "expressions, file names or line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000673 return findNamespaces;
674
675 case FindType::Type:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000676 if (Regex || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000677 return make_string_error("Cannot search for types using regular "
Pavel Labath9ea80d22018-06-28 10:03:42 +0000678 "expressions, file names or line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000679 return findTypes;
680
681 case FindType::Variable:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000682 if (Line != 0)
683 return make_string_error("Cannot search for variables "
684 "using line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000685 return findVariables;
686 }
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000687
688 llvm_unreachable("Unsupported symbol action.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000689}
690
691int opts::symbols::dumpSymbols(Debugger &Dbg) {
692 auto ActionOr = getAction();
693 if (!ActionOr) {
694 logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), "");
695 return 1;
696 }
697 auto Action = *ActionOr;
Pavel Labath90b0a532018-05-03 10:57:16 +0000698
Pavel Labath1cf23e12019-01-11 11:17:51 +0000699 outs() << "Module: " << InputFile << "\n";
700 ModuleSpec Spec{FileSpec(InputFile)};
701 StringRef Symbols = SymbolPath.empty() ? InputFile : SymbolPath;
702 Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native);
Zachary Turnera6d54642017-12-02 00:15:29 +0000703
Pavel Labath1cf23e12019-01-11 11:17:51 +0000704 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
705 SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
706 if (!Vendor) {
707 WithColor::error() << "Module has no symbol vendor.\n";
708 return 1;
Zachary Turnera6d54642017-12-02 00:15:29 +0000709 }
Pavel Labath1cf23e12019-01-11 11:17:51 +0000710
711 if (Error E = Action(*ModulePtr)) {
712 WithColor::error() << toString(std::move(E)) << "\n";
713 return 1;
714 }
715
716 return 0;
Zachary Turnera6d54642017-12-02 00:15:29 +0000717}
718
Pavel Labath280d2e82018-12-12 12:35:25 +0000719static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) {
720 size_t Count = List.GetNumSections(0);
721 if (Count == 0) {
722 Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : "");
723 return;
724 }
725 Printer.formatLine("Showing {0} {1}sections", Count,
726 is_subsection ? "sub" : "");
727 for (size_t I = 0; I < Count; ++I) {
728 auto S = List.GetSectionAtIndex(I);
729 assert(S);
730 AutoIndent Indent(Printer, 2);
731 Printer.formatLine("Index: {0}", I);
Pavel Labath0d38e4f2018-12-18 15:56:45 +0000732 Printer.formatLine("ID: {0:x}", S->GetID());
Pavel Labath280d2e82018-12-12 12:35:25 +0000733 Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
734 Printer.formatLine("Type: {0}", S->GetTypeAsCString());
Pavel Labath62a82542018-12-15 13:45:38 +0000735 Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions()));
Pavel Labathef8683a2018-12-12 15:46:18 +0000736 Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific());
Pavel Labath62a82542018-12-15 13:45:38 +0000737 Printer.formatLine("VM address: {0:x}", S->GetFileAddress());
Pavel Labath280d2e82018-12-12 12:35:25 +0000738 Printer.formatLine("VM size: {0}", S->GetByteSize());
739 Printer.formatLine("File size: {0}", S->GetFileSize());
740
741 if (opts::object::SectionContents) {
742 DataExtractor Data;
743 S->GetSectionData(Data);
744 ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()};
745 Printer.formatBinary("Data: ", Bytes, 0);
746 }
747
748 if (S->GetType() == eSectionTypeContainer)
749 dumpSectionList(Printer, S->GetChildren(), true);
750 Printer.NewLine();
751 }
752}
753
Pavel Labath62a7f802018-06-29 12:15:54 +0000754static int dumpObjectFiles(Debugger &Dbg) {
Zachary Turner888a4282017-12-01 00:52:51 +0000755 LinePrinter Printer(4, llvm::outs());
756
Pavel Labath90b0a532018-05-03 10:57:16 +0000757 int HadErrors = 0;
Pavel Labath62a7f802018-06-29 12:15:54 +0000758 for (const auto &File : opts::object::InputFilenames) {
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000759 ModuleSpec Spec{FileSpec(File)};
Zachary Turner888a4282017-12-01 00:52:51 +0000760
Zachary Turnera6d54642017-12-02 00:15:29 +0000761 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
Pavel Labath1f6b2472018-12-10 17:16:38 +0000762
763 ObjectFile *ObjectPtr = ModulePtr->GetObjectFile();
764 if (!ObjectPtr) {
765 WithColor::error() << File << " not recognised as an object file\n";
766 HadErrors = 1;
767 continue;
768 }
769
Pavel Labath96979ce2018-03-06 15:56:20 +0000770 // Fetch symbol vendor before we get the section list to give the symbol
771 // vendor a chance to populate it.
772 ModulePtr->GetSymbolVendor();
Zachary Turner888a4282017-12-01 00:52:51 +0000773 SectionList *Sections = ModulePtr->GetSectionList();
774 if (!Sections) {
775 llvm::errs() << "Could not load sections for module " << File << "\n";
Pavel Labath90b0a532018-05-03 10:57:16 +0000776 HadErrors = 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000777 continue;
778 }
779
Pavel Labath1f6b2472018-12-10 17:16:38 +0000780 Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName());
Pavel Labath62a7f802018-06-29 12:15:54 +0000781 Printer.formatLine("Architecture: {0}",
782 ModulePtr->GetArchitecture().GetTriple().getTriple());
783 Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
Pavel Labath1f6b2472018-12-10 17:16:38 +0000784 Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable());
785 Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped());
786 Printer.formatLine("Type: {0}", ObjectPtr->GetType());
787 Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata());
Pavel Labath976af432019-01-10 09:32:31 +0000788 Printer.formatLine("Base VM address: {0:x}",
789 ObjectPtr->GetBaseAddress().GetFileAddress());
Pavel Labath62a7f802018-06-29 12:15:54 +0000790
Pavel Labath280d2e82018-12-12 12:35:25 +0000791 dumpSectionList(Printer, *Sections, /*is_subsection*/ false);
Aaron Smith037ed1b2018-12-06 21:36:39 +0000792
793 if (opts::object::SectionDependentModules) {
794 // A non-empty section list ensures a valid object file.
795 auto Obj = ModulePtr->GetObjectFile();
796 FileSpecList Files;
797 auto Count = Obj->GetDependentModules(Files);
798 Printer.formatLine("Showing {0} dependent module(s)", Count);
799 for (size_t I = 0; I < Files.GetSize(); ++I) {
800 AutoIndent Indent(Printer, 2);
801 Printer.formatLine("Name: {0}",
802 Files.GetFileSpecAtIndex(I).GetCString());
803 }
804 Printer.NewLine();
805 }
Zachary Turner888a4282017-12-01 00:52:51 +0000806 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000807 return HadErrors;
Zachary Turner888a4282017-12-01 00:52:51 +0000808}
809
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000810bool opts::irmemorymap::evalMalloc(StringRef Line,
811 IRMemoryMapTestState &State) {
812 // ::= <label> = malloc <size> <alignment>
813 StringRef Label;
814 std::tie(Label, Line) = Line.split('=');
815 if (Line.empty())
816 return false;
817 Label = Label.trim();
818 Line = Line.trim();
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000819 size_t Size;
820 uint8_t Alignment;
821 int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment);
822 if (Matches != 2)
823 return false;
824
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000825 outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label,
826 Size, Alignment);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000827 if (!isPowerOf2_32(Alignment)) {
828 outs() << "Malloc error: alignment is not a power of 2\n";
829 exit(1);
830 }
831
Vedant Kumarf616b9d2018-05-31 22:09:00 +0000832 IRMemoryMap::AllocationPolicy AP =
833 UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly
834 : IRMemoryMap::eAllocationPolicyProcessOnly;
835
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000836 // Issue the malloc in the target process with "-rw" permissions.
837 const uint32_t Permissions = 0x3;
838 const bool ZeroMemory = false;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000839 Status ST;
840 addr_t Addr =
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000841 State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000842 if (ST.Fail()) {
843 outs() << formatv("Malloc error: {0}\n", ST);
844 return true;
845 }
846
847 // Print the result of the allocation before checking its validity.
848 outs() << formatv("Malloc: address = {0:x}\n", Addr);
849
850 // Check that the allocation is aligned.
851 if (!Addr || Addr % Alignment != 0) {
852 outs() << "Malloc error: zero or unaligned allocation detected\n";
853 exit(1);
854 }
855
Pavel Labatha352ed22018-12-27 09:32:04 +0000856 // In case of Size == 0, we still expect the returned address to be unique and
857 // non-overlapping.
858 addr_t EndOfRegion = Addr + std::max<size_t>(Size, 1);
859 if (State.Allocations.overlaps(Addr, EndOfRegion)) {
860 auto I = State.Allocations.find(Addr);
861 outs() << "Malloc error: overlapping allocation detected"
862 << formatv(", previous allocation at [{0:x}, {1:x})\n", I.start(),
863 I.stop());
864 exit(1);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000865 }
866
Aaron Smith037ed1b2018-12-06 21:36:39 +0000867 // Insert the new allocation into the interval map. Use unique allocation
868 // IDs to inhibit interval coalescing.
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000869 static unsigned AllocationID = 0;
Pavel Labatha352ed22018-12-27 09:32:04 +0000870 State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000871
872 // Store the label -> address mapping.
873 State.Label2AddrMap[Label] = Addr;
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000874
875 return true;
876}
877
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000878bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) {
879 // ::= free <label>
880 if (!Line.consume_front("free"))
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000881 return false;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000882 StringRef Label = Line.trim();
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000883
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000884 outs() << formatv("Command: free({0})\n", Label);
885 auto LabelIt = State.Label2AddrMap.find(Label);
886 if (LabelIt == State.Label2AddrMap.end()) {
887 outs() << "Free error: Invalid allocation label\n";
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000888 exit(1);
889 }
890
891 Status ST;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000892 addr_t Addr = LabelIt->getValue();
893 State.Map.Free(Addr, ST);
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000894 if (ST.Fail()) {
895 outs() << formatv("Free error: {0}\n", ST);
896 exit(1);
897 }
898
899 // Erase the allocation from the live interval map.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000900 auto Interval = State.Allocations.find(Addr);
901 if (Interval != State.Allocations.end()) {
902 outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(),
903 Interval.stop());
904 Interval.erase();
905 }
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000906
907 return true;
908}
909
910int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
911 // Set up a Target.
912 TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target);
913
914 // Set up a Process. In order to allocate memory within a target, this
915 // process must be alive and must support JIT'ing.
916 CommandReturnObject Result;
917 Dbg.SetAsyncExecution(false);
918 CommandInterpreter &CI = Dbg.GetCommandInterpreter();
919 auto IssueCmd = [&](const char *Cmd) -> bool {
920 return CI.HandleCommand(Cmd, eLazyBoolNo, Result);
921 };
922 if (!IssueCmd("b main") || !IssueCmd("run")) {
923 outs() << formatv("Failed: {0}\n", Result.GetErrorData());
924 exit(1);
925 }
926
927 ProcessSP Process = Target->GetProcessSP();
928 if (!Process || !Process->IsAlive() || !Process->CanJIT()) {
929 outs() << "Cannot use process to test IRMemoryMap\n";
930 exit(1);
931 }
932
933 // Set up an IRMemoryMap and associated testing state.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000934 IRMemoryMapTestState State(Target);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000935
936 // Parse and apply commands from the command file.
937 std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile);
938 StringRef Rest = MB->getBuffer();
939 while (!Rest.empty()) {
940 StringRef Line;
941 std::tie(Line, Rest) = Rest.split('\n');
942 Line = Line.ltrim();
943
944 if (Line.empty() || Line[0] == '#')
945 continue;
946
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000947 if (evalMalloc(Line, State))
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000948 continue;
949
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000950 if (evalFree(Line, State))
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000951 continue;
952
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000953 errs() << "Could not parse line: " << Line << "\n";
954 exit(1);
955 }
956 return 0;
957}
958
Zachary Turner888a4282017-12-01 00:52:51 +0000959int main(int argc, const char *argv[]) {
960 StringRef ToolName = argv[0];
961 sys::PrintStackTraceOnErrorSignal(ToolName);
962 PrettyStackTraceProgram X(argc, argv);
963 llvm_shutdown_obj Y;
964
965 cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
966
Pavel Labath90b0a532018-05-03 10:57:16 +0000967 SystemLifetimeManager DebuggerLifetime;
Jonas Devlieghere15eacd72018-12-03 17:28:29 +0000968 if (auto e = DebuggerLifetime.Initialize(
969 llvm::make_unique<SystemInitializerTest>(), {}, nullptr)) {
970 WithColor::error() << "initialization failed: " << toString(std::move(e))
971 << '\n';
972 return 1;
973 }
974
Pavel Labath90b0a532018-05-03 10:57:16 +0000975 CleanUp TerminateDebugger([&] { DebuggerLifetime.Terminate(); });
Zachary Turner888a4282017-12-01 00:52:51 +0000976
977 auto Dbg = lldb_private::Debugger::CreateInstance();
978
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000979 if (!opts::Log.empty())
980 Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, errs());
981
Pavel Labath7c945822018-02-26 18:50:16 +0000982 if (opts::BreakpointSubcommand)
Pavel Labath90b0a532018-05-03 10:57:16 +0000983 return opts::breakpoint::evaluateBreakpoints(*Dbg);
Pavel Labath62a7f802018-06-29 12:15:54 +0000984 if (opts::ObjectFileSubcommand)
985 return dumpObjectFiles(*Dbg);
Pavel Labath90b0a532018-05-03 10:57:16 +0000986 if (opts::SymbolsSubcommand)
987 return opts::symbols::dumpSymbols(*Dbg);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000988 if (opts::IRMemoryMapSubcommand)
989 return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
Zachary Turner888a4282017-12-01 00:52:51 +0000990
Pavel Labath90b0a532018-05-03 10:57:16 +0000991 WithColor::error() << "No command specified.\n";
992 return 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000993}