From 5a4ce7a9eae6823376363a065a63650d41e86152 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Fri, 29 Apr 2016 17:22:58 +0000 Subject: [PATCH] Refactor the PDB Stream reading interface. The motivation for this change is that PDB has the notion of streams and substreams. Substreams often consist of variable length structures that are convenient to be able to treat as guaranteed, contiguous byte arrays, whereas the streams they are contained in are not necessarily so, as a single stream could be spread across many discontiguous blocks. So, when processing data from a substream, we want to be able to assume that we have a contiguous byte array so that we can cast pointers to variable length arrays and such. This leads to the question of how to be able to read the same data structure from either a stream or a substream using the same interface, which is where this patch comes in. We separate out the stream's read state from the underlying representation, and introduce a `StreamReader` class. Then we change the name of `PDBStream` to `MappedBlockStream`, and introduce a second kind of stream called a `ByteStream` which is simply a sequence of contiguous bytes. Finally, we update all of the std::vectors in `PDBDbiStream` to use `ByteStream` instead as a proof of concept. llvm-svn: 268071 --- include/llvm/DebugInfo/PDB/Raw/ByteStream.h | 47 +++++++++++++++ .../DebugInfo/PDB/Raw/MappedBlockStream.h | 38 ++++++++++++ include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h | 20 ++++--- .../llvm/DebugInfo/PDB/Raw/PDBInfoStream.h | 4 +- include/llvm/DebugInfo/PDB/Raw/PDBNameMap.h | 4 +- include/llvm/DebugInfo/PDB/Raw/PDBStream.h | 46 -------------- .../llvm/DebugInfo/PDB/Raw/StreamInterface.h | 29 +++++++++ include/llvm/DebugInfo/PDB/Raw/StreamReader.h | 46 ++++++++++++++ lib/DebugInfo/PDB/CMakeLists.txt | 6 +- lib/DebugInfo/PDB/Raw/ByteStream.cpp | 60 +++++++++++++++++++ .../{PDBStream.cpp => MappedBlockStream.cpp} | 46 ++++---------- lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp | 52 ++++++++-------- lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp | 16 ++--- lib/DebugInfo/PDB/Raw/PDBNameMap.cpp | 5 +- lib/DebugInfo/PDB/Raw/StreamReader.cpp | 40 +++++++++++++ tools/llvm-pdbdump/llvm-pdbdump.cpp | 11 ++-- 16 files changed, 333 insertions(+), 137 deletions(-) create mode 100644 include/llvm/DebugInfo/PDB/Raw/ByteStream.h create mode 100644 include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h delete mode 100644 include/llvm/DebugInfo/PDB/Raw/PDBStream.h create mode 100644 include/llvm/DebugInfo/PDB/Raw/StreamInterface.h create mode 100644 include/llvm/DebugInfo/PDB/Raw/StreamReader.h create mode 100644 lib/DebugInfo/PDB/Raw/ByteStream.cpp rename lib/DebugInfo/PDB/Raw/{PDBStream.cpp => MappedBlockStream.cpp} (54%) create mode 100644 lib/DebugInfo/PDB/Raw/StreamReader.cpp diff --git a/include/llvm/DebugInfo/PDB/Raw/ByteStream.h b/include/llvm/DebugInfo/PDB/Raw/ByteStream.h new file mode 100644 index 00000000000..11b9366f73a --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/ByteStream.h @@ -0,0 +1,47 @@ +//===- ByteStream.h - Reads stream data from a byte sequence ----*- 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_BYTESTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_BYTESTREAM_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/PDB/Raw/StreamInterface.h" + +#include + +#include +#include + +namespace llvm { +class StreamReader; +class ByteStream : public StreamInterface { +public: + ByteStream(); + explicit ByteStream(MutableArrayRef Bytes); + explicit ByteStream(uint32_t Length); + ~ByteStream() override; + + void reset(); + void initialize(MutableArrayRef Bytes); + void initialize(uint32_t Length); + std::error_code initialize(StreamReader &Reader, uint32_t Length); + + std::error_code readBytes(uint32_t Offset, + MutableArrayRef Buffer) const override; + uint32_t getLength() const override; + + ArrayRef data() const { return Data; } + +private: + MutableArrayRef Data; + bool Owned; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h b/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h new file mode 100644 index 00000000000..74fae96ffdf --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h @@ -0,0 +1,38 @@ +//===- MappedBlockStream.h - Reads stream data from a PDBFile ---*- 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_MAPPEDBLOCKSTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_MAPPEDBLOCKSTREAM_H + +#include "llvm/DebugInfo/PDB/Raw/StreamInterface.h" + +#include + +#include +#include + +namespace llvm { +class PDBFile; + +class MappedBlockStream : public StreamInterface { +public: + MappedBlockStream(uint32_t StreamIdx, const PDBFile &File); + + std::error_code readBytes(uint32_t Offset, + MutableArrayRef Buffer) const override; + uint32_t getLength() const override { return StreamLength; } + +private: + uint32_t StreamLength; + std::vector BlockList; + const PDBFile &Pdb; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h b/include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h index eac7e4bbb75..0286e36f39f 100644 --- a/include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h +++ b/include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h @@ -11,9 +11,10 @@ #define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H #include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/DebugInfo/PDB/Raw/ByteStream.h" +#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Raw/ModInfo.h" #include "llvm/DebugInfo/PDB/Raw/PDBRawConstants.h" -#include "llvm/DebugInfo/PDB/Raw/PDBStream.h" #include "llvm/Support/Endian.h" namespace llvm { @@ -46,20 +47,21 @@ public: ArrayRef modules() const; private: - std::error_code readSubstream(std::vector &Bytes, uint32_t Size); std::error_code initializeFileInfo(); PDBFile &Pdb; - PDBStream Stream; + MappedBlockStream Stream; std::vector ModuleInfos; - std::vector ModInfoSubstream; - std::vector SecContrSubstream; - std::vector SecMapSubstream; - std::vector FileInfoSubstream; - std::vector TypeServerMapSubstream; - std::vector ECSubstream; + ByteStream ModInfoSubstream; + ByteStream SecContrSubstream; + ByteStream SecMapSubstream; + ByteStream FileInfoSubstream; + ByteStream TypeServerMapSubstream; + ByteStream ECSubstream; + ByteStream DbgHeader; + std::unique_ptr Header; }; } diff --git a/include/llvm/DebugInfo/PDB/Raw/PDBInfoStream.h b/include/llvm/DebugInfo/PDB/Raw/PDBInfoStream.h index ed914348d9f..0887c28910e 100644 --- a/include/llvm/DebugInfo/PDB/Raw/PDBInfoStream.h +++ b/include/llvm/DebugInfo/PDB/Raw/PDBInfoStream.h @@ -12,9 +12,9 @@ #include "llvm/ADT/StringMap.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Raw/PDBNameMap.h" #include "llvm/DebugInfo/PDB/Raw/PDBRawConstants.h" -#include "llvm/DebugInfo/PDB/Raw/PDBStream.h" #include "llvm/Support/Endian.h" @@ -37,7 +37,7 @@ public: private: PDBFile &Pdb; - PDBStream Stream1; + MappedBlockStream Stream; // PDB file format version. We only support VC70. See the enumeration // `PdbRaw_ImplVer` for the other possible values. diff --git a/include/llvm/DebugInfo/PDB/Raw/PDBNameMap.h b/include/llvm/DebugInfo/PDB/Raw/PDBNameMap.h index c747e499689..3f4aea41767 100644 --- a/include/llvm/DebugInfo/PDB/Raw/PDBNameMap.h +++ b/include/llvm/DebugInfo/PDB/Raw/PDBNameMap.h @@ -17,12 +17,12 @@ #include namespace llvm { -class PDBStream; +class StreamReader; class PDBNameMap { public: PDBNameMap(); - std::error_code load(PDBStream &Stream); + std::error_code load(StreamReader &Stream); bool tryGetValue(StringRef Name, uint32_t &Value) const; diff --git a/include/llvm/DebugInfo/PDB/Raw/PDBStream.h b/include/llvm/DebugInfo/PDB/Raw/PDBStream.h deleted file mode 100644 index 0f71e81cf2e..00000000000 --- a/include/llvm/DebugInfo/PDB/Raw/PDBStream.h +++ /dev/null @@ -1,46 +0,0 @@ -//===- PDBStream.h - Low level interface to a PDB stream --------*- 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_PDBSTREAM_H -#define LLVM_DEBUGINFO_PDB_RAW_PDBSTREAM_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" - -namespace llvm { - -class MemoryBufferRef; -class PDBFile; - -class PDBStream { -public: - PDBStream(uint32_t StreamIdx, const PDBFile &File); - - std::error_code readInteger(uint32_t &Dest); - std::error_code readZeroString(std::string &Dest); - std::error_code readBytes(void *Dest, uint32_t Length); - - void setOffset(uint32_t Off); - uint32_t getOffset() const; - uint32_t getLength() const; - - template std::error_code readObject(T *Dest) { - return readBytes(reinterpret_cast(Dest), sizeof(T)); - } - -private: - uint32_t Offset; - - uint32_t StreamLength; - std::vector BlockList; - const PDBFile &Pdb; -}; -} - -#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/StreamInterface.h b/include/llvm/DebugInfo/PDB/Raw/StreamInterface.h new file mode 100644 index 00000000000..6f235049d7e --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/StreamInterface.h @@ -0,0 +1,29 @@ +//===- StreamInterface.h - Base interface for a PDB stream ------*- 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_STREAMINTERFACE_H +#define LLVM_DEBUGINFO_PDB_RAW_STREAMINTERFACE_H + +#include "llvm/ADT/ArrayRef.h" + +#include +#include + +namespace llvm { +class StreamInterface { +public: + virtual ~StreamInterface() {} + + virtual std::error_code readBytes(uint32_t Offset, + MutableArrayRef Buffer) const = 0; + virtual uint32_t getLength() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Raw/StreamReader.h b/include/llvm/DebugInfo/PDB/Raw/StreamReader.h new file mode 100644 index 00000000000..84527ab840f --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Raw/StreamReader.h @@ -0,0 +1,46 @@ +//===- StreamReader.h - Reads bytes and objects from a stream ---*- 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_STREAMREADER_H +#define LLVM_DEBUGINFO_PDB_RAW_STREAMREADER_H + +#include "llvm/DebugInfo/PDB/Raw/StreamInterface.h" +#include "llvm/Support/Endian.h" + +#include +#include + +namespace llvm { + +class StreamReader { +public: + StreamReader(const StreamInterface &S); + + std::error_code readBytes(MutableArrayRef Buffer); + std::error_code readInteger(uint32_t &Dest); + std::error_code readZeroString(std::string &Dest); + + template std::error_code readObject(T *Dest) { + MutableArrayRef Buffer(reinterpret_cast(Dest), + sizeof(T)); + return readBytes(Buffer); + } + + void setOffset(uint32_t Off) { Offset = Off; } + uint32_t getOffset() const { return Offset; } + uint32_t getLength() const { return Stream.getLength(); } + uint32_t bytesRemaining() const { return getLength() - getOffset(); } + +private: + const StreamInterface &Stream; + uint32_t Offset; +}; +} + +#endif diff --git a/lib/DebugInfo/PDB/CMakeLists.txt b/lib/DebugInfo/PDB/CMakeLists.txt index b98c37bfbc8..93960c8ec31 100644 --- a/lib/DebugInfo/PDB/CMakeLists.txt +++ b/lib/DebugInfo/PDB/CMakeLists.txt @@ -27,13 +27,15 @@ if(HAVE_DIA_SDK) endif() add_pdb_impl_folder(Raw + Raw/ByteStream.cpp + Raw/MappedBlockStream.cpp Raw/ModInfo.cpp Raw/PDBFile.cpp Raw/PDBDbiStream.cpp Raw/PDBInfoStream.cpp Raw/PDBNameMap.cpp - Raw/PDBStream.cpp - Raw/RawSession.cpp) + Raw/RawSession.cpp + Raw/StreamReader.cpp) list(APPEND LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB") diff --git a/lib/DebugInfo/PDB/Raw/ByteStream.cpp b/lib/DebugInfo/PDB/Raw/ByteStream.cpp new file mode 100644 index 00000000000..20abe4c0d97 --- /dev/null +++ b/lib/DebugInfo/PDB/Raw/ByteStream.cpp @@ -0,0 +1,60 @@ +//===- ByteStream.cpp - Reads stream data from a byte sequence ------------===// +// +// 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/ByteStream.h" +#include "llvm/DebugInfo/PDB/Raw/StreamReader.h" + +using namespace llvm; + +ByteStream::ByteStream() : Owned(false) {} + +ByteStream::ByteStream(MutableArrayRef Bytes) : Owned(false) { + initialize(Bytes); +} + +ByteStream::ByteStream(uint32_t Length) : Owned(false) { initialize(Length); } + +ByteStream::~ByteStream() { reset(); } + +void ByteStream::reset() { + if (Owned) + delete[] Data.data(); + Owned = false; + Data = MutableArrayRef(); +} + +void ByteStream::initialize(MutableArrayRef Bytes) { + reset(); + Data = Bytes; + Owned = false; +} + +void ByteStream::initialize(uint32_t Length) { + reset(); + Data = MutableArrayRef(new uint8_t[Length], Length); + Owned = true; +} + +std::error_code ByteStream::initialize(StreamReader &Reader, uint32_t Length) { + initialize(Length); + std::error_code EC = Reader.readBytes(Data); + if (EC) + reset(); + return EC; +} + +std::error_code ByteStream::readBytes(uint32_t Offset, + MutableArrayRef Buffer) const { + if (Data.size() < Buffer.size() + Offset) + return std::make_error_code(std::errc::bad_address); + ::memcpy(Buffer.data(), Data.data() + Offset, Buffer.size()); + return std::error_code(); +} + +uint32_t ByteStream::getLength() const { return Data.size(); } diff --git a/lib/DebugInfo/PDB/Raw/PDBStream.cpp b/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp similarity index 54% rename from lib/DebugInfo/PDB/Raw/PDBStream.cpp rename to lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp index 6db04a55970..ed954bbed28 100644 --- a/lib/DebugInfo/PDB/Raw/PDBStream.cpp +++ b/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp @@ -1,4 +1,4 @@ -//===- PDBStream.cpp - Low level interface to a PDB stream ------*- C++ -*-===// +//===- MappedBlockStream.cpp - Reads stream data from a PDBFile -----------===// // // The LLVM Compiler Infrastructure // @@ -7,48 +7,31 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/Raw/PDBStream.h" +#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Raw/PDBFile.h" using namespace llvm; -PDBStream::PDBStream(uint32_t StreamIdx, const PDBFile &File) : Pdb(File) { +MappedBlockStream::MappedBlockStream(uint32_t StreamIdx, const PDBFile &File) : Pdb(File) { StreamLength = Pdb.getStreamByteSize(StreamIdx); BlockList = Pdb.getStreamBlockList(StreamIdx); - Offset = 0; } -std::error_code PDBStream::readInteger(uint32_t &Dest) { - support::ulittle32_t P; - if (std::error_code EC = readObject(&P)) - return EC; - Dest = P; - return std::error_code(); -} - -std::error_code PDBStream::readZeroString(std::string &Dest) { - char C; - do { - readObject(&C); - if (C != '\0') - Dest.push_back(C); - } while (C != '\0'); - return std::error_code(); -} - -std::error_code PDBStream::readBytes(void *Dest, uint32_t Length) { +std::error_code +MappedBlockStream::readBytes(uint32_t Offset, + MutableArrayRef Buffer) const { uint32_t BlockNum = Offset / Pdb.getBlockSize(); uint32_t OffsetInBlock = Offset % Pdb.getBlockSize(); // Make sure we aren't trying to read beyond the end of the stream. - if (Length > StreamLength) + if (Buffer.size() > StreamLength) return std::make_error_code(std::errc::bad_address); - if (Offset > StreamLength - Length) + if (Offset > StreamLength - Buffer.size()) return std::make_error_code(std::errc::bad_address); - uint32_t BytesLeft = Length; + uint32_t BytesLeft = Buffer.size(); uint32_t BytesWritten = 0; - char *WriteBuffer = static_cast(Dest); + uint8_t *WriteBuffer = Buffer.data(); while (BytesLeft > 0) { uint32_t StreamBlockAddr = BlockList[BlockNum]; @@ -65,14 +48,5 @@ std::error_code PDBStream::readBytes(void *Dest, uint32_t Length) { OffsetInBlock = 0; } - // Modify the offset to point to the data after the object. - Offset += Length; - return std::error_code(); } - -void PDBStream::setOffset(uint32_t O) { Offset = O; } - -uint32_t PDBStream::getOffset() const { return Offset; } - -uint32_t PDBStream::getLength() const { return StreamLength; } diff --git a/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp b/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp index 9c8b814d2b2..6c15385a16c 100644 --- a/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp +++ b/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp @@ -12,6 +12,7 @@ #include "llvm/DebugInfo/PDB/Raw/PDBFile.h" #include "llvm/DebugInfo/PDB/Raw/PDBInfoStream.h" #include "llvm/DebugInfo/PDB/Raw/PDBRawConstants.h" +#include "llvm/DebugInfo/PDB/Raw/StreamReader.h" using namespace llvm; using namespace llvm::support; @@ -58,12 +59,12 @@ struct PDBDbiStream::HeaderInfo { little32_t SecContrSubstreamSize; // Size of sec. contribution stream little32_t SectionMapSize; // Size of sec. map substream little32_t FileInfoSize; // Size of file info substream - 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. + 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 }; @@ -75,12 +76,13 @@ PDBDbiStream::PDBDbiStream(PDBFile &File) : Pdb(File), Stream(3, File) { PDBDbiStream::~PDBDbiStream() {} std::error_code PDBDbiStream::reload() { - Stream.setOffset(0); + StreamReader Reader(Stream); + Header.reset(new HeaderInfo()); if (Stream.getLength() < sizeof(HeaderInfo)) return std::make_error_code(std::errc::illegal_byte_sequence); - Stream.readObject(Header.get()); + Reader.readObject(Header.get()); if (Header->VersionSignature != -1) return std::make_error_code(std::errc::illegal_byte_sequence); @@ -115,30 +117,35 @@ std::error_code PDBDbiStream::reload() { return std::make_error_code(std::errc::illegal_byte_sequence); std::error_code EC; - if ((EC = readSubstream(ModInfoSubstream, Header->ModiSubstreamSize))) - return EC; + ModInfoSubstream.initialize(Reader, Header->ModiSubstreamSize); // Since each ModInfo in the stream is a variable length, we have to iterate // them to know how many there actually are. - auto Range = llvm::make_range(ModInfoIterator(&ModInfoSubstream.front()), - ModInfoIterator(&ModInfoSubstream.back() + 1)); + auto Range = + llvm::make_range(ModInfoIterator(&ModInfoSubstream.data().front()), + ModInfoIterator(&ModInfoSubstream.data().back() + 1)); for (auto Info : Range) ModuleInfos.push_back(ModuleInfoEx(Info)); - if ((EC = readSubstream(SecContrSubstream, Header->SecContrSubstreamSize))) + if ((EC = SecContrSubstream.initialize(Reader, Header->SecContrSubstreamSize))) return EC; - if ((EC = readSubstream(SecMapSubstream, Header->SectionMapSize))) + if ((EC = SecMapSubstream.initialize(Reader, Header->SectionMapSize))) return EC; - if ((EC = readSubstream(FileInfoSubstream, Header->FileInfoSize))) + if ((EC = FileInfoSubstream.initialize(Reader, Header->FileInfoSize))) return EC; - if ((EC = readSubstream(TypeServerMapSubstream, Header->TypeServerSize))) + if ((EC = TypeServerMapSubstream.initialize(Reader, Header->TypeServerSize))) return EC; - if ((EC = readSubstream(ECSubstream, Header->ECSubstreamSize))) + if ((EC = ECSubstream.initialize(Reader, Header->ECSubstreamSize))) + return EC; + if ((EC = DbgHeader.initialize(Reader, Header->OptionalDbgHdrSize))) return EC; if ((EC = initializeFileInfo())) return EC; + if (Reader.bytesRemaining() > 0) + return std::make_error_code(std::errc::illegal_byte_sequence); + return std::error_code(); } @@ -182,15 +189,6 @@ PDB_Machine PDBDbiStream::getMachineType() const { ArrayRef PDBDbiStream::modules() const { return ModuleInfos; } -std::error_code PDBDbiStream::readSubstream(std::vector &Bytes, uint32_t Size) { - Bytes.clear(); - if (Size == 0) - return std::error_code(); - - Bytes.resize(Size); - return Stream.readBytes(&Bytes[0], Size); -} - std::error_code PDBDbiStream::initializeFileInfo() { struct FileInfoSubstreamHeader { ulittle16_t NumModules; // Total # of modules, should match number of @@ -213,7 +211,7 @@ std::error_code PDBDbiStream::initializeFileInfo() { // with the caveat that `NumSourceFiles` cannot be trusted, so // it is computed by summing `ModFileCounts`. // - const uint8_t *Buf = &FileInfoSubstream[0]; + const uint8_t *Buf = &FileInfoSubstream.data().front(); auto FI = reinterpret_cast(Buf); Buf += sizeof(FileInfoSubstreamHeader); // The number of modules in the stream should be the same as reported by diff --git a/lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp b/lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp index fdf32470e78..90397db45bc 100644 --- a/lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp +++ b/lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp @@ -10,28 +10,30 @@ #include "llvm/DebugInfo/PDB/Raw/PDBInfoStream.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/PDB/Raw/StreamReader.h" using namespace llvm; -PDBInfoStream::PDBInfoStream(PDBFile &File) : Pdb(File), Stream1(1, File) {} +PDBInfoStream::PDBInfoStream(PDBFile &File) : Pdb(File), Stream(1, File) {} std::error_code PDBInfoStream::reload() { - Stream1.setOffset(0); + StreamReader Reader(Stream); + support::ulittle32_t Value; - Stream1.readObject(&Value); + Reader.readObject(&Value); Version = Value; if (Version < PdbRaw_ImplVer::PdbImplVC70) return std::make_error_code(std::errc::not_supported); - Stream1.readObject(&Value); + Reader.readObject(&Value); Signature = Value; - Stream1.readObject(&Value); + Reader.readObject(&Value); Age = Value; - Stream1.readObject(&Guid); - NamedStreams.load(Stream1); + Reader.readObject(&Guid); + NamedStreams.load(Reader); return std::error_code(); } diff --git a/lib/DebugInfo/PDB/Raw/PDBNameMap.cpp b/lib/DebugInfo/PDB/Raw/PDBNameMap.cpp index ed469317ee8..4dd8cf0c7aa 100644 --- a/lib/DebugInfo/PDB/Raw/PDBNameMap.cpp +++ b/lib/DebugInfo/PDB/Raw/PDBNameMap.cpp @@ -9,13 +9,14 @@ #include "llvm/DebugInfo/PDB/Raw/PDBNameMap.h" #include "llvm/ADT/BitVector.h" -#include "llvm/DebugInfo/PDB/Raw/PDBStream.h" +#include "llvm/DebugInfo/PDB/Raw/StreamReader.h" using namespace llvm; PDBNameMap::PDBNameMap() {} -std::error_code PDBNameMap::load(PDBStream &Stream) { +std::error_code PDBNameMap::load(StreamReader &Stream) { + // This is some sort of weird string-set/hash table encoded in the stream. // It starts with the number of bytes in the table. uint32_t NumberOfBytes; diff --git a/lib/DebugInfo/PDB/Raw/StreamReader.cpp b/lib/DebugInfo/PDB/Raw/StreamReader.cpp new file mode 100644 index 00000000000..707f77f5d73 --- /dev/null +++ b/lib/DebugInfo/PDB/Raw/StreamReader.cpp @@ -0,0 +1,40 @@ +//===- StreamReader.cpp - Reads bytes and objects from a stream -----------===// +// +// 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/StreamReader.h" + +using namespace llvm; + +StreamReader::StreamReader(const StreamInterface &S) : Stream(S), Offset(0) {} + +std::error_code StreamReader::readBytes(MutableArrayRef Buffer) { + if (auto EC = Stream.readBytes(Offset, Buffer)) + return EC; + Offset += Buffer.size(); + return std::error_code(); +} + +std::error_code StreamReader::readInteger(uint32_t &Dest) { + support::ulittle32_t P; + if (std::error_code EC = readObject(&P)) + return EC; + Dest = P; + return std::error_code(); +} + +std::error_code StreamReader::readZeroString(std::string &Dest) { + Dest.clear(); + char C; + do { + readObject(&C); + if (C != '\0') + Dest.push_back(C); + } while (C != '\0'); + return std::error_code(); +} diff --git a/tools/llvm-pdbdump/llvm-pdbdump.cpp b/tools/llvm-pdbdump/llvm-pdbdump.cpp index b91d8685715..45096daf097 100644 --- a/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -35,12 +35,13 @@ #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" #include "llvm/DebugInfo/PDB/PDBSymbolThunk.h" +#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Raw/ModInfo.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" #include "llvm/DebugInfo/PDB/Raw/RawSession.h" +#include "llvm/DebugInfo/PDB/Raw/StreamReader.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/FileSystem.h" @@ -246,17 +247,19 @@ static void dumpStructure(RawSession &RS) { // Let's try to dump out the named stream "/names". uint32_t NameStreamIndex = InfoStream.getNamedStreamIndex("/names"); if (NameStreamIndex != 0) { - PDBStream NameStream(NameStreamIndex, File); + MappedBlockStream NameStream(NameStreamIndex, File); + StreamReader Reader(NameStream); + outs() << "NameStream: " << NameStreamIndex << '\n'; // The name stream appears to start with a signature and version. uint32_t NameStreamSignature; - NameStream.readInteger(NameStreamSignature); + Reader.readInteger(NameStreamSignature); outs() << "NameStreamSignature: "; outs().write_hex(NameStreamSignature) << '\n'; uint32_t NameStreamVersion; - NameStream.readInteger(NameStreamVersion); + Reader.readInteger(NameStreamVersion); outs() << "NameStreamVersion: " << NameStreamVersion << '\n'; // We only support this particular version of the name stream.