summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShafik Yaghmour <syaghmour@apple.com>2019-10-11 16:36:20 +0000
committerShafik Yaghmour <syaghmour@apple.com>2019-10-11 16:36:20 +0000
commit5f46982b452b685419629b23d530281df2298536 (patch)
tree93b776a3d53de0dc6cc0361ec86c71099f575e59
parentadd0786dbaa8ca9c0b44b5eefcf700c15a0c8e44 (diff)
downloadbcm5719-llvm-5f46982b452b685419629b23d530281df2298536.tar.gz
bcm5719-llvm-5f46982b452b685419629b23d530281df2298536.zip
[lldb-test] Modify lldb-test to print out ASTs from symbol file
Summary: Currently when invoking lldb-test symbols -dump-ast it parses all the debug symbols and calls print(...) on the TranslationUnitDecl. While useful the TranslationUnitDecl::print(...) method gives us a higher level view then the dump from ASTDumper which is what we get when we invoke dump() on a specific AST node. The main motivation for this change is allow us to verify that the AST nodes we create when we parse DWARF. For example in order to verify we are correctly using DIFlagExportSymbols added by D66667 Differential Revision: https://reviews.llvm.org/D67994 llvm-svn: 374570
-rw-r--r--lldb/include/lldb/Symbol/ClangASTContext.h8
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp17
-rw-r--r--lldb/source/Symbol/ClangASTContext.cpp33
-rw-r--r--lldb/tools/lldb-test/lldb-test.cpp46
4 files changed, 97 insertions, 7 deletions
diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h
index 92d8985f446..c5d840973ae 100644
--- a/lldb/include/lldb/Symbol/ClangASTContext.h
+++ b/lldb/include/lldb/Symbol/ClangASTContext.h
@@ -886,6 +886,14 @@ public:
void Dump(Stream &s);
+ /// Dump clang AST types from the symbol file.
+ ///
+ /// \param[in] s
+ /// A stream to send the dumped AST node(s) to
+ /// \param[in] symbol_name
+ /// The name of the symbol to dump, if it is empty dump all the symbols
+ void DumpFromSymbolFile(Stream &s, llvm::StringRef symbol_name);
+
void DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
Stream *s, lldb::Format format, const DataExtractor &data,
lldb::offset_t data_offset, size_t data_byte_size,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 863cf2c1f0d..7d96e324ff9 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3024,12 +3024,21 @@ size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc,
bool parse_siblings, bool parse_children) {
size_t types_added = 0;
DWARFDIE die = orig_die;
+
while (die) {
+ const dw_tag_t tag = die.Tag();
bool type_is_new = false;
- if (ParseType(sc, die, &type_is_new).get()) {
- if (type_is_new)
- ++types_added;
- }
+
+ Tag dwarf_tag = static_cast<Tag>(tag);
+
+ // TODO: Currently ParseTypeFromDWARF(...) which is called by ParseType(...)
+ // does not handle DW_TAG_subrange_type. It is not clear if this is a bug or
+ // not.
+ if (isType(dwarf_tag) && tag != DW_TAG_subrange_type)
+ ParseType(sc, die, &type_is_new);
+
+ if (type_is_new)
+ ++types_added;
if (parse_children && die.HasChildren()) {
if (die.Tag() == DW_TAG_subprogram) {
diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp
index a1637ca7baa..b37346814bf 100644
--- a/lldb/source/Symbol/ClangASTContext.cpp
+++ b/lldb/source/Symbol/ClangASTContext.cpp
@@ -8973,6 +8973,39 @@ void ClangASTContext::Dump(Stream &s) {
tu->dump(s.AsRawOstream());
}
+void ClangASTContext::DumpFromSymbolFile(Stream &s,
+ llvm::StringRef symbol_name) {
+ SymbolFile *symfile = GetSymbolFile();
+
+ if (!symfile)
+ return;
+
+ lldb_private::TypeList type_list;
+ symfile->GetTypes(nullptr, eTypeClassAny, type_list);
+ size_t ntypes = type_list.GetSize();
+
+ for (size_t i = 0; i < ntypes; ++i) {
+ TypeSP type = type_list.GetTypeAtIndex(i);
+
+ if (!symbol_name.empty())
+ if (symbol_name.compare(type->GetName().GetStringRef()) != 0)
+ continue;
+
+ s << type->GetName().AsCString() << "\n";
+
+ if (clang::TagDecl *tag_decl =
+ GetAsTagDecl(type->GetFullCompilerType()))
+ tag_decl->dump(s.AsRawOstream());
+ else if (clang::TypedefNameDecl *typedef_decl =
+ GetAsTypedefDecl(type->GetFullCompilerType()))
+ typedef_decl->dump(s.AsRawOstream());
+ else {
+ GetCanonicalQualType(type->GetFullCompilerType().GetOpaqueQualType())
+ .dump(s.AsRawOstream());
+ }
+ }
+}
+
void ClangASTContext::DumpValue(
lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s,
lldb::Format format, const DataExtractor &data,
diff --git a/lldb/tools/lldb-test/lldb-test.cpp b/lldb/tools/lldb-test/lldb-test.cpp
index 426b12acd40..5c5d793466e 100644
--- a/lldb/tools/lldb-test/lldb-test.cpp
+++ b/lldb/tools/lldb-test/lldb-test.cpp
@@ -42,6 +42,7 @@
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/WithColor.h"
+
#include <cstdio>
#include <thread>
@@ -168,6 +169,10 @@ static FunctionNameType getFunctionNameFlags() {
static cl::opt<bool> DumpAST("dump-ast",
cl::desc("Dump AST restored from symbols."),
cl::sub(SymbolsSubcommand));
+static cl::opt<bool>
+ DumpClangAST("dump-clang-ast",
+ cl::desc("Dump clang AST restored from symbols."),
+ cl::sub(SymbolsSubcommand));
static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
cl::sub(SymbolsSubcommand));
@@ -187,6 +192,7 @@ static Error findTypes(lldb_private::Module &Module);
static Error findVariables(lldb_private::Module &Module);
static Error dumpModule(lldb_private::Module &Module);
static Error dumpAST(lldb_private::Module &Module);
+static Error dumpClangAST(lldb_private::Module &Module);
static Error verify(lldb_private::Module &Module);
static Expected<Error (*)(lldb_private::Module &)> getAction();
@@ -580,11 +586,11 @@ Error opts::symbols::dumpModule(lldb_private::Module &Module) {
Error opts::symbols::dumpAST(lldb_private::Module &Module) {
Module.ParseAllDebugSymbols();
- auto symfile = Module.GetSymbolFile();
+ SymbolFile *symfile = Module.GetSymbolFile();
if (!symfile)
return make_string_error("Module has no symbol file.");
- auto type_system_or_err =
+ llvm::Expected<TypeSystem &> type_system_or_err =
symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
if (!type_system_or_err)
return make_string_error("Can't retrieve ClangASTContext");
@@ -598,7 +604,7 @@ Error opts::symbols::dumpAST(lldb_private::Module &Module) {
if (!ast_ctx)
return make_string_error("Can't retrieve AST context.");
- auto tu = ast_ctx->getTranslationUnitDecl();
+ clang::TranslationUnitDecl *tu = ast_ctx->getTranslationUnitDecl();
if (!tu)
return make_string_error("Can't retrieve translation unit declaration.");
@@ -607,6 +613,30 @@ Error opts::symbols::dumpAST(lldb_private::Module &Module) {
return Error::success();
}
+Error opts::symbols::dumpClangAST(lldb_private::Module &Module) {
+ Module.ParseAllDebugSymbols();
+
+ SymbolFile *symfile = Module.GetSymbolFile();
+ if (!symfile)
+ return make_string_error("Module has no symbol file.");
+
+ llvm::Expected<TypeSystem &> type_system_or_err =
+ symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
+ if (!type_system_or_err)
+ return make_string_error("Can't retrieve ClangASTContext");
+
+ auto *clang_ast_ctx =
+ llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get());
+ if (!clang_ast_ctx)
+ return make_string_error("Retrieved TypeSystem was not a ClangASTContext");
+
+ StreamString Stream;
+ clang_ast_ctx->DumpFromSymbolFile(Stream, Name);
+ outs() << Stream.GetData() << "\n";
+
+ return Error::success();
+}
+
Error opts::symbols::verify(lldb_private::Module &Module) {
SymbolFile *symfile = Module.GetSymbolFile();
if (!symfile)
@@ -685,6 +715,16 @@ Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
return dumpAST;
}
+ if (DumpClangAST) {
+ if (Find != FindType::None)
+ return make_string_error("Cannot both search and dump clang AST.");
+ if (Regex || !Context.empty() || !File.empty() || Line != 0)
+ return make_string_error(
+ "-regex, -context, -name, -file and -line options are not "
+ "applicable for dumping clang AST.");
+ return dumpClangAST;
+ }
+
if (Regex && !Context.empty())
return make_string_error(
"Cannot search using both regular expressions and context.");
OpenPOWER on IntegriCloud