diff options
Diffstat (limited to 'llvm/include')
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/ByteStream.h | 21 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h | 1 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/StreamArray.h | 2 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/StreamInterface.h | 13 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/StreamReader.h | 1 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/StreamRef.h | 28 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/StreamWriter.h | 82 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/PDB/Raw/IPDBFile.h | 3 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h | 6 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h | 2 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h | 4 | ||||
-rw-r--r-- | llvm/include/llvm/Support/MathExtras.h | 8 |
12 files changed, 163 insertions, 8 deletions
diff --git a/llvm/include/llvm/DebugInfo/CodeView/ByteStream.h b/llvm/include/llvm/DebugInfo/CodeView/ByteStream.h index 44fcbaabd6d..ec841d9f45e 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/ByteStream.h +++ b/llvm/include/llvm/DebugInfo/CodeView/ByteStream.h @@ -16,19 +16,27 @@ #include "llvm/Support/Error.h" #include <cstdint> #include <memory> +#include <type_traits> namespace llvm { namespace codeview { class StreamReader; -class ByteStream : public StreamInterface { +template <bool Writable = false> class ByteStream : public StreamInterface { + typedef typename std::conditional<Writable, MutableArrayRef<uint8_t>, + ArrayRef<uint8_t>>::type ArrayType; + public: - ByteStream(); - explicit ByteStream(ArrayRef<uint8_t> Data); - ~ByteStream() override; + ByteStream() {} + explicit ByteStream(ArrayType Data) : Data(Data) {} + ~ByteStream() override {} 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; @@ -36,9 +44,12 @@ public: StringRef str() const; private: - ArrayRef<uint8_t> Data; + ArrayType Data; }; +extern template class ByteStream<true>; +extern template class ByteStream<false>; + } // end namespace pdb } // end namespace llvm diff --git a/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h b/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h index a3d4171f693..69ff29aab6f 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h +++ b/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h @@ -19,6 +19,7 @@ namespace codeview { enum class cv_error_code { unspecified = 1, insufficient_buffer, + operation_unsupported, corrupt_record, }; diff --git a/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h b/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h index 0241bb82be2..b6ecc75e439 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h +++ b/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h @@ -97,6 +97,8 @@ public: const Extractor &getExtractor() const { return E; } + StreamRef getUnderlyingStream() const { return Stream; } + private: StreamRef Stream; Extractor E; diff --git a/llvm/include/llvm/DebugInfo/CodeView/StreamInterface.h b/llvm/include/llvm/DebugInfo/CodeView/StreamInterface.h index f875f1896a4..a8b9dbfc2b6 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/StreamInterface.h +++ b/llvm/include/llvm/DebugInfo/CodeView/StreamInterface.h @@ -28,9 +28,22 @@ class StreamInterface { public: virtual ~StreamInterface() {} + // 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 + // stream, without copying any data. virtual Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef<uint8_t> &Buffer) const = 0; + // Given an offset into the stream, read as much as possible without copying + // any data. + virtual Error readLongestContiguousChunk(uint32_t Offset, + ArrayRef<uint8_t> &Buffer) const = 0; + + // 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; }; diff --git a/llvm/include/llvm/DebugInfo/CodeView/StreamReader.h b/llvm/include/llvm/DebugInfo/CodeView/StreamReader.h index a42cc8bc7b8..2f497c2c43f 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/StreamReader.h +++ b/llvm/include/llvm/DebugInfo/CodeView/StreamReader.h @@ -28,6 +28,7 @@ class StreamReader { public: StreamReader(StreamRef Stream); + Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer); Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size); Error readInteger(uint16_t &Dest); Error readInteger(uint32_t &Dest); diff --git a/llvm/include/llvm/DebugInfo/CodeView/StreamRef.h b/llvm/include/llvm/DebugInfo/CodeView/StreamRef.h index 036802d2499..93b116b78c8 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/StreamRef.h +++ b/llvm/include/llvm/DebugInfo/CodeView/StreamRef.h @@ -24,7 +24,8 @@ public: StreamRef(const StreamInterface &Stream, uint32_t Offset, uint32_t Length) : Stream(&Stream), ViewOffset(Offset), Length(Length) {} - StreamRef(const StreamRef &Stream, uint32_t Offset, uint32_t Length) = delete; + // Use StreamRef.slice() instead. + StreamRef(const StreamRef &S, uint32_t Offset, uint32_t Length) = delete; Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef<uint8_t> &Buffer) const override { @@ -33,7 +34,32 @@ public: return Stream->readBytes(ViewOffset + Offset, Size, Buffer); } + // Given an offset into the stream, read as much as possible without copying + // any data. + Error readLongestContiguousChunk(uint32_t Offset, + ArrayRef<uint8_t> &Buffer) const override { + if (Offset >= Length) + return make_error<CodeViewError>(cv_error_code::insufficient_buffer); + + if (auto EC = Stream->readLongestContiguousChunk(Offset, Buffer)) + return EC; + // This StreamRef might refer to a smaller window over a larger stream. In + // that case we will have read out more bytes than we should return, because + // we should not read past the end of the current view. + uint32_t MaxLength = Length - Offset; + if (Buffer.size() > MaxLength) + Buffer = Buffer.slice(0, MaxLength); + return Error::success(); + } + + Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const override { + if (Data.size() + Offset > Length) + return make_error<CodeViewError>(cv_error_code::insufficient_buffer); + return Stream->writeBytes(ViewOffset + Offset, Data); + } + uint32_t getLength() const override { return Length; } + StreamRef drop_front(uint32_t N) const { if (!Stream) return StreamRef(); diff --git a/llvm/include/llvm/DebugInfo/CodeView/StreamWriter.h b/llvm/include/llvm/DebugInfo/CodeView/StreamWriter.h new file mode 100644 index 00000000000..ad9277b8e22 --- /dev/null +++ b/llvm/include/llvm/DebugInfo/CodeView/StreamWriter.h @@ -0,0 +1,82 @@ +//===- StreamWriter.h - Writes bytes and objects to 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_CODEVIEW_STREAMWRITER_H +#define LLVM_DEBUGINFO_CODEVIEW_STREAMWRITER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/DebugInfo/CodeView/StreamArray.h" +#include "llvm/DebugInfo/CodeView/StreamInterface.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" + +#include <string> + +namespace llvm { +namespace codeview { + +class StreamRef; + +class StreamWriter { +public: + StreamWriter(StreamRef 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); + + template <typename T> Error writeEnum(T Num) { + return writeInteger( + static_cast<typename std::underlying_type<T>::type>(Num)); + } + + template <typename T> Error writeObject(const T &Obj) { + return writeBytes( + ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T))); + } + + template <typename T> Error writeArray(ArrayRef<T> Array) { + if (Array.size() == 0) + return Error::success(); + + if (Array.size() > UINT32_MAX / sizeof(T)) + return make_error<CodeViewError>(cv_error_code::insufficient_buffer); + + return writeBytes( + ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Array.data()), + Array.size() * sizeof(T))); + } + + template <typename T, typename U> + Error writeArray(VarStreamArray<T, U> Array) { + return writeStreamRef(Array.getUnderlyingStream()); + } + + template <typename T> Error writeArray(FixedStreamArray<T> Array) { + return writeStreamRef(Array.getUnderlyingStream()); + } + + 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: + StreamRef Stream; + uint32_t Offset; +}; +} // namespace codeview +} // namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMREADER_H diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/IPDBFile.h b/llvm/include/llvm/DebugInfo/PDB/Raw/IPDBFile.h index 0f8736d55c4..717a7880f3c 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/IPDBFile.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/IPDBFile.h @@ -14,6 +14,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/StreamArray.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" #include <stdint.h> @@ -34,6 +35,8 @@ public: virtual ArrayRef<uint8_t> getBlockData(uint32_t BlockIndex, uint32_t NumBytes) const = 0; + virtual Error setBlockData(uint32_t BlockIndex, uint32_t Offset, + ArrayRef<uint8_t> Data) const = 0; }; } } diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h b/llvm/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h index 0148ed6086b..8ee0ab66446 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h @@ -31,6 +31,9 @@ class MappedBlockStream : public codeview::StreamInterface { public: 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; @@ -51,8 +54,9 @@ protected: const IPDBFile &Pdb; std::unique_ptr<IPDBStreamData> Data; + typedef MutableArrayRef<uint8_t> CacheEntry; mutable llvm::BumpPtrAllocator Pool; - mutable DenseMap<uint32_t, uint8_t *> CacheMap; + mutable DenseMap<uint32_t, std::vector<CacheEntry>> CacheMap; }; } // end namespace pdb diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h index f6ee987adcd..20e22e318c6 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h @@ -54,6 +54,8 @@ public: ArrayRef<uint8_t> getBlockData(uint32_t BlockIndex, uint32_t NumBytes) const override; + Error setBlockData(uint32_t BlockIndex, uint32_t Offset, + ArrayRef<uint8_t> Data) const override; ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const; diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h b/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h index 5a1614fc82e..076f75ba031 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h @@ -22,7 +22,9 @@ enum class raw_error_code { corrupt_file, insufficient_buffer, no_stream, - index_out_of_bounds + index_out_of_bounds, + invalid_block_address, + not_writable, }; /// Base class for errors originating when parsing raw PDB files diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h index e9639450a70..94ca40d5789 100644 --- a/llvm/include/llvm/Support/MathExtras.h +++ b/llvm/include/llvm/Support/MathExtras.h @@ -681,6 +681,14 @@ inline int64_t SignExtend64(uint64_t X, unsigned B) { return int64_t(X << (64 - B)) >> (64 - B); } +/// \brief Subtract two unsigned integers, X and Y, of type T and return their +/// absolute value. +template <typename T> +typename std::enable_if<std::is_unsigned<T>::value, T>::type +AbsoluteDifference(T X, T Y) { + return std::max(X, Y) - std::min(X, Y); +} + /// \brief Add two unsigned integers, X and Y, of type T. /// Clamp the result to the maximum representable value of T on overflow. /// ResultOverflowed indicates if the result is larger than the maximum |