blob: a7e04318fef54823f28fa262f6fe4174138c3864 [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"
Pavel Labath90b0a532018-05-03 10:57:16 +000024#include "lldb/Symbol/SymbolVendor.h"
25#include "lldb/Symbol/TypeList.h"
26#include "lldb/Symbol/VariableList.h"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000027#include "lldb/Target/Process.h"
28#include "lldb/Target/Target.h"
Pavel Labath90b0a532018-05-03 10:57:16 +000029#include "lldb/Utility/CleanUp.h"
Zachary Turner888a4282017-12-01 00:52:51 +000030#include "lldb/Utility/DataExtractor.h"
Zachary Turnera6d54642017-12-02 00:15:29 +000031#include "lldb/Utility/StreamString.h"
Zachary Turner888a4282017-12-01 00:52:51 +000032
Vedant Kumarc1cd8262018-05-30 19:39:10 +000033#include "llvm/ADT/IntervalMap.h"
Zachary Turner888a4282017-12-01 00:52:51 +000034#include "llvm/ADT/StringRef.h"
35#include "llvm/Support/CommandLine.h"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000036#include "llvm/Support/MathExtras.h"
Zachary Turner888a4282017-12-01 00:52:51 +000037#include "llvm/Support/ManagedStatic.h"
Pavel Labath7c945822018-02-26 18:50:16 +000038#include "llvm/Support/Path.h"
Zachary Turner888a4282017-12-01 00:52:51 +000039#include "llvm/Support/PrettyStackTrace.h"
40#include "llvm/Support/Signals.h"
Pavel Labath90b0a532018-05-03 10:57:16 +000041#include "llvm/Support/WithColor.h"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000042#include <cstdio>
Zachary Turner888a4282017-12-01 00:52:51 +000043#include <thread>
44
45using namespace lldb;
46using namespace lldb_private;
47using namespace llvm;
48
49namespace opts {
Pavel Labath7c945822018-02-26 18:50:16 +000050static cl::SubCommand BreakpointSubcommand("breakpoints",
51 "Test breakpoint resolution");
Zachary Turner888a4282017-12-01 00:52:51 +000052cl::SubCommand ModuleSubcommand("module-sections",
53 "Display LLDB Module Information");
Zachary Turnera6d54642017-12-02 00:15:29 +000054cl::SubCommand SymbolsSubcommand("symbols", "Dump symbols for an object file");
Vedant Kumarc1cd8262018-05-30 19:39:10 +000055cl::SubCommand IRMemoryMapSubcommand("ir-memory-map", "Test IRMemoryMap");
56cl::opt<std::string> Log("log", cl::desc("Path to a log file"), cl::init(""),
57 cl::sub(IRMemoryMapSubcommand));
58
59/// Create a target using the file pointed to by \p Filename, or abort.
60TargetSP createTarget(Debugger &Dbg, const std::string &Filename);
61
62/// Read \p Filename into a null-terminated buffer, or abort.
63std::unique_ptr<MemoryBuffer> openFile(const std::string &Filename);
Zachary Turner888a4282017-12-01 00:52:51 +000064
Pavel Labath7c945822018-02-26 18:50:16 +000065namespace breakpoint {
66static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
67 cl::Required, cl::sub(BreakpointSubcommand));
68static cl::opt<std::string> CommandFile(cl::Positional,
69 cl::desc("<command-file>"),
70 cl::init("-"),
71 cl::sub(BreakpointSubcommand));
72static cl::opt<bool> Persistent(
73 "persistent",
74 cl::desc("Don't automatically remove all breakpoints before each command"),
75 cl::sub(BreakpointSubcommand));
76
77static llvm::StringRef plural(uintmax_t value) { return value == 1 ? "" : "s"; }
78static void dumpState(const BreakpointList &List, LinePrinter &P);
79static std::string substitute(StringRef Cmd);
Pavel Labath90b0a532018-05-03 10:57:16 +000080static int evaluateBreakpoints(Debugger &Dbg);
Pavel Labath7c945822018-02-26 18:50:16 +000081} // namespace breakpoint
82
Zachary Turner888a4282017-12-01 00:52:51 +000083namespace module {
84cl::opt<bool> SectionContents("contents",
85 cl::desc("Dump each section's contents"),
86 cl::sub(ModuleSubcommand));
87cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
88 cl::OneOrMore, cl::sub(ModuleSubcommand));
89} // namespace module
Zachary Turnera6d54642017-12-02 00:15:29 +000090
91namespace symbols {
Pavel Labath90b0a532018-05-03 10:57:16 +000092static cl::list<std::string> InputFilenames(cl::Positional,
93 cl::desc("<input files>"),
94 cl::OneOrMore,
95 cl::sub(SymbolsSubcommand));
96enum class FindType {
97 None,
98 Function,
99 Namespace,
100 Type,
101 Variable,
102};
103static cl::opt<FindType> Find(
104 "find", cl::desc("Choose search type:"),
105 cl::values(
106 clEnumValN(FindType::None, "none",
107 "No search, just dump the module."),
108 clEnumValN(FindType::Function, "function", "Find functions."),
109 clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
110 clEnumValN(FindType::Type, "type", "Find types."),
111 clEnumValN(FindType::Variable, "variable", "Find global variables.")),
112 cl::sub(SymbolsSubcommand));
113
114static cl::opt<std::string> Name("name", cl::desc("Name to find."),
115 cl::sub(SymbolsSubcommand));
116static cl::opt<bool>
117 Regex("regex",
118 cl::desc("Search using regular expressions (avaliable for variables "
119 "and functions only)."),
120 cl::sub(SymbolsSubcommand));
121static cl::opt<std::string>
122 Context("context",
123 cl::desc("Restrict search to the context of the given variable."),
124 cl::value_desc("variable"), cl::sub(SymbolsSubcommand));
125
126static cl::list<FunctionNameType> FunctionNameFlags(
127 "function-flags", cl::desc("Function search flags:"),
128 cl::values(clEnumValN(eFunctionNameTypeAuto, "auto",
129 "Automatically deduce flags based on name."),
130 clEnumValN(eFunctionNameTypeFull, "full", "Full function name."),
131 clEnumValN(eFunctionNameTypeBase, "base", "Base name."),
132 clEnumValN(eFunctionNameTypeMethod, "method", "Method name."),
133 clEnumValN(eFunctionNameTypeSelector, "selector",
134 "Selector name.")),
135 cl::sub(SymbolsSubcommand));
136static FunctionNameType getFunctionNameFlags() {
137 FunctionNameType Result = FunctionNameType(0);
138 for (FunctionNameType Flag : FunctionNameFlags)
139 Result = FunctionNameType(Result | Flag);
140 return Result;
141}
142
143static Expected<CompilerDeclContext> getDeclContext(SymbolVendor &Vendor);
144
145static Error findFunctions(lldb_private::Module &Module);
146static Error findNamespaces(lldb_private::Module &Module);
147static Error findTypes(lldb_private::Module &Module);
148static Error findVariables(lldb_private::Module &Module);
149static Error dumpModule(lldb_private::Module &Module);
150
151static int dumpSymbols(Debugger &Dbg);
Zachary Turnera6d54642017-12-02 00:15:29 +0000152}
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000153
154namespace irmemorymap {
155static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
156 cl::Required,
157 cl::sub(IRMemoryMapSubcommand));
158static cl::opt<std::string> CommandFile(cl::Positional,
159 cl::desc("<command-file>"),
160 cl::init("-"),
161 cl::sub(IRMemoryMapSubcommand));
162using AllocationT = std::pair<addr_t, addr_t>;
163bool areAllocationsOverlapping(const AllocationT &L, const AllocationT &R);
164using AddrIntervalMap =
165 IntervalMap<addr_t, bool, 8, IntervalMapHalfOpenInfo<addr_t>>;
166bool evalMalloc(IRMemoryMap &IRMemMap, StringRef Line,
167 AddrIntervalMap &AllocatedIntervals);
168int evaluateMemoryMapCommands(Debugger &Dbg);
169} // namespace irmemorymap
170
Zachary Turner888a4282017-12-01 00:52:51 +0000171} // namespace opts
172
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000173TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) {
174 TargetSP Target;
175 Status ST =
176 Dbg.GetTargetList().CreateTarget(Dbg, Filename, /*triple*/ "",
177 /*get_dependent_modules*/ false,
178 /*platform_options*/ nullptr, Target);
179 if (ST.Fail()) {
180 errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST);
181 exit(1);
182 }
183 return Target;
184}
185
186std::unique_ptr<MemoryBuffer> opts::openFile(const std::string &Filename) {
187 auto MB = MemoryBuffer::getFileOrSTDIN(Filename);
188 if (!MB) {
189 errs() << formatv("Could not open file '{0}: {1}\n", Filename,
190 MB.getError().message());
191 exit(1);
192 }
193 return std::move(*MB);
194}
195
Pavel Labath7c945822018-02-26 18:50:16 +0000196void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) {
197 P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize()));
198 if (List.GetSize() > 0)
199 P.formatLine("At least one breakpoint.");
200 for (size_t i = 0, e = List.GetSize(); i < e; ++i) {
201 BreakpointSP BP = List.GetBreakpointAtIndex(i);
202 P.formatLine("Breakpoint ID {0}:", BP->GetID());
203 AutoIndent Indent(P, 2);
204 P.formatLine("{0} location{1}.", BP->GetNumLocations(),
205 plural(BP->GetNumLocations()));
206 if (BP->GetNumLocations() > 0)
207 P.formatLine("At least one location.");
208 P.formatLine("{0} resolved location{1}.", BP->GetNumResolvedLocations(),
209 plural(BP->GetNumResolvedLocations()));
210 if (BP->GetNumResolvedLocations() > 0)
211 P.formatLine("At least one resolved location.");
212 for (size_t l = 0, le = BP->GetNumLocations(); l < le; ++l) {
213 BreakpointLocationSP Loc = BP->GetLocationAtIndex(l);
214 P.formatLine("Location ID {0}:", Loc->GetID());
215 AutoIndent Indent(P, 2);
216 P.formatLine("Enabled: {0}", Loc->IsEnabled());
217 P.formatLine("Resolved: {0}", Loc->IsResolved());
Jim Ingham08581262018-03-12 21:17:04 +0000218 SymbolContext sc;
219 Loc->GetAddress().CalculateSymbolContext(&sc);
220 lldb_private::StreamString S;
221 sc.DumpStopContext(&S, BP->GetTarget().GetProcessSP().get(),
222 Loc->GetAddress(), false, true, false, true, true);
223 P.formatLine("Address: {0}", S.GetString());
Pavel Labath7c945822018-02-26 18:50:16 +0000224 }
225 }
226 P.NewLine();
227}
228
229std::string opts::breakpoint::substitute(StringRef Cmd) {
230 std::string Result;
231 raw_string_ostream OS(Result);
232 while (!Cmd.empty()) {
233 switch (Cmd[0]) {
234 case '%':
235 if (Cmd.consume_front("%p") && (Cmd.empty() || !isalnum(Cmd[0]))) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000236 OS << sys::path::parent_path(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000237 break;
238 }
239 // fall through
240 default:
241 size_t pos = Cmd.find('%');
242 OS << Cmd.substr(0, pos);
243 Cmd = Cmd.substr(pos);
244 break;
245 }
246 }
247 return std::move(OS.str());
248}
249
Pavel Labath90b0a532018-05-03 10:57:16 +0000250int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000251 TargetSP Target = opts::createTarget(Dbg, breakpoint::Target);
252 std::unique_ptr<MemoryBuffer> MB = opts::openFile(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000253
254 LinePrinter P(4, outs());
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000255 StringRef Rest = MB->getBuffer();
Pavel Labath90b0a532018-05-03 10:57:16 +0000256 int HadErrors = 0;
Pavel Labath7c945822018-02-26 18:50:16 +0000257 while (!Rest.empty()) {
258 StringRef Line;
259 std::tie(Line, Rest) = Rest.split('\n');
260 Line = Line.ltrim();
261 if (Line.empty() || Line[0] == '#')
262 continue;
263
264 if (!Persistent)
265 Target->RemoveAllBreakpoints(/*internal_also*/ true);
266
267 std::string Command = substitute(Line);
268 P.formatLine("Command: {0}", Command);
269 CommandReturnObject Result;
270 if (!Dbg.GetCommandInterpreter().HandleCommand(
271 Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
272 P.formatLine("Failed: {0}", Result.GetErrorData());
Pavel Labath90b0a532018-05-03 10:57:16 +0000273 HadErrors = 1;
Pavel Labath7c945822018-02-26 18:50:16 +0000274 continue;
275 }
276
277 dumpState(Target->GetBreakpointList(/*internal*/ false), P);
278 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000279 return HadErrors;
Pavel Labath7c945822018-02-26 18:50:16 +0000280}
281
Pavel Labath90b0a532018-05-03 10:57:16 +0000282Expected<CompilerDeclContext>
283opts::symbols::getDeclContext(SymbolVendor &Vendor) {
284 if (Context.empty())
285 return CompilerDeclContext();
286 VariableList List;
Pavel Labath34cda142018-05-31 09:46:26 +0000287 Vendor.FindGlobalVariables(ConstString(Context), nullptr, UINT32_MAX, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000288 if (List.Empty()) {
289 return make_error<StringError>("Context search didn't find a match.",
290 inconvertibleErrorCode());
291 }
292 if (List.GetSize() > 1) {
293 return make_error<StringError>("Context search found multiple matches.",
294 inconvertibleErrorCode());
295 }
296 return List.GetVariableAtIndex(0)->GetDeclContext();
297}
298
299Error opts::symbols::findFunctions(lldb_private::Module &Module) {
300 SymbolVendor &Vendor = *Module.GetSymbolVendor();
301 SymbolContextList List;
302 if (Regex) {
303 RegularExpression RE(Name);
304 assert(RE.IsValid());
305 Vendor.FindFunctions(RE, true, false, List);
306 } else {
307 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
308 if (!ContextOr)
309 return ContextOr.takeError();
310 CompilerDeclContext *ContextPtr =
311 ContextOr->IsValid() ? &*ContextOr : nullptr;
312
313 Vendor.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
314 true, false, List);
315 }
316 outs() << formatv("Found {0} functions:\n", List.GetSize());
317 StreamString Stream;
318 List.Dump(&Stream, nullptr);
319 outs() << Stream.GetData() << "\n";
320 return Error::success();
321}
322
323Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
324 SymbolVendor &Vendor = *Module.GetSymbolVendor();
325 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
326 if (!ContextOr)
327 return ContextOr.takeError();
328 CompilerDeclContext *ContextPtr =
329 ContextOr->IsValid() ? &*ContextOr : nullptr;
330
331 SymbolContext SC;
332 CompilerDeclContext Result =
333 Vendor.FindNamespace(SC, ConstString(Name), ContextPtr);
334 if (Result)
335 outs() << "Found namespace: "
336 << Result.GetScopeQualifiedName().GetStringRef() << "\n";
337 else
338 outs() << "Namespace not found.\n";
339 return Error::success();
340}
341
342Error opts::symbols::findTypes(lldb_private::Module &Module) {
343 SymbolVendor &Vendor = *Module.GetSymbolVendor();
344 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
345 if (!ContextOr)
346 return ContextOr.takeError();
347 CompilerDeclContext *ContextPtr =
348 ContextOr->IsValid() ? &*ContextOr : nullptr;
349
350 SymbolContext SC;
351 DenseSet<SymbolFile *> SearchedFiles;
352 TypeMap Map;
353 Vendor.FindTypes(SC, ConstString(Name), ContextPtr, true, UINT32_MAX,
354 SearchedFiles, Map);
355
356 outs() << formatv("Found {0} types:\n", Map.GetSize());
357 StreamString Stream;
358 Map.Dump(&Stream, false);
359 outs() << Stream.GetData() << "\n";
360 return Error::success();
361}
362
363Error opts::symbols::findVariables(lldb_private::Module &Module) {
364 SymbolVendor &Vendor = *Module.GetSymbolVendor();
365 VariableList List;
366 if (Regex) {
367 RegularExpression RE(Name);
368 assert(RE.IsValid());
Pavel Labath34cda142018-05-31 09:46:26 +0000369 Vendor.FindGlobalVariables(RE, UINT32_MAX, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000370 } else {
371 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
372 if (!ContextOr)
373 return ContextOr.takeError();
374 CompilerDeclContext *ContextPtr =
375 ContextOr->IsValid() ? &*ContextOr : nullptr;
376
Pavel Labath34cda142018-05-31 09:46:26 +0000377 Vendor.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000378 }
379 outs() << formatv("Found {0} variables:\n", List.GetSize());
380 StreamString Stream;
381 List.Dump(&Stream, false);
382 outs() << Stream.GetData() << "\n";
383 return Error::success();
384}
385
386Error opts::symbols::dumpModule(lldb_private::Module &Module) {
387 StreamString Stream;
388 Module.ParseAllDebugSymbols();
389 Module.Dump(&Stream);
390 outs() << Stream.GetData() << "\n";
391 return Error::success();
392}
393
394int opts::symbols::dumpSymbols(Debugger &Dbg) {
395 if (Find != FindType::None && Regex && !Context.empty()) {
396 WithColor::error()
397 << "Cannot search using both regular expressions and context.\n";
398 return 1;
399 }
400 if ((Find == FindType::Type || Find == FindType::Namespace) && Regex) {
401 WithColor::error() << "Cannot search for types and namespaces using "
402 "regular expressions.\n";
403 return 1;
404 }
405 if (Find == FindType::Function && Regex && getFunctionNameFlags() != 0) {
406 WithColor::error() << "Cannot search for types using both regular "
407 "expressions and function-flags.\n";
408 return 1;
409 }
410 if (Regex && !RegularExpression(Name).IsValid()) {
411 WithColor::error() << "`" << Name
412 << "` is not a valid regular expression.\n";
413 return 1;
414 }
415
416 Error (*Action)(lldb_private::Module &);
417 switch (Find) {
418 case FindType::Function:
419 Action = findFunctions;
420 break;
421 case FindType::Namespace:
422 Action = findNamespaces;
423 break;
424 case FindType::Type:
425 Action = findTypes;
426 break;
427 case FindType::Variable:
428 Action = findVariables;
429 break;
430 case FindType::None:
431 Action = dumpModule;
432 break;
433 }
434
435 int HadErrors = 0;
436 for (const auto &File : InputFilenames) {
437 outs() << "Module: " << File << "\n";
Zachary Turnera6d54642017-12-02 00:15:29 +0000438 ModuleSpec Spec{FileSpec(File, false)};
439 Spec.GetSymbolFileSpec().SetFile(File, false);
440
441 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
Pavel Labath90b0a532018-05-03 10:57:16 +0000442 SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
443 if (!Vendor) {
444 WithColor::error() << "Module has no symbol vendor.\n";
445 HadErrors = 1;
446 continue;
447 }
448
449 if (Error E = Action(*ModulePtr)) {
450 WithColor::error() << toString(std::move(E)) << "\n";
451 HadErrors = 1;
452 }
Zachary Turnera6d54642017-12-02 00:15:29 +0000453
Pavel Labath90b0a532018-05-03 10:57:16 +0000454 outs().flush();
Zachary Turnera6d54642017-12-02 00:15:29 +0000455 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000456 return HadErrors;
Zachary Turnera6d54642017-12-02 00:15:29 +0000457}
458
Pavel Labath90b0a532018-05-03 10:57:16 +0000459static int dumpModules(Debugger &Dbg) {
Zachary Turner888a4282017-12-01 00:52:51 +0000460 LinePrinter Printer(4, llvm::outs());
461
Pavel Labath90b0a532018-05-03 10:57:16 +0000462 int HadErrors = 0;
Zachary Turner888a4282017-12-01 00:52:51 +0000463 for (const auto &File : opts::module::InputFilenames) {
464 ModuleSpec Spec{FileSpec(File, false)};
Zachary Turner888a4282017-12-01 00:52:51 +0000465
Zachary Turnera6d54642017-12-02 00:15:29 +0000466 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
Pavel Labath96979ce2018-03-06 15:56:20 +0000467 // Fetch symbol vendor before we get the section list to give the symbol
468 // vendor a chance to populate it.
469 ModulePtr->GetSymbolVendor();
Zachary Turner888a4282017-12-01 00:52:51 +0000470 SectionList *Sections = ModulePtr->GetSectionList();
471 if (!Sections) {
472 llvm::errs() << "Could not load sections for module " << File << "\n";
Pavel Labath90b0a532018-05-03 10:57:16 +0000473 HadErrors = 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000474 continue;
475 }
476
477 size_t Count = Sections->GetNumSections(0);
478 Printer.formatLine("Showing {0} sections", Count);
479 for (size_t I = 0; I < Count; ++I) {
480 AutoIndent Indent(Printer, 2);
481 auto S = Sections->GetSectionAtIndex(I);
482 assert(S);
483 Printer.formatLine("Index: {0}", I);
484 Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
Jan Kratochvile4777a92018-04-29 19:47:48 +0000485 Printer.formatLine("Type: {0}", S->GetTypeAsCString());
Pavel Labathe2867bc2017-12-15 14:23:58 +0000486 Printer.formatLine("VM size: {0}", S->GetByteSize());
487 Printer.formatLine("File size: {0}", S->GetFileSize());
Zachary Turner888a4282017-12-01 00:52:51 +0000488
489 if (opts::module::SectionContents) {
490 DataExtractor Data;
491 S->GetSectionData(Data);
492 ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()};
493 Printer.formatBinary("Data: ", Bytes, 0);
494 }
495 Printer.NewLine();
496 }
497 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000498 return HadErrors;
Zachary Turner888a4282017-12-01 00:52:51 +0000499}
500
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000501/// Check if two half-open intervals intersect:
502/// http://world.std.com/~swmcd/steven/tech/interval.html
503bool opts::irmemorymap::areAllocationsOverlapping(const AllocationT &L,
504 const AllocationT &R) {
505 return R.first < L.second && L.first < R.second;
506}
507
508bool opts::irmemorymap::evalMalloc(IRMemoryMap &IRMemMap, StringRef Line,
509 AddrIntervalMap &AllocatedIntervals) {
510 // ::= malloc <size> <alignment>
511 size_t Size;
512 uint8_t Alignment;
513 int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment);
514 if (Matches != 2)
515 return false;
516
517 outs() << formatv("Command: malloc(size={0}, alignment={1})\n", Size,
518 Alignment);
519 if (!isPowerOf2_32(Alignment)) {
520 outs() << "Malloc error: alignment is not a power of 2\n";
521 exit(1);
522 }
523
524 // Issue the malloc in the target process with "-rw" permissions.
525 const uint32_t Permissions = 0x3;
526 const bool ZeroMemory = false;
527 IRMemoryMap::AllocationPolicy Policy =
528 IRMemoryMap::eAllocationPolicyProcessOnly;
529 Status ST;
530 addr_t Addr =
531 IRMemMap.Malloc(Size, Alignment, Permissions, Policy, ZeroMemory, ST);
532 if (ST.Fail()) {
533 outs() << formatv("Malloc error: {0}\n", ST);
534 return true;
535 }
536
537 // Print the result of the allocation before checking its validity.
538 outs() << formatv("Malloc: address = {0:x}\n", Addr);
539
540 // Check that the allocation is aligned.
541 if (!Addr || Addr % Alignment != 0) {
542 outs() << "Malloc error: zero or unaligned allocation detected\n";
543 exit(1);
544 }
545
546 // Check that the allocation does not overlap another allocation. Do so by
547 // testing each allocation which may cover the interval [Addr, EndOfRegion).
548 addr_t EndOfRegion = Addr + Size;
549 auto Probe = AllocatedIntervals.begin();
550 Probe.advanceTo(Addr); //< First interval s.t stop >= Addr.
551 AllocationT NewAllocation = {Addr, EndOfRegion};
Vedant Kumarf3b6d292018-05-30 19:46:47 +0000552 while (Probe != AllocatedIntervals.end() && Probe.start() < EndOfRegion) {
553 AllocationT ProbeAllocation = {Probe.start(), Probe.stop()};
554 if (areAllocationsOverlapping(ProbeAllocation, NewAllocation)) {
555 outs() << "Malloc error: overlapping allocation detected"
556 << formatv(", previous allocation at [{0:x}, {1:x})\n",
557 Probe.start(), Probe.stop());
558 exit(1);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000559 }
Vedant Kumarf3b6d292018-05-30 19:46:47 +0000560 ++Probe;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000561 }
562
563 // Insert the new allocation into the interval map.
564 if (Size)
565 AllocatedIntervals.insert(Addr, EndOfRegion, true);
566
567 return true;
568}
569
570int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
571 // Set up a Target.
572 TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target);
573
574 // Set up a Process. In order to allocate memory within a target, this
575 // process must be alive and must support JIT'ing.
576 CommandReturnObject Result;
577 Dbg.SetAsyncExecution(false);
578 CommandInterpreter &CI = Dbg.GetCommandInterpreter();
579 auto IssueCmd = [&](const char *Cmd) -> bool {
580 return CI.HandleCommand(Cmd, eLazyBoolNo, Result);
581 };
582 if (!IssueCmd("b main") || !IssueCmd("run")) {
583 outs() << formatv("Failed: {0}\n", Result.GetErrorData());
584 exit(1);
585 }
586
587 ProcessSP Process = Target->GetProcessSP();
588 if (!Process || !Process->IsAlive() || !Process->CanJIT()) {
589 outs() << "Cannot use process to test IRMemoryMap\n";
590 exit(1);
591 }
592
593 // Set up an IRMemoryMap and associated testing state.
594 IRMemoryMap IRMemMap(Target);
595 AddrIntervalMap::Allocator AIMapAllocator;
596 AddrIntervalMap AllocatedIntervals(AIMapAllocator);
597
598 // Parse and apply commands from the command file.
599 std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile);
600 StringRef Rest = MB->getBuffer();
601 while (!Rest.empty()) {
602 StringRef Line;
603 std::tie(Line, Rest) = Rest.split('\n');
604 Line = Line.ltrim();
605
606 if (Line.empty() || Line[0] == '#')
607 continue;
608
609 if (evalMalloc(IRMemMap, Line, AllocatedIntervals))
610 continue;
611
612 errs() << "Could not parse line: " << Line << "\n";
613 exit(1);
614 }
615 return 0;
616}
617
Zachary Turner888a4282017-12-01 00:52:51 +0000618int main(int argc, const char *argv[]) {
619 StringRef ToolName = argv[0];
620 sys::PrintStackTraceOnErrorSignal(ToolName);
621 PrettyStackTraceProgram X(argc, argv);
622 llvm_shutdown_obj Y;
623
624 cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
625
Pavel Labath90b0a532018-05-03 10:57:16 +0000626 SystemLifetimeManager DebuggerLifetime;
627 DebuggerLifetime.Initialize(llvm::make_unique<SystemInitializerTest>(),
628 nullptr);
629 CleanUp TerminateDebugger([&] { DebuggerLifetime.Terminate(); });
Zachary Turner888a4282017-12-01 00:52:51 +0000630
631 auto Dbg = lldb_private::Debugger::CreateInstance();
632
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000633 if (!opts::Log.empty())
634 Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, errs());
635
Pavel Labath7c945822018-02-26 18:50:16 +0000636 if (opts::BreakpointSubcommand)
Pavel Labath90b0a532018-05-03 10:57:16 +0000637 return opts::breakpoint::evaluateBreakpoints(*Dbg);
Zachary Turner888a4282017-12-01 00:52:51 +0000638 if (opts::ModuleSubcommand)
Pavel Labath90b0a532018-05-03 10:57:16 +0000639 return dumpModules(*Dbg);
640 if (opts::SymbolsSubcommand)
641 return opts::symbols::dumpSymbols(*Dbg);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000642 if (opts::IRMemoryMapSubcommand)
643 return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
Zachary Turner888a4282017-12-01 00:52:51 +0000644
Pavel Labath90b0a532018-05-03 10:57:16 +0000645 WithColor::error() << "No command specified.\n";
646 return 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000647}