Index: lib/DebugInfo/PDB/Raw/TpiStream.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/TpiStream.cpp +++ lib/DebugInfo/PDB/Raw/TpiStream.cpp @@ -69,6 +69,38 @@ TpiStream::~TpiStream() {} +// Computes a hash for a given TPI record. +template +static Error getTpiHash(const codeview::CVType &Rec, uint32_t &Hash) { + ArrayRef Data = Rec.Data; + ErrorOr Obj = T::deserialize(K, Data); + if (Obj.getError()) + return make_error(raw_error_code::corrupt_file, + "Corrupt TPI hash table."); + + auto Opts = static_cast(Obj->getOptions()); + if (Opts & static_cast(codeview::ClassOptions::ForwardReference)) { + // We don't know how to calculate a hash value for this yet. + // Currently we just skip it. + Hash = 0; + return Error::success(); + } + + if (!(Opts & static_cast(codeview::ClassOptions::Scoped))) { + Hash = hashStringV1(Obj->getName()); + return Error::success(); + } + + if (Opts & static_cast(codeview::ClassOptions::HasUniqueName)) { + Hash = hashStringV1(Obj->getUniqueName()); + return Error::success(); + } + + // This case is not implemented yet. + Hash = 0; + return Error::success(); +} + // Verifies that a given type record matches with a given hash value. // Currently we only verify SRC_LINE records. static Error verifyTIHash(const codeview::CVType &Rec, uint32_t Expected, @@ -83,19 +115,32 @@ case LF_UDT_MOD_SRC_LINE: Hash = hashStringV1(StringRef((const char *)D.data(), 4)); break; - case LF_ENUM: { - ErrorOr Enum = EnumRecord::deserialize(TypeRecordKind::Enum, D); - if (Enum.getError()) - return make_error(raw_error_code::corrupt_file, - "Corrupt TPI hash table."); - Hash = hashStringV1(Enum->getName()); + case LF_CLASS: + if (auto EC = getTpiHash(Rec, Hash)) + return EC; + break; + case LF_ENUM: + if (auto EC = getTpiHash(Rec, Hash)) + return EC; + break; + case LF_INTERFACE: + if (auto EC = getTpiHash(Rec, Hash)) + return EC; + break; + case LF_STRUCTURE: + if (auto EC = getTpiHash(Rec, Hash)) + return EC; + break; + case LF_UNION: + if (auto EC = getTpiHash(Rec, Hash)) + return EC; break; - } default: + // This pattern is not implemented yet. return Error::success(); } - if ((Hash % NumHashBuckets) != Expected) + if (Hash && (Hash % NumHashBuckets) != Expected) return make_error(raw_error_code::corrupt_file, "Corrupt TPI hash table."); return Error::success();