blob: c9225f63d30335abad7eadbab6b6399205b0f223 [file] [log] [blame]
Zachary Turner888a4282017-12-01 00:52:51 +00001//===- lldb-test.cpp ------------------------------------------ *- C++ --*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "FormatUtil.h"
11#include "SystemInitializerTest.h"
12
Zachary Turnera6d54642017-12-02 00:15:29 +000013#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
Pavel Labath7c945822018-02-26 18:50:16 +000014#include "lldb/Breakpoint/BreakpointLocation.h"
Zachary Turner888a4282017-12-01 00:52:51 +000015#include "lldb/Core/Debugger.h"
16#include "lldb/Core/Module.h"
17#include "lldb/Core/Section.h"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000018#include "lldb/Expression/IRMemoryMap.h"
Zachary Turner888a4282017-12-01 00:52:51 +000019#include "lldb/Initialization/SystemLifetimeManager.h"
Pavel Labath7c945822018-02-26 18:50:16 +000020#include "lldb/Interpreter/CommandInterpreter.h"
21#include "lldb/Interpreter/CommandReturnObject.h"
Zachary Turnera6d54642017-12-02 00:15:29 +000022#include "lldb/Symbol/ClangASTContext.h"
23#include "lldb/Symbol/ClangASTImporter.h"
Aaron Smith010edd32018-06-08 02:45:25 +000024#include "lldb/Symbol/CompileUnit.h"
25#include "lldb/Symbol/LineTable.h"
Pavel Labath90b0a532018-05-03 10:57:16 +000026#include "lldb/Symbol/SymbolVendor.h"
27#include "lldb/Symbol/TypeList.h"
28#include "lldb/Symbol/VariableList.h"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000029#include "lldb/Target/Process.h"
30#include "lldb/Target/Target.h"
Pavel Labath90b0a532018-05-03 10:57:16 +000031#include "lldb/Utility/CleanUp.h"
Zachary Turner888a4282017-12-01 00:52:51 +000032#include "lldb/Utility/DataExtractor.h"
Zachary Turnera6d54642017-12-02 00:15:29 +000033#include "lldb/Utility/StreamString.h"
Zachary Turner888a4282017-12-01 00:52:51 +000034
Vedant Kumarc1cd8262018-05-30 19:39:10 +000035#include "llvm/ADT/IntervalMap.h"
Zachary Turner888a4282017-12-01 00:52:51 +000036#include "llvm/ADT/StringRef.h"
37#include "llvm/Support/CommandLine.h"
38#include "llvm/Support/ManagedStatic.h"
Pavel Labath9ea80d22018-06-28 10:03:42 +000039#include "llvm/Support/MathExtras.h"
Pavel Labath7c945822018-02-26 18:50:16 +000040#include "llvm/Support/Path.h"
Zachary Turner888a4282017-12-01 00:52:51 +000041#include "llvm/Support/PrettyStackTrace.h"
42#include "llvm/Support/Signals.h"
Pavel Labath90b0a532018-05-03 10:57:16 +000043#include "llvm/Support/WithColor.h"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000044#include <cstdio>
Zachary Turner888a4282017-12-01 00:52:51 +000045#include <thread>
46
47using namespace lldb;
48using namespace lldb_private;
49using namespace llvm;
50
51namespace opts {
Pavel Labath7c945822018-02-26 18:50:16 +000052static cl::SubCommand BreakpointSubcommand("breakpoints",
53 "Test breakpoint resolution");
Pavel Labath62a7f802018-06-29 12:15:54 +000054cl::SubCommand ObjectFileSubcommand("object-file",
55 "Display LLDB object file information");
Zachary Turnera6d54642017-12-02 00:15:29 +000056cl::SubCommand SymbolsSubcommand("symbols", "Dump symbols for an object file");
Vedant Kumarc1cd8262018-05-30 19:39:10 +000057cl::SubCommand IRMemoryMapSubcommand("ir-memory-map", "Test IRMemoryMap");
Vedant Kumar7e4c84a2018-05-31 22:09:00 +000058
Vedant Kumarc1cd8262018-05-30 19:39:10 +000059cl::opt<std::string> Log("log", cl::desc("Path to a log file"), cl::init(""),
Vedant Kumar7e4c84a2018-05-31 22:09:00 +000060 cl::sub(BreakpointSubcommand),
Pavel Labath62a7f802018-06-29 12:15:54 +000061 cl::sub(ObjectFileSubcommand),
62 cl::sub(SymbolsSubcommand),
Vedant Kumarc1cd8262018-05-30 19:39:10 +000063 cl::sub(IRMemoryMapSubcommand));
64
65/// Create a target using the file pointed to by \p Filename, or abort.
66TargetSP createTarget(Debugger &Dbg, const std::string &Filename);
67
68/// Read \p Filename into a null-terminated buffer, or abort.
69std::unique_ptr<MemoryBuffer> openFile(const std::string &Filename);
Zachary Turner888a4282017-12-01 00:52:51 +000070
Pavel Labath7c945822018-02-26 18:50:16 +000071namespace breakpoint {
72static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
73 cl::Required, cl::sub(BreakpointSubcommand));
74static cl::opt<std::string> CommandFile(cl::Positional,
75 cl::desc("<command-file>"),
76 cl::init("-"),
77 cl::sub(BreakpointSubcommand));
78static cl::opt<bool> Persistent(
79 "persistent",
80 cl::desc("Don't automatically remove all breakpoints before each command"),
81 cl::sub(BreakpointSubcommand));
82
83static llvm::StringRef plural(uintmax_t value) { return value == 1 ? "" : "s"; }
84static void dumpState(const BreakpointList &List, LinePrinter &P);
85static std::string substitute(StringRef Cmd);
Pavel Labath90b0a532018-05-03 10:57:16 +000086static int evaluateBreakpoints(Debugger &Dbg);
Pavel Labath7c945822018-02-26 18:50:16 +000087} // namespace breakpoint
88
Pavel Labath62a7f802018-06-29 12:15:54 +000089namespace object {
Zachary Turner888a4282017-12-01 00:52:51 +000090cl::opt<bool> SectionContents("contents",
91 cl::desc("Dump each section's contents"),
Pavel Labath62a7f802018-06-29 12:15:54 +000092 cl::sub(ObjectFileSubcommand));
Zachary Turner888a4282017-12-01 00:52:51 +000093cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
Pavel Labath62a7f802018-06-29 12:15:54 +000094 cl::OneOrMore,
95 cl::sub(ObjectFileSubcommand));
96} // namespace object
Zachary Turnera6d54642017-12-02 00:15:29 +000097
98namespace symbols {
Pavel Labath90b0a532018-05-03 10:57:16 +000099static cl::list<std::string> InputFilenames(cl::Positional,
100 cl::desc("<input files>"),
101 cl::OneOrMore,
102 cl::sub(SymbolsSubcommand));
103enum class FindType {
104 None,
105 Function,
106 Namespace,
107 Type,
108 Variable,
109};
110static cl::opt<FindType> Find(
111 "find", cl::desc("Choose search type:"),
112 cl::values(
Pavel Labath9ea80d22018-06-28 10:03:42 +0000113 clEnumValN(FindType::None, "none", "No search, just dump the module."),
Pavel Labath90b0a532018-05-03 10:57:16 +0000114 clEnumValN(FindType::Function, "function", "Find functions."),
115 clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
116 clEnumValN(FindType::Type, "type", "Find types."),
117 clEnumValN(FindType::Variable, "variable", "Find global variables.")),
118 cl::sub(SymbolsSubcommand));
119
120static cl::opt<std::string> Name("name", cl::desc("Name to find."),
121 cl::sub(SymbolsSubcommand));
122static cl::opt<bool>
123 Regex("regex",
124 cl::desc("Search using regular expressions (avaliable for variables "
125 "and functions only)."),
126 cl::sub(SymbolsSubcommand));
127static cl::opt<std::string>
128 Context("context",
129 cl::desc("Restrict search to the context of the given variable."),
130 cl::value_desc("variable"), cl::sub(SymbolsSubcommand));
131
132static cl::list<FunctionNameType> FunctionNameFlags(
133 "function-flags", cl::desc("Function search flags:"),
134 cl::values(clEnumValN(eFunctionNameTypeAuto, "auto",
135 "Automatically deduce flags based on name."),
136 clEnumValN(eFunctionNameTypeFull, "full", "Full function name."),
137 clEnumValN(eFunctionNameTypeBase, "base", "Base name."),
138 clEnumValN(eFunctionNameTypeMethod, "method", "Method name."),
139 clEnumValN(eFunctionNameTypeSelector, "selector",
140 "Selector name.")),
141 cl::sub(SymbolsSubcommand));
142static FunctionNameType getFunctionNameFlags() {
143 FunctionNameType Result = FunctionNameType(0);
144 for (FunctionNameType Flag : FunctionNameFlags)
145 Result = FunctionNameType(Result | Flag);
146 return Result;
147}
148
Aaron Smith010edd32018-06-08 02:45:25 +0000149static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
150 cl::sub(SymbolsSubcommand));
151
Pavel Labathe6954cb2018-06-12 12:57:36 +0000152static cl::opt<std::string> File("file",
153 cl::desc("File (compile unit) to search."),
154 cl::sub(SymbolsSubcommand));
Pavel Labath9ea80d22018-06-28 10:03:42 +0000155static cl::opt<int> Line("line", cl::desc("Line to search."),
156 cl::sub(SymbolsSubcommand));
Pavel Labathe6954cb2018-06-12 12:57:36 +0000157
Pavel Labath90b0a532018-05-03 10:57:16 +0000158static Expected<CompilerDeclContext> getDeclContext(SymbolVendor &Vendor);
159
160static Error findFunctions(lldb_private::Module &Module);
161static Error findNamespaces(lldb_private::Module &Module);
162static Error findTypes(lldb_private::Module &Module);
163static Error findVariables(lldb_private::Module &Module);
164static Error dumpModule(lldb_private::Module &Module);
Aaron Smith010edd32018-06-08 02:45:25 +0000165static Error verify(lldb_private::Module &Module);
Pavel Labath90b0a532018-05-03 10:57:16 +0000166
Pavel Labath38d9ff72018-06-12 13:26:43 +0000167static Expected<Error (*)(lldb_private::Module &)> getAction();
Pavel Labath90b0a532018-05-03 10:57:16 +0000168static int dumpSymbols(Debugger &Dbg);
Pavel Labath9ea80d22018-06-28 10:03:42 +0000169} // namespace symbols
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000170
171namespace irmemorymap {
172static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
173 cl::Required,
174 cl::sub(IRMemoryMapSubcommand));
175static cl::opt<std::string> CommandFile(cl::Positional,
176 cl::desc("<command-file>"),
177 cl::init("-"),
178 cl::sub(IRMemoryMapSubcommand));
Vedant Kumarf616b9d2018-05-31 22:09:00 +0000179static cl::opt<bool> UseHostOnlyAllocationPolicy(
180 "host-only", cl::desc("Use the host-only allocation policy"),
181 cl::init(false), cl::sub(IRMemoryMapSubcommand));
182
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000183using AllocationT = std::pair<addr_t, addr_t>;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000184using AddrIntervalMap =
Pavel Labath9ea80d22018-06-28 10:03:42 +0000185 IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000186
187struct IRMemoryMapTestState {
188 TargetSP Target;
189 IRMemoryMap Map;
190
191 AddrIntervalMap::Allocator IntervalMapAllocator;
192 AddrIntervalMap Allocations;
193
194 StringMap<addr_t> Label2AddrMap;
195
196 IRMemoryMapTestState(TargetSP Target)
197 : Target(Target), Map(Target), Allocations(IntervalMapAllocator) {}
198};
199
200bool areAllocationsOverlapping(const AllocationT &L, const AllocationT &R);
201bool evalMalloc(StringRef Line, IRMemoryMapTestState &State);
202bool evalFree(StringRef Line, IRMemoryMapTestState &State);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000203int evaluateMemoryMapCommands(Debugger &Dbg);
204} // namespace irmemorymap
205
Zachary Turner888a4282017-12-01 00:52:51 +0000206} // namespace opts
207
Pavel Labathe6954cb2018-06-12 12:57:36 +0000208template <typename... Args>
209static Error make_string_error(const char *Format, Args &&... args) {
210 return llvm::make_error<llvm::StringError>(
211 llvm::formatv(Format, std::forward<Args>(args)...).str(),
212 llvm::inconvertibleErrorCode());
213}
214
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000215TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) {
216 TargetSP Target;
217 Status ST =
218 Dbg.GetTargetList().CreateTarget(Dbg, Filename, /*triple*/ "",
219 /*get_dependent_modules*/ false,
220 /*platform_options*/ nullptr, Target);
221 if (ST.Fail()) {
222 errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST);
223 exit(1);
224 }
225 return Target;
226}
227
228std::unique_ptr<MemoryBuffer> opts::openFile(const std::string &Filename) {
229 auto MB = MemoryBuffer::getFileOrSTDIN(Filename);
230 if (!MB) {
231 errs() << formatv("Could not open file '{0}: {1}\n", Filename,
232 MB.getError().message());
233 exit(1);
234 }
235 return std::move(*MB);
236}
237
Pavel Labath7c945822018-02-26 18:50:16 +0000238void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) {
239 P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize()));
240 if (List.GetSize() > 0)
241 P.formatLine("At least one breakpoint.");
242 for (size_t i = 0, e = List.GetSize(); i < e; ++i) {
243 BreakpointSP BP = List.GetBreakpointAtIndex(i);
244 P.formatLine("Breakpoint ID {0}:", BP->GetID());
245 AutoIndent Indent(P, 2);
246 P.formatLine("{0} location{1}.", BP->GetNumLocations(),
247 plural(BP->GetNumLocations()));
248 if (BP->GetNumLocations() > 0)
249 P.formatLine("At least one location.");
250 P.formatLine("{0} resolved location{1}.", BP->GetNumResolvedLocations(),
251 plural(BP->GetNumResolvedLocations()));
252 if (BP->GetNumResolvedLocations() > 0)
253 P.formatLine("At least one resolved location.");
254 for (size_t l = 0, le = BP->GetNumLocations(); l < le; ++l) {
255 BreakpointLocationSP Loc = BP->GetLocationAtIndex(l);
256 P.formatLine("Location ID {0}:", Loc->GetID());
257 AutoIndent Indent(P, 2);
258 P.formatLine("Enabled: {0}", Loc->IsEnabled());
259 P.formatLine("Resolved: {0}", Loc->IsResolved());
Jim Ingham08581262018-03-12 21:17:04 +0000260 SymbolContext sc;
261 Loc->GetAddress().CalculateSymbolContext(&sc);
262 lldb_private::StreamString S;
263 sc.DumpStopContext(&S, BP->GetTarget().GetProcessSP().get(),
264 Loc->GetAddress(), false, true, false, true, true);
265 P.formatLine("Address: {0}", S.GetString());
Pavel Labath7c945822018-02-26 18:50:16 +0000266 }
267 }
268 P.NewLine();
269}
270
271std::string opts::breakpoint::substitute(StringRef Cmd) {
272 std::string Result;
273 raw_string_ostream OS(Result);
274 while (!Cmd.empty()) {
275 switch (Cmd[0]) {
276 case '%':
277 if (Cmd.consume_front("%p") && (Cmd.empty() || !isalnum(Cmd[0]))) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000278 OS << sys::path::parent_path(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000279 break;
280 }
281 // fall through
282 default:
283 size_t pos = Cmd.find('%');
284 OS << Cmd.substr(0, pos);
285 Cmd = Cmd.substr(pos);
286 break;
287 }
288 }
289 return std::move(OS.str());
290}
291
Pavel Labath90b0a532018-05-03 10:57:16 +0000292int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000293 TargetSP Target = opts::createTarget(Dbg, breakpoint::Target);
294 std::unique_ptr<MemoryBuffer> MB = opts::openFile(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000295
296 LinePrinter P(4, outs());
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000297 StringRef Rest = MB->getBuffer();
Pavel Labath90b0a532018-05-03 10:57:16 +0000298 int HadErrors = 0;
Pavel Labath7c945822018-02-26 18:50:16 +0000299 while (!Rest.empty()) {
300 StringRef Line;
301 std::tie(Line, Rest) = Rest.split('\n');
302 Line = Line.ltrim();
303 if (Line.empty() || Line[0] == '#')
304 continue;
305
306 if (!Persistent)
307 Target->RemoveAllBreakpoints(/*internal_also*/ true);
308
309 std::string Command = substitute(Line);
310 P.formatLine("Command: {0}", Command);
311 CommandReturnObject Result;
312 if (!Dbg.GetCommandInterpreter().HandleCommand(
313 Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
314 P.formatLine("Failed: {0}", Result.GetErrorData());
Pavel Labath90b0a532018-05-03 10:57:16 +0000315 HadErrors = 1;
Pavel Labath7c945822018-02-26 18:50:16 +0000316 continue;
317 }
318
319 dumpState(Target->GetBreakpointList(/*internal*/ false), P);
320 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000321 return HadErrors;
Pavel Labath7c945822018-02-26 18:50:16 +0000322}
323
Pavel Labath90b0a532018-05-03 10:57:16 +0000324Expected<CompilerDeclContext>
325opts::symbols::getDeclContext(SymbolVendor &Vendor) {
326 if (Context.empty())
327 return CompilerDeclContext();
328 VariableList List;
Pavel Labath34cda142018-05-31 09:46:26 +0000329 Vendor.FindGlobalVariables(ConstString(Context), nullptr, UINT32_MAX, List);
Pavel Labathe6954cb2018-06-12 12:57:36 +0000330 if (List.Empty())
331 return make_string_error("Context search didn't find a match.");
332 if (List.GetSize() > 1)
333 return make_string_error("Context search found multiple matches.");
Pavel Labath90b0a532018-05-03 10:57:16 +0000334 return List.GetVariableAtIndex(0)->GetDeclContext();
335}
336
337Error opts::symbols::findFunctions(lldb_private::Module &Module) {
338 SymbolVendor &Vendor = *Module.GetSymbolVendor();
339 SymbolContextList List;
Pavel Labath9ea80d22018-06-28 10:03:42 +0000340 if (!File.empty()) {
341 assert(Line != 0);
342
343 FileSpec src_file(File, false);
344 size_t cu_count = Module.GetNumCompileUnits();
345 for (size_t i = 0; i < cu_count; i++) {
346 lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
347 if (!cu_sp)
348 continue;
349
350 LineEntry le;
351 cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
352 if (!le.IsValid())
353 continue;
354
355 auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress();
356 if (!addr.IsValid())
357 continue;
358
359 SymbolContext sc;
360 uint32_t resolved =
361 addr.CalculateSymbolContext(&sc, eSymbolContextFunction);
362 if (resolved & eSymbolContextFunction)
363 List.Append(sc);
364 }
365 } else if (Regex) {
Pavel Labath90b0a532018-05-03 10:57:16 +0000366 RegularExpression RE(Name);
367 assert(RE.IsValid());
368 Vendor.FindFunctions(RE, true, false, List);
369 } else {
370 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
371 if (!ContextOr)
372 return ContextOr.takeError();
373 CompilerDeclContext *ContextPtr =
374 ContextOr->IsValid() ? &*ContextOr : nullptr;
375
376 Vendor.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
Pavel Labath9ea80d22018-06-28 10:03:42 +0000377 true, false, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000378 }
379 outs() << formatv("Found {0} functions:\n", List.GetSize());
380 StreamString Stream;
381 List.Dump(&Stream, nullptr);
382 outs() << Stream.GetData() << "\n";
383 return Error::success();
384}
385
386Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
387 SymbolVendor &Vendor = *Module.GetSymbolVendor();
388 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
389 if (!ContextOr)
390 return ContextOr.takeError();
391 CompilerDeclContext *ContextPtr =
392 ContextOr->IsValid() ? &*ContextOr : nullptr;
393
394 SymbolContext SC;
395 CompilerDeclContext Result =
396 Vendor.FindNamespace(SC, ConstString(Name), ContextPtr);
397 if (Result)
398 outs() << "Found namespace: "
399 << Result.GetScopeQualifiedName().GetStringRef() << "\n";
400 else
401 outs() << "Namespace not found.\n";
402 return Error::success();
403}
404
405Error opts::symbols::findTypes(lldb_private::Module &Module) {
406 SymbolVendor &Vendor = *Module.GetSymbolVendor();
407 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
408 if (!ContextOr)
409 return ContextOr.takeError();
410 CompilerDeclContext *ContextPtr =
411 ContextOr->IsValid() ? &*ContextOr : nullptr;
412
413 SymbolContext SC;
414 DenseSet<SymbolFile *> SearchedFiles;
415 TypeMap Map;
416 Vendor.FindTypes(SC, ConstString(Name), ContextPtr, true, UINT32_MAX,
Pavel Labath9ea80d22018-06-28 10:03:42 +0000417 SearchedFiles, Map);
Pavel Labath90b0a532018-05-03 10:57:16 +0000418
419 outs() << formatv("Found {0} types:\n", Map.GetSize());
420 StreamString Stream;
421 Map.Dump(&Stream, false);
422 outs() << Stream.GetData() << "\n";
423 return Error::success();
424}
425
426Error opts::symbols::findVariables(lldb_private::Module &Module) {
427 SymbolVendor &Vendor = *Module.GetSymbolVendor();
428 VariableList List;
429 if (Regex) {
430 RegularExpression RE(Name);
431 assert(RE.IsValid());
Pavel Labath34cda142018-05-31 09:46:26 +0000432 Vendor.FindGlobalVariables(RE, UINT32_MAX, List);
Pavel Labathe6954cb2018-06-12 12:57:36 +0000433 } else if (!File.empty()) {
434 CompUnitSP CU;
435 for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) {
436 CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind);
437 if (!Candidate || Candidate->GetFilename().GetStringRef() != File)
438 continue;
439 if (CU)
440 return make_string_error("Multiple compile units for file `{0}` found.",
441 File);
442 CU = std::move(Candidate);
443 }
444
445 if (!CU)
446 return make_string_error("Compile unit `{0}` not found.", File);
447
448 List.AddVariables(CU->GetVariableList(true).get());
Pavel Labath90b0a532018-05-03 10:57:16 +0000449 } else {
450 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
451 if (!ContextOr)
452 return ContextOr.takeError();
453 CompilerDeclContext *ContextPtr =
454 ContextOr->IsValid() ? &*ContextOr : nullptr;
455
Pavel Labath34cda142018-05-31 09:46:26 +0000456 Vendor.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000457 }
458 outs() << formatv("Found {0} variables:\n", List.GetSize());
459 StreamString Stream;
460 List.Dump(&Stream, false);
461 outs() << Stream.GetData() << "\n";
462 return Error::success();
463}
464
465Error opts::symbols::dumpModule(lldb_private::Module &Module) {
466 StreamString Stream;
467 Module.ParseAllDebugSymbols();
468 Module.Dump(&Stream);
469 outs() << Stream.GetData() << "\n";
470 return Error::success();
471}
472
Aaron Smith010edd32018-06-08 02:45:25 +0000473Error opts::symbols::verify(lldb_private::Module &Module) {
Pavel Labathe6954cb2018-06-12 12:57:36 +0000474 SymbolVendor &plugin = *Module.GetSymbolVendor();
Aaron Smith010edd32018-06-08 02:45:25 +0000475
Pavel Labathe6954cb2018-06-12 12:57:36 +0000476 SymbolFile *symfile = plugin.GetSymbolFile();
Aaron Smith010edd32018-06-08 02:45:25 +0000477 if (!symfile)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000478 return make_string_error("Module has no symbol file.");
Aaron Smith010edd32018-06-08 02:45:25 +0000479
480 uint32_t comp_units_count = symfile->GetNumCompileUnits();
481
482 outs() << "Found " << comp_units_count << " compile units.\n";
483
484 for (uint32_t i = 0; i < comp_units_count; i++) {
485 lldb::CompUnitSP comp_unit = symfile->ParseCompileUnitAtIndex(i);
486 if (!comp_unit)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000487 return make_string_error("Connot parse compile unit {0}.", i);
Aaron Smith010edd32018-06-08 02:45:25 +0000488
Pavel Labath9ea80d22018-06-28 10:03:42 +0000489 outs() << "Processing '" << comp_unit->GetFilename().AsCString()
490 << "' compile unit.\n";
Aaron Smith010edd32018-06-08 02:45:25 +0000491
492 LineTable *lt = comp_unit->GetLineTable();
493 if (!lt)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000494 return make_string_error("Can't get a line table of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000495
496 uint32_t count = lt->GetSize();
497
498 outs() << "The line table contains " << count << " entries.\n";
499
500 if (count == 0)
501 continue;
502
503 LineEntry le;
504 if (!lt->GetLineEntryAtIndex(0, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000505 return make_string_error("Can't get a line entry of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000506
507 for (uint32_t i = 1; i < count; i++) {
508 lldb::addr_t curr_end =
Pavel Labath9ea80d22018-06-28 10:03:42 +0000509 le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
Aaron Smith010edd32018-06-08 02:45:25 +0000510
511 if (!lt->GetLineEntryAtIndex(i, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000512 return make_string_error("Can't get a line entry of a compile unit");
Aaron Smith010edd32018-06-08 02:45:25 +0000513
514 if (curr_end > le.range.GetBaseAddress().GetFileAddress())
Pavel Labathe6954cb2018-06-12 12:57:36 +0000515 return make_string_error(
516 "Line table of a compile unit is inconsistent.");
Aaron Smith010edd32018-06-08 02:45:25 +0000517 }
518 }
519
520 outs() << "The symbol information is verified.\n";
521
522 return Error::success();
523}
524
Pavel Labath38d9ff72018-06-12 13:26:43 +0000525Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
Pavel Labathe6954cb2018-06-12 12:57:36 +0000526 if (Verify) {
527 if (Find != FindType::None)
528 return make_string_error(
529 "Cannot both search and verify symbol information.");
Pavel Labath9ea80d22018-06-28 10:03:42 +0000530 if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
531 Line != 0)
532 return make_string_error(
533 "-regex, -context, -name, -file and -line options are not "
534 "applicable for symbol verification.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000535 return verify;
Pavel Labath90b0a532018-05-03 10:57:16 +0000536 }
537
Pavel Labathe6954cb2018-06-12 12:57:36 +0000538 if (Regex && !Context.empty())
539 return make_string_error(
540 "Cannot search using both regular expressions and context.");
541
542 if (Regex && !RegularExpression(Name).IsValid())
543 return make_string_error("`{0}` is not a valid regular expression.", Name);
544
545 if (Regex + !Context.empty() + !File.empty() >= 2)
546 return make_string_error(
547 "Only one of -regex, -context and -file may be used simultaneously.");
548 if (Regex && Name.empty())
549 return make_string_error("-regex used without a -name");
550
551 switch (Find) {
552 case FindType::None:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000553 if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000554 return make_string_error(
555 "Specify search type (-find) to use search options.");
556 return dumpModule;
557
558 case FindType::Function:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000559 if (!File.empty() + (Line != 0) == 1)
560 return make_string_error("Both file name and line number must be "
561 "specified when searching a function "
562 "by file position.");
563 if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2)
564 return make_string_error("Only one of regular expression, function-flags "
565 "and file position may be used simultaneously "
566 "when searching a function.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000567 return findFunctions;
568
569 case FindType::Namespace:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000570 if (Regex || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000571 return make_string_error("Cannot search for namespaces using regular "
Pavel Labath9ea80d22018-06-28 10:03:42 +0000572 "expressions, file names or line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000573 return findNamespaces;
574
575 case FindType::Type:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000576 if (Regex || !File.empty() || Line != 0)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000577 return make_string_error("Cannot search for types using regular "
Pavel Labath9ea80d22018-06-28 10:03:42 +0000578 "expressions, file names or line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000579 return findTypes;
580
581 case FindType::Variable:
Pavel Labath9ea80d22018-06-28 10:03:42 +0000582 if (Line != 0)
583 return make_string_error("Cannot search for variables "
584 "using line numbers.");
Pavel Labathe6954cb2018-06-12 12:57:36 +0000585 return findVariables;
586 }
587}
588
589int opts::symbols::dumpSymbols(Debugger &Dbg) {
590 auto ActionOr = getAction();
591 if (!ActionOr) {
592 logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), "");
593 return 1;
594 }
595 auto Action = *ActionOr;
Pavel Labath90b0a532018-05-03 10:57:16 +0000596
597 int HadErrors = 0;
598 for (const auto &File : InputFilenames) {
599 outs() << "Module: " << File << "\n";
Zachary Turnera6d54642017-12-02 00:15:29 +0000600 ModuleSpec Spec{FileSpec(File, false)};
Jonas Devlieghere937348c2018-06-13 22:08:14 +0000601 Spec.GetSymbolFileSpec().SetFile(File, false, FileSpec::Style::native);
Zachary Turnera6d54642017-12-02 00:15:29 +0000602
603 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
Pavel Labath90b0a532018-05-03 10:57:16 +0000604 SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
605 if (!Vendor) {
606 WithColor::error() << "Module has no symbol vendor.\n";
607 HadErrors = 1;
608 continue;
609 }
Pavel Labathe6954cb2018-06-12 12:57:36 +0000610
Pavel Labath90b0a532018-05-03 10:57:16 +0000611 if (Error E = Action(*ModulePtr)) {
612 WithColor::error() << toString(std::move(E)) << "\n";
613 HadErrors = 1;
614 }
Zachary Turnera6d54642017-12-02 00:15:29 +0000615
Pavel Labath90b0a532018-05-03 10:57:16 +0000616 outs().flush();
Zachary Turnera6d54642017-12-02 00:15:29 +0000617 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000618 return HadErrors;
Zachary Turnera6d54642017-12-02 00:15:29 +0000619}
620
Pavel Labath62a7f802018-06-29 12:15:54 +0000621static int dumpObjectFiles(Debugger &Dbg) {
Zachary Turner888a4282017-12-01 00:52:51 +0000622 LinePrinter Printer(4, llvm::outs());
623
Pavel Labath90b0a532018-05-03 10:57:16 +0000624 int HadErrors = 0;
Pavel Labath62a7f802018-06-29 12:15:54 +0000625 for (const auto &File : opts::object::InputFilenames) {
Zachary Turner888a4282017-12-01 00:52:51 +0000626 ModuleSpec Spec{FileSpec(File, false)};
Zachary Turner888a4282017-12-01 00:52:51 +0000627
Zachary Turnera6d54642017-12-02 00:15:29 +0000628 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
Pavel Labath96979ce2018-03-06 15:56:20 +0000629 // Fetch symbol vendor before we get the section list to give the symbol
630 // vendor a chance to populate it.
631 ModulePtr->GetSymbolVendor();
Zachary Turner888a4282017-12-01 00:52:51 +0000632 SectionList *Sections = ModulePtr->GetSectionList();
633 if (!Sections) {
634 llvm::errs() << "Could not load sections for module " << File << "\n";
Pavel Labath90b0a532018-05-03 10:57:16 +0000635 HadErrors = 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000636 continue;
637 }
638
Pavel Labath62a7f802018-06-29 12:15:54 +0000639 Printer.formatLine("Architecture: {0}",
640 ModulePtr->GetArchitecture().GetTriple().getTriple());
641 Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
642
Zachary Turner888a4282017-12-01 00:52:51 +0000643 size_t Count = Sections->GetNumSections(0);
644 Printer.formatLine("Showing {0} sections", Count);
645 for (size_t I = 0; I < Count; ++I) {
646 AutoIndent Indent(Printer, 2);
647 auto S = Sections->GetSectionAtIndex(I);
648 assert(S);
649 Printer.formatLine("Index: {0}", I);
650 Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
Jan Kratochvile4777a92018-04-29 19:47:48 +0000651 Printer.formatLine("Type: {0}", S->GetTypeAsCString());
Pavel Labathe2867bc2017-12-15 14:23:58 +0000652 Printer.formatLine("VM size: {0}", S->GetByteSize());
653 Printer.formatLine("File size: {0}", S->GetFileSize());
Zachary Turner888a4282017-12-01 00:52:51 +0000654
Pavel Labath62a7f802018-06-29 12:15:54 +0000655 if (opts::object::SectionContents) {
Zachary Turner888a4282017-12-01 00:52:51 +0000656 DataExtractor Data;
657 S->GetSectionData(Data);
658 ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()};
659 Printer.formatBinary("Data: ", Bytes, 0);
660 }
661 Printer.NewLine();
662 }
663 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000664 return HadErrors;
Zachary Turner888a4282017-12-01 00:52:51 +0000665}
666
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000667/// Check if two half-open intervals intersect:
668/// http://world.std.com/~swmcd/steven/tech/interval.html
669bool opts::irmemorymap::areAllocationsOverlapping(const AllocationT &L,
670 const AllocationT &R) {
671 return R.first < L.second && L.first < R.second;
672}
673
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000674bool opts::irmemorymap::evalMalloc(StringRef Line,
675 IRMemoryMapTestState &State) {
676 // ::= <label> = malloc <size> <alignment>
677 StringRef Label;
678 std::tie(Label, Line) = Line.split('=');
679 if (Line.empty())
680 return false;
681 Label = Label.trim();
682 Line = Line.trim();
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000683 size_t Size;
684 uint8_t Alignment;
685 int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment);
686 if (Matches != 2)
687 return false;
688
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000689 outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label,
690 Size, Alignment);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000691 if (!isPowerOf2_32(Alignment)) {
692 outs() << "Malloc error: alignment is not a power of 2\n";
693 exit(1);
694 }
695
Vedant Kumarf616b9d2018-05-31 22:09:00 +0000696 IRMemoryMap::AllocationPolicy AP =
697 UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly
698 : IRMemoryMap::eAllocationPolicyProcessOnly;
699
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000700 // Issue the malloc in the target process with "-rw" permissions.
701 const uint32_t Permissions = 0x3;
702 const bool ZeroMemory = false;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000703 Status ST;
704 addr_t Addr =
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000705 State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000706 if (ST.Fail()) {
707 outs() << formatv("Malloc error: {0}\n", ST);
708 return true;
709 }
710
711 // Print the result of the allocation before checking its validity.
712 outs() << formatv("Malloc: address = {0:x}\n", Addr);
713
714 // Check that the allocation is aligned.
715 if (!Addr || Addr % Alignment != 0) {
716 outs() << "Malloc error: zero or unaligned allocation detected\n";
717 exit(1);
718 }
719
720 // Check that the allocation does not overlap another allocation. Do so by
721 // testing each allocation which may cover the interval [Addr, EndOfRegion).
722 addr_t EndOfRegion = Addr + Size;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000723 auto Probe = State.Allocations.begin();
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000724 Probe.advanceTo(Addr); //< First interval s.t stop >= Addr.
725 AllocationT NewAllocation = {Addr, EndOfRegion};
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000726 while (Probe != State.Allocations.end() && Probe.start() < EndOfRegion) {
Vedant Kumarf3b6d292018-05-30 19:46:47 +0000727 AllocationT ProbeAllocation = {Probe.start(), Probe.stop()};
728 if (areAllocationsOverlapping(ProbeAllocation, NewAllocation)) {
729 outs() << "Malloc error: overlapping allocation detected"
730 << formatv(", previous allocation at [{0:x}, {1:x})\n",
731 Probe.start(), Probe.stop());
732 exit(1);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000733 }
Vedant Kumarf3b6d292018-05-30 19:46:47 +0000734 ++Probe;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000735 }
736
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000737 // Insert the new allocation into the interval map. Use unique allocation IDs
738 // to inhibit interval coalescing.
739 static unsigned AllocationID = 0;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000740 if (Size)
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000741 State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
742
743 // Store the label -> address mapping.
744 State.Label2AddrMap[Label] = Addr;
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000745
746 return true;
747}
748
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000749bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) {
750 // ::= free <label>
751 if (!Line.consume_front("free"))
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000752 return false;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000753 StringRef Label = Line.trim();
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000754
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000755 outs() << formatv("Command: free({0})\n", Label);
756 auto LabelIt = State.Label2AddrMap.find(Label);
757 if (LabelIt == State.Label2AddrMap.end()) {
758 outs() << "Free error: Invalid allocation label\n";
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000759 exit(1);
760 }
761
762 Status ST;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000763 addr_t Addr = LabelIt->getValue();
764 State.Map.Free(Addr, ST);
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000765 if (ST.Fail()) {
766 outs() << formatv("Free error: {0}\n", ST);
767 exit(1);
768 }
769
770 // Erase the allocation from the live interval map.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000771 auto Interval = State.Allocations.find(Addr);
772 if (Interval != State.Allocations.end()) {
773 outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(),
774 Interval.stop());
775 Interval.erase();
776 }
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000777
778 return true;
779}
780
781int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
782 // Set up a Target.
783 TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target);
784
785 // Set up a Process. In order to allocate memory within a target, this
786 // process must be alive and must support JIT'ing.
787 CommandReturnObject Result;
788 Dbg.SetAsyncExecution(false);
789 CommandInterpreter &CI = Dbg.GetCommandInterpreter();
790 auto IssueCmd = [&](const char *Cmd) -> bool {
791 return CI.HandleCommand(Cmd, eLazyBoolNo, Result);
792 };
793 if (!IssueCmd("b main") || !IssueCmd("run")) {
794 outs() << formatv("Failed: {0}\n", Result.GetErrorData());
795 exit(1);
796 }
797
798 ProcessSP Process = Target->GetProcessSP();
799 if (!Process || !Process->IsAlive() || !Process->CanJIT()) {
800 outs() << "Cannot use process to test IRMemoryMap\n";
801 exit(1);
802 }
803
804 // Set up an IRMemoryMap and associated testing state.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000805 IRMemoryMapTestState State(Target);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000806
807 // Parse and apply commands from the command file.
808 std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile);
809 StringRef Rest = MB->getBuffer();
810 while (!Rest.empty()) {
811 StringRef Line;
812 std::tie(Line, Rest) = Rest.split('\n');
813 Line = Line.ltrim();
814
815 if (Line.empty() || Line[0] == '#')
816 continue;
817
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000818 if (evalMalloc(Line, State))
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000819 continue;
820
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000821 if (evalFree(Line, State))
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000822 continue;
823
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000824 errs() << "Could not parse line: " << Line << "\n";
825 exit(1);
826 }
827 return 0;
828}
829
Zachary Turner888a4282017-12-01 00:52:51 +0000830int main(int argc, const char *argv[]) {
831 StringRef ToolName = argv[0];
832 sys::PrintStackTraceOnErrorSignal(ToolName);
833 PrettyStackTraceProgram X(argc, argv);
834 llvm_shutdown_obj Y;
835
836 cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
837
Pavel Labath90b0a532018-05-03 10:57:16 +0000838 SystemLifetimeManager DebuggerLifetime;
839 DebuggerLifetime.Initialize(llvm::make_unique<SystemInitializerTest>(),
840 nullptr);
841 CleanUp TerminateDebugger([&] { DebuggerLifetime.Terminate(); });
Zachary Turner888a4282017-12-01 00:52:51 +0000842
843 auto Dbg = lldb_private::Debugger::CreateInstance();
844
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000845 if (!opts::Log.empty())
846 Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, errs());
847
Pavel Labath7c945822018-02-26 18:50:16 +0000848 if (opts::BreakpointSubcommand)
Pavel Labath90b0a532018-05-03 10:57:16 +0000849 return opts::breakpoint::evaluateBreakpoints(*Dbg);
Pavel Labath62a7f802018-06-29 12:15:54 +0000850 if (opts::ObjectFileSubcommand)
851 return dumpObjectFiles(*Dbg);
Pavel Labath90b0a532018-05-03 10:57:16 +0000852 if (opts::SymbolsSubcommand)
853 return opts::symbols::dumpSymbols(*Dbg);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000854 if (opts::IRMemoryMapSubcommand)
855 return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
Zachary Turner888a4282017-12-01 00:52:51 +0000856
Pavel Labath90b0a532018-05-03 10:57:16 +0000857 WithColor::error() << "No command specified.\n";
858 return 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000859}