summaryrefslogtreecommitdiffstats
path: root/llvm/lib/DebugInfo/CodeView
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/DebugInfo/CodeView')
-rw-r--r--llvm/lib/DebugInfo/CodeView/ByteStream.cpp52
-rw-r--r--llvm/lib/DebugInfo/CodeView/CMakeLists.txt1
-rw-r--r--llvm/lib/DebugInfo/CodeView/CodeViewError.cpp2
-rw-r--r--llvm/lib/DebugInfo/CodeView/StreamReader.cpp7
-rw-r--r--llvm/lib/DebugInfo/CodeView/StreamWriter.cpp77
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeDumper.cpp2
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())) {
OpenPOWER on IntegriCloud