[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
This commit is contained in:
Shafik Yaghmour 2019-10-11 16:36:20 +00:00
parent add0786dba
commit 5f46982b45
4 changed files with 97 additions and 7 deletions

View File

@ -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,

View File

@ -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) {

View File

@ -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,

View File

@ -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.");