Index: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h +++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h @@ -36,11 +36,17 @@ uint32_t getSymHash() const; uint32_t getAddrMap() const; uint32_t getNumBuckets() const { return NumBuckets; } + ArrayRef getHashBuckets() const { return HashBuckets; } + ArrayRef getAddressMap() const { return AddressMap; } + ArrayRef getThunkMap() const { return ThunkMap; } private: uint32_t StreamNum; MappedBlockStream Stream; uint32_t NumBuckets = 0; + std::vector HashBuckets; + std::vector AddressMap; + std::vector ThunkMap; std::unique_ptr Header; std::unique_ptr HashHdr; Index: llvm/trunk/lib/DebugInfo/PDB/Raw/PublicsStream.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/Raw/PublicsStream.cpp +++ llvm/trunk/lib/DebugInfo/PDB/Raw/PublicsStream.cpp @@ -53,7 +53,7 @@ ulittle16_t ISectThunkTable; char Padding[2]; ulittle32_t OffThunkTable; - ulittle32_t NumSects; + ulittle32_t NumSections; }; @@ -74,6 +74,15 @@ ulittle32_t CRef; }; +// This struct is defined as "SO" in langapi/include/pdb.h. +namespace { +struct SectionOffset { + ulittle32_t Off; + ulittle16_t Isect; + char Padding[2]; +}; +} + PublicsStream::PublicsStream(PDBFile &File, uint32_t StreamNum) : StreamNum(StreamNum), Stream(StreamNum, File) {} @@ -123,10 +132,37 @@ for (uint8_t B : Bitmap) NumBuckets += countPopulation(B); - // Buckets follow. - if (Reader.bytesRemaining() < NumBuckets * sizeof(uint32_t)) + // We don't yet understand the following data structures completely, + // but we at least know the types and sizes. Here we are trying + // to read the stream till end so that we at least can detect + // corrupted streams. + + // Hash buckets follow. + HashBuckets.resize(NumBuckets); + if (auto EC = Reader.readArray(HashBuckets)) return make_error(raw_error_code::corrupt_file, "Hash buckets corrupted."); + // Something called "address map" follows. + AddressMap.resize(Header->AddrMap / sizeof(uint32_t)); + if (auto EC = Reader.readArray(AddressMap)) + return make_error(raw_error_code::corrupt_file, + "Could not read an address map."); + + // Something called "thunk map" follows. + ThunkMap.resize(Header->NumThunks); + if (auto EC = Reader.readArray(ThunkMap)) + return make_error(raw_error_code::corrupt_file, + "Could not read a thunk map."); + + // Something called "section map" follows. + std::vector SectionMap(Header->NumSections); + if (auto EC = Reader.readArray(SectionMap)) + return make_error(raw_error_code::corrupt_file, + "Could not read a section map."); + + if (Reader.bytesRemaining() > 0) + return make_error(raw_error_code::corrupt_file, + "Corrupted publics stream."); return Error::success(); } Index: llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test =================================================================== --- llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test +++ llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test @@ -313,6 +313,9 @@ ; EMPTY-NEXT: SymHash: 556 ; EMPTY-NEXT: AddrMap: 8 ; EMPTY-NEXT: Number of buckets: 2 +; EMPTY-NEXT: Hash Buckets: [0, 12] +; EMPTY-NEXT: Address Map: [36, 0] +; EMPTY-NEXT: Thunk Map: [4112] ; EMPTY-NEXT: } ; BIG: FileHeaders { Index: llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp =================================================================== --- llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -411,6 +411,9 @@ P.printNumber("SymHash", Publics.getSymHash()); P.printNumber("AddrMap", Publics.getAddrMap()); P.printNumber("Number of buckets", Publics.getNumBuckets()); + P.printList("Hash Buckets", Publics.getHashBuckets()); + P.printList("Address Map", Publics.getAddressMap()); + P.printList("Thunk Map", Publics.getThunkMap()); return Error::success(); }