1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

[PDB] Add BinaryStreamError.

This migrates the stream code away from MSFError to using its
own custom Error class.

llvm-svn: 296494
This commit is contained in:
Zachary Turner 2017-02-28 17:49:34 +00:00
parent 2d8b1cfabe
commit 731b788b16
13 changed files with 184 additions and 80 deletions

View File

@ -14,7 +14,7 @@
#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"
@ -41,21 +41,16 @@ public:
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();
}
@ -119,12 +114,8 @@ public:
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());
@ -156,8 +147,8 @@ private:
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();
}

View File

@ -12,7 +12,7 @@
#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>
@ -45,9 +45,10 @@ public:
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();
}
@ -81,8 +82,7 @@ private:
++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;
}

View File

@ -11,6 +11,7 @@
#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>
@ -43,6 +44,15 @@ public:
/// \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

View File

@ -0,0 +1,47 @@
//===- 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

View File

@ -150,7 +150,8 @@ public:
}
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;
@ -193,16 +194,16 @@ public:
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();
}

View File

@ -12,7 +12,7 @@
#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>
@ -65,6 +65,14 @@ public:
}
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;
@ -98,12 +106,9 @@ public:
/// 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);
}
@ -114,9 +119,8 @@ public:
/// 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;
@ -152,9 +156,9 @@ public:
/// 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);
}

View File

@ -14,6 +14,7 @@
#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"
@ -123,10 +124,9 @@ public:
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()),

View File

@ -0,0 +1,58 @@
//===- 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();
}

View File

@ -9,11 +9,10 @@
#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) {}
@ -74,7 +73,7 @@ Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref) {
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();
@ -82,7 +81,7 @@ Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref, uint32_t Length) {
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();
}

View File

@ -1,4 +1,5 @@
add_llvm_library(LLVMDebugInfoMSF
BinaryStreamError.cpp
BinaryStreamReader.cpp
BinaryStreamWriter.cpp
MappedBlockStream.cpp

View File

@ -9,9 +9,9 @@
#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;
@ -89,10 +89,8 @@ MappedBlockStream::createFpmStream(const MSFLayout &Layout,
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();
@ -169,8 +167,9 @@ Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
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;
@ -244,10 +243,8 @@ Error MappedBlockStream::readBytes(uint32_t Offset,
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;
@ -374,11 +371,8 @@ uint32_t WritableMappedBlockStream::getLength() {
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();

View File

@ -396,11 +396,10 @@ bool PDBFile::hasStringTable() {
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,

View File

@ -42,16 +42,16 @@ public:
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();
}
@ -59,8 +59,8 @@ public:
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();
}