llvm.org GIT mirror llvm / 6bf4f87
[pdb] Don't verify TPI hash values up front. Verifying the hash values as we are currently doing results in iterating every type record before the user even tries to access the first one, and the API user has no control over, or ability to hook into this process. As a result, when the user wants to iterate over types to print them or index them, this results in a second iteration over the same list of types. When there's upwards of 1,000,000 type records, this is obviously quite undesirable. This patch raises the verification outside of TpiStream , and llvm-pdbdump hooks a hash verification visitor into the normal dumping process. So we still verify the hash records, but we can do it while not requiring a second iteration over the type stream. Differential Revision: https://reviews.llvm.org/D32873 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@302206 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 3 years ago
3 changed file(s) with 21 addition(s) and 33 deletion(s). Raw diff Collapse all Expand all
3939
4040 uint32_t TypeIndexBegin() const;
4141 uint32_t TypeIndexEnd() const;
42 uint32_t NumTypeRecords() const;
42 uint32_t getNumTypeRecords() const;
4343 uint16_t getTypeHashStreamIndex() const;
4444 uint16_t getTypeHashStreamAuxIndex() const;
4545
4646 uint32_t getHashKeySize() const;
47 uint32_t NumHashBuckets() const;
47 uint32_t getNumHashBuckets() const;
4848 FixedStreamArray getHashValues() const;
4949 FixedStreamArray getTypeIndexOffsets() const;
5050 HashTable &getHashAdjusters();
5454 Error commit();
5555
5656 private:
57 Error verifyHashValues();
58
5957 const PDBFile &Pdb;
6058 std::unique_ptr Stream;
6159
3737 : Pdb(File), Stream(std::move(Stream)) {}
3838
3939 TpiStream::~TpiStream() = default;
40
41 // Verifies that a given type record matches with a given hash value.
42 // Currently we only verify SRC_LINE records.
43 Error TpiStream::verifyHashValues() {
44 TpiHashVerifier Verifier(HashValues, Header->NumHashBuckets);
45 TypeDeserializer Deserializer;
46
47 TypeVisitorCallbackPipeline Pipeline;
48 Pipeline.addCallbackToPipeline(Deserializer);
49 Pipeline.addCallbackToPipeline(Verifier);
50
51 CVTypeVisitor Visitor(Pipeline);
52 return Visitor.visitTypeStream(TypeRecords);
53 }
5440
5541 Error TpiStream::reload() {
5642 BinaryStreamReader Reader(*Stream);
9783 // There should be a hash value for every type record, or no hashes at all.
9884 uint32_t NumHashValues =
9985 Header->HashValueBuffer.Length / sizeof(ulittle32_t);
100 if (NumHashValues != NumTypeRecords() && NumHashValues != 0)
86 if (NumHashValues != getNumTypeRecords() && NumHashValues != 0)
10187 return make_error(
10288 raw_error_code::corrupt_file,
10389 "TPI hash count does not match with the number of type records.");
121107 }
122108
123109 HashStream = std::move(HS);
124
125 // TPI hash table is a parallel array for the type records.
126 // Verify that the hash values match with type records.
127 if (NumHashValues > 0)
128 if (auto EC = verifyHashValues())
129 return EC;
130110 }
131111
132112 return Error::success();
141121
142122 uint32_t TpiStream::TypeIndexEnd() const { return Header->TypeIndexEnd; }
143123
144 uint32_t TpiStream::NumTypeRecords() const {
124 uint32_t TpiStream::getNumTypeRecords() const {
145125 return TypeIndexEnd() - TypeIndexBegin();
146126 }
147127
153133 return Header->HashAuxStreamIndex;
154134 }
155135
156 uint32_t TpiStream::NumHashBuckets() const { return Header->NumHashBuckets; }
136 uint32_t TpiStream::getNumHashBuckets() const { return Header->NumHashBuckets; }
157137 uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; }
158138
159139 FixedStreamArray TpiStream::getHashValues() const {
3838 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
3939 #include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
4040 #include "llvm/DebugInfo/PDB/Native/RawError.h"
41 #include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
4142 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
4243 #include "llvm/DebugInfo/PDB/PDBExtras.h"
4344 #include "llvm/Object/COFF.h"
621622
622623 StreamScope = llvm::make_unique(P, Label);
623624 P.printNumber(VerLabel, Tpi->getTpiVersion());
624 P.printNumber("Record count", Tpi->NumTypeRecords());
625 P.printNumber("Record count", Tpi->getNumTypeRecords());
625626
626627 Optional &StreamDB = (StreamIdx == StreamTPI) ? TypeDB : ItemDB;
627628
681682
682683 if (DumpTpiHash) {
683684 DictScope DD(P, "Hash");
684 P.printNumber("Number of Hash Buckets", Tpi->NumHashBuckets());
685 P.printNumber("Number of Hash Buckets", Tpi->getNumHashBuckets());
685686 P.printNumber("Hash Key Size", Tpi->getHashKeySize());
686687 P.printList("Values", Tpi->getHashValues());
687688
722723
723724 DB.emplace();
724725
726 auto Tpi =
727 (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream();
728
729 if (!Tpi)
730 return Tpi.takeError();
731
725732 TypeVisitorCallbackPipeline Pipeline;
726733 TypeDeserializer Deserializer;
727734 TypeDatabaseVisitor DBV(*DB);
728735 Pipeline.addCallbackToPipeline(Deserializer);
729736 Pipeline.addCallbackToPipeline(DBV);
730737
731 auto Tpi =
732 (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream();
733 if (!Tpi)
734 return Tpi.takeError();
738 auto HashValues = Tpi->getHashValues();
739 std::unique_ptr HashVerifier;
740 if (!HashValues.empty()) {
741 HashVerifier =
742 make_unique(HashValues, Tpi->getNumHashBuckets());
743 Pipeline.addCallbackToPipeline(*HashVerifier);
744 }
735745
736746 CVTypeVisitor Visitor(Pipeline);
737747 return Visitor.visitTypeStream(Tpi->types(nullptr));