Index: include/llvm/DebugInfo/CodeView/StreamReader.h =================================================================== --- include/llvm/DebugInfo/CodeView/StreamReader.h +++ include/llvm/DebugInfo/CodeView/StreamReader.h @@ -36,6 +36,14 @@ Error readStreamRef(StreamRef &Ref); Error readStreamRef(StreamRef &Ref, uint32_t Length); + template Error readEnum(T &Dest) { + typename std::underlying_type::type N; + if (auto EC = readInteger(N)) + return EC; + Dest = static_cast(N); + return Error::success(); + } + template Error readObject(const T *&Dest) { ArrayRef Buffer; if (auto EC = readBytes(Buffer, sizeof(T))) Index: include/llvm/DebugInfo/PDB/Raw/DbiStream.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/DbiStream.h +++ include/llvm/DebugInfo/PDB/Raw/DbiStream.h @@ -17,12 +17,14 @@ #include "llvm/DebugInfo/PDB/Raw/ModInfo.h" #include "llvm/DebugInfo/PDB/Raw/NameHashTable.h" #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" +#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" namespace llvm { namespace pdb { class PDBFile; +class ISectionContrVisitor; class DbiStream { struct HeaderInfo; @@ -50,11 +52,16 @@ PDB_Machine getMachineType() const; + uint32_t getDebugStreamIndex(DbgHeaderType Type) const; + ArrayRef modules() const; - uint32_t getDebugStreamIndex(DbgHeaderType Type) const; + codeview::FixedStreamArray getSectionMap() const; + void visitSectionContributions(ISectionContrVisitor &Visitor) const; private: + Error initializeSectionContributionData(); + Error initializeSectionMapData(); Error initializeFileInfo(); PDBFile &Pdb; @@ -72,6 +79,11 @@ codeview::FixedStreamArray DbgStreams; + PdbRaw_DbiSecContrVer SectionContrVersion; + codeview::FixedStreamArray SectionContrs; + codeview::FixedStreamArray SectionContrs2; + codeview::FixedStreamArray SectionMap; + const HeaderInfo *Header; }; } Index: include/llvm/DebugInfo/PDB/Raw/ISectionContrVisitor.h =================================================================== --- /dev/null +++ include/llvm/DebugInfo/PDB/Raw/ISectionContrVisitor.h @@ -0,0 +1,28 @@ +//===- ISectionContrVisitor.h -----------------------------------*- 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_ISECTIONCONTRVISITOR_H +#define LLVM_DEBUGINFO_PDB_RAW_ISECTIONCONTRVISITOR_H + +namespace llvm { +namespace pdb { +struct SectionContr; +struct SectionContr2; + +class ISectionContrVisitor { +public: + virtual ~ISectionContrVisitor() {} + + virtual void visit(const SectionContr &C) = 0; + virtual void visit(const SectionContr2 &C) = 0; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_RAW_ISECTIONCONTRVISITOR_H \ No newline at end of file Index: include/llvm/DebugInfo/PDB/Raw/PublicsStream.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/PublicsStream.h +++ include/llvm/DebugInfo/PDB/Raw/PublicsStream.h @@ -15,6 +15,7 @@ #include "llvm/DebugInfo/PDB/PDBTypes.h" #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" +#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" #include "llvm/Support/Error.h" Index: include/llvm/DebugInfo/PDB/Raw/RawConstants.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/RawConstants.h +++ include/llvm/DebugInfo/PDB/Raw/RawConstants.h @@ -1,4 +1,4 @@ -//===- PDBRawConstants.h ----------------------------------------*- C++ -*-===// +//===- RawConstants.h -------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,8 +10,6 @@ #ifndef LLVM_DEBUGINFO_PDB_RAW_PDBRAWCONSTANTS_H #define LLVM_DEBUGINFO_PDB_RAW_PDBRAWCONSTANTS_H -#include "llvm/Support/Endian.h" - #include namespace llvm { @@ -46,6 +44,11 @@ PdbTpiV80 = 20040203, }; +enum PdbRaw_DbiSecContrVer : uint32_t { + DbiSecContrVer60 = 0xeffe0000 + 19970605, + DbiSecContrV2 = 0xeffe0000 + 20140516 +}; + enum SpecialStream : uint32_t { // Stream 0 contains the copy of previous version of the MSF directory. // We are not currently using it, but technically if we find the main @@ -73,19 +76,6 @@ Max }; -// This struct is defined as "SO" in langapi/include/pdb.h. -struct SectionOffset { - support::ulittle32_t Off; - support::ulittle16_t Isect; - char Padding[2]; -}; - -// This is HRFile. -struct PSHashRecord { - support::ulittle32_t Off; // Offset in the symbol record stream - support::ulittle32_t CRef; -}; - } // end namespace pdb } // end namespace llvm Index: include/llvm/DebugInfo/PDB/Raw/RawTypes.h =================================================================== --- /dev/null +++ include/llvm/DebugInfo/PDB/Raw/RawTypes.h @@ -0,0 +1,73 @@ +//===- RawTypes.h -----------------------------------------------*- 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_RAWTYPES_H +#define LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H + +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace pdb { +// This struct is defined as "SO" in langapi/include/pdb.h. +struct SectionOffset { + support::ulittle32_t Off; + support::ulittle16_t Isect; + char Padding[2]; +}; + +// This is HRFile. +struct PSHashRecord { + support::ulittle32_t Off; // Offset in the symbol record stream + support::ulittle32_t CRef; +}; + +// This struct is defined as `SC` in include/dbicommon.h +struct SectionContr { + support::ulittle16_t ISect; + char Padding[2]; + support::little32_t Off; + support::little32_t Size; + support::ulittle32_t Characteristics; + support::ulittle16_t Imod; + char Padding2[2]; + support::ulittle32_t DataCrc; + support::ulittle32_t RelocCrc; +}; + +// This struct is defined as `SC2` in include/dbicommon.h +struct SectionContr2 : public SectionContr { + support::ulittle32_t ISectCoff; +}; + +// This corresponds to the `OMFSegMap` structure. The definition is not +// present in the reference implementation, but the layout is derived from +// code that accesses the fields. +struct SecMapHeader { + support::ulittle16_t SecCount; + support::ulittle16_t SecCountLog; +}; + +// This corresponds to the `OMFSegMapDesc` structure. The definition is not +// present in the reference implementation, but the layout is derived from +// code that accesses the fields. +struct SecMapEntry { + support::ulittle16_t Flags; + support::ulittle16_t Ovl; + support::ulittle16_t Group; + support::ulittle16_t Frame; + support::ulittle16_t SecName; + support::ulittle16_t ClassName; + support::ulittle32_t Offset; + support::ulittle32_t SecByteLength; +}; + +} // namespace pdb +} // namespace llvm + +#endif \ No newline at end of file Index: lib/DebugInfo/PDB/Raw/DbiStream.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/DbiStream.cpp +++ lib/DebugInfo/PDB/Raw/DbiStream.cpp @@ -10,14 +10,17 @@ #include "llvm/DebugInfo/CodeView/StreamArray.h" #include "llvm/DebugInfo/CodeView/StreamReader.h" +#include "llvm/DebugInfo/PDB/Raw/ISectionContrVisitor.h" #include "llvm/DebugInfo/PDB/Raw/InfoStream.h" #include "llvm/DebugInfo/PDB/Raw/ModInfo.h" #include "llvm/DebugInfo/PDB/Raw/NameHashTable.h" #include "llvm/DebugInfo/PDB/Raw/PDBFile.h" #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" #include "llvm/DebugInfo/PDB/Raw/RawError.h" +#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" using namespace llvm; +using namespace llvm::codeview; using namespace llvm::pdb; using namespace llvm::support; @@ -73,6 +76,20 @@ ulittle32_t Reserved; // Pad to 64 bytes }; +template +Error loadSectionContributions(FixedStreamArray &Output, + StreamReader &Reader) { + if (Reader.bytesRemaining() % sizeof(ContrType) != 0) + return make_error( + raw_error_code::corrupt_file, + "Invalid number of bytes of section contributions"); + + uint32_t Count = Reader.bytesRemaining() / sizeof(ContrType); + if (auto EC = Reader.readArray(Output, Count)) + return EC; + return Error::success(); +} + DbiStream::DbiStream(PDBFile &File) : Pdb(File), Stream(StreamDBI, File), Header(nullptr) { static_assert(sizeof(HeaderInfo) == 64, "Invalid HeaderInfo size!"); @@ -81,7 +98,7 @@ DbiStream::~DbiStream() {} Error DbiStream::reload() { - codeview::StreamReader Reader(Stream); + StreamReader Reader(Stream); if (Stream.getLength() < sizeof(HeaderInfo)) return make_error(raw_error_code::corrupt_file, @@ -98,7 +115,7 @@ // produced in the last decade and allows us to avoid having to // special case all kinds of complicated arcane formats. if (Header->VersionHeader < PdbDbiV70) - return make_error(raw_error_code::corrupt_file, + return make_error(raw_error_code::feature_unsupported, "Unsupported DBI version."); auto InfoStream = Pdb.getPDBInfoStream(); @@ -138,7 +155,7 @@ // Since each ModInfo in the stream is a variable length, we have to iterate // them to know how many there actually are. - codeview::VarStreamArray ModInfoArray; + VarStreamArray ModInfoArray; if (auto EC = Reader.readArray(ModInfoArray, Header->ModiSubstreamSize)) return EC; for (auto &Info : ModInfoArray) { @@ -161,6 +178,12 @@ sizeof(ulittle16_t))) return EC; + if (auto EC = initializeSectionContributionData()) + return EC; + + if (auto EC = initializeSectionMapData()) + return EC; + if (auto EC = initializeFileInfo()) return EC; @@ -168,7 +191,7 @@ return make_error(raw_error_code::corrupt_file, "Found unexpected bytes in DBI Stream."); - codeview::StreamReader ECReader(ECSubstream); + StreamReader ECReader(ECSubstream); if (auto EC = ECNames.load(ECReader)) return EC; @@ -222,6 +245,44 @@ } ArrayRef DbiStream::modules() const { return ModuleInfos; } +codeview::FixedStreamArray DbiStream::getSectionMap() const { + return SectionMap; +} + +void llvm::pdb::DbiStream::visitSectionContributions( + ISectionContrVisitor &Visitor) const { + if (SectionContrVersion == DbiSecContrVer60) { + for (auto &SC : SectionContrs) + Visitor.visit(SC); + } else if (SectionContrVersion == DbiSecContrV2) { + for (auto &SC : SectionContrs2) + Visitor.visit(SC); + } +} + +Error DbiStream::initializeSectionContributionData() { + StreamReader SCReader(SecContrSubstream); + if (auto EC = SCReader.readEnum(SectionContrVersion)) + return EC; + + if (SectionContrVersion == DbiSecContrVer60) + return loadSectionContributions(SectionContrs, SCReader); + if (SectionContrVersion == DbiSecContrV2) + return loadSectionContributions(SectionContrs2, SCReader); + + return make_error(raw_error_code::feature_unsupported, + "Unsupported DBI Section Contribution version"); +} + +Error DbiStream::initializeSectionMapData() { + StreamReader SMReader(SecMapSubstream); + const SecMapHeader *Header; + if (auto EC = SMReader.readObject(Header)) + return EC; + if (auto EC = SMReader.readArray(SectionMap, Header->SecCount)) + return EC; + return Error::success(); +} Error DbiStream::initializeFileInfo() { struct FileInfoSubstreamHeader { @@ -246,7 +307,7 @@ // it is computed by summing `ModFileCounts`. // const FileInfoSubstreamHeader *FH; - codeview::StreamReader FISR(FileInfoSubstream); + StreamReader FISR(FileInfoSubstream); if (auto EC = FISR.readObject(FH)) return EC; @@ -256,9 +317,9 @@ return make_error(raw_error_code::corrupt_file, "FileInfo substream count doesn't match DBI."); - codeview::FixedStreamArray ModIndexArray; - codeview::FixedStreamArray ModFileCountArray; - codeview::FixedStreamArray FileNameOffsets; + FixedStreamArray ModIndexArray; + FixedStreamArray ModFileCountArray; + FixedStreamArray 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, @@ -286,10 +347,10 @@ if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles)) return EC; - codeview::StreamRef NamesBufferRef; + StreamRef NamesBufferRef; if (auto EC = FISR.readStreamRef(NamesBufferRef)) return EC; - codeview::StreamReader Names(NamesBufferRef); + 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 Index: lib/DebugInfo/PDB/Raw/ModStream.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/ModStream.cpp +++ lib/DebugInfo/PDB/Raw/ModStream.cpp @@ -45,6 +45,10 @@ return EC; if (auto EC = Reader.readStreamRef(C13LinesSubstream, C13Size)) return EC; + ArrayRef LineBytes; + codeview::StreamReader LinesReader(C13LinesSubstream); + if (auto EC = LinesReader.readBytes(LineBytes, C13LinesSubstream.getLength())) + return EC; uint32_t GlobalRefsSize; if (auto EC = Reader.readInteger(GlobalRefsSize)) Index: test/DebugInfo/PDB/pdbdump-headers.test =================================================================== --- test/DebugInfo/PDB/pdbdump-headers.test +++ test/DebugInfo/PDB/pdbdump-headers.test @@ -1021,6 +1021,157 @@ ; ALL: } ; ALL: ] ; ALL: } +; ALL: Section Contributions [ +; ALL: Contribution { +; ALL: ISect: 1 +; ALL: Off: 0 +; ALL: Size: 10 +; ALL: Characteristics [ (0x60000020) +; ALL: IMAGE_SCN_CNT_CODE (0x20) +; ALL: IMAGE_SCN_MEM_EXECUTE (0x20000000) +; ALL: IMAGE_SCN_MEM_READ (0x40000000) +; ALL: ] +; ALL: Module { +; ALL: Index: 1 +; ALL: Name: * Linker * +; ALL: } +; ALL: Data CRC: 0 +; ALL: Reloc CRC: 0 +; ALL: } +; ALL: Contribution { +; ALL: ISect: 1 +; ALL: Off: 16 +; ALL: Size: 10 +; ALL: Characteristics [ (0x60500020) +; ALL: IMAGE_SCN_ALIGN_16BYTES (0x500000) +; ALL: IMAGE_SCN_CNT_CODE (0x20) +; ALL: IMAGE_SCN_MEM_EXECUTE (0x20000000) +; ALL: IMAGE_SCN_MEM_READ (0x40000000) +; ALL: ] +; ALL: Module { +; ALL: Index: 0 +; ALL: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj +; ALL: } +; ALL: Data CRC: 3617027124 +; ALL: Reloc CRC: 0 +; ALL: } +; ALL: Contribution { +; ALL: ISect: 2 +; ALL: Off: 0 +; ALL: Size: 56 +; ALL: Characteristics [ (0x40000040) +; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) +; ALL: IMAGE_SCN_MEM_READ (0x40000000) +; ALL: ] +; ALL: Module { +; ALL: Index: 1 +; ALL: Name: * Linker * +; ALL: } +; ALL: Data CRC: 0 +; ALL: Reloc CRC: 0 +; ALL: } +; ALL: Contribution { +; ALL: ISect: 2 +; ALL: Off: 324 +; ALL: Size: 72 +; ALL: Characteristics [ (0x40300040) +; ALL: IMAGE_SCN_ALIGN_4BYTES (0x300000) +; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) +; ALL: IMAGE_SCN_MEM_READ (0x40000000) +; ALL: ] +; ALL: Module { +; ALL: Index: 1 +; ALL: Name: * Linker * +; ALL: } +; ALL: Data CRC: 0 +; ALL: Reloc CRC: 0 +; ALL: } +; ALL: Contribution { +; ALL: ISect: 2 +; ALL: Off: 396 +; ALL: Size: 20 +; ALL: Characteristics [ (0x40300040) +; ALL: IMAGE_SCN_ALIGN_4BYTES (0x300000) +; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) +; ALL: IMAGE_SCN_MEM_READ (0x40000000) +; ALL: ] +; ALL: Module { +; ALL: Index: 1 +; ALL: Name: * Linker * +; ALL: } +; ALL: Data CRC: 0 +; ALL: Reloc CRC: 0 +; ALL: } +; ALL: Contribution { +; ALL: ISect: 3 +; ALL: Off: 0 +; ALL: Size: 4 +; ALL: Characteristics [ (0xC0300080) +; ALL: IMAGE_SCN_ALIGN_4BYTES (0x300000) +; ALL: IMAGE_SCN_CNT_UNINITIALIZED_DATA (0x80) +; ALL: IMAGE_SCN_MEM_READ (0x40000000) +; ALL: IMAGE_SCN_MEM_WRITE (0x80000000) +; ALL: ] +; ALL: Module { +; ALL: Index: 0 +; ALL: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj +; ALL: } +; ALL: Data CRC: 0 +; ALL: Reloc CRC: 0 +; ALL: } +; ALL: ] +; ALL: Section Map [ +; ALL: Entry { +; ALL: Flags: 269 +; ALL: Ovl: 0 +; ALL: Group: 0 +; ALL: Frame: 1 +; ALL: SecName: 65535 +; ALL: ClassName: 65535 +; ALL: Offset: 0 +; ALL: SecByteLength: 4122 +; ALL: } +; ALL: Entry { +; ALL: Flags: 265 +; ALL: Ovl: 0 +; ALL: Group: 0 +; ALL: Frame: 2 +; ALL: SecName: 65535 +; ALL: ClassName: 65535 +; ALL: Offset: 0 +; ALL: SecByteLength: 690 +; ALL: } +; ALL: Entry { +; ALL: Flags: 267 +; ALL: Ovl: 0 +; ALL: Group: 0 +; ALL: Frame: 3 +; ALL: SecName: 65535 +; ALL: ClassName: 65535 +; ALL: Offset: 0 +; ALL: SecByteLength: 4 +; ALL: } +; ALL: Entry { +; ALL: Flags: 265 +; ALL: Ovl: 0 +; ALL: Group: 0 +; ALL: Frame: 4 +; ALL: SecName: 65535 +; ALL: ClassName: 65535 +; ALL: Offset: 0 +; ALL: SecByteLength: 8 +; ALL: } +; ALL: Entry { +; ALL: Flags: 520 +; ALL: Ovl: 0 +; ALL: Group: 0 +; ALL: Frame: 0 +; ALL: SecName: 65535 +; ALL: ClassName: 65535 +; ALL: Offset: 0 +; ALL: SecByteLength: 4294967295 +; ALL: } +; ALL: ] ; ALL: Publics Stream { ; ALL: Stream number: 7 ; ALL: SymHash: 556 Index: tools/llvm-pdbdump/llvm-pdbdump.cpp =================================================================== --- tools/llvm-pdbdump/llvm-pdbdump.cpp +++ tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -40,6 +40,7 @@ #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" #include "llvm/DebugInfo/PDB/PDBSymbolThunk.h" #include "llvm/DebugInfo/PDB/Raw/DbiStream.h" +#include "llvm/DebugInfo/PDB/Raw/ISectionContrVisitor.h" #include "llvm/DebugInfo/PDB/Raw/InfoStream.h" #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Raw/ModInfo.h" @@ -50,6 +51,8 @@ #include "llvm/DebugInfo/PDB/Raw/RawError.h" #include "llvm/DebugInfo/PDB/Raw/RawSession.h" #include "llvm/DebugInfo/PDB/Raw/TpiStream.h" +#include "llvm/Support/COFF.h" +#include "llvm/Support/COM.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/FileSystem.h" @@ -62,16 +65,53 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/raw_ostream.h" -#if defined(HAVE_DIA_SDK) -#ifndef NOMINMAX -#define NOMINMAX -#endif -#include -#endif - using namespace llvm; using namespace llvm::pdb; +namespace { +#define LLVM_PDBDUMP_ENUM_ENT(ns, enum) \ + { #enum, ns::enum } + +static const EnumEntry + ImageSectionCharacteristics[] = { + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NOLOAD), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NO_PAD), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_CNT_CODE), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_CNT_INITIALIZED_DATA), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_CNT_UNINITIALIZED_DATA), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_LNK_OTHER), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_LNK_INFO), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_LNK_REMOVE), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_LNK_COMDAT), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_GPREL), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_MEM_PURGEABLE), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_MEM_16BIT), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_MEM_LOCKED), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_MEM_PRELOAD), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1BYTES), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2BYTES), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4BYTES), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8BYTES), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_16BYTES), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_32BYTES), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_64BYTES), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_128BYTES), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_256BYTES), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_512BYTES), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1024BYTES), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2048BYTES), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4096BYTES), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8192BYTES), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_LNK_NRELOC_OVFL), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_MEM_DISCARDABLE), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_CACHED), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_PAGED), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_MEM_SHARED), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_MEM_EXECUTE), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_MEM_READ), + LLVM_PDBDUMP_ENUM_ENT(COFF, IMAGE_SCN_MEM_WRITE)}; +} + namespace opts { enum class PDB_DumpType { ByType, ByObjFile, Both }; @@ -143,6 +183,11 @@ cl::cat(NativeOptions)); cl::opt DumpPublics("raw-publics", cl::desc("dump Publics stream data"), cl::cat(NativeOptions)); +cl::opt DumpSectionContrs("raw-section-contrs", + cl::desc("dump section contributions"), + cl::cat(NativeOptions)); +cl::opt DumpSectionMap("raw-section-map", cl::desc("dump section map"), + cl::cat(NativeOptions)); cl::opt DumpSymRecordBytes("raw-sym-record-bytes", cl::desc("dump CodeView symbol record raw bytes"), @@ -505,6 +550,77 @@ return Error::success(); } +static Error dumpSectionContrs(ScopedPrinter &P, PDBFile &File) { + if (!opts::DumpSectionContrs) + return Error::success(); + + auto DbiS = File.getPDBDbiStream(); + if (auto EC = DbiS.takeError()) + return EC; + DbiStream &DS = DbiS.get(); + ListScope L(P, "Section Contributions"); + class Visitor : public ISectionContrVisitor { + public: + Visitor(ScopedPrinter &P, DbiStream &DS) : P(P), DS(DS) {} + void visit(const SectionContr &SC) override { + DictScope D(P, "Contribution"); + P.printNumber("ISect", SC.ISect); + P.printNumber("Off", SC.Off); + P.printNumber("Size", SC.Size); + P.printFlags("Characteristics", SC.Characteristics, + makeArrayRef(ImageSectionCharacteristics), + COFF::SectionCharacteristics(0x00F00000)); + { + DictScope DD(P, "Module"); + P.printNumber("Index", SC.Imod); + auto M = DS.modules(); + if (M.size() > SC.Imod) { + P.printString("Name", M[SC.Imod].Info.getModuleName()); + } + } + P.printNumber("Data CRC", SC.DataCrc); + P.printNumber("Reloc CRC", SC.RelocCrc); + P.flush(); + } + void visit(const SectionContr2 &SC) override { + visit(static_cast(SC)); + P.printNumber("ISect Coff", SC.ISectCoff); + P.flush(); + } + + private: + ScopedPrinter &P; + DbiStream &DS; + }; + Visitor V(P, DS); + DS.visitSectionContributions(V); + return Error::success(); +} + +static Error dumpSectionMap(ScopedPrinter &P, PDBFile &File) { + if (!opts::DumpSectionMap) + return Error::success(); + + auto DbiS = File.getPDBDbiStream(); + if (auto EC = DbiS.takeError()) + return EC; + DbiStream &DS = DbiS.get(); + ListScope L(P, "Section Map"); + for (auto &M : DS.getSectionMap()) { + DictScope D(P, "Entry"); + P.printNumber("Flags", M.Flags); + P.printNumber("Ovl", M.Ovl); + P.printNumber("Group", M.Group); + P.printNumber("Frame", M.Frame); + P.printNumber("SecName", M.SecName); + P.printNumber("ClassName", M.ClassName); + P.printNumber("Offset", M.Offset); + P.printNumber("SecByteLength", M.SecByteLength); + P.flush(); + } + return Error::success(); +} + static Error dumpTpiStream(ScopedPrinter &P, PDBFile &File, codeview::CVTypeDumper &TD, uint32_t StreamIdx) { assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI); @@ -648,8 +764,15 @@ if (auto EC = dumpDbiStream(P, File, TD)) return EC; + if (auto EC = dumpSectionContrs(P, File)) + return EC; + + if (auto EC = dumpSectionMap(P, File)) + return EC; + if (auto EC = dumpPublicsStream(P, File, TD)) return EC; + return Error::success(); } @@ -682,6 +805,10 @@ return true; if (opts::DumpIpiRecordBytes) return true; + if (opts::DumpSectionContrs) + return true; + if (opts::DumpSectionMap) + return true; return false; } @@ -846,6 +973,8 @@ opts::DumpStreamBlocks = true; opts::DumpTpiRecords = true; opts::DumpIpiRecords = true; + opts::DumpSectionMap = true; + opts::DumpSectionContrs = true; } // When adding filters for excluded compilands and types, we need to remember @@ -864,16 +993,11 @@ opts::ExcludeCompilands.push_back("d:\\\\th.obj.x86fre\\\\minkernel"); } -#if defined(HAVE_DIA_SDK) - CoInitializeEx(nullptr, COINIT_MULTITHREADED); -#endif + llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded); std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(), dumpInput); -#if defined(HAVE_DIA_SDK) - CoUninitialize(); -#endif outs().flush(); return 0; }