diff options
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/Line.h | 6 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h | 2 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h | 10 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h | 5 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h | 5 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h | 2 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp | 26 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp | 22 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/RawError.cpp | 4 | ||||
-rw-r--r-- | llvm/test/DebugInfo/PDB/pdbdump-headers.test | 4 | ||||
-rw-r--r-- | llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp | 54 |
11 files changed, 104 insertions, 36 deletions
diff --git a/llvm/include/llvm/DebugInfo/CodeView/Line.h b/llvm/include/llvm/DebugInfo/CodeView/Line.h index 278400742b1..975b503fe30 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/Line.h +++ b/llvm/include/llvm/DebugInfo/CodeView/Line.h @@ -142,9 +142,9 @@ struct InlineeSourceLine { }; struct FileChecksum { - ulittle32_t FileNameOffset; // Offset of filename in string table substream. - uint8_t ChecksumSize; - uint8_t ChecksumKind; // FileChecksumKind + ulittle32_t FileNameOffset; // Byte offset of filename in global string table. + uint8_t ChecksumSize; // Number of bytes of checksum. + uint8_t ChecksumKind; // FileChecksumKind // Checksum bytes follow. }; diff --git a/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h b/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h index 0de564d82b4..6affac801d4 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h +++ b/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h @@ -35,7 +35,7 @@ struct LineSubstreamHeader { // Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure. struct LineFileBlockHeader { - support::ulittle32_t FileOffset; + support::ulittle32_t NameIndex; // Index in DBI name buffer of filename. support::ulittle32_t NumLines; // Number of lines support::ulittle32_t BlockSize; // Code size of block, in bytes. // The following two variable length arrays appear immediately after the diff --git a/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h b/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h index 1c15512e98b..6df23090371 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h +++ b/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h @@ -21,7 +21,7 @@ namespace llvm { namespace codeview { struct LineColumnEntry { - support::ulittle32_t Offset; + support::ulittle32_t NameIndex; FixedStreamArray<LineNumberEntry> LineNumbers; FixedStreamArray<ColumnNumberEntry> Columns; }; @@ -50,7 +50,7 @@ public: // The value recorded in BlockHeader->BlockSize includes the size of // LineFileBlockHeader. Len = BlockHeader->BlockSize; - Item.Offset = BlockHeader->FileOffset; + Item.NameIndex = BlockHeader->NameIndex; if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines)) return EC; if (HasColumn) { @@ -65,9 +65,9 @@ private: }; struct FileChecksumEntry { - uint32_t FileNameOffset; - FileChecksumKind Kind; - ArrayRef<uint8_t> Checksum; + uint32_t FileNameOffset; // Byte offset of filename in global stringtable. + FileChecksumKind Kind; // The type of checksum. + ArrayRef<uint8_t> Checksum; // The bytes of the checksum. }; template <> class VarStreamArrayExtractor<FileChecksumEntry> { diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h b/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h index c3b00271628..132dfda5506 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h @@ -61,6 +61,8 @@ public: ArrayRef<ModuleInfoEx> modules() const; + Expected<StringRef> getFileNameForIndex(uint32_t Index) const; + codeview::FixedStreamArray<object::coff_section> getSectionHeaders(); codeview::FixedStreamArray<SecMapEntry> getSectionMap() const; @@ -85,12 +87,15 @@ private: codeview::StreamRef TypeServerMapSubstream; codeview::StreamRef ECSubstream; + codeview::StreamRef NamesBuffer; + codeview::FixedStreamArray<support::ulittle16_t> DbgStreams; PdbRaw_DbiSecContribVer SectionContribVersion; codeview::FixedStreamArray<SectionContrib> SectionContribs; codeview::FixedStreamArray<SectionContrib2> SectionContribs2; codeview::FixedStreamArray<SecMapEntry> SectionMap; + codeview::FixedStreamArray<support::little32_t> FileNameOffsets; std::unique_ptr<MappedBlockStream> SectionHeaderStream; codeview::FixedStreamArray<object::coff_section> SectionHeaders; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h index e6eada8c09d..1b8dbb898be 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h @@ -25,6 +25,8 @@ namespace pdb { struct PDBFileContext; class DbiStream; class InfoStream; +class MappedBlockStream; +class NameHashTable; class PublicsStream; class SymbolStream; class TpiStream; @@ -69,6 +71,7 @@ public: Expected<TpiStream &> getPDBIpiStream(); Expected<PublicsStream &> getPDBPublicsStream(); Expected<SymbolStream &> getPDBSymbolStream(); + Expected<NameHashTable &> getStringTable(); private: std::unique_ptr<PDBFileContext> Context; @@ -78,6 +81,8 @@ private: std::unique_ptr<TpiStream> Ipi; std::unique_ptr<PublicsStream> Publics; std::unique_ptr<SymbolStream> Symbols; + std::unique_ptr<MappedBlockStream> StringTableStream; + std::unique_ptr<NameHashTable> StringTable; }; } } diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h b/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h index b3c491a8bdc..5a1614fc82e 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h @@ -21,6 +21,8 @@ enum class raw_error_code { feature_unsupported, corrupt_file, insufficient_buffer, + no_stream, + index_out_of_bounds }; /// Base class for errors originating when parsing raw PDB files diff --git a/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp index 8c46957706e..e79d6572be1 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp @@ -345,7 +345,6 @@ Error DbiStream::initializeFileInfo() { FixedStreamArray<ulittle16_t> ModIndexArray; FixedStreamArray<ulittle16_t> ModFileCountArray; - FixedStreamArray<little32_t> FileNameOffsets; // First is an array of `NumModules` module indices. This is not used for the // same reason that `NumSourceFiles` is not used. It's an array of uint16's, @@ -373,10 +372,8 @@ Error DbiStream::initializeFileInfo() { if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles)) return EC; - StreamRef NamesBufferRef; - if (auto EC = FISR.readStreamRef(NamesBufferRef)) + if (auto EC = FISR.readStreamRef(NamesBuffer)) return EC; - StreamReader Names(NamesBufferRef); // We go through each ModuleInfo, determine the number N of source files for // that module, and then get the next N offsets from the Offsets array, using @@ -387,10 +384,10 @@ Error DbiStream::initializeFileInfo() { uint32_t NumFiles = ModFileCountArray[I]; ModuleInfos[I].SourceFiles.resize(NumFiles); for (size_t J = 0; J < NumFiles; ++J, ++NextFileIndex) { - uint32_t FileOffset = FileNameOffsets[NextFileIndex]; - Names.setOffset(FileOffset); - if (auto EC = Names.readZeroString(ModuleInfos[I].SourceFiles[J])) - return EC; + if (auto Name = getFileNameForIndex(NextFileIndex)) + ModuleInfos[I].SourceFiles[J] = Name.get(); + else + return Name.takeError(); } } @@ -400,3 +397,16 @@ Error DbiStream::initializeFileInfo() { uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const { return DbgStreams[static_cast<uint16_t>(Type)]; } + +Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const { + StreamReader Names(NamesBuffer); + if (Index >= FileNameOffsets.size()) + return make_error<RawError>(raw_error_code::index_out_of_bounds); + + uint32_t FileOffset = FileNameOffsets[Index]; + Names.setOffset(FileOffset); + StringRef Name; + if (auto EC = Names.readZeroString(Name)) + return std::move(EC); + return Name; +} diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp index d0fbb142ec3..73d8eef570f 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/DebugInfo/PDB/Raw/DbiStream.h" #include "llvm/DebugInfo/PDB/Raw/InfoStream.h" +#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h" #include "llvm/DebugInfo/PDB/Raw/PublicsStream.h" #include "llvm/DebugInfo/PDB/Raw/RawError.h" #include "llvm/DebugInfo/PDB/Raw/SymbolStream.h" @@ -359,3 +360,24 @@ Expected<SymbolStream &> PDBFile::getPDBSymbolStream() { } return *Symbols; } + +Expected<NameHashTable &> PDBFile::getStringTable() { + if (!StringTable || !StringTableStream) { + auto InfoS = getPDBInfoStream(); + if (auto EC = InfoS.takeError()) + return std::move(EC); + auto &IS = InfoS.get(); + uint32_t NameStreamIndex = IS.getNamedStreamIndex("/names"); + + if (NameStreamIndex == 0) + return make_error<RawError>(raw_error_code::no_stream); + auto S = llvm::make_unique<MappedBlockStream>(NameStreamIndex, *this); + codeview::StreamReader Reader(*S); + auto N = llvm::make_unique<NameHashTable>(); + if (auto EC = N->load(Reader)) + return std::move(EC); + StringTable = std::move(N); + StringTableStream = std::move(S); + } + return *StringTable; +} diff --git a/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp b/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp index 037a1aab4b1..bcfa55a8b01 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp @@ -24,6 +24,10 @@ public: case raw_error_code::insufficient_buffer: return "The buffer is not large enough to read the requested number of " "bytes."; + case raw_error_code::no_stream: + return "The specified stream could not be loaded."; + case raw_error_code::index_out_of_bounds: + return "The specified item does not exist in the array."; } llvm_unreachable("Unrecognized raw_error_code"); } diff --git a/llvm/test/DebugInfo/PDB/pdbdump-headers.test b/llvm/test/DebugInfo/PDB/pdbdump-headers.test index 136e4005ef9..902dae9f941 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-headers.test +++ b/llvm/test/DebugInfo/PDB/pdbdump-headers.test @@ -332,7 +332,7 @@ ; EMPTY-NEXT: ] ; EMPTY-NEXT: LineInfo [ ; EMPTY-NEXT: Lines { -; EMPTY-NEXT: FileOffset: 0 +; EMPTY-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp ; EMPTY-NEXT: Line { ; EMPTY-NEXT: Offset: 0 ; EMPTY-NEXT: LineNumberStart: 5 @@ -354,7 +354,7 @@ ; EMPTY-NEXT: } ; EMPTY-NEXT: FileChecksums { ; EMPTY-NEXT: Checksum { -; EMPTY-NEXT: FileNameOffset: 86 +; EMPTY-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp ; EMPTY-NEXT: Kind: MD5 (0x1) ; EMPTY-NEXT: Checksum ( ; EMPTY-NEXT: 0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC |....>...)...&...| diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp index dcaf494ee5c..1a9d5583486 100644 --- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -522,11 +522,19 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File, // substream types types. class RecordVisitor : public codeview::IModuleSubstreamVisitor { public: - RecordVisitor(ScopedPrinter &P) : P(P) {} + RecordVisitor(ScopedPrinter &P, PDBFile &F) : P(P), F(F) {} Error visitUnknown(ModuleSubstreamKind Kind, - StreamRef Data) override { + StreamRef Stream) override { DictScope DD(P, "Unknown"); - return printBinaryData(Data); + ArrayRef<uint8_t> Data; + StreamReader R(Stream); + if (auto EC = R.readBytes(Data, R.bytesRemaining())) { + return make_error<RawError>( + raw_error_code::corrupt_file, + "DBI stream contained corrupt line info record"); + } + P.printBinaryBlock("Data", Data); + return Error::success(); } Error visitFileChecksums(StreamRef Data, @@ -534,7 +542,11 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File, DictScope DD(P, "FileChecksums"); for (const auto &C : Checksums) { DictScope DDD(P, "Checksum"); - P.printNumber("FileNameOffset", C.FileNameOffset); + if (auto Result = getFileNameForOffset(C.FileNameOffset)) + P.printString("FileName", Result.get()); + else + return Result.takeError(); + P.flush(); P.printEnum("Kind", uint8_t(C.Kind), getFileChecksumNames()); P.printBinaryBlock("Checksum", C.Checksum); } @@ -545,7 +557,11 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File, const LineInfoArray &Lines) override { DictScope DD(P, "Lines"); for (const auto &L : Lines) { - P.printNumber("FileOffset", L.Offset); + if (auto Result = getFileNameForOffset2(L.NameIndex)) + P.printString("FileName", Result.get()); + else + return Result.takeError(); + P.flush(); for (const auto &N : L.LineNumbers) { DictScope DDD(P, "Line"); LineInfo LI(N.Flags); @@ -569,21 +585,25 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File, } private: - Error printBinaryData(StreamRef Stream) { - ArrayRef<uint8_t> Data; - StreamReader R(Stream); - if (auto EC = R.readBytes(Data, R.bytesRemaining())) { - return make_error<RawError>( - raw_error_code::corrupt_file, - "DBI stream contained corrupt line info record"); - } - P.printBinaryBlock("Data", Data); - P.flush(); - return Error::success(); + Expected<StringRef> getFileNameForOffset(uint32_t Offset) { + auto StringT = F.getStringTable(); + if (auto EC = StringT.takeError()) + return std::move(EC); + NameHashTable &ST = StringT.get(); + return ST.getStringForID(Offset); + } + Expected<StringRef> getFileNameForOffset2(uint32_t Offset) { + auto DbiS = F.getPDBDbiStream(); + if (auto EC = DbiS.takeError()) + return std::move(EC); + auto &DS = DbiS.get(); + return DS.getFileNameForIndex(Offset); } ScopedPrinter &P; + PDBFile &F; }; - RecordVisitor V(P); + + RecordVisitor V(P, File); for (const auto &L : ModS.lines(&HadError)) { if (auto EC = codeview::visitModuleSubstream(L, V)) return EC; |