diff options
| author | Zachary Turner <zturner@google.com> | 2016-04-29 17:22:58 +0000 |
|---|---|---|
| committer | Zachary Turner <zturner@google.com> | 2016-04-29 17:22:58 +0000 |
| commit | 6ba65deeb9b017e4144cdae341dcb9e3564c7c7b (patch) | |
| tree | 7b038a1cbb48d78056d0af5bd76f9a3ad44ea9d6 /llvm/lib | |
| parent | eaaec4a4c85a81ee9169e1647b733d839159c648 (diff) | |
| download | bcm5719-llvm-6ba65deeb9b017e4144cdae341dcb9e3564c7c7b.tar.gz bcm5719-llvm-6ba65deeb9b017e4144cdae341dcb9e3564c7c7b.zip | |
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
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/ByteStream.cpp | 60 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp (renamed from llvm/lib/DebugInfo/PDB/Raw/PDBStream.cpp) | 46 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp | 52 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp | 16 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/PDBNameMap.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/StreamReader.cpp | 40 |
7 files changed, 151 insertions, 74 deletions
diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt index b98c37bfbc8..93960c8ec31 100644 --- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt +++ b/llvm/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/llvm/lib/DebugInfo/PDB/Raw/ByteStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/ByteStream.cpp new file mode 100644 index 00000000000..20abe4c0d97 --- /dev/null +++ b/llvm/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<uint8_t> 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<uint8_t>(); +} + +void ByteStream::initialize(MutableArrayRef<uint8_t> Bytes) { + reset(); + Data = Bytes; + Owned = false; +} + +void ByteStream::initialize(uint32_t Length) { + reset(); + Data = MutableArrayRef<uint8_t>(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<uint8_t> 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/llvm/lib/DebugInfo/PDB/Raw/PDBStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp index 6db04a55970..ed954bbed28 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/PDBStream.cpp +++ b/llvm/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<uint8_t> 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<char *>(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/llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp index 9c8b814d2b2..6c15385a16c 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp +++ b/llvm/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<ModuleInfoEx> PDBDbiStream::modules() const { return ModuleInfos; } -std::error_code PDBDbiStream::readSubstream(std::vector<uint8_t> &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<const FileInfoSubstreamHeader *>(Buf); Buf += sizeof(FileInfoSubstreamHeader); // The number of modules in the stream should be the same as reported by diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp index fdf32470e78..90397db45bc 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/PDBInfoStream.cpp +++ b/llvm/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/llvm/lib/DebugInfo/PDB/Raw/PDBNameMap.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBNameMap.cpp index ed469317ee8..4dd8cf0c7aa 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/PDBNameMap.cpp +++ b/llvm/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/llvm/lib/DebugInfo/PDB/Raw/StreamReader.cpp b/llvm/lib/DebugInfo/PDB/Raw/StreamReader.cpp new file mode 100644 index 00000000000..707f77f5d73 --- /dev/null +++ b/llvm/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<uint8_t> 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(); +} |

