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 | |