| //===-- SymbolFileNativePDB.h -----------------------------------*- C++ -*-===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H | |
| #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H | |
| #include "lldb/Symbol/LineTable.h" | |
| #include "lldb/Symbol/SymbolFile.h" | |
| #include "llvm/ADT/DenseMap.h" | |
| #include "llvm/DebugInfo/CodeView/CVRecord.h" | |
| #include "llvm/DebugInfo/CodeView/SymbolRecord.h" | |
| #include "llvm/DebugInfo/PDB/PDBTypes.h" | |
| #include "CompileUnitIndex.h" | |
| #include "PdbIndex.h" | |
| #include "PdbAstBuilder.h" | |
| #include <optional> | |
| namespace clang { | |
| class TagDecl; | |
| } | |
| namespace llvm { | |
| namespace codeview { | |
| class ClassRecord; | |
| class EnumRecord; | |
| class ModifierRecord; | |
| class PointerRecord; | |
| struct UnionRecord; | |
| } // namespace codeview | |
| } // namespace llvm | |
| namespace lldb_private { | |
| namespace npdb { | |
| class SymbolFileNativePDB : public SymbolFileCommon { | |
| friend class UdtRecordCompleter; | |
| /// LLVM RTTI support. | |
| static char ID; | |
| public: | |
| /// LLVM RTTI support. | |
| /// \{ | |
| bool isA(const void *ClassID) const override { | |
| return ClassID == &ID || SymbolFileCommon::isA(ClassID); | |
| } | |
| static bool classof(const SymbolFile *obj) { return obj->isA(&ID); } | |
| /// \} | |
| // Static Functions | |
| static void Initialize(); | |
| static void Terminate(); | |
| static void DebuggerInitialize(Debugger &debugger); | |
| static llvm::StringRef GetPluginNameStatic() { return "native-pdb"; } | |
| static llvm::StringRef GetPluginDescriptionStatic(); | |
| static SymbolFile *CreateInstance(lldb::ObjectFileSP objfile_sp); | |
| // Constructors and Destructors | |
| SymbolFileNativePDB(lldb::ObjectFileSP objfile_sp); | |
| ~SymbolFileNativePDB() override; | |
| uint32_t CalculateAbilities() override; | |
| void InitializeObject() override; | |
| uint64_t GetDebugInfoSize(bool load_all_debug_info = false) override; | |
| // Compile Unit function calls | |
| void | |
| ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override; | |
| lldb::LanguageType | |
| ParseLanguage(lldb_private::CompileUnit &comp_unit) override; | |
| size_t ParseFunctions(lldb_private::CompileUnit &comp_unit) override; | |
| bool ParseLineTable(lldb_private::CompileUnit &comp_unit) override; | |
| bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; | |
| bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, | |
| SupportFileList &support_files) override; | |
| size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override; | |
| bool ParseImportedModules( | |
| const SymbolContext &sc, | |
| std::vector<lldb_private::SourceModule> &imported_modules) override; | |
| size_t ParseBlocksRecursive(Function &func) override; | |
| void FindGlobalVariables(ConstString name, | |
| const CompilerDeclContext &parent_decl_ctx, | |
| uint32_t max_matches, | |
| VariableList &variables) override; | |
| size_t ParseVariablesForContext(const SymbolContext &sc) override; | |
| void AddSymbols(Symtab &symtab) override; | |
| CompilerDecl GetDeclForUID(lldb::user_id_t uid) override; | |
| CompilerDeclContext GetDeclContextForUID(lldb::user_id_t uid) override; | |
| CompilerDeclContext GetDeclContextContainingUID(lldb::user_id_t uid) override; | |
| Type *ResolveTypeUID(lldb::user_id_t type_uid) override; | |
| std::optional<ArrayInfo> GetDynamicArrayInfoForUID( | |
| lldb::user_id_t type_uid, | |
| const lldb_private::ExecutionContext *exe_ctx) override; | |
| bool CompleteType(CompilerType &compiler_type) override; | |
| uint32_t ResolveSymbolContext(const Address &so_addr, | |
| lldb::SymbolContextItem resolve_scope, | |
| SymbolContext &sc) override; | |
| uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec, | |
| lldb::SymbolContextItem resolve_scope, | |
| SymbolContextList &sc_list) override; | |
| void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, | |
| TypeList &type_list) override; | |
| void FindFunctions(const Module::LookupInfo &lookup_info, | |
| const CompilerDeclContext &parent_decl_ctx, | |
| bool include_inlines, SymbolContextList &sc_list) override; | |
| void FindFunctions(const RegularExpression ®ex, bool include_inlines, | |
| SymbolContextList &sc_list) override; | |
| std::optional<PdbCompilandSymId> FindSymbolScope(PdbCompilandSymId id); | |
| /// Find the mangled name for a function | |
| /// | |
| /// \param id A symbol ID of a S_LPROC32/S_GPROC32 record | |
| /// \returns The mangled name of the function (if available) | |
| std::optional<llvm::StringRef> FindMangledFunctionName(PdbCompilandSymId id); | |
| void FindTypes(const lldb_private::TypeQuery &match, | |
| lldb_private::TypeResults &results) override; | |
| llvm::Expected<lldb::TypeSystemSP> | |
| GetTypeSystemForLanguage(lldb::LanguageType language) override; | |
| CompilerDeclContext FindNamespace(ConstString name, | |
| const CompilerDeclContext &parent_decl_ctx, | |
| bool only_root_namespaces) override; | |
| llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } | |
| llvm::pdb::PDBFile &GetPDBFile() { return m_index->pdb(); } | |
| const llvm::pdb::PDBFile &GetPDBFile() const { return m_index->pdb(); } | |
| PdbIndex &GetIndex() { return *m_index; }; | |
| void DumpClangAST(Stream &s, llvm::StringRef filter, | |
| bool show_color) override; | |
| std::optional<llvm::codeview::TypeIndex> | |
| GetParentType(llvm::codeview::TypeIndex ti); | |
| private: | |
| struct LineTableEntryComparator { | |
| bool operator()(const lldb_private::LineTable::Entry &lhs, | |
| const lldb_private::LineTable::Entry &rhs) const { | |
| return lhs.file_addr < rhs.file_addr; | |
| } | |
| }; | |
| // From address range relative to function base to source line number. | |
| using RangeSourceLineVector = | |
| lldb_private::RangeDataVector<uint32_t, uint32_t, int32_t>; | |
| // InlineSite contains information in a S_INLINESITE record. | |
| struct InlineSite { | |
| PdbCompilandSymId parent_id; | |
| std::shared_ptr<InlineFunctionInfo> inline_function_info; | |
| RangeSourceLineVector ranges; | |
| std::vector<lldb_private::LineTable::Entry> line_entries; | |
| InlineSite(PdbCompilandSymId parent_id) : parent_id(parent_id){}; | |
| }; | |
| void BuildParentMap(); | |
| uint32_t CalculateNumCompileUnits() override; | |
| lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; | |
| void FindTypesByName(llvm::StringRef name, uint32_t max_matches, | |
| TypeMap &types); | |
| lldb::TypeSP CreateModifierType(PdbTypeSymId type_id, | |
| const llvm::codeview::ModifierRecord &mr, | |
| CompilerType ct); | |
| lldb::TypeSP CreatePointerType(PdbTypeSymId type_id, | |
| const llvm::codeview::PointerRecord &pr, | |
| CompilerType ct); | |
| lldb::TypeSP CreateSimpleType(llvm::codeview::TypeIndex ti, CompilerType ct); | |
| lldb::TypeSP CreateTagType(PdbTypeSymId type_id, | |
| const llvm::codeview::ClassRecord &cr, | |
| CompilerType ct); | |
| lldb::TypeSP CreateTagType(PdbTypeSymId type_id, | |
| const llvm::codeview::EnumRecord &er, | |
| CompilerType ct); | |
| lldb::TypeSP CreateTagType(PdbTypeSymId type_id, | |
| const llvm::codeview::UnionRecord &ur, | |
| CompilerType ct); | |
| lldb::TypeSP CreateArrayType(PdbTypeSymId type_id, | |
| const llvm::codeview::ArrayRecord &ar, | |
| CompilerType ct); | |
| lldb::TypeSP CreateFunctionType(PdbTypeSymId type_id, | |
| const llvm::codeview::MemberFunctionRecord &pr, | |
| CompilerType ct); | |
| lldb::TypeSP CreateProcedureType(PdbTypeSymId type_id, | |
| const llvm::codeview::ProcedureRecord &pr, | |
| CompilerType ct); | |
| lldb::TypeSP CreateClassStructUnion(PdbTypeSymId type_id, | |
| const llvm::codeview::TagRecord &record, | |
| size_t size, CompilerType ct); | |
| lldb::FunctionSP GetOrCreateFunction(PdbCompilandSymId func_id, | |
| CompileUnit &comp_unit); | |
| lldb::CompUnitSP GetOrCreateCompileUnit(const CompilandIndexItem &cci); | |
| lldb::TypeSP GetOrCreateType(PdbTypeSymId type_id); | |
| lldb::TypeSP GetOrCreateType(llvm::codeview::TypeIndex ti); | |
| lldb::VariableSP GetOrCreateGlobalVariable(PdbGlobalSymId var_id); | |
| Block *GetOrCreateBlock(PdbCompilandSymId block_id); | |
| lldb::VariableSP GetOrCreateLocalVariable(PdbCompilandSymId scope_id, | |
| PdbCompilandSymId var_id, | |
| bool is_param, | |
| bool is_constant = false); | |
| lldb::TypeSP GetOrCreateTypedef(PdbGlobalSymId id); | |
| lldb::FunctionSP CreateFunction(PdbCompilandSymId func_id, | |
| CompileUnit &comp_unit); | |
| Block *CreateBlock(PdbCompilandSymId block_id); | |
| lldb::VariableSP CreateLocalVariable(PdbCompilandSymId scope_id, | |
| PdbCompilandSymId var_id, bool is_param, | |
| bool is_constant = false); | |
| lldb::TypeSP CreateTypedef(PdbGlobalSymId id); | |
| lldb::CompUnitSP CreateCompileUnit(const CompilandIndexItem &cci); | |
| lldb::TypeSP CreateType(PdbTypeSymId type_id, CompilerType ct); | |
| lldb::TypeSP CreateAndCacheType(PdbTypeSymId type_id); | |
| lldb::VariableSP CreateGlobalVariable(PdbGlobalSymId var_id); | |
| lldb::VariableSP CreateConstantSymbol(PdbGlobalSymId var_id, | |
| const llvm::codeview::CVSymbol &cvs); | |
| size_t ParseVariablesForCompileUnit(CompileUnit &comp_unit, | |
| VariableList &variables); | |
| size_t ParseVariablesForBlock(PdbCompilandSymId block_id); | |
| void CreateSimpleArgumentListTypes(llvm::codeview::TypeIndex arglist_ti); | |
| llvm::Expected<uint32_t> GetFileIndex(const CompilandIndexItem &cii, | |
| uint32_t file_id); | |
| size_t ParseSymbolArrayInScope( | |
| PdbCompilandSymId parent, | |
| llvm::function_ref<bool(llvm::codeview::SymbolKind, PdbCompilandSymId)> | |
| fn); | |
| void ParseInlineSite(PdbCompilandSymId inline_site_id, Address func_addr); | |
| std::vector<CompilerContext> GetContextForType(llvm::codeview::TypeIndex ti); | |
| /// Caches the basenames of symbols found in the globals stream. | |
| /// | |
| /// This includes functions and global variables | |
| void CacheGlobalBaseNames(); | |
| void CacheUdtDeclarations(); | |
| llvm::Expected<Declaration> ResolveUdtDeclaration(PdbTypeSymId type_id); | |
| /// Find a symbol name at a specific address (`so`). | |
| /// | |
| /// \param[in] so The segment and offset where the symbol is located. | |
| /// \param[in] function_type If the symbol is expected to be a function, this | |
| /// has to be the type of the function. It's used to strip the name of | |
| /// __cdecl functions on x86. | |
| /// \returns The mangled symbol name if found, otherwise `std::nullopt`. | |
| std::optional<llvm::StringRef> FindMangledSymbol( | |
| SegmentOffset so, | |
| llvm::codeview::TypeIndex function_type = llvm::codeview::TypeIndex()); | |
| llvm::StringRef StripMangledFunctionName(llvm::StringRef mangled, | |
| PdbTypeSymId func_ty); | |
| llvm::BumpPtrAllocator m_allocator; | |
| lldb::addr_t m_obj_load_address = 0; | |
| bool m_done_full_type_scan = false; | |
| // UID for anonymous union and anonymous struct as they don't have entities in | |
| // pdb debug info. | |
| lldb::user_id_t anonymous_id = LLDB_INVALID_UID - 1; | |
| std::unique_ptr<llvm::pdb::PDBFile> m_file_up; | |
| std::unique_ptr<PdbIndex> m_index; | |
| llvm::DenseMap<lldb::user_id_t, lldb::VariableSP> m_global_vars; | |
| llvm::DenseMap<lldb::user_id_t, lldb::VariableSP> m_local_variables; | |
| llvm::DenseMap<lldb::user_id_t, lldb::BlockSP> m_blocks; | |
| llvm::DenseMap<lldb::user_id_t, lldb::FunctionSP> m_functions; | |
| llvm::DenseMap<lldb::user_id_t, lldb::CompUnitSP> m_compilands; | |
| llvm::DenseMap<lldb::user_id_t, lldb::TypeSP> m_types; | |
| llvm::DenseMap<lldb::user_id_t, std::shared_ptr<InlineSite>> m_inline_sites; | |
| llvm::DenseMap<llvm::codeview::TypeIndex, llvm::codeview::TypeIndex> | |
| m_parent_types; | |
| bool m_parent_map_built = false; | |
| struct UdtDeclaration { | |
| /// This could either be an index into the `/names` section (string table, | |
| /// LF_UDT_MOD_SRC_LINE) or, this could be an index into the IPI stream to a | |
| /// LF_STRING_ID record (LF_UDT_SRC_LINE). | |
| llvm::codeview::TypeIndex FileNameIndex; | |
| bool IsIpiIndex; | |
| uint32_t Line; | |
| }; | |
| llvm::DenseMap<llvm::codeview::TypeIndex, UdtDeclaration> m_udt_declarations; | |
| std::once_flag m_cached_udt_declarations; | |
| lldb_private::UniqueCStringMap<uint32_t> m_type_base_names; | |
| /// mangled name/full function name -> Global ID(s) | |
| lldb_private::UniqueCStringMap<uint32_t> m_func_full_names; | |
| /// basename -> Global ID(s) | |
| lldb_private::UniqueCStringMap<uint32_t> m_func_base_names; | |
| /// method basename -> Global ID(s) | |
| lldb_private::UniqueCStringMap<uint32_t> m_func_method_names; | |
| /// global variable basename -> Global ID(s) | |
| lldb_private::UniqueCStringMap<uint32_t> m_global_variable_base_names; | |
| }; | |
| } // namespace npdb | |
| } // namespace lldb_private | |
| #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H |