[pdb] Move file layout header structs to RawTypes.h

This facilitates code reuse between the builder classes and the
"frozen" read only versions of the classes used for parsing
existing PDB files.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@276427 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Zachary Turner 2016-07-22 15:46:46 +00:00
parent 6406b60a78
commit 44bd3bd7dc
7 changed files with 210 additions and 160 deletions

View File

@ -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<MappedBlockStream> 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<MappedBlockStream> FpoStream;
codeview::FixedStreamArray<object::FpoData> FpoRecords;
const HeaderInfo *Header;
const DbiStreamHeader *Header;
};
}
}

View File

@ -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 <cstdint>
#include <vector>
@ -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 {

View File

@ -17,6 +17,8 @@
namespace llvm {
namespace pdb {
const uint16_t kInvalidStreamIndex = 0xFFFF;
enum PdbRaw_ImplVer : uint32_t {
PdbImplVC2 = 19941610,
PdbImplVC4 = 19950623,

View File

@ -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

View File

@ -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 <typename ContribType>
static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
StreamReader &Reader) {
@ -81,7 +44,6 @@ static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
DbiStream::DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> 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<RawError>(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<uint16_t>(Type);
if (T >= DbgStreams.size())
return DbiStream::InvalidStreamIndex;
return kInvalidStreamIndex;
return DbgStreams[T];
}

View File

@ -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<std::unique_ptr<DbiStream>> DbiStreamBuilder::build(PDBFile &File) {
if (!DbiS)
return DbiS.takeError();
auto DS = std::move(*DbiS);
DbiStream::HeaderInfo *H =
static_cast<DbiStream::HeaderInfo *>(DS->getAllocator().Allocate(
sizeof(DbiStream::HeaderInfo),
llvm::AlignOf<DbiStream::HeaderInfo>::Alignment));
DbiStreamHeader *H = DS->getAllocator().Allocate<DbiStreamHeader>(1);
if (auto EC = generateModiSubstream())
return std::move(EC);
@ -230,10 +221,10 @@ Expected<std::unique_ptr<DbiStream>> 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<DbiStream>(File, std::move(DS));
Dbi->Header = H;

View File

@ -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;
}