blob: 42eb5642f972048c0eb35cf3d207b23dfab6f1a4 [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"
Zachary Turnera6d54642017-12-02 00:15:29 +000033#include "lldb/Utility/StreamString.h"
Zachary Turner888a4282017-12-01 00:52:51 +000034
Vedant Kumarc1cd8262018-05-30 19:39:10 +000035#include "llvm/ADT/IntervalMap.h"
Zachary Turner888a4282017-12-01 00:52:51 +000036#include "llvm/ADT/StringRef.h"
37#include "llvm/Support/CommandLine.h"
38#include "llvm/Support/ManagedStatic.h"
Pavel Labath9ea80d22018-06-28 10:03:42 +000039#include "llvm/Support/MathExtras.h"
Pavel Labath7c945822018-02-26 18:50:16 +000040#include "llvm/Support/Path.h"
Zachary Turner888a4282017-12-01 00:52:51 +000041#include "llvm/Support/PrettyStackTrace.h"
42#include "llvm/Support/Signals.h"
Pavel Labath90b0a532018-05-03 10:57:16 +000043#include "llvm/Support/WithColor.h"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000044#include <cstdio>
Zachary Turner888a4282017-12-01 00:52:51 +000045#include <thread>
46
47using namespace lldb;
48using namespace lldb_private;
49using namespace llvm;
50
51namespace opts {
Pavel Labath7c945822018-02-26 18:50:16 +000052static cl::SubCommand BreakpointSubcommand("breakpoints",
53 "Test breakpoint resolution");
Pavel Labath62a7f802018-06-29 12:15:54 +000054cl::SubCommand ObjectFileSubcommand("object-file",
55 "Display LLDB object file information");
Zachary Turnera6d54642017-12-02 00:15:29 +000056cl::SubCommand SymbolsSubcommand("symbols", "Dump symbols for an object file");
Vedant Kumarc1cd8262018-05-30 19:39:10 +000057cl::SubCommand IRMemoryMapSubcommand("ir-memory-map", "Test IRMemoryMap");
Vedant Kumar7e4c84a2018-05-31 22:09:00 +000058
Vedant Kumarc1cd8262018-05-30 19:39:10 +000059cl::opt<std::string> Log("log", cl::desc("Path to a log file"), cl::init(""),
Vedant Kumar7e4c84a2018-05-31 22:09:00 +000060 cl::sub(BreakpointSubcommand),
Pavel Labath62a7f802018-06-29 12:15:54 +000061 cl::sub(ObjectFileSubcommand),
62 cl::sub(SymbolsSubcommand),
Vedant Kumarc1cd8262018-05-30 19:39:10 +000063 cl::sub(IRMemoryMapSubcommand));
64
65/// Create a target using the file pointed to by \p Filename, or abort.
66TargetSP createTarget(Debugger &Dbg, const std::string &Filename);
67
68/// Read \p Filename into a null-terminated buffer, or abort.
69std::unique_ptr<MemoryBuffer> openFile(const std::string &Filename);
Zachary Turner888a4282017-12-01 00:52:51 +000070
Pavel Labath7c945822018-02-26 18:50:16 +000071namespace breakpoint {
72static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
73 cl::Required, cl::sub(BreakpointSubcommand));
74static cl::opt<std::string> CommandFile(cl::Positional,
75 cl::desc("<command-file>"),
76 cl::init("-"),
77 cl::sub(BreakpointSubcommand));
78static cl::opt<bool> Persistent(
79 "persistent",
80 cl::desc("Don't automatically remove all breakpoints before each command"),
81 cl::sub(BreakpointSubcommand));
82
83static llvm::StringRef plural(uintmax_t value) { return value == 1 ? "" : "s"; }
84static void dumpState(const BreakpointList &List, LinePrinter &P);
85static std::string substitute(StringRef Cmd);
Pavel Labath90b0a532018-05-03 10:57:16 +000086static int evaluateBreakpoints(Debugger &Dbg);
Pavel Labath7c945822018-02-26 18:50:16 +000087} // namespace breakpoint
88
Pavel Labath62a7f802018-06-29 12:15:54 +000089namespace object {
Zachary Turner888a4282017-12-01 00:52:51 +000090cl::opt<bool> SectionContents("contents",
91 cl::desc("Dump each section's contents"),
Pavel Labath62a7f802018-06-29 12:15:54 +000092 cl::sub(ObjectFileSubcommand));
Aaron Smith037ed1b2018-12-06 21:36:39 +000093cl::opt<bool> SectionDependentModules("dep-modules",
94 cl::desc("Dump each dependent module"),
95 cl::sub(ObjectFileSubcommand));
Zachary Turner888a4282017-12-01 00:52:51 +000096cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
Pavel Labath62a7f802018-06-29 12:15:54 +000097 cl::OneOrMore,
98 cl::sub(ObjectFileSubcommand));
99} // namespace object
Zachary Turnera6d54642017-12-02 00:15:29 +0000100
101namespace symbols {
Pavel Labath90b0a532018-05-03 10:57:16 +0000102static cl::list<std::string> InputFilenames(cl::Positional,
103 cl::desc("<input files>"),
104 cl::OneOrMore,
105 cl::sub(SymbolsSubcommand));
106enum class FindType {
107 None,
108 Function,
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000109 Block,
Pavel Labath90b0a532018-05-03 10:57:16 +0000110 Namespace,
111 Type,
112 Variable,
113};
114static cl::opt<FindType> Find(
115 "find", cl::desc("Choose search type:"),
116 cl::values(
Pavel Labath9ea80d22018-06-28 10:03:42 +0000117 clEnumValN(FindType::None, "none", "No search, just dump the module."),
Pavel Labath90b0a532018-05-03 10:57:16 +0000118 clEnumValN(FindType::Function, "function", "Find functions."),
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000119 clEnumValN(FindType::Block, "block", "Find blocks."),
Pavel Labath90b0a532018-05-03 10:57:16 +0000120 clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
121 clEnumValN(FindType::Type, "type", "Find types."),
122 clEnumValN(FindType::Variable, "variable", "Find global variables.")),
123 cl::sub(SymbolsSubcommand));
124
125static cl::opt<std::string> Name("name", cl::desc("Name to find."),
126 cl::sub(SymbolsSubcommand));
127static cl::opt<bool>
128 Regex("regex",
129 cl::desc("Search using regular expressions (avaliable for variables "
130 "and functions only)."),
131 cl::sub(SymbolsSubcommand));
132static cl::opt<std::string>
133 Context("context",
134 cl::desc("Restrict search to the context of the given variable."),
135 cl::value_desc("variable"), cl::sub(SymbolsSubcommand));
136
137static cl::list<FunctionNameType> FunctionNameFlags(
138 "function-flags", cl::desc("Function search flags:"),
139 cl::values(clEnumValN(eFunctionNameTypeAuto, "auto",
140 "Automatically deduce flags based on name."),
141 clEnumValN(eFunctionNameTypeFull, "full", "Full function name."),
142 clEnumValN(eFunctionNameTypeBase, "base", "Base name."),
143 clEnumValN(eFunctionNameTypeMethod, "method", "Method name."),
144 clEnumValN(eFunctionNameTypeSelector, "selector",
145 "Selector name.")),
146 cl::sub(SymbolsSubcommand));
147static FunctionNameType getFunctionNameFlags() {
148 FunctionNameType Result = FunctionNameType(0);
149 for (FunctionNameType Flag : FunctionNameFlags)
150 Result = FunctionNameType(Result | Flag);
151 return Result;
152}
153
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000154static cl::opt<bool> DumpAST("dump-ast",
155 cl::desc("Dump AST restored from symbols."),
156 cl::sub(SymbolsSubcommand));
157
Aaron Smith010edd32018-06-08 02:45:25 +0000158static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
159 cl::sub(SymbolsSubcommand));
160
Pavel Labathe6954cb2018-06-12 12:57:36 +0000161static cl::opt<std::string> File("file",
162 cl::desc("File (compile unit) to search."),
163 cl::sub(SymbolsSubcommand));
Pavel Labath9ea80d22018-06-28 10:03:42 +0000164static cl::opt<int> Line("line", cl::desc("Line to search."),
165 cl::sub(SymbolsSubcommand));
Pavel Labathe6954cb2018-06-12 12:57:36 +0000166
Pavel Labath90b0a532018-05-03 10:57:16 +0000167static Expected<CompilerDeclContext> getDeclContext(SymbolVendor &Vendor);
168
169static Error findFunctions(lldb_private::Module &Module);
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000170static Error findBlocks(lldb_private::Module &Module);
Pavel Labath90b0a532018-05-03 10:57:16 +0000171static Error findNamespaces(lldb_private::Module &Module);
172static Error findTypes(lldb_private::Module &Module);
173static Error findVariables(lldb_private::Module &Module);
174static Error dumpModule(lldb_private::Module &Module);
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000175static Error dumpAST(lldb_private::Module &Module);
Aaron Smith010edd32018-06-08 02:45:25 +0000176static Error verify(lldb_private::Module &Module);
Pavel Labath90b0a532018-05-03 10:57:16 +0000177
Pavel Labath38d9ff72018-06-12 13:26:43 +0000178static Expected<Error (*)(lldb_private::Module &)> getAction();
Pavel Labath90b0a532018-05-03 10:57:16 +0000179static int dumpSymbols(Debugger &Dbg);
Pavel Labath9ea80d22018-06-28 10:03:42 +0000180} // namespace symbols
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000181
182namespace irmemorymap {
183static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
184 cl::Required,
185 cl::sub(IRMemoryMapSubcommand));
186static cl::opt<std::string> CommandFile(cl::Positional,
187 cl::desc("<command-file>"),
188 cl::init("-"),
189 cl::sub(IRMemoryMapSubcommand));
Vedant Kumarf616b9d2018-05-31 22:09:00 +0000190static cl::opt<bool> UseHostOnlyAllocationPolicy(
191 "host-only", cl::desc("Use the host-only allocation policy"),
192 cl::init(false), cl::sub(IRMemoryMapSubcommand));
193
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000194using AllocationT = std::pair<addr_t, addr_t>;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000195using AddrIntervalMap =
Pavel Labath9ea80d22018-06-28 10:03:42 +0000196 IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000197
198struct IRMemoryMapTestState {
199 TargetSP Target;
200 IRMemoryMap Map;
201
202 AddrIntervalMap::Allocator IntervalMapAllocator;
203 AddrIntervalMap Allocations;
204
205 StringMap<addr_t> Label2AddrMap;
206
207 IRMemoryMapTestState(TargetSP Target)
208 : Target(Target), Map(Target), Allocations(IntervalMapAllocator) {}
209};
210
211bool areAllocationsOverlapping(const AllocationT &L, const AllocationT &R);
212bool evalMalloc(StringRef Line, IRMemoryMapTestState &State);
213bool evalFree(StringRef Line, IRMemoryMapTestState &State);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000214int evaluateMemoryMapCommands(Debugger &Dbg);
215} // namespace irmemorymap
216
Zachary Turner888a4282017-12-01 00:52:51 +0000217} // namespace opts
218
Pavel Labathe6954cb2018-06-12 12:57:36 +0000219template <typename... Args>
220static Error make_string_error(const char *Format, Args &&... args) {
221 return llvm::make_error<llvm::StringError>(
222 llvm::formatv(Format, std::forward<Args>(args)...).str(),
223 llvm::inconvertibleErrorCode());
224}
225
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000226TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) {
227 TargetSP Target;
Jonas Devliegheref9a07e92018-09-20 09:09:05 +0000228 Status ST = Dbg.GetTargetList().CreateTarget(
229 Dbg, Filename, /*triple*/ "", eLoadDependentsNo,
230 /*platform_options*/ nullptr, Target);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000231 if (ST.Fail()) {
232 errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST);
233 exit(1);
234 }
235 return Target;
236}
237
238std::unique_ptr<MemoryBuffer> opts::openFile(const std::string &Filename) {
239 auto MB = MemoryBuffer::getFileOrSTDIN(Filename);
240 if (!MB) {
241 errs() << formatv("Could not open file '{0}: {1}\n", Filename,
242 MB.getError().message());
243 exit(1);
244 }
245 return std::move(*MB);
246}
247
Pavel Labath7c945822018-02-26 18:50:16 +0000248void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) {
249 P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize()));
250 if (List.GetSize() > 0)
251 P.formatLine("At least one breakpoint.");
252 for (size_t i = 0, e = List.GetSize(); i < e; ++i) {
253 BreakpointSP BP = List.GetBreakpointAtIndex(i);
254 P.formatLine("Breakpoint ID {0}:", BP->GetID());
255 AutoIndent Indent(P, 2);
256 P.formatLine("{0} location{1}.", BP->GetNumLocations(),
257 plural(BP->GetNumLocations()));
258 if (BP->GetNumLocations() > 0)
259 P.formatLine("At least one location.");
260 P.formatLine("{0} resolved location{1}.", BP->GetNumResolvedLocations(),
261 plural(BP->GetNumResolvedLocations()));
262 if (BP->GetNumResolvedLocations() > 0)
263 P.formatLine("At least one resolved location.");
264 for (size_t l = 0, le = BP->GetNumLocations(); l < le; ++l) {
265 BreakpointLocationSP Loc = BP->GetLocationAtIndex(l);
266 P.formatLine("Location ID {0}:", Loc->GetID());
267 AutoIndent Indent(P, 2);
268 P.formatLine("Enabled: {0}", Loc->IsEnabled());
269 P.formatLine("Resolved: {0}", Loc->IsResolved());
Jim Ingham08581262018-03-12 21:17:04 +0000270 SymbolContext sc;
271 Loc->GetAddress().CalculateSymbolContext(&sc);
272 lldb_private::StreamString S;
273 sc.DumpStopContext(&S, BP->GetTarget().GetProcessSP().get(),
274 Loc->GetAddress(), false, true, false, true, true);
275 P.formatLine("Address: {0}", S.GetString());
Pavel Labath7c945822018-02-26 18:50:16 +0000276 }
277 }
278 P.NewLine();
279}
280
281std::string opts::breakpoint::substitute(StringRef Cmd) {
282 std::string Result;
283 raw_string_ostream OS(Result);
284 while (!Cmd.empty()) {
285 switch (Cmd[0]) {
286 case '%':
287 if (Cmd.consume_front("%p") && (Cmd.empty() || !isalnum(Cmd[0]))) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000288 OS << sys::path::parent_path(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000289 break;
290 }
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000291 LLVM_FALLTHROUGH;
Pavel Labath7c945822018-02-26 18:50:16 +0000292 default:
293 size_t pos = Cmd.find('%');
294 OS << Cmd.substr(0, pos);
295 Cmd = Cmd.substr(pos);
296 break;
297 }
298 }
299 return std::move(OS.str());
300}
301
Pavel Labath90b0a532018-05-03 10:57:16 +0000302int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000303 TargetSP Target = opts::createTarget(Dbg, breakpoint::Target);
304 std::unique_ptr<MemoryBuffer> MB = opts::openFile(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000305
306 LinePrinter P(4, outs());
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000307 StringRef Rest = MB->getBuffer();
Pavel Labath90b0a532018-05-03 10:57:16 +0000308 int HadErrors = 0;
Pavel Labath7c945822018-02-26 18:50:16 +0000309 while (!Rest.empty()) {
310 StringRef Line;
311 std::tie(Line, Rest) = Rest.split('\n');
312 Line = Line.ltrim();
313 if (Line.empty() || Line[0] == '#')
314 continue;
315
316 if (!Persistent)
317 Target->RemoveAllBreakpoints(/*internal_also*/ true);
318
319 std::string Command = substitute(Line);
320 P.formatLine("Command: {0}", Command);
321 CommandReturnObject Result;
322 if (!Dbg.GetCommandInterpreter().HandleCommand(
323 Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
324 P.formatLine("Failed: {0}", Result.GetErrorData());
Pavel Labath90b0a532018-05-03 10:57:16 +0000325 HadErrors = 1;
Pavel Labath7c945822018-02-26 18:50:16 +0000326 continue;
327 }
328
329 dumpState(Target->GetBreakpointList(/*internal*/ false), P);
330 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000331 return HadErrors;
Pavel Labath7c945822018-02-26 18:50:16 +0000332}
333
Pavel Labath90b0a532018-05-03 10:57:16 +0000334Expected<CompilerDeclContext>
335opts::symbols::getDeclContext(SymbolVendor &Vendor) {
336 if (Context.empty())
337 return CompilerDeclContext();
338 VariableList List;
Pavel Labath34cda142018-05-31 09:46:26 +0000339 Vendor.FindGlobalVariables(ConstString(Context), nullptr, UINT32_MAX, List);
Pavel Labathe6954cb2018-06-12 12:57:36 +0000340 if (List.Empty())
341 return make_string_error("Context search didn't find a match.");
342 if (List.GetSize() > 1)
343 return make_string_error("Context search found multiple matches.");
Pavel Labath90b0a532018-05-03 10:57:16 +0000344 return List.GetVariableAtIndex(0)->GetDeclContext();
345}
346
347Error opts::symbols::findFunctions(lldb_private::Module &Module) {
348 SymbolVendor &Vendor = *Module.GetSymbolVendor();
349 SymbolContextList List;
Pavel Labath9ea80d22018-06-28 10:03:42 +0000350 if (!File.empty()) {
351 assert(Line != 0);
352
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000353 FileSpec src_file(File);
Pavel Labath9ea80d22018-06-28 10:03:42 +0000354 size_t cu_count = Module.GetNumCompileUnits();
355 for (size_t i = 0; i < cu_count; i++) {
356 lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
357 if (!cu_sp)
358 continue;
359
360 LineEntry le;
361 cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
362 if (!le.IsValid())
363 continue;
364
365 auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress();
366 if (!addr.IsValid())
367 continue;
368
369 SymbolContext sc;
370 uint32_t resolved =
371 addr.CalculateSymbolContext(&sc, eSymbolContextFunction);
372 if (resolved & eSymbolContextFunction)
373 List.Append(sc);
374 }
375 } else if (Regex) {
Pavel Labath90b0a532018-05-03 10:57:16 +0000376 RegularExpression RE(Name);
377 assert(RE.IsValid());
378 Vendor.FindFunctions(RE, true, false, List);
379 } else {
380 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
381 if (!ContextOr)
382 return ContextOr.takeError();
383 CompilerDeclContext *ContextPtr =
384 ContextOr->IsValid() ? &*ContextOr : nullptr;
385
386 Vendor.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
Pavel Labath9ea80d22018-06-28 10:03:42 +0000387 true, false, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000388 }
389 outs() << formatv("Found {0} functions:\n", List.GetSize());
390 StreamString Stream;
391 List.Dump(&Stream, nullptr);
392 outs() << Stream.GetData() << "\n";
393 return Error::success();
394}
395
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000396Error opts::symbols::findBlocks(lldb_private::Module &Module) {
397 assert(!Regex);
398 assert(!File.empty());
399 assert(Line != 0);
400
401 SymbolContextList List;
402
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000403 FileSpec src_file(File);
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000404 size_t cu_count = Module.GetNumCompileUnits();
405 for (size_t i = 0; i < cu_count; i++) {
406 lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
407 if (!cu_sp)
408 continue;
409
410 LineEntry le;
411 cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
412 if (!le.IsValid())
413 continue;
414
415 auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress();
416 if (!addr.IsValid())
417 continue;
418
419 SymbolContext sc;
420 uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock);
421 if (resolved & eSymbolContextBlock)
422 List.Append(sc);
423 }
424
425 outs() << formatv("Found {0} blocks:\n", List.GetSize());
426 StreamString Stream;
427 List.Dump(&Stream, nullptr);
428 outs() << Stream.GetData() << "\n";
429 return Error::success();
430}
431
Pavel Labath90b0a532018-05-03 10:57:16 +0000432Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
433 SymbolVendor &Vendor = *Module.GetSymbolVendor();
434 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
435 if (!ContextOr)
436 return ContextOr.takeError();
437 CompilerDeclContext *ContextPtr =
438 ContextOr->IsValid() ? &*ContextOr : nullptr;
439
440 SymbolContext SC;
441 CompilerDeclContext Result =
442 Vendor.FindNamespace(SC, ConstString(Name), ContextPtr);
443 if (Result)
444 outs() << "Found namespace: "
445 << Result.GetScopeQualifiedName().GetStringRef() << "\n";
446 else
447 outs() << "Namespace not found.\n";
448 return Error::success();
449}
450
451Error opts::symbols::findTypes(lldb_private::Module &Module) {
452 SymbolVendor &Vendor = *Module.GetSymbolVendor();
453 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
454 if (!ContextOr)
455 return ContextOr.takeError();
456 CompilerDeclContext *ContextPtr =
457 ContextOr->IsValid() ? &*ContextOr : nullptr;
458
459 SymbolContext SC;
460 DenseSet<SymbolFile *> SearchedFiles;
461 TypeMap Map;
462 Vendor.FindTypes(SC, ConstString(Name), ContextPtr, true, UINT32_MAX,
Pavel Labath9ea80d22018-06-28 10:03:42 +0000463 SearchedFiles, Map);
Pavel Labath90b0a532018-05-03 10:57:16 +0000464
465 outs() << formatv("Found {0} types:\n", Map.GetSize());
466 StreamString Stream;
467 Map.Dump(&Stream, false);
468 outs() << Stream.GetData() << "\n";
469 return Error::success();
470}
471
472Error opts::symbols::findVariables(lldb_private::Module &Module) {
473 SymbolVendor &Vendor = *Module.GetSymbolVendor();
474 VariableList List;
475 if (Regex) {
476 RegularExpression RE(Name);
477 assert(RE.IsValid());
Pavel Labath34cda142018-05-31 09:46:26 +0000478 Vendor.FindGlobalVariables(RE, UINT32_MAX, List);
Pavel Labathe6954cb2018-06-12 12:57:36 +0000479 } else if (!File.empty()) {
480 CompUnitSP CU;
481 for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) {
482 CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind);
483 if (!Candidate || Candidate->GetFilename().GetStringRef() != File)
484 continue;
485 if (CU)
486 return make_string_error("Multiple compile units for file `{0}` found.",
487 File);
488 CU = std::move(Candidate);
489 }
490
491 if (!CU)
492 return make_string_error("Compile unit `{0}` not found.", File);
493
494 List.AddVariables(CU->GetVariableList(true).get());
Pavel Labath90b0a532018-05-03 10:57:16 +0000495 } else {
496 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
497 if (!ContextOr)
498 return ContextOr.takeError();
499 CompilerDeclContext *ContextPtr =
500 ContextOr->IsValid() ? &*ContextOr : nullptr;
501
Pavel Labath34cda142018-05-31 09:46:26 +0000502 Vendor.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000503 }
504 outs() << formatv("Found {0} variables:\n", List.GetSize());
505 StreamString Stream;
506 List.Dump(&Stream, false);
507 outs() << Stream.GetData() << "\n";
508 return Error::success();
509}
510
511Error opts::symbols::dumpModule(lldb_private::Module &Module) {
512 StreamString Stream;
513 Module.ParseAllDebugSymbols();
514 Module.Dump(&Stream);
515 outs() << Stream.GetData() << "\n";
516 return Error::success();
517}
518
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000519Error opts::symbols::dumpAST(lldb_private::Module &Module) {
520 SymbolVendor &plugin = *Module.GetSymbolVendor();
521
522 auto symfile = plugin.GetSymbolFile();
523 if (!symfile)
524 return make_string_error("Module has no symbol file.");
525
526 auto clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
527 symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus));
528 if (!clang_ast_ctx)
529 return make_string_error("Can't retrieve Clang AST context.");
530
531 auto ast_ctx = clang_ast_ctx->getASTContext();
532 if (!ast_ctx)
533 return make_string_error("Can't retrieve AST context.");
534
535 auto tu = ast_ctx->getTranslationUnitDecl();
536 if (!tu)
537 return make_string_error("Can't retrieve translation unit declaration.");
538
539 symfile->ParseDeclsForContext(CompilerDeclContext(
540 clang_ast_ctx, static_cast<clang::DeclContext *>(tu)));
541
542 tu->print(outs());
543
544 return Error::success();
545}
546
Aaron Smith010edd32018-06-08 02:45:25 +0000547Error opts::symbols::verify(lldb_private::Module &Module) {
Pavel Labathe6954cb2018-06-12 12:57:36 +0000548 SymbolVendor &plugin = *Module.GetSymbolVendor();
Aaron Smith010edd32018-06-08 02:45:25 +0000549
Pavel Labathe6954cb2018-06-12 12:57:36 +0000550 SymbolFile *symfile = plugin.GetSymbolFile();
Aaron Smith010edd32018-06-08 02:45:25 +0000551 if (!symfile)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000552 return make_string_error("Module has no symbol file.");
Aaron Smith010edd32018-06-08 02:45:25 +0000553
554 uint32_t comp_units_count = symfile->GetNumCompileUnits();
555
556 outs() << "Found " << comp_units_count << " compile units.\n";
557
558 for (uint32_t i = 0; i < comp_units_count; i++) {
559 lldb::CompUnitSP comp_unit = symfile->ParseCompileUnitAtIndex(i);
560 if (!comp_unit)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000561 return make_string_error("Connot parse compile unit {0}.", i);
Aaron Smith010edd32018-06-08 02:45:25 +0000562
Pavel Labath9ea80d22018-06-28 10:03:42 +0000563 outs() << "Processing '" << comp_unit->GetFilename().AsCString()
564 << "' compile unit.\n";
Aaron Smith010edd32018-06-08 02:45:25 +0000565
566 LineTable *lt = comp_unit->GetLineTable();
567 if (!lt)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000568 return make_string_error("Can't get a line table of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000569
570 uint32_t count = lt->GetSize();
571
572 outs() << "The line table contains " << count << " entries.\n";
573
574 if (count == 0)
575 continue;
576
577 LineEntry le;
578 if (!lt->GetLineEntryAtIndex(0, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000579 return make_string_error("Can't get a line entry of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000580
581 for (uint32_t i = 1; i < count; i++) {
582 lldb::addr_t curr_end =
Pavel Labath9ea80d22018-06-28 10:03:42 +0000583 le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
Aaron Smith010edd32018-06-08 02:45:25 +0000584
585 if (!lt->GetLineEntryAtIndex(i, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000586 return make_string_error("Can't get a line entry of a compile unit");
Aaron Smith010edd32018-06-08 02:45:25 +0000587
588 if (curr_end > le.range.GetBaseAddress().GetFileAddress())
Pavel Labathe6954cb2018-06-12 12:57:36 +0000589 return make_string_error(
590 "Line table of a compile unit is inconsistent.");
Aaron Smith010edd32018-06-08 02:45:25 +0000591 }
592 }
593
594 outs() << "The symbol information is verified.\n";
595
596 return Error::success();
597}
598
Pavel Labath38d9ff72018-06-12 13:26:43 +0000599Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000600 if (Verify && DumpAST)
601 return make_string_error(
602 "Cannot both verify symbol information and dump AST.");
603
Pavel Labathe6954cb2018-06-12 12:57:36 +0000604 if (Verify) {
605 if (Find != FindType::None)
606 return make_string_error(
607 "Cannot both search and verify symbol information.");
Pavel Labath9ea80d22018-06-28 10:03:42 +0000608 if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
609 Line != 0)
610 return make_string_error(
611 "-regex, -context, -name, -file and -line options are not "
612 "applicable for symbol verification.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000613 return verify;
Pavel Labath90b0a532018-05-03 10:57:16 +0000614 }
615
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000616 if (DumpAST) {
617 if (Find != FindType::None)
Aaron Smith037ed1b2018-12-06 21:36:39 +0000618 return make_string_error("Cannot both search and dump AST.");
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000619 if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
620 Line != 0)
621 return make_string_error(
622 "-regex, -context, -name, -file and -line options are not "
623 "applicable for dumping AST.");
624 return dumpAST;
625 }
626
Pavel Labathe6954cb2018-06-12 12:57:36 +0000627 if (Regex && !Context.empty())
628 return make_string_error(
629 "Cannot search using both regular expressions and context.");
630
631 if (Regex && !RegularExpression(Name).IsValid())
632 return make_string_error("`{0}` is not a valid regular expression.", Name);
633
634 if (Regex + !Context.empty() + !File.empty() >= 2)
635 return make_string_error(
636 "Only one of -regex, -context and -file may be used simultaneously.");
637 if (Regex && Name.empty())
638 return make_string_error("-regex used without a -name");
639
640 switch (Find) {
641 case FindType::None:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000642 if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000643 return make_string_error(
644 "Specify search type (-find) to use search options.");
645 return dumpModule;
646
647 case FindType::Function:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000648 if (!File.empty() + (Line != 0) == 1)
649 return make_string_error("Both file name and line number must be "
650 "specified when searching a function "
651 "by file position.");
652 if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2)
653 return make_string_error("Only one of regular expression, function-flags "
654 "and file position may be used simultaneously "
655 "when searching a function.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000656 return findFunctions;
657
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000658 case FindType::Block:
659 if (File.empty() || Line == 0)
660 return make_string_error("Both file name and line number must be "
661 "specified when searching a block.");
662 if (Regex || getFunctionNameFlags() != 0)
663 return make_string_error("Cannot use regular expression or "
664 "function-flags for searching a block.");
665 return findBlocks;
666
Pavel Labathe6954cb2018-06-12 12:57:36 +0000667 case FindType::Namespace:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000668 if (Regex || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000669 return make_string_error("Cannot search for namespaces using regular "
Pavel Labath9ea80d22018-06-28 10:03:42 +0000670 "expressions, file names or line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000671 return findNamespaces;
672
673 case FindType::Type:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000674 if (Regex || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000675 return make_string_error("Cannot search for types using regular "
Pavel Labath9ea80d22018-06-28 10:03:42 +0000676 "expressions, file names or line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000677 return findTypes;
678
679 case FindType::Variable:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000680 if (Line != 0)
681 return make_string_error("Cannot search for variables "
682 "using line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000683 return findVariables;
684 }
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000685
686 llvm_unreachable("Unsupported symbol action.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000687}
688
689int opts::symbols::dumpSymbols(Debugger &Dbg) {
690 auto ActionOr = getAction();
691 if (!ActionOr) {
692 logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), "");
693 return 1;
694 }
695 auto Action = *ActionOr;
Pavel Labath90b0a532018-05-03 10:57:16 +0000696
697 int HadErrors = 0;
698 for (const auto &File : InputFilenames) {
699 outs() << "Module: " << File << "\n";
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000700 ModuleSpec Spec{FileSpec(File)};
701 Spec.GetSymbolFileSpec().SetFile(File, FileSpec::Style::native);
Zachary Turnera6d54642017-12-02 00:15:29 +0000702
703 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
Pavel Labath90b0a532018-05-03 10:57:16 +0000704 SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
705 if (!Vendor) {
706 WithColor::error() << "Module has no symbol vendor.\n";
707 HadErrors = 1;
708 continue;
709 }
Pavel Labathe6954cb2018-06-12 12:57:36 +0000710
Pavel Labath90b0a532018-05-03 10:57:16 +0000711 if (Error E = Action(*ModulePtr)) {
712 WithColor::error() << toString(std::move(E)) << "\n";
713 HadErrors = 1;
714 }
Zachary Turnera6d54642017-12-02 00:15:29 +0000715
Pavel Labath90b0a532018-05-03 10:57:16 +0000716 outs().flush();
Zachary Turnera6d54642017-12-02 00:15:29 +0000717 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000718 return HadErrors;
Zachary Turnera6d54642017-12-02 00:15:29 +0000719}
720
Pavel Labath62a7f802018-06-29 12:15:54 +0000721static int dumpObjectFiles(Debugger &Dbg) {
Zachary Turner888a4282017-12-01 00:52:51 +0000722 LinePrinter Printer(4, llvm::outs());
723
Pavel Labath90b0a532018-05-03 10:57:16 +0000724 int HadErrors = 0;
Pavel Labath62a7f802018-06-29 12:15:54 +0000725 for (const auto &File : opts::object::InputFilenames) {
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000726 ModuleSpec Spec{FileSpec(File)};
Zachary Turner888a4282017-12-01 00:52:51 +0000727
Zachary Turnera6d54642017-12-02 00:15:29 +0000728 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
Pavel Labath96979ce2018-03-06 15:56:20 +0000729 // Fetch symbol vendor before we get the section list to give the symbol
730 // vendor a chance to populate it.
731 ModulePtr->GetSymbolVendor();
Zachary Turner888a4282017-12-01 00:52:51 +0000732 SectionList *Sections = ModulePtr->GetSectionList();
733 if (!Sections) {
734 llvm::errs() << "Could not load sections for module " << File << "\n";
Pavel Labath90b0a532018-05-03 10:57:16 +0000735 HadErrors = 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000736 continue;
737 }
738
Pavel Labath62a7f802018-06-29 12:15:54 +0000739 Printer.formatLine("Architecture: {0}",
740 ModulePtr->GetArchitecture().GetTriple().getTriple());
741 Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
742
Zachary Turner888a4282017-12-01 00:52:51 +0000743 size_t Count = Sections->GetNumSections(0);
744 Printer.formatLine("Showing {0} sections", Count);
745 for (size_t I = 0; I < Count; ++I) {
746 AutoIndent Indent(Printer, 2);
747 auto S = Sections->GetSectionAtIndex(I);
748 assert(S);
749 Printer.formatLine("Index: {0}", I);
750 Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
Jan Kratochvile4777a92018-04-29 19:47:48 +0000751 Printer.formatLine("Type: {0}", S->GetTypeAsCString());
Pavel Labathe2867bc2017-12-15 14:23:58 +0000752 Printer.formatLine("VM size: {0}", S->GetByteSize());
753 Printer.formatLine("File size: {0}", S->GetFileSize());
Zachary Turner888a4282017-12-01 00:52:51 +0000754
Pavel Labath62a7f802018-06-29 12:15:54 +0000755 if (opts::object::SectionContents) {
Zachary Turner888a4282017-12-01 00:52:51 +0000756 DataExtractor Data;
757 S->GetSectionData(Data);
758 ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()};
759 Printer.formatBinary("Data: ", Bytes, 0);
760 }
761 Printer.NewLine();
762 }
Aaron Smith037ed1b2018-12-06 21:36:39 +0000763
764 if (opts::object::SectionDependentModules) {
765 // A non-empty section list ensures a valid object file.
766 auto Obj = ModulePtr->GetObjectFile();
767 FileSpecList Files;
768 auto Count = Obj->GetDependentModules(Files);
769 Printer.formatLine("Showing {0} dependent module(s)", Count);
770 for (size_t I = 0; I < Files.GetSize(); ++I) {
771 AutoIndent Indent(Printer, 2);
772 Printer.formatLine("Name: {0}",
773 Files.GetFileSpecAtIndex(I).GetCString());
774 }
775 Printer.NewLine();
776 }
Zachary Turner888a4282017-12-01 00:52:51 +0000777 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000778 return HadErrors;
Zachary Turner888a4282017-12-01 00:52:51 +0000779}
780
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000781/// Check if two half-open intervals intersect:
782/// http://world.std.com/~swmcd/steven/tech/interval.html
783bool opts::irmemorymap::areAllocationsOverlapping(const AllocationT &L,
784 const AllocationT &R) {
785 return R.first < L.second && L.first < R.second;
786}
787
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000788bool opts::irmemorymap::evalMalloc(StringRef Line,
789 IRMemoryMapTestState &State) {
790 // ::= <label> = malloc <size> <alignment>
791 StringRef Label;
792 std::tie(Label, Line) = Line.split('=');
793 if (Line.empty())
794 return false;
795 Label = Label.trim();
796 Line = Line.trim();
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000797 size_t Size;
798 uint8_t Alignment;
799 int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment);
800 if (Matches != 2)
801 return false;
802
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000803 outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label,
804 Size, Alignment);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000805 if (!isPowerOf2_32(Alignment)) {
806 outs() << "Malloc error: alignment is not a power of 2\n";
807 exit(1);
808 }
809
Vedant Kumarf616b9d2018-05-31 22:09:00 +0000810 IRMemoryMap::AllocationPolicy AP =
811 UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly
812 : IRMemoryMap::eAllocationPolicyProcessOnly;
813
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000814 // Issue the malloc in the target process with "-rw" permissions.
815 const uint32_t Permissions = 0x3;
816 const bool ZeroMemory = false;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000817 Status ST;
818 addr_t Addr =
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000819 State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000820 if (ST.Fail()) {
821 outs() << formatv("Malloc error: {0}\n", ST);
822 return true;
823 }
824
825 // Print the result of the allocation before checking its validity.
826 outs() << formatv("Malloc: address = {0:x}\n", Addr);
827
828 // Check that the allocation is aligned.
829 if (!Addr || Addr % Alignment != 0) {
830 outs() << "Malloc error: zero or unaligned allocation detected\n";
831 exit(1);
832 }
833
834 // Check that the allocation does not overlap another allocation. Do so by
835 // testing each allocation which may cover the interval [Addr, EndOfRegion).
836 addr_t EndOfRegion = Addr + Size;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000837 auto Probe = State.Allocations.begin();
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000838 Probe.advanceTo(Addr); //< First interval s.t stop >= Addr.
839 AllocationT NewAllocation = {Addr, EndOfRegion};
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000840 while (Probe != State.Allocations.end() && Probe.start() < EndOfRegion) {
Vedant Kumarf3b6d292018-05-30 19:46:47 +0000841 AllocationT ProbeAllocation = {Probe.start(), Probe.stop()};
842 if (areAllocationsOverlapping(ProbeAllocation, NewAllocation)) {
843 outs() << "Malloc error: overlapping allocation detected"
844 << formatv(", previous allocation at [{0:x}, {1:x})\n",
845 Probe.start(), Probe.stop());
846 exit(1);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000847 }
Vedant Kumarf3b6d292018-05-30 19:46:47 +0000848 ++Probe;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000849 }
850
Aaron Smith037ed1b2018-12-06 21:36:39 +0000851 // Insert the new allocation into the interval map. Use unique allocation
852 // IDs to inhibit interval coalescing.
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000853 static unsigned AllocationID = 0;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000854 if (Size)
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000855 State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
856
857 // Store the label -> address mapping.
858 State.Label2AddrMap[Label] = Addr;
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000859
860 return true;
861}
862
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000863bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) {
864 // ::= free <label>
865 if (!Line.consume_front("free"))
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000866 return false;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000867 StringRef Label = Line.trim();
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000868
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000869 outs() << formatv("Command: free({0})\n", Label);
870 auto LabelIt = State.Label2AddrMap.find(Label);
871 if (LabelIt == State.Label2AddrMap.end()) {
872 outs() << "Free error: Invalid allocation label\n";
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000873 exit(1);
874 }
875
876 Status ST;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000877 addr_t Addr = LabelIt->getValue();
878 State.Map.Free(Addr, ST);
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000879 if (ST.Fail()) {
880 outs() << formatv("Free error: {0}\n", ST);
881 exit(1);
882 }
883
884 // Erase the allocation from the live interval map.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000885 auto Interval = State.Allocations.find(Addr);
886 if (Interval != State.Allocations.end()) {
887 outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(),
888 Interval.stop());
889 Interval.erase();
890 }
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000891
892 return true;
893}
894
895int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
896 // Set up a Target.
897 TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target);
898
899 // Set up a Process. In order to allocate memory within a target, this
900 // process must be alive and must support JIT'ing.
901 CommandReturnObject Result;
902 Dbg.SetAsyncExecution(false);
903 CommandInterpreter &CI = Dbg.GetCommandInterpreter();
904 auto IssueCmd = [&](const char *Cmd) -> bool {
905 return CI.HandleCommand(Cmd, eLazyBoolNo, Result);
906 };
907 if (!IssueCmd("b main") || !IssueCmd("run")) {
908 outs() << formatv("Failed: {0}\n", Result.GetErrorData());
909 exit(1);
910 }
911
912 ProcessSP Process = Target->GetProcessSP();
913 if (!Process || !Process->IsAlive() || !Process->CanJIT()) {
914 outs() << "Cannot use process to test IRMemoryMap\n";
915 exit(1);
916 }
917
918 // Set up an IRMemoryMap and associated testing state.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000919 IRMemoryMapTestState State(Target);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000920
921 // Parse and apply commands from the command file.
922 std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile);
923 StringRef Rest = MB->getBuffer();
924 while (!Rest.empty()) {
925 StringRef Line;
926 std::tie(Line, Rest) = Rest.split('\n');
927 Line = Line.ltrim();
928
929 if (Line.empty() || Line[0] == '#')
930 continue;
931
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000932 if (evalMalloc(Line, State))
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000933 continue;
934
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000935 if (evalFree(Line, State))
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000936 continue;
937
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000938 errs() << "Could not parse line: " << Line << "\n";
939 exit(1);
940 }
941 return 0;
942}
943
Zachary Turner888a4282017-12-01 00:52:51 +0000944int main(int argc, const char *argv[]) {
945 StringRef ToolName = argv[0];
946 sys::PrintStackTraceOnErrorSignal(ToolName);
947 PrettyStackTraceProgram X(argc, argv);
948 llvm_shutdown_obj Y;
949
950 cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
951
Pavel Labath90b0a532018-05-03 10:57:16 +0000952 SystemLifetimeManager DebuggerLifetime;
Jonas Devlieghere15eacd72018-12-03 17:28:29 +0000953 if (auto e = DebuggerLifetime.Initialize(
954 llvm::make_unique<SystemInitializerTest>(), {}, nullptr)) {
955 WithColor::error() << "initialization failed: " << toString(std::move(e))
956 << '\n';
957 return 1;
958 }
959
Pavel Labath90b0a532018-05-03 10:57:16 +0000960 CleanUp TerminateDebugger([&] { DebuggerLifetime.Terminate(); });
Zachary Turner888a4282017-12-01 00:52:51 +0000961
962 auto Dbg = lldb_private::Debugger::CreateInstance();
963
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000964 if (!opts::Log.empty())
965 Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, errs());
966
Pavel Labath7c945822018-02-26 18:50:16 +0000967 if (opts::BreakpointSubcommand)
Pavel Labath90b0a532018-05-03 10:57:16 +0000968 return opts::breakpoint::evaluateBreakpoints(*Dbg);
Pavel Labath62a7f802018-06-29 12:15:54 +0000969 if (opts::ObjectFileSubcommand)
970 return dumpObjectFiles(*Dbg);
Pavel Labath90b0a532018-05-03 10:57:16 +0000971 if (opts::SymbolsSubcommand)
972 return opts::symbols::dumpSymbols(*Dbg);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000973 if (opts::IRMemoryMapSubcommand)
974 return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
Zachary Turner888a4282017-12-01 00:52:51 +0000975
Pavel Labath90b0a532018-05-03 10:57:16 +0000976 WithColor::error() << "No command specified.\n";
977 return 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000978}