blob: e5e23fb7695d12e94b11da127fe0c74888408280 [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');
Adrian McCarthy4447d152019-06-07 21:13:30 +0000315 Line = Line.ltrim().rtrim();
Pavel Labath7c945822018-02-26 18:50:16 +0000316 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;
Greg Clayton8a777922019-05-06 20:01:21 +0000367 const bool include_inlined_functions = false;
368 auto addr =
369 le.GetSameLineContiguousAddressRange(include_inlined_functions)
370 .GetBaseAddress();
Pavel Labath9ea80d22018-06-28 10:03:42 +0000371 if (!addr.IsValid())
372 continue;
373
374 SymbolContext sc;
375 uint32_t resolved =
376 addr.CalculateSymbolContext(&sc, eSymbolContextFunction);
377 if (resolved & eSymbolContextFunction)
378 List.Append(sc);
379 }
380 } else if (Regex) {
Pavel Labath90b0a532018-05-03 10:57:16 +0000381 RegularExpression RE(Name);
382 assert(RE.IsValid());
383 Vendor.FindFunctions(RE, true, false, List);
384 } else {
385 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
386 if (!ContextOr)
387 return ContextOr.takeError();
388 CompilerDeclContext *ContextPtr =
389 ContextOr->IsValid() ? &*ContextOr : nullptr;
390
391 Vendor.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
Pavel Labath9ea80d22018-06-28 10:03:42 +0000392 true, false, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000393 }
394 outs() << formatv("Found {0} functions:\n", List.GetSize());
395 StreamString Stream;
396 List.Dump(&Stream, nullptr);
397 outs() << Stream.GetData() << "\n";
398 return Error::success();
399}
400
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000401Error opts::symbols::findBlocks(lldb_private::Module &Module) {
402 assert(!Regex);
403 assert(!File.empty());
404 assert(Line != 0);
405
406 SymbolContextList List;
407
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000408 FileSpec src_file(File);
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000409 size_t cu_count = Module.GetNumCompileUnits();
410 for (size_t i = 0; i < cu_count; i++) {
411 lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
412 if (!cu_sp)
413 continue;
414
415 LineEntry le;
416 cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
417 if (!le.IsValid())
418 continue;
Greg Clayton8a777922019-05-06 20:01:21 +0000419 const bool include_inlined_functions = false;
420 auto addr = le.GetSameLineContiguousAddressRange(include_inlined_functions)
421 .GetBaseAddress();
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000422 if (!addr.IsValid())
423 continue;
424
425 SymbolContext sc;
426 uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock);
427 if (resolved & eSymbolContextBlock)
428 List.Append(sc);
429 }
430
431 outs() << formatv("Found {0} blocks:\n", List.GetSize());
432 StreamString Stream;
433 List.Dump(&Stream, nullptr);
434 outs() << Stream.GetData() << "\n";
435 return Error::success();
436}
437
Pavel Labath90b0a532018-05-03 10:57:16 +0000438Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
439 SymbolVendor &Vendor = *Module.GetSymbolVendor();
440 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
441 if (!ContextOr)
442 return ContextOr.takeError();
443 CompilerDeclContext *ContextPtr =
444 ContextOr->IsValid() ? &*ContextOr : nullptr;
445
Pavel Labath90b0a532018-05-03 10:57:16 +0000446 CompilerDeclContext Result =
Zachary Turnerc0a246a2019-01-14 22:41:00 +0000447 Vendor.FindNamespace(ConstString(Name), ContextPtr);
Pavel Labath90b0a532018-05-03 10:57:16 +0000448 if (Result)
449 outs() << "Found namespace: "
450 << Result.GetScopeQualifiedName().GetStringRef() << "\n";
451 else
452 outs() << "Namespace not found.\n";
453 return Error::success();
454}
455
456Error opts::symbols::findTypes(lldb_private::Module &Module) {
457 SymbolVendor &Vendor = *Module.GetSymbolVendor();
458 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
459 if (!ContextOr)
460 return ContextOr.takeError();
461 CompilerDeclContext *ContextPtr =
462 ContextOr->IsValid() ? &*ContextOr : nullptr;
463
Pavel Labath90b0a532018-05-03 10:57:16 +0000464 DenseSet<SymbolFile *> SearchedFiles;
465 TypeMap Map;
Zachary Turner576495e2019-01-14 22:41:21 +0000466 Vendor.FindTypes(ConstString(Name), ContextPtr, true, UINT32_MAX,
Pavel Labath9ea80d22018-06-28 10:03:42 +0000467 SearchedFiles, Map);
Pavel Labath90b0a532018-05-03 10:57:16 +0000468
469 outs() << formatv("Found {0} types:\n", Map.GetSize());
470 StreamString Stream;
471 Map.Dump(&Stream, false);
472 outs() << Stream.GetData() << "\n";
473 return Error::success();
474}
475
476Error opts::symbols::findVariables(lldb_private::Module &Module) {
477 SymbolVendor &Vendor = *Module.GetSymbolVendor();
478 VariableList List;
479 if (Regex) {
480 RegularExpression RE(Name);
481 assert(RE.IsValid());
Pavel Labath34cda142018-05-31 09:46:26 +0000482 Vendor.FindGlobalVariables(RE, UINT32_MAX, List);
Pavel Labathe6954cb2018-06-12 12:57:36 +0000483 } else if (!File.empty()) {
484 CompUnitSP CU;
485 for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) {
486 CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind);
487 if (!Candidate || Candidate->GetFilename().GetStringRef() != File)
488 continue;
489 if (CU)
490 return make_string_error("Multiple compile units for file `{0}` found.",
491 File);
492 CU = std::move(Candidate);
493 }
494
495 if (!CU)
496 return make_string_error("Compile unit `{0}` not found.", File);
497
498 List.AddVariables(CU->GetVariableList(true).get());
Pavel Labath90b0a532018-05-03 10:57:16 +0000499 } else {
500 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
501 if (!ContextOr)
502 return ContextOr.takeError();
503 CompilerDeclContext *ContextPtr =
504 ContextOr->IsValid() ? &*ContextOr : nullptr;
505
Pavel Labath34cda142018-05-31 09:46:26 +0000506 Vendor.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000507 }
508 outs() << formatv("Found {0} variables:\n", List.GetSize());
509 StreamString Stream;
510 List.Dump(&Stream, false);
511 outs() << Stream.GetData() << "\n";
512 return Error::success();
513}
514
515Error opts::symbols::dumpModule(lldb_private::Module &Module) {
516 StreamString Stream;
517 Module.ParseAllDebugSymbols();
518 Module.Dump(&Stream);
519 outs() << Stream.GetData() << "\n";
520 return Error::success();
521}
522
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000523Error opts::symbols::dumpAST(lldb_private::Module &Module) {
524 SymbolVendor &plugin = *Module.GetSymbolVendor();
Zachary Turnerc68925a2019-01-09 21:20:44 +0000525 Module.ParseAllDebugSymbols();
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000526
527 auto symfile = plugin.GetSymbolFile();
528 if (!symfile)
529 return make_string_error("Module has no symbol file.");
530
531 auto clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
532 symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus));
533 if (!clang_ast_ctx)
534 return make_string_error("Can't retrieve Clang AST context.");
535
536 auto ast_ctx = clang_ast_ctx->getASTContext();
537 if (!ast_ctx)
538 return make_string_error("Can't retrieve AST context.");
539
540 auto tu = ast_ctx->getTranslationUnitDecl();
541 if (!tu)
542 return make_string_error("Can't retrieve translation unit declaration.");
543
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000544 tu->print(outs());
545
546 return Error::success();
547}
548
Aaron Smith010edd32018-06-08 02:45:25 +0000549Error opts::symbols::verify(lldb_private::Module &Module) {
Pavel Labathe6954cb2018-06-12 12:57:36 +0000550 SymbolVendor &plugin = *Module.GetSymbolVendor();
Aaron Smith010edd32018-06-08 02:45:25 +0000551
Pavel Labathe6954cb2018-06-12 12:57:36 +0000552 SymbolFile *symfile = plugin.GetSymbolFile();
Aaron Smith010edd32018-06-08 02:45:25 +0000553 if (!symfile)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000554 return make_string_error("Module has no symbol file.");
Aaron Smith010edd32018-06-08 02:45:25 +0000555
556 uint32_t comp_units_count = symfile->GetNumCompileUnits();
557
558 outs() << "Found " << comp_units_count << " compile units.\n";
559
560 for (uint32_t i = 0; i < comp_units_count; i++) {
561 lldb::CompUnitSP comp_unit = symfile->ParseCompileUnitAtIndex(i);
562 if (!comp_unit)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000563 return make_string_error("Connot parse compile unit {0}.", i);
Aaron Smith010edd32018-06-08 02:45:25 +0000564
Pavel Labath9ea80d22018-06-28 10:03:42 +0000565 outs() << "Processing '" << comp_unit->GetFilename().AsCString()
566 << "' compile unit.\n";
Aaron Smith010edd32018-06-08 02:45:25 +0000567
568 LineTable *lt = comp_unit->GetLineTable();
569 if (!lt)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000570 return make_string_error("Can't get a line table of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000571
572 uint32_t count = lt->GetSize();
573
574 outs() << "The line table contains " << count << " entries.\n";
575
576 if (count == 0)
577 continue;
578
579 LineEntry le;
580 if (!lt->GetLineEntryAtIndex(0, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000581 return make_string_error("Can't get a line entry of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000582
583 for (uint32_t i = 1; i < count; i++) {
584 lldb::addr_t curr_end =
Pavel Labath9ea80d22018-06-28 10:03:42 +0000585 le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
Aaron Smith010edd32018-06-08 02:45:25 +0000586
587 if (!lt->GetLineEntryAtIndex(i, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000588 return make_string_error("Can't get a line entry of a compile unit");
Aaron Smith010edd32018-06-08 02:45:25 +0000589
590 if (curr_end > le.range.GetBaseAddress().GetFileAddress())
Pavel Labathe6954cb2018-06-12 12:57:36 +0000591 return make_string_error(
592 "Line table of a compile unit is inconsistent.");
Aaron Smith010edd32018-06-08 02:45:25 +0000593 }
594 }
595
596 outs() << "The symbol information is verified.\n";
597
598 return Error::success();
599}
600
Pavel Labath38d9ff72018-06-12 13:26:43 +0000601Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000602 if (Verify && DumpAST)
603 return make_string_error(
604 "Cannot both verify symbol information and dump AST.");
605
Pavel Labathe6954cb2018-06-12 12:57:36 +0000606 if (Verify) {
607 if (Find != FindType::None)
608 return make_string_error(
609 "Cannot both search and verify symbol information.");
Pavel Labath9ea80d22018-06-28 10:03:42 +0000610 if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
611 Line != 0)
612 return make_string_error(
613 "-regex, -context, -name, -file and -line options are not "
614 "applicable for symbol verification.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000615 return verify;
Pavel Labath90b0a532018-05-03 10:57:16 +0000616 }
617
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000618 if (DumpAST) {
619 if (Find != FindType::None)
Aaron Smith037ed1b2018-12-06 21:36:39 +0000620 return make_string_error("Cannot both search and dump AST.");
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000621 if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
622 Line != 0)
623 return make_string_error(
624 "-regex, -context, -name, -file and -line options are not "
625 "applicable for dumping AST.");
626 return dumpAST;
627 }
628
Pavel Labathe6954cb2018-06-12 12:57:36 +0000629 if (Regex && !Context.empty())
630 return make_string_error(
631 "Cannot search using both regular expressions and context.");
632
633 if (Regex && !RegularExpression(Name).IsValid())
634 return make_string_error("`{0}` is not a valid regular expression.", Name);
635
636 if (Regex + !Context.empty() + !File.empty() >= 2)
637 return make_string_error(
638 "Only one of -regex, -context and -file may be used simultaneously.");
639 if (Regex && Name.empty())
640 return make_string_error("-regex used without a -name");
641
642 switch (Find) {
643 case FindType::None:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000644 if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000645 return make_string_error(
646 "Specify search type (-find) to use search options.");
647 return dumpModule;
648
649 case FindType::Function:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000650 if (!File.empty() + (Line != 0) == 1)
651 return make_string_error("Both file name and line number must be "
652 "specified when searching a function "
653 "by file position.");
654 if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2)
655 return make_string_error("Only one of regular expression, function-flags "
656 "and file position may be used simultaneously "
657 "when searching a function.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000658 return findFunctions;
659
Aleksandr Urakov398f81b2018-08-29 07:26:11 +0000660 case FindType::Block:
661 if (File.empty() || Line == 0)
662 return make_string_error("Both file name and line number must be "
663 "specified when searching a block.");
664 if (Regex || getFunctionNameFlags() != 0)
665 return make_string_error("Cannot use regular expression or "
666 "function-flags for searching a block.");
667 return findBlocks;
668
Pavel Labathe6954cb2018-06-12 12:57:36 +0000669 case FindType::Namespace:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000670 if (Regex || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000671 return make_string_error("Cannot search for namespaces using regular "
Pavel Labath9ea80d22018-06-28 10:03:42 +0000672 "expressions, file names or line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000673 return findNamespaces;
674
675 case FindType::Type:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000676 if (Regex || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000677 return make_string_error("Cannot search for types using regular "
Pavel Labath9ea80d22018-06-28 10:03:42 +0000678 "expressions, file names or line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000679 return findTypes;
680
681 case FindType::Variable:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000682 if (Line != 0)
683 return make_string_error("Cannot search for variables "
684 "using line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000685 return findVariables;
686 }
Aleksandr Urakov709426b2018-09-10 08:08:43 +0000687
688 llvm_unreachable("Unsupported symbol action.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000689}
690
691int opts::symbols::dumpSymbols(Debugger &Dbg) {
692 auto ActionOr = getAction();
693 if (!ActionOr) {
694 logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), "");
695 return 1;
696 }
697 auto Action = *ActionOr;
Pavel Labath90b0a532018-05-03 10:57:16 +0000698
Pavel Labath1cf23e12019-01-11 11:17:51 +0000699 outs() << "Module: " << InputFile << "\n";
700 ModuleSpec Spec{FileSpec(InputFile)};
701 StringRef Symbols = SymbolPath.empty() ? InputFile : SymbolPath;
702 Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native);
Zachary Turnera6d54642017-12-02 00:15:29 +0000703
Pavel Labath1cf23e12019-01-11 11:17:51 +0000704 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
705 SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
706 if (!Vendor) {
707 WithColor::error() << "Module has no symbol vendor.\n";
708 return 1;
Zachary Turnera6d54642017-12-02 00:15:29 +0000709 }
Pavel Labath1cf23e12019-01-11 11:17:51 +0000710
711 if (Error E = Action(*ModulePtr)) {
712 WithColor::error() << toString(std::move(E)) << "\n";
713 return 1;
714 }
715
716 return 0;
Zachary Turnera6d54642017-12-02 00:15:29 +0000717}
718
Pavel Labath280d2e82018-12-12 12:35:25 +0000719static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) {
720 size_t Count = List.GetNumSections(0);
721 if (Count == 0) {
722 Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : "");
723 return;
724 }
725 Printer.formatLine("Showing {0} {1}sections", Count,
726 is_subsection ? "sub" : "");
727 for (size_t I = 0; I < Count; ++I) {
728 auto S = List.GetSectionAtIndex(I);
729 assert(S);
730 AutoIndent Indent(Printer, 2);
731 Printer.formatLine("Index: {0}", I);
Pavel Labath0d38e4f2018-12-18 15:56:45 +0000732 Printer.formatLine("ID: {0:x}", S->GetID());
Pavel Labath280d2e82018-12-12 12:35:25 +0000733 Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
734 Printer.formatLine("Type: {0}", S->GetTypeAsCString());
Pavel Labath62a82542018-12-15 13:45:38 +0000735 Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions()));
Pavel Labathef8683a2018-12-12 15:46:18 +0000736 Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific());
Pavel Labath62a82542018-12-15 13:45:38 +0000737 Printer.formatLine("VM address: {0:x}", S->GetFileAddress());
Pavel Labath280d2e82018-12-12 12:35:25 +0000738 Printer.formatLine("VM size: {0}", S->GetByteSize());
739 Printer.formatLine("File size: {0}", S->GetFileSize());
740
741 if (opts::object::SectionContents) {
742 DataExtractor Data;
743 S->GetSectionData(Data);
744 ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()};
745 Printer.formatBinary("Data: ", Bytes, 0);
746 }
747
748 if (S->GetType() == eSectionTypeContainer)
749 dumpSectionList(Printer, S->GetChildren(), true);
750 Printer.NewLine();
751 }
752}
753
Pavel Labath62a7f802018-06-29 12:15:54 +0000754static int dumpObjectFiles(Debugger &Dbg) {
Zachary Turner888a4282017-12-01 00:52:51 +0000755 LinePrinter Printer(4, llvm::outs());
756
Pavel Labath90b0a532018-05-03 10:57:16 +0000757 int HadErrors = 0;
Pavel Labath62a7f802018-06-29 12:15:54 +0000758 for (const auto &File : opts::object::InputFilenames) {
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000759 ModuleSpec Spec{FileSpec(File)};
Zachary Turner888a4282017-12-01 00:52:51 +0000760
Zachary Turnera6d54642017-12-02 00:15:29 +0000761 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
Pavel Labath1f6b2472018-12-10 17:16:38 +0000762
763 ObjectFile *ObjectPtr = ModulePtr->GetObjectFile();
764 if (!ObjectPtr) {
765 WithColor::error() << File << " not recognised as an object file\n";
766 HadErrors = 1;
767 continue;
768 }
769
Pavel Labath96979ce2018-03-06 15:56:20 +0000770 // Fetch symbol vendor before we get the section list to give the symbol
771 // vendor a chance to populate it.
772 ModulePtr->GetSymbolVendor();
Zachary Turner888a4282017-12-01 00:52:51 +0000773 SectionList *Sections = ModulePtr->GetSectionList();
774 if (!Sections) {
775 llvm::errs() << "Could not load sections for module " << File << "\n";
Pavel Labath90b0a532018-05-03 10:57:16 +0000776 HadErrors = 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000777 continue;
778 }
779
Pavel Labath1f6b2472018-12-10 17:16:38 +0000780 Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName());
Pavel Labath62a7f802018-06-29 12:15:54 +0000781 Printer.formatLine("Architecture: {0}",
782 ModulePtr->GetArchitecture().GetTriple().getTriple());
783 Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
Pavel Labath1f6b2472018-12-10 17:16:38 +0000784 Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable());
785 Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped());
786 Printer.formatLine("Type: {0}", ObjectPtr->GetType());
787 Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata());
Pavel Labath976af432019-01-10 09:32:31 +0000788 Printer.formatLine("Base VM address: {0:x}",
789 ObjectPtr->GetBaseAddress().GetFileAddress());
Pavel Labath62a7f802018-06-29 12:15:54 +0000790
Pavel Labath280d2e82018-12-12 12:35:25 +0000791 dumpSectionList(Printer, *Sections, /*is_subsection*/ false);
Aaron Smith037ed1b2018-12-06 21:36:39 +0000792
793 if (opts::object::SectionDependentModules) {
794 // A non-empty section list ensures a valid object file.
795 auto Obj = ModulePtr->GetObjectFile();
796 FileSpecList Files;
797 auto Count = Obj->GetDependentModules(Files);
798 Printer.formatLine("Showing {0} dependent module(s)", Count);
799 for (size_t I = 0; I < Files.GetSize(); ++I) {
800 AutoIndent Indent(Printer, 2);
801 Printer.formatLine("Name: {0}",
802 Files.GetFileSpecAtIndex(I).GetCString());
803 }
804 Printer.NewLine();
805 }
Zachary Turner888a4282017-12-01 00:52:51 +0000806 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000807 return HadErrors;
Zachary Turner888a4282017-12-01 00:52:51 +0000808}
809
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000810bool opts::irmemorymap::evalMalloc(StringRef Line,
811 IRMemoryMapTestState &State) {
812 // ::= <label> = malloc <size> <alignment>
813 StringRef Label;
814 std::tie(Label, Line) = Line.split('=');
815 if (Line.empty())
816 return false;
817 Label = Label.trim();
818 Line = Line.trim();
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000819 size_t Size;
820 uint8_t Alignment;
821 int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment);
822 if (Matches != 2)
823 return false;
824
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000825 outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label,
826 Size, Alignment);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000827 if (!isPowerOf2_32(Alignment)) {
828 outs() << "Malloc error: alignment is not a power of 2\n";
829 exit(1);
830 }
831
Vedant Kumarf616b9d2018-05-31 22:09:00 +0000832 IRMemoryMap::AllocationPolicy AP =
833 UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly
834 : IRMemoryMap::eAllocationPolicyProcessOnly;
835
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000836 // Issue the malloc in the target process with "-rw" permissions.
837 const uint32_t Permissions = 0x3;
838 const bool ZeroMemory = false;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000839 Status ST;
840 addr_t Addr =
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000841 State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000842 if (ST.Fail()) {
843 outs() << formatv("Malloc error: {0}\n", ST);
844 return true;
845 }
846
847 // Print the result of the allocation before checking its validity.
848 outs() << formatv("Malloc: address = {0:x}\n", Addr);
849
850 // Check that the allocation is aligned.
851 if (!Addr || Addr % Alignment != 0) {
852 outs() << "Malloc error: zero or unaligned allocation detected\n";
853 exit(1);
854 }
855
Pavel Labatha352ed22018-12-27 09:32:04 +0000856 // In case of Size == 0, we still expect the returned address to be unique and
857 // non-overlapping.
858 addr_t EndOfRegion = Addr + std::max<size_t>(Size, 1);
859 if (State.Allocations.overlaps(Addr, EndOfRegion)) {
860 auto I = State.Allocations.find(Addr);
861 outs() << "Malloc error: overlapping allocation detected"
862 << formatv(", previous allocation at [{0:x}, {1:x})\n", I.start(),
863 I.stop());
864 exit(1);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000865 }
866
Aaron Smith037ed1b2018-12-06 21:36:39 +0000867 // Insert the new allocation into the interval map. Use unique allocation
868 // IDs to inhibit interval coalescing.
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000869 static unsigned AllocationID = 0;
Pavel Labatha352ed22018-12-27 09:32:04 +0000870 State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000871
872 // Store the label -> address mapping.
873 State.Label2AddrMap[Label] = Addr;
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000874
875 return true;
876}
877
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000878bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) {
879 // ::= free <label>
880 if (!Line.consume_front("free"))
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000881 return false;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000882 StringRef Label = Line.trim();
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000883
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000884 outs() << formatv("Command: free({0})\n", Label);
885 auto LabelIt = State.Label2AddrMap.find(Label);
886 if (LabelIt == State.Label2AddrMap.end()) {
887 outs() << "Free error: Invalid allocation label\n";
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000888 exit(1);
889 }
890
891 Status ST;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000892 addr_t Addr = LabelIt->getValue();
893 State.Map.Free(Addr, ST);
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000894 if (ST.Fail()) {
895 outs() << formatv("Free error: {0}\n", ST);
896 exit(1);
897 }
898
899 // Erase the allocation from the live interval map.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000900 auto Interval = State.Allocations.find(Addr);
901 if (Interval != State.Allocations.end()) {
902 outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(),
903 Interval.stop());
904 Interval.erase();
905 }
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000906
907 return true;
908}
909
910int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
911 // Set up a Target.
912 TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target);
913
914 // Set up a Process. In order to allocate memory within a target, this
915 // process must be alive and must support JIT'ing.
916 CommandReturnObject Result;
917 Dbg.SetAsyncExecution(false);
918 CommandInterpreter &CI = Dbg.GetCommandInterpreter();
919 auto IssueCmd = [&](const char *Cmd) -> bool {
920 return CI.HandleCommand(Cmd, eLazyBoolNo, Result);
921 };
922 if (!IssueCmd("b main") || !IssueCmd("run")) {
923 outs() << formatv("Failed: {0}\n", Result.GetErrorData());
924 exit(1);
925 }
926
927 ProcessSP Process = Target->GetProcessSP();
928 if (!Process || !Process->IsAlive() || !Process->CanJIT()) {
929 outs() << "Cannot use process to test IRMemoryMap\n";
930 exit(1);
931 }
932
933 // Set up an IRMemoryMap and associated testing state.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000934 IRMemoryMapTestState State(Target);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000935
936 // Parse and apply commands from the command file.
937 std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile);
938 StringRef Rest = MB->getBuffer();
939 while (!Rest.empty()) {
940 StringRef Line;
941 std::tie(Line, Rest) = Rest.split('\n');
Adrian McCarthy4447d152019-06-07 21:13:30 +0000942 Line = Line.ltrim().rtrim();
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000943
944 if (Line.empty() || Line[0] == '#')
945 continue;
946
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000947 if (evalMalloc(Line, State))
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000948 continue;
949
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000950 if (evalFree(Line, State))
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000951 continue;
952
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000953 errs() << "Could not parse line: " << Line << "\n";
954 exit(1);
955 }
956 return 0;
957}
958
Zachary Turner888a4282017-12-01 00:52:51 +0000959int main(int argc, const char *argv[]) {
960 StringRef ToolName = argv[0];
961 sys::PrintStackTraceOnErrorSignal(ToolName);
962 PrettyStackTraceProgram X(argc, argv);
963 llvm_shutdown_obj Y;
964
965 cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
966
Pavel Labath90b0a532018-05-03 10:57:16 +0000967 SystemLifetimeManager DebuggerLifetime;
Jonas Devlieghere15eacd72018-12-03 17:28:29 +0000968 if (auto e = DebuggerLifetime.Initialize(
Jonas Devlieghere936c6242019-02-21 22:26:16 +0000969 llvm::make_unique<SystemInitializerTest>(), nullptr)) {
Jonas Devlieghere15eacd72018-12-03 17:28:29 +0000970 WithColor::error() << "initialization failed: " << toString(std::move(e))
971 << '\n';
972 return 1;
973 }
974
Pavel Labath90b0a532018-05-03 10:57:16 +0000975 CleanUp TerminateDebugger([&] { DebuggerLifetime.Terminate(); });
Zachary Turner888a4282017-12-01 00:52:51 +0000976
977 auto Dbg = lldb_private::Debugger::CreateInstance();
978
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000979 if (!opts::Log.empty())
980 Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, errs());
981
Pavel Labath7c945822018-02-26 18:50:16 +0000982 if (opts::BreakpointSubcommand)
Pavel Labath90b0a532018-05-03 10:57:16 +0000983 return opts::breakpoint::evaluateBreakpoints(*Dbg);
Pavel Labath62a7f802018-06-29 12:15:54 +0000984 if (opts::ObjectFileSubcommand)
985 return dumpObjectFiles(*Dbg);
Pavel Labath90b0a532018-05-03 10:57:16 +0000986 if (opts::SymbolsSubcommand)
987 return opts::symbols::dumpSymbols(*Dbg);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000988 if (opts::IRMemoryMapSubcommand)
989 return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
Zachary Turner888a4282017-12-01 00:52:51 +0000990
Pavel Labath90b0a532018-05-03 10:57:16 +0000991 WithColor::error() << "No command specified.\n";
992 return 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000993}