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