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