DebugTypes.h
6.76 KB
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
//===- DebugTypes.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 LLD_COFF_DEBUGTYPES_H
#define LLD_COFF_DEBUGTYPES_H
#include "lld/Common/LLVM.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
namespace llvm {
namespace codeview {
struct GloballyHashedType;
} // namespace codeview
namespace pdb {
class NativeSession;
class TpiStream;
}
} // namespace llvm
namespace lld {
namespace coff {
using llvm::codeview::GloballyHashedType;
using llvm::codeview::TypeIndex;
class ObjFile;
class PDBInputFile;
class TypeMerger;
struct GHashState;
class TpiSource {
public:
enum TpiKind : uint8_t { Regular, PCH, UsingPCH, PDB, PDBIpi, UsingPDB };
TpiSource(TpiKind k, ObjFile *f);
virtual ~TpiSource();
/// Produce a mapping from the type and item indices used in the object
/// file to those in the destination PDB.
///
/// If the object file uses a type server PDB (compiled with /Zi), merge TPI
/// and IPI from the type server PDB and return a map for it. Each unique type
/// server PDB is merged at most once, so this may return an existing index
/// mapping.
///
/// If the object does not use a type server PDB (compiled with /Z7), we merge
/// all the type and item records from the .debug$S stream and fill in the
/// caller-provided ObjectIndexMap.
virtual Error mergeDebugT(TypeMerger *m);
/// Load global hashes, either by hashing types directly, or by loading them
/// from LLVM's .debug$H section.
virtual void loadGHashes();
/// Use global hashes to merge type information.
virtual void remapTpiWithGHashes(GHashState *g);
// Remap a type index in place.
bool remapTypeIndex(TypeIndex &ti, llvm::codeview::TiRefKind refKind) const;
protected:
void remapRecord(MutableArrayRef<uint8_t> rec,
ArrayRef<llvm::codeview::TiReference> typeRefs);
void mergeTypeRecord(TypeIndex curIndex, llvm::codeview::CVType ty);
// Merge the type records listed in uniqueTypes. beginIndex is the TypeIndex
// of the first record in this source, typically 0x1000. When PCHs are
// involved, it may start higher.
void mergeUniqueTypeRecords(
ArrayRef<uint8_t> debugTypes,
TypeIndex beginIndex = TypeIndex(TypeIndex::FirstNonSimpleIndex));
// Use the ghash table to construct a map from source type index to
// destination PDB type index. Usable for either TPI or IPI.
void fillMapFromGHashes(GHashState *m,
llvm::SmallVectorImpl<TypeIndex> &indexMap);
// Copies ghashes from a vector into an array. These are long lived, so it's
// worth the time to copy these into an appropriately sized vector to reduce
// memory usage.
void assignGHashesFromVector(std::vector<GloballyHashedType> &&hashVec);
// Walk over file->debugTypes and fill in the isItemIndex bit vector.
void fillIsItemIndexFromDebugT();
public:
bool remapTypesInSymbolRecord(MutableArrayRef<uint8_t> rec);
void remapTypesInTypeRecord(MutableArrayRef<uint8_t> rec);
/// Is this a dependent file that needs to be processed first, before other
/// OBJs?
virtual bool isDependency() const { return false; }
/// Returns true if this type record should be omitted from the PDB, even if
/// it is unique. This prevents a record from being added to the input ghash
/// table.
bool shouldOmitFromPdb(uint32_t ghashIdx) {
return ghashIdx == endPrecompGHashIdx;
}
/// All sources of type information in the program.
static std::vector<TpiSource *> instances;
/// Dependency type sources, such as type servers or PCH object files. These
/// must be processed before objects that rely on them. Set by
/// TpiSources::sortDependencies.
static ArrayRef<TpiSource *> dependencySources;
/// Object file sources. These must be processed after dependencySources.
static ArrayRef<TpiSource *> objectSources;
/// Sorts the dependencies and reassigns TpiSource indices.
static void sortDependencies();
static uint32_t countTypeServerPDBs();
static uint32_t countPrecompObjs();
/// Free heap allocated ghashes.
static void clearGHashes();
/// Clear global data structures for TpiSources.
static void clear();
const TpiKind kind;
bool ownedGHashes = true;
uint32_t tpiSrcIdx = 0;
protected:
/// The ghash index (zero based, not 0x1000-based) of the LF_ENDPRECOMP record
/// in this object, if one exists. This is the all ones value otherwise. It is
/// recorded here so that it can be omitted from the final ghash table.
uint32_t endPrecompGHashIdx = ~0U;
public:
ObjFile *file;
/// An error encountered during type merging, if any.
Error typeMergingError = Error::success();
// Storage for tpiMap or ipiMap, depending on the kind of source.
llvm::SmallVector<TypeIndex, 0> indexMapStorage;
// Source type index to PDB type index mapping for type and item records.
// These mappings will be the same for /Z7 objects, and distinct for /Zi
// objects.
llvm::ArrayRef<TypeIndex> tpiMap;
llvm::ArrayRef<TypeIndex> ipiMap;
/// Array of global type hashes, indexed by TypeIndex. May be calculated on
/// demand, or present in input object files.
llvm::ArrayRef<llvm::codeview::GloballyHashedType> ghashes;
/// When ghashing is used, record the mapping from LF_[M]FUNC_ID to function
/// type index here. Both indices are PDB indices, not object type indexes.
std::vector<std::pair<TypeIndex, TypeIndex>> funcIdToType;
/// Indicates if a type record is an item index or a type index.
llvm::BitVector isItemIndex;
/// A list of all "unique" type indices which must be merged into the final
/// PDB. GHash type deduplication produces this list, and it should be
/// considerably smaller than the input.
std::vector<uint32_t> uniqueTypes;
struct MergedInfo {
std::vector<uint8_t> recs;
std::vector<uint16_t> recSizes;
std::vector<uint32_t> recHashes;
};
MergedInfo mergedTpi;
MergedInfo mergedIpi;
uint64_t nbTypeRecords = 0;
uint64_t nbTypeRecordsBytes = 0;
};
TpiSource *makeTpiSource(ObjFile *file);
TpiSource *makeTypeServerSource(PDBInputFile *pdbInputFile);
TpiSource *makeUseTypeServerSource(ObjFile *file,
llvm::codeview::TypeServer2Record ts);
TpiSource *makePrecompSource(ObjFile *file);
TpiSource *makeUsePrecompSource(ObjFile *file,
llvm::codeview::PrecompRecord ts);
} // namespace coff
} // namespace lld
#endif