diff options
author | Alexandre Ganea <alexandre.ganea@ubisoft.com> | 2018-11-05 19:20:47 +0000 |
---|---|---|
committer | Alexandre Ganea <alexandre.ganea@ubisoft.com> | 2018-11-05 19:20:47 +0000 |
commit | 71c43ceaf862a5d9c9654f079fcaf82ed7ba40b4 (patch) | |
tree | ae3e1dce36e7fa3945ff04b63a697d387134cc5f /llvm/lib/DebugInfo/CodeView | |
parent | 1a9b0723385c8426bf9f7cca169bf3d4bbd1e729 (diff) | |
download | bcm5719-llvm-71c43ceaf862a5d9c9654f079fcaf82ed7ba40b4.tar.gz bcm5719-llvm-71c43ceaf862a5d9c9654f079fcaf82ed7ba40b4.zip |
[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
llvm-svn: 346154
Diffstat (limited to 'llvm/lib/DebugInfo/CodeView')
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CodeViewError.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp | 113 |
2 files changed, 82 insertions, 35 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp b/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp index 914157ef0c1..2a9753add31 100644 --- a/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp +++ b/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp @@ -41,6 +41,8 @@ public: }; static llvm::ManagedStatic<CodeViewErrorCategory> CodeViewErrCategory; -const std::error_category &llvm::codeview::CVErrorCategory() { return *CodeViewErrCategory; } +const std::error_category &llvm::codeview::CVErrorCategory() { + return *CodeViewErrCategory; +} char CodeViewError::ID; diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp index 1a1d516ff3c..803818226e5 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h" #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" @@ -63,7 +64,12 @@ class TypeStreamMerger { public: explicit TypeStreamMerger(SmallVectorImpl<TypeIndex> &SourceToDest) : IndexMap(SourceToDest) { - SourceToDest.clear(); + // When dealing with precompiled headers objects, all data in SourceToDest + // belongs to the precompiled headers object, and is assumed to be already + // remapped to the target PDB. Any forthcoming type that will be merged in + // might potentially back-reference this data. We also don't want to resolve + // twice the types in the precompiled object. + CurIndex += SourceToDest.size(); } static const TypeIndex Untranslated; @@ -71,7 +77,8 @@ public: // Local hashing entry points Error mergeTypesAndIds(MergingTypeTableBuilder &DestIds, MergingTypeTableBuilder &DestTypes, - const CVTypeArray &IdsAndTypes); + const CVTypeArray &IdsAndTypes, + Optional<EndPrecompRecord> &EP); Error mergeIdRecords(MergingTypeTableBuilder &Dest, ArrayRef<TypeIndex> TypeSourceToDest, const CVTypeArray &Ids); @@ -82,13 +89,15 @@ public: Error mergeTypesAndIds(GlobalTypeTableBuilder &DestIds, GlobalTypeTableBuilder &DestTypes, const CVTypeArray &IdsAndTypes, - ArrayRef<GloballyHashedType> Hashes); + ArrayRef<GloballyHashedType> Hashes, + Optional<EndPrecompRecord> &EP); Error mergeIdRecords(GlobalTypeTableBuilder &Dest, ArrayRef<TypeIndex> TypeSourceToDest, const CVTypeArray &Ids, ArrayRef<GloballyHashedType> Hashes); Error mergeTypeRecords(GlobalTypeTableBuilder &Dest, const CVTypeArray &Types, - ArrayRef<GloballyHashedType> Hashes); + ArrayRef<GloballyHashedType> Hashes, + Optional<EndPrecompRecord> &EP); private: Error doit(const CVTypeArray &Types); @@ -156,6 +165,8 @@ private: return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record); } + Expected<bool> shouldRemapType(const CVType &Type); + Optional<Error> LastError; bool UseGlobalHashes = false; @@ -185,6 +196,8 @@ private: /// Temporary storage that we use to copy a record's data while re-writing /// its type indices. SmallVector<uint8_t, 256> RemapStorage; + + Optional<EndPrecompRecord> EndPrecomp; }; } // end anonymous namespace @@ -261,22 +274,27 @@ Error TypeStreamMerger::mergeIdRecords(MergingTypeTableBuilder &Dest, Error TypeStreamMerger::mergeTypesAndIds(MergingTypeTableBuilder &DestIds, MergingTypeTableBuilder &DestTypes, - const CVTypeArray &IdsAndTypes) { + const CVTypeArray &IdsAndTypes, + Optional<EndPrecompRecord> &EP) { DestIdStream = &DestIds; DestTypeStream = &DestTypes; UseGlobalHashes = false; - return doit(IdsAndTypes); + auto Err = doit(IdsAndTypes); + EP = EndPrecomp; + return Err; } // Global hashing entry points Error TypeStreamMerger::mergeTypeRecords(GlobalTypeTableBuilder &Dest, const CVTypeArray &Types, - ArrayRef<GloballyHashedType> Hashes) { + ArrayRef<GloballyHashedType> Hashes, + Optional<EndPrecompRecord> &EP) { DestGlobalTypeStream = &Dest; UseGlobalHashes = true; GlobalHashes = Hashes; - - return doit(Types); + auto Err = doit(Types); + EP = EndPrecomp; + return Err; } Error TypeStreamMerger::mergeIdRecords(GlobalTypeTableBuilder &Dest, @@ -294,12 +312,15 @@ Error TypeStreamMerger::mergeIdRecords(GlobalTypeTableBuilder &Dest, Error TypeStreamMerger::mergeTypesAndIds(GlobalTypeTableBuilder &DestIds, GlobalTypeTableBuilder &DestTypes, const CVTypeArray &IdsAndTypes, - ArrayRef<GloballyHashedType> Hashes) { + ArrayRef<GloballyHashedType> Hashes, + Optional<EndPrecompRecord> &EP) { DestGlobalIdStream = &DestIds; DestGlobalTypeStream = &DestTypes; UseGlobalHashes = true; GlobalHashes = Hashes; - return doit(IdsAndTypes); + auto Err = doit(IdsAndTypes); + EP = EndPrecomp; + return Err; } Error TypeStreamMerger::doit(const CVTypeArray &Types) { @@ -345,25 +366,30 @@ Error TypeStreamMerger::remapAllTypes(const CVTypeArray &Types) { } Error TypeStreamMerger::remapType(const CVType &Type) { - auto DoSerialize = - [this, Type](MutableArrayRef<uint8_t> Storage) -> ArrayRef<uint8_t> { - return remapIndices(Type, Storage); - }; + auto R = shouldRemapType(Type); + if (!R) + return R.takeError(); TypeIndex DestIdx = Untranslated; - if (LLVM_LIKELY(UseGlobalHashes)) { - GlobalTypeTableBuilder &Dest = - isIdRecord(Type.kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream; - GloballyHashedType H = GlobalHashes[CurIndex.toArrayIndex()]; - DestIdx = Dest.insertRecordAs(H, Type.RecordData.size(), DoSerialize); - } else { - MergingTypeTableBuilder &Dest = - isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream; - - RemapStorage.resize(Type.RecordData.size()); - ArrayRef<uint8_t> Result = DoSerialize(RemapStorage); - if (!Result.empty()) - DestIdx = Dest.insertRecordBytes(Result); + if (*R) { + auto DoSerialize = + [this, Type](MutableArrayRef<uint8_t> Storage) -> ArrayRef<uint8_t> { + return remapIndices(Type, Storage); + }; + if (LLVM_LIKELY(UseGlobalHashes)) { + GlobalTypeTableBuilder &Dest = + isIdRecord(Type.kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream; + GloballyHashedType H = GlobalHashes[CurIndex.toArrayIndex()]; + DestIdx = Dest.insertRecordAs(H, Type.RecordData.size(), DoSerialize); + } else { + MergingTypeTableBuilder &Dest = + isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream; + + RemapStorage.resize(Type.RecordData.size()); + ArrayRef<uint8_t> Result = DoSerialize(RemapStorage); + if (!Result.empty()) + DestIdx = Dest.insertRecordBytes(Result); + } } addMapping(DestIdx); @@ -418,25 +444,29 @@ Error llvm::codeview::mergeIdRecords(MergingTypeTableBuilder &Dest, Error llvm::codeview::mergeTypeAndIdRecords( MergingTypeTableBuilder &DestIds, MergingTypeTableBuilder &DestTypes, - SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes) { + SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes, + Optional<EndPrecompRecord> &EndPrecomp) { TypeStreamMerger M(SourceToDest); - return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes); + return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, EndPrecomp); } Error llvm::codeview::mergeTypeAndIdRecords( GlobalTypeTableBuilder &DestIds, GlobalTypeTableBuilder &DestTypes, SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes, - ArrayRef<GloballyHashedType> Hashes) { + ArrayRef<GloballyHashedType> Hashes, + Optional<EndPrecompRecord> &EndPrecomp) { TypeStreamMerger M(SourceToDest); - return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes); + return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes, + EndPrecomp); } Error llvm::codeview::mergeTypeRecords(GlobalTypeTableBuilder &Dest, SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &Types, - ArrayRef<GloballyHashedType> Hashes) { + ArrayRef<GloballyHashedType> Hashes, + Optional<EndPrecompRecord> &EndPrecomp) { TypeStreamMerger M(SourceToDest); - return M.mergeTypeRecords(Dest, Types, Hashes); + return M.mergeTypeRecords(Dest, Types, Hashes, EndPrecomp); } Error llvm::codeview::mergeIdRecords(GlobalTypeTableBuilder &Dest, @@ -447,3 +477,18 @@ Error llvm::codeview::mergeIdRecords(GlobalTypeTableBuilder &Dest, TypeStreamMerger M(SourceToDest); return M.mergeIdRecords(Dest, Types, Ids, Hashes); } + +Expected<bool> TypeStreamMerger::shouldRemapType(const CVType &Type) { + // For object files containing precompiled types, we need to extract the + // signature, through EndPrecompRecord. This is done here for performance + // reasons, to avoid re-parsing the Types stream. + if (Type.kind() == LF_ENDPRECOMP) { + assert(!EndPrecomp); + EndPrecomp.emplace(); + if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type), + EndPrecomp.getValue())) + return joinErrors(std::move(EC), errorCorruptRecord()); + return false; + } + return true; +} |