Index: lldb/include/lldb/Symbol/SymbolFile.h =================================================================== --- lldb/include/lldb/Symbol/SymbolFile.h +++ lldb/include/lldb/Symbol/SymbolFile.h @@ -161,6 +161,8 @@ uint32_t line, bool check_inlines, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list); + + virtual void DumpClangAST() {} virtual uint32_t FindGlobalVariables(const ConstString &name, const CompilerDeclContext *parent_decl_ctx, Index: lldb/source/Commands/CommandObjectTarget.cpp =================================================================== --- lldb/source/Commands/CommandObjectTarget.cpp +++ lldb/source/Commands/CommandObjectTarget.cpp @@ -2227,6 +2227,85 @@ } }; +#pragma mark CommandObjectTargetModulesDumpSections + +//---------------------------------------------------------------------- +// Clang AST dumping command +//---------------------------------------------------------------------- + +class CommandObjectTargetModulesDumpClangAST + : public CommandObjectTargetModulesModuleAutoComplete { +public: + CommandObjectTargetModulesDumpClangAST(CommandInterpreter &interpreter) + : CommandObjectTargetModulesModuleAutoComplete( + interpreter, "target modules dump ast", + "Dump the clang ast for a given module's symbol file.", + //"target modules dump ast [ ...]") + nullptr) {} + + ~CommandObjectTargetModulesDumpClangAST() override = default; + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target == nullptr) { + result.AppendError("invalid target, create a debug target using the " + "'target create' command"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + const size_t num_modules = target->GetImages().GetSize(); + if (num_modules == 0) { + result.AppendError("the target has no associated executable images"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (command.GetArgumentCount() == 0) { + // Dump all ASTs for all modules images + result.GetOutputStream().Printf("Dumping clang ast for %" PRIu64 + " modules.\n", + (uint64_t)num_modules); + for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { + if (m_interpreter.WasInterrupted()) + break; + Module *m = target->GetImages().GetModulePointerAtIndex(image_idx); + SymbolFile *sf = m->GetSymbolVendor()->GetSymbolFile(); + sf->DumpClangAST(); + } + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + + // Dump specified ASTs (by basename or fullpath) + for (const Args::ArgEntry &arg : command.entries()) { + ModuleList module_list; + const size_t num_matches = + FindModulesByName(target, arg.c_str(), module_list, true); + if (num_matches == 0) { + // Check the global list + std::lock_guard guard( + Module::GetAllocationModuleCollectionMutex()); + + result.AppendWarningWithFormat( + "Unable to find an image that matches '%s'.\n", arg.c_str()); + continue; + } + + for (size_t i = 0; i < num_matches; ++i) { + if (m_interpreter.WasInterrupted()) + break; + Module *m = module_list.GetModulePointerAtIndex(i); + SymbolFile *sf = m->GetSymbolVendor()->GetSymbolFile(); + sf->DumpClangAST(); + } + } + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } +}; + #pragma mark CommandObjectTargetModulesDumpSymfile //---------------------------------------------------------------------- @@ -2406,7 +2485,7 @@ "Commands for dumping information about one or " "more target modules.", "target modules dump " - "[headers|symtab|sections|symfile|line-table] " + "[headers|symtab|sections|ast|symfile|line-table] " "[ ...]") { LoadSubCommand("objfile", CommandObjectSP( @@ -2420,6 +2499,9 @@ LoadSubCommand("symfile", CommandObjectSP( new CommandObjectTargetModulesDumpSymfile(interpreter))); + LoadSubCommand("ast", + CommandObjectSP(new CommandObjectTargetModulesDumpClangAST( + interpreter))); LoadSubCommand("line-table", CommandObjectSP(new CommandObjectTargetModulesDumpLineTable( interpreter))); Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -329,6 +329,8 @@ void Dump(lldb_private::Stream &s) override; + void DumpClangAST() override; + protected: typedef llvm::DenseMap DIEToTypePtr; Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -3854,6 +3854,18 @@ void SymbolFileDWARF::Dump(lldb_private::Stream &s) { m_index->Dump(s); } +void SymbolFileDWARF::DumpClangAST() { + TypeSystem *ts = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); + ClangASTContext *clang = llvm::dyn_cast_or_null(ts); + if (!clang) + return; + clang::TranslationUnitDecl *tu = clang->getASTContext()->getTranslationUnitDecl(); + if (llvm::errs().has_colors()) + tu->dumpColor(); + else + tu->dump(); +} + SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() { if (m_debug_map_symfile == NULL && !m_debug_map_module_wp.expired()) { lldb::ModuleSP module_sp(m_debug_map_module_wp.lock()); Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -126,6 +126,8 @@ std::vector ParseCallEdgesInFunction(lldb_private::UserID func_id) override; + void DumpClangAST() override; + //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1227,6 +1227,13 @@ return matching_namespace; } +void SymbolFileDWARFDebugMap::DumpClangAST() { + ForEachSymbolFile([](SymbolFileDWARF *oso_dwarf) -> bool { + oso_dwarf->DumpClangAST(); + return true; + }); +} + //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ Index: lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h =================================================================== --- lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -155,6 +155,8 @@ ClangASTContext &GetASTContext() { return *m_clang; } ClangASTImporter &GetASTImporter() { return *m_importer; } + void DumpClangAST() override; + private: size_t FindTypesByName(llvm::StringRef name, uint32_t max_matches, TypeMap &types); Index: lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1391,6 +1391,17 @@ return 0; } +void SymbolFileNativePDB::DumpClangAST() { + if (!m_clang) + return; + + clang::TranslationUnitDecl *tu = m_clang->getASTContext()->getTranslationUnitDecl(); + if (llvm::errs().has_colors()) + tu->dumpColor(); + else + tu->dump(); +} + uint32_t SymbolFileNativePDB::FindGlobalVariables( const ConstString &name, const CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, VariableList &variables) { Index: lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h =================================================================== --- lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -169,6 +169,8 @@ const llvm::pdb::IPDBSession &GetPDBSession() const; + void DumpClangAST() override; + private: struct SecContribInfo { uint32_t Offset; Index: lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -1356,6 +1356,18 @@ return types.GetSize(); } +void SymbolFilePDB::DumpClangAST() { + auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + auto clang = llvm::dyn_cast_or_null(type_system); + if (!clang) + return; + clang::TranslationUnitDecl *tu = clang->getASTContext()->getTranslationUnitDecl(); + if (llvm::errs().has_colors()) + tu->dumpColor(); + else + tu->dump(); +} + void SymbolFilePDB::FindTypesByRegex( const lldb_private::RegularExpression ®ex, uint32_t max_matches, lldb_private::TypeMap &types) {