diff --git a/include/llvm/DebugInfo/PDB/Native/DbiStream.h b/include/llvm/DebugInfo/PDB/Native/DbiStream.h index 760d19ac3f8..280615bdb50 100644 --- a/include/llvm/DebugInfo/PDB/Native/DbiStream.h +++ b/include/llvm/DebugInfo/PDB/Native/DbiStream.h @@ -38,9 +38,9 @@ class DbiStream { friend class DbiStreamBuilder; public: - DbiStream(PDBFile &File, std::unique_ptr Stream); + explicit DbiStream(std::unique_ptr Stream); ~DbiStream(); - Error reload(); + Error reload(PDBFile *Pdb); PdbRaw_DbiVer getDbiVersion() const; uint32_t getAge() const; @@ -89,12 +89,11 @@ public: private: Error initializeSectionContributionData(); - Error initializeSectionHeadersData(); + Error initializeSectionHeadersData(PDBFile *Pdb); Error initializeSectionMapData(); - Error initializeFpoRecords(); + Error initializeFpoRecords(PDBFile *Pdb); - PDBFile &Pdb; - std::unique_ptr Stream; + std::unique_ptr Stream; PDBStringTable ECNames; diff --git a/include/llvm/DebugInfo/PDB/Native/InfoStream.h b/include/llvm/DebugInfo/PDB/Native/InfoStream.h index f49e7afc07e..8c52b042f28 100644 --- a/include/llvm/DebugInfo/PDB/Native/InfoStream.h +++ b/include/llvm/DebugInfo/PDB/Native/InfoStream.h @@ -30,7 +30,7 @@ class InfoStream { friend class InfoStreamBuilder; public: - InfoStream(std::unique_ptr Stream); + InfoStream(std::unique_ptr Stream); Error reload(); @@ -56,7 +56,7 @@ public: StringMap named_streams() const; private: - std::unique_ptr Stream; + std::unique_ptr Stream; const InfoStreamHeader *Header; diff --git a/include/llvm/DebugInfo/PDB/Native/RawTypes.h b/include/llvm/DebugInfo/PDB/Native/RawTypes.h index 5cc8821f729..04ea10de06b 100644 --- a/include/llvm/DebugInfo/PDB/Native/RawTypes.h +++ b/include/llvm/DebugInfo/PDB/Native/RawTypes.h @@ -112,6 +112,8 @@ struct DbiBuildNo { static const uint16_t BuildMajorMask = 0x7F00; static const uint16_t BuildMajorShift = 8; + + static const uint16_t NewVersionFormatMask = 0x8000; }; /// The fixed size header that appears at the beginning of the DBI Stream. diff --git a/lib/DebugInfo/PDB/Native/DbiStream.cpp b/lib/DebugInfo/PDB/Native/DbiStream.cpp index 04e6664c68d..edaa783398c 100644 --- a/lib/DebugInfo/PDB/Native/DbiStream.cpp +++ b/lib/DebugInfo/PDB/Native/DbiStream.cpp @@ -45,12 +45,12 @@ static Error loadSectionContribs(FixedStreamArray &Output, return Error::success(); } -DbiStream::DbiStream(PDBFile &File, std::unique_ptr Stream) - : Pdb(File), Stream(std::move(Stream)), Header(nullptr) {} +DbiStream::DbiStream(std::unique_ptr Stream) + : Stream(std::move(Stream)), Header(nullptr) {} DbiStream::~DbiStream() = default; -Error DbiStream::reload() { +Error DbiStream::reload(PDBFile *Pdb) { BinaryStreamReader Reader(*Stream); if (Stream->getLength() < sizeof(DbiStreamHeader)) @@ -123,11 +123,11 @@ Error DbiStream::reload() { if (auto EC = initializeSectionContributionData()) return EC; - if (auto EC = initializeSectionHeadersData()) + if (auto EC = initializeSectionHeadersData(Pdb)) return EC; if (auto EC = initializeSectionMapData()) return EC; - if (auto EC = initializeFpoRecords()) + if (auto EC = initializeFpoRecords(Pdb)) return EC; if (Reader.bytesRemaining() > 0) @@ -246,7 +246,10 @@ Error DbiStream::initializeSectionContributionData() { } // Initializes this->SectionHeaders. -Error DbiStream::initializeSectionHeadersData() { +Error DbiStream::initializeSectionHeadersData(PDBFile *Pdb) { + if (!Pdb) + return Error::success(); + if (DbgStreams.size() == 0) return Error::success(); @@ -254,11 +257,11 @@ Error DbiStream::initializeSectionHeadersData() { if (StreamNum == kInvalidStreamIndex) return Error::success(); - if (StreamNum >= Pdb.getNumStreams()) + if (StreamNum >= Pdb->getNumStreams()) return make_error(raw_error_code::no_stream); auto SHS = MappedBlockStream::createIndexedStream( - Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator()); + Pdb->getMsfLayout(), Pdb->getMsfBuffer(), StreamNum, Pdb->getAllocator()); size_t StreamLen = SHS->getLength(); if (StreamLen % sizeof(object::coff_section)) @@ -276,7 +279,10 @@ Error DbiStream::initializeSectionHeadersData() { } // Initializes this->Fpos. -Error DbiStream::initializeFpoRecords() { +Error DbiStream::initializeFpoRecords(PDBFile *Pdb) { + if (!Pdb) + return Error::success(); + if (DbgStreams.size() == 0) return Error::success(); @@ -286,11 +292,11 @@ Error DbiStream::initializeFpoRecords() { if (StreamNum == kInvalidStreamIndex) return Error::success(); - if (StreamNum >= Pdb.getNumStreams()) + if (StreamNum >= Pdb->getNumStreams()) return make_error(raw_error_code::no_stream); auto FS = MappedBlockStream::createIndexedStream( - Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator()); + Pdb->getMsfLayout(), Pdb->getMsfBuffer(), StreamNum, Pdb->getAllocator()); size_t StreamLen = FS->getLength(); if (StreamLen % sizeof(object::FpoData)) diff --git a/lib/DebugInfo/PDB/Native/InfoStream.cpp b/lib/DebugInfo/PDB/Native/InfoStream.cpp index 0bb543e8c64..973a520ffca 100644 --- a/lib/DebugInfo/PDB/Native/InfoStream.cpp +++ b/lib/DebugInfo/PDB/Native/InfoStream.cpp @@ -20,7 +20,7 @@ using namespace llvm::codeview; using namespace llvm::msf; using namespace llvm::pdb; -InfoStream::InfoStream(std::unique_ptr Stream) +InfoStream::InfoStream(std::unique_ptr Stream) : Stream(std::move(Stream)), Header(nullptr) {} Error InfoStream::reload() { diff --git a/lib/DebugInfo/PDB/Native/PDBFile.cpp b/lib/DebugInfo/PDB/Native/PDBFile.cpp index 6b1d28a3731..78b11937f05 100644 --- a/lib/DebugInfo/PDB/Native/PDBFile.cpp +++ b/lib/DebugInfo/PDB/Native/PDBFile.cpp @@ -289,8 +289,8 @@ Expected PDBFile::getPDBDbiStream() { auto DbiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamDBI); if (!DbiS) return DbiS.takeError(); - auto TempDbi = llvm::make_unique(*this, std::move(*DbiS)); - if (auto EC = TempDbi->reload()) + auto TempDbi = llvm::make_unique(std::move(*DbiS)); + if (auto EC = TempDbi->reload(this)) return std::move(EC); Dbi = std::move(TempDbi); } diff --git a/tools/llvm-pdbutil/ExplainOutputStyle.cpp b/tools/llvm-pdbutil/ExplainOutputStyle.cpp index a53263a1fde..d16bfa480e1 100644 --- a/tools/llvm-pdbutil/ExplainOutputStyle.cpp +++ b/tools/llvm-pdbutil/ExplainOutputStyle.cpp @@ -10,6 +10,7 @@ #include "ExplainOutputStyle.h" #include "FormatUtil.h" +#include "InputFile.h" #include "StreamUtil.h" #include "llvm-pdbutil.h" @@ -19,6 +20,7 @@ #include "llvm/DebugInfo/PDB/Native/InfoStream.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryByteStream.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/Error.h" @@ -27,114 +29,157 @@ using namespace llvm::codeview; using namespace llvm::msf; using namespace llvm::pdb; -ExplainOutputStyle::ExplainOutputStyle(PDBFile &File, uint64_t FileOffset) - : File(File), FileOffset(FileOffset), - BlockIndex(FileOffset / File.getBlockSize()), - OffsetInBlock(FileOffset - BlockIndex * File.getBlockSize()), - P(2, false, outs()) {} +ExplainOutputStyle::ExplainOutputStyle(InputFile &File, uint64_t FileOffset) + : File(File), FileOffset(FileOffset), P(2, false, outs()) {} Error ExplainOutputStyle::dump() { P.formatLine("Explaining file offset {0} of file '{1}'.", FileOffset, File.getFilePath()); - bool IsAllocated = explainBlockStatus(); + if (File.isPdb()) + return explainPdbFile(); + + return explainBinaryFile(); +} + +Error ExplainOutputStyle::explainPdbFile() { + bool IsAllocated = explainPdbBlockStatus(); if (!IsAllocated) return Error::success(); AutoIndent Indent(P); - if (isSuperBlock()) - explainSuperBlockOffset(); - else if (isFpmBlock()) - explainFpmBlockOffset(); - else if (isBlockMapBlock()) - explainBlockMapOffset(); - else if (isStreamDirectoryBlock()) - explainStreamDirectoryOffset(); - else if (auto Index = getBlockStreamIndex()) - explainStreamOffset(*Index); + if (isPdbSuperBlock()) + explainPdbSuperBlockOffset(); + else if (isPdbFpmBlock()) + explainPdbFpmBlockOffset(); + else if (isPdbBlockMapBlock()) + explainPdbBlockMapOffset(); + else if (isPdbStreamDirectoryBlock()) + explainPdbStreamDirectoryOffset(); + else if (auto Index = getPdbBlockStreamIndex()) + explainPdbStreamOffset(*Index); else - explainUnknownBlock(); + explainPdbUnknownBlock(); return Error::success(); } -bool ExplainOutputStyle::isSuperBlock() const { return BlockIndex == 0; } - -bool ExplainOutputStyle::isFpm1() const { - return ((BlockIndex - 1) % File.getBlockSize() == 0); -} -bool ExplainOutputStyle::isFpm2() const { - return ((BlockIndex - 2) % File.getBlockSize() == 0); +Error ExplainOutputStyle::explainBinaryFile() { + std::unique_ptr Stream = + llvm::make_unique(File.unknown().getBuffer(), + llvm::support::little); + switch (opts::explain::InputType) { + case opts::explain::InputFileType::DBIStream: { + DbiStream Dbi(std::move(Stream)); + if (auto EC = Dbi.reload(nullptr)) + return EC; + explainStreamOffset(Dbi, FileOffset); + break; + } + case opts::explain::InputFileType::PDBStream: { + InfoStream Info(std::move(Stream)); + if (auto EC = Info.reload()) + return EC; + explainStreamOffset(Info, FileOffset); + break; + } + default: + llvm_unreachable("Invalid input file type!"); + } + return Error::success(); } -bool ExplainOutputStyle::isFpmBlock() const { return isFpm1() || isFpm2(); } - -bool ExplainOutputStyle::isBlockMapBlock() const { - return BlockIndex == File.getBlockMapIndex(); +uint32_t ExplainOutputStyle::pdbBlockIndex() const { + return FileOffset / File.pdb().getBlockSize(); } -bool ExplainOutputStyle::isStreamDirectoryBlock() const { - const auto &Layout = File.getMsfLayout(); - return llvm::is_contained(Layout.DirectoryBlocks, BlockIndex); +uint32_t ExplainOutputStyle::pdbBlockOffset() const { + uint64_t BlockStart = pdbBlockIndex() * File.pdb().getBlockSize(); + assert(FileOffset >= BlockStart); + return FileOffset - BlockStart; } -Optional ExplainOutputStyle::getBlockStreamIndex() const { - const auto &Layout = File.getMsfLayout(); +bool ExplainOutputStyle::isPdbSuperBlock() const { + return pdbBlockIndex() == 0; +} + +bool ExplainOutputStyle::isPdbFpm1() const { + return ((pdbBlockIndex() - 1) % File.pdb().getBlockSize() == 0); +} +bool ExplainOutputStyle::isPdbFpm2() const { + return ((pdbBlockIndex() - 2) % File.pdb().getBlockSize() == 0); +} + +bool ExplainOutputStyle::isPdbFpmBlock() const { + return isPdbFpm1() || isPdbFpm2(); +} + +bool ExplainOutputStyle::isPdbBlockMapBlock() const { + return pdbBlockIndex() == File.pdb().getBlockMapIndex(); +} + +bool ExplainOutputStyle::isPdbStreamDirectoryBlock() const { + const auto &Layout = File.pdb().getMsfLayout(); + return llvm::is_contained(Layout.DirectoryBlocks, pdbBlockIndex()); +} + +Optional ExplainOutputStyle::getPdbBlockStreamIndex() const { + const auto &Layout = File.pdb().getMsfLayout(); for (const auto &Entry : enumerate(Layout.StreamMap)) { - if (!llvm::is_contained(Entry.value(), BlockIndex)) + if (!llvm::is_contained(Entry.value(), pdbBlockIndex())) continue; return Entry.index(); } return None; } -bool ExplainOutputStyle::explainBlockStatus() { - if (FileOffset >= File.getFileSize()) { +bool ExplainOutputStyle::explainPdbBlockStatus() { + if (FileOffset >= File.pdb().getFileSize()) { P.formatLine("Address {0} is not in the file (file size = {1}).", - FileOffset, File.getFileSize()); + FileOffset, File.pdb().getFileSize()); return false; } - P.formatLine("Block:Offset = {2:X-}:{1:X-4}.", FileOffset, OffsetInBlock, - BlockIndex); + P.formatLine("Block:Offset = {2:X-}:{1:X-4}.", FileOffset, pdbBlockOffset(), + pdbBlockIndex()); - bool IsFree = File.getMsfLayout().FreePageMap[BlockIndex]; - P.formatLine("Address is in block {0} ({1}allocated).", BlockIndex, + bool IsFree = File.pdb().getMsfLayout().FreePageMap[pdbBlockIndex()]; + P.formatLine("Address is in block {0} ({1}allocated).", pdbBlockIndex(), IsFree ? "un" : ""); return !IsFree; } #define endof(Class, Field) (offsetof(Class, Field) + sizeof(Class::Field)) -void ExplainOutputStyle::explainSuperBlockOffset() { +void ExplainOutputStyle::explainPdbSuperBlockOffset() { P.formatLine("This corresponds to offset {0} of the MSF super block, ", - OffsetInBlock); - if (OffsetInBlock < endof(SuperBlock, MagicBytes)) + pdbBlockOffset()); + if (pdbBlockOffset() < endof(SuperBlock, MagicBytes)) P.printLine("which is part of the MSF file magic."); - else if (OffsetInBlock < endof(SuperBlock, BlockSize)) { + else if (pdbBlockOffset() < endof(SuperBlock, BlockSize)) { P.printLine("which contains the block size of the file."); P.formatLine("The current value is {0}.", - uint32_t(File.getMsfLayout().SB->BlockSize)); - } else if (OffsetInBlock < endof(SuperBlock, FreeBlockMapBlock)) { + uint32_t(File.pdb().getMsfLayout().SB->BlockSize)); + } else if (pdbBlockOffset() < endof(SuperBlock, FreeBlockMapBlock)) { P.printLine("which contains the index of the FPM block (e.g. 1 or 2)."); P.formatLine("The current value is {0}.", - uint32_t(File.getMsfLayout().SB->FreeBlockMapBlock)); - } else if (OffsetInBlock < endof(SuperBlock, NumBlocks)) { + uint32_t(File.pdb().getMsfLayout().SB->FreeBlockMapBlock)); + } else if (pdbBlockOffset() < endof(SuperBlock, NumBlocks)) { P.printLine("which contains the number of blocks in the file."); P.formatLine("The current value is {0}.", - uint32_t(File.getMsfLayout().SB->NumBlocks)); - } else if (OffsetInBlock < endof(SuperBlock, NumDirectoryBytes)) { + uint32_t(File.pdb().getMsfLayout().SB->NumBlocks)); + } else if (pdbBlockOffset() < endof(SuperBlock, NumDirectoryBytes)) { P.printLine("which contains the number of bytes in the stream directory."); P.formatLine("The current value is {0}.", - uint32_t(File.getMsfLayout().SB->NumDirectoryBytes)); - } else if (OffsetInBlock < endof(SuperBlock, Unknown1)) { + uint32_t(File.pdb().getMsfLayout().SB->NumDirectoryBytes)); + } else if (pdbBlockOffset() < endof(SuperBlock, Unknown1)) { P.printLine("whose purpose is unknown."); P.formatLine("The current value is {0}.", - uint32_t(File.getMsfLayout().SB->Unknown1)); - } else if (OffsetInBlock < endof(SuperBlock, BlockMapAddr)) { + uint32_t(File.pdb().getMsfLayout().SB->Unknown1)); + } else if (pdbBlockOffset() < endof(SuperBlock, BlockMapAddr)) { P.printLine("which contains the file offset of the block map."); P.formatLine("The current value is {0}.", - uint32_t(File.getMsfLayout().SB->BlockMapAddr)); + uint32_t(File.pdb().getMsfLayout().SB->BlockMapAddr)); } else { - assert(OffsetInBlock > sizeof(SuperBlock)); + assert(pdbBlockOffset() > sizeof(SuperBlock)); P.printLine( "which is outside the range of valid data for the super block."); } @@ -150,21 +195,21 @@ static std::string toBinaryString(uint8_t Byte) { return std::string(Result); } -void ExplainOutputStyle::explainFpmBlockOffset() { - const MSFLayout &Layout = File.getMsfLayout(); +void ExplainOutputStyle::explainPdbFpmBlockOffset() { + const MSFLayout &Layout = File.pdb().getMsfLayout(); uint32_t MainFpm = Layout.mainFpmBlock(); uint32_t AltFpm = Layout.alternateFpmBlock(); - assert(isFpmBlock()); - uint32_t Fpm = isFpm1() ? 1 : 2; - uint32_t FpmChunk = BlockIndex / File.getBlockSize(); + assert(isPdbFpmBlock()); + uint32_t Fpm = isPdbFpm1() ? 1 : 2; + uint32_t FpmChunk = pdbBlockIndex() / File.pdb().getBlockSize(); assert((Fpm == MainFpm) || (Fpm == AltFpm)); (void)AltFpm; bool IsMain = (Fpm == MainFpm); P.formatLine("Address is in FPM{0} ({1} FPM)", Fpm, IsMain ? "Main" : "Alt"); uint32_t DescribedBlockStart = - 8 * (FpmChunk * File.getBlockSize() + OffsetInBlock); - if (DescribedBlockStart > File.getBlockCount()) { + 8 * (FpmChunk * File.pdb().getBlockSize() + pdbBlockOffset()); + if (DescribedBlockStart > File.pdb().getBlockCount()) { P.printLine("Address is in extraneous FPM space."); return; } @@ -172,13 +217,13 @@ void ExplainOutputStyle::explainFpmBlockOffset() { P.formatLine("Address describes the allocation status of blocks [{0},{1})", DescribedBlockStart, DescribedBlockStart + 8); ArrayRef Bytes; - cantFail(File.getMsfBuffer().readBytes(FileOffset, 1, Bytes)); + cantFail(File.pdb().getMsfBuffer().readBytes(FileOffset, 1, Bytes)); P.formatLine("Status = {0} (Note: 0 = allocated, 1 = free)", toBinaryString(Bytes[0])); } -void ExplainOutputStyle::explainBlockMapOffset() { - uint64_t BlockMapOffset = File.getBlockMapOffset(); +void ExplainOutputStyle::explainPdbBlockMapOffset() { + uint64_t BlockMapOffset = File.pdb().getBlockMapOffset(); uint32_t OffsetInBlock = FileOffset - BlockMapOffset; P.formatLine("Address is at offset {0} of the directory block list", OffsetInBlock); @@ -195,25 +240,29 @@ static uint32_t getOffsetInStream(ArrayRef StreamBlocks, return StreamBlockIndex * BlockSize + OffsetInBlock; } -void ExplainOutputStyle::explainStreamOffset(uint32_t Stream) { +void ExplainOutputStyle::explainPdbStreamOffset(uint32_t Stream) { SmallVector Streams; - discoverStreamPurposes(File, Streams); + discoverStreamPurposes(File.pdb(), Streams); assert(Stream <= Streams.size()); const StreamInfo &S = Streams[Stream]; - const auto &Layout = File.getStreamLayout(Stream); + const auto &Layout = File.pdb().getStreamLayout(Stream); uint32_t StreamOff = - getOffsetInStream(Layout.Blocks, FileOffset, File.getBlockSize()); + getOffsetInStream(Layout.Blocks, FileOffset, File.pdb().getBlockSize()); P.formatLine("Address is at offset {0}/{1} of Stream {2} ({3}){4}.", StreamOff, Layout.Length, Stream, S.getLongName(), (StreamOff > Layout.Length) ? " in unused space" : ""); switch (S.getPurpose()) { - case StreamPurpose::DBI: - explainDbiStream(Stream, StreamOff); + case StreamPurpose::DBI: { + DbiStream &Dbi = cantFail(File.pdb().getPDBDbiStream()); + explainStreamOffset(Dbi, StreamOff); break; - case StreamPurpose::PDB: - explainPdbStream(Stream, StreamOff); + } + case StreamPurpose::PDB: { + InfoStream &Info = cantFail(File.pdb().getPDBInfoStream()); + explainStreamOffset(Info, StreamOff); break; + } case StreamPurpose::IPI: case StreamPurpose::TPI: case StreamPurpose::ModuleStream: @@ -223,11 +272,11 @@ void ExplainOutputStyle::explainStreamOffset(uint32_t Stream) { } } -void ExplainOutputStyle::explainStreamDirectoryOffset() { - auto DirectoryBlocks = File.getDirectoryBlockArray(); - const auto &Layout = File.getMsfLayout(); +void ExplainOutputStyle::explainPdbStreamDirectoryOffset() { + auto DirectoryBlocks = File.pdb().getDirectoryBlockArray(); + const auto &Layout = File.pdb().getMsfLayout(); uint32_t StreamOff = - getOffsetInStream(DirectoryBlocks, FileOffset, File.getBlockSize()); + getOffsetInStream(DirectoryBlocks, FileOffset, File.pdb().getBlockSize()); P.formatLine("Address is at offset {0}/{1} of Stream Directory{2}.", StreamOff, uint32_t(Layout.SB->NumDirectoryBytes), uint32_t(StreamOff > Layout.SB->NumDirectoryBytes) @@ -235,7 +284,7 @@ void ExplainOutputStyle::explainStreamDirectoryOffset() { : ""); } -void ExplainOutputStyle::explainUnknownBlock() { +void ExplainOutputStyle::explainPdbUnknownBlock() { P.formatLine("Address has unknown purpose."); } @@ -352,10 +401,9 @@ static void explainSubstreamOffset(LinePrinter &P, uint32_t OffsetInStream, } } -void ExplainOutputStyle::explainDbiStream(uint32_t StreamIdx, - uint32_t OffsetInStream) { +void ExplainOutputStyle::explainStreamOffset(DbiStream &Dbi, + uint32_t OffsetInStream) { P.printLine("Within the DBI stream:"); - DbiStream &Dbi = cantFail(File.getPDBDbiStream()); AutoIndent Indent(P); const DbiStreamHeader *Header = Dbi.getHeader(); assert(Header != nullptr); @@ -401,10 +449,9 @@ static void explainPdbStreamHeaderOffset(LinePrinter &P, InfoStream &Info, printStructField(P, "the guid of the PDB", fmt_guid(Header->Guid.Guid)); } -void ExplainOutputStyle::explainPdbStream(uint32_t StreamIdx, - uint32_t OffsetInStream) { +void ExplainOutputStyle::explainStreamOffset(InfoStream &Info, + uint32_t OffsetInStream) { P.printLine("Within the PDB stream:"); - InfoStream &Info = cantFail(File.getPDBInfoStream()); AutoIndent Indent(P); struct SubstreamInfo { diff --git a/tools/llvm-pdbutil/ExplainOutputStyle.h b/tools/llvm-pdbutil/ExplainOutputStyle.h index 383007b84c5..9a497accb81 100644 --- a/tools/llvm-pdbutil/ExplainOutputStyle.h +++ b/tools/llvm-pdbutil/ExplainOutputStyle.h @@ -20,41 +20,46 @@ namespace llvm { namespace pdb { class DbiStream; -class PDBFile; +class InfoStream; +class InputFile; class ExplainOutputStyle : public OutputStyle { public: - ExplainOutputStyle(PDBFile &File, uint64_t FileOffset); + ExplainOutputStyle(InputFile &File, uint64_t FileOffset); Error dump() override; private: - bool explainBlockStatus(); + Error explainPdbFile(); + Error explainBinaryFile(); - bool isFpm1() const; - bool isFpm2() const; + bool explainPdbBlockStatus(); - bool isSuperBlock() const; - bool isFpmBlock() const; - bool isBlockMapBlock() const; - bool isStreamDirectoryBlock() const; - Optional getBlockStreamIndex() const; + bool isPdbFpm1() const; + bool isPdbFpm2() const; - void explainSuperBlockOffset(); - void explainFpmBlockOffset(); - void explainBlockMapOffset(); - void explainStreamDirectoryOffset(); - void explainStreamOffset(uint32_t Stream); - void explainUnknownBlock(); + bool isPdbSuperBlock() const; + bool isPdbFpmBlock() const; + bool isPdbBlockMapBlock() const; + bool isPdbStreamDirectoryBlock() const; + Optional getPdbBlockStreamIndex() const; - void explainDbiStream(uint32_t StreamIdx, uint32_t OffsetInStream); - void explainPdbStream(uint32_t StreamIdx, uint32_t OffsetInStream); + void explainPdbSuperBlockOffset(); + void explainPdbFpmBlockOffset(); + void explainPdbBlockMapOffset(); + void explainPdbStreamDirectoryOffset(); + void explainPdbStreamOffset(uint32_t Stream); + void explainPdbUnknownBlock(); - PDBFile &File; + void explainStreamOffset(DbiStream &Stream, uint32_t OffsetInStream); + void explainStreamOffset(InfoStream &Stream, uint32_t OffsetInStream); + + uint32_t pdbBlockIndex() const; + uint32_t pdbBlockOffset() const; + + InputFile &File; const uint64_t FileOffset; - const uint64_t BlockIndex; - const uint64_t OffsetInBlock; LinePrinter P; }; } // namespace pdb diff --git a/tools/llvm-pdbutil/InputFile.cpp b/tools/llvm-pdbutil/InputFile.cpp index 28747824d3f..8319fc550d6 100644 --- a/tools/llvm-pdbutil/InputFile.cpp +++ b/tools/llvm-pdbutil/InputFile.cpp @@ -242,7 +242,7 @@ void SymbolGroup::formatFromChecksumsOffset(LinePrinter &Printer, } } -Expected InputFile::open(StringRef Path) { +Expected InputFile::open(StringRef Path, bool AllowUnknownFile) { InputFile IF; if (!llvm::sys::fs::exists(Path)) return make_error(formatv("File {0} not found", Path), @@ -274,9 +274,19 @@ Expected InputFile::open(StringRef Path) { return std::move(IF); } - return make_error( - formatv("File {0} is not a supported file type", Path), - inconvertibleErrorCode()); + if (!AllowUnknownFile) + return make_error( + formatv("File {0} is not a supported file type", Path), + inconvertibleErrorCode()); + + auto Result = MemoryBuffer::getFile(Path, -1i64, false); + if (!Result) + return make_error( + formatv("File {0} could not be opened", Path), Result.getError()); + + IF.UnknownFile = std::move(*Result); + IF.PdbOrObj = IF.UnknownFile.get(); + return std::move(IF); } PDBFile &InputFile::pdb() { @@ -299,6 +309,25 @@ const object::COFFObjectFile &InputFile::obj() const { return *PdbOrObj.get(); } +MemoryBuffer &InputFile::unknown() { + assert(isUnknown()); + return *PdbOrObj.get(); +} + +const MemoryBuffer &InputFile::unknown() const { + assert(isUnknown()); + return *PdbOrObj.get(); +} + +StringRef InputFile::getFilePath() const { + if (isPdb()) + return pdb().getFilePath(); + if (isObj()) + return obj().getFileName(); + assert(isUnknown()); + return unknown().getBufferIdentifier(); +} + bool InputFile::hasTypes() const { if (isPdb()) return pdb().hasPDBTpiStream(); @@ -323,6 +352,8 @@ bool InputFile::isObj() const { return PdbOrObj.is(); } +bool InputFile::isUnknown() const { return PdbOrObj.is(); } + codeview::LazyRandomTypeCollection & InputFile::getOrCreateTypeCollection(TypeCollectionKind Kind) { if (Types && Kind == kTypes) diff --git a/tools/llvm-pdbutil/InputFile.h b/tools/llvm-pdbutil/InputFile.h index 8063439133c..552f3a3b212 100644 --- a/tools/llvm-pdbutil/InputFile.h +++ b/tools/llvm-pdbutil/InputFile.h @@ -43,7 +43,8 @@ class InputFile { std::unique_ptr PdbSession; object::OwningBinary CoffObject; - PointerUnion PdbOrObj; + std::unique_ptr UnknownFile; + PointerUnion3 PdbOrObj; using TypeCollectionPtr = std::unique_ptr; @@ -58,12 +59,17 @@ public: ~InputFile(); InputFile(InputFile &&Other) = default; - static Expected open(StringRef Path); + static Expected open(StringRef Path, + bool AllowUnknownFile = false); PDBFile &pdb(); const PDBFile &pdb() const; object::COFFObjectFile &obj(); const object::COFFObjectFile &obj() const; + MemoryBuffer &unknown(); + const MemoryBuffer &unknown() const; + + StringRef getFilePath() const; bool hasTypes() const; bool hasIds() const; @@ -77,6 +83,7 @@ public: bool isPdb() const; bool isObj() const; + bool isUnknown() const; }; class SymbolGroup { diff --git a/tools/llvm-pdbutil/llvm-pdbutil.cpp b/tools/llvm-pdbutil/llvm-pdbutil.cpp index a694d47bd01..616e135db50 100644 --- a/tools/llvm-pdbutil/llvm-pdbutil.cpp +++ b/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -621,6 +621,20 @@ cl::list InputFilename(cl::Positional, cl::list Offsets("offset", cl::desc("The file offset to explain"), cl::sub(ExplainSubcommand), cl::OneOrMore); + +cl::opt InputType( + "input-type", cl::desc("Specify how to interpret the input file"), + cl::init(InputFileType::PDBFile), cl::Optional, cl::sub(ExplainSubcommand), + cl::values(clEnumValN(InputFileType::PDBFile, "pdb-file", + "Treat input as a PDB file (default)"), + clEnumValN(InputFileType::PDBStream, "pdb-stream", + "Treat input as raw contents of PDB stream"), + clEnumValN(InputFileType::DBIStream, "dbi-stream", + "Treat input as raw contents of DBI stream"), + clEnumValN(InputFileType::Names, "names-stream", + "Treat input as raw contents of /names named stream"), + clEnumValN(InputFileType::ModuleStream, "mod-stream", + "Treat input as raw contents of a module stream"))); } // namespace explain namespace exportstream { @@ -772,7 +786,6 @@ static void pdb2Yaml(StringRef Path) { } static void dumpRaw(StringRef Path) { - InputFile IF = ExitOnErr(InputFile::open(Path)); auto O = llvm::make_unique(IF); @@ -1111,10 +1124,11 @@ static void mergePdbs() { static void explain() { std::unique_ptr Session; - PDBFile &File = loadPDB(opts::explain::InputFilename.front(), Session); + InputFile IF = + ExitOnErr(InputFile::open(opts::explain::InputFilename.front(), true)); for (uint64_t Off : opts::explain::Offsets) { - auto O = llvm::make_unique(File, Off); + auto O = llvm::make_unique(IF, Off); ExitOnErr(O->dump()); } diff --git a/tools/llvm-pdbutil/llvm-pdbutil.h b/tools/llvm-pdbutil/llvm-pdbutil.h index 82f4e52c1e4..811faf6a394 100644 --- a/tools/llvm-pdbutil/llvm-pdbutil.h +++ b/tools/llvm-pdbutil/llvm-pdbutil.h @@ -190,8 +190,11 @@ extern llvm::cl::opt DumpModuleSyms; } // namespace pdb2yaml namespace explain { +enum class InputFileType { PDBFile, PDBStream, DBIStream, Names, ModuleStream }; + extern llvm::cl::list InputFilename; extern llvm::cl::list Offsets; +extern llvm::cl::opt InputType; } // namespace explain namespace exportstream {