summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Symbol/VariableList.h1
-rw-r--r--lldb/lit/CMakeLists.txt28
-rw-r--r--lldb/lit/SymbolFile/DWARF/find-basic-function.cpp67
-rw-r--r--lldb/lit/SymbolFile/DWARF/find-basic-namespace.cpp29
-rw-r--r--lldb/lit/SymbolFile/DWARF/find-basic-type.cpp38
-rw-r--r--lldb/lit/SymbolFile/DWARF/find-basic-variable.cpp55
-rw-r--r--lldb/lit/SymbolFile/DWARF/find-type-in-function.cpp24
-rw-r--r--lldb/lit/SymbolFile/DWARF/lit.local.cfg1
-rw-r--r--lldb/lit/lit.cfg2
-rw-r--r--lldb/lit/lit.site.cfg.in1
-rw-r--r--lldb/tools/lldb-test/lldb-test.cpp277
11 files changed, 491 insertions, 32 deletions
diff --git a/lldb/include/lldb/Symbol/VariableList.h b/lldb/include/lldb/Symbol/VariableList.h
index cee2a258513..6729a9c108a 100644
--- a/lldb/include/lldb/Symbol/VariableList.h
+++ b/lldb/include/lldb/Symbol/VariableList.h
@@ -66,6 +66,7 @@ public:
size_t MemorySize() const;
size_t GetSize() const;
+ bool Empty() const { return m_variables.empty(); }
protected:
typedef std::vector<lldb::VariableSP> collection;
diff --git a/lldb/lit/CMakeLists.txt b/lldb/lit/CMakeLists.txt
index f01cded2437..ee639a2a07d 100644
--- a/lldb/lit/CMakeLists.txt
+++ b/lldb/lit/CMakeLists.txt
@@ -18,6 +18,24 @@ endif ()
string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLDB_LIBS_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLDB_TOOLS_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR})
+set(LLDB_TEST_DEPS
+ LLDBUnitTests
+ dsymutil
+ lldb
+ lldb-test
+ llvm-config
+ llvm-mc
+ llvm-objcopy
+ )
+
+if(TARGET lld)
+ list(APPEND LLDB_TEST_DEPS lld)
+ set(LLDB_HAVE_LLD 1)
+else()
+ set(LLDB_HAVE_LLD 0)
+endif()
+
+
if(BUILD_SHARED_LIBS)
set(ENABLE_SHARED 1)
else()
@@ -36,16 +54,6 @@ configure_lit_site_cfg(
${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg
)
-set(LLDB_TEST_DEPS
- LLDBUnitTests
- dsymutil
- lldb
- lldb-test
- llvm-config
- llvm-mc
- llvm-objcopy
- )
-
if(NOT LLDB_BUILT_STANDALONE)
list(APPEND LLDB_TEST_DEPS FileCheck not yaml2obj)
endif()
diff --git a/lldb/lit/SymbolFile/DWARF/find-basic-function.cpp b/lldb/lit/SymbolFile/DWARF/find-basic-function.cpp
new file mode 100644
index 00000000000..39d81ae7eb3
--- /dev/null
+++ b/lldb/lit/SymbolFile/DWARF/find-basic-function.cpp
@@ -0,0 +1,67 @@
+// REQUIRES: lld
+
+// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t
+// RUN: lldb-test symbols --name=foo --find=function --function-flags=base %t | \
+// RUN: FileCheck --check-prefix=BASE %s
+// RUN: lldb-test symbols --name=foo --find=function --function-flags=method %t | \
+// RUN: FileCheck --check-prefix=METHOD %s
+// RUN: lldb-test symbols --name=foo --find=function --function-flags=full %t | \
+// RUN: FileCheck --check-prefix=FULL %s
+// RUN: lldb-test symbols --name=foo --context=context --find=function --function-flags=base %t | \
+// RUN: FileCheck --check-prefix=CONTEXT %s
+// RUN: lldb-test symbols --name=not_there --find=function %t | \
+// RUN: FileCheck --check-prefix=EMPTY %s
+
+// BASE: Found 4 functions:
+// BASE-DAG: name = "foo()", mangled = "_Z3foov"
+// BASE-DAG: name = "foo(int)", mangled = "_Z3fooi"
+// BASE-DAG: name = "bar::foo()", mangled = "_ZN3bar3fooEv"
+// BASE-DAG: name = "bar::baz::foo()", mangled = "_ZN3bar3baz3fooEv"
+
+// METHOD: Found 3 functions:
+// METHOD-DAG: name = "sbar::foo()", mangled = "_ZN4sbar3fooEv"
+// METHOD-DAG: name = "sbar::foo(int)", mangled = "_ZN4sbar3fooEi"
+// METHOD-DAG: name = "ffbar()::sbar::foo()", mangled = "_ZZ5ffbarvEN4sbar3fooEv"
+
+// FULL: Found 2 functions:
+// FULL-DAG: name = "foo()", mangled = "_Z3foov"
+// FULL-DAG: name = "foo(int)", mangled = "_Z3fooi"
+
+// CONTEXT: Found 1 functions:
+// CONTEXT-DAG: name = "bar::foo()", mangled = "_ZN3bar3fooEv"
+
+// EMPTY: Found 0 functions:
+
+void foo() {}
+void foo(int) {}
+
+namespace bar {
+int context;
+void foo() {}
+namespace baz {
+void foo() {}
+} // namespace baz
+} // namespace bar
+
+struct foo {};
+void fbar(struct foo) {}
+
+void Foo() {}
+
+struct sbar {
+ void foo();
+ static void foo(int);
+};
+void sbar::foo() {}
+void sbar::foo(int) {}
+
+void ffbar() {
+ struct sbar {
+ void foo() {}
+ };
+ sbar a;
+ a.foo();
+}
+
+extern "C" void _start() {}
diff --git a/lldb/lit/SymbolFile/DWARF/find-basic-namespace.cpp b/lldb/lit/SymbolFile/DWARF/find-basic-namespace.cpp
new file mode 100644
index 00000000000..393cc7eab76
--- /dev/null
+++ b/lldb/lit/SymbolFile/DWARF/find-basic-namespace.cpp
@@ -0,0 +1,29 @@
+// REQUIRES: lld
+
+// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t
+// RUN: lldb-test symbols --name=foo --find=namespace %t | \
+// RUN: FileCheck --check-prefix=FOO %s
+// RUN: lldb-test symbols --name=foo --find=namespace --context=context %t | \
+// RUN: FileCheck --check-prefix=CONTEXT %s
+// RUN: lldb-test symbols --name=not_there --find=namespace %t | \
+// RUN: FileCheck --check-prefix=EMPTY %s
+
+// FOO: Found namespace: foo
+
+// CONTEXT: Found namespace: bar::foo
+
+// EMPTY: Namespace not found.
+
+namespace foo {
+int X;
+}
+
+namespace bar {
+int context;
+namespace foo {
+int X;
+}
+} // namespace bar
+
+extern "C" void _start() {}
diff --git a/lldb/lit/SymbolFile/DWARF/find-basic-type.cpp b/lldb/lit/SymbolFile/DWARF/find-basic-type.cpp
new file mode 100644
index 00000000000..b67ef60b7e9
--- /dev/null
+++ b/lldb/lit/SymbolFile/DWARF/find-basic-type.cpp
@@ -0,0 +1,38 @@
+// REQUIRES: lld
+
+// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t
+// RUN: lldb-test symbols --name=foo --find=type %t | \
+// RUN: FileCheck --check-prefix=NAME %s
+// RUN: lldb-test symbols --name=foo --context=context --find=type %t | \
+// RUN: FileCheck --check-prefix=CONTEXT %s
+// RUN: lldb-test symbols --name=not_there --find=type %t | \
+// RUN: FileCheck --check-prefix=EMPTY %s
+
+// EMPTY: Found 0 types:
+// NAME: Found 4 types:
+// CONTEXT: Found 1 types:
+struct foo { };
+// NAME-DAG: name = "foo", {{.*}} decl = find-basic-type.cpp:[[@LINE-1]]
+
+namespace bar {
+int context;
+struct foo {};
+// NAME-DAG: name = "foo", {{.*}} decl = find-basic-type.cpp:[[@LINE-1]]
+// CONTEXT-DAG: name = "foo", {{.*}} decl = find-basic-type.cpp:[[@LINE-2]]
+namespace baz {
+struct foo {};
+// NAME-DAG: name = "foo", {{.*}} decl = find-basic-type.cpp:[[@LINE-1]]
+}
+}
+
+struct sbar {
+ struct foo {};
+// NAME-DAG: name = "foo", {{.*}} decl = find-basic-type.cpp:[[@LINE-1]]
+};
+
+struct foobar {};
+
+struct Foo {};
+
+extern "C" void _start(foo, bar::foo, bar::baz::foo, sbar::foo, foobar, Foo) {}
diff --git a/lldb/lit/SymbolFile/DWARF/find-basic-variable.cpp b/lldb/lit/SymbolFile/DWARF/find-basic-variable.cpp
new file mode 100644
index 00000000000..729d493cca7
--- /dev/null
+++ b/lldb/lit/SymbolFile/DWARF/find-basic-variable.cpp
@@ -0,0 +1,55 @@
+// REQUIRES: lld
+
+// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t
+// RUN: lldb-test symbols --name=foo --find=variable --context=context %t | \
+// RUN: FileCheck --check-prefix=CONTEXT %s
+// RUN: lldb-test symbols --name=foo --find=variable %t | \
+// RUN: FileCheck --check-prefix=NAME %s
+// RUN: lldb-test symbols --regex --name=foo --find=variable %t | \
+// RUN: FileCheck --check-prefix=REGEX %s
+// RUN: lldb-test symbols --name=not_there --find=variable %t | \
+// RUN: FileCheck --check-prefix=EMPTY %s
+
+// EMPTY: Found 0 variables:
+// NAME: Found 4 variables:
+// CONTEXT: Found 1 variables:
+// REGEX: Found 5 variables:
+int foo;
+// NAME-DAG: name = "foo", type = {{.*}} (int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-1]]
+// REGEX-DAG: name = "foo", type = {{.*}} (int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-2]]
+namespace bar {
+int context;
+long foo;
+// NAME-DAG: name = "foo", type = {{.*}} (long int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-1]]
+// CONTEXT-DAG: name = "foo", type = {{.*}} (long int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-2]]
+// REGEX-DAG: name = "foo", type = {{.*}} (long int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-3]]
+namespace baz {
+static short foo;
+// NAME-DAG: name = "foo", type = {{.*}} (short), {{.*}} decl = find-basic-variable.cpp:[[@LINE-1]]
+// REGEX-DAG: name = "foo", type = {{.*}} (short), {{.*}} decl = find-basic-variable.cpp:[[@LINE-2]]
+}
+}
+
+struct sbar {
+ static int foo;
+// NAME-DAG: name = "foo", type = {{.*}} (int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-1]]
+// REGEX-DAG: name = "foo", type = {{.*}} (int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-2]]
+};
+int sbar::foo;
+
+int foobar;
+// REGEX-DAG: name = "foobar", type = {{.*}} (int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-1]]
+
+int fbar() {
+ static int foo;
+ return foo + bar::baz::foo;
+}
+
+int Foo;
+
+struct ssbar {
+ int foo;
+};
+
+extern "C" void _start(sbar, ssbar) {}
diff --git a/lldb/lit/SymbolFile/DWARF/find-type-in-function.cpp b/lldb/lit/SymbolFile/DWARF/find-type-in-function.cpp
new file mode 100644
index 00000000000..a0894284fa2
--- /dev/null
+++ b/lldb/lit/SymbolFile/DWARF/find-type-in-function.cpp
@@ -0,0 +1,24 @@
+// REQUIRES: lld
+
+// XFAIL: *
+
+// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t
+// RUN: lldb-test symbols --name=foo --find=type %t | \
+// RUN: FileCheck --check-prefix=NAME %s
+
+// Lookup for "foo" should find either both "struct foo" types or just the
+// global one. Right now, it finds the definition inside bar(), which is
+// definitely wrong.
+
+// NAME: Found 2 types:
+struct foo {};
+// NAME-DAG: name = "foo", {{.*}} decl = find-type-in-function.cpp:[[@LINE-1]]
+
+void bar() {
+ struct foo {};
+// NAME-DAG: name = "foo", {{.*}} decl = find-type-in-function.cpp:[[@LINE-1]]
+ foo a;
+}
+
+extern "C" void _start(foo) {}
diff --git a/lldb/lit/SymbolFile/DWARF/lit.local.cfg b/lldb/lit/SymbolFile/DWARF/lit.local.cfg
new file mode 100644
index 00000000000..159c376beed
--- /dev/null
+++ b/lldb/lit/SymbolFile/DWARF/lit.local.cfg
@@ -0,0 +1 @@
+config.suffixes = ['.cpp']
diff --git a/lldb/lit/lit.cfg b/lldb/lit/lit.cfg
index 7b44292ecee..98dab4271aa 100644
--- a/lldb/lit/lit.cfg
+++ b/lldb/lit/lit.cfg
@@ -132,6 +132,8 @@ elif re.match(r'cl', config.cc):
config.available_features.add("compiler-msvc")
config.available_features.add(binary_feature(config.have_zlib, "zlib", "no"))
+if config.have_lld:
+ config.available_features.add("lld")
# llvm-config knows whether it is compiled with asserts (and)
# whether we are operating in release/debug mode.
diff --git a/lldb/lit/lit.site.cfg.in b/lldb/lit/lit.site.cfg.in
index 6aa7e249eca..55942db64c4 100644
--- a/lldb/lit/lit.site.cfg.in
+++ b/lldb/lit/lit.site.cfg.in
@@ -13,6 +13,7 @@ config.python_executable = "@PYTHON_EXECUTABLE@"
config.cc = "@LLDB_TEST_C_COMPILER@"
config.cxx = "@LLDB_TEST_CXX_COMPILER@"
config.have_zlib = @LLVM_ENABLE_ZLIB@
+config.have_lld = @LLDB_HAVE_LLD@
# Support substitution of the tools and libs dirs with user parameters. This is
# used when we can't determine the tool dir at configuration time.
diff --git a/lldb/tools/lldb-test/lldb-test.cpp b/lldb/tools/lldb-test/lldb-test.cpp
index 3c55aa72800..7fa44e69da0 100644
--- a/lldb/tools/lldb-test/lldb-test.cpp
+++ b/lldb/tools/lldb-test/lldb-test.cpp
@@ -20,6 +20,10 @@
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangASTImporter.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/StreamString.h"
@@ -29,6 +33,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
+#include "llvm/Support/WithColor.h"
#include <thread>
using namespace lldb;
@@ -57,7 +62,7 @@ static cl::opt<bool> Persistent(
static llvm::StringRef plural(uintmax_t value) { return value == 1 ? "" : "s"; }
static void dumpState(const BreakpointList &List, LinePrinter &P);
static std::string substitute(StringRef Cmd);
-static void evaluateBreakpoints(Debugger &Dbg);
+static int evaluateBreakpoints(Debugger &Dbg);
} // namespace breakpoint
namespace module {
@@ -69,12 +74,68 @@ cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
} // namespace module
namespace symbols {
-cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
- cl::OneOrMore, cl::sub(SymbolsSubcommand));
+static cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<input files>"),
+ cl::OneOrMore,
+ cl::sub(SymbolsSubcommand));
+enum class FindType {
+ None,
+ Function,
+ Namespace,
+ Type,
+ Variable,
+};
+static cl::opt<FindType> Find(
+ "find", cl::desc("Choose search type:"),
+ cl::values(
+ clEnumValN(FindType::None, "none",
+ "No search, just dump the module."),
+ clEnumValN(FindType::Function, "function", "Find functions."),
+ clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
+ clEnumValN(FindType::Type, "type", "Find types."),
+ clEnumValN(FindType::Variable, "variable", "Find global variables.")),
+ cl::sub(SymbolsSubcommand));
+
+static cl::opt<std::string> Name("name", cl::desc("Name to find."),
+ cl::sub(SymbolsSubcommand));
+static cl::opt<bool>
+ Regex("regex",
+ cl::desc("Search using regular expressions (avaliable for variables "
+ "and functions only)."),
+ cl::sub(SymbolsSubcommand));
+static cl::opt<std::string>
+ Context("context",
+ cl::desc("Restrict search to the context of the given variable."),
+ cl::value_desc("variable"), cl::sub(SymbolsSubcommand));
+
+static cl::list<FunctionNameType> FunctionNameFlags(
+ "function-flags", cl::desc("Function search flags:"),
+ cl::values(clEnumValN(eFunctionNameTypeAuto, "auto",
+ "Automatically deduce flags based on name."),
+ clEnumValN(eFunctionNameTypeFull, "full", "Full function name."),
+ clEnumValN(eFunctionNameTypeBase, "base", "Base name."),
+ clEnumValN(eFunctionNameTypeMethod, "method", "Method name."),
+ clEnumValN(eFunctionNameTypeSelector, "selector",
+ "Selector name.")),
+ cl::sub(SymbolsSubcommand));
+static FunctionNameType getFunctionNameFlags() {
+ FunctionNameType Result = FunctionNameType(0);
+ for (FunctionNameType Flag : FunctionNameFlags)
+ Result = FunctionNameType(Result | Flag);
+ return Result;
}
-} // namespace opts
-static llvm::ManagedStatic<SystemLifetimeManager> DebuggerLifetime;
+static Expected<CompilerDeclContext> getDeclContext(SymbolVendor &Vendor);
+
+static Error findFunctions(lldb_private::Module &Module);
+static Error findNamespaces(lldb_private::Module &Module);
+static Error findTypes(lldb_private::Module &Module);
+static Error findVariables(lldb_private::Module &Module);
+static Error dumpModule(lldb_private::Module &Module);
+
+static int dumpSymbols(Debugger &Dbg);
+}
+} // namespace opts
void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) {
P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize()));
@@ -130,7 +191,7 @@ std::string opts::breakpoint::substitute(StringRef Cmd) {
return std::move(OS.str());
}
-void opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
+int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
TargetSP Target;
Status ST =
Dbg.GetTargetList().CreateTarget(Dbg, breakpoint::Target, /*triple*/ "",
@@ -151,6 +212,7 @@ void opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
LinePrinter P(4, outs());
StringRef Rest = (*MB)->getBuffer();
+ int HadErrors = 0;
while (!Rest.empty()) {
StringRef Line;
std::tie(Line, Rest) = Rest.split('\n');
@@ -167,31 +229,198 @@ void opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
if (!Dbg.GetCommandInterpreter().HandleCommand(
Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
P.formatLine("Failed: {0}", Result.GetErrorData());
+ HadErrors = 1;
continue;
}
dumpState(Target->GetBreakpointList(/*internal*/ false), P);
}
+ return HadErrors;
+}
+
+Expected<CompilerDeclContext>
+opts::symbols::getDeclContext(SymbolVendor &Vendor) {
+ if (Context.empty())
+ return CompilerDeclContext();
+ VariableList List;
+ Vendor.FindGlobalVariables(ConstString(Context), nullptr, false, UINT32_MAX,
+ List);
+ if (List.Empty()) {
+ return make_error<StringError>("Context search didn't find a match.",
+ inconvertibleErrorCode());
+ }
+ if (List.GetSize() > 1) {
+ return make_error<StringError>("Context search found multiple matches.",
+ inconvertibleErrorCode());
+ }
+ return List.GetVariableAtIndex(0)->GetDeclContext();
+}
+
+Error opts::symbols::findFunctions(lldb_private::Module &Module) {
+ SymbolVendor &Vendor = *Module.GetSymbolVendor();
+ SymbolContextList List;
+ if (Regex) {
+ RegularExpression RE(Name);
+ assert(RE.IsValid());
+ Vendor.FindFunctions(RE, true, false, List);
+ } else {
+ Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
+ if (!ContextOr)
+ return ContextOr.takeError();
+ CompilerDeclContext *ContextPtr =
+ ContextOr->IsValid() ? &*ContextOr : nullptr;
+
+ Vendor.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
+ true, false, List);
+ }
+ outs() << formatv("Found {0} functions:\n", List.GetSize());
+ StreamString Stream;
+ List.Dump(&Stream, nullptr);
+ outs() << Stream.GetData() << "\n";
+ return Error::success();
+}
+
+Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
+ SymbolVendor &Vendor = *Module.GetSymbolVendor();
+ Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
+ if (!ContextOr)
+ return ContextOr.takeError();
+ CompilerDeclContext *ContextPtr =
+ ContextOr->IsValid() ? &*ContextOr : nullptr;
+
+ SymbolContext SC;
+ CompilerDeclContext Result =
+ Vendor.FindNamespace(SC, ConstString(Name), ContextPtr);
+ if (Result)
+ outs() << "Found namespace: "
+ << Result.GetScopeQualifiedName().GetStringRef() << "\n";
+ else
+ outs() << "Namespace not found.\n";
+ return Error::success();
+}
+
+Error opts::symbols::findTypes(lldb_private::Module &Module) {
+ SymbolVendor &Vendor = *Module.GetSymbolVendor();
+ Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
+ if (!ContextOr)
+ return ContextOr.takeError();
+ CompilerDeclContext *ContextPtr =
+ ContextOr->IsValid() ? &*ContextOr : nullptr;
+
+ SymbolContext SC;
+ DenseSet<SymbolFile *> SearchedFiles;
+ TypeMap Map;
+ Vendor.FindTypes(SC, ConstString(Name), ContextPtr, true, UINT32_MAX,
+ SearchedFiles, Map);
+
+ outs() << formatv("Found {0} types:\n", Map.GetSize());
+ StreamString Stream;
+ Map.Dump(&Stream, false);
+ outs() << Stream.GetData() << "\n";
+ return Error::success();
+}
+
+Error opts::symbols::findVariables(lldb_private::Module &Module) {
+ SymbolVendor &Vendor = *Module.GetSymbolVendor();
+ VariableList List;
+ if (Regex) {
+ RegularExpression RE(Name);
+ assert(RE.IsValid());
+ Vendor.FindGlobalVariables(RE, false, UINT32_MAX, List);
+ } else {
+ Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
+ if (!ContextOr)
+ return ContextOr.takeError();
+ CompilerDeclContext *ContextPtr =
+ ContextOr->IsValid() ? &*ContextOr : nullptr;
+
+ Vendor.FindGlobalVariables(ConstString(Name), ContextPtr, false, UINT32_MAX,
+ List);
+ }
+ outs() << formatv("Found {0} variables:\n", List.GetSize());
+ StreamString Stream;
+ List.Dump(&Stream, false);
+ outs() << Stream.GetData() << "\n";
+ return Error::success();
}
-static void dumpSymbols(Debugger &Dbg) {
- for (const auto &File : opts::symbols::InputFilenames) {
+Error opts::symbols::dumpModule(lldb_private::Module &Module) {
+ StreamString Stream;
+ Module.ParseAllDebugSymbols();
+ Module.Dump(&Stream);
+ outs() << Stream.GetData() << "\n";
+ return Error::success();
+}
+
+int opts::symbols::dumpSymbols(Debugger &Dbg) {
+ if (Find != FindType::None && Regex && !Context.empty()) {
+ WithColor::error()
+ << "Cannot search using both regular expressions and context.\n";
+ return 1;
+ }
+ if ((Find == FindType::Type || Find == FindType::Namespace) && Regex) {
+ WithColor::error() << "Cannot search for types and namespaces using "
+ "regular expressions.\n";
+ return 1;
+ }
+ if (Find == FindType::Function && Regex && getFunctionNameFlags() != 0) {
+ WithColor::error() << "Cannot search for types using both regular "
+ "expressions and function-flags.\n";
+ return 1;
+ }
+ if (Regex && !RegularExpression(Name).IsValid()) {
+ WithColor::error() << "`" << Name
+ << "` is not a valid regular expression.\n";
+ return 1;
+ }
+
+ Error (*Action)(lldb_private::Module &);
+ switch (Find) {
+ case FindType::Function:
+ Action = findFunctions;
+ break;
+ case FindType::Namespace:
+ Action = findNamespaces;
+ break;
+ case FindType::Type:
+ Action = findTypes;
+ break;
+ case FindType::Variable:
+ Action = findVariables;
+ break;
+ case FindType::None:
+ Action = dumpModule;
+ break;
+ }
+
+ int HadErrors = 0;
+ for (const auto &File : InputFilenames) {
+ outs() << "Module: " << File << "\n";
ModuleSpec Spec{FileSpec(File, false)};
Spec.GetSymbolFileSpec().SetFile(File, false);
auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
+ SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
+ if (!Vendor) {
+ WithColor::error() << "Module has no symbol vendor.\n";
+ HadErrors = 1;
+ continue;
+ }
+
+ if (Error E = Action(*ModulePtr)) {
+ WithColor::error() << toString(std::move(E)) << "\n";
+ HadErrors = 1;
+ }
- StreamString Stream;
- ModulePtr->ParseAllDebugSymbols();
- ModulePtr->Dump(&Stream);
- llvm::outs() << Stream.GetData() << "\n";
- llvm::outs().flush();
+ outs().flush();
}
+ return HadErrors;
}
-static void dumpModules(Debugger &Dbg) {
+static int dumpModules(Debugger &Dbg) {
LinePrinter Printer(4, llvm::outs());
+ int HadErrors = 0;
for (const auto &File : opts::module::InputFilenames) {
ModuleSpec Spec{FileSpec(File, false)};
@@ -202,6 +431,7 @@ static void dumpModules(Debugger &Dbg) {
SectionList *Sections = ModulePtr->GetSectionList();
if (!Sections) {
llvm::errs() << "Could not load sections for module " << File << "\n";
+ HadErrors = 1;
continue;
}
@@ -226,6 +456,7 @@ static void dumpModules(Debugger &Dbg) {
Printer.NewLine();
}
}
+ return HadErrors;
}
int main(int argc, const char *argv[]) {
@@ -236,18 +467,20 @@ int main(int argc, const char *argv[]) {
cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
- DebuggerLifetime->Initialize(llvm::make_unique<SystemInitializerTest>(),
- nullptr);
+ SystemLifetimeManager DebuggerLifetime;
+ DebuggerLifetime.Initialize(llvm::make_unique<SystemInitializerTest>(),
+ nullptr);
+ CleanUp TerminateDebugger([&] { DebuggerLifetime.Terminate(); });
auto Dbg = lldb_private::Debugger::CreateInstance();
if (opts::BreakpointSubcommand)
- opts::breakpoint::evaluateBreakpoints(*Dbg);
+ return opts::breakpoint::evaluateBreakpoints(*Dbg);
if (opts::ModuleSubcommand)
- dumpModules(*Dbg);
- else if (opts::SymbolsSubcommand)
- dumpSymbols(*Dbg);
+ return dumpModules(*Dbg);
+ if (opts::SymbolsSubcommand)
+ return opts::symbols::dumpSymbols(*Dbg);
- DebuggerLifetime->Terminate();
- return 0;
+ WithColor::error() << "No command specified.\n";
+ return 1;
}
OpenPOWER on IntegriCloud