blob: e41c066f9abc4133f436de53d49f8e99fd03e6bb [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"
Vedant Kumarc1cd8262018-05-30 19:39:10 +000038#include "llvm/Support/MathExtras.h"
Zachary Turner888a4282017-12-01 00:52:51 +000039#include "llvm/Support/ManagedStatic.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");
Zachary Turner888a4282017-12-01 00:52:51 +000054cl::SubCommand ModuleSubcommand("module-sections",
55 "Display LLDB Module 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),
61 cl::sub(ModuleSubcommand), cl::sub(SymbolsSubcommand),
Vedant Kumarc1cd8262018-05-30 19:39:10 +000062 cl::sub(IRMemoryMapSubcommand));
63
64/// Create a target using the file pointed to by \p Filename, or abort.
65TargetSP createTarget(Debugger &Dbg, const std::string &Filename);
66
67/// Read \p Filename into a null-terminated buffer, or abort.
68std::unique_ptr<MemoryBuffer> openFile(const std::string &Filename);
Zachary Turner888a4282017-12-01 00:52:51 +000069
Pavel Labath7c945822018-02-26 18:50:16 +000070namespace breakpoint {
71static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
72 cl::Required, cl::sub(BreakpointSubcommand));
73static cl::opt<std::string> CommandFile(cl::Positional,
74 cl::desc("<command-file>"),
75 cl::init("-"),
76 cl::sub(BreakpointSubcommand));
77static cl::opt<bool> Persistent(
78 "persistent",
79 cl::desc("Don't automatically remove all breakpoints before each command"),
80 cl::sub(BreakpointSubcommand));
81
82static llvm::StringRef plural(uintmax_t value) { return value == 1 ? "" : "s"; }
83static void dumpState(const BreakpointList &List, LinePrinter &P);
84static std::string substitute(StringRef Cmd);
Pavel Labath90b0a532018-05-03 10:57:16 +000085static int evaluateBreakpoints(Debugger &Dbg);
Pavel Labath7c945822018-02-26 18:50:16 +000086} // namespace breakpoint
87
Zachary Turner888a4282017-12-01 00:52:51 +000088namespace module {
89cl::opt<bool> SectionContents("contents",
90 cl::desc("Dump each section's contents"),
91 cl::sub(ModuleSubcommand));
92cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
93 cl::OneOrMore, cl::sub(ModuleSubcommand));
94} // namespace module
Zachary Turnera6d54642017-12-02 00:15:29 +000095
96namespace symbols {
Pavel Labath90b0a532018-05-03 10:57:16 +000097static cl::list<std::string> InputFilenames(cl::Positional,
98 cl::desc("<input files>"),
99 cl::OneOrMore,
100 cl::sub(SymbolsSubcommand));
101enum class FindType {
102 None,
103 Function,
104 Namespace,
105 Type,
106 Variable,
107};
108static cl::opt<FindType> Find(
109 "find", cl::desc("Choose search type:"),
110 cl::values(
111 clEnumValN(FindType::None, "none",
112 "No search, just dump the module."),
113 clEnumValN(FindType::Function, "function", "Find functions."),
114 clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
115 clEnumValN(FindType::Type, "type", "Find types."),
116 clEnumValN(FindType::Variable, "variable", "Find global variables.")),
117 cl::sub(SymbolsSubcommand));
118
119static cl::opt<std::string> Name("name", cl::desc("Name to find."),
120 cl::sub(SymbolsSubcommand));
121static cl::opt<bool>
122 Regex("regex",
123 cl::desc("Search using regular expressions (avaliable for variables "
124 "and functions only)."),
125 cl::sub(SymbolsSubcommand));
126static cl::opt<std::string>
127 Context("context",
128 cl::desc("Restrict search to the context of the given variable."),
129 cl::value_desc("variable"), cl::sub(SymbolsSubcommand));
130
131static cl::list<FunctionNameType> FunctionNameFlags(
132 "function-flags", cl::desc("Function search flags:"),
133 cl::values(clEnumValN(eFunctionNameTypeAuto, "auto",
134 "Automatically deduce flags based on name."),
135 clEnumValN(eFunctionNameTypeFull, "full", "Full function name."),
136 clEnumValN(eFunctionNameTypeBase, "base", "Base name."),
137 clEnumValN(eFunctionNameTypeMethod, "method", "Method name."),
138 clEnumValN(eFunctionNameTypeSelector, "selector",
139 "Selector name.")),
140 cl::sub(SymbolsSubcommand));
141static FunctionNameType getFunctionNameFlags() {
142 FunctionNameType Result = FunctionNameType(0);
143 for (FunctionNameType Flag : FunctionNameFlags)
144 Result = FunctionNameType(Result | Flag);
145 return Result;
146}
147
Aaron Smith010edd32018-06-08 02:45:25 +0000148static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
149 cl::sub(SymbolsSubcommand));
150
Pavel Labathe6954cb2018-06-12 12:57:36 +0000151static cl::opt<std::string> File("file",
152 cl::desc("File (compile unit) to search."),
153 cl::sub(SymbolsSubcommand));
154
Pavel Labath90b0a532018-05-03 10:57:16 +0000155static Expected<CompilerDeclContext> getDeclContext(SymbolVendor &Vendor);
156
157static Error findFunctions(lldb_private::Module &Module);
158static Error findNamespaces(lldb_private::Module &Module);
159static Error findTypes(lldb_private::Module &Module);
160static Error findVariables(lldb_private::Module &Module);
161static Error dumpModule(lldb_private::Module &Module);
Aaron Smith010edd32018-06-08 02:45:25 +0000162static Error verify(lldb_private::Module &Module);
Pavel Labath90b0a532018-05-03 10:57:16 +0000163
Pavel Labath38d9ff72018-06-12 13:26:43 +0000164static Expected<Error (*)(lldb_private::Module &)> getAction();
Pavel Labath90b0a532018-05-03 10:57:16 +0000165static int dumpSymbols(Debugger &Dbg);
Zachary Turnera6d54642017-12-02 00:15:29 +0000166}
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000167
168namespace irmemorymap {
169static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
170 cl::Required,
171 cl::sub(IRMemoryMapSubcommand));
172static cl::opt<std::string> CommandFile(cl::Positional,
173 cl::desc("<command-file>"),
174 cl::init("-"),
175 cl::sub(IRMemoryMapSubcommand));
Vedant Kumarf616b9d2018-05-31 22:09:00 +0000176static cl::opt<bool> UseHostOnlyAllocationPolicy(
177 "host-only", cl::desc("Use the host-only allocation policy"),
178 cl::init(false), cl::sub(IRMemoryMapSubcommand));
179
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000180using AllocationT = std::pair<addr_t, addr_t>;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000181using AddrIntervalMap =
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000182 IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000183
184struct IRMemoryMapTestState {
185 TargetSP Target;
186 IRMemoryMap Map;
187
188 AddrIntervalMap::Allocator IntervalMapAllocator;
189 AddrIntervalMap Allocations;
190
191 StringMap<addr_t> Label2AddrMap;
192
193 IRMemoryMapTestState(TargetSP Target)
194 : Target(Target), Map(Target), Allocations(IntervalMapAllocator) {}
195};
196
197bool areAllocationsOverlapping(const AllocationT &L, const AllocationT &R);
198bool evalMalloc(StringRef Line, IRMemoryMapTestState &State);
199bool evalFree(StringRef Line, IRMemoryMapTestState &State);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000200int evaluateMemoryMapCommands(Debugger &Dbg);
201} // namespace irmemorymap
202
Zachary Turner888a4282017-12-01 00:52:51 +0000203} // namespace opts
204
Pavel Labathe6954cb2018-06-12 12:57:36 +0000205template <typename... Args>
206static Error make_string_error(const char *Format, Args &&... args) {
207 return llvm::make_error<llvm::StringError>(
208 llvm::formatv(Format, std::forward<Args>(args)...).str(),
209 llvm::inconvertibleErrorCode());
210}
211
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000212TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) {
213 TargetSP Target;
214 Status ST =
215 Dbg.GetTargetList().CreateTarget(Dbg, Filename, /*triple*/ "",
216 /*get_dependent_modules*/ false,
217 /*platform_options*/ nullptr, Target);
218 if (ST.Fail()) {
219 errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST);
220 exit(1);
221 }
222 return Target;
223}
224
225std::unique_ptr<MemoryBuffer> opts::openFile(const std::string &Filename) {
226 auto MB = MemoryBuffer::getFileOrSTDIN(Filename);
227 if (!MB) {
228 errs() << formatv("Could not open file '{0}: {1}\n", Filename,
229 MB.getError().message());
230 exit(1);
231 }
232 return std::move(*MB);
233}
234
Pavel Labath7c945822018-02-26 18:50:16 +0000235void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) {
236 P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize()));
237 if (List.GetSize() > 0)
238 P.formatLine("At least one breakpoint.");
239 for (size_t i = 0, e = List.GetSize(); i < e; ++i) {
240 BreakpointSP BP = List.GetBreakpointAtIndex(i);
241 P.formatLine("Breakpoint ID {0}:", BP->GetID());
242 AutoIndent Indent(P, 2);
243 P.formatLine("{0} location{1}.", BP->GetNumLocations(),
244 plural(BP->GetNumLocations()));
245 if (BP->GetNumLocations() > 0)
246 P.formatLine("At least one location.");
247 P.formatLine("{0} resolved location{1}.", BP->GetNumResolvedLocations(),
248 plural(BP->GetNumResolvedLocations()));
249 if (BP->GetNumResolvedLocations() > 0)
250 P.formatLine("At least one resolved location.");
251 for (size_t l = 0, le = BP->GetNumLocations(); l < le; ++l) {
252 BreakpointLocationSP Loc = BP->GetLocationAtIndex(l);
253 P.formatLine("Location ID {0}:", Loc->GetID());
254 AutoIndent Indent(P, 2);
255 P.formatLine("Enabled: {0}", Loc->IsEnabled());
256 P.formatLine("Resolved: {0}", Loc->IsResolved());
Jim Ingham08581262018-03-12 21:17:04 +0000257 SymbolContext sc;
258 Loc->GetAddress().CalculateSymbolContext(&sc);
259 lldb_private::StreamString S;
260 sc.DumpStopContext(&S, BP->GetTarget().GetProcessSP().get(),
261 Loc->GetAddress(), false, true, false, true, true);
262 P.formatLine("Address: {0}", S.GetString());
Pavel Labath7c945822018-02-26 18:50:16 +0000263 }
264 }
265 P.NewLine();
266}
267
268std::string opts::breakpoint::substitute(StringRef Cmd) {
269 std::string Result;
270 raw_string_ostream OS(Result);
271 while (!Cmd.empty()) {
272 switch (Cmd[0]) {
273 case '%':
274 if (Cmd.consume_front("%p") && (Cmd.empty() || !isalnum(Cmd[0]))) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000275 OS << sys::path::parent_path(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000276 break;
277 }
278 // fall through
279 default:
280 size_t pos = Cmd.find('%');
281 OS << Cmd.substr(0, pos);
282 Cmd = Cmd.substr(pos);
283 break;
284 }
285 }
286 return std::move(OS.str());
287}
288
Pavel Labath90b0a532018-05-03 10:57:16 +0000289int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000290 TargetSP Target = opts::createTarget(Dbg, breakpoint::Target);
291 std::unique_ptr<MemoryBuffer> MB = opts::openFile(breakpoint::CommandFile);
Pavel Labath7c945822018-02-26 18:50:16 +0000292
293 LinePrinter P(4, outs());
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000294 StringRef Rest = MB->getBuffer();
Pavel Labath90b0a532018-05-03 10:57:16 +0000295 int HadErrors = 0;
Pavel Labath7c945822018-02-26 18:50:16 +0000296 while (!Rest.empty()) {
297 StringRef Line;
298 std::tie(Line, Rest) = Rest.split('\n');
299 Line = Line.ltrim();
300 if (Line.empty() || Line[0] == '#')
301 continue;
302
303 if (!Persistent)
304 Target->RemoveAllBreakpoints(/*internal_also*/ true);
305
306 std::string Command = substitute(Line);
307 P.formatLine("Command: {0}", Command);
308 CommandReturnObject Result;
309 if (!Dbg.GetCommandInterpreter().HandleCommand(
310 Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
311 P.formatLine("Failed: {0}", Result.GetErrorData());
Pavel Labath90b0a532018-05-03 10:57:16 +0000312 HadErrors = 1;
Pavel Labath7c945822018-02-26 18:50:16 +0000313 continue;
314 }
315
316 dumpState(Target->GetBreakpointList(/*internal*/ false), P);
317 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000318 return HadErrors;
Pavel Labath7c945822018-02-26 18:50:16 +0000319}
320
Pavel Labath90b0a532018-05-03 10:57:16 +0000321Expected<CompilerDeclContext>
322opts::symbols::getDeclContext(SymbolVendor &Vendor) {
323 if (Context.empty())
324 return CompilerDeclContext();
325 VariableList List;
Pavel Labath34cda142018-05-31 09:46:26 +0000326 Vendor.FindGlobalVariables(ConstString(Context), nullptr, UINT32_MAX, List);
Pavel Labathe6954cb2018-06-12 12:57:36 +0000327 if (List.Empty())
328 return make_string_error("Context search didn't find a match.");
329 if (List.GetSize() > 1)
330 return make_string_error("Context search found multiple matches.");
Pavel Labath90b0a532018-05-03 10:57:16 +0000331 return List.GetVariableAtIndex(0)->GetDeclContext();
332}
333
334Error opts::symbols::findFunctions(lldb_private::Module &Module) {
335 SymbolVendor &Vendor = *Module.GetSymbolVendor();
336 SymbolContextList List;
337 if (Regex) {
338 RegularExpression RE(Name);
339 assert(RE.IsValid());
340 Vendor.FindFunctions(RE, true, false, List);
341 } else {
342 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
343 if (!ContextOr)
344 return ContextOr.takeError();
345 CompilerDeclContext *ContextPtr =
346 ContextOr->IsValid() ? &*ContextOr : nullptr;
347
348 Vendor.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
349 true, false, List);
350 }
351 outs() << formatv("Found {0} functions:\n", List.GetSize());
352 StreamString Stream;
353 List.Dump(&Stream, nullptr);
354 outs() << Stream.GetData() << "\n";
355 return Error::success();
356}
357
358Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
359 SymbolVendor &Vendor = *Module.GetSymbolVendor();
360 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
361 if (!ContextOr)
362 return ContextOr.takeError();
363 CompilerDeclContext *ContextPtr =
364 ContextOr->IsValid() ? &*ContextOr : nullptr;
365
366 SymbolContext SC;
367 CompilerDeclContext Result =
368 Vendor.FindNamespace(SC, ConstString(Name), ContextPtr);
369 if (Result)
370 outs() << "Found namespace: "
371 << Result.GetScopeQualifiedName().GetStringRef() << "\n";
372 else
373 outs() << "Namespace not found.\n";
374 return Error::success();
375}
376
377Error opts::symbols::findTypes(lldb_private::Module &Module) {
378 SymbolVendor &Vendor = *Module.GetSymbolVendor();
379 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
380 if (!ContextOr)
381 return ContextOr.takeError();
382 CompilerDeclContext *ContextPtr =
383 ContextOr->IsValid() ? &*ContextOr : nullptr;
384
385 SymbolContext SC;
386 DenseSet<SymbolFile *> SearchedFiles;
387 TypeMap Map;
388 Vendor.FindTypes(SC, ConstString(Name), ContextPtr, true, UINT32_MAX,
389 SearchedFiles, Map);
390
391 outs() << formatv("Found {0} types:\n", Map.GetSize());
392 StreamString Stream;
393 Map.Dump(&Stream, false);
394 outs() << Stream.GetData() << "\n";
395 return Error::success();
396}
397
398Error opts::symbols::findVariables(lldb_private::Module &Module) {
399 SymbolVendor &Vendor = *Module.GetSymbolVendor();
400 VariableList List;
401 if (Regex) {
402 RegularExpression RE(Name);
403 assert(RE.IsValid());
Pavel Labath34cda142018-05-31 09:46:26 +0000404 Vendor.FindGlobalVariables(RE, UINT32_MAX, List);
Pavel Labathe6954cb2018-06-12 12:57:36 +0000405 } else if (!File.empty()) {
406 CompUnitSP CU;
407 for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) {
408 CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind);
409 if (!Candidate || Candidate->GetFilename().GetStringRef() != File)
410 continue;
411 if (CU)
412 return make_string_error("Multiple compile units for file `{0}` found.",
413 File);
414 CU = std::move(Candidate);
415 }
416
417 if (!CU)
418 return make_string_error("Compile unit `{0}` not found.", File);
419
420 List.AddVariables(CU->GetVariableList(true).get());
Pavel Labath90b0a532018-05-03 10:57:16 +0000421 } else {
422 Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
423 if (!ContextOr)
424 return ContextOr.takeError();
425 CompilerDeclContext *ContextPtr =
426 ContextOr->IsValid() ? &*ContextOr : nullptr;
427
Pavel Labath34cda142018-05-31 09:46:26 +0000428 Vendor.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List);
Pavel Labath90b0a532018-05-03 10:57:16 +0000429 }
430 outs() << formatv("Found {0} variables:\n", List.GetSize());
431 StreamString Stream;
432 List.Dump(&Stream, false);
433 outs() << Stream.GetData() << "\n";
434 return Error::success();
435}
436
437Error opts::symbols::dumpModule(lldb_private::Module &Module) {
438 StreamString Stream;
439 Module.ParseAllDebugSymbols();
440 Module.Dump(&Stream);
441 outs() << Stream.GetData() << "\n";
442 return Error::success();
443}
444
Aaron Smith010edd32018-06-08 02:45:25 +0000445Error opts::symbols::verify(lldb_private::Module &Module) {
Pavel Labathe6954cb2018-06-12 12:57:36 +0000446 SymbolVendor &plugin = *Module.GetSymbolVendor();
Aaron Smith010edd32018-06-08 02:45:25 +0000447
Pavel Labathe6954cb2018-06-12 12:57:36 +0000448 SymbolFile *symfile = plugin.GetSymbolFile();
Aaron Smith010edd32018-06-08 02:45:25 +0000449 if (!symfile)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000450 return make_string_error("Module has no symbol file.");
Aaron Smith010edd32018-06-08 02:45:25 +0000451
452 uint32_t comp_units_count = symfile->GetNumCompileUnits();
453
454 outs() << "Found " << comp_units_count << " compile units.\n";
455
456 for (uint32_t i = 0; i < comp_units_count; i++) {
457 lldb::CompUnitSP comp_unit = symfile->ParseCompileUnitAtIndex(i);
458 if (!comp_unit)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000459 return make_string_error("Connot parse compile unit {0}.", i);
Aaron Smith010edd32018-06-08 02:45:25 +0000460
461 outs() << "Processing '" << comp_unit->GetFilename().AsCString() <<
462 "' compile unit.\n";
463
464 LineTable *lt = comp_unit->GetLineTable();
465 if (!lt)
Pavel Labathe6954cb2018-06-12 12:57:36 +0000466 return make_string_error("Can't get a line table of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000467
468 uint32_t count = lt->GetSize();
469
470 outs() << "The line table contains " << count << " entries.\n";
471
472 if (count == 0)
473 continue;
474
475 LineEntry le;
476 if (!lt->GetLineEntryAtIndex(0, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000477 return make_string_error("Can't get a line entry of a compile unit.");
Aaron Smith010edd32018-06-08 02:45:25 +0000478
479 for (uint32_t i = 1; i < count; i++) {
480 lldb::addr_t curr_end =
481 le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
482
483 if (!lt->GetLineEntryAtIndex(i, le))
Pavel Labathe6954cb2018-06-12 12:57:36 +0000484 return make_string_error("Can't get a line entry of a compile unit");
Aaron Smith010edd32018-06-08 02:45:25 +0000485
486 if (curr_end > le.range.GetBaseAddress().GetFileAddress())
Pavel Labathe6954cb2018-06-12 12:57:36 +0000487 return make_string_error(
488 "Line table of a compile unit is inconsistent.");
Aaron Smith010edd32018-06-08 02:45:25 +0000489 }
490 }
491
492 outs() << "The symbol information is verified.\n";
493
494 return Error::success();
495}
496
Pavel Labath38d9ff72018-06-12 13:26:43 +0000497Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
Pavel Labathe6954cb2018-06-12 12:57:36 +0000498 if (Verify) {
499 if (Find != FindType::None)
500 return make_string_error(
501 "Cannot both search and verify symbol information.");
502 if (Regex || !Context.empty() || !Name.empty() || !File.empty())
503 return make_string_error("-regex, -context, -name and -file options are not "
504 "applicable for symbol verification.");
505 return verify;
Pavel Labath90b0a532018-05-03 10:57:16 +0000506 }
507
Pavel Labathe6954cb2018-06-12 12:57:36 +0000508 if (Regex && !Context.empty())
509 return make_string_error(
510 "Cannot search using both regular expressions and context.");
511
512 if (Regex && !RegularExpression(Name).IsValid())
513 return make_string_error("`{0}` is not a valid regular expression.", Name);
514
515 if (Regex + !Context.empty() + !File.empty() >= 2)
516 return make_string_error(
517 "Only one of -regex, -context and -file may be used simultaneously.");
518 if (Regex && Name.empty())
519 return make_string_error("-regex used without a -name");
520
521 switch (Find) {
522 case FindType::None:
523 if (!Context.empty() || !Name.empty() || !File.empty())
524 return make_string_error(
525 "Specify search type (-find) to use search options.");
526 return dumpModule;
527
528 case FindType::Function:
529 if (!File.empty())
530 return make_string_error("Cannot search for functions by file name.");
531 if (Regex && getFunctionNameFlags() != 0)
532 return make_string_error("Cannot search for functions using both regular "
533 "expressions and function-flags.");
534 return findFunctions;
535
536 case FindType::Namespace:
537 if (Regex || !File.empty())
538 return make_string_error("Cannot search for namespaces using regular "
539 "expressions or file names.");
540 return findNamespaces;
541
542 case FindType::Type:
543 if (Regex || !File.empty())
544 return make_string_error("Cannot search for types using regular "
545 "expressions or file names.");
546 return findTypes;
547
548 case FindType::Variable:
549 return findVariables;
550 }
551}
552
553int opts::symbols::dumpSymbols(Debugger &Dbg) {
554 auto ActionOr = getAction();
555 if (!ActionOr) {
556 logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), "");
557 return 1;
558 }
559 auto Action = *ActionOr;
Pavel Labath90b0a532018-05-03 10:57:16 +0000560
561 int HadErrors = 0;
562 for (const auto &File : InputFilenames) {
563 outs() << "Module: " << File << "\n";
Zachary Turnera6d54642017-12-02 00:15:29 +0000564 ModuleSpec Spec{FileSpec(File, false)};
Jonas Devlieghere937348c2018-06-13 22:08:14 +0000565 Spec.GetSymbolFileSpec().SetFile(File, false, FileSpec::Style::native);
Zachary Turnera6d54642017-12-02 00:15:29 +0000566
567 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
Pavel Labath90b0a532018-05-03 10:57:16 +0000568 SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
569 if (!Vendor) {
570 WithColor::error() << "Module has no symbol vendor.\n";
571 HadErrors = 1;
572 continue;
573 }
Pavel Labathe6954cb2018-06-12 12:57:36 +0000574
Pavel Labath90b0a532018-05-03 10:57:16 +0000575 if (Error E = Action(*ModulePtr)) {
576 WithColor::error() << toString(std::move(E)) << "\n";
577 HadErrors = 1;
578 }
Zachary Turnera6d54642017-12-02 00:15:29 +0000579
Pavel Labath90b0a532018-05-03 10:57:16 +0000580 outs().flush();
Zachary Turnera6d54642017-12-02 00:15:29 +0000581 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000582 return HadErrors;
Zachary Turnera6d54642017-12-02 00:15:29 +0000583}
584
Pavel Labath90b0a532018-05-03 10:57:16 +0000585static int dumpModules(Debugger &Dbg) {
Zachary Turner888a4282017-12-01 00:52:51 +0000586 LinePrinter Printer(4, llvm::outs());
587
Pavel Labath90b0a532018-05-03 10:57:16 +0000588 int HadErrors = 0;
Zachary Turner888a4282017-12-01 00:52:51 +0000589 for (const auto &File : opts::module::InputFilenames) {
590 ModuleSpec Spec{FileSpec(File, false)};
Zachary Turner888a4282017-12-01 00:52:51 +0000591
Zachary Turnera6d54642017-12-02 00:15:29 +0000592 auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
Pavel Labath96979ce2018-03-06 15:56:20 +0000593 // Fetch symbol vendor before we get the section list to give the symbol
594 // vendor a chance to populate it.
595 ModulePtr->GetSymbolVendor();
Zachary Turner888a4282017-12-01 00:52:51 +0000596 SectionList *Sections = ModulePtr->GetSectionList();
597 if (!Sections) {
598 llvm::errs() << "Could not load sections for module " << File << "\n";
Pavel Labath90b0a532018-05-03 10:57:16 +0000599 HadErrors = 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000600 continue;
601 }
602
603 size_t Count = Sections->GetNumSections(0);
604 Printer.formatLine("Showing {0} sections", Count);
605 for (size_t I = 0; I < Count; ++I) {
606 AutoIndent Indent(Printer, 2);
607 auto S = Sections->GetSectionAtIndex(I);
608 assert(S);
609 Printer.formatLine("Index: {0}", I);
610 Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
Jan Kratochvile4777a92018-04-29 19:47:48 +0000611 Printer.formatLine("Type: {0}", S->GetTypeAsCString());
Pavel Labathe2867bc2017-12-15 14:23:58 +0000612 Printer.formatLine("VM size: {0}", S->GetByteSize());
613 Printer.formatLine("File size: {0}", S->GetFileSize());
Zachary Turner888a4282017-12-01 00:52:51 +0000614
615 if (opts::module::SectionContents) {
616 DataExtractor Data;
617 S->GetSectionData(Data);
618 ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()};
619 Printer.formatBinary("Data: ", Bytes, 0);
620 }
621 Printer.NewLine();
622 }
623 }
Pavel Labath90b0a532018-05-03 10:57:16 +0000624 return HadErrors;
Zachary Turner888a4282017-12-01 00:52:51 +0000625}
626
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000627/// Check if two half-open intervals intersect:
628/// http://world.std.com/~swmcd/steven/tech/interval.html
629bool opts::irmemorymap::areAllocationsOverlapping(const AllocationT &L,
630 const AllocationT &R) {
631 return R.first < L.second && L.first < R.second;
632}
633
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000634bool opts::irmemorymap::evalMalloc(StringRef Line,
635 IRMemoryMapTestState &State) {
636 // ::= <label> = malloc <size> <alignment>
637 StringRef Label;
638 std::tie(Label, Line) = Line.split('=');
639 if (Line.empty())
640 return false;
641 Label = Label.trim();
642 Line = Line.trim();
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000643 size_t Size;
644 uint8_t Alignment;
645 int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment);
646 if (Matches != 2)
647 return false;
648
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000649 outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label,
650 Size, Alignment);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000651 if (!isPowerOf2_32(Alignment)) {
652 outs() << "Malloc error: alignment is not a power of 2\n";
653 exit(1);
654 }
655
Vedant Kumarf616b9d2018-05-31 22:09:00 +0000656 IRMemoryMap::AllocationPolicy AP =
657 UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly
658 : IRMemoryMap::eAllocationPolicyProcessOnly;
659
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000660 // Issue the malloc in the target process with "-rw" permissions.
661 const uint32_t Permissions = 0x3;
662 const bool ZeroMemory = false;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000663 Status ST;
664 addr_t Addr =
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000665 State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000666 if (ST.Fail()) {
667 outs() << formatv("Malloc error: {0}\n", ST);
668 return true;
669 }
670
671 // Print the result of the allocation before checking its validity.
672 outs() << formatv("Malloc: address = {0:x}\n", Addr);
673
674 // Check that the allocation is aligned.
675 if (!Addr || Addr % Alignment != 0) {
676 outs() << "Malloc error: zero or unaligned allocation detected\n";
677 exit(1);
678 }
679
680 // Check that the allocation does not overlap another allocation. Do so by
681 // testing each allocation which may cover the interval [Addr, EndOfRegion).
682 addr_t EndOfRegion = Addr + Size;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000683 auto Probe = State.Allocations.begin();
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000684 Probe.advanceTo(Addr); //< First interval s.t stop >= Addr.
685 AllocationT NewAllocation = {Addr, EndOfRegion};
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000686 while (Probe != State.Allocations.end() && Probe.start() < EndOfRegion) {
Vedant Kumarf3b6d292018-05-30 19:46:47 +0000687 AllocationT ProbeAllocation = {Probe.start(), Probe.stop()};
688 if (areAllocationsOverlapping(ProbeAllocation, NewAllocation)) {
689 outs() << "Malloc error: overlapping allocation detected"
690 << formatv(", previous allocation at [{0:x}, {1:x})\n",
691 Probe.start(), Probe.stop());
692 exit(1);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000693 }
Vedant Kumarf3b6d292018-05-30 19:46:47 +0000694 ++Probe;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000695 }
696
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000697 // Insert the new allocation into the interval map. Use unique allocation IDs
698 // to inhibit interval coalescing.
699 static unsigned AllocationID = 0;
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000700 if (Size)
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000701 State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
702
703 // Store the label -> address mapping.
704 State.Label2AddrMap[Label] = Addr;
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000705
706 return true;
707}
708
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000709bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) {
710 // ::= free <label>
711 if (!Line.consume_front("free"))
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000712 return false;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000713 StringRef Label = Line.trim();
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000714
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000715 outs() << formatv("Command: free({0})\n", Label);
716 auto LabelIt = State.Label2AddrMap.find(Label);
717 if (LabelIt == State.Label2AddrMap.end()) {
718 outs() << "Free error: Invalid allocation label\n";
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000719 exit(1);
720 }
721
722 Status ST;
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000723 addr_t Addr = LabelIt->getValue();
724 State.Map.Free(Addr, ST);
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000725 if (ST.Fail()) {
726 outs() << formatv("Free error: {0}\n", ST);
727 exit(1);
728 }
729
730 // Erase the allocation from the live interval map.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000731 auto Interval = State.Allocations.find(Addr);
732 if (Interval != State.Allocations.end()) {
733 outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(),
734 Interval.stop());
735 Interval.erase();
736 }
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000737
738 return true;
739}
740
741int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
742 // Set up a Target.
743 TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target);
744
745 // Set up a Process. In order to allocate memory within a target, this
746 // process must be alive and must support JIT'ing.
747 CommandReturnObject Result;
748 Dbg.SetAsyncExecution(false);
749 CommandInterpreter &CI = Dbg.GetCommandInterpreter();
750 auto IssueCmd = [&](const char *Cmd) -> bool {
751 return CI.HandleCommand(Cmd, eLazyBoolNo, Result);
752 };
753 if (!IssueCmd("b main") || !IssueCmd("run")) {
754 outs() << formatv("Failed: {0}\n", Result.GetErrorData());
755 exit(1);
756 }
757
758 ProcessSP Process = Target->GetProcessSP();
759 if (!Process || !Process->IsAlive() || !Process->CanJIT()) {
760 outs() << "Cannot use process to test IRMemoryMap\n";
761 exit(1);
762 }
763
764 // Set up an IRMemoryMap and associated testing state.
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000765 IRMemoryMapTestState State(Target);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000766
767 // Parse and apply commands from the command file.
768 std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile);
769 StringRef Rest = MB->getBuffer();
770 while (!Rest.empty()) {
771 StringRef Line;
772 std::tie(Line, Rest) = Rest.split('\n');
773 Line = Line.ltrim();
774
775 if (Line.empty() || Line[0] == '#')
776 continue;
777
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000778 if (evalMalloc(Line, State))
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000779 continue;
780
Vedant Kumarc418b5c2018-06-04 17:11:15 +0000781 if (evalFree(Line, State))
Vedant Kumarcc5a6162018-05-31 22:09:01 +0000782 continue;
783
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000784 errs() << "Could not parse line: " << Line << "\n";
785 exit(1);
786 }
787 return 0;
788}
789
Zachary Turner888a4282017-12-01 00:52:51 +0000790int main(int argc, const char *argv[]) {
791 StringRef ToolName = argv[0];
792 sys::PrintStackTraceOnErrorSignal(ToolName);
793 PrettyStackTraceProgram X(argc, argv);
794 llvm_shutdown_obj Y;
795
796 cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
797
Pavel Labath90b0a532018-05-03 10:57:16 +0000798 SystemLifetimeManager DebuggerLifetime;
799 DebuggerLifetime.Initialize(llvm::make_unique<SystemInitializerTest>(),
800 nullptr);
801 CleanUp TerminateDebugger([&] { DebuggerLifetime.Terminate(); });
Zachary Turner888a4282017-12-01 00:52:51 +0000802
803 auto Dbg = lldb_private::Debugger::CreateInstance();
804
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000805 if (!opts::Log.empty())
806 Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, errs());
807
Pavel Labath7c945822018-02-26 18:50:16 +0000808 if (opts::BreakpointSubcommand)
Pavel Labath90b0a532018-05-03 10:57:16 +0000809 return opts::breakpoint::evaluateBreakpoints(*Dbg);
Zachary Turner888a4282017-12-01 00:52:51 +0000810 if (opts::ModuleSubcommand)
Pavel Labath90b0a532018-05-03 10:57:16 +0000811 return dumpModules(*Dbg);
812 if (opts::SymbolsSubcommand)
813 return opts::symbols::dumpSymbols(*Dbg);
Vedant Kumarc1cd8262018-05-30 19:39:10 +0000814 if (opts::IRMemoryMapSubcommand)
815 return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
Zachary Turner888a4282017-12-01 00:52:51 +0000816
Pavel Labath90b0a532018-05-03 10:57:16 +0000817 WithColor::error() << "No command specified.\n";
818 return 1;
Zachary Turner888a4282017-12-01 00:52:51 +0000819}