diff options
Diffstat (limited to 'llvm/lib/DebugInfo/CodeView')
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/ByteStream.cpp | 52 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CodeViewError.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/StreamReader.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/StreamWriter.cpp | 77 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeDumper.cpp | 2 |
6 files changed, 133 insertions, 8 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/ByteStream.cpp b/llvm/lib/DebugInfo/CodeView/ByteStream.cpp index c0ac0b7a8ff..83b2f8ec307 100644 --- a/llvm/lib/DebugInfo/CodeView/ByteStream.cpp +++ b/llvm/lib/DebugInfo/CodeView/ByteStream.cpp @@ -15,23 +15,61 @@ using namespace llvm; using namespace llvm::codeview; -ByteStream::ByteStream() {} +static Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Src, + ArrayRef<uint8_t> Dest) { + return make_error<CodeViewError>(cv_error_code::operation_unsupported, + "ByteStream is immutable."); +} -ByteStream::ByteStream(ArrayRef<uint8_t> Data) : Data(Data) {} +static Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Src, + MutableArrayRef<uint8_t> Dest) { + if (Dest.size() < Src.size()) + return make_error<CodeViewError>(cv_error_code::insufficient_buffer); + if (Offset > Src.size() - Dest.size()) + return make_error<CodeViewError>(cv_error_code::insufficient_buffer); -ByteStream::~ByteStream() {} + ::memcpy(Dest.data() + Offset, Src.data(), Src.size()); + return Error::success(); +} -Error ByteStream::readBytes(uint32_t Offset, uint32_t Size, - ArrayRef<uint8_t> &Buffer) const { +template <bool Writable> +Error ByteStream<Writable>::readBytes(uint32_t Offset, uint32_t Size, + ArrayRef<uint8_t> &Buffer) const { + if (Offset > Data.size()) + return make_error<CodeViewError>(cv_error_code::insufficient_buffer); if (Data.size() < Size + Offset) return make_error<CodeViewError>(cv_error_code::insufficient_buffer); Buffer = Data.slice(Offset, Size); return Error::success(); } -uint32_t ByteStream::getLength() const { return Data.size(); } +template <bool Writable> +Error ByteStream<Writable>::readLongestContiguousChunk( + uint32_t Offset, ArrayRef<uint8_t> &Buffer) const { + if (Offset >= Data.size()) + return make_error<CodeViewError>(cv_error_code::insufficient_buffer); + Buffer = Data.slice(Offset); + return Error::success(); +} + +template <bool Writable> +Error ByteStream<Writable>::writeBytes(uint32_t Offset, + ArrayRef<uint8_t> Buffer) const { + return ::writeBytes(Offset, Buffer, Data); +} + +template <bool Writable> uint32_t ByteStream<Writable>::getLength() const { + return Data.size(); +} -StringRef ByteStream::str() const { +template <bool Writable> StringRef ByteStream<Writable>::str() const { const char *CharData = reinterpret_cast<const char *>(Data.data()); return StringRef(CharData, Data.size()); } + +namespace llvm { +namespace codeview { +template class ByteStream<true>; +template class ByteStream<false>; +} +} diff --git a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt index 6c4e09fe4e3..4393f9c52ee 100644 --- a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt @@ -11,6 +11,7 @@ add_llvm_library(LLVMDebugInfoCodeView ModuleSubstreamVisitor.cpp RecordSerialization.cpp StreamReader.cpp + StreamWriter.cpp SymbolDumper.cpp TypeDumper.cpp TypeRecord.cpp diff --git a/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp b/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp index 4db6b2941a6..aad1d8b25cd 100644 --- a/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp +++ b/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp @@ -31,6 +31,8 @@ public: "bytes."; case cv_error_code::corrupt_record: return "The CodeView record is corrupted."; + case cv_error_code::operation_unsupported: + return "The requested operation is not supported."; } llvm_unreachable("Unrecognized cv_error_code"); } diff --git a/llvm/lib/DebugInfo/CodeView/StreamReader.cpp b/llvm/lib/DebugInfo/CodeView/StreamReader.cpp index cc5cebc9c43..64e45487322 100644 --- a/llvm/lib/DebugInfo/CodeView/StreamReader.cpp +++ b/llvm/lib/DebugInfo/CodeView/StreamReader.cpp @@ -17,6 +17,13 @@ using namespace llvm::codeview; StreamReader::StreamReader(StreamRef S) : Stream(S), Offset(0) {} +Error StreamReader::readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer) { + if (auto EC = Stream.readLongestContiguousChunk(Offset, Buffer)) + return EC; + Offset += Buffer.size(); + return Error::success(); +} + Error StreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) { if (auto EC = Stream.readBytes(Offset, Size, Buffer)) return EC; diff --git a/llvm/lib/DebugInfo/CodeView/StreamWriter.cpp b/llvm/lib/DebugInfo/CodeView/StreamWriter.cpp new file mode 100644 index 00000000000..f61c6b522f5 --- /dev/null +++ b/llvm/lib/DebugInfo/CodeView/StreamWriter.cpp @@ -0,0 +1,77 @@ +//===- StreamWrite.cpp - Writes bytes and objects to 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/CodeView/StreamWriter.h" + +#include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/DebugInfo/CodeView/StreamReader.h" +#include "llvm/DebugInfo/CodeView/StreamRef.h" + +using namespace llvm; +using namespace llvm::codeview; + +StreamWriter::StreamWriter(StreamRef S) : Stream(S), Offset(0) {} + +Error StreamWriter::writeBytes(ArrayRef<uint8_t> Buffer) { + if (auto EC = Stream.writeBytes(Offset, Buffer)) + return EC; + Offset += Buffer.size(); + return Error::success(); +} + +Error StreamWriter::writeInteger(uint16_t Int) { + return writeObject(support::ulittle16_t(Int)); +} + +Error StreamWriter::writeInteger(uint32_t Int) { + return writeObject(support::ulittle32_t(Int)); +} + +Error StreamWriter::writeZeroString(StringRef Str) { + if (auto EC = writeFixedString(Str)) + return EC; + if (auto EC = writeObject('\0')) + return EC; + + return Error::success(); +} + +Error StreamWriter::writeFixedString(StringRef Str) { + ArrayRef<uint8_t> Bytes(Str.bytes_begin(), Str.bytes_end()); + if (auto EC = Stream.writeBytes(Offset, Bytes)) + return EC; + + Offset += Str.size(); + return Error::success(); +} + +Error StreamWriter::writeStreamRef(StreamRef Ref) { + if (auto EC = writeStreamRef(Ref, Ref.getLength())) + return EC; + Offset += Ref.getLength(); + return Error::success(); +} + +Error StreamWriter::writeStreamRef(StreamRef Ref, uint32_t Length) { + Ref = Ref.slice(0, Length); + + StreamReader SrcReader(Ref); + // This is a bit tricky. If we just call readBytes, we are requiring that it + // return us the entire stream as a contiguous buffer. For large streams this + // will allocate a huge amount of space from the pool. Instead, iterate over + // each contiguous chunk until we've consumed the entire stream. + while (SrcReader.bytesRemaining() > 0) { + ArrayRef<uint8_t> Chunk; + if (auto EC = SrcReader.readLongestContiguousChunk(Chunk)) + return EC; + if (auto EC = writeBytes(Chunk)) + return EC; + } + return Error::success(); +} diff --git a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp index 2080a63d8bc..42cb0aa1fd2 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp @@ -692,7 +692,7 @@ bool CVTypeDumper::dump(const CVTypeArray &Types) { } bool CVTypeDumper::dump(ArrayRef<uint8_t> Data) { - ByteStream Stream(Data); + ByteStream<> Stream(Data); CVTypeArray Types; StreamReader Reader(Stream); if (auto EC = Reader.readArray(Types, Reader.getLength())) { |