diff options
-rw-r--r-- | llvm/include/llvm/DebugInfo/PDB/PDBExtras.h | 1 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h | 52 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h | 8 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/PDB/Raw/PDBRawConstants.h | 28 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/PDBExtras.cpp | 28 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp | 143 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp | 18 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp | 2 | ||||
-rw-r--r-- | llvm/test/DebugInfo/PDB/pdbdump-headers.test | 10 | ||||
-rw-r--r-- | llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp | 22 |
11 files changed, 296 insertions, 17 deletions
diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h b/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h index 48ce1c12719..75706491c2d 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h @@ -29,6 +29,7 @@ raw_ostream &operator<<(raw_ostream &OS, const PDB_SymType &Tag); 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); diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h new file mode 100644 index 00000000000..7cfda03ebf2 --- /dev/null +++ b/llvm/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<HeaderInfo> Header; +}; +} + +#endif diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h index 1ab6d05649d..dd4f2a09df8 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h @@ -20,7 +20,8 @@ namespace llvm { class MemoryBuffer; struct PDBFileContext; -class PDBStream; +class PDBDbiStream; +class PDBInfoStream; class PDBFile { public: @@ -55,10 +56,13 @@ public: return BlockNumber * BlockSize; } - PDBStream *getPDBStream() const; + PDBInfoStream &getPDBInfoStream(); + PDBDbiStream &getPDBDbiStream(); private: std::unique_ptr<PDBFileContext> Context; + std::unique_ptr<PDBInfoStream> InfoStream; + std::unique_ptr<PDBDbiStream> DbiStream; }; } diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBRawConstants.h b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBRawConstants.h index 912c7d1f5ce..17cd0d9c799 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBRawConstants.h +++ b/llvm/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 }; } diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt index 5d6f3022889..24a9e8bf6f5 100644 --- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt +++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt @@ -28,6 +28,7 @@ endif() add_pdb_impl_folder(Raw Raw/PDBFile.cpp + Raw/PDBDbiStream.cpp Raw/PDBInfoStream.cpp Raw/PDBNameMap.cpp Raw/PDBStream.cpp diff --git a/llvm/lib/DebugInfo/PDB/PDBExtras.cpp b/llvm/lib/DebugInfo/PDB/PDBExtras.cpp index 52328db42c1..e044d03fab9 100644 --- a/llvm/lib/DebugInfo/PDB/PDBExtras.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBExtras.cpp @@ -281,6 +281,34 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_UniqueId &Id) { 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: diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp new file mode 100644 index 00000000000..15adae666e3 --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp @@ -0,0 +1,143 @@ +//===- PDBDbiStream.cpp - PDB Dbi Stream (Stream 3) Access ----------------===// +// +// 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; +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; + +const uint16_t BuildNewFormatMask = 0x8000; +const uint16_t BuildNewFormatShift = 15; +} + +struct PDBDbiStream::HeaderInfo { + ulittle32_t VersionSignature; + ulittle32_t VersionHeader; + ulittle32_t Age; // Should match PDBInfoStream. + ulittle16_t GSSyms; + ulittle16_t BuildNumber; // See DbiBuildNo structure. + ulittle16_t PSSyms; + ulittle16_t PdbDllVersion; // version of mspdbNNN.dll + ulittle16_t SymRecords; // Number of symbols + ulittle16_t PdbDllRbld; // rbld number of mspdbNNN.dll + little32_t ModiSubstreamSize; // Size of module info stream + little32_t SecContrSubstreamSize; // Size of sec. contribution stream + little32_t SectionMapSize; + little32_t FileInfoSize; + little32_t TypeServerSize; // Size of type server map + ulittle32_t MFCTypeServerIndex; // Index of MFC Type Server + little32_t OptionalDbgHdrSize; // Size of DbgHeader info + little32_t ECSubstreamSize; // Size of EC stream (what is EC?) + ulittle16_t Flags; // See DbiFlags enum. + ulittle16_t MachineType; // See PDB_MachineType enum. + + 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<PdbRaw_DbiVer>(Value); +} + +uint32_t PDBDbiStream::getAge() const { return Header->Age; } + +bool PDBDbiStream::isIncrementallyLinked() const { + return (Header->Flags & FlagIncrementalMask) != 0; +} + +bool PDBDbiStream::hasCTypes() const { + return (Header->Flags & FlagHasCTypesMask) != 0; +} + +bool PDBDbiStream::isStripped() const { + return (Header->Flags & FlagStrippedMask) != 0; +} + +uint16_t PDBDbiStream::getBuildMajorVersion() const { + return (Header->BuildNumber & BuildMajorMask) >> BuildMajorShift; +} + +uint16_t PDBDbiStream::getBuildMinorVersion() const { + return (Header->BuildNumber & BuildMinorMask) >> BuildMinorShift; +} + +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<PDB_Machine>(Machine); +} diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp index 01d7554a183..6fefafe597c 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp +++ b/llvm/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 @@ llvm::ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() { 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; +} diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp index 76fa1952d7f..8b12eeaf8dd 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp @@ -20,7 +20,7 @@ std::error_code PDBInfoStream::reload() { 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); diff --git a/llvm/test/DebugInfo/PDB/pdbdump-headers.test b/llvm/test/DebugInfo/PDB/pdbdump-headers.test index 5f6961294b3..4bb05cb0f8e 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-headers.test +++ b/llvm/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 diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp index c9c78a97110..4f24e058f21 100644 --- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/llvm/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 @@ static void dumpStructure(RawSession &RS) { } } - 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 @@ static void dumpStructure(RawSession &RS) { 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) { |