diff options
Diffstat (limited to 'llvm/include')
25 files changed, 389 insertions, 184 deletions
diff --git a/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h b/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h index 30c13ce5880..7cd6b45ef50 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h +++ b/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h @@ -32,7 +32,7 @@ namespace msf { template <typename Kind> struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> { - Error operator()(StreamRef Stream, uint32_t &Len, + Error operator()(ReadableStreamRef Stream, uint32_t &Len, codeview::CVRecord<Kind> &Item) const { using namespace codeview; const RecordPrefix *Prefix = nullptr; diff --git a/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h b/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h index a530a5d888a..073031f84a1 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h +++ b/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h @@ -59,15 +59,15 @@ struct ColumnNumberEntry { class ModuleSubstream { public: ModuleSubstream(); - ModuleSubstream(ModuleSubstreamKind Kind, msf::StreamRef Data); - static Error initialize(msf::StreamRef Stream, ModuleSubstream &Info); + ModuleSubstream(ModuleSubstreamKind Kind, msf::ReadableStreamRef Data); + static Error initialize(msf::ReadableStreamRef Stream, ModuleSubstream &Info); uint32_t getRecordLength() const; ModuleSubstreamKind getSubstreamKind() const; - msf::StreamRef getRecordData() const; + msf::ReadableStreamRef getRecordData() const; private: ModuleSubstreamKind Kind; - msf::StreamRef Data; + msf::ReadableStreamRef Data; }; typedef msf::VarStreamArray<ModuleSubstream> ModuleSubstreamArray; @@ -75,7 +75,7 @@ typedef msf::VarStreamArray<ModuleSubstream> ModuleSubstreamArray; namespace msf { template <> struct VarStreamArrayExtractor<codeview::ModuleSubstream> { - Error operator()(StreamRef Stream, uint32_t &Length, + Error operator()(ReadableStreamRef Stream, uint32_t &Length, codeview::ModuleSubstream &Info) const { if (auto EC = codeview::ModuleSubstream::initialize(Stream, Info)) return EC; diff --git a/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h b/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h index 697bc7d787a..e1bc68f80e2 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h +++ b/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h @@ -38,23 +38,24 @@ class IModuleSubstreamVisitor { public: virtual ~IModuleSubstreamVisitor() {} - virtual Error visitUnknown(ModuleSubstreamKind Kind, msf::StreamRef Data) = 0; - virtual Error visitSymbols(msf::StreamRef Data); - virtual Error visitLines(msf::StreamRef Data, + virtual Error visitUnknown(ModuleSubstreamKind Kind, + msf::ReadableStreamRef Data) = 0; + virtual Error visitSymbols(msf::ReadableStreamRef Data); + virtual Error visitLines(msf::ReadableStreamRef Data, const LineSubstreamHeader *Header, const LineInfoArray &Lines); - virtual Error visitStringTable(msf::StreamRef Data); - virtual Error visitFileChecksums(msf::StreamRef Data, + virtual Error visitStringTable(msf::ReadableStreamRef Data); + virtual Error visitFileChecksums(msf::ReadableStreamRef Data, const FileChecksumArray &Checksums); - virtual Error visitFrameData(msf::StreamRef Data); - virtual Error visitInlineeLines(msf::StreamRef Data); - virtual Error visitCrossScopeImports(msf::StreamRef Data); - virtual Error visitCrossScopeExports(msf::StreamRef Data); - virtual Error visitILLines(msf::StreamRef Data); - virtual Error visitFuncMDTokenMap(msf::StreamRef Data); - virtual Error visitTypeMDTokenMap(msf::StreamRef Data); - virtual Error visitMergedAssemblyInput(msf::StreamRef Data); - virtual Error visitCoffSymbolRVA(msf::StreamRef Data); + virtual Error visitFrameData(msf::ReadableStreamRef Data); + virtual Error visitInlineeLines(msf::ReadableStreamRef Data); + virtual Error visitCrossScopeImports(msf::ReadableStreamRef Data); + virtual Error visitCrossScopeExports(msf::ReadableStreamRef Data); + virtual Error visitILLines(msf::ReadableStreamRef Data); + virtual Error visitFuncMDTokenMap(msf::ReadableStreamRef Data); + virtual Error visitTypeMDTokenMap(msf::ReadableStreamRef Data); + virtual Error visitMergedAssemblyInput(msf::ReadableStreamRef Data); + virtual Error visitCoffSymbolRVA(msf::ReadableStreamRef Data); }; Error visitModuleSubstream(const ModuleSubstream &R, @@ -67,7 +68,7 @@ public: VarStreamArrayExtractor(const codeview::LineSubstreamHeader *Header) : Header(Header) {} - Error operator()(StreamRef Stream, uint32_t &Len, + Error operator()(ReadableStreamRef Stream, uint32_t &Len, codeview::LineColumnEntry &Item) const { using namespace codeview; const LineFileBlockHeader *BlockHeader; @@ -104,7 +105,7 @@ private: template <> class VarStreamArrayExtractor<codeview::FileChecksumEntry> { public: - Error operator()(StreamRef Stream, uint32_t &Len, + Error operator()(ReadableStreamRef Stream, uint32_t &Len, codeview::FileChecksumEntry &Item) const { using namespace codeview; const FileChecksum *Header; diff --git a/llvm/include/llvm/DebugInfo/Msf/ByteStream.h b/llvm/include/llvm/DebugInfo/Msf/ByteStream.h index 621848cf3d2..78ea1111975 100644 --- a/llvm/include/llvm/DebugInfo/Msf/ByteStream.h +++ b/llvm/include/llvm/DebugInfo/Msf/ByteStream.h @@ -12,45 +12,147 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/Msf/MsfError.h" #include "llvm/DebugInfo/Msf/StreamInterface.h" #include "llvm/Support/Error.h" +#include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/MemoryBuffer.h" #include <cstdint> #include <memory> #include <type_traits> namespace llvm { namespace msf { -class StreamReader; - -template <bool Writable = false> class ByteStream : public StreamInterface { - typedef typename std::conditional<Writable, MutableArrayRef<uint8_t>, - ArrayRef<uint8_t>>::type ArrayType; +class ByteStream : public ReadableStream { public: ByteStream() {} - explicit ByteStream(ArrayType Data) : Data(Data) {} - ~ByteStream() override {} + explicit ByteStream(ArrayRef<uint8_t> Data) : Data(Data) {} Error readBytes(uint32_t Offset, uint32_t Size, - ArrayRef<uint8_t> &Buffer) const override; + ArrayRef<uint8_t> &Buffer) const override { + if (Offset > Data.size()) + return make_error<MsfError>(msf_error_code::insufficient_buffer); + if (Data.size() < Size + Offset) + return make_error<MsfError>(msf_error_code::insufficient_buffer); + Buffer = Data.slice(Offset, Size); + return Error::success(); + } Error readLongestContiguousChunk(uint32_t Offset, - ArrayRef<uint8_t> &Buffer) const override; + ArrayRef<uint8_t> &Buffer) const override { + if (Offset >= Data.size()) + return make_error<MsfError>(msf_error_code::insufficient_buffer); + Buffer = Data.slice(Offset); + return Error::success(); + } - Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) const override; + uint32_t getLength() const override { return Data.size(); } - uint32_t getLength() const override; + ArrayRef<uint8_t> data() const { return Data; } - Error commit() const override; + StringRef str() const { + const char *CharData = reinterpret_cast<const char *>(Data.data()); + return StringRef(CharData, Data.size()); + } - ArrayRef<uint8_t> data() const { return Data; } - StringRef str() const; +protected: + ArrayRef<uint8_t> Data; +}; + +// MemoryBufferByteStream behaves like a read-only ByteStream, but has its data +// backed by an llvm::MemoryBuffer. It also owns the underlying MemoryBuffer. +class MemoryBufferByteStream : public ByteStream { +public: + explicit MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer) + : ByteStream(ArrayRef<uint8_t>(Buffer->getBuffer().bytes_begin(), + Buffer->getBuffer().bytes_end())), + MemBuffer(std::move(Buffer)) {} + + std::unique_ptr<MemoryBuffer> MemBuffer; +}; + +class MutableByteStream : public WritableStream { +public: + MutableByteStream() {} + explicit MutableByteStream(MutableArrayRef<uint8_t> Data) + : Data(Data), ImmutableStream(Data) {} + + Error readBytes(uint32_t Offset, uint32_t Size, + ArrayRef<uint8_t> &Buffer) const override { + return ImmutableStream.readBytes(Offset, Size, Buffer); + } + Error readLongestContiguousChunk(uint32_t Offset, + ArrayRef<uint8_t> &Buffer) const override { + return ImmutableStream.readLongestContiguousChunk(Offset, Buffer); + } + + uint32_t getLength() const override { return ImmutableStream.getLength(); } + + Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) const override { + if (Data.size() < Buffer.size()) + return make_error<MsfError>(msf_error_code::insufficient_buffer); + if (Offset > Buffer.size() - Data.size()) + return make_error<MsfError>(msf_error_code::insufficient_buffer); + + uint8_t *DataPtr = const_cast<uint8_t *>(Data.data()); + ::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size()); + return Error::success(); + } + + Error commit() const override { return Error::success(); } + + MutableArrayRef<uint8_t> data() const { return Data; } + +private: + MutableArrayRef<uint8_t> Data; + ByteStream ImmutableStream; +}; + +// A simple adapter that acts like a ByteStream but holds ownership over +// and underlying FileOutputBuffer. +class FileBufferByteStream : public WritableStream { +private: + class StreamImpl : public MutableByteStream { + public: + StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer) + : MutableByteStream(MutableArrayRef<uint8_t>(Buffer->getBufferStart(), + Buffer->getBufferEnd())), + FileBuffer(std::move(Buffer)) {} + + Error commit() const override { + if (FileBuffer->commit()) + return llvm::make_error<MsfError>(msf_error_code::not_writable); + return Error::success(); + } + + private: + std::unique_ptr<FileOutputBuffer> FileBuffer; + }; + +public: + explicit FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer) + : Impl(std::move(Buffer)) {} + + Error readBytes(uint32_t Offset, uint32_t Size, + ArrayRef<uint8_t> &Buffer) const override { + return Impl.readBytes(Offset, Size, Buffer); + } + Error readLongestContiguousChunk(uint32_t Offset, + ArrayRef<uint8_t> &Buffer) const override { + return Impl.readLongestContiguousChunk(Offset, Buffer); + } + + uint32_t getLength() const override { return Impl.getLength(); } + + Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const override { + return Impl.writeBytes(Offset, Data); + } + Error commit() const override { return Impl.commit(); } private: - ArrayType Data; + StreamImpl Impl; }; -extern template class ByteStream<true>; -extern template class ByteStream<false>; } // end namespace msf } // end namespace llvm diff --git a/llvm/include/llvm/DebugInfo/Msf/MappedBlockStream.h b/llvm/include/llvm/DebugInfo/Msf/MappedBlockStream.h index 94cff45d72a..f66826ba804 100644 --- a/llvm/include/llvm/DebugInfo/Msf/MappedBlockStream.h +++ b/llvm/include/llvm/DebugInfo/Msf/MappedBlockStream.h @@ -25,7 +25,7 @@ namespace llvm { namespace msf { -class IMsfFile; +struct MsfLayout; /// MappedBlockStream represents data stored in an Msf file into chunks of a /// particular size (called the Block Size), and whose chunks may not be @@ -37,42 +37,102 @@ class IMsfFile; /// the Msf. MappedBlockStream provides methods for reading from and writing /// to one of these streams transparently, as if it were a contiguous sequence /// of bytes. -class MappedBlockStream : public StreamInterface { +class MappedBlockStream : public ReadableStream { + friend class WritableMappedBlockStream; + public: + static std::unique_ptr<MappedBlockStream> + createStream(uint32_t BlockSize, uint32_t NumBlocks, + const MsfStreamLayout &Layout, const ReadableStream &MsfData); + + static std::unique_ptr<MappedBlockStream> + createIndexedStream(const MsfLayout &Layout, const ReadableStream &MsfData, + uint32_t StreamIndex); + + static std::unique_ptr<MappedBlockStream> + createDirectoryStream(const MsfLayout &Layout, const ReadableStream &MsfData); + Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef<uint8_t> &Buffer) const override; Error readLongestContiguousChunk(uint32_t Offset, ArrayRef<uint8_t> &Buffer) const override; - Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) const override; uint32_t getLength() const override; - Error commit() const override; uint32_t getNumBytesCopied() const; - static Expected<std::unique_ptr<MappedBlockStream>> - createIndexedStream(uint32_t StreamIdx, const IMsfFile &File); - static Expected<std::unique_ptr<MappedBlockStream>> - createDirectoryStream(uint32_t Length, ArrayRef<support::ulittle32_t> Blocks, - const IMsfFile &File); - llvm::BumpPtrAllocator &getAllocator() { return Pool; } + void invalidateCache(); + + uint32_t getBlockSize() const { return BlockSize; } + uint32_t getNumBlocks() const { return NumBlocks; } + uint32_t getStreamLength() const { return StreamLayout.Length; } + protected: - MappedBlockStream(const MsfStreamLayout &Layout, const IMsfFile &File); + MappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks, + const MsfStreamLayout &StreamLayout, + const ReadableStream &MsfData); + +private: + const MsfStreamLayout &getStreamLayout() const { return StreamLayout; } + void fixCacheAfterWrite(uint32_t Offset, ArrayRef<uint8_t> Data) const; Error readBytes(uint32_t Offset, MutableArrayRef<uint8_t> Buffer) const; bool tryReadContiguously(uint32_t Offset, uint32_t Size, ArrayRef<uint8_t> &Buffer) const; - const IMsfFile &Msf; - const MsfStreamLayout Layout; + const uint32_t BlockSize; + const uint32_t NumBlocks; + const MsfStreamLayout StreamLayout; + const ReadableStream &MsfData; typedef MutableArrayRef<uint8_t> CacheEntry; mutable llvm::BumpPtrAllocator Pool; mutable DenseMap<uint32_t, std::vector<CacheEntry>> CacheMap; }; +class WritableMappedBlockStream : public WritableStream { +public: + static std::unique_ptr<WritableMappedBlockStream> + createStream(uint32_t BlockSize, uint32_t NumBlocks, + const MsfStreamLayout &Layout, const WritableStream &MsfData); + + static std::unique_ptr<WritableMappedBlockStream> + createIndexedStream(const MsfLayout &Layout, const WritableStream &MsfData, + uint32_t StreamIndex); + + static std::unique_ptr<WritableMappedBlockStream> + createDirectoryStream(const MsfLayout &Layout, const WritableStream &MsfData); + + Error readBytes(uint32_t Offset, uint32_t Size, + ArrayRef<uint8_t> &Buffer) const override; + Error readLongestContiguousChunk(uint32_t Offset, + ArrayRef<uint8_t> &Buffer) const override; + uint32_t getLength() const override; + + Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) const override; + + Error commit() const override; + + const MsfStreamLayout &getStreamLayout() const { + return ReadInterface.getStreamLayout(); + } + uint32_t getBlockSize() const { return ReadInterface.getBlockSize(); } + uint32_t getNumBlocks() const { return ReadInterface.getNumBlocks(); } + uint32_t getStreamLength() const { return ReadInterface.getStreamLength(); } + +protected: + WritableMappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks, + const MsfStreamLayout &StreamLayout, + const WritableStream &MsfData); + +private: + MappedBlockStream ReadInterface; + + const WritableStream &WriteInterface; +}; + } // end namespace pdb } // end namespace llvm diff --git a/llvm/include/llvm/DebugInfo/Msf/MsfBuilder.h b/llvm/include/llvm/DebugInfo/Msf/MsfBuilder.h index 814e1655745..0ccdd6f0149 100644 --- a/llvm/include/llvm/DebugInfo/Msf/MsfBuilder.h +++ b/llvm/include/llvm/DebugInfo/Msf/MsfBuilder.h @@ -111,7 +111,7 @@ public: /// Finalize the layout and build the headers and structures that describe the /// MSF layout and can be written directly to the MSF file. - Expected<Layout> build(); + Expected<MsfLayout> build(); private: MsfBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow, diff --git a/llvm/include/llvm/DebugInfo/Msf/MsfCommon.h b/llvm/include/llvm/DebugInfo/Msf/MsfCommon.h index a53316cb657..86f20bd1711 100644 --- a/llvm/include/llvm/DebugInfo/Msf/MsfCommon.h +++ b/llvm/include/llvm/DebugInfo/Msf/MsfCommon.h @@ -48,8 +48,8 @@ struct SuperBlock { support::ulittle32_t BlockMapAddr; }; -struct Layout { - Layout() : SB(nullptr) {} +struct MsfLayout { + MsfLayout() : SB(nullptr) {} const SuperBlock *SB; ArrayRef<support::ulittle32_t> DirectoryBlocks; ArrayRef<support::ulittle32_t> StreamSizes; diff --git a/llvm/include/llvm/DebugInfo/Msf/StreamArray.h b/llvm/include/llvm/DebugInfo/Msf/StreamArray.h index dcdae8f00a0..569fb9bdd89 100644 --- a/llvm/include/llvm/DebugInfo/Msf/StreamArray.h +++ b/llvm/include/llvm/DebugInfo/Msf/StreamArray.h @@ -34,7 +34,8 @@ namespace msf { template <typename T> struct VarStreamArrayExtractor { // Method intentionally deleted. You must provide an explicit specialization // with the following method implemented. - Error operator()(StreamRef Stream, uint32_t &Len, T &Item) const = delete; + Error operator()(ReadableStreamRef Stream, uint32_t &Len, + T &Item) const = delete; }; /// VarStreamArray represents an array of variable length records backed by a @@ -83,8 +84,9 @@ public: VarStreamArray() {} explicit VarStreamArray(const Extractor &E) : E(E) {} - explicit VarStreamArray(StreamRef Stream) : Stream(Stream) {} - VarStreamArray(StreamRef Stream, const Extractor &E) : Stream(Stream), E(E) {} + explicit VarStreamArray(ReadableStreamRef Stream) : Stream(Stream) {} + VarStreamArray(ReadableStreamRef Stream, const Extractor &E) + : Stream(Stream), E(E) {} VarStreamArray(const VarStreamArray<ValueType, Extractor> &Other) : Stream(Other.Stream), E(Other.E) {} @@ -97,10 +99,10 @@ public: const Extractor &getExtractor() const { return E; } - StreamRef getUnderlyingStream() const { return Stream; } + ReadableStreamRef getUnderlyingStream() const { return Stream; } private: - StreamRef Stream; + ReadableStreamRef Stream; Extractor E; }; @@ -189,7 +191,7 @@ private: } ValueType ThisValue; - StreamRef IterRef; + ReadableStreamRef IterRef; const ArrayType *Array{nullptr}; uint32_t ThisLen{0}; bool HasError{false}; @@ -204,7 +206,7 @@ template <typename T> class FixedStreamArray { public: FixedStreamArray() : Stream() {} - FixedStreamArray(StreamRef Stream) : Stream(Stream) { + FixedStreamArray(ReadableStreamRef Stream) : Stream(Stream) { assert(Stream.getLength() % sizeof(T) == 0); } @@ -230,10 +232,10 @@ public: return FixedStreamArrayIterator<T>(*this, size()); } - StreamRef getUnderlyingStream() const { return Stream; } + ReadableStreamRef getUnderlyingStream() const { return Stream; } private: - StreamRef Stream; + ReadableStreamRef Stream; }; template <typename T> class FixedStreamArrayIterator { diff --git a/llvm/include/llvm/DebugInfo/Msf/StreamInterface.h b/llvm/include/llvm/DebugInfo/Msf/StreamInterface.h index 7a886e39289..78347e46c22 100644 --- a/llvm/include/llvm/DebugInfo/Msf/StreamInterface.h +++ b/llvm/include/llvm/DebugInfo/Msf/StreamInterface.h @@ -17,16 +17,9 @@ namespace llvm { namespace msf { -/// StreamInterface abstracts the notion of a data stream. This way, an -/// implementation could implement trivial reading from a contiguous memory -/// buffer or, as in the case of PDB files, reading from a set of possibly -/// discontiguous blocks. The implementation is required to return references -/// to stable memory, so if this is not possible (for example in the case of -/// a PDB file with discontiguous blocks, it must keep its own pool of temp -/// storage. -class StreamInterface { +class ReadableStream { public: - virtual ~StreamInterface() {} + virtual ~ReadableStream() {} // Given an offset into the stream and a number of bytes, attempt to read // the bytes and set the output ArrayRef to point to a reference into the @@ -39,13 +32,18 @@ public: virtual Error readLongestContiguousChunk(uint32_t Offset, ArrayRef<uint8_t> &Buffer) const = 0; + virtual uint32_t getLength() const = 0; +}; + +class WritableStream : public ReadableStream { +public: + virtual ~WritableStream() {} + // Attempt to write the given bytes into the stream at the desired offset. // This will always necessitate a copy. Cannot shrink or grow the stream, // only writes into existing allocated space. virtual Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const = 0; - virtual uint32_t getLength() const = 0; - virtual Error commit() const = 0; }; diff --git a/llvm/include/llvm/DebugInfo/Msf/StreamReader.h b/llvm/include/llvm/DebugInfo/Msf/StreamReader.h index 3d03f406551..31f437f87c9 100644 --- a/llvm/include/llvm/DebugInfo/Msf/StreamReader.h +++ b/llvm/include/llvm/DebugInfo/Msf/StreamReader.h @@ -14,6 +14,7 @@ #include "llvm/DebugInfo/Msf/MsfError.h" #include "llvm/DebugInfo/Msf/StreamArray.h" #include "llvm/DebugInfo/Msf/StreamInterface.h" +#include "llvm/DebugInfo/Msf/StreamRef.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" @@ -22,11 +23,9 @@ namespace llvm { namespace msf { -class StreamRef; - class StreamReader { public: - StreamReader(StreamRef Stream); + StreamReader(ReadableStreamRef Stream); Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer); Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size); @@ -34,8 +33,8 @@ public: Error readInteger(uint32_t &Dest); Error readZeroString(StringRef &Dest); Error readFixedString(StringRef &Dest, uint32_t Length); - Error readStreamRef(StreamRef &Ref); - Error readStreamRef(StreamRef &Ref, uint32_t Length); + Error readStreamRef(ReadableStreamRef &Ref); + Error readStreamRef(ReadableStreamRef &Ref, uint32_t Length); template <typename T> Error readEnum(T &Dest) { typename std::underlying_type<T>::type N; @@ -72,7 +71,7 @@ public: template <typename T, typename U> Error readArray(VarStreamArray<T, U> &Array, uint32_t Size) { - StreamRef S; + ReadableStreamRef S; if (auto EC = readStreamRef(S, Size)) return EC; Array = VarStreamArray<T, U>(S, Array.getExtractor()); @@ -90,7 +89,7 @@ public: return make_error<MsfError>(msf_error_code::invalid_format); if (Offset + Length > Stream.getLength()) return make_error<MsfError>(msf_error_code::insufficient_buffer); - StreamRef View = Stream.slice(Offset, Length); + ReadableStreamRef View = Stream.slice(Offset, Length); Array = FixedStreamArray<T>(View); Offset += Length; return Error::success(); @@ -102,7 +101,7 @@ public: uint32_t bytesRemaining() const { return getLength() - getOffset(); } private: - StreamRef Stream; + ReadableStreamRef Stream; uint32_t Offset; }; } // namespace msf diff --git a/llvm/include/llvm/DebugInfo/Msf/StreamRef.h b/llvm/include/llvm/DebugInfo/Msf/StreamRef.h index e87d298a834..87e53ce4fa4 100644 --- a/llvm/include/llvm/DebugInfo/Msf/StreamRef.h +++ b/llvm/include/llvm/DebugInfo/Msf/StreamRef.h @@ -15,17 +15,63 @@ namespace llvm { namespace msf { - -class StreamRef { +template <class StreamType, class RefType> class StreamRefBase { public: - StreamRef() : Stream(nullptr), ViewOffset(0), Length(0) {} - StreamRef(const StreamInterface &Stream) - : Stream(&Stream), ViewOffset(0), Length(Stream.getLength()) {} - StreamRef(const StreamInterface &Stream, uint32_t Offset, uint32_t Length) + StreamRefBase() : Stream(nullptr), Length(0), ViewOffset(0) {} + StreamRefBase(const StreamType &Stream, uint32_t Offset, uint32_t Length) : Stream(&Stream), ViewOffset(Offset), Length(Length) {} + uint32_t getLength() const { return Length; } + const StreamType *getStream() const { return Stream; } + + RefType drop_front(uint32_t N) const { + if (!Stream) + return RefType(); + + N = std::min(N, Length); + return RefType(*Stream, ViewOffset + N, Length - N); + } + + RefType keep_front(uint32_t N) const { + if (!Stream) + return RefType(); + N = std::min(N, Length); + return RefType(*Stream, ViewOffset, N); + } + + RefType slice(uint32_t Offset, uint32_t Len) const { + return drop_front(Offset).keep_front(Len); + } + + bool operator==(const RefType &Other) const { + if (Stream != Other.Stream) + return false; + if (ViewOffset != Other.ViewOffset) + return false; + if (Length != Other.Length) + return false; + return true; + } + +protected: + const StreamType *Stream; + uint32_t ViewOffset; + uint32_t Length; +}; + +class ReadableStreamRef + : public StreamRefBase<ReadableStream, ReadableStreamRef> { +public: + ReadableStreamRef() : StreamRefBase() {} + ReadableStreamRef(const ReadableStream &Stream) + : StreamRefBase(Stream, 0, Stream.getLength()) {} + ReadableStreamRef(const ReadableStream &Stream, uint32_t Offset, + uint32_t Length) + : StreamRefBase(Stream, Offset, Length) {} + // Use StreamRef.slice() instead. - StreamRef(const StreamRef &S, uint32_t Offset, uint32_t Length) = delete; + ReadableStreamRef(const ReadableStreamRef &S, uint32_t Offset, + uint32_t Length) = delete; Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef<uint8_t> &Buffer) const { @@ -53,6 +99,21 @@ public: Buffer = Buffer.slice(0, MaxLength); return Error::success(); } +}; + +class WritableStreamRef + : public StreamRefBase<WritableStream, WritableStreamRef> { +public: + WritableStreamRef() : StreamRefBase() {} + WritableStreamRef(const WritableStream &Stream) + : StreamRefBase(Stream, 0, Stream.getLength()) {} + WritableStreamRef(const WritableStream &Stream, uint32_t Offset, + uint32_t Length) + : StreamRefBase(Stream, Offset, Length) {} + + // Use StreamRef.slice() instead. + WritableStreamRef(const WritableStreamRef &S, uint32_t Offset, + uint32_t Length) = delete; Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const { if (Data.size() + Offset > Length) @@ -60,44 +121,9 @@ public: return Stream->writeBytes(ViewOffset + Offset, Data); } - uint32_t getLength() const { return Length; } - Error commit() const { return Stream->commit(); } - - StreamRef drop_front(uint32_t N) const { - if (!Stream) - return StreamRef(); - - N = std::min(N, Length); - return StreamRef(*Stream, ViewOffset + N, Length - N); - } - - StreamRef keep_front(uint32_t N) const { - if (!Stream) - return StreamRef(); - N = std::min(N, Length); - return StreamRef(*Stream, ViewOffset, N); - } - - StreamRef slice(uint32_t Offset, uint32_t Len) const { - return drop_front(Offset).keep_front(Len); - } - - bool operator==(const StreamRef &Other) const { - if (Stream != Other.Stream) - return false; - if (ViewOffset != Other.ViewOffset) - return false; - if (Length != Other.Length) - return false; - return true; - } - -private: - const StreamInterface *Stream; - uint32_t ViewOffset; - uint32_t Length; }; + } // namespace msf } // namespace llvm diff --git a/llvm/include/llvm/DebugInfo/Msf/StreamWriter.h b/llvm/include/llvm/DebugInfo/Msf/StreamWriter.h index a4cf3576a3e..04194892e9b 100644 --- a/llvm/include/llvm/DebugInfo/Msf/StreamWriter.h +++ b/llvm/include/llvm/DebugInfo/Msf/StreamWriter.h @@ -14,6 +14,7 @@ #include "llvm/DebugInfo/Msf/MsfError.h" #include "llvm/DebugInfo/Msf/StreamArray.h" #include "llvm/DebugInfo/Msf/StreamInterface.h" +#include "llvm/DebugInfo/Msf/StreamRef.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" @@ -22,19 +23,17 @@ namespace llvm { namespace msf { -class StreamRef; - class StreamWriter { public: - StreamWriter(StreamRef Stream); + StreamWriter(WritableStreamRef Stream); Error writeBytes(ArrayRef<uint8_t> Buffer); Error writeInteger(uint16_t Dest); Error writeInteger(uint32_t Dest); Error writeZeroString(StringRef Str); Error writeFixedString(StringRef Str); - Error writeStreamRef(StreamRef Ref); - Error writeStreamRef(StreamRef Ref, uint32_t Size); + Error writeStreamRef(ReadableStreamRef Ref); + Error writeStreamRef(ReadableStreamRef Ref, uint32_t Size); template <typename T> Error writeEnum(T Num) { return writeInteger( @@ -77,7 +76,7 @@ public: uint32_t bytesRemaining() const { return getLength() - getOffset(); } private: - StreamRef Stream; + WritableStreamRef Stream; uint32_t Offset; }; } // namespace msf diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h b/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h index a9325a43436..0d232f15d74 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h @@ -12,9 +12,10 @@ #include "llvm/Config/llvm-config.h" #include "llvm/DebugInfo/CodeView/CodeView.h" -#include <functional> +#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" #include <cstdint> #include <cstring> +#include <functional> namespace llvm { namespace pdb { @@ -73,13 +74,6 @@ enum class PDB_ReaderType { Raw = 1, }; -/// Defines a 128-bit unique identifier. This maps to a GUID on Windows, but -/// is abstracted here for the purposes of non-Windows platforms that don't have -/// the GUID structure defined. -struct PDB_UniqueId { - char Guid[16]; -}; - /// An enumeration indicating the type of data contained in this table. enum class PDB_TableType { Symbols, diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h b/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h index bbdf0dfd562..7802f48be2c 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h @@ -77,8 +77,6 @@ public: msf::FixedStreamArray<SecMapEntry> getSectionMap() const; void visitSectionContributions(ISectionContribVisitor &Visitor) const; - Error commit(); - private: Error initializeModInfoArray(); Error initializeSectionContributionData(); @@ -93,14 +91,14 @@ private: std::vector<ModuleInfoEx> ModuleInfos; NameHashTable ECNames; - msf::StreamRef ModInfoSubstream; - msf::StreamRef SecContrSubstream; - msf::StreamRef SecMapSubstream; - msf::StreamRef FileInfoSubstream; - msf::StreamRef TypeServerMapSubstream; - msf::StreamRef ECSubstream; + msf::ReadableStreamRef ModInfoSubstream; + msf::ReadableStreamRef SecContrSubstream; + msf::ReadableStreamRef SecMapSubstream; + msf::ReadableStreamRef FileInfoSubstream; + msf::ReadableStreamRef TypeServerMapSubstream; + msf::ReadableStreamRef ECSubstream; - msf::StreamRef NamesBuffer; + msf::ReadableStreamRef NamesBuffer; msf::FixedStreamArray<support::ulittle16_t> DbgStreams; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h index 7abe9546f88..a3c8fc5dbbb 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h @@ -23,6 +23,7 @@ namespace llvm { namespace pdb { class DbiStream; +struct DbiStreamHeader; class PDBFile; class DbiStreamBuilder { @@ -45,9 +46,13 @@ public: Error addModuleInfo(StringRef ObjFile, StringRef Module); Error addModuleSourceFile(StringRef Module, StringRef File); - Expected<std::unique_ptr<DbiStream>> build(PDBFile &File); + Expected<std::unique_ptr<DbiStream>> build(PDBFile &File, + const msf::WritableStream &Buffer); + Error commit(const msf::MsfLayout &Layout, + const msf::WritableStream &Buffer) const; private: + Error finalize(); uint32_t calculateModiSubstreamSize() const; uint32_t calculateFileInfoSubstreamSize() const; uint32_t calculateNamesBufferSize() const; @@ -71,14 +76,16 @@ private: uint16_t Flags; PDB_Machine MachineType; + const DbiStreamHeader *Header; + StringMap<std::unique_ptr<ModuleInfo>> ModuleInfos; std::vector<ModuleInfo *> ModuleInfoList; StringMap<uint32_t> SourceFileNames; - msf::StreamRef NamesBuffer; - msf::ByteStream<true> ModInfoBuffer; - msf::ByteStream<true> FileInfoBuffer; + msf::WritableStreamRef NamesBuffer; + msf::MutableByteStream ModInfoBuffer; + msf::MutableByteStream FileInfoBuffer; }; } } diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h b/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h index bc6aebb156a..e71c63d0552 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h @@ -27,18 +27,10 @@ class PDBFile; class InfoStream { friend class InfoStreamBuilder; - struct HeaderInfo { - support::ulittle32_t Version; - support::ulittle32_t Signature; - support::ulittle32_t Age; - PDB_UniqueId Guid; - }; - public: InfoStream(std::unique_ptr<msf::MappedBlockStream> Stream); Error reload(); - Error commit(); PdbRaw_ImplVer getVersion() const; uint32_t getSignature() const; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h index e9869bb2786..f3c3eadcec6 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h @@ -19,6 +19,9 @@ #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" namespace llvm { +namespace msf { +class StreamWriter; +} namespace pdb { class PDBFile; @@ -37,13 +40,17 @@ public: uint32_t calculateSerializedLength() const; - Expected<std::unique_ptr<InfoStream>> build(PDBFile &File); + Expected<std::unique_ptr<InfoStream>> + build(PDBFile &File, const msf::WritableStream &Buffer); + + Error commit(const msf::MsfLayout &Layout, + const msf::WritableStream &Buffer) const; private: - Optional<PdbRaw_ImplVer> Ver; - Optional<uint32_t> Sig; - Optional<uint32_t> Age; - Optional<PDB_UniqueId> Guid; + PdbRaw_ImplVer Ver; + uint32_t Sig; + uint32_t Age; + PDB_UniqueId Guid; NameMapBuilder NamedStreams; }; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h b/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h index cdb3735fcb4..e48b6aa15fa 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h @@ -29,7 +29,7 @@ public: ModInfo(const ModInfo &Info); ~ModInfo(); - static Error initialize(msf::StreamRef Stream, ModInfo &Info); + static Error initialize(msf::ReadableStreamRef Stream, ModInfo &Info); bool hasECInfo() const; uint16_t getTypeServerIndex() const; @@ -65,7 +65,7 @@ struct ModuleInfoEx { namespace msf { template <> struct VarStreamArrayExtractor<pdb::ModInfo> { - Error operator()(StreamRef Stream, uint32_t &Length, + Error operator()(ReadableStreamRef Stream, uint32_t &Length, pdb::ModInfo &Info) const { if (auto EC = pdb::ModInfo::initialize(Stream, Info)) return EC; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h b/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h index bee4075aaf2..57e84edc1bb 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h @@ -46,9 +46,9 @@ private: std::unique_ptr<msf::MappedBlockStream> Stream; codeview::CVSymbolArray SymbolsSubstream; - msf::StreamRef LinesSubstream; - msf::StreamRef C13LinesSubstream; - msf::StreamRef GlobalRefsSubstream; + msf::ReadableStreamRef LinesSubstream; + msf::ReadableStreamRef C13LinesSubstream; + msf::ReadableStreamRef GlobalRefsSubstream; codeview::ModuleSubstreamArray LineInfo; }; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h b/llvm/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h index 7de26f3b270..c9dd95d01c1 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h @@ -41,7 +41,7 @@ public: msf::FixedStreamArray<support::ulittle32_t> name_ids() const; private: - msf::StreamRef NamesBuffer; + msf::ReadableStreamRef NamesBuffer; msf::FixedStreamArray<support::ulittle32_t> IDs; uint32_t Signature; uint32_t HashVersion; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h b/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h index ca1a6541dfb..de1163bc307 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h @@ -29,7 +29,6 @@ public: NameMap(); Error load(msf::StreamReader &Stream); - Error commit(msf::StreamWriter &Writer); bool tryGetValue(StringRef Name, uint32_t &Value) const; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h index bf49bfd9bf2..f5244ac2180 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h @@ -17,6 +17,9 @@ #include <memory> namespace llvm { +namespace msf { +class StreamWriter; +} namespace pdb { class NameMap; @@ -27,6 +30,7 @@ public: void addMapping(StringRef Name, uint32_t Mapping); Expected<std::unique_ptr<NameMap>> build(); + Error commit(msf::StreamWriter &Writer) const; uint32_t calculateSerializedLength() const; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h index 2aaef3af838..b0be4fb4705 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h @@ -26,7 +26,7 @@ namespace llvm { namespace msf { class MappedBlockStream; -class StreamInterface; +class WritableStream; } namespace pdb { @@ -42,7 +42,7 @@ class PDBFile : public msf::IMsfFile { friend PDBFileBuilder; public: - PDBFile(std::unique_ptr<msf::StreamInterface> PdbFileBuffer, + PDBFile(std::unique_ptr<msf::ReadableStream> PdbFileBuffer, BumpPtrAllocator &Allocator); ~PDBFile() override; @@ -68,12 +68,15 @@ public: ArrayRef<uint8_t> Data) const override; ArrayRef<support::ulittle32_t> getStreamSizes() const { - return MsfLayout.StreamSizes; + return ContainerLayout.StreamSizes; } ArrayRef<ArrayRef<support::ulittle32_t>> getStreamMap() const { - return MsfLayout.StreamMap; + return ContainerLayout.StreamMap; } + const msf::MsfLayout &getMsfLayout() const { return ContainerLayout; } + const msf::ReadableStream &getMsfBuffer() const { return *Buffer; } + ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const; Error parseFileHeaders(); @@ -87,14 +90,12 @@ public: Expected<SymbolStream &> getPDBSymbolStream(); Expected<NameHashTable &> getStringTable(); - Error commit(); - private: BumpPtrAllocator &Allocator; - std::unique_ptr<msf::StreamInterface> Buffer; + std::unique_ptr<msf::ReadableStream> Buffer; - msf::Layout MsfLayout; + msf::MsfLayout ContainerLayout; std::unique_ptr<InfoStream> Info; std::unique_ptr<DbiStream> Dbi; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h index c2effd170fd..6242f42e991 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h @@ -24,7 +24,6 @@ namespace llvm { namespace msf { class MsfBuilder; -class StreamInterface; } namespace pdb { class DbiStreamBuilder; @@ -43,10 +42,12 @@ public: DbiStreamBuilder &getDbiBuilder(); Expected<std::unique_ptr<PDBFile>> - build(std::unique_ptr<msf::StreamInterface> PdbFileBuffer); + build(std::unique_ptr<msf::WritableStream> PdbFileBuffer); + + Error commit(const msf::WritableStream &Buffer); private: - Expected<msf::Layout> finalizeMsfLayout() const; + Expected<msf::MsfLayout> finalizeMsfLayout() const; BumpPtrAllocator &Allocator; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/RawTypes.h b/llvm/include/llvm/DebugInfo/PDB/Raw/RawTypes.h index 8567f827e70..7edfbf0d250 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/RawTypes.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/RawTypes.h @@ -259,6 +259,21 @@ struct ModuleInfoHeader { /// char ObjFileName[]; }; +/// Defines a 128-bit unique identifier. This maps to a GUID on Windows, but +/// is abstracted here for the purposes of non-Windows platforms that don't have +/// the GUID structure defined. +struct PDB_UniqueId { + char Guid[16]; +}; + +/// The header preceeding the global PDB Stream (Stream 1) +struct InfoStreamHeader { + support::ulittle32_t Version; + support::ulittle32_t Signature; + support::ulittle32_t Age; + PDB_UniqueId Guid; +}; + } // namespace pdb } // namespace llvm |