Index: llvm/trunk/include/llvm/DebugInfo/CodeView/StreamArray.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/StreamArray.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/StreamArray.h @@ -221,7 +221,7 @@ return FixedStreamArrayIterator(*this, 0); } FixedStreamArrayIterator end() const { - return FixedStreamArrayIterator(*this); + return FixedStreamArrayIterator(*this, size()); } private: @@ -230,13 +230,8 @@ template class FixedStreamArrayIterator { public: - FixedStreamArrayIterator(const FixedStreamArray &Array) - : Array(Array), Index(uint32_t(-1)) {} - FixedStreamArrayIterator(const FixedStreamArray &Array, uint32_t ArrayIndex) - : Array(Array), Index(ArrayIndex) { - if (Array.size() <= Index) - Index = uint32_t(-1); - } + FixedStreamArrayIterator(const FixedStreamArray &Array, uint32_t Index) + : Array(Array), Index(Index) {} bool operator==(const FixedStreamArrayIterator &R) { assert(&Array == &R.Array); @@ -250,10 +245,8 @@ const T &operator*() const { return Array[Index]; } FixedStreamArrayIterator &operator++() { - if (Index == uint32_t(-1)) - return *this; - if (++Index >= Array.size()) - Index = uint32_t(-1); + assert(Index < Array.size()); + ++Index; return *this; } Index: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawTypes.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawTypes.h +++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawTypes.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H #define LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H +#include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/Support/Endian.h" namespace llvm { @@ -72,6 +73,13 @@ support::ulittle32_t SecByteLength; // Byte count of the segment or group. }; +// Used for serialized hash table in TPI stream. +// In the reference, it is an array of TI and cbOff pair. +struct TypeIndexOffset { + codeview::TypeIndex Type; + support::ulittle32_t Offset; +}; + } // namespace pdb } // namespace llvm Index: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h +++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h @@ -16,6 +16,8 @@ #include "llvm/DebugInfo/PDB/PDBTypes.h" #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" +#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Error.h" @@ -41,6 +43,10 @@ uint16_t getTypeHashStreamIndex() const; uint16_t getTypeHashStreamAuxIndex() const; + codeview::FixedStreamArray getHashValues() const; + codeview::FixedStreamArray getTypeIndexOffsets() const; + codeview::FixedStreamArray getHashAdjustments() const; + iterator_range types(bool *HadError) const; private: @@ -49,9 +55,11 @@ HashFunctionType HashFunction; codeview::CVTypeArray TypeRecords; - codeview::StreamRef TypeIndexOffsetBuffer; - codeview::StreamRef HashValuesBuffer; - codeview::StreamRef HashAdjBuffer; + + std::unique_ptr HashStream; + codeview::FixedStreamArray HashValues; + codeview::FixedStreamArray TypeIndexOffsets; + codeview::FixedStreamArray HashAdjustments; const HeaderInfo *Header; }; Index: llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp +++ llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp @@ -11,11 +11,13 @@ #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/StreamReader.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Raw/PDBFile.h" #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" #include "llvm/DebugInfo/PDB/Raw/RawError.h" +#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" #include "llvm/Support/Endian.h" @@ -99,20 +101,23 @@ return EC; // Hash indices, hash values, etc come from the hash stream. - MappedBlockStream HS(Header->HashStreamIndex, Pdb); - codeview::StreamReader HSR(HS); + HashStream.reset(new MappedBlockStream(Header->HashStreamIndex, Pdb)); + codeview::StreamReader HSR(*HashStream); + uint32_t NumHashValues = Header->HashValueBuffer.Length / sizeof(ulittle32_t); HSR.setOffset(Header->HashValueBuffer.Off); - if (auto EC = - HSR.readStreamRef(HashValuesBuffer, Header->HashValueBuffer.Length)) + if (auto EC = HSR.readArray(HashValues, NumHashValues)) return EC; - HSR.setOffset(Header->HashAdjBuffer.Off); - if (auto EC = HSR.readStreamRef(HashAdjBuffer, Header->HashAdjBuffer.Length)) + HSR.setOffset(Header->IndexOffsetBuffer.Off); + uint32_t NumTypeIndexOffsets = + Header->IndexOffsetBuffer.Length / sizeof(TypeIndexOffset); + if (auto EC = HSR.readArray(TypeIndexOffsets, NumTypeIndexOffsets)) return EC; - HSR.setOffset(Header->IndexOffsetBuffer.Off); - if (auto EC = HSR.readStreamRef(TypeIndexOffsetBuffer, - Header->IndexOffsetBuffer.Length)) + HSR.setOffset(Header->HashAdjBuffer.Off); + uint32_t NumHashAdjustments = + Header->HashAdjBuffer.Length / sizeof(TypeIndexOffset); + if (auto EC = HSR.readArray(HashAdjustments, NumHashAdjustments)) return EC; return Error::success(); @@ -139,6 +144,21 @@ return Header->HashAuxStreamIndex; } +codeview::FixedStreamArray +TpiStream::getHashValues() const { + return HashValues; +} + +codeview::FixedStreamArray +TpiStream::getTypeIndexOffsets() const { + return TypeIndexOffsets; +} + +codeview::FixedStreamArray +TpiStream::getHashAdjustments() const { + return HashAdjustments; +} + iterator_range TpiStream::types(bool *HadError) const { return llvm::make_range(TypeRecords.begin(HadError), TypeRecords.end()); 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 @@ -2,7 +2,7 @@ ; RUN: -raw-sym-record-bytes -raw-publics -raw-module-files -raw-stream-name=/names \ ; RUN: -raw-stream-summary -raw-stream-blocks -raw-ipi-records -raw-ipi-record-bytes \ ; RUN: -raw-section-contribs -raw-section-map -raw-section-headers -raw-line-info \ -; RUN: %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s +; RUN: -raw-tpi-hash %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s ; RUN: llvm-pdbdump -raw-all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s ; RUN: llvm-pdbdump -raw-headers -raw-stream-name=/names -raw-modules -raw-module-files \ ; RUN: %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s @@ -141,6 +141,11 @@ ; EMPTY-NEXT: 0040: 0500626F 746800F1 |..both..| ; EMPTY-NEXT: ) ; EMPTY-NEXT: } +; EMPTY: Hash { +; EMPTY-NEXT: Values: [205956, 163561, 59811, 208239, 16377, 247078, 194342, 254156, 194536, 167492, 185421, 119540, 261871, 198119, 48056, 251486, 134580, 148190, 113636, 53336, 55779, 220695, 198114, 148734, 81128, 60158, 217249, 174209, 159978, 249504, 141941, 238785, 6214, 94935, 151449, 135589, 73373, 96512, 254299, 17744, 239514, 173189, 130544, 204437, 238560, 144673, 115151, 197306, 256035, 101096, 231280, 52156, 48854, 170035, 177041, 102745, 16947, 183703, 98548, 35693, 171328, 203640, 139292, 49018, 43821, 202555, 165040, 215835, 142625, 52534, 44186, 103930, 110942, 17991, 213215] +; EMPTY-NEXT: Type Index Offsets: [{4096, 0}] +; EMPTY-NEXT: Hash Adjustments: [] +; EMPTY-NEXT: } ; EMPTY: Type Info Stream (IPI) { ; EMPTY-NEXT: IPI Version: 20040203 ; EMPTY-NEXT: Record count: 15 @@ -217,6 +222,11 @@ ; EMPTY-NEXT: 0000: 42100000 01000000 6C000000 0100F2F1 |B.......l.......| ; EMPTY-NEXT: ) ; EMPTY-NEXT: } +; EMPTY: Hash { +; EMPTY-NEXT: Values: [7186, 7198, 7180, 7191, 7201, 7241, 7249, 80727, 154177, 75189, 253662, 193467, 222705, 186099, 257108] +; EMPTY-NEXT: Type Index Offsets: [{4096, 0}] +; EMPTY-NEXT: Hash Adjustments: [] +; EMPTY-NEXT: } ; EMPTY: DBI Stream { ; EMPTY-NEXT: Dbi Version: 19990903 ; EMPTY-NEXT: Age: 1 Index: llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp =================================================================== --- llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -264,6 +264,23 @@ return Error::success(); } +static void printTypeIndexOffset(raw_ostream &OS, + const TypeIndexOffset &TIOff) { + OS << "{" << TIOff.Type.getIndex() << ", " << TIOff.Offset << "}"; +} + +static void dumpTpiHash(ScopedPrinter &P, TpiStream &Tpi) { + if (!opts::DumpTpiHash) + return; + DictScope DD(P, "Hash"); + codeview::FixedStreamArray S = Tpi.getHashValues(); + P.printList("Values", Tpi.getHashValues()); + P.printList("Type Index Offsets", Tpi.getTypeIndexOffsets(), + printTypeIndexOffset); + P.printList("Hash Adjustments", Tpi.getHashAdjustments(), + printTypeIndexOffset); +} + Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI); @@ -309,6 +326,7 @@ if (DumpRecordBytes) P.printBinaryBlock("Bytes", Type.Data); } + dumpTpiHash(P, Tpi); if (HadError) return make_error(raw_error_code::corrupt_file, "TPI stream contained corrupt record"); @@ -325,6 +343,7 @@ TD.dump(Type); TD.setPrinter(OldP); + dumpTpiHash(P, Tpi); if (HadError) return make_error(raw_error_code::corrupt_file, "TPI stream contained corrupt record"); Index: llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h =================================================================== --- llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h +++ llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h @@ -27,8 +27,9 @@ extern llvm::cl::opt DumpHeaders; extern llvm::cl::opt DumpStreamBlocks; extern llvm::cl::opt DumpStreamSummary; -extern llvm::cl::opt DumpTpiRecords; +extern llvm::cl::opt DumpTpiHash; extern llvm::cl::opt DumpTpiRecordBytes; +extern llvm::cl::opt DumpTpiRecords; extern llvm::cl::opt DumpIpiRecords; extern llvm::cl::opt DumpIpiRecordBytes; extern llvm::cl::opt DumpStreamDataIdx; 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 @@ -113,6 +113,9 @@ "raw-tpi-record-bytes", cl::desc("dump CodeView type record raw bytes from TPI stream"), cl::cat(NativeOptions)); +cl::opt DumpTpiHash("raw-tpi-hash", + cl::desc("dump CodeView TPI hash stream"), + cl::cat(NativeOptions)); cl::opt DumpIpiRecords("raw-ipi-records", cl::desc("dump CodeView type records from IPI stream"), @@ -276,6 +279,8 @@ return true; if (opts::DumpTpiRecords) return true; + if (opts::DumpTpiHash) + return true; if (opts::DumpIpiRecords) return true; if (opts::DumpIpiRecordBytes) @@ -450,6 +455,7 @@ opts::DumpStreamSummary = true; opts::DumpStreamBlocks = true; opts::DumpTpiRecords = true; + opts::DumpTpiHash = true; opts::DumpIpiRecords = true; opts::DumpSectionMap = true; opts::DumpSectionContribs = true;