14
14
#include " SymbolTable.h"
15
15
#include " Symbols.h"
16
16
#include " llvm/DebugInfo/CodeView/CVDebugRecord.h"
17
- #include " llvm/DebugInfo/CodeView/CVTypeVisitor.h"
18
17
#include " llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
19
- #include " llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
20
18
#include " llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
21
19
#include " llvm/DebugInfo/CodeView/SymbolSerializer.h"
20
+ #include " llvm/DebugInfo/CodeView/TypeDeserializer.h"
22
21
#include " llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
23
22
#include " llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
24
23
#include " llvm/DebugInfo/CodeView/TypeStreamMerger.h"
25
24
#include " llvm/DebugInfo/CodeView/TypeTableBuilder.h"
26
25
#include " llvm/DebugInfo/MSF/MSFBuilder.h"
27
26
#include " llvm/DebugInfo/MSF/MSFCommon.h"
27
+ #include " llvm/DebugInfo/PDB/GenericError.h"
28
28
#include " llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
29
29
#include " llvm/DebugInfo/PDB/Native/DbiStream.h"
30
30
#include " llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
31
31
#include " llvm/DebugInfo/PDB/Native/InfoStream.h"
32
32
#include " llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
33
+ #include " llvm/DebugInfo/PDB/Native/NativeSession.h"
33
34
#include " llvm/DebugInfo/PDB/Native/PDBFile.h"
34
35
#include " llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
35
36
#include " llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
36
37
#include " llvm/DebugInfo/PDB/Native/TpiStream.h"
37
38
#include " llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
39
+ #include " llvm/DebugInfo/PDB/PDB.h"
38
40
#include " llvm/Object/COFF.h"
39
41
#include " llvm/Support/BinaryByteStream.h"
40
42
#include " llvm/Support/Endian.h"
@@ -53,6 +55,14 @@ using llvm::object::coff_section;
53
55
static ExitOnError ExitOnErr;
54
56
55
57
namespace {
58
+ // / Map from type index and item index in a type server PDB to the
59
+ // / corresponding index in the destination PDB.
60
+ struct CVIndexMap {
61
+ SmallVector<TypeIndex, 0 > TPIMap;
62
+ SmallVector<TypeIndex, 0 > IPIMap;
63
+ bool IsTypeServerMap = false ;
64
+ };
65
+
56
66
class PDBLinker {
57
67
public:
58
68
PDBLinker (SymbolTable *Symtab)
@@ -68,10 +78,21 @@ class PDBLinker {
68
78
// / Link CodeView from a single object file into the PDB.
69
79
void addObjectFile (ObjectFile *File);
70
80
71
- // / Merge the type information from the .debug$T section in the given object
72
- // / file. Produce a mapping from object file type indices to type or
73
- // / item indices in the final PDB.
74
- void mergeDebugT (ObjectFile *File, SmallVectorImpl<TypeIndex> &TypeIndexMap);
81
+ // / Produce a mapping from the type and item indices used in the object
82
+ // / file to those in the destination PDB.
83
+ // /
84
+ // / If the object file uses a type server PDB (compiled with /Zi), merge TPI
85
+ // / and IPI from the type server PDB and return a map for it. Each unique type
86
+ // / server PDB is merged at most once, so this may return an existing index
87
+ // / mapping.
88
+ // /
89
+ // / If the object does not use a type server PDB (compiled with /Z7), we merge
90
+ // / all the type and item records from the .debug$S stream and fill in the
91
+ // / caller-provided ObjectIndexMap.
92
+ const CVIndexMap &mergeDebugT (ObjectFile *File, CVIndexMap &ObjectIndexMap);
93
+
94
+ const CVIndexMap &maybeMergeTypeServerPDB (ObjectFile *File,
95
+ TypeServer2Record &TS);
75
96
76
97
// / Add the section map and section contributions to the PDB.
77
98
void addSections (ArrayRef<uint8_t > SectionTable);
@@ -99,6 +120,9 @@ class PDBLinker {
99
120
llvm::SmallString<128 > NativePath;
100
121
101
122
std::vector<pdb::SecMapEntry> SectionMap;
123
+
124
+ // / Type index mappings of type server PDBs that we've loaded so far.
125
+ std::map<GUID, CVIndexMap> TypeServerIndexMappings;
102
126
};
103
127
}
104
128
@@ -146,25 +170,114 @@ static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
146
170
});
147
171
}
148
172
149
- void PDBLinker::mergeDebugT (ObjectFile *File,
150
- SmallVectorImpl<TypeIndex> &TypeIndexMap) {
173
+ static Optional<TypeServer2Record>
174
+ maybeReadTypeServerRecord (CVTypeArray &Types) {
175
+ auto I = Types.begin ();
176
+ if (I == Types.end ())
177
+ return None;
178
+ const CVType &Type = *I;
179
+ if (Type.kind () != LF_TYPESERVER2)
180
+ return None;
181
+ TypeServer2Record TS;
182
+ if (auto EC = TypeDeserializer::deserializeAs (const_cast <CVType &>(Type), TS))
183
+ fatal (EC, " error reading type server record" );
184
+ return std::move (TS);
185
+ }
186
+
187
+ const CVIndexMap &PDBLinker::mergeDebugT (ObjectFile *File,
188
+ CVIndexMap &ObjectIndexMap) {
151
189
ArrayRef<uint8_t > Data = getDebugSection (File, " .debug$T" );
152
190
if (Data.empty ())
153
- return ;
154
-
155
- // Look for type server PDBs next to the input file. If this file has a parent
156
- // archive, look next to the archive path.
157
- StringRef LocalPath =
158
- !File->ParentName .empty () ? File->ParentName : File->getName ();
159
- (void )LocalPath; // FIXME: Implement type server handling here.
191
+ return ObjectIndexMap;
160
192
161
193
BinaryByteStream Stream (Data, support::little);
162
194
CVTypeArray Types;
163
195
BinaryStreamReader Reader (Stream);
164
196
if (auto EC = Reader.readArray (Types, Reader.getLength ()))
165
197
fatal (EC, " Reader::readArray failed" );
166
- if (auto Err = mergeTypeAndIdRecords (IDTable, TypeTable, TypeIndexMap, Types))
167
- fatal (Err, " codeview::mergeTypeStreams failed" );
198
+
199
+ // Look through type servers. If we've already seen this type server, don't
200
+ // merge any type information.
201
+ if (Optional<TypeServer2Record> TS = maybeReadTypeServerRecord (Types))
202
+ return maybeMergeTypeServerPDB (File, *TS);
203
+
204
+ // This is a /Z7 object. Fill in the temporary, caller-provided
205
+ // ObjectIndexMap.
206
+ if (auto Err = mergeTypeAndIdRecords (IDTable, TypeTable,
207
+ ObjectIndexMap.TPIMap , Types))
208
+ fatal (Err, " codeview::mergeTypeAndIdRecords failed" );
209
+ return ObjectIndexMap;
210
+ }
211
+
212
+ static Expected<std::unique_ptr<pdb::NativeSession>>
213
+ tryToLoadPDB (const GUID &GuidFromObj, StringRef TSPath) {
214
+ std::unique_ptr<pdb::IPDBSession> ThisSession;
215
+ if (auto EC =
216
+ pdb::loadDataForPDB (pdb::PDB_ReaderType::Native, TSPath, ThisSession))
217
+ return std::move (EC);
218
+
219
+ std::unique_ptr<pdb::NativeSession> NS (
220
+ static_cast <pdb::NativeSession *>(ThisSession.release()));
221
+ pdb::PDBFile &File = NS->getPDBFile ();
222
+ auto ExpectedInfo = File.getPDBInfoStream ();
223
+ // All PDB Files should have an Info stream.
224
+ if (!ExpectedInfo)
225
+ return ExpectedInfo.takeError ();
226
+
227
+ // Just because a file with a matching name was found and it was an actual
228
+ // PDB file doesn't mean it matches. For it to match the InfoStream's GUID
229
+ // must match the GUID specified in the TypeServer2 record.
230
+ if (ExpectedInfo->getGuid () != GuidFromObj)
231
+ return make_error<pdb::GenericError>(
232
+ pdb::generic_error_code::type_server_not_found, TSPath);
233
+
234
+ return std::move (NS);
235
+ }
236
+
237
+ const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB (ObjectFile *File,
238
+ TypeServer2Record &TS) {
239
+ // First, check if we already loaded a PDB with this GUID. Return the type
240
+ // index mapping if we have it.
241
+ auto Insertion = TypeServerIndexMappings.insert ({TS.getGuid (), CVIndexMap ()});
242
+ CVIndexMap &IndexMap = Insertion.first ->second ;
243
+ if (!Insertion.second )
244
+ return IndexMap;
245
+
246
+ // Mark this map as a type server map.
247
+ IndexMap.IsTypeServerMap = true ;
248
+
249
+ // Check for a PDB at:
250
+ // 1. The given file path
251
+ // 2. Next to the object file or archive file
252
+ auto ExpectedSession = tryToLoadPDB (TS.getGuid (), TS.getName ());
253
+ if (!ExpectedSession) {
254
+ consumeError (ExpectedSession.takeError ());
255
+ StringRef LocalPath =
256
+ !File->ParentName .empty () ? File->ParentName : File->getName ();
257
+ SmallString<128 > Path = sys::path::parent_path (LocalPath);
258
+ sys::path::append (Path, sys::path::filename (TS.getName ()));
259
+ ExpectedSession = tryToLoadPDB (TS.getGuid (), Path);
260
+ }
261
+ if (auto E = ExpectedSession.takeError ())
262
+ fatal (E, " Type server PDB was not found" );
263
+
264
+ // Merge TPI first, because the IPI stream will reference type indices.
265
+ auto ExpectedTpi = (*ExpectedSession)->getPDBFile ().getPDBTpiStream ();
266
+ if (auto E = ExpectedTpi.takeError ())
267
+ fatal (E, " Type server does not have TPI stream" );
268
+ if (auto Err = mergeTypeRecords (TypeTable, IndexMap.TPIMap ,
269
+ ExpectedTpi->typeArray ()))
270
+ fatal (Err, " codeview::mergeTypeRecords failed" );
271
+
272
+ // Merge IPI.
273
+ auto ExpectedIpi = (*ExpectedSession)->getPDBFile ().getPDBIpiStream ();
274
+ if (auto E = ExpectedIpi.takeError ())
275
+ fatal (E, " Type server does not have TPI stream" );
276
+ if (auto Err = mergeIdRecords (IDTable, IndexMap.TPIMap , IndexMap.IPIMap ,
277
+ ExpectedIpi->typeArray ()))
278
+ fatal (Err, " codeview::mergeIdRecords failed" );
279
+
280
+ return IndexMap;
168
281
}
169
282
170
283
static bool remapTypeIndex (TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) {
@@ -178,16 +291,22 @@ static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) {
178
291
179
292
static void remapTypesInSymbolRecord (ObjectFile *File,
180
293
MutableArrayRef<uint8_t > Contents,
181
- ArrayRef<TypeIndex> TypeIndexMap ,
294
+ const CVIndexMap &IndexMap ,
182
295
ArrayRef<TiReference> TypeRefs) {
183
296
for (const TiReference &Ref : TypeRefs) {
184
297
unsigned ByteSize = Ref.Count * sizeof (TypeIndex);
185
298
if (Contents.size () < Ref.Offset + ByteSize)
186
299
fatal (" symbol record too short" );
300
+
301
+ // This can be an item index or a type index. Choose the appropriate map.
302
+ ArrayRef<TypeIndex> TypeOrItemMap = IndexMap.TPIMap ;
303
+ if (Ref.Kind == TiRefKind::IndexRef && IndexMap.IsTypeServerMap )
304
+ TypeOrItemMap = IndexMap.IPIMap ;
305
+
187
306
MutableArrayRef<TypeIndex> TIs (
188
307
reinterpret_cast <TypeIndex *>(Contents.data () + Ref.Offset ), Ref.Count );
189
308
for (TypeIndex &TI : TIs) {
190
- if (!remapTypeIndex (TI, TypeIndexMap )) {
309
+ if (!remapTypeIndex (TI, TypeOrItemMap )) {
191
310
TI = TypeIndex (SimpleTypeKind::NotTranslated);
192
311
log (" ignoring symbol record in " + File->getName () +
193
312
" with bad type index 0x" + utohexstr (TI.getIndex ()));
@@ -292,7 +411,7 @@ static void scopeStackClose(SmallVectorImpl<SymbolScope> &Stack,
292
411
}
293
412
294
413
static void mergeSymbolRecords (BumpPtrAllocator &Alloc, ObjectFile *File,
295
- ArrayRef<TypeIndex> TypeIndexMap ,
414
+ const CVIndexMap &IndexMap ,
296
415
BinaryStreamRef SymData) {
297
416
// FIXME: Improve error recovery by warning and skipping records when
298
417
// possible.
@@ -315,7 +434,7 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File,
315
434
// Re-map all the type index references.
316
435
MutableArrayRef<uint8_t > Contents =
317
436
NewData.drop_front (sizeof (RecordPrefix));
318
- remapTypesInSymbolRecord (File, Contents, TypeIndexMap , TypeRefs);
437
+ remapTypesInSymbolRecord (File, Contents, IndexMap , TypeRefs);
319
438
320
439
// Fill in "Parent" and "End" fields by maintaining a stack of scopes.
321
440
CVSymbol NewSym (Sym.kind (), NewData);
@@ -358,8 +477,8 @@ void PDBLinker::addObjectFile(ObjectFile *File) {
358
477
// type information, file checksums, and the string table. Add type info to
359
478
// the PDB first, so that we can get the map from object file type and item
360
479
// indices to PDB type and item indices.
361
- SmallVector<TypeIndex, 128 > TypeIndexMap ;
362
- mergeDebugT (File, TypeIndexMap );
480
+ CVIndexMap ObjectIndexMap ;
481
+ const CVIndexMap &IndexMap = mergeDebugT (File, ObjectIndexMap );
363
482
364
483
// Now do all live .debug$S sections.
365
484
for (SectionChunk *DebugChunk : File->getDebugChunks ()) {
@@ -391,7 +510,7 @@ void PDBLinker::addObjectFile(ObjectFile *File) {
391
510
File->ModuleDBI ->addDebugSubsection (SS);
392
511
break ;
393
512
case DebugSubsectionKind::Symbols:
394
- mergeSymbolRecords (Alloc, File, TypeIndexMap , SS.getRecordData ());
513
+ mergeSymbolRecords (Alloc, File, IndexMap , SS.getRecordData ());
395
514
break ;
396
515
default :
397
516
// FIXME: Process the rest of the subsections.
0 commit comments