344 lines · c
1//===-- SymbolFileNativePDB.h -----------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H10#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H11 12#include "lldb/Symbol/LineTable.h"13#include "lldb/Symbol/SymbolFile.h"14 15#include "llvm/ADT/DenseMap.h"16#include "llvm/DebugInfo/CodeView/CVRecord.h"17#include "llvm/DebugInfo/CodeView/SymbolRecord.h"18#include "llvm/DebugInfo/PDB/PDBTypes.h"19 20#include "CompileUnitIndex.h"21#include "PdbIndex.h"22#include "PdbAstBuilder.h"23#include <optional>24 25namespace clang {26class TagDecl;27}28 29namespace llvm {30namespace codeview {31class ClassRecord;32class EnumRecord;33class ModifierRecord;34class PointerRecord;35struct UnionRecord;36} // namespace codeview37} // namespace llvm38 39namespace lldb_private {40 41namespace npdb {42 43class SymbolFileNativePDB : public SymbolFileCommon {44 friend class UdtRecordCompleter;45 46 /// LLVM RTTI support.47 static char ID;48 49public:50 /// LLVM RTTI support.51 /// \{52 bool isA(const void *ClassID) const override {53 return ClassID == &ID || SymbolFileCommon::isA(ClassID);54 }55 static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }56 /// \}57 58 // Static Functions59 static void Initialize();60 61 static void Terminate();62 63 static void DebuggerInitialize(Debugger &debugger);64 65 static llvm::StringRef GetPluginNameStatic() { return "native-pdb"; }66 67 static llvm::StringRef GetPluginDescriptionStatic();68 69 static SymbolFile *CreateInstance(lldb::ObjectFileSP objfile_sp);70 71 // Constructors and Destructors72 SymbolFileNativePDB(lldb::ObjectFileSP objfile_sp);73 74 ~SymbolFileNativePDB() override;75 76 uint32_t CalculateAbilities() override;77 78 void InitializeObject() override;79 80 uint64_t GetDebugInfoSize(bool load_all_debug_info = false) override;81 82 // Compile Unit function calls83 84 void85 ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override;86 87 lldb::LanguageType88 ParseLanguage(lldb_private::CompileUnit &comp_unit) override;89 90 size_t ParseFunctions(lldb_private::CompileUnit &comp_unit) override;91 92 bool ParseLineTable(lldb_private::CompileUnit &comp_unit) override;93 94 bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override;95 96 bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit,97 SupportFileList &support_files) override;98 size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override;99 100 bool ParseImportedModules(101 const SymbolContext &sc,102 std::vector<lldb_private::SourceModule> &imported_modules) override;103 104 size_t ParseBlocksRecursive(Function &func) override;105 106 void FindGlobalVariables(ConstString name,107 const CompilerDeclContext &parent_decl_ctx,108 uint32_t max_matches,109 VariableList &variables) override;110 111 size_t ParseVariablesForContext(const SymbolContext &sc) override;112 113 void AddSymbols(Symtab &symtab) override;114 115 CompilerDecl GetDeclForUID(lldb::user_id_t uid) override;116 CompilerDeclContext GetDeclContextForUID(lldb::user_id_t uid) override;117 CompilerDeclContext GetDeclContextContainingUID(lldb::user_id_t uid) override;118 Type *ResolveTypeUID(lldb::user_id_t type_uid) override;119 std::optional<ArrayInfo> GetDynamicArrayInfoForUID(120 lldb::user_id_t type_uid,121 const lldb_private::ExecutionContext *exe_ctx) override;122 123 bool CompleteType(CompilerType &compiler_type) override;124 uint32_t ResolveSymbolContext(const Address &so_addr,125 lldb::SymbolContextItem resolve_scope,126 SymbolContext &sc) override;127 uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec,128 lldb::SymbolContextItem resolve_scope,129 SymbolContextList &sc_list) override;130 131 void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask,132 TypeList &type_list) override;133 134 void FindFunctions(const Module::LookupInfo &lookup_info,135 const CompilerDeclContext &parent_decl_ctx,136 bool include_inlines, SymbolContextList &sc_list) override;137 138 void FindFunctions(const RegularExpression ®ex, bool include_inlines,139 SymbolContextList &sc_list) override;140 141 std::optional<PdbCompilandSymId> FindSymbolScope(PdbCompilandSymId id);142 143 /// Find the mangled name for a function144 ///145 /// \param id A symbol ID of a S_LPROC32/S_GPROC32 record146 /// \returns The mangled name of the function (if available)147 std::optional<llvm::StringRef> FindMangledFunctionName(PdbCompilandSymId id);148 149 void FindTypes(const lldb_private::TypeQuery &match,150 lldb_private::TypeResults &results) override;151 152 llvm::Expected<lldb::TypeSystemSP>153 GetTypeSystemForLanguage(lldb::LanguageType language) override;154 155 CompilerDeclContext FindNamespace(ConstString name,156 const CompilerDeclContext &parent_decl_ctx,157 bool only_root_namespaces) override;158 159 llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }160 161 llvm::pdb::PDBFile &GetPDBFile() { return m_index->pdb(); }162 const llvm::pdb::PDBFile &GetPDBFile() const { return m_index->pdb(); }163 164 PdbIndex &GetIndex() { return *m_index; };165 166 void DumpClangAST(Stream &s, llvm::StringRef filter,167 bool show_color) override;168 169 std::optional<llvm::codeview::TypeIndex>170 GetParentType(llvm::codeview::TypeIndex ti);171 172private:173 struct LineTableEntryComparator {174 bool operator()(const lldb_private::LineTable::Entry &lhs,175 const lldb_private::LineTable::Entry &rhs) const {176 return lhs.file_addr < rhs.file_addr;177 }178 };179 180 // From address range relative to function base to source line number.181 using RangeSourceLineVector =182 lldb_private::RangeDataVector<uint32_t, uint32_t, int32_t>;183 // InlineSite contains information in a S_INLINESITE record.184 struct InlineSite {185 PdbCompilandSymId parent_id;186 std::shared_ptr<InlineFunctionInfo> inline_function_info;187 RangeSourceLineVector ranges;188 std::vector<lldb_private::LineTable::Entry> line_entries;189 InlineSite(PdbCompilandSymId parent_id) : parent_id(parent_id){};190 };191 192 void BuildParentMap();193 194 uint32_t CalculateNumCompileUnits() override;195 196 lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;197 198 void FindTypesByName(llvm::StringRef name, uint32_t max_matches,199 TypeMap &types);200 201 lldb::TypeSP CreateModifierType(PdbTypeSymId type_id,202 const llvm::codeview::ModifierRecord &mr,203 CompilerType ct);204 lldb::TypeSP CreatePointerType(PdbTypeSymId type_id,205 const llvm::codeview::PointerRecord &pr,206 CompilerType ct);207 lldb::TypeSP CreateSimpleType(llvm::codeview::TypeIndex ti, CompilerType ct);208 lldb::TypeSP CreateTagType(PdbTypeSymId type_id,209 const llvm::codeview::ClassRecord &cr,210 CompilerType ct);211 lldb::TypeSP CreateTagType(PdbTypeSymId type_id,212 const llvm::codeview::EnumRecord &er,213 CompilerType ct);214 lldb::TypeSP CreateTagType(PdbTypeSymId type_id,215 const llvm::codeview::UnionRecord &ur,216 CompilerType ct);217 lldb::TypeSP CreateArrayType(PdbTypeSymId type_id,218 const llvm::codeview::ArrayRecord &ar,219 CompilerType ct);220 lldb::TypeSP CreateFunctionType(PdbTypeSymId type_id,221 const llvm::codeview::MemberFunctionRecord &pr,222 CompilerType ct);223 lldb::TypeSP CreateProcedureType(PdbTypeSymId type_id,224 const llvm::codeview::ProcedureRecord &pr,225 CompilerType ct);226 lldb::TypeSP CreateClassStructUnion(PdbTypeSymId type_id,227 const llvm::codeview::TagRecord &record,228 size_t size, CompilerType ct);229 230 lldb::FunctionSP GetOrCreateFunction(PdbCompilandSymId func_id,231 CompileUnit &comp_unit);232 lldb::CompUnitSP GetOrCreateCompileUnit(const CompilandIndexItem &cci);233 lldb::TypeSP GetOrCreateType(PdbTypeSymId type_id);234 lldb::TypeSP GetOrCreateType(llvm::codeview::TypeIndex ti);235 lldb::VariableSP GetOrCreateGlobalVariable(PdbGlobalSymId var_id);236 Block *GetOrCreateBlock(PdbCompilandSymId block_id);237 lldb::VariableSP GetOrCreateLocalVariable(PdbCompilandSymId scope_id,238 PdbCompilandSymId var_id,239 bool is_param);240 lldb::TypeSP GetOrCreateTypedef(PdbGlobalSymId id);241 242 lldb::FunctionSP CreateFunction(PdbCompilandSymId func_id,243 CompileUnit &comp_unit);244 Block *CreateBlock(PdbCompilandSymId block_id);245 lldb::VariableSP CreateLocalVariable(PdbCompilandSymId scope_id,246 PdbCompilandSymId var_id, bool is_param);247 lldb::TypeSP CreateTypedef(PdbGlobalSymId id);248 lldb::CompUnitSP CreateCompileUnit(const CompilandIndexItem &cci);249 lldb::TypeSP CreateType(PdbTypeSymId type_id, CompilerType ct);250 lldb::TypeSP CreateAndCacheType(PdbTypeSymId type_id);251 lldb::VariableSP CreateGlobalVariable(PdbGlobalSymId var_id);252 lldb::VariableSP CreateConstantSymbol(PdbGlobalSymId var_id,253 const llvm::codeview::CVSymbol &cvs);254 size_t ParseVariablesForCompileUnit(CompileUnit &comp_unit,255 VariableList &variables);256 size_t ParseVariablesForBlock(PdbCompilandSymId block_id);257 258 void CreateSimpleArgumentListTypes(llvm::codeview::TypeIndex arglist_ti);259 260 llvm::Expected<uint32_t> GetFileIndex(const CompilandIndexItem &cii,261 uint32_t file_id);262 263 size_t ParseSymbolArrayInScope(264 PdbCompilandSymId parent,265 llvm::function_ref<bool(llvm::codeview::SymbolKind, PdbCompilandSymId)>266 fn);267 268 void ParseInlineSite(PdbCompilandSymId inline_site_id, Address func_addr);269 270 std::vector<CompilerContext> GetContextForType(llvm::codeview::TypeIndex ti);271 272 /// Caches the basenames of symbols found in the globals stream.273 ///274 /// This includes functions and global variables275 void CacheGlobalBaseNames();276 277 void CacheUdtDeclarations();278 llvm::Expected<Declaration> ResolveUdtDeclaration(PdbTypeSymId type_id);279 280 /// Find a symbol name at a specific address (`so`).281 ///282 /// \param[in] so The segment and offset where the symbol is located.283 /// \param[in] function_type If the symbol is expected to be a function, this284 /// has to be the type of the function. It's used to strip the name of285 /// __cdecl functions on x86.286 /// \returns The mangled symbol name if found, otherwise `std::nullopt`.287 std::optional<llvm::StringRef> FindMangledSymbol(288 SegmentOffset so,289 llvm::codeview::TypeIndex function_type = llvm::codeview::TypeIndex());290 291 llvm::StringRef StripMangledFunctionName(llvm::StringRef mangled,292 PdbTypeSymId func_ty);293 294 llvm::BumpPtrAllocator m_allocator;295 296 lldb::addr_t m_obj_load_address = 0;297 bool m_done_full_type_scan = false;298 // UID for anonymous union and anonymous struct as they don't have entities in299 // pdb debug info.300 lldb::user_id_t anonymous_id = LLDB_INVALID_UID - 1;301 302 std::unique_ptr<llvm::pdb::PDBFile> m_file_up;303 std::unique_ptr<PdbIndex> m_index;304 305 llvm::DenseMap<lldb::user_id_t, lldb::VariableSP> m_global_vars;306 llvm::DenseMap<lldb::user_id_t, lldb::VariableSP> m_local_variables;307 llvm::DenseMap<lldb::user_id_t, lldb::BlockSP> m_blocks;308 llvm::DenseMap<lldb::user_id_t, lldb::FunctionSP> m_functions;309 llvm::DenseMap<lldb::user_id_t, lldb::CompUnitSP> m_compilands;310 llvm::DenseMap<lldb::user_id_t, lldb::TypeSP> m_types;311 llvm::DenseMap<lldb::user_id_t, std::shared_ptr<InlineSite>> m_inline_sites;312 llvm::DenseMap<llvm::codeview::TypeIndex, llvm::codeview::TypeIndex>313 m_parent_types;314 315 struct UdtDeclaration {316 /// This could either be an index into the `/names` section (string table,317 /// LF_UDT_MOD_SRC_LINE) or, this could be an index into the IPI stream to a318 /// LF_STRING_ID record (LF_UDT_SRC_LINE).319 llvm::codeview::TypeIndex FileNameIndex;320 bool IsIpiIndex;321 322 uint32_t Line;323 };324 llvm::DenseMap<llvm::codeview::TypeIndex, UdtDeclaration> m_udt_declarations;325 std::once_flag m_cached_udt_declarations;326 327 lldb_private::UniqueCStringMap<uint32_t> m_type_base_names;328 329 /// mangled name/full function name -> Global ID(s)330 lldb_private::UniqueCStringMap<uint32_t> m_func_full_names;331 /// basename -> Global ID(s)332 lldb_private::UniqueCStringMap<uint32_t> m_func_base_names;333 /// method basename -> Global ID(s)334 lldb_private::UniqueCStringMap<uint32_t> m_func_method_names;335 336 /// global variable basename -> Global ID(s)337 lldb_private::UniqueCStringMap<uint32_t> m_global_variable_base_names;338};339 340} // namespace npdb341} // namespace lldb_private342 343#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H344