llvm.org GIT mirror llvm / 4a52ea2
[COFF][LLD] Add link support for Microsoft precompiled headers OBJs This change allows for link-time merging of debugging information from Microsoft precompiled types OBJs compiled with cl.exe /Z7 /Yc and /Yu. This fixes llvm.org/PR34278 Differential Revision: https://reviews.llvm.org/D45213 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@346154 91177308-0d34-0410-b5e6-96231b3b80d8 Alexandre Ganea 11 months ago
7 changed file(s) with 103 addition(s) and 52 deletion(s). Raw diff Collapse all Expand all
8282 Error mergeTypeAndIdRecords(MergingTypeTableBuilder &DestIds,
8383 MergingTypeTableBuilder &DestTypes,
8484 SmallVectorImpl &SourceToDest,
85 const CVTypeArray &IdsAndTypes);
85 const CVTypeArray &IdsAndTypes,
86 Optional &EndPrecomp);
8687
8788 Error mergeTypeAndIdRecords(GlobalTypeTableBuilder &DestIds,
8889 GlobalTypeTableBuilder &DestTypes,
8990 SmallVectorImpl &SourceToDest,
9091 const CVTypeArray &IdsAndTypes,
91 ArrayRef Hashes);
92 ArrayRef Hashes,
93 Optional &EndPrecomp);
9294
9395 Error mergeTypeRecords(GlobalTypeTableBuilder &Dest,
9496 SmallVectorImpl &SourceToDest,
9597 const CVTypeArray &Types,
96 ArrayRef Hashes);
98 ArrayRef Hashes,
99 Optional &EndPrecomp);
97100
98101 Error mergeIdRecords(GlobalTypeTableBuilder &Dest, ArrayRef Types,
99102 SmallVectorImpl &SourceToDest,
2020 dia_sdk_not_present,
2121 dia_failed_loading,
2222 signature_out_of_date,
23 type_server_not_found,
2423 unspecified,
2524 };
26 } // namespace codeview
25 } // namespace pdb
2726 } // namespace llvm
2827
2928 namespace std {
30 template <>
31 struct is_error_code_enum : std::true_type {};
29 template <>
30 struct is_error_code_enum : std::true_type {};
3231 } // namespace std
3332
3433 namespace llvm {
3534 namespace pdb {
36 const std::error_category &PDBErrCategory();
35 const std::error_category &PDBErrCategory();
3736
38 inline std::error_code make_error_code(pdb_error_code E) {
39 return std::error_code(static_cast(E), PDBErrCategory());
40 }
37 inline std::error_code make_error_code(pdb_error_code E) {
38 return std::error_code(static_cast(E), PDBErrCategory());
39 }
4140
4241 /// Base class for errors originating when parsing raw PDB files
4342 class PDBError : public ErrorInfo {
123123
124124 BinaryStreamRef getUnderlyingStream() const { return Stream; }
125125 void setUnderlyingStream(BinaryStreamRef S) { Stream = S; }
126
127 void drop_front() { Stream = Stream.drop_front(begin()->length()); }
126128
127129 private:
128130 BinaryStreamRef Stream;
4040 };
4141
4242 static llvm::ManagedStatic CodeViewErrCategory;
43 const std::error_category &llvm::codeview::CVErrorCategory() { return *CodeViewErrCategory; }
43 const std::error_category &llvm::codeview::CVErrorCategory() {
44 return *CodeViewErrCategory;
45 }
4446
4547 char CodeViewError::ID;
1111 #include "llvm/ADT/StringExtras.h"
1212 #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
1313 #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
14 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
1415 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
1516 #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
1617 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
6263 public:
6364 explicit TypeStreamMerger(SmallVectorImpl &SourceToDest)
6465 : IndexMap(SourceToDest) {
65 SourceToDest.clear();
66 // When dealing with precompiled headers objects, all data in SourceToDest
67 // belongs to the precompiled headers object, and is assumed to be already
68 // remapped to the target PDB. Any forthcoming type that will be merged in
69 // might potentially back-reference this data. We also don't want to resolve
70 // twice the types in the precompiled object.
71 CurIndex += SourceToDest.size();
6672 }
6773
6874 static const TypeIndex Untranslated;
7076 // Local hashing entry points
7177 Error mergeTypesAndIds(MergingTypeTableBuilder &DestIds,
7278 MergingTypeTableBuilder &DestTypes,
73 const CVTypeArray &IdsAndTypes);
79 const CVTypeArray &IdsAndTypes,
80 Optional &EP);
7481 Error mergeIdRecords(MergingTypeTableBuilder &Dest,
7582 ArrayRef TypeSourceToDest,
7683 const CVTypeArray &Ids);
8188 Error mergeTypesAndIds(GlobalTypeTableBuilder &DestIds,
8289 GlobalTypeTableBuilder &DestTypes,
8390 const CVTypeArray &IdsAndTypes,
84 ArrayRef Hashes);
91 ArrayRef Hashes,
92 Optional &EP);
8593 Error mergeIdRecords(GlobalTypeTableBuilder &Dest,
8694 ArrayRef TypeSourceToDest,
8795 const CVTypeArray &Ids,
8896 ArrayRef Hashes);
8997 Error mergeTypeRecords(GlobalTypeTableBuilder &Dest, const CVTypeArray &Types,
90 ArrayRef Hashes);
98 ArrayRef Hashes,
99 Optional &EP);
91100
92101 private:
93102 Error doit(const CVTypeArray &Types);
155164 return llvm::make_error(cv_error_code::corrupt_record);
156165 }
157166
167 Expected shouldRemapType(const CVType &Type);
168
158169 Optional LastError;
159170
160171 bool UseGlobalHashes = false;
184195 /// Temporary storage that we use to copy a record's data while re-writing
185196 /// its type indices.
186197 SmallVector RemapStorage;
198
199 Optional EndPrecomp;
187200 };
188201
189202 } // end anonymous namespace
260273
261274 Error TypeStreamMerger::mergeTypesAndIds(MergingTypeTableBuilder &DestIds,
262275 MergingTypeTableBuilder &DestTypes,
263 const CVTypeArray &IdsAndTypes) {
276 const CVTypeArray &IdsAndTypes,
277 Optional &EP) {
264278 DestIdStream = &DestIds;
265279 DestTypeStream = &DestTypes;
266280 UseGlobalHashes = false;
267 return doit(IdsAndTypes);
281 auto Err = doit(IdsAndTypes);
282 EP = EndPrecomp;
283 return Err;
268284 }
269285
270286 // Global hashing entry points
271287 Error TypeStreamMerger::mergeTypeRecords(GlobalTypeTableBuilder &Dest,
272288 const CVTypeArray &Types,
273 ArrayRef Hashes) {
289 ArrayRef Hashes,
290 Optional &EP) {
274291 DestGlobalTypeStream = &Dest;
275292 UseGlobalHashes = true;
276293 GlobalHashes = Hashes;
277
278 return doit(Types);
294 auto Err = doit(Types);
295 EP = EndPrecomp;
296 return Err;
279297 }
280298
281299 Error TypeStreamMerger::mergeIdRecords(GlobalTypeTableBuilder &Dest,
293311 Error TypeStreamMerger::mergeTypesAndIds(GlobalTypeTableBuilder &DestIds,
294312 GlobalTypeTableBuilder &DestTypes,
295313 const CVTypeArray &IdsAndTypes,
296 ArrayRef Hashes) {
314 ArrayRef Hashes,
315 Optional &EP) {
297316 DestGlobalIdStream = &DestIds;
298317 DestGlobalTypeStream = &DestTypes;
299318 UseGlobalHashes = true;
300319 GlobalHashes = Hashes;
301 return doit(IdsAndTypes);
320 auto Err = doit(IdsAndTypes);
321 EP = EndPrecomp;
322 return Err;
302323 }
303324
304325 Error TypeStreamMerger::doit(const CVTypeArray &Types) {
344365 }
345366
346367 Error TypeStreamMerger::remapType(const CVType &Type) {
347 auto DoSerialize =
348 [this, Type](MutableArrayRef Storage) -> ArrayRef {
349 return remapIndices(Type, Storage);
350 };
368 auto R = shouldRemapType(Type);
369 if (!R)
370 return R.takeError();
351371
352372 TypeIndex DestIdx = Untranslated;
353 if (LLVM_LIKELY(UseGlobalHashes)) {
354 GlobalTypeTableBuilder &Dest =
355 isIdRecord(Type.kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream;
356 GloballyHashedType H = GlobalHashes[CurIndex.toArrayIndex()];
357 DestIdx = Dest.insertRecordAs(H, Type.RecordData.size(), DoSerialize);
358 } else {
359 MergingTypeTableBuilder &Dest =
360 isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream;
361
362 RemapStorage.resize(Type.RecordData.size());
363 ArrayRef Result = DoSerialize(RemapStorage);
364 if (!Result.empty())
365 DestIdx = Dest.insertRecordBytes(Result);
373 if (*R) {
374 auto DoSerialize =
375 [this, Type](MutableArrayRef Storage) -> ArrayRef {
376 return remapIndices(Type, Storage);
377 };
378 if (LLVM_LIKELY(UseGlobalHashes)) {
379 GlobalTypeTableBuilder &Dest =
380 isIdRecord(Type.kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream;
381 GloballyHashedType H = GlobalHashes[CurIndex.toArrayIndex()];
382 DestIdx = Dest.insertRecordAs(H, Type.RecordData.size(), DoSerialize);
383 } else {
384 MergingTypeTableBuilder &Dest =
385 isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream;
386
387 RemapStorage.resize(Type.RecordData.size());
388 ArrayRef Result = DoSerialize(RemapStorage);
389 if (!Result.empty())
390 DestIdx = Dest.insertRecordBytes(Result);
391 }
366392 }
367393 addMapping(DestIdx);
368394
417443
418444 Error llvm::codeview::mergeTypeAndIdRecords(
419445 MergingTypeTableBuilder &DestIds, MergingTypeTableBuilder &DestTypes,
420 SmallVectorImpl &SourceToDest, const CVTypeArray &IdsAndTypes) {
421 TypeStreamMerger M(SourceToDest);
422 return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes);
446 SmallVectorImpl &SourceToDest, const CVTypeArray &IdsAndTypes,
447 Optional &EndPrecomp) {
448 TypeStreamMerger M(SourceToDest);
449 return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, EndPrecomp);
423450 }
424451
425452 Error llvm::codeview::mergeTypeAndIdRecords(
426453 GlobalTypeTableBuilder &DestIds, GlobalTypeTableBuilder &DestTypes,
427454 SmallVectorImpl &SourceToDest, const CVTypeArray &IdsAndTypes,
428 ArrayRef Hashes) {
429 TypeStreamMerger M(SourceToDest);
430 return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes);
455 ArrayRef Hashes,
456 Optional &EndPrecomp) {
457 TypeStreamMerger M(SourceToDest);
458 return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes,
459 EndPrecomp);
431460 }
432461
433462 Error llvm::codeview::mergeTypeRecords(GlobalTypeTableBuilder &Dest,
434463 SmallVectorImpl &SourceToDest,
435464 const CVTypeArray &Types,
436 ArrayRef Hashes) {
437 TypeStreamMerger M(SourceToDest);
438 return M.mergeTypeRecords(Dest, Types, Hashes);
465 ArrayRef Hashes,
466 Optional &EndPrecomp) {
467 TypeStreamMerger M(SourceToDest);
468 return M.mergeTypeRecords(Dest, Types, Hashes, EndPrecomp);
439469 }
440470
441471 Error llvm::codeview::mergeIdRecords(GlobalTypeTableBuilder &Dest,
446476 TypeStreamMerger M(SourceToDest);
447477 return M.mergeIdRecords(Dest, Types, Ids, Hashes);
448478 }
479
480 Expected TypeStreamMerger::shouldRemapType(const CVType &Type) {
481 // For object files containing precompiled types, we need to extract the
482 // signature, through EndPrecompRecord. This is done here for performance
483 // reasons, to avoid re-parsing the Types stream.
484 if (Type.kind() == LF_ENDPRECOMP) {
485 assert(!EndPrecomp);
486 EndPrecomp.emplace();
487 if (auto EC = TypeDeserializer::deserializeAs(const_cast(Type),
488 EndPrecomp.getValue()))
489 return joinErrors(std::move(EC), errorCorruptRecord());
490 return false;
491 }
492 return true;
493 }
2323 switch (static_cast(Condition)) {
2424 case pdb_error_code::unspecified:
2525 return "An unknown error has occurred.";
26 case pdb_error_code::type_server_not_found:
27 return "Type server PDB was not found.";
2826 case pdb_error_code::dia_sdk_not_present:
2927 return "LLVM was not compiled with support for DIA. This usually means "
3028 "that you are not using MSVC, or your Visual Studio "
12471247 error(object_error::parse_failed);
12481248 }
12491249 SmallVector SourceToDest;
1250 if (auto EC = mergeTypeAndIdRecords(CVIDs, CVTypes, SourceToDest, Types))
1250 Optional EndPrecomp;
1251 if (auto EC = mergeTypeAndIdRecords(CVIDs, CVTypes, SourceToDest, Types,
1252 EndPrecomp))
12511253 return error(std::move(EC));
12521254 }
12531255 }