diff --git a/include/llvm/DebugInfo/PDB/Raw/DbiStream.h b/include/llvm/DebugInfo/PDB/Raw/DbiStream.h index e0ca91029c7..3d2552e1c63 100644 --- a/include/llvm/DebugInfo/PDB/Raw/DbiStream.h +++ b/include/llvm/DebugInfo/PDB/Raw/DbiStream.h @@ -36,30 +36,6 @@ class ISectionContribVisitor; class DbiStream { friend class DbiStreamBuilder; - struct HeaderInfo { - support::little32_t VersionSignature; - support::ulittle32_t VersionHeader; - support::ulittle32_t Age; // Should match InfoStream. - support::ulittle16_t GlobalSymbolStreamIndex; // Global symbol stream # - support::ulittle16_t BuildNumber; // See DbiBuildNo structure. - support::ulittle16_t PublicSymbolStreamIndex; // Public symbols stream # - support::ulittle16_t PdbDllVersion; // version of mspdbNNN.dll - support::ulittle16_t SymRecordStreamIndex; // Symbol records stream # - support::ulittle16_t PdbDllRbld; // rbld number of mspdbNNN.dll - support::little32_t ModiSubstreamSize; // Size of module info stream - support::little32_t SecContrSubstreamSize; // Size of sec. contrib stream - support::little32_t SectionMapSize; // Size of sec. map substream - support::little32_t FileInfoSize; // Size of file info substream - support::little32_t TypeServerSize; // Size of type server map - support::ulittle32_t MFCTypeServerIndex; // Index of MFC Type Server - support::little32_t OptionalDbgHdrSize; // Size of DbgHeader info - support::little32_t ECSubstreamSize; // Size of EC stream (what is EC?) - support::ulittle16_t Flags; // See DbiFlags enum. - support::ulittle16_t MachineType; // See PDB_MachineType enum. - - support::ulittle32_t Reserved; // Pad to 64 bytes - }; - public: DbiStream(PDBFile &File, std::unique_ptr Stream); ~DbiStream(); @@ -86,8 +62,6 @@ public: PDB_Machine getMachineType() const; - enum { InvalidStreamIndex = 0xffff }; - /// If the given stream type is present, returns its stream index. If it is /// not present, returns InvalidStreamIndex. uint32_t getDebugStreamIndex(DbgHeaderType Type) const; @@ -142,7 +116,7 @@ private: std::unique_ptr FpoStream; codeview::FixedStreamArray FpoRecords; - const HeaderInfo *Header; + const DbiStreamHeader *Header; }; } } diff --git a/include/llvm/DebugInfo/PDB/Raw/ModInfo.h b/include/llvm/DebugInfo/PDB/Raw/ModInfo.h index f1648be3edf..62282c28017 100644 --- a/include/llvm/DebugInfo/PDB/Raw/ModInfo.h +++ b/include/llvm/DebugInfo/PDB/Raw/ModInfo.h @@ -13,6 +13,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/StreamArray.h" #include "llvm/DebugInfo/CodeView/StreamRef.h" +#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" #include "llvm/Support/Endian.h" #include #include @@ -23,58 +24,6 @@ namespace pdb { class ModInfo { friend class DbiStreamBuilder; -private: - typedef support::ulittle16_t ulittle16_t; - typedef support::ulittle32_t ulittle32_t; - typedef support::little32_t little32_t; - - struct SCBytes { - ulittle16_t Section; - char Padding1[2]; - little32_t Offset; - little32_t Size; - ulittle32_t Characteristics; - ulittle16_t ModuleIndex; - char Padding2[2]; - ulittle32_t DataCrc; - ulittle32_t RelocCrc; - }; - - // struct Flags { - // uint16_t fWritten : 1; // True if ModInfo is dirty - // uint16_t fECEnabled : 1; // Is EC symbolic info present? (What is EC?) - // uint16_t unused : 6; // Reserved - // uint16_t iTSM : 8; // Type Server Index for this module - //}; - const uint16_t HasECFlagMask = 0x2; - - const uint16_t TypeServerIndexMask = 0xFF00; - const uint16_t TypeServerIndexShift = 8; - - struct FileLayout { - ulittle32_t Mod; // Currently opened module. This field is a - // pointer in the reference implementation, but - // that won't work on 64-bit systems, and anyway - // it doesn't make sense to read a pointer from a - // file. For now it is unused, so just ignore it. - SCBytes SC; // First section contribution of this module. - ulittle16_t Flags; // See Flags definition. - ulittle16_t ModDiStream; // Stream Number of module debug info - ulittle32_t SymBytes; // Size of local symbol debug info in above stream - ulittle32_t LineBytes; // Size of line number debug info in above stream - ulittle32_t C13Bytes; // Size of C13 line number info in above stream - ulittle16_t NumFiles; // Number of files contributing to this module - char Padding1[2]; // Padding so the next field is 4-byte aligned. - ulittle32_t FileNameOffs; // array of [0..NumFiles) DBI name buffer offsets. - // This field is a pointer in the reference - // implementation, but as with `Mod`, we ignore it - // for now since it is unused. - ulittle32_t SrcFileNameNI; // Name Index for src file name - ulittle32_t PdbFilePathNI; // Name Index for path to compiler PDB - // Null terminated Module name - // Null terminated Obj File Name - }; - public: ModInfo(); ModInfo(const ModInfo &Info); @@ -100,7 +49,7 @@ public: private: StringRef ModuleName; StringRef ObjFileName; - const FileLayout *Layout; + const ModuleInfoHeader *Layout; }; struct ModuleInfoEx { diff --git a/include/llvm/DebugInfo/PDB/Raw/RawConstants.h b/include/llvm/DebugInfo/PDB/Raw/RawConstants.h index 8daaf47882d..73bc09c1dbe 100644 --- a/include/llvm/DebugInfo/PDB/Raw/RawConstants.h +++ b/include/llvm/DebugInfo/PDB/Raw/RawConstants.h @@ -17,6 +17,8 @@ namespace llvm { namespace pdb { +const uint16_t kInvalidStreamIndex = 0xFFFF; + enum PdbRaw_ImplVer : uint32_t { PdbImplVC2 = 19941610, PdbImplVC4 = 19950623, diff --git a/include/llvm/DebugInfo/PDB/Raw/RawTypes.h b/include/llvm/DebugInfo/PDB/Raw/RawTypes.h index afcfe9405c0..8567f827e70 100644 --- a/include/llvm/DebugInfo/PDB/Raw/RawTypes.h +++ b/include/llvm/DebugInfo/PDB/Raw/RawTypes.h @@ -80,6 +80,185 @@ struct TypeIndexOffset { support::ulittle32_t Offset; }; +/// Some of the values are stored in bitfields. Since this needs to be portable +/// across compilers and architectures (big / little endian in particular) we +/// can't use the actual structures below, but must instead do the shifting +/// and masking ourselves. The struct definitions are provided for reference. +struct DbiFlags { + /// uint16_t IncrementalLinking : 1; // True if linked incrementally + /// uint16_t IsStripped : 1; // True if private symbols were + /// stripped. + /// uint16_t HasCTypes : 1; // True if linked with /debug:ctypes. + /// uint16_t Reserved : 13; + static const uint16_t FlagIncrementalMask = 0x0001; + static const uint16_t FlagStrippedMask = 0x0002; + static const uint16_t FlagHasCTypesMask = 0x0004; +}; + +struct DbiBuildNo { + /// uint16_t MinorVersion : 8; + /// uint16_t MajorVersion : 7; + /// uint16_t NewVersionFormat : 1; + static const uint16_t BuildMinorMask = 0x00FF; + static const uint16_t BuildMinorShift = 0; + + static const uint16_t BuildMajorMask = 0x7F00; + static const uint16_t BuildMajorShift = 8; +}; + +/// The fixed size header that appears at the beginning of the DBI Stream. +struct DbiStreamHeader { + support::little32_t VersionSignature; + support::ulittle32_t VersionHeader; + + /// How "old" is this DBI Stream. Should match the age of the PDB InfoStream. + support::ulittle32_t Age; + + /// Global symbol stream # + support::ulittle16_t GlobalSymbolStreamIndex; + + /// See DbiBuildNo structure. + support::ulittle16_t BuildNumber; + + /// Public symbols stream # + support::ulittle16_t PublicSymbolStreamIndex; + + /// version of mspdbNNN.dll + support::ulittle16_t PdbDllVersion; + + /// Symbol records stream # + support::ulittle16_t SymRecordStreamIndex; + + /// rbld number of mspdbNNN.dll + support::ulittle16_t PdbDllRbld; + + /// Size of module info stream + support::little32_t ModiSubstreamSize; + + /// Size of sec. contrib stream + support::little32_t SecContrSubstreamSize; + + /// Size of sec. map substream + support::little32_t SectionMapSize; + + /// Size of file info substream + support::little32_t FileInfoSize; + + /// Size of type server map + support::little32_t TypeServerSize; + + /// Index of MFC Type Server + support::ulittle32_t MFCTypeServerIndex; + + /// Size of DbgHeader info + support::little32_t OptionalDbgHdrSize; + + /// Size of EC stream (what is EC?) + support::little32_t ECSubstreamSize; + + /// See DbiFlags enum. + support::ulittle16_t Flags; + + /// See PDB_MachineType enum. + support::ulittle16_t MachineType; + + /// Pad to 64 bytes + support::ulittle32_t Reserved; +}; +static_assert(sizeof(DbiStreamHeader) == 64, "Invalid DbiStreamHeader size!"); + +struct SectionContribEntry { + support::ulittle16_t Section; + char Padding1[2]; + support::little32_t Offset; + support::little32_t Size; + support::ulittle32_t Characteristics; + support::ulittle16_t ModuleIndex; + char Padding2[2]; + support::ulittle32_t DataCrc; + support::ulittle32_t RelocCrc; +}; + +/// The header preceeding the File Info Substream of the DBI stream. +struct FileInfoSubstreamHeader { + /// Total # of modules, should match number of records in the ModuleInfo + /// substream. + support::ulittle16_t NumModules; + + /// Total # of source files. This value is not accurate because PDB actually + /// supports more than 64k source files, so we ignore it and compute the value + /// from other stream fields. + support::ulittle16_t NumSourceFiles; + + /// Following this header the File Info Substream is laid out as follows: + /// ulittle16_t ModIndices[NumModules]; + /// ulittle16_t ModFileCounts[NumModules]; + /// ulittle32_t FileNameOffsets[NumSourceFiles]; + /// char Names[][NumSourceFiles]; + /// with the caveat that `NumSourceFiles` cannot be trusted, so + /// it is computed by summing the `ModFileCounts` array. +}; + +struct ModInfoFlags { + /// uint16_t fWritten : 1; // True if ModInfo is dirty + /// uint16_t fECEnabled : 1; // Is EC symbolic info present? (What is EC?) + /// uint16_t unused : 6; // Reserved + /// uint16_t iTSM : 8; // Type Server Index for this module + static const uint16_t HasECFlagMask = 0x2; + + static const uint16_t TypeServerIndexMask = 0xFF00; + static const uint16_t TypeServerIndexShift = 8; +}; + +/// The header preceeding each entry in the Module Info substream of the DBI +/// stream. +struct ModuleInfoHeader { + /// Currently opened module. This field is a pointer in the reference + /// implementation, but that won't work on 64-bit systems, and anyway it + /// doesn't make sense to read a pointer from a file. For now it is unused, + /// so just ignore it. + support::ulittle32_t Mod; + + /// First section contribution of this module. + SectionContribEntry SC; + + /// See ModInfoFlags definition. + support::ulittle16_t Flags; + + /// Stream Number of module debug info + support::ulittle16_t ModDiStream; + + /// Size of local symbol debug info in above stream + support::ulittle32_t SymBytes; + + /// Size of line number debug info in above stream + support::ulittle32_t LineBytes; + + /// Size of C13 line number info in above stream + support::ulittle32_t C13Bytes; + + /// Number of files contributing to this module + support::ulittle16_t NumFiles; + + /// Padding so the next field is 4-byte aligned. + char Padding1[2]; + + /// Array of [0..NumFiles) DBI name buffer offsets. This field is a pointer + /// in the reference implementation, but as with `Mod`, we ignore it for now + /// since it is unused. + support::ulittle32_t FileNameOffs; + + /// Name Index for src file name + support::ulittle32_t SrcFileNameNI; + + /// Name Index for path to compiler PDB + support::ulittle32_t PdbFilePathNI; + + /// Following this header are two zero terminated strings. + /// char ModuleName[]; + /// char ObjFileName[]; +}; + } // namespace pdb } // namespace llvm diff --git a/lib/DebugInfo/PDB/Raw/DbiStream.cpp b/lib/DebugInfo/PDB/Raw/DbiStream.cpp index 63a7ba109ce..430a84f93a2 100644 --- a/lib/DebugInfo/PDB/Raw/DbiStream.cpp +++ b/lib/DebugInfo/PDB/Raw/DbiStream.cpp @@ -28,43 +28,6 @@ using namespace llvm::codeview; using namespace llvm::pdb; using namespace llvm::support; -namespace { -// Some of the values are stored in bitfields. Since this needs to be portable -// across compilers and architectures (big / little endian in particular) we -// can't use the actual structures below, but must instead do the shifting -// and masking ourselves. The struct definitions are provided for reference. - -// struct DbiFlags { -// uint16_t IncrementalLinking : 1; // True if linked incrementally -// uint16_t IsStripped : 1; // True if private symbols were stripped. -// uint16_t HasCTypes : 1; // True if linked with /debug:ctypes. -// uint16_t Reserved : 13; -//}; -const uint16_t FlagIncrementalMask = 0x0001; -const uint16_t FlagStrippedMask = 0x0002; -const uint16_t FlagHasCTypesMask = 0x0004; - -// struct DbiBuildNo { -// uint16_t MinorVersion : 8; -// uint16_t MajorVersion : 7; -// uint16_t NewVersionFormat : 1; -//}; -const uint16_t BuildMinorMask = 0x00FF; -const uint16_t BuildMinorShift = 0; - -const uint16_t BuildMajorMask = 0x7F00; -const uint16_t BuildMajorShift = 8; - -struct FileInfoSubstreamHeader { - ulittle16_t NumModules; // Total # of modules, should match number of - // records in the ModuleInfo substream. - ulittle16_t NumSourceFiles; // Total # of source files. This value is not - // accurate because PDB actually supports more - // than 64k source files, so we ignore it and - // compute the value from other stream fields. -}; -} - template static Error loadSectionContribs(FixedStreamArray &Output, StreamReader &Reader) { @@ -81,7 +44,6 @@ static Error loadSectionContribs(FixedStreamArray &Output, DbiStream::DbiStream(PDBFile &File, std::unique_ptr Stream) : Pdb(File), Stream(std::move(Stream)), Header(nullptr) { - static_assert(sizeof(HeaderInfo) == 64, "Invalid HeaderInfo size!"); } DbiStream::~DbiStream() {} @@ -89,7 +51,7 @@ DbiStream::~DbiStream() {} Error DbiStream::reload() { StreamReader Reader(*Stream); - if (Stream->getLength() < sizeof(HeaderInfo)) + if (Stream->getLength() < sizeof(DbiStreamHeader)) return make_error(raw_error_code::corrupt_file, "DBI Stream does not contain a header."); if (auto EC = Reader.readObject(Header)) @@ -116,7 +78,7 @@ Error DbiStream::reload() { "DBI Age does not match PDB Age."); if (Stream->getLength() != - sizeof(HeaderInfo) + Header->ModiSubstreamSize + + sizeof(DbiStreamHeader) + Header->ModiSubstreamSize + Header->SecContrSubstreamSize + Header->SectionMapSize + Header->FileInfoSize + Header->TypeServerSize + Header->OptionalDbgHdrSize + Header->ECSubstreamSize) @@ -206,25 +168,27 @@ uint16_t DbiStream::getGlobalSymbolStreamIndex() const { uint16_t DbiStream::getFlags() const { return Header->Flags; } bool DbiStream::isIncrementallyLinked() const { - return (Header->Flags & FlagIncrementalMask) != 0; + return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0; } bool DbiStream::hasCTypes() const { - return (Header->Flags & FlagHasCTypesMask) != 0; + return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0; } bool DbiStream::isStripped() const { - return (Header->Flags & FlagStrippedMask) != 0; + return (Header->Flags & DbiFlags::FlagStrippedMask) != 0; } uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; } uint16_t DbiStream::getBuildMajorVersion() const { - return (Header->BuildNumber & BuildMajorMask) >> BuildMajorShift; + return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >> + DbiBuildNo::BuildMajorShift; } uint16_t DbiStream::getBuildMinorVersion() const { - return (Header->BuildNumber & BuildMinorMask) >> BuildMinorShift; + return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >> + DbiBuildNo::BuildMinorShift; } uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; } @@ -336,7 +300,7 @@ Error DbiStream::initializeFpoRecords() { uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::NewFPO); // This means there is no FPO data. - if (StreamNum == InvalidStreamIndex) + if (StreamNum == kInvalidStreamIndex) return Error::success(); if (StreamNum >= Pdb.getNumStreams()) @@ -374,18 +338,6 @@ Error DbiStream::initializeSectionMapData() { } Error DbiStream::initializeFileInfo() { - // The layout of the FileInfoSubstream is like this: - // struct { - // ulittle16_t NumModules; - // ulittle16_t NumSourceFiles; - // ulittle16_t ModIndices[NumModules]; - // ulittle16_t ModFileCounts[NumModules]; - // ulittle32_t FileNameOffsets[NumSourceFiles]; - // char Names[][NumSourceFiles]; - // }; - // with the caveat that `NumSourceFiles` cannot be trusted, so - // it is computed by summing `ModFileCounts`. - // if (FileInfoSubstream.getLength() == 0) return Error::success(); @@ -454,7 +406,7 @@ Error DbiStream::initializeFileInfo() { uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const { uint16_t T = static_cast(Type); if (T >= DbgStreams.size()) - return DbiStream::InvalidStreamIndex; + return kInvalidStreamIndex; return DbgStreams[T]; } diff --git a/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp b/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp index bbb0876380d..751f869c52a 100644 --- a/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp +++ b/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp @@ -42,7 +42,7 @@ void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; } uint32_t DbiStreamBuilder::calculateSerializedLength() const { // For now we only support serializing the header. - return sizeof(DbiStream::HeaderInfo) + calculateFileInfoSubstreamSize() + + return sizeof(DbiStreamHeader) + calculateFileInfoSubstreamSize() + calculateModiSubstreamSize(); } @@ -74,7 +74,7 @@ Error DbiStreamBuilder::addModuleSourceFile(StringRef Module, StringRef File) { uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const { uint32_t Size = 0; for (const auto &M : ModuleInfoList) { - Size += sizeof(ModInfo::FileLayout); + Size += sizeof(ModuleInfoHeader); Size += M->Mod.size() + 1; Size += M->Obj.size() + 1; } @@ -82,12 +82,6 @@ uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const { } uint32_t DbiStreamBuilder::calculateFileInfoSubstreamSize() const { - // ulittle16_t NumModules; - // ulittle16_t NumSourceFiles; - // ulittle16_t ModIndices[NumModules]; - // ulittle16_t ModFileCounts[NumModules]; - // ulittle32_t FileNameOffsets[NumSourceFiles]; - // char Names[NumSourceFiles][]; uint32_t Size = 0; Size += sizeof(ulittle16_t); // NumModules Size += sizeof(ulittle16_t); // NumSourceFiles @@ -117,8 +111,8 @@ Error DbiStreamBuilder::generateModiSubstream() { StreamWriter ModiWriter(ModInfoBuffer); for (const auto &M : ModuleInfoList) { - ModInfo::FileLayout Layout = {}; - Layout.ModDiStream = DbiStream::InvalidStreamIndex; + ModuleInfoHeader Layout = {}; + Layout.ModDiStream = kInvalidStreamIndex; Layout.NumFiles = M->SourceFiles.size(); if (auto EC = ModiWriter.writeObject(Layout)) return EC; @@ -204,10 +198,7 @@ Expected> DbiStreamBuilder::build(PDBFile &File) { if (!DbiS) return DbiS.takeError(); auto DS = std::move(*DbiS); - DbiStream::HeaderInfo *H = - static_cast(DS->getAllocator().Allocate( - sizeof(DbiStream::HeaderInfo), - llvm::AlignOf::Alignment)); + DbiStreamHeader *H = DS->getAllocator().Allocate(1); if (auto EC = generateModiSubstream()) return std::move(EC); @@ -230,10 +221,10 @@ Expected> DbiStreamBuilder::build(PDBFile &File) { H->SecContrSubstreamSize = 0; H->SectionMapSize = 0; H->TypeServerSize = 0; - H->SymRecordStreamIndex = DbiStream::InvalidStreamIndex; - H->PublicSymbolStreamIndex = DbiStream::InvalidStreamIndex; - H->MFCTypeServerIndex = DbiStream::InvalidStreamIndex; - H->GlobalSymbolStreamIndex = DbiStream::InvalidStreamIndex; + H->SymRecordStreamIndex = kInvalidStreamIndex; + H->PublicSymbolStreamIndex = kInvalidStreamIndex; + H->MFCTypeServerIndex = kInvalidStreamIndex; + H->GlobalSymbolStreamIndex = kInvalidStreamIndex; auto Dbi = llvm::make_unique(File, std::move(DS)); Dbi->Header = H; diff --git a/lib/DebugInfo/PDB/Raw/ModInfo.cpp b/lib/DebugInfo/PDB/Raw/ModInfo.cpp index 538fe225599..9d0a0ae6e36 100644 --- a/lib/DebugInfo/PDB/Raw/ModInfo.cpp +++ b/lib/DebugInfo/PDB/Raw/ModInfo.cpp @@ -39,10 +39,13 @@ Error ModInfo::initialize(codeview::StreamRef Stream, ModInfo &Info) { return Error::success(); } -bool ModInfo::hasECInfo() const { return (Layout->Flags & HasECFlagMask) != 0; } +bool ModInfo::hasECInfo() const { + return (Layout->Flags & ModInfoFlags::HasECFlagMask) != 0; +} uint16_t ModInfo::getTypeServerIndex() const { - return (Layout->Flags & TypeServerIndexMask) >> TypeServerIndexShift; + return (Layout->Flags & ModInfoFlags::TypeServerIndexMask) >> + ModInfoFlags::TypeServerIndexShift; } uint16_t ModInfo::getModuleStreamIndex() const { return Layout->ModDiStream; } @@ -72,7 +75,7 @@ StringRef ModInfo::getObjFileName() const { return ObjFileName; } uint32_t ModInfo::getRecordLength() const { uint32_t M = ModuleName.str().size() + 1; uint32_t O = ObjFileName.str().size() + 1; - uint32_t Size = sizeof(FileLayout) + M + O; + uint32_t Size = sizeof(ModuleInfoHeader) + M + O; Size = llvm::alignTo(Size, 4); return Size; }