1 //===-- PdbIndex.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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_PDBINDEX_H 10 #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_PDBINDEX_H 11 12 #include "lldb/lldb-types.h" 13 #include "llvm/ADT/IntervalMap.h" 14 #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 15 #include "llvm/DebugInfo/PDB/PDBTypes.h" 16 17 #include "CompileUnitIndex.h" 18 #include "PdbSymUid.h" 19 20 #include <map> 21 #include <memory> 22 #include <optional> 23 24 namespace llvm { 25 namespace pdb { 26 class DbiStream; 27 class TpiStream; 28 class InfoStream; 29 class PublicsStream; 30 class GlobalsStream; 31 class SymbolStream; 32 } // namespace pdb 33 } // namespace llvm 34 35 namespace lldb_private { 36 namespace npdb { 37 struct SegmentOffset; 38 39 /// PdbIndex - Lazy access to the important parts of a PDB file. 40 /// 41 /// This is a layer on top of LLVM's native PDB support libraries which cache 42 /// certain data when it is accessed the first time. The entire PDB file is 43 /// mapped into memory, and the underlying support libraries vend out memory 44 /// that is always backed by the file, so it is safe to hold StringRefs and 45 /// ArrayRefs into the backing memory as long as the PdbIndex instance is 46 /// alive. 47 class PdbIndex { 48 49 /// The underlying PDB file. 50 llvm::pdb::PDBFile *m_file = nullptr; 51 52 /// The DBI stream. This contains general high level information about the 53 /// features present in the PDB file, compile units (such as the information 54 /// necessary to locate full symbol information for each compile unit), 55 /// section contributions, and other data which is not specifically symbol or 56 /// type records. 57 llvm::pdb::DbiStream *m_dbi = nullptr; 58 59 /// TPI (types) and IPI (indices) streams. These are both in the exact same 60 /// format with different data. Most type records are stored in the TPI 61 /// stream but certain specific types of records are stored in the IPI stream. 62 /// The IPI stream records can refer to the records in the TPI stream, but not 63 /// the other way around. 64 llvm::pdb::TpiStream *m_tpi = nullptr; 65 llvm::pdb::TpiStream *m_ipi = nullptr; 66 67 /// This is called the "PDB Stream" in the Microsoft reference implementation. 68 /// It contains information about the structure of the file, as well as fields 69 /// used to match EXE and PDB. 70 llvm::pdb::InfoStream *m_info = nullptr; 71 72 /// Publics stream. Is actually a serialized hash table where the keys are 73 /// addresses of symbols in the executable, and values are a record containing 74 /// mangled names and an index which can be used to locate more detailed info 75 /// about the symbol in the Symbol Records stream. The publics stream only 76 /// contains info about externally visible symbols. 77 llvm::pdb::PublicsStream *m_publics = nullptr; 78 79 /// Globals stream. Contrary to its name, this does not contain information 80 /// about all "global variables" or "global functions". Rather, it is the 81 /// "global symbol table", i.e. it contains information about *every* symbol 82 /// in the executable. It is a hash table keyed on name, whose values are 83 /// indices into the symbol records stream to find the full record. 84 llvm::pdb::GlobalsStream *m_globals = nullptr; 85 86 /// Symbol records stream. The publics and globals stream refer to records 87 /// in this stream. For some records, like constants and typedefs, the 88 /// complete record lives in this stream. For other symbol types, such as 89 /// functions, data, and other things that have been materialied into a 90 /// specific compile unit, the records here simply provide a reference 91 /// necessary to locate the full information. 92 llvm::pdb::SymbolStream *m_symrecords = nullptr; 93 94 /// Index of all compile units, mapping identifier to |CompilandIndexItem| 95 /// instance. 96 CompileUnitIndex m_cus; 97 98 /// An allocator for the interval maps 99 llvm::IntervalMap<lldb::addr_t, uint32_t>::Allocator m_allocator; 100 101 /// Maps virtual address to module index 102 llvm::IntervalMap<lldb::addr_t, uint16_t> m_va_to_modi; 103 104 /// The address at which the program has been loaded into memory. 105 lldb::addr_t m_load_address = 0; 106 107 PdbIndex(); 108 109 void BuildAddrToSymbolMap(CompilandIndexItem &cci); 110 111 public: 112 static llvm::Expected<std::unique_ptr<PdbIndex>> create(llvm::pdb::PDBFile *); 113 SetLoadAddress(lldb::addr_t addr)114 void SetLoadAddress(lldb::addr_t addr) { m_load_address = addr; } GetLoadAddress()115 lldb::addr_t GetLoadAddress() const { return m_load_address; } 116 void ParseSectionContribs(); 117 pdb()118 llvm::pdb::PDBFile &pdb() { return *m_file; } pdb()119 const llvm::pdb::PDBFile &pdb() const { return *m_file; } 120 dbi()121 llvm::pdb::DbiStream &dbi() { return *m_dbi; } dbi()122 const llvm::pdb::DbiStream &dbi() const { return *m_dbi; } 123 tpi()124 llvm::pdb::TpiStream &tpi() { return *m_tpi; } tpi()125 const llvm::pdb::TpiStream &tpi() const { return *m_tpi; } 126 ipi()127 llvm::pdb::TpiStream &ipi() { return *m_ipi; } ipi()128 const llvm::pdb::TpiStream &ipi() const { return *m_ipi; } 129 info()130 llvm::pdb::InfoStream &info() { return *m_info; } info()131 const llvm::pdb::InfoStream &info() const { return *m_info; } 132 publics()133 llvm::pdb::PublicsStream &publics() { return *m_publics; } publics()134 const llvm::pdb::PublicsStream &publics() const { return *m_publics; } 135 globals()136 llvm::pdb::GlobalsStream &globals() { return *m_globals; } globals()137 const llvm::pdb::GlobalsStream &globals() const { return *m_globals; } 138 symrecords()139 llvm::pdb::SymbolStream &symrecords() { return *m_symrecords; } symrecords()140 const llvm::pdb::SymbolStream &symrecords() const { return *m_symrecords; } 141 compilands()142 CompileUnitIndex &compilands() { return m_cus; } compilands()143 const CompileUnitIndex &compilands() const { return m_cus; } 144 145 lldb::addr_t MakeVirtualAddress(uint16_t segment, uint32_t offset) const; 146 147 std::vector<SymbolAndUid> FindSymbolsByVa(lldb::addr_t va); 148 149 llvm::codeview::CVSymbol ReadSymbolRecord(PdbCompilandSymId cu_sym) const; 150 llvm::codeview::CVSymbol ReadSymbolRecord(PdbGlobalSymId global) const; 151 152 std::optional<uint16_t> GetModuleIndexForAddr(uint16_t segment, 153 uint32_t offset) const; 154 std::optional<uint16_t> GetModuleIndexForVa(lldb::addr_t va) const; 155 }; 156 } // namespace npdb 157 } // namespace lldb_private 158 159 #endif 160