blob: 3efb26b8c88c7b3c3a5c35e032568bf32d471d44 [file] [log] [blame]
Zachary Turner888a4282017-12-01 00:52:51 +00001//===- lldb-test.cpp ------------------------------------------ *- C++ --*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Zachary Turner888a4282017-12-01 00:52:51 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "FormatUtil.h"
10#include "SystemInitializerTest.h"
11
Zachary Turnera6d54642017-12-02 00:15:29 +000012#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
Pavel Labath7c945822018-02-26 18:50:16 +000013#include "lldb/Breakpoint/BreakpointLocation.h"
Zachary Turner888a4282017-12-01 00:52:51 +000014#include "lldb/Core/Debugger.h"
15#include "lldb/Core/Module.h"
16#include "lldb/Core/Section.h"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000017#include "lldb/Expression/IRMemoryMap.h"
Zachary Turner888a4282017-12-01 00:52:51 +000018#include "lldb/Initialization/SystemLifetimeManager.h"
Pavel Labath7c945822018-02-26 18:50:16 +000019#include "lldb/Interpreter/CommandInterpreter.h"
20#include "lldb/Interpreter/CommandReturnObject.h"
Zachary Turnera6d54642017-12-02 00:15:29 +000021#include "lldb/Symbol/ClangASTContext.h"
22#include "lldb/Symbol/ClangASTImporter.h"
Aaron Smith010edd32018-06-08 02:45:25 +000023#include "lldb/Symbol/CompileUnit.h"
24#include "lldb/Symbol/LineTable.h"
Pavel Labath90b0a532018-05-03 10:57:16 +000025#include "lldb/Symbol/SymbolVendor.h"
26#include "lldb/Symbol/TypeList.h"
27#include "lldb/Symbol/VariableList.h"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000028#include "lldb/Target/Process.h"
29#include "lldb/Target/Target.h"
Pavel Labath90b0a532018-05-03 10:57:16 +000030#include "lldb/Utility/CleanUp.h"
Zachary Turner888a4282017-12-01 00:52:51 +000031#include "lldb/Utility/DataExtractor.h"
Pavel Labath62a82542018-12-15 13:45:38 +000032#include "lldb/Utility/State.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 Labath1cf23e12019-01-11 11:17:51 +0000102static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
103 cl::Required, cl::sub(SymbolsSubcommand));
104
105static cl::opt<std::string>
106 SymbolPath("symbol-file",
107 cl::desc("The file from which to fetch symbol information."),
108 cl::value_desc("file"), cl::sub(SymbolsSubcommand));
109
Pavel Labath90b0a532018-05-03 10:57:16 +0000110enum class FindType {
111 None,
112 Function,
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000113 Block,
Pavel Labath90b0a532018-05-03 10:57:16 +0000114 Namespace,
115 Type,
116 Variable,
117};
118static cl::opt<FindType> Find(
119 "find", cl::desc("Choose search type:"),
120 cl::values(
Pavel Labath9ea80d22018-06-28 10:03:42 +0000121 clEnumValN(FindType::None, "none", "No search, just dump the module."),
Pavel Labath90b0a532018-05-03 10:57:16 +0000122 clEnumValN(FindType::Function, "function", "Find functions."),
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000123 clEnumValN(FindType::Block, "block", "Find blocks."),
Pavel Labath90b0a532018-05-03 10:57:16 +0000124 clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
125 clEnumValN(FindType::Type, "type", "Find types."),
126 clEnumValN(FindType::Variable, "variable", "Find global variables.")),
127 cl::sub(SymbolsSubcommand));
128
129static cl::opt<std::string> Name("name", cl::desc("Name to find."),
130 cl::sub(SymbolsSubcommand));
131static cl::opt<bool>
132 Regex("regex",
133 cl::desc("Search using regular expressions (avaliable for variables "
134 "and functions only)."),
135 cl::sub(SymbolsSubcommand));
136static cl::opt<std::string>
137 Context("context",
138 cl::desc("Restrict search to the context of the given variable."),
139 cl::value_desc("variable"), cl::sub(SymbolsSubcommand));
140
141static cl::list<FunctionNameType> FunctionNameFlags(
142 "function-flags", cl::desc("Function search flags:"),
143 cl::values(clEnumValN(eFunctionNameTypeAuto, "auto",
144 "Automatically deduce flags based on name."),
145 clEnumValN(eFunctionNameTypeFull, "full", "Full function name."),
146 clEnumValN(eFunctionNameTypeBase, "base", "Base name."),
147 clEnumValN(eFunctionNameTypeMethod, "method", "Method name."),
148 clEnumValN(eFunctionNameTypeSelector, "selector",
149 "Selector name.")),
150 cl::sub(SymbolsSubcommand));
151static FunctionNameType getFunctionNameFlags() {
152 FunctionNameType Result = FunctionNameType(0);
153 for (FunctionNameType Flag : FunctionNameFlags)
154 Result = FunctionNameType(Result | Flag);
155 return Result;
156}
157
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000158static cl::opt<bool> DumpAST("dump-ast",
159 cl::desc("Dump AST restored from symbols."),
160 cl::sub(SymbolsSubcommand));
161
Aaron Smith010edd32018-06-08 02:45:25 +0000162static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
163 cl::sub(SymbolsSubcommand));
164
Pavel Labathe6954cb2018-06-12 12:57:36 +0000165static cl::opt<std::string> File("file",
166 cl::desc("File (compile unit) to search."),
167 cl::sub(SymbolsSubcommand));
Pavel Labath9ea80d22018-06-28 10:03:42 +0000168static cl::opt<int> Line("line", cl::desc("Line to search."),
169 cl::sub(SymbolsSubcommand));
Pavel Labathe6954cb2018-06-12 12:57:36 +0000170
Pavel Labath90b0a532018-05-03 10:57:16 +0000171static Expected<CompilerDeclContext> getDeclContext(SymbolVendor &Vendor);
172
173static Error findFunctions(lldb_private::Module &Module);
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000174static Error findBlocks(lldb_private::Module &Module);
Pavel Labath90b0a532018-05-03 10:57:16 +0000175static Error findNamespaces(lldb_private::Module &Module);
176static Error findTypes(lldb_private::Module &Module);
177static Error findVariables(lldb_private::Module &Module);
178static Error dumpModule(lldb_private::Module &Module);
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000179static Error dumpAST(lldb_private::Module &Module);
Aaron Smith010edd32018-06-08 02:45:25 +0000180static Error verify(lldb_private::Module &Module);
Pavel Labath90b0a532018-05-03 10:57:16 +0000181
Pavel Labath38d9ff72018-06-12 13:26:43 +0000182static Expected<Error (*)(lldb_private::Module &)> getAction();
Pavel Labath90b0a532018-05-03 10:57:16 +0000183static int dumpSymbols(Debugger &Dbg);
Pavel Labath9ea80d22018-06-28 10:03:42 +0000184} // namespace symbols
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000185
186namespace irmemorymap {
187static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
188 cl::Required,
189 cl::sub(IRMemoryMapSubcommand));
190static cl::opt<std::string> CommandFile(cl::Positional,
191 cl::desc("<command-file>"),
192 cl::init("-"),
193 cl::sub(IRMemoryMapSubcommand));
Vedant Kumarf616b9d2018-05-31 22:09:00 +0000194static cl::opt<bool> UseHostOnlyAllocationPolicy(
195 "host-only", cl::desc("Use the host-only allocation policy"),
196 cl::init(false), cl::sub(IRMemoryMapSubcommand));
197
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000198using AllocationT = std::pair<addr_t, addr_t>;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000199using AddrIntervalMap =
Pavel Labath9ea80d22018-06-28 10:03:42 +0000200 IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000201
202struct IRMemoryMapTestState {
203 TargetSP Target;
204 IRMemoryMap Map;
205
206 AddrIntervalMap::Allocator IntervalMapAllocator;
207 AddrIntervalMap Allocations;
208
209 StringMap<addr_t> Label2AddrMap;
210
211 IRMemoryMapTestState(TargetSP Target)
212 : Target(Target), Map(Target), Allocations(IntervalMapAllocator) {}
213};
214
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000215bool evalMalloc(StringRef Line, IRMemoryMapTestState &State);
216bool evalFree(StringRef Line, IRMemoryMapTestState &State);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000217int evaluateMemoryMapCommands(Debugger &Dbg);
218} // namespace irmemorymap
219
Zachary Turner888a4282017-12-01 00:52:51 +0000220} // namespace opts
221
Pavel Labathe6954cb2018-06-12 12:57:36 +0000222template <typename... Args>
223static Error make_string_error(const char *Format, Args &&... args) {
224 return llvm::make_error<llvm::StringError>(
225 llvm::formatv(Format, std::forward<Args>(args)...).str(),
226 llvm::inconvertibleErrorCode());
227}
228
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000229TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) {
230 TargetSP Target;
Jonas Devliegheref9a07e92018-09-20 09:09:05 +0000231 Status ST = Dbg.GetTargetList().CreateTarget(
232 Dbg, Filename, /*triple*/ "", eLoadDependentsNo,
233 /*platform_options*/ nullptr, Target);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000234 if (ST.Fail()) {
235 errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST);
236 exit(1);
237 }
238 return Target;
239}
240
241std::unique_ptr<MemoryBuffer> opts::openFile(const std::string &Filename) {
242 auto MB = MemoryBuffer::getFileOrSTDIN(Filename);
243 if (!MB) {
244 errs() << formatv("Could not open file '{0}: {1}\n", Filename,
245 MB.getError().message());
246 exit(1);
247 }
248 return std::move(*MB);
249}
250
Pavel Labath7c945822018-02-26 18:50:16 +0000251void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) {
252 P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize()));
253 if (List.GetSize() > 0)
254 P.formatLine("At least one breakpoint.");
255 for (size_t i = 0, e = List.GetSize(); i < e; ++i) {
256 BreakpointSP BP = List.GetBreakpointAtIndex(i);
257 P.formatLine("Breakpoint ID {0}:", BP->GetID());
258 AutoIndent Indent(P, 2);
259 P.formatLine("{0} location{1}.", BP->GetNumLocations(),
260 plural(BP->GetNumLocations()));
261 if (BP->GetNumLocations() > 0)
262 P.formatLine("At least one location.");
263 P.formatLine("{0} resolved location{1}.", BP->GetNumResolvedLocations(),
264 plural(BP->GetNumResolvedLocations()));
265 if (BP->GetNumResolvedLocations() > 0)
266 P.formatLine("At least one resolved location.");
267 for (size_t l = 0, le = BP->GetNumLocations(); l < le; ++l) {
268 BreakpointLocationSP Loc = BP->GetLocationAtIndex(l);
269 P.formatLine("Location ID {0}:", Loc->GetID());
270 AutoIndent Indent(P, 2);
271 P.formatLine("Enabled: {0}", Loc->IsEnabled());
272 P.formatLine("Resolved: {0}", Loc->IsResolved());
Jim Ingham08581262018-03-12 21:17:04 +0000273 SymbolContext sc;
274 Loc->GetAddress().CalculateSymbolContext(&sc);
275 lldb_private::StreamString S;
276 sc.DumpStopContext(&S, BP->GetTarget().GetProcessSP().get(),
277 Loc->GetAddress(), false, true, false, true, true);
278 P.formatLine("Address: {0}", S.GetString());
Pavel Labath7c945822018-02-26 18:50:16 +0000279 }
280 }
281 P.NewLine();
282}
283
284std::string opts::breakpoint::substitute(StringRef Cmd) {
285 std::string Result;
286 raw_string_ostream OS(Result);
287 while (!Cmd.empty()) {
288 switch (Cmd[0]) {
289 case '%':
290 if (Cmd.consume_front("%p") && (Cmd.empty() || !isalnum(Cmd[0]))) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000291 OS << sys::path::parent_path(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000292 break;
293 }
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000294 LLVM_FALLTHROUGH;
Pavel Labath7c945822018-02-26 18:50:16 +0000295 default:
296 size_t pos = Cmd.find('%');
297 OS << Cmd.substr(0, pos);
298 Cmd = Cmd.substr(pos);
299 break;
300 }
301 }
302 return std::move(OS.str());
303}
304
Pavel Labath90b0a532018-05-03 10:57:16 +0000305int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000306 TargetSP Target = opts::createTarget(Dbg, breakpoint::Target);
307 std::unique_ptr<MemoryBuffer> MB = opts::openFile(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000308
309 LinePrinter P(4, outs());
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000310 StringRef Rest = MB->getBuffer();
Pavel Labath90b0a532018-05-03 10:57:16 +0000311 int HadErrors = 0;
Pavel Labath7c945822018-02-26 18:50:16 +0000312 while (!Rest.empty()) {
313 StringRef Line;
314 std::tie(Line, Rest) = Rest.split('\n');
315 Line = Line.ltrim();
316 if (Line.empty() || Line[0] == '#')
317 continue;
318
319 if (!Persistent)
320 Target->RemoveAllBreakpoints(/*internal_also*/ true);
321
322 std::string Command = substitute(Line);
323 P.formatLine("Command: {0}", Command);
324 CommandReturnObject Result;
325 if (!Dbg.GetCommandInterpreter().HandleCommand(
326 Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
327 P.formatLine("Failed: {0}", Result.GetErrorData());
Pavel Labath90b0a532018-05-03 10:57:16 +0000328 HadErrors = 1;
Pavel Labath7c945822018-02-26 18:50:16 +0000329 continue;
330 }
331
332 dumpState(Target->GetBreakpointList(/*internal*/ false), P);
333 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000334 return HadErrors;
Pavel Labath7c945822018-02-26 18:50:16 +0000335}
336
Pavel Labath90b0a532018-05-03 10:57:16 +0000337Expected<CompilerDeclContext>
338opts::symbols::getDeclContext(SymbolVendor &Vendor) {
339 if (Context.empty())
340 return CompilerDeclContext();
341 VariableList List;
Pavel Labath34cda142018-05-31 09:46:26 +0000342 Vendor.FindGlobalVariables(ConstString(Context), nullptr, UINT32_MAX, List);
Pavel Labathe6954cb2018-06-12 12:57:36 +0000343 if (List.Empty())
344 return make_string_error("Context search didn't find a match.");
345 if (List.GetSize() > 1)
346 return make_string_error("Context search found multiple matches.");
Pavel Labath90b0a532018-05-03 10:57:16 +0000347 return List.GetVariableAtIndex(0)->GetDeclContext();
348}
349
350Error opts::symbols::findFunctions(lldb_private::Module &Module) {
351 SymbolVendor &Vendor = *Module.GetSymbolVendor();
352 SymbolContextList List;
Pavel Labath9ea80d22018-06-28 10:03:42 +0000353 if (!File.empty()) {
354 assert(Line != 0);
355
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000356 FileSpec src_file(File);
Pavel Labath9ea80d22018-06-28 10:03:42 +0000357 size_t cu_count = Module.GetNumCompileUnits();
358 for (size_t i = 0; i < cu_count; i++) {
359 lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
360 if (!cu_sp)
361 continue;
362
363 LineEntry le;
364 cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
365 if (!le.IsValid())
366 continue;
367
368 auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress();
369 if (!addr.IsValid())
370 continue;
371
372 SymbolContext sc;
373 uint32_t resolved =
374 addr.CalculateSymbolContext(&sc, eSymbolContextFunction);
375 if (resolved & eSymbolContextFunction)
376 List.Append(sc);
377 }
378 } else if (Regex) {
Pavel Labath90b0a532018-05-03 10:57:16 +0000379 RegularExpression RE(Name);
380 assert(RE.IsValid());
381 Vendor.FindFunctions(RE, true, false, List);
382 } else {
383 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
384 if (!ContextOr)
385 return ContextOr.takeError();
386 CompilerDeclContext *ContextPtr =
387 ContextOr->IsValid() ? &*ContextOr : nullptr;
388
389 Vendor.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
Pavel Labath9ea80d22018-06-28 10:03:42 +0000390 true, false, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000391 }
392 outs() << formatv("Found {0} functions:\n", List.GetSize());
393 StreamString Stream;
394 List.Dump(&Stream, nullptr);
395 outs() << Stream.GetData() << "\n";
396 return Error::success();
397}
398
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000399Error opts::symbols::findBlocks(lldb_private::Module &Module) {
400 assert(!Regex);
401 assert(!File.empty());
402 assert(Line != 0);
403
404 SymbolContextList List;
405
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000406 FileSpec src_file(File);
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000407 size_t cu_count = Module.GetNumCompileUnits();
408 for (size_t i = 0; i < cu_count; i++) {
409 lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
410 if (!cu_sp)
411 continue;
412
413 LineEntry le;
414 cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
415 if (!le.IsValid())
416 continue;
417
418 auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress();
419 if (!addr.IsValid())
420 continue;
421
422 SymbolContext sc;
423 uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock);
424 if (resolved & eSymbolContextBlock)
425 List.Append(sc);
426 }
427
428 outs() << formatv("Found {0} blocks:\n", List.GetSize());
429 StreamString Stream;
430 List.Dump(&Stream, nullptr);
431 outs() << Stream.GetData() << "\n";
432 return Error::success();
433}
434
Pavel Labath90b0a532018-05-03 10:57:16 +0000435Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
436 SymbolVendor &Vendor = *Module.GetSymbolVendor();
437 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
438 if (!ContextOr)
439 return ContextOr.takeError();
440 CompilerDeclContext *ContextPtr =
441 ContextOr->IsValid() ? &*ContextOr : nullptr;
442
Pavel Labath90b0a532018-05-03 10:57:16 +0000443 CompilerDeclContext Result =
Zachary Turnerc0a246a2019-01-14 22:41:00 +0000444 Vendor.FindNamespace(ConstString(Name), ContextPtr);
Pavel Labath90b0a532018-05-03 10:57:16 +0000445 if (Result)
446 outs() << "Found namespace: "
447 << Result.GetScopeQualifiedName().GetStringRef() << "\n";
448 else
449 outs() << "Namespace not found.\n";
450 return Error::success();
451}
452
453Error opts::symbols::findTypes(lldb_private::Module &Module) {
454 SymbolVendor &Vendor = *Module.GetSymbolVendor();
455 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
456 if (!ContextOr)
457 return ContextOr.takeError();
458 CompilerDeclContext *ContextPtr =
459 ContextOr->IsValid() ? &*ContextOr : nullptr;
460
Pavel Labath90b0a532018-05-03 10:57:16 +0000461 DenseSet<SymbolFile *> SearchedFiles;
462 TypeMap Map;
Zachary Turner576495e2019-01-14 22:41:21 +0000463 Vendor.FindTypes(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();
Zachary Turnerc68925a2019-01-09 21:20:44 +0000522 Module.ParseAllDebugSymbols();
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000523
524 auto symfile = plugin.GetSymbolFile();
525 if (!symfile)
526 return make_string_error("Module has no symbol file.");
527
528 auto clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
529 symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus));
530 if (!clang_ast_ctx)
531 return make_string_error("Can't retrieve Clang AST context.");
532
533 auto ast_ctx = clang_ast_ctx->getASTContext();
534 if (!ast_ctx)
535 return make_string_error("Can't retrieve AST context.");
536
537 auto tu = ast_ctx->getTranslationUnitDecl();
538 if (!tu)
539 return make_string_error("Can't retrieve translation unit declaration.");
540
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000541 tu->print(outs());
542
543 return Error::success();
544}
545
Aaron Smith010edd32018-06-08 02:45:25 +0000546Error opts::symbols::verify(lldb_private::Module &Module) {
Pavel Labathe6954cb2018-06-12 12:57:36 +0000547 SymbolVendor &plugin = *Module.GetSymbolVendor();
Aaron Smith010edd32018-06-08 02:45:25 +0000548
Pavel Labathe6954cb2018-06-12 12:57:36 +0000549 SymbolFile *symfile = plugin.GetSymbolFile();
Aaron Smith010edd32018-06-08 02:45:25 +0000550 if (!symfile)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000551 return make_string_error("Module has no symbol file.");
Aaron Smith010edd32018-06-08 02:45:25 +0000552
553 uint32_t comp_units_count = symfile->GetNumCompileUnits();
554
555 outs() << "Found " << comp_units_count << " compile units.\n";
556
557 for (uint32_t i = 0; i < comp_units_count; i++) {
558 lldb::CompUnitSP comp_unit = symfile->ParseCompileUnitAtIndex(i);
559 if (!comp_unit)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000560 return make_string_error("Connot parse compile unit {0}.", i);
Aaron Smith010edd32018-06-08 02:45:25 +0000561
Pavel Labath9ea80d22018-06-28 10:03:42 +0000562 outs() << "Processing '" << comp_unit->GetFilename().AsCString()
563 << "' compile unit.\n";
Aaron Smith010edd32018-06-08 02:45:25 +0000564
565 LineTable *lt = comp_unit->GetLineTable();
566 if (!lt)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000567 return make_string_error("Can't get a line table of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000568
569 uint32_t count = lt->GetSize();
570
571 outs() << "The line table contains " << count << " entries.\n";
572
573 if (count == 0)
574 continue;
575
576 LineEntry le;
577 if (!lt->GetLineEntryAtIndex(0, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000578 return make_string_error("Can't get a line entry of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000579
580 for (uint32_t i = 1; i < count; i++) {
581 lldb::addr_t curr_end =
Pavel Labath9ea80d22018-06-28 10:03:42 +0000582 le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
Aaron Smith010edd32018-06-08 02:45:25 +0000583
584 if (!lt->GetLineEntryAtIndex(i, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000585 return make_string_error("Can't get a line entry of a compile unit");
Aaron Smith010edd32018-06-08 02:45:25 +0000586
587 if (curr_end > le.range.GetBaseAddress().GetFileAddress())
Pavel Labathe6954cb2018-06-12 12:57:36 +0000588 return make_string_error(
589 "Line table of a compile unit is inconsistent.");
Aaron Smith010edd32018-06-08 02:45:25 +0000590 }
591 }
592
593 outs() << "The symbol information is verified.\n";
594
595 return Error::success();
596}
597
Pavel Labath38d9ff72018-06-12 13:26:43 +0000598Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000599 if (Verify && DumpAST)
600 return make_string_error(
601 "Cannot both verify symbol information and dump AST.");
602
Pavel Labathe6954cb2018-06-12 12:57:36 +0000603 if (Verify) {
604 if (Find != FindType::None)
605 return make_string_error(
606 "Cannot both search and verify symbol information.");
Pavel Labath9ea80d22018-06-28 10:03:42 +0000607 if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
608 Line != 0)
609 return make_string_error(
610 "-regex, -context, -name, -file and -line options are not "
611 "applicable for symbol verification.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000612 return verify;
Pavel Labath90b0a532018-05-03 10:57:16 +0000613 }
614
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000615 if (DumpAST) {
616 if (Find != FindType::None)
Aaron Smith037ed1b2018-12-06 21:36:39 +0000617 return make_string_error("Cannot both search and dump AST.");
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000618 if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
619 Line != 0)
620 return make_string_error(
621 "-regex, -context, -name, -file and -line options are not "
622 "applicable for dumping AST.");
623 return dumpAST;
624 }
625
Pavel Labathe6954cb2018-06-12 12:57:36 +0000626 if (Regex && !Context.empty())
627 return make_string_error(
628 "Cannot search using both regular expressions and context.");
629
630 if (Regex && !RegularExpression(Name).IsValid())
631 return make_string_error("`{0}` is not a valid regular expression.", Name);
632
633 if (Regex + !Context.empty() + !File.empty() >= 2)
634 return make_string_error(
635 "Only one of -regex, -context and -file may be used simultaneously.");
636 if (Regex && Name.empty())
637 return make_string_error("-regex used without a -name");
638
639 switch (Find) {
640 case FindType::None:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000641 if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000642 return make_string_error(
643 "Specify search type (-find) to use search options.");
644 return dumpModule;
645
646 case FindType::Function:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000647 if (!File.empty() + (Line != 0) == 1)
648 return make_string_error("Both file name and line number must be "
649 "specified when searching a function "
650 "by file position.");
651 if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2)
652 return make_string_error("Only one of regular expression, function-flags "
653 "and file position may be used simultaneously "
654 "when searching a function.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000655 return findFunctions;
656
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000657 case FindType::Block:
658 if (File.empty() || Line == 0)
659 return make_string_error("Both file name and line number must be "
660 "specified when searching a block.");
661 if (Regex || getFunctionNameFlags() != 0)
662 return make_string_error("Cannot use regular expression or "
663 "function-flags for searching a block.");
664 return findBlocks;
665
Pavel Labathe6954cb2018-06-12 12:57:36 +0000666 case FindType::Namespace:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000667 if (Regex || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000668 return make_string_error("Cannot search for namespaces using regular "
Pavel Labath9ea80d22018-06-28 10:03:42 +0000669 "expressions, file names or line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000670 return findNamespaces;
671
672 case FindType::Type:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000673 if (Regex || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000674 return make_string_error("Cannot search for types using regular "
Pavel Labath9ea80d22018-06-28 10:03:42 +0000675 "expressions, file names or line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000676 return findTypes;
677
678 case FindType::Variable:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000679 if (Line != 0)
680 return make_string_error("Cannot search for variables "
681 "using line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000682 return findVariables;
683 }
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000684
685 llvm_unreachable("Unsupported symbol action.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000686}
687
688int opts::symbols::dumpSymbols(Debugger &Dbg) {
689 auto ActionOr = getAction();
690 if (!ActionOr) {
691 logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), "");
692 return 1;
693 }
694 auto Action = *ActionOr;
Pavel Labath90b0a532018-05-03 10:57:16 +0000695
Pavel Labath1cf23e12019-01-11 11:17:51 +0000696 outs() << "Module: " << InputFile << "\n";
697 ModuleSpec Spec{FileSpec(InputFile)};
698 StringRef Symbols = SymbolPath.empty() ? InputFile : SymbolPath;
699 Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native);
Zachary Turnera6d54642017-12-02 00:15:29 +0000700
Pavel Labath1cf23e12019-01-11 11:17:51 +0000701 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
702 SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
703 if (!Vendor) {
704 WithColor::error() << "Module has no symbol vendor.\n";
705 return 1;
Zachary Turnera6d54642017-12-02 00:15:29 +0000706 }
Pavel Labath1cf23e12019-01-11 11:17:51 +0000707
708 if (Error E = Action(*ModulePtr)) {
709 WithColor::error() << toString(std::move(E)) << "\n";
710 return 1;
711 }
712
713 return 0;
Zachary Turnera6d54642017-12-02 00:15:29 +0000714}
715
Pavel Labath280d2e82018-12-12 12:35:25 +0000716static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) {
717 size_t Count = List.GetNumSections(0);
718 if (Count == 0) {
719 Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : "");
720 return;
721 }
722 Printer.formatLine("Showing {0} {1}sections", Count,
723 is_subsection ? "sub" : "");
724 for (size_t I = 0; I < Count; ++I) {
725 auto S = List.GetSectionAtIndex(I);
726 assert(S);
727 AutoIndent Indent(Printer, 2);
728 Printer.formatLine("Index: {0}", I);
Pavel Labath0d38e4f2018-12-18 15:56:45 +0000729 Printer.formatLine("ID: {0:x}", S->GetID());
Pavel Labath280d2e82018-12-12 12:35:25 +0000730 Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
731 Printer.formatLine("Type: {0}", S->GetTypeAsCString());
Pavel Labath62a82542018-12-15 13:45:38 +0000732 Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions()));
Pavel Labathef8683a2018-12-12 15:46:18 +0000733 Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific());
Pavel Labath62a82542018-12-15 13:45:38 +0000734 Printer.formatLine("VM address: {0:x}", S->GetFileAddress());
Pavel Labath280d2e82018-12-12 12:35:25 +0000735 Printer.formatLine("VM size: {0}", S->GetByteSize());
736 Printer.formatLine("File size: {0}", S->GetFileSize());
737
738 if (opts::object::SectionContents) {
739 DataExtractor Data;
740 S->GetSectionData(Data);
741 ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()};
742 Printer.formatBinary("Data: ", Bytes, 0);
743 }
744
745 if (S->GetType() == eSectionTypeContainer)
746 dumpSectionList(Printer, S->GetChildren(), true);
747 Printer.NewLine();
748 }
749}
750
Pavel Labath62a7f802018-06-29 12:15:54 +0000751static int dumpObjectFiles(Debugger &Dbg) {
Zachary Turner888a4282017-12-01 00:52:51 +0000752 LinePrinter Printer(4, llvm::outs());
753
Pavel Labath90b0a532018-05-03 10:57:16 +0000754 int HadErrors = 0;
Pavel Labath62a7f802018-06-29 12:15:54 +0000755 for (const auto &File : opts::object::InputFilenames) {
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000756 ModuleSpec Spec{FileSpec(File)};
Zachary Turner888a4282017-12-01 00:52:51 +0000757
Zachary Turnera6d54642017-12-02 00:15:29 +0000758 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
Pavel Labath1f6b2472018-12-10 17:16:38 +0000759
760 ObjectFile *ObjectPtr = ModulePtr->GetObjectFile();
761 if (!ObjectPtr) {
762 WithColor::error() << File << " not recognised as an object file\n";
763 HadErrors = 1;
764 continue;
765 }
766
Pavel Labath96979ce2018-03-06 15:56:20 +0000767 // Fetch symbol vendor before we get the section list to give the symbol
768 // vendor a chance to populate it.
769 ModulePtr->GetSymbolVendor();
Zachary Turner888a4282017-12-01 00:52:51 +0000770 SectionList *Sections = ModulePtr->GetSectionList();
771 if (!Sections) {
772 llvm::errs() << "Could not load sections for module " << File << "\n";
Pavel Labath90b0a532018-05-03 10:57:16 +0000773 HadErrors = 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000774 continue;
775 }
776
Pavel Labath1f6b2472018-12-10 17:16:38 +0000777 Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName());
Pavel Labath62a7f802018-06-29 12:15:54 +0000778 Printer.formatLine("Architecture: {0}",
779 ModulePtr->GetArchitecture().GetTriple().getTriple());
780 Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
Pavel Labath1f6b2472018-12-10 17:16:38 +0000781 Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable());
782 Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped());
783 Printer.formatLine("Type: {0}", ObjectPtr->GetType());
784 Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata());
Pavel Labath976af432019-01-10 09:32:31 +0000785 Printer.formatLine("Base VM address: {0:x}",
786 ObjectPtr->GetBaseAddress().GetFileAddress());
Pavel Labath62a7f802018-06-29 12:15:54 +0000787
Pavel Labath280d2e82018-12-12 12:35:25 +0000788 dumpSectionList(Printer, *Sections, /*is_subsection*/ false);
Aaron Smith037ed1b2018-12-06 21:36:39 +0000789
790 if (opts::object::SectionDependentModules) {
791 // A non-empty section list ensures a valid object file.
792 auto Obj = ModulePtr->GetObjectFile();
793 FileSpecList Files;
794 auto Count = Obj->GetDependentModules(Files);
795 Printer.formatLine("Showing {0} dependent module(s)", Count);
796 for (size_t I = 0; I < Files.GetSize(); ++I) {
797 AutoIndent Indent(Printer, 2);
798 Printer.formatLine("Name: {0}",
799 Files.GetFileSpecAtIndex(I).GetCString());
800 }
801 Printer.NewLine();
802 }
Zachary Turner888a4282017-12-01 00:52:51 +0000803 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000804 return HadErrors;
Zachary Turner888a4282017-12-01 00:52:51 +0000805}
806
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000807bool opts::irmemorymap::evalMalloc(StringRef Line,
808 IRMemoryMapTestState &State) {
809 // ::= <label> = malloc <size> <alignment>
810 StringRef Label;
811 std::tie(Label, Line) = Line.split('=');
812 if (Line.empty())
813 return false;
814 Label = Label.trim();
815 Line = Line.trim();
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000816 size_t Size;
817 uint8_t Alignment;
818 int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment);
819 if (Matches != 2)
820 return false;
821
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000822 outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label,
823 Size, Alignment);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000824 if (!isPowerOf2_32(Alignment)) {
825 outs() << "Malloc error: alignment is not a power of 2\n";
826 exit(1);
827 }
828
Vedant Kumarf616b9d2018-05-31 22:09:00 +0000829 IRMemoryMap::AllocationPolicy AP =
830 UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly
831 : IRMemoryMap::eAllocationPolicyProcessOnly;
832
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000833 // Issue the malloc in the target process with "-rw" permissions.
834 const uint32_t Permissions = 0x3;
835 const bool ZeroMemory = false;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000836 Status ST;
837 addr_t Addr =
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000838 State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000839 if (ST.Fail()) {
840 outs() << formatv("Malloc error: {0}\n", ST);
841 return true;
842 }
843
844 // Print the result of the allocation before checking its validity.
845 outs() << formatv("Malloc: address = {0:x}\n", Addr);
846
847 // Check that the allocation is aligned.
848 if (!Addr || Addr % Alignment != 0) {
849 outs() << "Malloc error: zero or unaligned allocation detected\n";
850 exit(1);
851 }
852
Pavel Labatha352ed22018-12-27 09:32:04 +0000853 // In case of Size == 0, we still expect the returned address to be unique and
854 // non-overlapping.
855 addr_t EndOfRegion = Addr + std::max<size_t>(Size, 1);
856 if (State.Allocations.overlaps(Addr, EndOfRegion)) {
857 auto I = State.Allocations.find(Addr);
858 outs() << "Malloc error: overlapping allocation detected"
859 << formatv(", previous allocation at [{0:x}, {1:x})\n", I.start(),
860 I.stop());
861 exit(1);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000862 }
863
Aaron Smith037ed1b2018-12-06 21:36:39 +0000864 // Insert the new allocation into the interval map. Use unique allocation
865 // IDs to inhibit interval coalescing.
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000866 static unsigned AllocationID = 0;
Pavel Labatha352ed22018-12-27 09:32:04 +0000867 State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000868
869 // Store the label -> address mapping.
870 State.Label2AddrMap[Label] = Addr;
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000871
872 return true;
873}
874
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000875bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) {
876 // ::= free <label>
877 if (!Line.consume_front("free"))
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000878 return false;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000879 StringRef Label = Line.trim();
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000880
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000881 outs() << formatv("Command: free({0})\n", Label);
882 auto LabelIt = State.Label2AddrMap.find(Label);
883 if (LabelIt == State.Label2AddrMap.end()) {
884 outs() << "Free error: Invalid allocation label\n";
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000885 exit(1);
886 }
887
888 Status ST;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000889 addr_t Addr = LabelIt->getValue();
890 State.Map.Free(Addr, ST);
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000891 if (ST.Fail()) {
892 outs() << formatv("Free error: {0}\n", ST);
893 exit(1);
894 }
895
896 // Erase the allocation from the live interval map.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000897 auto Interval = State.Allocations.find(Addr);
898 if (Interval != State.Allocations.end()) {
899 outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(),
900 Interval.stop());
901 Interval.erase();
902 }
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000903
904 return true;
905}
906
907int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
908 // Set up a Target.
909 TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target);
910
911 // Set up a Process. In order to allocate memory within a target, this
912 // process must be alive and must support JIT'ing.
913 CommandReturnObject Result;
914 Dbg.SetAsyncExecution(false);
915 CommandInterpreter &CI = Dbg.GetCommandInterpreter();
916 auto IssueCmd = [&](const char *Cmd) -> bool {
917 return CI.HandleCommand(Cmd, eLazyBoolNo, Result);
918 };
919 if (!IssueCmd("b main") || !IssueCmd("run")) {
920 outs() << formatv("Failed: {0}\n", Result.GetErrorData());
921 exit(1);
922 }
923
924 ProcessSP Process = Target->GetProcessSP();
925 if (!Process || !Process->IsAlive() || !Process->CanJIT()) {
926 outs() << "Cannot use process to test IRMemoryMap\n";
927 exit(1);
928 }
929
930 // Set up an IRMemoryMap and associated testing state.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000931 IRMemoryMapTestState State(Target);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000932
933 // Parse and apply commands from the command file.
934 std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile);
935 StringRef Rest = MB->getBuffer();
936 while (!Rest.empty()) {
937 StringRef Line;
938 std::tie(Line, Rest) = Rest.split('\n');
939 Line = Line.ltrim();
940
941 if (Line.empty() || Line[0] == '#')
942 continue;
943
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000944 if (evalMalloc(Line, State))
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000945 continue;
946
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000947 if (evalFree(Line, State))
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000948 continue;
949
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000950 errs() << "Could not parse line: " << Line << "\n";
951 exit(1);
952 }
953 return 0;
954}
955
Zachary Turner888a4282017-12-01 00:52:51 +0000956int main(int argc, const char *argv[]) {
957 StringRef ToolName = argv[0];
958 sys::PrintStackTraceOnErrorSignal(ToolName);
959 PrettyStackTraceProgram X(argc, argv);
960 llvm_shutdown_obj Y;
961
962 cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
963
Pavel Labath90b0a532018-05-03 10:57:16 +0000964 SystemLifetimeManager DebuggerLifetime;
Jonas Devlieghere15eacd72018-12-03 17:28:29 +0000965 if (auto e = DebuggerLifetime.Initialize(
Jonas Devlieghere936c6242019-02-21 22:26:16 +0000966 llvm::make_unique<SystemInitializerTest>(), nullptr)) {
Jonas Devlieghere15eacd72018-12-03 17:28:29 +0000967 WithColor::error() << "initialization failed: " << toString(std::move(e))
968 << '\n';
969 return 1;
970 }
971
Pavel Labath90b0a532018-05-03 10:57:16 +0000972 CleanUp TerminateDebugger([&] { DebuggerLifetime.Terminate(); });
Zachary Turner888a4282017-12-01 00:52:51 +0000973
974 auto Dbg = lldb_private::Debugger::CreateInstance();
975
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000976 if (!opts::Log.empty())
977 Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, errs());
978
Pavel Labath7c945822018-02-26 18:50:16 +0000979 if (opts::BreakpointSubcommand)
Pavel Labath90b0a532018-05-03 10:57:16 +0000980 return opts::breakpoint::evaluateBreakpoints(*Dbg);
Pavel Labath62a7f802018-06-29 12:15:54 +0000981 if (opts::ObjectFileSubcommand)
982 return dumpObjectFiles(*Dbg);
Pavel Labath90b0a532018-05-03 10:57:16 +0000983 if (opts::SymbolsSubcommand)
984 return opts::symbols::dumpSymbols(*Dbg);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000985 if (opts::IRMemoryMapSubcommand)
986 return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
Zachary Turner888a4282017-12-01 00:52:51 +0000987
Pavel Labath90b0a532018-05-03 10:57:16 +0000988 WithColor::error() << "No command specified.\n";
989 return 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000990}