Index: include/llvm/DebugInfo/PDB/PDBExtras.h =================================================================== --- include/llvm/DebugInfo/PDB/PDBExtras.h +++ include/llvm/DebugInfo/PDB/PDBExtras.h @@ -29,6 +29,7 @@ raw_ostream &operator<<(raw_ostream &OS, const PDB_MemberAccess &Access); raw_ostream &operator<<(raw_ostream &OS, const PDB_UdtType &Type); raw_ostream &operator<<(raw_ostream &OS, const PDB_UniqueId &Id); +raw_ostream &operator<<(raw_ostream &OS, const PDB_Machine &Machine); raw_ostream &operator<<(raw_ostream &OS, const Variant &Value); raw_ostream &operator<<(raw_ostream &OS, const VersionInfo &Version); Index: include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h =================================================================== --- /dev/null +++ include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h @@ -0,0 +1,52 @@ +//===- PDBDbiStream.h - PDB Dbi Stream (Stream 3) Access --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H + +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/DebugInfo/PDB/Raw/PDBRawConstants.h" +#include "llvm/DebugInfo/PDB/Raw/PDBStream.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +class PDBFile; + +class PDBDbiStream { + struct HeaderInfo; + +public: + PDBDbiStream(PDBFile &File); + ~PDBDbiStream(); + std::error_code reload(); + + PdbRaw_DbiVer getDbiVersion() const; + uint32_t getAge() const; + + bool isIncrementallyLinked() const; + bool hasCTypes() const; + bool isStripped() const; + + uint16_t getBuildMajorVersion() const; + uint16_t getBuildMinorVersion() const; + + uint32_t getPdbDllVersion() const; + + uint32_t getNumberOfSymbols() const; + + PDB_Machine getMachineType() const; + +private: + PDBStream Stream; + PDBFile &Pdb; + std::unique_ptr Header; +}; +} + +#endif Index: include/llvm/DebugInfo/PDB/Raw/PDBFile.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/PDBFile.h +++ include/llvm/DebugInfo/PDB/Raw/PDBFile.h @@ -20,7 +20,8 @@ class MemoryBuffer; struct PDBFileContext; -class PDBStream; +class PDBDbiStream; +class PDBInfoStream; class PDBFile { public: @@ -55,10 +56,13 @@ return BlockNumber * BlockSize; } - PDBStream *getPDBStream() const; + PDBInfoStream &getPDBInfoStream(); + PDBDbiStream &getPDBDbiStream(); private: std::unique_ptr Context; + std::unique_ptr InfoStream; + std::unique_ptr DbiStream; }; } Index: include/llvm/DebugInfo/PDB/Raw/PDBInfoStream.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/PDBInfoStream.h +++ include/llvm/DebugInfo/PDB/Raw/PDBInfoStream.h @@ -22,7 +22,7 @@ class PDBInfoStream { public: - PDBInfoStream(const PDBFile &File); + PDBInfoStream(PDBFile &File); std::error_code reload(); @@ -35,7 +35,7 @@ private: PDBStream Stream1; - const PDBFile &Pdb; + PDBFile &Pdb; // PDB file format version. We only support VC70. See the enumeration // `PdbRaw_ImplVer` for the other possible values. Index: include/llvm/DebugInfo/PDB/Raw/PDBRawConstants.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/PDBRawConstants.h +++ include/llvm/DebugInfo/PDB/Raw/PDBRawConstants.h @@ -15,16 +15,24 @@ namespace llvm { enum PdbRaw_ImplVer : uint32_t { - VC2 = 19941610, - VC4 = 19950623, - VC41 = 19950814, - VC50 = 19960307, - VC98 = 19970604, - VC70Dep = 19990604, // deprecated - VC70 = 20000404, - VC80 = 20030901, - VC110 = 20091201, - VC140 = 20140508, + PdbImplVC2 = 19941610, + PdbImplVC4 = 19950623, + PdbImplVC41 = 19950814, + PdbImplVC50 = 19960307, + PdbImplVC98 = 19970604, + PdbImplVC70Dep = 19990604, // deprecated + PdbImplVC70 = 20000404, + PdbImplVC80 = 20030901, + PdbImplVC110 = 20091201, + PdbImplVC140 = 20140508, +}; + +enum PdbRaw_DbiVer : uint32_t { + PdbDbiVC41 = 930803, + PdbDbiV50 = 19960307, + PdbDbiV60 = 19970606, + PdbDbiV70 = 19990903, + PdbDbiV110 = 20091201 }; } Index: lib/DebugInfo/PDB/CMakeLists.txt =================================================================== --- lib/DebugInfo/PDB/CMakeLists.txt +++ lib/DebugInfo/PDB/CMakeLists.txt @@ -28,6 +28,7 @@ add_pdb_impl_folder(Raw Raw/PDBFile.cpp + Raw/PDBDbiStream.cpp Raw/PDBInfoStream.cpp Raw/PDBNameMap.cpp Raw/PDBStream.cpp Index: lib/DebugInfo/PDB/PDBExtras.cpp =================================================================== --- lib/DebugInfo/PDB/PDBExtras.cpp +++ lib/DebugInfo/PDB/PDBExtras.cpp @@ -281,6 +281,34 @@ return OS; } +raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_Machine &Machine) { + switch (Machine) { + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, Am33, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, Amd64, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, Arm, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, ArmNT, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, Ebc, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, x86, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, Ia64, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, M32R, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, Mips16, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, MipsFpu, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, MipsFpu16, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, PowerPC, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, PowerPCFP, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, R4000, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, SH3, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, SH3DSP, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, SH4, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, SH5, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, Thumb, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, WceMipsV2, OS) + default: + OS << "Unknown"; + } + return OS; +} + raw_ostream &llvm::operator<<(raw_ostream &OS, const Variant &Value) { switch (Value.Type) { case PDB_VariantType::Bool: Index: lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp =================================================================== --- /dev/null +++ lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp @@ -0,0 +1,142 @@ +//===- PDBDbiStream.cpp - PDB Dbi Stream (Stream 3) Access ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Raw/PDBDbiStream.h" +#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" +#include "llvm/DebugInfo/PDB/Raw/PDBInfoStream.h" +#include "llvm/DebugInfo/PDB/Raw/PDBRawConstants.h" + +using namespace llvm; + +namespace { +// 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 FLAG_INCREMENTAL_MASK = 0x0001; +static const uint16_t FLAG_INCREMENTAL_SHIFT = 0; + +static const uint16_t FLAG_STRIPPED_MASK = 0x0002; +static const uint16_t FLAG_STRIPPED_SHIFT = 1; + +static const uint16_t FLAG_HAS_CTYPES_MASK = 0x0004; +static const uint16_t FLAG_HAS_CTYPES_SHIFT = 2; + +// struct DbiBuildNo { +// uint16_t MinorVersion : 8; +// uint16_t MajorVersion : 7; +// uint16_t NewVersionFormat : 1; +//}; +static const uint16_t BUILD_MINOR_MASK = 0x00FF; +static const uint16_t BUILD_MINOR_SHIFT = 0; + +static const uint16_t BUILD_MAJOR_MASK = 0x7F00; +static const uint16_t BUILD_MAJOR_SHIFT = 8; + +static const uint16_t BUILD_NEWFMT_MASK = 0x8000; +static const uint16_t BUILD_NEWFMT_SHIFT = 15; +} + +struct PDBDbiStream::HeaderInfo { + support::ulittle32_t VersionSignature; + support::ulittle32_t VersionHeader; + support::ulittle32_t Age; // Should match PDBInfoStream. + support::ulittle16_t GSSyms; + support::ulittle16_t BuildNumber; // See DbiBuildNo structure. + support::ulittle16_t PSSyms; + support::ulittle16_t PdbDllVersion; // version of mspdbNNN.dll + support::ulittle16_t SymRecords; // Number of symbols + 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. contribution stream + support::little32_t SectionMapSize; + support::little32_t FileInfoSize; + 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 +}; + +PDBDbiStream::PDBDbiStream(PDBFile &File) : Pdb(File), Stream(3, File) { + static_assert(sizeof(HeaderInfo) == 64, "Invalid HeaderInfo size!"); +} + +PDBDbiStream::~PDBDbiStream() {} + +std::error_code PDBDbiStream::reload() { + Stream.setOffset(0); + Header.reset(new HeaderInfo()); + + if (Stream.getLength() < sizeof(HeaderInfo)) + return std::make_error_code(std::errc::illegal_byte_sequence); + Stream.readObject(Header.get()); + + if (Header->VersionSignature != -1) + return std::make_error_code(std::errc::illegal_byte_sequence); + + // Prior to VC50 an old style header was used. We don't support this. + if (Header->VersionHeader < PdbDbiV50) + return std::make_error_code(std::errc::not_supported); + + if (Header->Age != Pdb.getPDBInfoStream().getAge()) + return std::make_error_code(std::errc::illegal_byte_sequence); + + if (Stream.getLength() != + sizeof(HeaderInfo) + Header->ModiSubstreamSize + + Header->SecContrSubstreamSize + Header->SectionMapSize + + Header->FileInfoSize + Header->TypeServerSize + + Header->OptionalDbgHdrSize + Header->ECSubstreamSize) + return std::make_error_code(std::errc::illegal_byte_sequence); + + return std::error_code(); +} + +PdbRaw_DbiVer PDBDbiStream::getDbiVersion() const { + uint32_t Value = Header->VersionHeader; + return static_cast(Value); +} + +uint32_t PDBDbiStream::getAge() const { return Header->Age; } + +bool PDBDbiStream::isIncrementallyLinked() const { + return !!((Header->Flags & FLAG_INCREMENTAL_MASK) >> FLAG_INCREMENTAL_SHIFT); +} + +bool PDBDbiStream::hasCTypes() const { + return !!((Header->Flags & FLAG_HAS_CTYPES_MASK) >> FLAG_HAS_CTYPES_SHIFT); +} + +bool PDBDbiStream::isStripped() const { + return !!((Header->Flags & FLAG_STRIPPED_MASK) >> FLAG_STRIPPED_SHIFT); +} + +uint16_t PDBDbiStream::getBuildMajorVersion() const { + return (Header->BuildNumber & BUILD_MAJOR_MASK) >> BUILD_MAJOR_SHIFT; +} + +uint16_t PDBDbiStream::getBuildMinorVersion() const { + return (Header->BuildNumber & BUILD_MINOR_MASK) >> BUILD_MINOR_SHIFT; +} + +uint32_t PDBDbiStream::getPdbDllVersion() const { + return Header->PdbDllVersion; +} + +uint32_t PDBDbiStream::getNumberOfSymbols() const { return Header->SymRecords; } + +PDB_Machine PDBDbiStream::getMachineType() const { + uint16_t Machine = Header->MachineType; + return static_cast(Machine); +} Index: lib/DebugInfo/PDB/Raw/PDBFile.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/PDBFile.cpp +++ lib/DebugInfo/PDB/Raw/PDBFile.cpp @@ -9,6 +9,8 @@ #include "llvm/DebugInfo/PDB/Raw/PDBFile.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/PDB/Raw/PDBDbiStream.h" +#include "llvm/DebugInfo/PDB/Raw/PDBInfoStream.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" @@ -236,3 +238,19 @@ Context->Buffer->getBufferStart() + getBlockMapOffset()), getNumDirectoryBlocks()); } + +PDBInfoStream &PDBFile::getPDBInfoStream() { + if (!InfoStream) { + InfoStream.reset(new PDBInfoStream(*this)); + InfoStream->reload(); + } + return *InfoStream; +} + +PDBDbiStream &PDBFile::getPDBDbiStream() { + if (!DbiStream) { + DbiStream.reset(new PDBDbiStream(*this)); + DbiStream->reload(); + } + return *DbiStream; +} Index: lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp +++ lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp @@ -13,15 +13,14 @@ using namespace llvm; -PDBInfoStream::PDBInfoStream(const PDBFile &File) - : Pdb(File), Stream1(1, File) {} +PDBInfoStream::PDBInfoStream(PDBFile &File) : Pdb(File), Stream1(1, File) {} std::error_code PDBInfoStream::reload() { Stream1.setOffset(0); support::ulittle32_t Value; Stream1.readObject(&Version); - if (Version < PdbRaw_ImplVer::VC70) + if (Version < PdbRaw_ImplVer::PdbImplVC70) return std::make_error_code(std::errc::not_supported); Stream1.readObject(&Value); Index: test/DebugInfo/PDB/pdbdump-headers.test =================================================================== --- test/DebugInfo/PDB/pdbdump-headers.test +++ test/DebugInfo/PDB/pdbdump-headers.test @@ -18,3 +18,13 @@ ; CHECK: NameStream: 13 ; CHECK-NEXT: NameStreamSignature: effeeffe ; CHECK-NEXT: NameStreamVersion: 1 + +; CHECK: Dbi Version: 19990903 +; CHECK-NEXT: Age: 1 +; CHECK-NEXT: Incremental Linking: 1 +; CHECK-NEXT: Has CTypes: 0 +; CHECK-NEXT: Is Stripped: 0 +; CHECK-NEXT: Machine Type: x86 +; CHECK-NEXT: Number of Symbols: 8 +; CHECK-NEXT: Toolchain Version: 12.0 +; CHECK-NEXT: mspdb120.dll version: 12.0.31101 Index: tools/llvm-pdbdump/llvm-pdbdump.cpp =================================================================== --- tools/llvm-pdbdump/llvm-pdbdump.cpp +++ tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -35,6 +35,7 @@ #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" #include "llvm/DebugInfo/PDB/PDBSymbolThunk.h" +#include "llvm/DebugInfo/PDB/Raw/PDBDbiStream.h" #include "llvm/DebugInfo/PDB/Raw/PDBFile.h" #include "llvm/DebugInfo/PDB/Raw/PDBInfoStream.h" #include "llvm/DebugInfo/PDB/Raw/PDBStream.h" @@ -234,10 +235,7 @@ } } - PDBInfoStream InfoStream(File); - if (auto EC = InfoStream.reload()) - reportError("", EC); - + PDBInfoStream &InfoStream = File.getPDBInfoStream(); outs() << "Version: " << InfoStream.getVersion() << '\n'; outs() << "Signature: "; outs().write_hex(InfoStream.getSignature()) << '\n'; @@ -264,6 +262,22 @@ if (NameStreamSignature != 0xeffeeffe || NameStreamVersion != 1) reportError("", std::make_error_code(std::errc::not_supported)); } + + PDBDbiStream &DbiStream = File.getPDBDbiStream(); + outs() << "Dbi Version: " << DbiStream.getDbiVersion() << '\n'; + outs() << "Age: " << DbiStream.getAge() << '\n'; + outs() << "Incremental Linking: " << DbiStream.isIncrementallyLinked() + << '\n'; + outs() << "Has CTypes: " << DbiStream.hasCTypes() << '\n'; + outs() << "Is Stripped: " << DbiStream.isStripped() << '\n'; + outs() << "Machine Type: " << DbiStream.getMachineType() << '\n'; + outs() << "Number of Symbols: " << DbiStream.getNumberOfSymbols() << '\n'; + + uint16_t Major = DbiStream.getBuildMajorVersion(); + uint16_t Minor = DbiStream.getBuildMinorVersion(); + outs() << "Toolchain Version: " << Major << "." << Minor << '\n'; + outs() << "mspdb" << Major << Minor << ".dll version: " << Major << "." + << Minor << "." << DbiStream.getPdbDllVersion() << '\n'; } static void dumpInput(StringRef Path) {