Skip to content

Commit

Permalink
[lldb-test] Modify lldb-test to print out ASTs from symbol file
Browse files Browse the repository at this point in the history
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
  • Loading branch information
shafik committed Oct 11, 2019
1 parent add0786 commit 5f46982
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 7 deletions.
8 changes: 8 additions & 0 deletions lldb/include/lldb/Symbol/ClangASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,14 @@ class ClangASTContext : public TypeSystem {

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,
Expand Down
17 changes: 13 additions & 4 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
33 changes: 33 additions & 0 deletions lldb/source/Symbol/ClangASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
46 changes: 43 additions & 3 deletions lldb/tools/lldb-test/lldb-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/WithColor.h"

#include <cstdio>
#include <thread>

Expand Down Expand Up @@ -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));
Expand All @@ -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();
Expand Down Expand Up @@ -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");
Expand All @@ -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.");

Expand All @@ -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)
Expand Down Expand Up @@ -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.");
Expand Down

0 comments on commit 5f46982

Please sign in to comment.