| 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 | |
| 114 | void SetLoadAddress(lldb::addr_t addr) { m_load_address = addr; } |
| 115 | lldb::addr_t GetLoadAddress() const { return m_load_address; } |
| 116 | void ParseSectionContribs(); |
| 117 | |
| 118 | llvm::pdb::PDBFile &pdb() { return *m_file; } |
| 119 | const llvm::pdb::PDBFile &pdb() const { return *m_file; } |
| 120 | |
| 121 | llvm::pdb::DbiStream &dbi() { return *m_dbi; } |
| 122 | const llvm::pdb::DbiStream &dbi() const { return *m_dbi; } |
| 123 | |
| 124 | llvm::pdb::TpiStream &tpi() { return *m_tpi; } |
| 125 | const llvm::pdb::TpiStream &tpi() const { return *m_tpi; } |
| 126 | |
| 127 | llvm::pdb::TpiStream &ipi() { return *m_ipi; } |
| 128 | const llvm::pdb::TpiStream &ipi() const { return *m_ipi; } |
| 129 | |
| 130 | llvm::pdb::InfoStream &info() { return *m_info; } |
| 131 | const llvm::pdb::InfoStream &info() const { return *m_info; } |
| 132 | |
| 133 | llvm::pdb::PublicsStream &publics() { return *m_publics; } |
| 134 | const llvm::pdb::PublicsStream &publics() const { return *m_publics; } |
| 135 | |
| 136 | llvm::pdb::GlobalsStream &globals() { return *m_globals; } |
| 137 | const llvm::pdb::GlobalsStream &globals() const { return *m_globals; } |
| 138 | |
| 139 | llvm::pdb::SymbolStream &symrecords() { return *m_symrecords; } |
| 140 | const llvm::pdb::SymbolStream &symrecords() const { return *m_symrecords; } |
| 141 | |
| 142 | CompileUnitIndex &compilands() { return m_cus; } |
| 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 | |