10b57cec5SDimitry Andric //===-- PdbIndex.h ----------------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 95ffd83dbSDimitry Andric #ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_PDBINDEX_H 105ffd83dbSDimitry Andric #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_PDBINDEX_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "lldb/lldb-types.h" 130b57cec5SDimitry Andric #include "llvm/ADT/IntervalMap.h" 140b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 150b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBTypes.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "CompileUnitIndex.h" 180b57cec5SDimitry Andric #include "PdbSymUid.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #include <map> 210b57cec5SDimitry Andric #include <memory> 22bdd1243dSDimitry Andric #include <optional> 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace llvm { 250b57cec5SDimitry Andric namespace pdb { 260b57cec5SDimitry Andric class DbiStream; 270b57cec5SDimitry Andric class TpiStream; 280b57cec5SDimitry Andric class InfoStream; 290b57cec5SDimitry Andric class PublicsStream; 300b57cec5SDimitry Andric class GlobalsStream; 310b57cec5SDimitry Andric class SymbolStream; 320b57cec5SDimitry Andric } // namespace pdb 330b57cec5SDimitry Andric } // namespace llvm 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric namespace lldb_private { 360b57cec5SDimitry Andric namespace npdb { 370b57cec5SDimitry Andric struct SegmentOffset; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric /// PdbIndex - Lazy access to the important parts of a PDB file. 400b57cec5SDimitry Andric /// 410b57cec5SDimitry Andric /// This is a layer on top of LLVM's native PDB support libraries which cache 420b57cec5SDimitry Andric /// certain data when it is accessed the first time. The entire PDB file is 430b57cec5SDimitry Andric /// mapped into memory, and the underlying support libraries vend out memory 440b57cec5SDimitry Andric /// that is always backed by the file, so it is safe to hold StringRefs and 450b57cec5SDimitry Andric /// ArrayRefs into the backing memory as long as the PdbIndex instance is 460b57cec5SDimitry Andric /// alive. 470b57cec5SDimitry Andric class PdbIndex { 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric /// The underlying PDB file. 50e8d8bef9SDimitry Andric llvm::pdb::PDBFile *m_file = nullptr; 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric /// The DBI stream. This contains general high level information about the 530b57cec5SDimitry Andric /// features present in the PDB file, compile units (such as the information 540b57cec5SDimitry Andric /// necessary to locate full symbol information for each compile unit), 550b57cec5SDimitry Andric /// section contributions, and other data which is not specifically symbol or 560b57cec5SDimitry Andric /// type records. 570b57cec5SDimitry Andric llvm::pdb::DbiStream *m_dbi = nullptr; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric /// TPI (types) and IPI (indices) streams. These are both in the exact same 600b57cec5SDimitry Andric /// format with different data. Most type records are stored in the TPI 610b57cec5SDimitry Andric /// stream but certain specific types of records are stored in the IPI stream. 620b57cec5SDimitry Andric /// The IPI stream records can refer to the records in the TPI stream, but not 630b57cec5SDimitry Andric /// the other way around. 640b57cec5SDimitry Andric llvm::pdb::TpiStream *m_tpi = nullptr; 650b57cec5SDimitry Andric llvm::pdb::TpiStream *m_ipi = nullptr; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric /// This is called the "PDB Stream" in the Microsoft reference implementation. 680b57cec5SDimitry Andric /// It contains information about the structure of the file, as well as fields 690b57cec5SDimitry Andric /// used to match EXE and PDB. 700b57cec5SDimitry Andric llvm::pdb::InfoStream *m_info = nullptr; 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric /// Publics stream. Is actually a serialized hash table where the keys are 730b57cec5SDimitry Andric /// addresses of symbols in the executable, and values are a record containing 740b57cec5SDimitry Andric /// mangled names and an index which can be used to locate more detailed info 750b57cec5SDimitry Andric /// about the symbol in the Symbol Records stream. The publics stream only 760b57cec5SDimitry Andric /// contains info about externally visible symbols. 770b57cec5SDimitry Andric llvm::pdb::PublicsStream *m_publics = nullptr; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric /// Globals stream. Contrary to its name, this does not contain information 800b57cec5SDimitry Andric /// about all "global variables" or "global functions". Rather, it is the 810b57cec5SDimitry Andric /// "global symbol table", i.e. it contains information about *every* symbol 820b57cec5SDimitry Andric /// in the executable. It is a hash table keyed on name, whose values are 830b57cec5SDimitry Andric /// indices into the symbol records stream to find the full record. 840b57cec5SDimitry Andric llvm::pdb::GlobalsStream *m_globals = nullptr; 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric /// Symbol records stream. The publics and globals stream refer to records 870b57cec5SDimitry Andric /// in this stream. For some records, like constants and typedefs, the 880b57cec5SDimitry Andric /// complete record lives in this stream. For other symbol types, such as 890b57cec5SDimitry Andric /// functions, data, and other things that have been materialied into a 900b57cec5SDimitry Andric /// specific compile unit, the records here simply provide a reference 910b57cec5SDimitry Andric /// necessary to locate the full information. 920b57cec5SDimitry Andric llvm::pdb::SymbolStream *m_symrecords = nullptr; 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric /// Index of all compile units, mapping identifier to |CompilandIndexItem| 950b57cec5SDimitry Andric /// instance. 960b57cec5SDimitry Andric CompileUnitIndex m_cus; 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric /// An allocator for the interval maps 990b57cec5SDimitry Andric llvm::IntervalMap<lldb::addr_t, uint32_t>::Allocator m_allocator; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric /// Maps virtual address to module index 1020b57cec5SDimitry Andric llvm::IntervalMap<lldb::addr_t, uint16_t> m_va_to_modi; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric /// The address at which the program has been loaded into memory. 1050b57cec5SDimitry Andric lldb::addr_t m_load_address = 0; 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric PdbIndex(); 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric void BuildAddrToSymbolMap(CompilandIndexItem &cci); 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric public: 112e8d8bef9SDimitry Andric static llvm::Expected<std::unique_ptr<PdbIndex>> create(llvm::pdb::PDBFile *); 1130b57cec5SDimitry Andric SetLoadAddress(lldb::addr_t addr)1140b57cec5SDimitry Andric void SetLoadAddress(lldb::addr_t addr) { m_load_address = addr; } GetLoadAddress()1150b57cec5SDimitry Andric lldb::addr_t GetLoadAddress() const { return m_load_address; } 1160b57cec5SDimitry Andric void ParseSectionContribs(); 1170b57cec5SDimitry Andric pdb()1180b57cec5SDimitry Andric llvm::pdb::PDBFile &pdb() { return *m_file; } pdb()1190b57cec5SDimitry Andric const llvm::pdb::PDBFile &pdb() const { return *m_file; } 1200b57cec5SDimitry Andric dbi()1210b57cec5SDimitry Andric llvm::pdb::DbiStream &dbi() { return *m_dbi; } dbi()1220b57cec5SDimitry Andric const llvm::pdb::DbiStream &dbi() const { return *m_dbi; } 1230b57cec5SDimitry Andric tpi()1240b57cec5SDimitry Andric llvm::pdb::TpiStream &tpi() { return *m_tpi; } tpi()1250b57cec5SDimitry Andric const llvm::pdb::TpiStream &tpi() const { return *m_tpi; } 1260b57cec5SDimitry Andric ipi()1270b57cec5SDimitry Andric llvm::pdb::TpiStream &ipi() { return *m_ipi; } ipi()1280b57cec5SDimitry Andric const llvm::pdb::TpiStream &ipi() const { return *m_ipi; } 1290b57cec5SDimitry Andric info()1300b57cec5SDimitry Andric llvm::pdb::InfoStream &info() { return *m_info; } info()1310b57cec5SDimitry Andric const llvm::pdb::InfoStream &info() const { return *m_info; } 1320b57cec5SDimitry Andric publics()1330b57cec5SDimitry Andric llvm::pdb::PublicsStream &publics() { return *m_publics; } publics()1340b57cec5SDimitry Andric const llvm::pdb::PublicsStream &publics() const { return *m_publics; } 1350b57cec5SDimitry Andric globals()1360b57cec5SDimitry Andric llvm::pdb::GlobalsStream &globals() { return *m_globals; } globals()1370b57cec5SDimitry Andric const llvm::pdb::GlobalsStream &globals() const { return *m_globals; } 1380b57cec5SDimitry Andric symrecords()1390b57cec5SDimitry Andric llvm::pdb::SymbolStream &symrecords() { return *m_symrecords; } symrecords()1400b57cec5SDimitry Andric const llvm::pdb::SymbolStream &symrecords() const { return *m_symrecords; } 1410b57cec5SDimitry Andric compilands()1420b57cec5SDimitry Andric CompileUnitIndex &compilands() { return m_cus; } compilands()1430b57cec5SDimitry Andric const CompileUnitIndex &compilands() const { return m_cus; } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric lldb::addr_t MakeVirtualAddress(uint16_t segment, uint32_t offset) const; 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric std::vector<SymbolAndUid> FindSymbolsByVa(lldb::addr_t va); 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric llvm::codeview::CVSymbol ReadSymbolRecord(PdbCompilandSymId cu_sym) const; 1500b57cec5SDimitry Andric llvm::codeview::CVSymbol ReadSymbolRecord(PdbGlobalSymId global) const; 1510b57cec5SDimitry Andric 152bdd1243dSDimitry Andric std::optional<uint16_t> GetModuleIndexForAddr(uint16_t segment, 1530b57cec5SDimitry Andric uint32_t offset) const; 154bdd1243dSDimitry Andric std::optional<uint16_t> GetModuleIndexForVa(lldb::addr_t va) const; 1550b57cec5SDimitry Andric }; 1560b57cec5SDimitry Andric } // namespace npdb 1570b57cec5SDimitry Andric } // namespace lldb_private 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric #endif 160