diff options
| author | Alexandre Ganea <alexandre.ganea@ubisoft.com> | 2019-02-07 15:24:18 +0000 |
|---|---|---|
| committer | Alexandre Ganea <alexandre.ganea@ubisoft.com> | 2019-02-07 15:24:18 +0000 |
| commit | 120366edc733ac85ba71e45ecb96edfa9ce9b9d3 (patch) | |
| tree | 8fea50ae302f46fd965b105df265ea11a5d1f09d /llvm/lib/DebugInfo/CodeView | |
| parent | 892e63319497bfbea7c93d763c43a1944d6d7ab4 (diff) | |
| download | bcm5719-llvm-120366edc733ac85ba71e45ecb96edfa9ce9b9d3.tar.gz bcm5719-llvm-120366edc733ac85ba71e45ecb96edfa9ce9b9d3.zip | |
[CodeView] Fix cycles in debug info when merging Types with global hashes
When type streams with forward references were merged using GHashes, cycles
were introduced in the debug info. This was caused by
GlobalTypeTableBuilder::insertRecordAs() not inserting the record on the second
pass, thus yielding an empty ArrayRef at that record slot. Later on, upon PDB
emission, TpiStreamBuilder::commit() would skip that empty record, thus
offseting all indices that came after in the stream.
This solution comes in two steps:
1. Fix the hash calculation, by doing a multiple-step resolution, iff there are
forward references in the input stream.
2. Fix merge by resolving with multiple passes, therefore moving records with
forward references at the end of the stream.
This patch also adds support for llvm-readoj --codeview-ghash.
Finally, fix dumpCodeViewMergedTypes() which previously could reference deleted
memory.
Fixes PR40221
Differential Revision: https://reviews.llvm.org/D57790
llvm-svn: 353412
Diffstat (limited to 'llvm/lib/DebugInfo/CodeView')
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeHashing.cpp | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp b/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp index 612399ddbff..2dbc11a84f0 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp @@ -54,10 +54,16 @@ GloballyHashedType::hashType(ArrayRef<uint8_t> RecordData, reinterpret_cast<const TypeIndex *>(RefData.data()), Ref.Count); for (TypeIndex TI : Indices) { ArrayRef<uint8_t> BytesToHash; - if (TI.isSimple() || TI.isNoneType() || TI.toArrayIndex() >= Prev.size()) { + if (TI.isSimple() || TI.isNoneType()) { const uint8_t *IndexBytes = reinterpret_cast<const uint8_t *>(&TI); BytesToHash = makeArrayRef(IndexBytes, sizeof(TypeIndex)); } else { + if (TI.toArrayIndex() >= Prev.size() || + Prev[TI.toArrayIndex()].empty()) { + // There are references to yet-unhashed records. Suspend hashing for + // this record until all the other records are processed. + return {}; + } BytesToHash = Prev[TI.toArrayIndex()].Hash; } S.update(BytesToHash); |

