From: Rui Ueyama Date: Wed, 15 Jun 2016 18:26:59 +0000 (+0000) Subject: [pdbdump] Verify LF_{CLASS,ENUM,INTERFACE,STRUCTURE,UNION} records. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=69d870720c186e9b8990a1f2ba569ccf125bff1e;p=llvm [pdbdump] Verify LF_{CLASS,ENUM,INTERFACE,STRUCTURE,UNION} records. Differential Revision: http://reviews.llvm.org/D21361 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@272815 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/DebugInfo/PDB/Raw/TpiStream.cpp b/lib/DebugInfo/PDB/Raw/TpiStream.cpp index 74456112829..0853202f34e 100644 --- a/lib/DebugInfo/PDB/Raw/TpiStream.cpp +++ b/lib/DebugInfo/PDB/Raw/TpiStream.cpp @@ -69,6 +69,38 @@ TpiStream::TpiStream(const PDBFile &File, 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 llvm::make_error( + codeview::cv_error_code::corrupt_record); + + 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 @@ static Error verifyTIHash(const codeview::CVType &Rec, uint32_t Expected, 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();