blob: d8f4472e2d06662a245c00226c089b03e453584a [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 Labath90b0a532018-05-03 10:57:16 +0000103static cl::list<std::string> InputFilenames(cl::Positional,
104 cl::desc("<input files>"),
105 cl::OneOrMore,
106 cl::sub(SymbolsSubcommand));
107enum class FindType {
108 None,
109 Function,
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000110 Block,
Pavel Labath90b0a532018-05-03 10:57:16 +0000111 Namespace,
112 Type,
113 Variable,
114};
115static cl::opt<FindType> Find(
116 "find", cl::desc("Choose search type:"),
117 cl::values(
Pavel Labath9ea80d22018-06-28 10:03:42 +0000118 clEnumValN(FindType::None, "none", "No search, just dump the module."),
Pavel Labath90b0a532018-05-03 10:57:16 +0000119 clEnumValN(FindType::Function, "function", "Find functions."),
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000120 clEnumValN(FindType::Block, "block", "Find blocks."),
Pavel Labath90b0a532018-05-03 10:57:16 +0000121 clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
122 clEnumValN(FindType::Type, "type", "Find types."),
123 clEnumValN(FindType::Variable, "variable", "Find global variables.")),
124 cl::sub(SymbolsSubcommand));
125
126static cl::opt<std::string> Name("name", cl::desc("Name to find."),
127 cl::sub(SymbolsSubcommand));
128static cl::opt<bool>
129 Regex("regex",
130 cl::desc("Search using regular expressions (avaliable for variables "
131 "and functions only)."),
132 cl::sub(SymbolsSubcommand));
133static cl::opt<std::string>
134 Context("context",
135 cl::desc("Restrict search to the context of the given variable."),
136 cl::value_desc("variable"), cl::sub(SymbolsSubcommand));
137
138static cl::list<FunctionNameType> FunctionNameFlags(
139 "function-flags", cl::desc("Function search flags:"),
140 cl::values(clEnumValN(eFunctionNameTypeAuto, "auto",
141 "Automatically deduce flags based on name."),
142 clEnumValN(eFunctionNameTypeFull, "full", "Full function name."),
143 clEnumValN(eFunctionNameTypeBase, "base", "Base name."),
144 clEnumValN(eFunctionNameTypeMethod, "method", "Method name."),
145 clEnumValN(eFunctionNameTypeSelector, "selector",
146 "Selector name.")),
147 cl::sub(SymbolsSubcommand));
148static FunctionNameType getFunctionNameFlags() {
149 FunctionNameType Result = FunctionNameType(0);
150 for (FunctionNameType Flag : FunctionNameFlags)
151 Result = FunctionNameType(Result | Flag);
152 return Result;
153}
154
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000155static cl::opt<bool> DumpAST("dump-ast",
156 cl::desc("Dump AST restored from symbols."),
157 cl::sub(SymbolsSubcommand));
158
Aaron Smith010edd32018-06-08 02:45:25 +0000159static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
160 cl::sub(SymbolsSubcommand));
161
Pavel Labathe6954cb2018-06-12 12:57:36 +0000162static cl::opt<std::string> File("file",
163 cl::desc("File (compile unit) to search."),
164 cl::sub(SymbolsSubcommand));
Pavel Labath9ea80d22018-06-28 10:03:42 +0000165static cl::opt<int> Line("line", cl::desc("Line to search."),
166 cl::sub(SymbolsSubcommand));
Pavel Labathe6954cb2018-06-12 12:57:36 +0000167
Pavel Labath90b0a532018-05-03 10:57:16 +0000168static Expected<CompilerDeclContext> getDeclContext(SymbolVendor &Vendor);
169
170static Error findFunctions(lldb_private::Module &Module);
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000171static Error findBlocks(lldb_private::Module &Module);
Pavel Labath90b0a532018-05-03 10:57:16 +0000172static Error findNamespaces(lldb_private::Module &Module);
173static Error findTypes(lldb_private::Module &Module);
174static Error findVariables(lldb_private::Module &Module);
175static Error dumpModule(lldb_private::Module &Module);
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000176static Error dumpAST(lldb_private::Module &Module);
Aaron Smith010edd32018-06-08 02:45:25 +0000177static Error verify(lldb_private::Module &Module);
Pavel Labath90b0a532018-05-03 10:57:16 +0000178
Pavel Labath38d9ff72018-06-12 13:26:43 +0000179static Expected<Error (*)(lldb_private::Module &)> getAction();
Pavel Labath90b0a532018-05-03 10:57:16 +0000180static int dumpSymbols(Debugger &Dbg);
Pavel Labath9ea80d22018-06-28 10:03:42 +0000181} // namespace symbols
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000182
183namespace irmemorymap {
184static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
185 cl::Required,
186 cl::sub(IRMemoryMapSubcommand));
187static cl::opt<std::string> CommandFile(cl::Positional,
188 cl::desc("<command-file>"),
189 cl::init("-"),
190 cl::sub(IRMemoryMapSubcommand));
Vedant Kumarf616b9d2018-05-31 22:09:00 +0000191static cl::opt<bool> UseHostOnlyAllocationPolicy(
192 "host-only", cl::desc("Use the host-only allocation policy"),
193 cl::init(false), cl::sub(IRMemoryMapSubcommand));
194
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000195using AllocationT = std::pair<addr_t, addr_t>;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000196using AddrIntervalMap =
Pavel Labath9ea80d22018-06-28 10:03:42 +0000197 IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000198
199struct IRMemoryMapTestState {
200 TargetSP Target;
201 IRMemoryMap Map;
202
203 AddrIntervalMap::Allocator IntervalMapAllocator;
204 AddrIntervalMap Allocations;
205
206 StringMap<addr_t> Label2AddrMap;
207
208 IRMemoryMapTestState(TargetSP Target)
209 : Target(Target), Map(Target), Allocations(IntervalMapAllocator) {}
210};
211
212bool areAllocationsOverlapping(const AllocationT &L, const AllocationT &R);
213bool evalMalloc(StringRef Line, IRMemoryMapTestState &State);
214bool evalFree(StringRef Line, IRMemoryMapTestState &State);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000215int evaluateMemoryMapCommands(Debugger &Dbg);
216} // namespace irmemorymap
217
Zachary Turner888a4282017-12-01 00:52:51 +0000218} // namespace opts
219
Pavel Labathe6954cb2018-06-12 12:57:36 +0000220template <typename... Args>
221static Error make_string_error(const char *Format, Args &&... args) {
222 return llvm::make_error<llvm::StringError>(
223 llvm::formatv(Format, std::forward<Args>(args)...).str(),
224 llvm::inconvertibleErrorCode());
225}
226
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000227TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) {
228 TargetSP Target;
Jonas Devliegheref9a07e92018-09-20 09:09:05 +0000229 Status ST = Dbg.GetTargetList().CreateTarget(
230 Dbg, Filename, /*triple*/ "", eLoadDependentsNo,
231 /*platform_options*/ nullptr, Target);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000232 if (ST.Fail()) {
233 errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST);
234 exit(1);
235 }
236 return Target;
237}
238
239std::unique_ptr<MemoryBuffer> opts::openFile(const std::string &Filename) {
240 auto MB = MemoryBuffer::getFileOrSTDIN(Filename);
241 if (!MB) {
242 errs() << formatv("Could not open file '{0}: {1}\n", Filename,
243 MB.getError().message());
244 exit(1);
245 }
246 return std::move(*MB);
247}
248
Pavel Labath7c945822018-02-26 18:50:16 +0000249void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) {
250 P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize()));
251 if (List.GetSize() > 0)
252 P.formatLine("At least one breakpoint.");
253 for (size_t i = 0, e = List.GetSize(); i < e; ++i) {
254 BreakpointSP BP = List.GetBreakpointAtIndex(i);
255 P.formatLine("Breakpoint ID {0}:", BP->GetID());
256 AutoIndent Indent(P, 2);
257 P.formatLine("{0} location{1}.", BP->GetNumLocations(),
258 plural(BP->GetNumLocations()));
259 if (BP->GetNumLocations() > 0)
260 P.formatLine("At least one location.");
261 P.formatLine("{0} resolved location{1}.", BP->GetNumResolvedLocations(),
262 plural(BP->GetNumResolvedLocations()));
263 if (BP->GetNumResolvedLocations() > 0)
264 P.formatLine("At least one resolved location.");
265 for (size_t l = 0, le = BP->GetNumLocations(); l < le; ++l) {
266 BreakpointLocationSP Loc = BP->GetLocationAtIndex(l);
267 P.formatLine("Location ID {0}:", Loc->GetID());
268 AutoIndent Indent(P, 2);
269 P.formatLine("Enabled: {0}", Loc->IsEnabled());
270 P.formatLine("Resolved: {0}", Loc->IsResolved());
Jim Ingham08581262018-03-12 21:17:04 +0000271 SymbolContext sc;
272 Loc->GetAddress().CalculateSymbolContext(&sc);
273 lldb_private::StreamString S;
274 sc.DumpStopContext(&S, BP->GetTarget().GetProcessSP().get(),
275 Loc->GetAddress(), false, true, false, true, true);
276 P.formatLine("Address: {0}", S.GetString());
Pavel Labath7c945822018-02-26 18:50:16 +0000277 }
278 }
279 P.NewLine();
280}
281
282std::string opts::breakpoint::substitute(StringRef Cmd) {
283 std::string Result;
284 raw_string_ostream OS(Result);
285 while (!Cmd.empty()) {
286 switch (Cmd[0]) {
287 case '%':
288 if (Cmd.consume_front("%p") && (Cmd.empty() || !isalnum(Cmd[0]))) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000289 OS << sys::path::parent_path(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000290 break;
291 }
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000292 LLVM_FALLTHROUGH;
Pavel Labath7c945822018-02-26 18:50:16 +0000293 default:
294 size_t pos = Cmd.find('%');
295 OS << Cmd.substr(0, pos);
296 Cmd = Cmd.substr(pos);
297 break;
298 }
299 }
300 return std::move(OS.str());
301}
302
Pavel Labath90b0a532018-05-03 10:57:16 +0000303int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000304 TargetSP Target = opts::createTarget(Dbg, breakpoint::Target);
305 std::unique_ptr<MemoryBuffer> MB = opts::openFile(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000306
307 LinePrinter P(4, outs());
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000308 StringRef Rest = MB->getBuffer();
Pavel Labath90b0a532018-05-03 10:57:16 +0000309 int HadErrors = 0;
Pavel Labath7c945822018-02-26 18:50:16 +0000310 while (!Rest.empty()) {
311 StringRef Line;
312 std::tie(Line, Rest) = Rest.split('\n');
313 Line = Line.ltrim();
314 if (Line.empty() || Line[0] == '#')
315 continue;
316
317 if (!Persistent)
318 Target->RemoveAllBreakpoints(/*internal_also*/ true);
319
320 std::string Command = substitute(Line);
321 P.formatLine("Command: {0}", Command);
322 CommandReturnObject Result;
323 if (!Dbg.GetCommandInterpreter().HandleCommand(
324 Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
325 P.formatLine("Failed: {0}", Result.GetErrorData());
Pavel Labath90b0a532018-05-03 10:57:16 +0000326 HadErrors = 1;
Pavel Labath7c945822018-02-26 18:50:16 +0000327 continue;
328 }
329
330 dumpState(Target->GetBreakpointList(/*internal*/ false), P);
331 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000332 return HadErrors;
Pavel Labath7c945822018-02-26 18:50:16 +0000333}
334
Pavel Labath90b0a532018-05-03 10:57:16 +0000335Expected<CompilerDeclContext>
336opts::symbols::getDeclContext(SymbolVendor &Vendor) {
337 if (Context.empty())
338 return CompilerDeclContext();
339 VariableList List;
Pavel Labath34cda142018-05-31 09:46:26 +0000340 Vendor.FindGlobalVariables(ConstString(Context), nullptr, UINT32_MAX, List);
Pavel Labathe6954cb2018-06-12 12:57:36 +0000341 if (List.Empty())
342 return make_string_error("Context search didn't find a match.");
343 if (List.GetSize() > 1)
344 return make_string_error("Context search found multiple matches.");
Pavel Labath90b0a532018-05-03 10:57:16 +0000345 return List.GetVariableAtIndex(0)->GetDeclContext();
346}
347
348Error opts::symbols::findFunctions(lldb_private::Module &Module) {
349 SymbolVendor &Vendor = *Module.GetSymbolVendor();
350 SymbolContextList List;
Pavel Labath9ea80d22018-06-28 10:03:42 +0000351 if (!File.empty()) {
352 assert(Line != 0);
353
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000354 FileSpec src_file(File);
Pavel Labath9ea80d22018-06-28 10:03:42 +0000355 size_t cu_count = Module.GetNumCompileUnits();
356 for (size_t i = 0; i < cu_count; i++) {
357 lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
358 if (!cu_sp)
359 continue;
360
361 LineEntry le;
362 cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
363 if (!le.IsValid())
364 continue;
365
366 auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress();
367 if (!addr.IsValid())
368 continue;
369
370 SymbolContext sc;
371 uint32_t resolved =
372 addr.CalculateSymbolContext(&sc, eSymbolContextFunction);
373 if (resolved & eSymbolContextFunction)
374 List.Append(sc);
375 }
376 } else if (Regex) {
Pavel Labath90b0a532018-05-03 10:57:16 +0000377 RegularExpression RE(Name);
378 assert(RE.IsValid());
379 Vendor.FindFunctions(RE, true, false, List);
380 } else {
381 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
382 if (!ContextOr)
383 return ContextOr.takeError();
384 CompilerDeclContext *ContextPtr =
385 ContextOr->IsValid() ? &*ContextOr : nullptr;
386
387 Vendor.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
Pavel Labath9ea80d22018-06-28 10:03:42 +0000388 true, false, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000389 }
390 outs() << formatv("Found {0} functions:\n", List.GetSize());
391 StreamString Stream;
392 List.Dump(&Stream, nullptr);
393 outs() << Stream.GetData() << "\n";
394 return Error::success();
395}
396
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000397Error opts::symbols::findBlocks(lldb_private::Module &Module) {
398 assert(!Regex);
399 assert(!File.empty());
400 assert(Line != 0);
401
402 SymbolContextList List;
403
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000404 FileSpec src_file(File);
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000405 size_t cu_count = Module.GetNumCompileUnits();
406 for (size_t i = 0; i < cu_count; i++) {
407 lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
408 if (!cu_sp)
409 continue;
410
411 LineEntry le;
412 cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
413 if (!le.IsValid())
414 continue;
415
416 auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress();
417 if (!addr.IsValid())
418 continue;
419
420 SymbolContext sc;
421 uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock);
422 if (resolved & eSymbolContextBlock)
423 List.Append(sc);
424 }
425
426 outs() << formatv("Found {0} blocks:\n", List.GetSize());
427 StreamString Stream;
428 List.Dump(&Stream, nullptr);
429 outs() << Stream.GetData() << "\n";
430 return Error::success();
431}
432
Pavel Labath90b0a532018-05-03 10:57:16 +0000433Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
434 SymbolVendor &Vendor = *Module.GetSymbolVendor();
435 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
436 if (!ContextOr)
437 return ContextOr.takeError();
438 CompilerDeclContext *ContextPtr =
439 ContextOr->IsValid() ? &*ContextOr : nullptr;
440
441 SymbolContext SC;
442 CompilerDeclContext Result =
443 Vendor.FindNamespace(SC, ConstString(Name), ContextPtr);
444 if (Result)
445 outs() << "Found namespace: "
446 << Result.GetScopeQualifiedName().GetStringRef() << "\n";
447 else
448 outs() << "Namespace not found.\n";
449 return Error::success();
450}
451
452Error opts::symbols::findTypes(lldb_private::Module &Module) {
453 SymbolVendor &Vendor = *Module.GetSymbolVendor();
454 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
455 if (!ContextOr)
456 return ContextOr.takeError();
457 CompilerDeclContext *ContextPtr =
458 ContextOr->IsValid() ? &*ContextOr : nullptr;
459
460 SymbolContext SC;
461 DenseSet<SymbolFile *> SearchedFiles;
462 TypeMap Map;
463 Vendor.FindTypes(SC, ConstString(Name), ContextPtr, true, UINT32_MAX,
Pavel Labath9ea80d22018-06-28 10:03:42 +0000464 SearchedFiles, Map);
Pavel Labath90b0a532018-05-03 10:57:16 +0000465
466 outs() << formatv("Found {0} types:\n", Map.GetSize());
467 StreamString Stream;
468 Map.Dump(&Stream, false);
469 outs() << Stream.GetData() << "\n";
470 return Error::success();
471}
472
473Error opts::symbols::findVariables(lldb_private::Module &Module) {
474 SymbolVendor &Vendor = *Module.GetSymbolVendor();
475 VariableList List;
476 if (Regex) {
477 RegularExpression RE(Name);
478 assert(RE.IsValid());
Pavel Labath34cda142018-05-31 09:46:26 +0000479 Vendor.FindGlobalVariables(RE, UINT32_MAX, List);
Pavel Labathe6954cb2018-06-12 12:57:36 +0000480 } else if (!File.empty()) {
481 CompUnitSP CU;
482 for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) {
483 CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind);
484 if (!Candidate || Candidate->GetFilename().GetStringRef() != File)
485 continue;
486 if (CU)
487 return make_string_error("Multiple compile units for file `{0}` found.",
488 File);
489 CU = std::move(Candidate);
490 }
491
492 if (!CU)
493 return make_string_error("Compile unit `{0}` not found.", File);
494
495 List.AddVariables(CU->GetVariableList(true).get());
Pavel Labath90b0a532018-05-03 10:57:16 +0000496 } else {
497 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
498 if (!ContextOr)
499 return ContextOr.takeError();
500 CompilerDeclContext *ContextPtr =
501 ContextOr->IsValid() ? &*ContextOr : nullptr;
502
Pavel Labath34cda142018-05-31 09:46:26 +0000503 Vendor.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000504 }
505 outs() << formatv("Found {0} variables:\n", List.GetSize());
506 StreamString Stream;
507 List.Dump(&Stream, false);
508 outs() << Stream.GetData() << "\n";
509 return Error::success();
510}
511
512Error opts::symbols::dumpModule(lldb_private::Module &Module) {
513 StreamString Stream;
514 Module.ParseAllDebugSymbols();
515 Module.Dump(&Stream);
516 outs() << Stream.GetData() << "\n";
517 return Error::success();
518}
519
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000520Error opts::symbols::dumpAST(lldb_private::Module &Module) {
521 SymbolVendor &plugin = *Module.GetSymbolVendor();
522
523 auto symfile = plugin.GetSymbolFile();
524 if (!symfile)
525 return make_string_error("Module has no symbol file.");
526
527 auto clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
528 symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus));
529 if (!clang_ast_ctx)
530 return make_string_error("Can't retrieve Clang AST context.");
531
532 auto ast_ctx = clang_ast_ctx->getASTContext();
533 if (!ast_ctx)
534 return make_string_error("Can't retrieve AST context.");
535
536 auto tu = ast_ctx->getTranslationUnitDecl();
537 if (!tu)
538 return make_string_error("Can't retrieve translation unit declaration.");
539
540 symfile->ParseDeclsForContext(CompilerDeclContext(
541 clang_ast_ctx, static_cast<clang::DeclContext *>(tu)));
542
543 tu->print(outs());
544
545 return Error::success();
546}
547
Aaron Smith010edd32018-06-08 02:45:25 +0000548Error opts::symbols::verify(lldb_private::Module &Module) {
Pavel Labathe6954cb2018-06-12 12:57:36 +0000549 SymbolVendor &plugin = *Module.GetSymbolVendor();
Aaron Smith010edd32018-06-08 02:45:25 +0000550
Pavel Labathe6954cb2018-06-12 12:57:36 +0000551 SymbolFile *symfile = plugin.GetSymbolFile();
Aaron Smith010edd32018-06-08 02:45:25 +0000552 if (!symfile)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000553 return make_string_error("Module has no symbol file.");
Aaron Smith010edd32018-06-08 02:45:25 +0000554
555 uint32_t comp_units_count = symfile->GetNumCompileUnits();
556
557 outs() << "Found " << comp_units_count << " compile units.\n";
558
559 for (uint32_t i = 0; i < comp_units_count; i++) {
560 lldb::CompUnitSP comp_unit = symfile->ParseCompileUnitAtIndex(i);
561 if (!comp_unit)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000562 return make_string_error("Connot parse compile unit {0}.", i);
Aaron Smith010edd32018-06-08 02:45:25 +0000563
Pavel Labath9ea80d22018-06-28 10:03:42 +0000564 outs() << "Processing '" << comp_unit->GetFilename().AsCString()
565 << "' compile unit.\n";
Aaron Smith010edd32018-06-08 02:45:25 +0000566
567 LineTable *lt = comp_unit->GetLineTable();
568 if (!lt)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000569 return make_string_error("Can't get a line table of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000570
571 uint32_t count = lt->GetSize();
572
573 outs() << "The line table contains " << count << " entries.\n";
574
575 if (count == 0)
576 continue;
577
578 LineEntry le;
579 if (!lt->GetLineEntryAtIndex(0, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000580 return make_string_error("Can't get a line entry of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000581
582 for (uint32_t i = 1; i < count; i++) {
583 lldb::addr_t curr_end =
Pavel Labath9ea80d22018-06-28 10:03:42 +0000584 le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
Aaron Smith010edd32018-06-08 02:45:25 +0000585
586 if (!lt->GetLineEntryAtIndex(i, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000587 return make_string_error("Can't get a line entry of a compile unit");
Aaron Smith010edd32018-06-08 02:45:25 +0000588
589 if (curr_end > le.range.GetBaseAddress().GetFileAddress())
Pavel Labathe6954cb2018-06-12 12:57:36 +0000590 return make_string_error(
591 "Line table of a compile unit is inconsistent.");
Aaron Smith010edd32018-06-08 02:45:25 +0000592 }
593 }
594
595 outs() << "The symbol information is verified.\n";
596
597 return Error::success();
598}
599
Pavel Labath38d9ff72018-06-12 13:26:43 +0000600Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000601 if (Verify && DumpAST)
602 return make_string_error(
603 "Cannot both verify symbol information and dump AST.");
604
Pavel Labathe6954cb2018-06-12 12:57:36 +0000605 if (Verify) {
606 if (Find != FindType::None)
607 return make_string_error(
608 "Cannot both search and verify symbol information.");
Pavel Labath9ea80d22018-06-28 10:03:42 +0000609 if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
610 Line != 0)
611 return make_string_error(
612 "-regex, -context, -name, -file and -line options are not "
613 "applicable for symbol verification.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000614 return verify;
Pavel Labath90b0a532018-05-03 10:57:16 +0000615 }
616
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000617 if (DumpAST) {
618 if (Find != FindType::None)
Aaron Smith037ed1b2018-12-06 21:36:39 +0000619 return make_string_error("Cannot both search and dump AST.");
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000620 if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
621 Line != 0)
622 return make_string_error(
623 "-regex, -context, -name, -file and -line options are not "
624 "applicable for dumping AST.");
625 return dumpAST;
626 }
627
Pavel Labathe6954cb2018-06-12 12:57:36 +0000628 if (Regex && !Context.empty())
629 return make_string_error(
630 "Cannot search using both regular expressions and context.");
631
632 if (Regex && !RegularExpression(Name).IsValid())
633 return make_string_error("`{0}` is not a valid regular expression.", Name);
634
635 if (Regex + !Context.empty() + !File.empty() >= 2)
636 return make_string_error(
637 "Only one of -regex, -context and -file may be used simultaneously.");
638 if (Regex && Name.empty())
639 return make_string_error("-regex used without a -name");
640
641 switch (Find) {
642 case FindType::None:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000643 if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000644 return make_string_error(
645 "Specify search type (-find) to use search options.");
646 return dumpModule;
647
648 case FindType::Function:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000649 if (!File.empty() + (Line != 0) == 1)
650 return make_string_error("Both file name and line number must be "
651 "specified when searching a function "
652 "by file position.");
653 if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2)
654 return make_string_error("Only one of regular expression, function-flags "
655 "and file position may be used simultaneously "
656 "when searching a function.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000657 return findFunctions;
658
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000659 case FindType::Block:
660 if (File.empty() || Line == 0)
661 return make_string_error("Both file name and line number must be "
662 "specified when searching a block.");
663 if (Regex || getFunctionNameFlags() != 0)
664 return make_string_error("Cannot use regular expression or "
665 "function-flags for searching a block.");
666 return findBlocks;
667
Pavel Labathe6954cb2018-06-12 12:57:36 +0000668 case FindType::Namespace:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000669 if (Regex || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000670 return make_string_error("Cannot search for namespaces using regular "
Pavel Labath9ea80d22018-06-28 10:03:42 +0000671 "expressions, file names or line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000672 return findNamespaces;
673
674 case FindType::Type:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000675 if (Regex || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000676 return make_string_error("Cannot search for types using regular "
Pavel Labath9ea80d22018-06-28 10:03:42 +0000677 "expressions, file names or line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000678 return findTypes;
679
680 case FindType::Variable:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000681 if (Line != 0)
682 return make_string_error("Cannot search for variables "
683 "using line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000684 return findVariables;
685 }
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000686
687 llvm_unreachable("Unsupported symbol action.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000688}
689
690int opts::symbols::dumpSymbols(Debugger &Dbg) {
691 auto ActionOr = getAction();
692 if (!ActionOr) {
693 logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), "");
694 return 1;
695 }
696 auto Action = *ActionOr;
Pavel Labath90b0a532018-05-03 10:57:16 +0000697
698 int HadErrors = 0;
699 for (const auto &File : InputFilenames) {
700 outs() << "Module: " << File << "\n";
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000701 ModuleSpec Spec{FileSpec(File)};
702 Spec.GetSymbolFileSpec().SetFile(File, FileSpec::Style::native);
Zachary Turnera6d54642017-12-02 00:15:29 +0000703
704 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
Pavel Labath90b0a532018-05-03 10:57:16 +0000705 SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
706 if (!Vendor) {
707 WithColor::error() << "Module has no symbol vendor.\n";
708 HadErrors = 1;
709 continue;
710 }
Pavel Labathe6954cb2018-06-12 12:57:36 +0000711
Pavel Labath90b0a532018-05-03 10:57:16 +0000712 if (Error E = Action(*ModulePtr)) {
713 WithColor::error() << toString(std::move(E)) << "\n";
714 HadErrors = 1;
715 }
Zachary Turnera6d54642017-12-02 00:15:29 +0000716
Pavel Labath90b0a532018-05-03 10:57:16 +0000717 outs().flush();
Zachary Turnera6d54642017-12-02 00:15:29 +0000718 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000719 return HadErrors;
Zachary Turnera6d54642017-12-02 00:15:29 +0000720}
721
Pavel Labath280d2e82018-12-12 12:35:25 +0000722static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) {
723 size_t Count = List.GetNumSections(0);
724 if (Count == 0) {
725 Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : "");
726 return;
727 }
728 Printer.formatLine("Showing {0} {1}sections", Count,
729 is_subsection ? "sub" : "");
730 for (size_t I = 0; I < Count; ++I) {
731 auto S = List.GetSectionAtIndex(I);
732 assert(S);
733 AutoIndent Indent(Printer, 2);
734 Printer.formatLine("Index: {0}", I);
Pavel Labath0d38e4f2018-12-18 15:56:45 +0000735 Printer.formatLine("ID: {0:x}", S->GetID());
Pavel Labath280d2e82018-12-12 12:35:25 +0000736 Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
737 Printer.formatLine("Type: {0}", S->GetTypeAsCString());
Pavel Labath62a82542018-12-15 13:45:38 +0000738 Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions()));
Pavel Labathef8683a2018-12-12 15:46:18 +0000739 Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific());
Pavel Labath62a82542018-12-15 13:45:38 +0000740 Printer.formatLine("VM address: {0:x}", S->GetFileAddress());
Pavel Labath280d2e82018-12-12 12:35:25 +0000741 Printer.formatLine("VM size: {0}", S->GetByteSize());
742 Printer.formatLine("File size: {0}", S->GetFileSize());
743
744 if (opts::object::SectionContents) {
745 DataExtractor Data;
746 S->GetSectionData(Data);
747 ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()};
748 Printer.formatBinary("Data: ", Bytes, 0);
749 }
750
751 if (S->GetType() == eSectionTypeContainer)
752 dumpSectionList(Printer, S->GetChildren(), true);
753 Printer.NewLine();
754 }
755}
756
Pavel Labath62a7f802018-06-29 12:15:54 +0000757static int dumpObjectFiles(Debugger &Dbg) {
Zachary Turner888a4282017-12-01 00:52:51 +0000758 LinePrinter Printer(4, llvm::outs());
759
Pavel Labath90b0a532018-05-03 10:57:16 +0000760 int HadErrors = 0;
Pavel Labath62a7f802018-06-29 12:15:54 +0000761 for (const auto &File : opts::object::InputFilenames) {
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000762 ModuleSpec Spec{FileSpec(File)};
Zachary Turner888a4282017-12-01 00:52:51 +0000763
Zachary Turnera6d54642017-12-02 00:15:29 +0000764 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
Pavel Labath1f6b2472018-12-10 17:16:38 +0000765
766 ObjectFile *ObjectPtr = ModulePtr->GetObjectFile();
767 if (!ObjectPtr) {
768 WithColor::error() << File << " not recognised as an object file\n";
769 HadErrors = 1;
770 continue;
771 }
772
Pavel Labath96979ce2018-03-06 15:56:20 +0000773 // Fetch symbol vendor before we get the section list to give the symbol
774 // vendor a chance to populate it.
775 ModulePtr->GetSymbolVendor();
Zachary Turner888a4282017-12-01 00:52:51 +0000776 SectionList *Sections = ModulePtr->GetSectionList();
777 if (!Sections) {
778 llvm::errs() << "Could not load sections for module " << File << "\n";
Pavel Labath90b0a532018-05-03 10:57:16 +0000779 HadErrors = 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000780 continue;
781 }
782
Pavel Labath1f6b2472018-12-10 17:16:38 +0000783 Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName());
Pavel Labath62a7f802018-06-29 12:15:54 +0000784 Printer.formatLine("Architecture: {0}",
785 ModulePtr->GetArchitecture().GetTriple().getTriple());
786 Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
Pavel Labath1f6b2472018-12-10 17:16:38 +0000787 Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable());
788 Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped());
789 Printer.formatLine("Type: {0}", ObjectPtr->GetType());
790 Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata());
Pavel Labath62a7f802018-06-29 12:15:54 +0000791
Pavel Labath280d2e82018-12-12 12:35:25 +0000792 dumpSectionList(Printer, *Sections, /*is_subsection*/ false);
Aaron Smith037ed1b2018-12-06 21:36:39 +0000793
794 if (opts::object::SectionDependentModules) {
795 // A non-empty section list ensures a valid object file.
796 auto Obj = ModulePtr->GetObjectFile();
797 FileSpecList Files;
798 auto Count = Obj->GetDependentModules(Files);
799 Printer.formatLine("Showing {0} dependent module(s)", Count);
800 for (size_t I = 0; I < Files.GetSize(); ++I) {
801 AutoIndent Indent(Printer, 2);
802 Printer.formatLine("Name: {0}",
803 Files.GetFileSpecAtIndex(I).GetCString());
804 }
805 Printer.NewLine();
806 }
Zachary Turner888a4282017-12-01 00:52:51 +0000807 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000808 return HadErrors;
Zachary Turner888a4282017-12-01 00:52:51 +0000809}
810
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000811/// Check if two half-open intervals intersect:
812/// http://world.std.com/~swmcd/steven/tech/interval.html
813bool opts::irmemorymap::areAllocationsOverlapping(const AllocationT &L,
814 const AllocationT &R) {
815 return R.first < L.second && L.first < R.second;
816}
817
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000818bool opts::irmemorymap::evalMalloc(StringRef Line,
819 IRMemoryMapTestState &State) {
820 // ::= <label> = malloc <size> <alignment>
821 StringRef Label;
822 std::tie(Label, Line) = Line.split('=');
823 if (Line.empty())
824 return false;
825 Label = Label.trim();
826 Line = Line.trim();
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000827 size_t Size;
828 uint8_t Alignment;
829 int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment);
830 if (Matches != 2)
831 return false;
832
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000833 outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label,
834 Size, Alignment);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000835 if (!isPowerOf2_32(Alignment)) {
836 outs() << "Malloc error: alignment is not a power of 2\n";
837 exit(1);
838 }
839
Vedant Kumarf616b9d2018-05-31 22:09:00 +0000840 IRMemoryMap::AllocationPolicy AP =
841 UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly
842 : IRMemoryMap::eAllocationPolicyProcessOnly;
843
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000844 // Issue the malloc in the target process with "-rw" permissions.
845 const uint32_t Permissions = 0x3;
846 const bool ZeroMemory = false;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000847 Status ST;
848 addr_t Addr =
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000849 State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000850 if (ST.Fail()) {
851 outs() << formatv("Malloc error: {0}\n", ST);
852 return true;
853 }
854
855 // Print the result of the allocation before checking its validity.
856 outs() << formatv("Malloc: address = {0:x}\n", Addr);
857
858 // Check that the allocation is aligned.
859 if (!Addr || Addr % Alignment != 0) {
860 outs() << "Malloc error: zero or unaligned allocation detected\n";
861 exit(1);
862 }
863
864 // Check that the allocation does not overlap another allocation. Do so by
865 // testing each allocation which may cover the interval [Addr, EndOfRegion).
866 addr_t EndOfRegion = Addr + Size;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000867 auto Probe = State.Allocations.begin();
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000868 Probe.advanceTo(Addr); //< First interval s.t stop >= Addr.
869 AllocationT NewAllocation = {Addr, EndOfRegion};
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000870 while (Probe != State.Allocations.end() && Probe.start() < EndOfRegion) {
Vedant Kumarf3b6d292018-05-30 19:46:47 +0000871 AllocationT ProbeAllocation = {Probe.start(), Probe.stop()};
872 if (areAllocationsOverlapping(ProbeAllocation, NewAllocation)) {
873 outs() << "Malloc error: overlapping allocation detected"
874 << formatv(", previous allocation at [{0:x}, {1:x})\n",
875 Probe.start(), Probe.stop());
876 exit(1);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000877 }
Vedant Kumarf3b6d292018-05-30 19:46:47 +0000878 ++Probe;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000879 }
880
Aaron Smith037ed1b2018-12-06 21:36:39 +0000881 // Insert the new allocation into the interval map. Use unique allocation
882 // IDs to inhibit interval coalescing.
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000883 static unsigned AllocationID = 0;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000884 if (Size)
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000885 State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
886
887 // Store the label -> address mapping.
888 State.Label2AddrMap[Label] = Addr;
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000889
890 return true;
891}
892
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000893bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) {
894 // ::= free <label>
895 if (!Line.consume_front("free"))
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000896 return false;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000897 StringRef Label = Line.trim();
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000898
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000899 outs() << formatv("Command: free({0})\n", Label);
900 auto LabelIt = State.Label2AddrMap.find(Label);
901 if (LabelIt == State.Label2AddrMap.end()) {
902 outs() << "Free error: Invalid allocation label\n";
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000903 exit(1);
904 }
905
906 Status ST;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000907 addr_t Addr = LabelIt->getValue();
908 State.Map.Free(Addr, ST);
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000909 if (ST.Fail()) {
910 outs() << formatv("Free error: {0}\n", ST);
911 exit(1);
912 }
913
914 // Erase the allocation from the live interval map.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000915 auto Interval = State.Allocations.find(Addr);
916 if (Interval != State.Allocations.end()) {
917 outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(),
918 Interval.stop());
919 Interval.erase();
920 }
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000921
922 return true;
923}
924
925int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
926 // Set up a Target.
927 TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target);
928
929 // Set up a Process. In order to allocate memory within a target, this
930 // process must be alive and must support JIT'ing.
931 CommandReturnObject Result;
932 Dbg.SetAsyncExecution(false);
933 CommandInterpreter &CI = Dbg.GetCommandInterpreter();
934 auto IssueCmd = [&](const char *Cmd) -> bool {
935 return CI.HandleCommand(Cmd, eLazyBoolNo, Result);
936 };
937 if (!IssueCmd("b main") || !IssueCmd("run")) {
938 outs() << formatv("Failed: {0}\n", Result.GetErrorData());
939 exit(1);
940 }
941
942 ProcessSP Process = Target->GetProcessSP();
943 if (!Process || !Process->IsAlive() || !Process->CanJIT()) {
944 outs() << "Cannot use process to test IRMemoryMap\n";
945 exit(1);
946 }
947
948 // Set up an IRMemoryMap and associated testing state.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000949 IRMemoryMapTestState State(Target);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000950
951 // Parse and apply commands from the command file.
952 std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile);
953 StringRef Rest = MB->getBuffer();
954 while (!Rest.empty()) {
955 StringRef Line;
956 std::tie(Line, Rest) = Rest.split('\n');
957 Line = Line.ltrim();
958
959 if (Line.empty() || Line[0] == '#')
960 continue;
961
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000962 if (evalMalloc(Line, State))
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000963 continue;
964
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000965 if (evalFree(Line, State))
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000966 continue;
967
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000968 errs() << "Could not parse line: " << Line << "\n";
969 exit(1);
970 }
971 return 0;
972}
973
Zachary Turner888a4282017-12-01 00:52:51 +0000974int main(int argc, const char *argv[]) {
975 StringRef ToolName = argv[0];
976 sys::PrintStackTraceOnErrorSignal(ToolName);
977 PrettyStackTraceProgram X(argc, argv);
978 llvm_shutdown_obj Y;
979
980 cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
981
Pavel Labath90b0a532018-05-03 10:57:16 +0000982 SystemLifetimeManager DebuggerLifetime;
Jonas Devlieghere15eacd72018-12-03 17:28:29 +0000983 if (auto e = DebuggerLifetime.Initialize(
984 llvm::make_unique<SystemInitializerTest>(), {}, nullptr)) {
985 WithColor::error() << "initialization failed: " << toString(std::move(e))
986 << '\n';
987 return 1;
988 }
989
Pavel Labath90b0a532018-05-03 10:57:16 +0000990 CleanUp TerminateDebugger([&] { DebuggerLifetime.Terminate(); });
Zachary Turner888a4282017-12-01 00:52:51 +0000991
992 auto Dbg = lldb_private::Debugger::CreateInstance();
993
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000994 if (!opts::Log.empty())
995 Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, errs());
996
Pavel Labath7c945822018-02-26 18:50:16 +0000997 if (opts::BreakpointSubcommand)
Pavel Labath90b0a532018-05-03 10:57:16 +0000998 return opts::breakpoint::evaluateBreakpoints(*Dbg);
Pavel Labath62a7f802018-06-29 12:15:54 +0000999 if (opts::ObjectFileSubcommand)
1000 return dumpObjectFiles(*Dbg);
Pavel Labath90b0a532018-05-03 10:57:16 +00001001 if (opts::SymbolsSubcommand)
1002 return opts::symbols::dumpSymbols(*Dbg);
Vedant Kumarc1cd8262018-05-30 19:39:10 +00001003 if (opts::IRMemoryMapSubcommand)
1004 return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
Zachary Turner888a4282017-12-01 00:52:51 +00001005
Pavel Labath90b0a532018-05-03 10:57:16 +00001006 WithColor::error() << "No command specified.\n";
1007 return 1;
Zachary Turner888a4282017-12-01 00:52:51 +00001008}