1 //===- lldb-test.cpp ------------------------------------------ *- C++ --*-===//
3 // 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
7 //===----------------------------------------------------------------------===//
9 #include "FormatUtil.h"
10 #include "SystemInitializerTest.h"
12 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
13 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
14 #include "lldb/Breakpoint/BreakpointLocation.h"
15 #include "lldb/Core/Debugger.h"
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/Section.h"
18 #include "lldb/Expression/IRMemoryMap.h"
19 #include "lldb/Initialization/SystemLifetimeManager.h"
20 #include "lldb/Interpreter/CommandInterpreter.h"
21 #include "lldb/Interpreter/CommandReturnObject.h"
22 #include "lldb/Symbol/CompileUnit.h"
23 #include "lldb/Symbol/LineTable.h"
24 #include "lldb/Symbol/SymbolFile.h"
25 #include "lldb/Symbol/Symtab.h"
26 #include "lldb/Symbol/TypeList.h"
27 #include "lldb/Symbol/TypeMap.h"
28 #include "lldb/Symbol/VariableList.h"
29 #include "lldb/Target/Language.h"
30 #include "lldb/Target/Process.h"
31 #include "lldb/Target/Target.h"
32 #include "lldb/Utility/DataExtractor.h"
33 #include "lldb/Utility/LLDBAssert.h"
34 #include "lldb/Utility/State.h"
35 #include "lldb/Utility/StreamString.h"
37 #include "llvm/ADT/IntervalMap.h"
38 #include "llvm/ADT/ScopeExit.h"
39 #include "llvm/ADT/StringRef.h"
40 #include "llvm/Support/CommandLine.h"
41 #include "llvm/Support/ManagedStatic.h"
42 #include "llvm/Support/MathExtras.h"
43 #include "llvm/Support/Path.h"
44 #include "llvm/Support/PrettyStackTrace.h"
45 #include "llvm/Support/Signals.h"
46 #include "llvm/Support/WithColor.h"
53 using namespace lldb_private
;
57 static cl::SubCommand
BreakpointSubcommand("breakpoints",
58 "Test breakpoint resolution");
59 cl::SubCommand
ObjectFileSubcommand("object-file",
60 "Display LLDB object file information");
61 cl::SubCommand
SymbolsSubcommand("symbols", "Dump symbols for an object file");
62 cl::SubCommand
SymTabSubcommand("symtab",
63 "Test symbol table functionality");
64 cl::SubCommand
IRMemoryMapSubcommand("ir-memory-map", "Test IRMemoryMap");
65 cl::SubCommand
AssertSubcommand("assert", "Test assert handling");
67 cl::opt
<std::string
> Log("log", cl::desc("Path to a log file"), cl::init(""),
68 cl::sub(BreakpointSubcommand
),
69 cl::sub(ObjectFileSubcommand
),
70 cl::sub(SymbolsSubcommand
),
71 cl::sub(SymTabSubcommand
),
72 cl::sub(IRMemoryMapSubcommand
));
74 /// Create a target using the file pointed to by \p Filename, or abort.
75 TargetSP
createTarget(Debugger
&Dbg
, const std::string
&Filename
);
77 /// Read \p Filename into a null-terminated buffer, or abort.
78 std::unique_ptr
<MemoryBuffer
> openFile(const std::string
&Filename
);
80 namespace breakpoint
{
81 static cl::opt
<std::string
> Target(cl::Positional
, cl::desc("<target>"),
82 cl::Required
, cl::sub(BreakpointSubcommand
));
83 static cl::opt
<std::string
> CommandFile(cl::Positional
,
84 cl::desc("<command-file>"),
86 cl::sub(BreakpointSubcommand
));
87 static cl::opt
<bool> Persistent(
89 cl::desc("Don't automatically remove all breakpoints before each command"),
90 cl::sub(BreakpointSubcommand
));
92 static llvm::StringRef
plural(uintmax_t value
) { return value
== 1 ? "" : "s"; }
93 static void dumpState(const BreakpointList
&List
, LinePrinter
&P
);
94 static std::string
substitute(StringRef Cmd
);
95 static int evaluateBreakpoints(Debugger
&Dbg
);
96 } // namespace breakpoint
99 cl::opt
<bool> SectionContents("contents",
100 cl::desc("Dump each section's contents"),
101 cl::sub(ObjectFileSubcommand
));
102 cl::opt
<bool> SectionDependentModules("dep-modules",
103 cl::desc("Dump each dependent module"),
104 cl::sub(ObjectFileSubcommand
));
105 cl::list
<std::string
> InputFilenames(cl::Positional
, cl::desc("<input files>"),
107 cl::sub(ObjectFileSubcommand
));
108 } // namespace object
112 /// The same enum as Mangled::NamePreference but with a default
113 /// 'None' case. This is needed to disambiguate wheter "ManglingPreference" was
114 /// explicitly set or not.
115 enum class ManglingPreference
{
119 MangledWithoutArguments
,
122 static cl::opt
<std::string
> FindSymbolsByRegex(
123 "find-symbols-by-regex",
125 "Dump symbols found in the symbol table matching the specified regex."),
126 cl::sub(SymTabSubcommand
));
128 static cl::opt
<ManglingPreference
> ManglingPreference(
129 "mangling-preference",
130 cl::desc("Preference on mangling scheme the regex should match against and "
133 clEnumValN(ManglingPreference::Mangled
, "mangled", "Prefer mangled"),
134 clEnumValN(ManglingPreference::Demangled
, "demangled",
136 clEnumValN(ManglingPreference::MangledWithoutArguments
,
137 "demangled-without-args", "Prefer mangled without args")),
138 cl::sub(SymTabSubcommand
));
140 static cl::opt
<std::string
> InputFile(cl::Positional
, cl::desc("<input file>"),
141 cl::Required
, cl::sub(SymTabSubcommand
));
143 /// Validate that the options passed make sense.
144 static std::optional
<llvm::Error
> validate();
146 /// Transforms the selected mangling preference into a Mangled::NamePreference
147 static Mangled::NamePreference
getNamePreference();
149 static int handleSymtabCommand(Debugger
&Dbg
);
150 } // namespace symtab
153 static cl::opt
<std::string
> InputFile(cl::Positional
, cl::desc("<input file>"),
154 cl::Required
, cl::sub(SymbolsSubcommand
));
156 static cl::opt
<std::string
>
157 SymbolPath("symbol-file",
158 cl::desc("The file from which to fetch symbol information."),
159 cl::value_desc("file"), cl::sub(SymbolsSubcommand
));
161 enum class FindType
{
169 static cl::opt
<FindType
> Find(
170 "find", cl::desc("Choose search type:"),
172 clEnumValN(FindType::None
, "none", "No search, just dump the module."),
173 clEnumValN(FindType::Function
, "function", "Find functions."),
174 clEnumValN(FindType::Block
, "block", "Find blocks."),
175 clEnumValN(FindType::Namespace
, "namespace", "Find namespaces."),
176 clEnumValN(FindType::Type
, "type", "Find types."),
177 clEnumValN(FindType::Variable
, "variable", "Find global variables.")),
178 cl::sub(SymbolsSubcommand
));
180 static cl::opt
<std::string
> Name("name", cl::desc("Name to find."),
181 cl::sub(SymbolsSubcommand
));
184 cl::desc("Search using regular expressions (available for variables "
185 "and functions only)."),
186 cl::sub(SymbolsSubcommand
));
187 static cl::opt
<std::string
>
189 cl::desc("Restrict search to the context of the given variable."),
190 cl::value_desc("variable"), cl::sub(SymbolsSubcommand
));
192 static cl::opt
<std::string
> CompilerContext(
194 cl::desc("Specify a compiler context as \"kind:name,...\"."),
195 cl::value_desc("context"), cl::sub(SymbolsSubcommand
));
197 static cl::opt
<std::string
>
198 Language("language", cl::desc("Specify a language type, like C99."),
199 cl::value_desc("language"), cl::sub(SymbolsSubcommand
));
201 static cl::list
<FunctionNameType
> FunctionNameFlags(
202 "function-flags", cl::desc("Function search flags:"),
203 cl::values(clEnumValN(eFunctionNameTypeAuto
, "auto",
204 "Automatically deduce flags based on name."),
205 clEnumValN(eFunctionNameTypeFull
, "full", "Full function name."),
206 clEnumValN(eFunctionNameTypeBase
, "base", "Base name."),
207 clEnumValN(eFunctionNameTypeMethod
, "method", "Method name."),
208 clEnumValN(eFunctionNameTypeSelector
, "selector",
210 cl::sub(SymbolsSubcommand
));
211 static FunctionNameType
getFunctionNameFlags() {
212 FunctionNameType Result
= FunctionNameType(0);
213 for (FunctionNameType Flag
: FunctionNameFlags
)
214 Result
= FunctionNameType(Result
| Flag
);
218 static cl::opt
<bool> DumpAST("dump-ast",
219 cl::desc("Dump AST restored from symbols."),
220 cl::sub(SymbolsSubcommand
));
221 static cl::opt
<bool> DumpClangAST(
223 cl::desc("Dump clang AST restored from symbols. When used on its own this "
224 "will dump the entire AST of all loaded symbols. When combined "
225 "with -find, it changes the presentation of the search results "
226 "from pretty-printing the types to an AST dump."),
227 cl::sub(SymbolsSubcommand
));
229 static cl::opt
<bool> Verify("verify", cl::desc("Verify symbol information."),
230 cl::sub(SymbolsSubcommand
));
232 static cl::opt
<std::string
> File("file",
233 cl::desc("File (compile unit) to search."),
234 cl::sub(SymbolsSubcommand
));
235 static cl::opt
<int> Line("line", cl::desc("Line to search."),
236 cl::sub(SymbolsSubcommand
));
238 static Expected
<CompilerDeclContext
> getDeclContext(SymbolFile
&Symfile
);
240 static Error
findFunctions(lldb_private::Module
&Module
);
241 static Error
findBlocks(lldb_private::Module
&Module
);
242 static Error
findNamespaces(lldb_private::Module
&Module
);
243 static Error
findTypes(lldb_private::Module
&Module
);
244 static Error
findVariables(lldb_private::Module
&Module
);
245 static Error
dumpModule(lldb_private::Module
&Module
);
246 static Error
dumpAST(lldb_private::Module
&Module
);
247 static Error
dumpEntireClangAST(lldb_private::Module
&Module
);
248 static Error
verify(lldb_private::Module
&Module
);
250 static Expected
<Error (*)(lldb_private::Module
&)> getAction();
251 static int dumpSymbols(Debugger
&Dbg
);
252 } // namespace symbols
254 namespace irmemorymap
{
255 static cl::opt
<std::string
> Target(cl::Positional
, cl::desc("<target>"),
257 cl::sub(IRMemoryMapSubcommand
));
258 static cl::opt
<std::string
> CommandFile(cl::Positional
,
259 cl::desc("<command-file>"),
261 cl::sub(IRMemoryMapSubcommand
));
262 static cl::opt
<bool> UseHostOnlyAllocationPolicy(
263 "host-only", cl::desc("Use the host-only allocation policy"),
264 cl::init(false), cl::sub(IRMemoryMapSubcommand
));
266 using AllocationT
= std::pair
<addr_t
, addr_t
>;
267 using AddrIntervalMap
=
268 IntervalMap
<addr_t
, unsigned, 8, IntervalMapHalfOpenInfo
<addr_t
>>;
270 struct IRMemoryMapTestState
{
274 AddrIntervalMap::Allocator IntervalMapAllocator
;
275 AddrIntervalMap Allocations
;
277 StringMap
<addr_t
> Label2AddrMap
;
279 IRMemoryMapTestState(TargetSP Target
)
280 : Target(Target
), Map(Target
), Allocations(IntervalMapAllocator
) {}
283 bool evalMalloc(StringRef Line
, IRMemoryMapTestState
&State
);
284 bool evalFree(StringRef Line
, IRMemoryMapTestState
&State
);
285 int evaluateMemoryMapCommands(Debugger
&Dbg
);
286 } // namespace irmemorymap
289 int lldb_assert(Debugger
&Dbg
);
290 } // namespace assert
293 std::vector
<CompilerContext
> parseCompilerContext() {
294 std::vector
<CompilerContext
> result
;
295 if (opts::symbols::CompilerContext
.empty())
298 StringRef str
{opts::symbols::CompilerContext
};
299 SmallVector
<StringRef
, 8> entries_str
;
300 str
.split(entries_str
, ',', /*maxSplit*/-1, /*keepEmpty=*/false);
301 for (auto entry_str
: entries_str
) {
302 StringRef key
, value
;
303 std::tie(key
, value
) = entry_str
.split(':');
305 StringSwitch
<CompilerContextKind
>(key
)
306 .Case("TranslationUnit", CompilerContextKind::TranslationUnit
)
307 .Case("Module", CompilerContextKind::Module
)
308 .Case("Namespace", CompilerContextKind::Namespace
)
309 .Case("Class", CompilerContextKind::Class
)
310 .Case("Struct", CompilerContextKind::Struct
)
311 .Case("Union", CompilerContextKind::Union
)
312 .Case("Function", CompilerContextKind::Function
)
313 .Case("Variable", CompilerContextKind::Variable
)
314 .Case("Enum", CompilerContextKind::Enum
)
315 .Case("Typedef", CompilerContextKind::Typedef
)
316 .Case("AnyModule", CompilerContextKind::AnyModule
)
317 .Case("AnyType", CompilerContextKind::AnyType
)
318 .Default(CompilerContextKind::Invalid
);
320 WithColor::error() << "compiler context entry has no \"name\"\n";
323 result
.push_back({kind
, ConstString
{value
}});
325 outs() << "Search context: {";
326 lldb_private::StreamString s
;
327 llvm::interleaveComma(result
, s
, [&](auto &ctx
) { ctx
.Dump(s
); });
328 outs() << s
.GetString().str() << "}\n";
333 template <typename
... Args
>
334 static Error
make_string_error(const char *Format
, Args
&&... args
) {
335 return llvm::make_error
<llvm::StringError
>(
336 llvm::formatv(Format
, std::forward
<Args
>(args
)...).str(),
337 llvm::inconvertibleErrorCode());
340 TargetSP
opts::createTarget(Debugger
&Dbg
, const std::string
&Filename
) {
342 Status ST
= Dbg
.GetTargetList().CreateTarget(
343 Dbg
, Filename
, /*triple*/ "", eLoadDependentsNo
,
344 /*platform_options*/ nullptr, Target
);
346 errs() << formatv("Failed to create target '{0}: {1}\n", Filename
, ST
);
352 std::unique_ptr
<MemoryBuffer
> opts::openFile(const std::string
&Filename
) {
353 auto MB
= MemoryBuffer::getFileOrSTDIN(Filename
);
355 errs() << formatv("Could not open file '{0}: {1}\n", Filename
,
356 MB
.getError().message());
359 return std::move(*MB
);
362 void opts::breakpoint::dumpState(const BreakpointList
&List
, LinePrinter
&P
) {
363 P
.formatLine("{0} breakpoint{1}", List
.GetSize(), plural(List
.GetSize()));
364 if (List
.GetSize() > 0)
365 P
.formatLine("At least one breakpoint.");
366 for (size_t i
= 0, e
= List
.GetSize(); i
< e
; ++i
) {
367 BreakpointSP BP
= List
.GetBreakpointAtIndex(i
);
368 P
.formatLine("Breakpoint ID {0}:", BP
->GetID());
369 AutoIndent
Indent(P
, 2);
370 P
.formatLine("{0} location{1}.", BP
->GetNumLocations(),
371 plural(BP
->GetNumLocations()));
372 if (BP
->GetNumLocations() > 0)
373 P
.formatLine("At least one location.");
374 P
.formatLine("{0} resolved location{1}.", BP
->GetNumResolvedLocations(),
375 plural(BP
->GetNumResolvedLocations()));
376 if (BP
->GetNumResolvedLocations() > 0)
377 P
.formatLine("At least one resolved location.");
378 for (size_t l
= 0, le
= BP
->GetNumLocations(); l
< le
; ++l
) {
379 BreakpointLocationSP Loc
= BP
->GetLocationAtIndex(l
);
380 P
.formatLine("Location ID {0}:", Loc
->GetID());
381 AutoIndent
Indent(P
, 2);
382 P
.formatLine("Enabled: {0}", Loc
->IsEnabled());
383 P
.formatLine("Resolved: {0}", Loc
->IsResolved());
385 Loc
->GetAddress().CalculateSymbolContext(&sc
);
386 lldb_private::StreamString S
;
387 sc
.DumpStopContext(&S
, BP
->GetTarget().GetProcessSP().get(),
388 Loc
->GetAddress(), false, true, false, true, true);
389 P
.formatLine("Address: {0}", S
.GetString());
395 std::string
opts::breakpoint::substitute(StringRef Cmd
) {
397 raw_string_ostream
OS(Result
);
398 while (!Cmd
.empty()) {
401 if (Cmd
.consume_front("%p") && (Cmd
.empty() || !isalnum(Cmd
[0]))) {
402 OS
<< sys::path::parent_path(breakpoint::CommandFile
);
407 size_t pos
= Cmd
.find('%');
408 OS
<< Cmd
.substr(0, pos
);
409 Cmd
= Cmd
.substr(pos
);
413 return std::move(OS
.str());
416 int opts::breakpoint::evaluateBreakpoints(Debugger
&Dbg
) {
417 TargetSP Target
= opts::createTarget(Dbg
, breakpoint::Target
);
418 std::unique_ptr
<MemoryBuffer
> MB
= opts::openFile(breakpoint::CommandFile
);
420 LinePrinter
P(4, outs());
421 StringRef Rest
= MB
->getBuffer();
423 while (!Rest
.empty()) {
425 std::tie(Line
, Rest
) = Rest
.split('\n');
426 Line
= Line
.ltrim().rtrim();
427 if (Line
.empty() || Line
[0] == '#')
431 Target
->RemoveAllBreakpoints(/*internal_also*/ true);
433 std::string Command
= substitute(Line
);
434 P
.formatLine("Command: {0}", Command
);
435 CommandReturnObject
Result(/*colors*/ false);
436 if (!Dbg
.GetCommandInterpreter().HandleCommand(
437 Command
.c_str(), /*add_to_history*/ eLazyBoolNo
, Result
)) {
438 P
.formatLine("Failed: {0}", Result
.GetErrorData());
443 dumpState(Target
->GetBreakpointList(/*internal*/ false), P
);
448 Expected
<CompilerDeclContext
>
449 opts::symbols::getDeclContext(SymbolFile
&Symfile
) {
451 return CompilerDeclContext();
453 Symfile
.FindGlobalVariables(ConstString(Context
), CompilerDeclContext(),
456 return make_string_error("Context search didn't find a match.");
457 if (List
.GetSize() > 1)
458 return make_string_error("Context search found multiple matches.");
459 return List
.GetVariableAtIndex(0)->GetDeclContext();
462 static lldb::DescriptionLevel
GetDescriptionLevel() {
463 return opts::symbols::DumpClangAST
? eDescriptionLevelVerbose
: eDescriptionLevelFull
;
466 Error
opts::symbols::findFunctions(lldb_private::Module
&Module
) {
467 SymbolFile
&Symfile
= *Module
.GetSymbolFile();
468 SymbolContextList List
;
472 FileSpec
src_file(File
);
473 size_t cu_count
= Module
.GetNumCompileUnits();
474 for (size_t i
= 0; i
< cu_count
; i
++) {
475 lldb::CompUnitSP cu_sp
= Module
.GetCompileUnitAtIndex(i
);
480 cu_sp
->FindLineEntry(0, Line
, &src_file
, false, &le
);
483 const bool include_inlined_functions
= false;
485 le
.GetSameLineContiguousAddressRange(include_inlined_functions
)
492 addr
.CalculateSymbolContext(&sc
, eSymbolContextFunction
);
493 if (resolved
& eSymbolContextFunction
)
497 RegularExpression
RE(Name
);
498 assert(RE
.IsValid());
500 Symfile
.FindFunctions(RE
, true, List
);
502 Expected
<CompilerDeclContext
> ContextOr
= getDeclContext(Symfile
);
504 return ContextOr
.takeError();
505 const CompilerDeclContext
&ContextPtr
=
506 ContextOr
->IsValid() ? *ContextOr
: CompilerDeclContext();
509 Module::LookupInfo
lookup_info(ConstString(Name
), getFunctionNameFlags(),
510 eLanguageTypeUnknown
);
511 Symfile
.FindFunctions(lookup_info
, ContextPtr
, true, List
);
513 outs() << formatv("Found {0} functions:\n", List
.GetSize());
515 List
.Dump(&Stream
, nullptr);
516 outs() << Stream
.GetData() << "\n";
517 return Error::success();
520 Error
opts::symbols::findBlocks(lldb_private::Module
&Module
) {
522 assert(!File
.empty());
525 SymbolContextList List
;
527 FileSpec
src_file(File
);
528 size_t cu_count
= Module
.GetNumCompileUnits();
529 for (size_t i
= 0; i
< cu_count
; i
++) {
530 lldb::CompUnitSP cu_sp
= Module
.GetCompileUnitAtIndex(i
);
535 cu_sp
->FindLineEntry(0, Line
, &src_file
, false, &le
);
538 const bool include_inlined_functions
= false;
539 auto addr
= le
.GetSameLineContiguousAddressRange(include_inlined_functions
)
545 uint32_t resolved
= addr
.CalculateSymbolContext(&sc
, eSymbolContextBlock
);
546 if (resolved
& eSymbolContextBlock
)
550 outs() << formatv("Found {0} blocks:\n", List
.GetSize());
552 List
.Dump(&Stream
, nullptr);
553 outs() << Stream
.GetData() << "\n";
554 return Error::success();
557 Error
opts::symbols::findNamespaces(lldb_private::Module
&Module
) {
558 SymbolFile
&Symfile
= *Module
.GetSymbolFile();
559 Expected
<CompilerDeclContext
> ContextOr
= getDeclContext(Symfile
);
561 return ContextOr
.takeError();
562 const CompilerDeclContext
&ContextPtr
=
563 ContextOr
->IsValid() ? *ContextOr
: CompilerDeclContext();
565 CompilerDeclContext Result
=
566 Symfile
.FindNamespace(ConstString(Name
), ContextPtr
);
568 outs() << "Found namespace: "
569 << Result
.GetScopeQualifiedName().GetStringRef() << "\n";
571 outs() << "Namespace not found.\n";
572 return Error::success();
575 Error
opts::symbols::findTypes(lldb_private::Module
&Module
) {
576 SymbolFile
&Symfile
= *Module
.GetSymbolFile();
577 Expected
<CompilerDeclContext
> ContextOr
= getDeclContext(Symfile
);
579 return ContextOr
.takeError();
580 const CompilerDeclContext
&ContextPtr
=
581 ContextOr
->IsValid() ? *ContextOr
: CompilerDeclContext();
583 LanguageSet languages
;
584 if (!Language
.empty())
585 languages
.Insert(Language::GetLanguageTypeFromString(Language
));
587 DenseSet
<SymbolFile
*> SearchedFiles
;
590 Symfile
.FindTypes(ConstString(Name
), ContextPtr
, UINT32_MAX
, SearchedFiles
,
593 Module
.FindTypes(parseCompilerContext(), languages
, SearchedFiles
, Map
);
595 outs() << formatv("Found {0} types:\n", Map
.GetSize());
597 // Resolve types to force-materialize typedef types.
598 Map
.ForEach([&](TypeSP
&type
) {
599 type
->GetFullCompilerType();
602 Map
.Dump(&Stream
, false, GetDescriptionLevel());
603 outs() << Stream
.GetData() << "\n";
604 return Error::success();
607 Error
opts::symbols::findVariables(lldb_private::Module
&Module
) {
608 SymbolFile
&Symfile
= *Module
.GetSymbolFile();
611 RegularExpression
RE(Name
);
612 assert(RE
.IsValid());
613 Symfile
.FindGlobalVariables(RE
, UINT32_MAX
, List
);
614 } else if (!File
.empty()) {
616 for (size_t Ind
= 0; !CU
&& Ind
< Module
.GetNumCompileUnits(); ++Ind
) {
617 CompUnitSP Candidate
= Module
.GetCompileUnitAtIndex(Ind
);
619 Candidate
->GetPrimaryFile().GetFilename().GetStringRef() != File
)
622 return make_string_error("Multiple compile units for file `{0}` found.",
624 CU
= std::move(Candidate
);
628 return make_string_error("Compile unit `{0}` not found.", File
);
630 List
.AddVariables(CU
->GetVariableList(true).get());
632 Expected
<CompilerDeclContext
> ContextOr
= getDeclContext(Symfile
);
634 return ContextOr
.takeError();
635 const CompilerDeclContext
&ContextPtr
=
636 ContextOr
->IsValid() ? *ContextOr
: CompilerDeclContext();
638 Symfile
.FindGlobalVariables(ConstString(Name
), ContextPtr
, UINT32_MAX
, List
);
640 outs() << formatv("Found {0} variables:\n", List
.GetSize());
642 List
.Dump(&Stream
, false);
643 outs() << Stream
.GetData() << "\n";
644 return Error::success();
647 Error
opts::symbols::dumpModule(lldb_private::Module
&Module
) {
649 Module
.ParseAllDebugSymbols();
650 Module
.Dump(&Stream
);
651 outs() << Stream
.GetData() << "\n";
652 return Error::success();
655 Error
opts::symbols::dumpAST(lldb_private::Module
&Module
) {
656 Module
.ParseAllDebugSymbols();
658 SymbolFile
*symfile
= Module
.GetSymbolFile();
660 return make_string_error("Module has no symbol file.");
662 auto type_system_or_err
=
663 symfile
->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus
);
664 if (!type_system_or_err
)
665 return make_string_error("Can't retrieve TypeSystemClang");
667 auto ts
= *type_system_or_err
;
668 auto *clang_ast_ctx
= llvm::dyn_cast_or_null
<TypeSystemClang
>(ts
.get());
670 return make_string_error("Retrieved TypeSystem was not a TypeSystemClang");
672 clang::ASTContext
&ast_ctx
= clang_ast_ctx
->getASTContext();
674 clang::TranslationUnitDecl
*tu
= ast_ctx
.getTranslationUnitDecl();
676 return make_string_error("Can't retrieve translation unit declaration.");
680 return Error::success();
683 Error
opts::symbols::dumpEntireClangAST(lldb_private::Module
&Module
) {
684 Module
.ParseAllDebugSymbols();
686 SymbolFile
*symfile
= Module
.GetSymbolFile();
688 return make_string_error("Module has no symbol file.");
690 auto type_system_or_err
=
691 symfile
->GetTypeSystemForLanguage(eLanguageTypeObjC_plus_plus
);
692 if (!type_system_or_err
)
693 return make_string_error("Can't retrieve TypeSystemClang");
694 auto ts
= *type_system_or_err
;
695 auto *clang_ast_ctx
= llvm::dyn_cast_or_null
<TypeSystemClang
>(ts
.get());
697 return make_string_error("Retrieved TypeSystem was not a TypeSystemClang");
700 clang_ast_ctx
->DumpFromSymbolFile(Stream
, Name
);
701 outs() << Stream
.GetData() << "\n";
703 return Error::success();
706 Error
opts::symbols::verify(lldb_private::Module
&Module
) {
707 SymbolFile
*symfile
= Module
.GetSymbolFile();
709 return make_string_error("Module has no symbol file.");
711 uint32_t comp_units_count
= symfile
->GetNumCompileUnits();
713 outs() << "Found " << comp_units_count
<< " compile units.\n";
715 for (uint32_t i
= 0; i
< comp_units_count
; i
++) {
716 lldb::CompUnitSP comp_unit
= symfile
->GetCompileUnitAtIndex(i
);
718 return make_string_error("Cannot parse compile unit {0}.", i
);
720 outs() << "Processing '"
721 << comp_unit
->GetPrimaryFile().GetFilename().AsCString()
722 << "' compile unit.\n";
724 LineTable
*lt
= comp_unit
->GetLineTable();
726 return make_string_error("Can't get a line table of a compile unit.");
728 uint32_t count
= lt
->GetSize();
730 outs() << "The line table contains " << count
<< " entries.\n";
736 if (!lt
->GetLineEntryAtIndex(0, le
))
737 return make_string_error("Can't get a line entry of a compile unit.");
739 for (uint32_t i
= 1; i
< count
; i
++) {
740 lldb::addr_t curr_end
=
741 le
.range
.GetBaseAddress().GetFileAddress() + le
.range
.GetByteSize();
743 if (!lt
->GetLineEntryAtIndex(i
, le
))
744 return make_string_error("Can't get a line entry of a compile unit");
746 if (curr_end
> le
.range
.GetBaseAddress().GetFileAddress())
747 return make_string_error(
748 "Line table of a compile unit is inconsistent.");
752 outs() << "The symbol information is verified.\n";
754 return Error::success();
757 Expected
<Error (*)(lldb_private::Module
&)> opts::symbols::getAction() {
758 if (Verify
&& DumpAST
)
759 return make_string_error(
760 "Cannot both verify symbol information and dump AST.");
763 if (Find
!= FindType::None
)
764 return make_string_error(
765 "Cannot both search and verify symbol information.");
766 if (Regex
|| !Context
.empty() || !Name
.empty() || !File
.empty() ||
768 return make_string_error(
769 "-regex, -context, -name, -file and -line options are not "
770 "applicable for symbol verification.");
775 if (Find
!= FindType::None
)
776 return make_string_error("Cannot both search and dump AST.");
777 if (Regex
|| !Context
.empty() || !Name
.empty() || !File
.empty() ||
779 return make_string_error(
780 "-regex, -context, -name, -file and -line options are not "
781 "applicable for dumping AST.");
786 if (Find
== FindType::None
) {
787 if (Regex
|| !Context
.empty() || !File
.empty() || Line
!= 0)
788 return make_string_error(
789 "-regex, -context, -name, -file and -line options are not "
790 "applicable for dumping the entire clang AST. Either combine with "
791 "-find, or use -dump-clang-ast as a standalone option.");
792 return dumpEntireClangAST
;
794 if (Find
!= FindType::Type
)
795 return make_string_error("This combination of -dump-clang-ast and -find "
796 "<kind> is not yet implemented.");
799 if (Regex
&& !Context
.empty())
800 return make_string_error(
801 "Cannot search using both regular expressions and context.");
803 if (Regex
&& !RegularExpression(Name
).IsValid())
804 return make_string_error("`{0}` is not a valid regular expression.", Name
);
806 if (Regex
+ !Context
.empty() + !File
.empty() >= 2)
807 return make_string_error(
808 "Only one of -regex, -context and -file may be used simultaneously.");
809 if (Regex
&& Name
.empty())
810 return make_string_error("-regex used without a -name");
814 if (!Context
.empty() || !Name
.empty() || !File
.empty() || Line
!= 0)
815 return make_string_error(
816 "Specify search type (-find) to use search options.");
819 case FindType::Function
:
820 if (!File
.empty() + (Line
!= 0) == 1)
821 return make_string_error("Both file name and line number must be "
822 "specified when searching a function "
823 "by file position.");
824 if (Regex
+ (getFunctionNameFlags() != 0) + !File
.empty() >= 2)
825 return make_string_error("Only one of regular expression, function-flags "
826 "and file position may be used simultaneously "
827 "when searching a function.");
828 return findFunctions
;
830 case FindType::Block
:
831 if (File
.empty() || Line
== 0)
832 return make_string_error("Both file name and line number must be "
833 "specified when searching a block.");
834 if (Regex
|| getFunctionNameFlags() != 0)
835 return make_string_error("Cannot use regular expression or "
836 "function-flags for searching a block.");
839 case FindType::Namespace
:
840 if (Regex
|| !File
.empty() || Line
!= 0)
841 return make_string_error("Cannot search for namespaces using regular "
842 "expressions, file names or line numbers.");
843 return findNamespaces
;
846 if (Regex
|| !File
.empty() || Line
!= 0)
847 return make_string_error("Cannot search for types using regular "
848 "expressions, file names or line numbers.");
849 if (!Name
.empty() && !CompilerContext
.empty())
850 return make_string_error("Name is ignored if compiler context present.");
854 case FindType::Variable
:
856 return make_string_error("Cannot search for variables "
857 "using line numbers.");
858 return findVariables
;
861 llvm_unreachable("Unsupported symbol action.");
864 std::optional
<llvm::Error
> opts::symtab::validate() {
865 if (ManglingPreference
!= ManglingPreference::None
&&
866 FindSymbolsByRegex
.empty())
867 return make_string_error("Mangling preference set but no regex specified.");
872 static Mangled::NamePreference
opts::symtab::getNamePreference() {
873 switch (ManglingPreference
) {
874 case ManglingPreference::None
:
875 case ManglingPreference::Mangled
:
876 return Mangled::ePreferMangled
;
877 case ManglingPreference::Demangled
:
878 return Mangled::ePreferDemangled
;
879 case ManglingPreference::MangledWithoutArguments
:
880 return Mangled::ePreferDemangledWithoutArguments
;
882 llvm_unreachable("Fully covered switch above!");
885 int opts::symtab::handleSymtabCommand(Debugger
&Dbg
) {
886 if (auto error
= validate()) {
887 logAllUnhandledErrors(std::move(*error
), WithColor::error(), "");
891 if (!FindSymbolsByRegex
.empty()) {
892 ModuleSpec Spec
{FileSpec(InputFile
)};
894 auto ModulePtr
= std::make_shared
<lldb_private::Module
>(Spec
);
895 auto *Symtab
= ModulePtr
->GetSymtab();
896 auto NamePreference
= getNamePreference();
897 std::vector
<uint32_t> Indexes
;
899 Symtab
->FindAllSymbolsMatchingRexExAndType(
900 RegularExpression(FindSymbolsByRegex
), lldb::eSymbolTypeAny
,
901 Symtab::eDebugAny
, Symtab::eVisibilityAny
, Indexes
, NamePreference
);
902 for (auto i
: Indexes
) {
903 auto *symbol
= Symtab
->SymbolAtIndex(i
);
906 symbol
->Dump(&stream
, nullptr, i
, NamePreference
);
907 outs() << stream
.GetString();
915 int opts::symbols::dumpSymbols(Debugger
&Dbg
) {
916 auto ActionOr
= getAction();
918 logAllUnhandledErrors(ActionOr
.takeError(), WithColor::error(), "");
921 auto Action
= *ActionOr
;
923 outs() << "Module: " << InputFile
<< "\n";
924 ModuleSpec Spec
{FileSpec(InputFile
)};
925 StringRef Symbols
= SymbolPath
.empty() ? InputFile
: SymbolPath
;
926 Spec
.GetSymbolFileSpec().SetFile(Symbols
, FileSpec::Style::native
);
928 auto ModulePtr
= std::make_shared
<lldb_private::Module
>(Spec
);
929 SymbolFile
*Symfile
= ModulePtr
->GetSymbolFile();
931 WithColor::error() << "Module has no symbol vendor.\n";
935 if (Error E
= Action(*ModulePtr
)) {
936 WithColor::error() << toString(std::move(E
)) << "\n";
943 static void dumpSectionList(LinePrinter
&Printer
, const SectionList
&List
, bool is_subsection
) {
944 size_t Count
= List
.GetNumSections(0);
946 Printer
.formatLine("There are no {0}sections", is_subsection
? "sub" : "");
949 Printer
.formatLine("Showing {0} {1}sections", Count
,
950 is_subsection
? "sub" : "");
951 for (size_t I
= 0; I
< Count
; ++I
) {
952 auto S
= List
.GetSectionAtIndex(I
);
954 AutoIndent
Indent(Printer
, 2);
955 Printer
.formatLine("Index: {0}", I
);
956 Printer
.formatLine("ID: {0:x}", S
->GetID());
957 Printer
.formatLine("Name: {0}", S
->GetName().GetStringRef());
958 Printer
.formatLine("Type: {0}", S
->GetTypeAsCString());
959 Printer
.formatLine("Permissions: {0}", GetPermissionsAsCString(S
->GetPermissions()));
960 Printer
.formatLine("Thread specific: {0:y}", S
->IsThreadSpecific());
961 Printer
.formatLine("VM address: {0:x}", S
->GetFileAddress());
962 Printer
.formatLine("VM size: {0}", S
->GetByteSize());
963 Printer
.formatLine("File size: {0}", S
->GetFileSize());
965 if (opts::object::SectionContents
) {
966 lldb_private::DataExtractor Data
;
967 S
->GetSectionData(Data
);
968 ArrayRef
<uint8_t> Bytes(Data
.GetDataStart(), Data
.GetDataEnd());
969 Printer
.formatBinary("Data: ", Bytes
, 0);
972 if (S
->GetType() == eSectionTypeContainer
)
973 dumpSectionList(Printer
, S
->GetChildren(), true);
978 static int dumpObjectFiles(Debugger
&Dbg
) {
979 LinePrinter
Printer(4, llvm::outs());
982 for (const auto &File
: opts::object::InputFilenames
) {
983 ModuleSpec Spec
{FileSpec(File
)};
985 auto ModulePtr
= std::make_shared
<lldb_private::Module
>(Spec
);
987 ObjectFile
*ObjectPtr
= ModulePtr
->GetObjectFile();
989 WithColor::error() << File
<< " not recognised as an object file\n";
994 // Fetch symbol vendor before we get the section list to give the symbol
995 // vendor a chance to populate it.
996 ModulePtr
->GetSymbolFile();
997 SectionList
*Sections
= ModulePtr
->GetSectionList();
999 llvm::errs() << "Could not load sections for module " << File
<< "\n";
1004 Printer
.formatLine("Plugin name: {0}", ObjectPtr
->GetPluginName());
1005 Printer
.formatLine("Architecture: {0}",
1006 ModulePtr
->GetArchitecture().GetTriple().getTriple());
1007 Printer
.formatLine("UUID: {0}", ModulePtr
->GetUUID().GetAsString());
1008 Printer
.formatLine("Executable: {0}", ObjectPtr
->IsExecutable());
1009 Printer
.formatLine("Stripped: {0}", ObjectPtr
->IsStripped());
1010 Printer
.formatLine("Type: {0}", ObjectPtr
->GetType());
1011 Printer
.formatLine("Strata: {0}", ObjectPtr
->GetStrata());
1012 Printer
.formatLine("Base VM address: {0:x}",
1013 ObjectPtr
->GetBaseAddress().GetFileAddress());
1015 dumpSectionList(Printer
, *Sections
, /*is_subsection*/ false);
1017 if (opts::object::SectionDependentModules
) {
1018 // A non-empty section list ensures a valid object file.
1019 auto Obj
= ModulePtr
->GetObjectFile();
1021 auto Count
= Obj
->GetDependentModules(Files
);
1022 Printer
.formatLine("Showing {0} dependent module(s)", Count
);
1023 for (size_t I
= 0; I
< Files
.GetSize(); ++I
) {
1024 AutoIndent
Indent(Printer
, 2);
1025 Printer
.formatLine("Name: {0}",
1026 Files
.GetFileSpecAtIndex(I
).GetPath());
1034 bool opts::irmemorymap::evalMalloc(StringRef Line
,
1035 IRMemoryMapTestState
&State
) {
1036 // ::= <label> = malloc <size> <alignment>
1038 std::tie(Label
, Line
) = Line
.split('=');
1041 Label
= Label
.trim();
1045 int Matches
= sscanf(Line
.data(), "malloc %zu %hhu", &Size
, &Alignment
);
1049 outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label
,
1051 if (!isPowerOf2_32(Alignment
)) {
1052 outs() << "Malloc error: alignment is not a power of 2\n";
1056 IRMemoryMap::AllocationPolicy AP
=
1057 UseHostOnlyAllocationPolicy
? IRMemoryMap::eAllocationPolicyHostOnly
1058 : IRMemoryMap::eAllocationPolicyProcessOnly
;
1060 // Issue the malloc in the target process with "-rw" permissions.
1061 const uint32_t Permissions
= 0x3;
1062 const bool ZeroMemory
= false;
1065 State
.Map
.Malloc(Size
, Alignment
, Permissions
, AP
, ZeroMemory
, ST
);
1067 outs() << formatv("Malloc error: {0}\n", ST
);
1071 // Print the result of the allocation before checking its validity.
1072 outs() << formatv("Malloc: address = {0:x}\n", Addr
);
1074 // Check that the allocation is aligned.
1075 if (!Addr
|| Addr
% Alignment
!= 0) {
1076 outs() << "Malloc error: zero or unaligned allocation detected\n";
1080 // In case of Size == 0, we still expect the returned address to be unique and
1082 addr_t EndOfRegion
= Addr
+ std::max
<size_t>(Size
, 1);
1083 if (State
.Allocations
.overlaps(Addr
, EndOfRegion
)) {
1084 auto I
= State
.Allocations
.find(Addr
);
1085 outs() << "Malloc error: overlapping allocation detected"
1086 << formatv(", previous allocation at [{0:x}, {1:x})\n", I
.start(),
1091 // Insert the new allocation into the interval map. Use unique allocation
1092 // IDs to inhibit interval coalescing.
1093 static unsigned AllocationID
= 0;
1094 State
.Allocations
.insert(Addr
, EndOfRegion
, AllocationID
++);
1096 // Store the label -> address mapping.
1097 State
.Label2AddrMap
[Label
] = Addr
;
1102 bool opts::irmemorymap::evalFree(StringRef Line
, IRMemoryMapTestState
&State
) {
1104 if (!Line
.consume_front("free"))
1106 StringRef Label
= Line
.trim();
1108 outs() << formatv("Command: free({0})\n", Label
);
1109 auto LabelIt
= State
.Label2AddrMap
.find(Label
);
1110 if (LabelIt
== State
.Label2AddrMap
.end()) {
1111 outs() << "Free error: Invalid allocation label\n";
1116 addr_t Addr
= LabelIt
->getValue();
1117 State
.Map
.Free(Addr
, ST
);
1119 outs() << formatv("Free error: {0}\n", ST
);
1123 // Erase the allocation from the live interval map.
1124 auto Interval
= State
.Allocations
.find(Addr
);
1125 if (Interval
!= State
.Allocations
.end()) {
1126 outs() << formatv("Free: [{0:x}, {1:x})\n", Interval
.start(),
1134 int opts::irmemorymap::evaluateMemoryMapCommands(Debugger
&Dbg
) {
1136 TargetSP Target
= opts::createTarget(Dbg
, irmemorymap::Target
);
1138 // Set up a Process. In order to allocate memory within a target, this
1139 // process must be alive and must support JIT'ing.
1140 CommandReturnObject
Result(/*colors*/ false);
1141 Dbg
.SetAsyncExecution(false);
1142 CommandInterpreter
&CI
= Dbg
.GetCommandInterpreter();
1143 auto IssueCmd
= [&](const char *Cmd
) -> bool {
1144 return CI
.HandleCommand(Cmd
, eLazyBoolNo
, Result
);
1146 if (!IssueCmd("b main") || !IssueCmd("run")) {
1147 outs() << formatv("Failed: {0}\n", Result
.GetErrorData());
1151 ProcessSP Process
= Target
->GetProcessSP();
1152 if (!Process
|| !Process
->IsAlive() || !Process
->CanJIT()) {
1153 outs() << "Cannot use process to test IRMemoryMap\n";
1157 // Set up an IRMemoryMap and associated testing state.
1158 IRMemoryMapTestState
State(Target
);
1160 // Parse and apply commands from the command file.
1161 std::unique_ptr
<MemoryBuffer
> MB
= opts::openFile(irmemorymap::CommandFile
);
1162 StringRef Rest
= MB
->getBuffer();
1163 while (!Rest
.empty()) {
1165 std::tie(Line
, Rest
) = Rest
.split('\n');
1166 Line
= Line
.ltrim().rtrim();
1168 if (Line
.empty() || Line
[0] == '#')
1171 if (evalMalloc(Line
, State
))
1174 if (evalFree(Line
, State
))
1177 errs() << "Could not parse line: " << Line
<< "\n";
1183 int opts::assert::lldb_assert(Debugger
&Dbg
) {
1184 lldbassert(false && "lldb-test assert");
1188 int main(int argc
, const char *argv
[]) {
1189 StringRef ToolName
= argv
[0];
1190 sys::PrintStackTraceOnErrorSignal(ToolName
);
1191 PrettyStackTraceProgram
X(argc
, argv
);
1192 llvm_shutdown_obj Y
;
1194 cl::ParseCommandLineOptions(argc
, argv
, "LLDB Testing Utility\n");
1196 SystemLifetimeManager DebuggerLifetime
;
1197 if (auto e
= DebuggerLifetime
.Initialize(
1198 std::make_unique
<SystemInitializerTest
>(), nullptr)) {
1199 WithColor::error() << "initialization failed: " << toString(std::move(e
))
1204 auto TerminateDebugger
=
1205 llvm::make_scope_exit([&] { DebuggerLifetime
.Terminate(); });
1207 auto Dbg
= lldb_private::Debugger::CreateInstance();
1208 ModuleList::GetGlobalModuleListProperties().SetEnableExternalLookup(false);
1209 CommandReturnObject
Result(/*colors*/ false);
1210 Dbg
->GetCommandInterpreter().HandleCommand(
1211 "settings set plugin.process.gdb-remote.packet-timeout 60",
1212 /*add_to_history*/ eLazyBoolNo
, Result
);
1213 Dbg
->GetCommandInterpreter().HandleCommand(
1214 "settings set target.inherit-tcc true",
1215 /*add_to_history*/ eLazyBoolNo
, Result
);
1216 Dbg
->GetCommandInterpreter().HandleCommand(
1217 "settings set target.detach-on-error false",
1218 /*add_to_history*/ eLazyBoolNo
, Result
);
1220 if (!opts::Log
.empty())
1221 Dbg
->EnableLog("lldb", {"all"}, opts::Log
, 0, 0, eLogHandlerStream
, errs());
1223 if (opts::BreakpointSubcommand
)
1224 return opts::breakpoint::evaluateBreakpoints(*Dbg
);
1225 if (opts::ObjectFileSubcommand
)
1226 return dumpObjectFiles(*Dbg
);
1227 if (opts::SymbolsSubcommand
)
1228 return opts::symbols::dumpSymbols(*Dbg
);
1229 if (opts::SymTabSubcommand
)
1230 return opts::symtab::handleSymtabCommand(*Dbg
);
1231 if (opts::IRMemoryMapSubcommand
)
1232 return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg
);
1233 if (opts::AssertSubcommand
)
1234 return opts::assert::lldb_assert(*Dbg
);
1236 WithColor::error() << "No command specified.\n";