#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/MSF/BinaryStream.h"
-#include "llvm/DebugInfo/MSF/MSFError.h"
+#include "llvm/DebugInfo/MSF/BinaryStreamError.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/MemoryBuffer.h"
Error readBytes(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) override {
- if (Offset > Data.size())
- return make_error<msf::MSFError>(
- msf::msf_error_code::insufficient_buffer);
- if (Data.size() < Size + Offset)
- return make_error<msf::MSFError>(
- msf::msf_error_code::insufficient_buffer);
+ if (auto EC = checkOffset(Offset, Size))
+ return EC;
Buffer = Data.slice(Offset, Size);
return Error::success();
}
Error readLongestContiguousChunk(uint32_t Offset,
ArrayRef<uint8_t> &Buffer) override {
- if (Offset >= Data.size())
- return make_error<msf::MSFError>(
- msf::msf_error_code::insufficient_buffer);
+ if (auto EC = checkOffset(Offset, 1))
+ return EC;
Buffer = Data.slice(Offset);
return Error::success();
}
if (Buffer.empty())
return Error::success();
- if (Data.size() < Buffer.size())
- return make_error<msf::MSFError>(
- msf::msf_error_code::insufficient_buffer);
- if (Offset > Buffer.size() - Data.size())
- return make_error<msf::MSFError>(
- msf::msf_error_code::insufficient_buffer);
+ if (auto EC = checkOffset(Offset, Buffer.size()))
+ return EC;
uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
Error commit() override {
if (FileBuffer->commit())
- return make_error<msf::MSFError>(
- msf::msf_error_code::insufficient_buffer);
+ return make_error<BinaryStreamError>(
+ stream_error_code::filesystem_error);
return Error::success();
}
#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/MSF/BinaryStream.h"
-#include "llvm/DebugInfo/MSF/MSFError.h"
+#include "llvm/DebugInfo/MSF/BinaryStreamError.h"
#include "llvm/Support/Error.h"
#include <cstddef>
#include <cstdint>
if (!ExpectedIndex)
return ExpectedIndex.takeError();
const auto &Item = Items[*ExpectedIndex];
+ if (auto EC = checkOffset(Offset, Size))
+ return EC;
if (Size > Traits::length(Item))
- return make_error<msf::MSFError>(
- msf::msf_error_code::insufficient_buffer);
+ return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
Buffer = Traits::bytes(Item).take_front(Size);
return Error::success();
}
++CurrentIndex;
}
if (CurrentOffset != Offset)
- return make_error<msf::MSFError>(
- msf::msf_error_code::insufficient_buffer);
+ return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
return CurrentIndex;
}
#define LLVM_DEBUGINFO_MSF_BINARYSTREAM_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/MSF/BinaryStreamError.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstdint>
/// \brief Return the number of bytes of data in this stream.
virtual uint32_t getLength() = 0;
+
+protected:
+ Error checkOffset(uint32_t Offset, uint32_t DataSize) {
+ if (Offset > getLength())
+ return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
+ if (getLength() < DataSize + Offset)
+ return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
+ return Error::success();
+ }
};
/// \brief A BinaryStream which can be read from as well as written to. Note
--- /dev/null
+//===- BinaryStreamError.h - Error extensions for Binary Streams *- 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_MSF_BINARYSTREAMERROR_H
+#define LLVM_DEBUGINFO_MSF_BINARYSTREAMERROR_H
+
+#include "llvm/Support/Error.h"
+
+#include <string>
+
+namespace llvm {
+enum class stream_error_code {
+ unspecified,
+ stream_too_short,
+ invalid_array_size,
+ invalid_offset,
+ filesystem_error
+};
+
+/// Base class for errors originating when parsing raw PDB files
+class BinaryStreamError : public ErrorInfo<BinaryStreamError> {
+public:
+ static char ID;
+ explicit BinaryStreamError(stream_error_code C);
+ explicit BinaryStreamError(StringRef Context);
+ BinaryStreamError(stream_error_code C, StringRef Context);
+
+ void log(raw_ostream &OS) const override;
+ std::error_code convertToErrorCode() const override;
+
+ StringRef getErrorMessage() const;
+
+ stream_error_code getErrorCode() const { return Code; }
+
+private:
+ std::string ErrMsg;
+ stream_error_code Code;
+};
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_MSF_BINARYSTREAMERROR_H
}
if (NumElements > UINT32_MAX / sizeof(T))
- return make_error<msf::MSFError>(msf::msf_error_code::insufficient_buffer);
+ return make_error<BinaryStreamError>(
+ stream_error_code::invalid_array_size);
if (auto EC = readBytes(Bytes, NumElements * sizeof(T)))
return EC;
Array = FixedStreamArray<T>();
return Error::success();
}
- uint32_t Length = NumItems * sizeof(T);
- if (Length / sizeof(T) != NumItems)
- return errorCodeToError(
- make_error_code(std::errc::illegal_byte_sequence));
- if (Offset + Length > Stream.getLength())
- return make_error<msf::MSFError>(
- msf::msf_error_code::insufficient_buffer);
- BinaryStreamRef View = Stream.slice(Offset, Length);
+
+ if (NumItems > UINT32_MAX / sizeof(T))
+ return make_error<BinaryStreamError>(
+ stream_error_code::invalid_array_size);
+
+ BinaryStreamRef View;
+ if (auto EC = readStreamRef(View, NumItems * sizeof(T)))
+ return EC;
+
Array = FixedStreamArray<T>(View);
- Offset += Length;
return Error::success();
}
#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/MSF/BinaryStream.h"
-#include "llvm/DebugInfo/MSF/MSFError.h"
+#include "llvm/DebugInfo/MSF/BinaryStreamError.h"
#include "llvm/Support/Error.h"
#include <algorithm>
#include <cstdint>
}
protected:
+ Error checkOffset(uint32_t Offset, uint32_t DataSize) const {
+ if (Offset > getLength())
+ return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
+ if (getLength() < DataSize + Offset)
+ return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
+ return Error::success();
+ }
+
StreamType *Stream;
uint32_t ViewOffset;
uint32_t Length;
/// the data, and an appropriate error code otherwise.
Error readBytes(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) const {
- if (ViewOffset + Offset < Offset)
- return make_error<msf::MSFError>(
- msf::msf_error_code::insufficient_buffer);
- if (Size + Offset > Length)
- return make_error<msf::MSFError>(
- msf::msf_error_code::insufficient_buffer);
+ if (auto EC = checkOffset(Offset, Size))
+ return EC;
+
return Stream->readBytes(ViewOffset + Offset, Size, Buffer);
}
/// and an appropriate error code otherwise.
Error readLongestContiguousChunk(uint32_t Offset,
ArrayRef<uint8_t> &Buffer) const {
- if (Offset >= Length)
- return make_error<msf::MSFError>(
- msf::msf_error_code::insufficient_buffer);
+ if (auto EC = checkOffset(Offset, 1))
+ return EC;
if (auto EC = Stream->readLongestContiguousChunk(Offset, Buffer))
return EC;
/// stream at the specified location and the implementation could write the
/// data, and an appropriate error code otherwise.
Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const {
- if (Data.size() + Offset > Length)
- return make_error<msf::MSFError>(
- msf::msf_error_code::insufficient_buffer);
+ if (auto EC = checkOffset(Offset, Data.size()))
+ return EC;
+
return Stream->writeBytes(ViewOffset + Offset, Data);
}
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
+#include "llvm/DebugInfo/MSF/BinaryStreamError.h"
#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
template <typename T> Error writeArray(ArrayRef<T> Array) {
if (Array.empty())
return Error::success();
-
if (Array.size() > UINT32_MAX / sizeof(T))
- return make_error<msf::MSFError>(
- msf::msf_error_code::insufficient_buffer);
+ return make_error<BinaryStreamError>(
+ stream_error_code::invalid_array_size);
return writeBytes(
ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Array.data()),
--- /dev/null
+//===- BinaryStreamError.cpp - Error extensions for streams -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/MSF/BinaryStreamError.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+char BinaryStreamError::ID = 0;
+
+BinaryStreamError::BinaryStreamError(stream_error_code C)
+ : BinaryStreamError(C, "") {}
+
+BinaryStreamError::BinaryStreamError(StringRef Context)
+ : BinaryStreamError(stream_error_code::unspecified, Context) {}
+
+BinaryStreamError::BinaryStreamError(stream_error_code C, StringRef Context)
+ : Code(C) {
+ ErrMsg = "Stream Error: ";
+ switch (C) {
+ case stream_error_code::unspecified:
+ ErrMsg += "An unspecified error has occurred.";
+ break;
+ case stream_error_code::stream_too_short:
+ ErrMsg += "The stream is too short to perform the requested operation.";
+ break;
+ case stream_error_code::invalid_array_size:
+ ErrMsg += "The buffer size is not a multiple of the array element size.";
+ break;
+ case stream_error_code::invalid_offset:
+ ErrMsg += "The specified offset is invalid for the current stream.";
+ break;
+ case stream_error_code::filesystem_error:
+ ErrMsg += "An I/O error occurred on the file system.";
+ break;
+ default:
+ llvm_unreachable("Unreachable!");
+ }
+
+ if (!Context.empty()) {
+ ErrMsg += " ";
+ ErrMsg += Context;
+ }
+}
+
+void BinaryStreamError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; }
+
+StringRef BinaryStreamError::getErrorMessage() const { return ErrMsg; }
+
+std::error_code BinaryStreamError::convertToErrorCode() const {
+ return inconvertibleErrorCode();
+}
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
+#include "llvm/DebugInfo/MSF/BinaryStreamError.h"
#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
-#include "llvm/DebugInfo/MSF/MSFError.h"
using namespace llvm;
-using namespace llvm::msf;
BinaryStreamReader::BinaryStreamReader(BinaryStreamRef S)
: Stream(S), Offset(0) {}
Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref, uint32_t Length) {
if (bytesRemaining() < Length)
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
Ref = Stream.slice(Offset, Length);
Offset += Length;
return Error::success();
Error BinaryStreamReader::skip(uint32_t Amount) {
if (Amount > bytesRemaining())
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
Offset += Amount;
return Error::success();
}
add_llvm_library(LLVMDebugInfoMSF
+ BinaryStreamError.cpp
BinaryStreamReader.cpp
BinaryStreamWriter.cpp
MappedBlockStream.cpp
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/MSF/BinaryStreamError.h"
#include "llvm/DebugInfo/MSF/IMSFFile.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
-#include "llvm/DebugInfo/MSF/MSFError.h"
#include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
using namespace llvm;
Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) {
// Make sure we aren't trying to read beyond the end of the stream.
- if (Size > StreamLayout.Length)
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
- if (Offset > StreamLayout.Length - Size)
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ if (auto EC = checkOffset(Offset, Size))
+ return EC;
if (tryReadContiguously(Offset, Size, Buffer))
return Error::success();
Error MappedBlockStream::readLongestContiguousChunk(uint32_t Offset,
ArrayRef<uint8_t> &Buffer) {
// Make sure we aren't trying to read beyond the end of the stream.
- if (Offset >= StreamLayout.Length)
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ if (auto EC = checkOffset(Offset, 1))
+ return EC;
+
uint32_t First = Offset / BlockSize;
uint32_t Last = First;
uint32_t OffsetInBlock = Offset % BlockSize;
// Make sure we aren't trying to read beyond the end of the stream.
- if (Buffer.size() > StreamLayout.Length)
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
- if (Offset > StreamLayout.Length - Buffer.size())
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ if (auto EC = checkOffset(Offset, Buffer.size()))
+ return EC;
uint32_t BytesLeft = Buffer.size();
uint32_t BytesWritten = 0;
Error WritableMappedBlockStream::writeBytes(uint32_t Offset,
ArrayRef<uint8_t> Buffer) {
// Make sure we aren't trying to write beyond the end of the stream.
- if (Buffer.size() > getStreamLength())
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
-
- if (Offset > getStreamLayout().Length - Buffer.size())
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ if (auto EC = checkOffset(Offset, Buffer.size()))
+ return EC;
uint32_t BlockNum = Offset / getBlockSize();
uint32_t OffsetInBlock = Offset % getBlockSize();
return IS->getNamedStreamIndex("/names") < getNumStreams();
}
-/// Wrapper around MappedBlockStream::createIndexedStream()
-/// that checks if a stream with that index actually exists.
-/// If it does not, the return value will have an MSFError with
-/// code msf_error_code::no_stream. Else, the return value will
-/// contain the stream returned by createIndexedStream().
+/// Wrapper around MappedBlockStream::createIndexedStream() that checks if a
+/// stream with that index actually exists. If it does not, the return value
+/// will have an MSFError with code msf_error_code::no_stream. Else, the return
+/// value will contain the stream returned by createIndexedStream().
Expected<std::unique_ptr<MappedBlockStream>>
PDBFile::safelyCreateIndexedStream(const MSFLayout &Layout,
BinaryStreamRef MsfData,
Error readBytes(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) override {
- if (Offset + Size > Data.size())
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ if (auto EC = checkOffset(Offset, Size))
+ return EC;
Buffer = Data.slice(Offset, Size);
return Error::success();
}
Error readLongestContiguousChunk(uint32_t Offset,
ArrayRef<uint8_t> &Buffer) override {
- if (Offset >= Data.size())
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ if (auto EC = checkOffset(Offset, 1))
+ return EC;
Buffer = Data.drop_front(Offset);
return Error::success();
}
uint32_t getLength() override { return Data.size(); }
Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> SrcData) override {
- if (Offset + SrcData.size() > Data.size())
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ if (auto EC = checkOffset(Offset, SrcData.size()))
+ return EC;
::memcpy(&Data[Offset], SrcData.data(), SrcData.size());
return Error::success();
}