mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-27 21:50:40 +00:00
Revert r296215, "[PDB] General improvements to Stream library." and followings.
r296215, "[PDB] General improvements to Stream library." r296217, "Disable BinaryStreamTest.StreamReaderObject temporarily." r296220, "Re-enable BinaryStreamTest.StreamReaderObject." r296244, "[PDB] Disable some tests that are breaking bots." r296249, "Add static_cast to silence -Wc++11-narrowing." std::errc::no_buffer_space should be used for OS-oriented errors for socket transmission. (Seek discussions around llvm/xray.) I could substitute s/no_buffer_space/others/g, but I revert whole them ATM. Could we define and use LLVM errors there? git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296258 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2a05efcebd
commit
96678fa6d8
@ -640,16 +640,6 @@ detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) {
|
|||||||
// Extra additions to <utility>
|
// Extra additions to <utility>
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// \brief Template class to compute the sum of sizes of all items in a
|
|
||||||
/// parameter pack.
|
|
||||||
template <typename T, typename... Ts> struct sizeof_sum {
|
|
||||||
static const size_t value = sizeof(T) + sizeof_sum<Ts...>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T> struct sizeof_sum<T> {
|
|
||||||
static const size_t value = sizeof(T);
|
|
||||||
};
|
|
||||||
|
|
||||||
/// \brief Function object to check whether the first component of a std::pair
|
/// \brief Function object to check whether the first component of a std::pair
|
||||||
/// compares less than the first component of another std::pair.
|
/// compares less than the first component of another std::pair.
|
||||||
struct less_first {
|
struct less_first {
|
||||||
|
@ -48,13 +48,15 @@ public:
|
|||||||
|
|
||||||
} // end namespace codeview
|
} // end namespace codeview
|
||||||
|
|
||||||
|
namespace msf {
|
||||||
|
|
||||||
template <typename Kind>
|
template <typename Kind>
|
||||||
struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> {
|
struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> {
|
||||||
Error operator()(BinaryStreamRef Stream, uint32_t &Len,
|
Error operator()(ReadableStreamRef Stream, uint32_t &Len,
|
||||||
codeview::CVRecord<Kind> &Item) const {
|
codeview::CVRecord<Kind> &Item) const {
|
||||||
using namespace codeview;
|
using namespace codeview;
|
||||||
const RecordPrefix *Prefix = nullptr;
|
const RecordPrefix *Prefix = nullptr;
|
||||||
BinaryStreamReader Reader(Stream);
|
StreamReader Reader(Stream);
|
||||||
uint32_t Offset = Reader.getOffset();
|
uint32_t Offset = Reader.getOffset();
|
||||||
|
|
||||||
if (auto EC = Reader.readObject(Prefix))
|
if (auto EC = Reader.readObject(Prefix))
|
||||||
@ -74,6 +76,8 @@ struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end namespace msf
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H
|
#endif // LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H
|
||||||
|
@ -34,7 +34,7 @@ public:
|
|||||||
Error visitTypeStream(CVTypeRange Types);
|
Error visitTypeStream(CVTypeRange Types);
|
||||||
|
|
||||||
Error visitFieldListMemberStream(ArrayRef<uint8_t> FieldList);
|
Error visitFieldListMemberStream(ArrayRef<uint8_t> FieldList);
|
||||||
Error visitFieldListMemberStream(BinaryStreamReader Reader);
|
Error visitFieldListMemberStream(msf::StreamReader Reader);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// The interface to the class that gets notified of each visitation.
|
/// The interface to the class that gets notified of each visitation.
|
||||||
|
@ -33,8 +33,8 @@ class CodeViewRecordIO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CodeViewRecordIO(BinaryStreamReader &Reader) : Reader(&Reader) {}
|
explicit CodeViewRecordIO(msf::StreamReader &Reader) : Reader(&Reader) {}
|
||||||
explicit CodeViewRecordIO(BinaryStreamWriter &Writer) : Writer(&Writer) {}
|
explicit CodeViewRecordIO(msf::StreamWriter &Writer) : Writer(&Writer) {}
|
||||||
|
|
||||||
Error beginRecord(Optional<uint32_t> MaxLength);
|
Error beginRecord(Optional<uint32_t> MaxLength);
|
||||||
Error endRecord();
|
Error endRecord();
|
||||||
@ -59,9 +59,9 @@ public:
|
|||||||
|
|
||||||
template <typename T> Error mapInteger(T &Value) {
|
template <typename T> Error mapInteger(T &Value) {
|
||||||
if (isWriting())
|
if (isWriting())
|
||||||
return Writer->writeInteger(Value);
|
return Writer->writeInteger(Value, llvm::support::little);
|
||||||
|
|
||||||
return Reader->readInteger(Value);
|
return Reader->readInteger(Value, llvm::support::little);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> Error mapEnum(T &Value) {
|
template <typename T> Error mapEnum(T &Value) {
|
||||||
@ -93,7 +93,7 @@ public:
|
|||||||
SizeType Size;
|
SizeType Size;
|
||||||
if (isWriting()) {
|
if (isWriting()) {
|
||||||
Size = static_cast<SizeType>(Items.size());
|
Size = static_cast<SizeType>(Items.size());
|
||||||
if (auto EC = Writer->writeInteger(Size))
|
if (auto EC = Writer->writeInteger(Size, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
for (auto &X : Items) {
|
for (auto &X : Items) {
|
||||||
@ -101,7 +101,7 @@ public:
|
|||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (auto EC = Reader->readInteger(Size))
|
if (auto EC = Reader->readInteger(Size, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
for (SizeType I = 0; I < Size; ++I) {
|
for (SizeType I = 0; I < Size; ++I) {
|
||||||
typename T::value_type Item;
|
typename T::value_type Item;
|
||||||
@ -160,8 +160,8 @@ private:
|
|||||||
|
|
||||||
SmallVector<RecordLimit, 2> Limits;
|
SmallVector<RecordLimit, 2> Limits;
|
||||||
|
|
||||||
BinaryStreamReader *Reader = nullptr;
|
msf::StreamReader *Reader = nullptr;
|
||||||
BinaryStreamWriter *Writer = nullptr;
|
msf::StreamWriter *Writer = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace codeview
|
} // end namespace codeview
|
||||||
|
@ -59,22 +59,23 @@ struct ColumnNumberEntry {
|
|||||||
class ModuleSubstream {
|
class ModuleSubstream {
|
||||||
public:
|
public:
|
||||||
ModuleSubstream();
|
ModuleSubstream();
|
||||||
ModuleSubstream(ModuleSubstreamKind Kind, BinaryStreamRef Data);
|
ModuleSubstream(ModuleSubstreamKind Kind, msf::ReadableStreamRef Data);
|
||||||
static Error initialize(BinaryStreamRef Stream, ModuleSubstream &Info);
|
static Error initialize(msf::ReadableStreamRef Stream, ModuleSubstream &Info);
|
||||||
uint32_t getRecordLength() const;
|
uint32_t getRecordLength() const;
|
||||||
ModuleSubstreamKind getSubstreamKind() const;
|
ModuleSubstreamKind getSubstreamKind() const;
|
||||||
BinaryStreamRef getRecordData() const;
|
msf::ReadableStreamRef getRecordData() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ModuleSubstreamKind Kind;
|
ModuleSubstreamKind Kind;
|
||||||
BinaryStreamRef Data;
|
msf::ReadableStreamRef Data;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef VarStreamArray<ModuleSubstream> ModuleSubstreamArray;
|
typedef msf::VarStreamArray<ModuleSubstream> ModuleSubstreamArray;
|
||||||
} // namespace codeview
|
} // namespace codeview
|
||||||
|
|
||||||
|
namespace msf {
|
||||||
template <> struct VarStreamArrayExtractor<codeview::ModuleSubstream> {
|
template <> struct VarStreamArrayExtractor<codeview::ModuleSubstream> {
|
||||||
Error operator()(BinaryStreamRef Stream, uint32_t &Length,
|
Error operator()(ReadableStreamRef Stream, uint32_t &Length,
|
||||||
codeview::ModuleSubstream &Info) const {
|
codeview::ModuleSubstream &Info) const {
|
||||||
if (auto EC = codeview::ModuleSubstream::initialize(Stream, Info))
|
if (auto EC = codeview::ModuleSubstream::initialize(Stream, Info))
|
||||||
return EC;
|
return EC;
|
||||||
@ -82,6 +83,7 @@ template <> struct VarStreamArrayExtractor<codeview::ModuleSubstream> {
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
} // namespace msf
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAM_H
|
#endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAM_H
|
||||||
|
@ -28,8 +28,8 @@ namespace codeview {
|
|||||||
|
|
||||||
struct LineColumnEntry {
|
struct LineColumnEntry {
|
||||||
support::ulittle32_t NameIndex;
|
support::ulittle32_t NameIndex;
|
||||||
FixedStreamArray<LineNumberEntry> LineNumbers;
|
msf::FixedStreamArray<LineNumberEntry> LineNumbers;
|
||||||
FixedStreamArray<ColumnNumberEntry> Columns;
|
msf::FixedStreamArray<ColumnNumberEntry> Columns;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FileChecksumEntry {
|
struct FileChecksumEntry {
|
||||||
@ -38,47 +38,49 @@ struct FileChecksumEntry {
|
|||||||
ArrayRef<uint8_t> Checksum; // The bytes of the checksum.
|
ArrayRef<uint8_t> Checksum; // The bytes of the checksum.
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef VarStreamArray<LineColumnEntry> LineInfoArray;
|
typedef msf::VarStreamArray<LineColumnEntry> LineInfoArray;
|
||||||
typedef VarStreamArray<FileChecksumEntry> FileChecksumArray;
|
typedef msf::VarStreamArray<FileChecksumEntry> FileChecksumArray;
|
||||||
|
|
||||||
class IModuleSubstreamVisitor {
|
class IModuleSubstreamVisitor {
|
||||||
public:
|
public:
|
||||||
virtual ~IModuleSubstreamVisitor() = default;
|
virtual ~IModuleSubstreamVisitor() = default;
|
||||||
|
|
||||||
virtual Error visitUnknown(ModuleSubstreamKind Kind,
|
virtual Error visitUnknown(ModuleSubstreamKind Kind,
|
||||||
BinaryStreamRef Data) = 0;
|
msf::ReadableStreamRef Data) = 0;
|
||||||
virtual Error visitSymbols(BinaryStreamRef Data);
|
virtual Error visitSymbols(msf::ReadableStreamRef Data);
|
||||||
virtual Error visitLines(BinaryStreamRef Data,
|
virtual Error visitLines(msf::ReadableStreamRef Data,
|
||||||
const LineSubstreamHeader *Header,
|
const LineSubstreamHeader *Header,
|
||||||
const LineInfoArray &Lines);
|
const LineInfoArray &Lines);
|
||||||
virtual Error visitStringTable(BinaryStreamRef Data);
|
virtual Error visitStringTable(msf::ReadableStreamRef Data);
|
||||||
virtual Error visitFileChecksums(BinaryStreamRef Data,
|
virtual Error visitFileChecksums(msf::ReadableStreamRef Data,
|
||||||
const FileChecksumArray &Checksums);
|
const FileChecksumArray &Checksums);
|
||||||
virtual Error visitFrameData(BinaryStreamRef Data);
|
virtual Error visitFrameData(msf::ReadableStreamRef Data);
|
||||||
virtual Error visitInlineeLines(BinaryStreamRef Data);
|
virtual Error visitInlineeLines(msf::ReadableStreamRef Data);
|
||||||
virtual Error visitCrossScopeImports(BinaryStreamRef Data);
|
virtual Error visitCrossScopeImports(msf::ReadableStreamRef Data);
|
||||||
virtual Error visitCrossScopeExports(BinaryStreamRef Data);
|
virtual Error visitCrossScopeExports(msf::ReadableStreamRef Data);
|
||||||
virtual Error visitILLines(BinaryStreamRef Data);
|
virtual Error visitILLines(msf::ReadableStreamRef Data);
|
||||||
virtual Error visitFuncMDTokenMap(BinaryStreamRef Data);
|
virtual Error visitFuncMDTokenMap(msf::ReadableStreamRef Data);
|
||||||
virtual Error visitTypeMDTokenMap(BinaryStreamRef Data);
|
virtual Error visitTypeMDTokenMap(msf::ReadableStreamRef Data);
|
||||||
virtual Error visitMergedAssemblyInput(BinaryStreamRef Data);
|
virtual Error visitMergedAssemblyInput(msf::ReadableStreamRef Data);
|
||||||
virtual Error visitCoffSymbolRVA(BinaryStreamRef Data);
|
virtual Error visitCoffSymbolRVA(msf::ReadableStreamRef Data);
|
||||||
};
|
};
|
||||||
|
|
||||||
Error visitModuleSubstream(const ModuleSubstream &R,
|
Error visitModuleSubstream(const ModuleSubstream &R,
|
||||||
IModuleSubstreamVisitor &V);
|
IModuleSubstreamVisitor &V);
|
||||||
} // end namespace codeview
|
} // end namespace codeview
|
||||||
|
|
||||||
|
namespace msf {
|
||||||
|
|
||||||
template <> class VarStreamArrayExtractor<codeview::LineColumnEntry> {
|
template <> class VarStreamArrayExtractor<codeview::LineColumnEntry> {
|
||||||
public:
|
public:
|
||||||
VarStreamArrayExtractor(const codeview::LineSubstreamHeader *Header)
|
VarStreamArrayExtractor(const codeview::LineSubstreamHeader *Header)
|
||||||
: Header(Header) {}
|
: Header(Header) {}
|
||||||
|
|
||||||
Error operator()(BinaryStreamRef Stream, uint32_t &Len,
|
Error operator()(ReadableStreamRef Stream, uint32_t &Len,
|
||||||
codeview::LineColumnEntry &Item) const {
|
codeview::LineColumnEntry &Item) const {
|
||||||
using namespace codeview;
|
using namespace codeview;
|
||||||
const LineFileBlockHeader *BlockHeader;
|
const LineFileBlockHeader *BlockHeader;
|
||||||
BinaryStreamReader Reader(Stream);
|
StreamReader Reader(Stream);
|
||||||
if (auto EC = Reader.readObject(BlockHeader))
|
if (auto EC = Reader.readObject(BlockHeader))
|
||||||
return EC;
|
return EC;
|
||||||
bool HasColumn = Header->Flags & LineFlags::HaveColumns;
|
bool HasColumn = Header->Flags & LineFlags::HaveColumns;
|
||||||
@ -111,11 +113,11 @@ private:
|
|||||||
|
|
||||||
template <> class VarStreamArrayExtractor<codeview::FileChecksumEntry> {
|
template <> class VarStreamArrayExtractor<codeview::FileChecksumEntry> {
|
||||||
public:
|
public:
|
||||||
Error operator()(BinaryStreamRef Stream, uint32_t &Len,
|
Error operator()(ReadableStreamRef Stream, uint32_t &Len,
|
||||||
codeview::FileChecksumEntry &Item) const {
|
codeview::FileChecksumEntry &Item) const {
|
||||||
using namespace codeview;
|
using namespace codeview;
|
||||||
const FileChecksum *Header;
|
const FileChecksum *Header;
|
||||||
BinaryStreamReader Reader(Stream);
|
StreamReader Reader(Stream);
|
||||||
if (auto EC = Reader.readObject(Header))
|
if (auto EC = Reader.readObject(Header))
|
||||||
return EC;
|
return EC;
|
||||||
Item.FileNameOffset = Header->FileNameOffset;
|
Item.FileNameOffset = Header->FileNameOffset;
|
||||||
@ -127,6 +129,8 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end namespace msf
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H
|
#endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H
|
||||||
|
@ -41,37 +41,37 @@ struct RecordPrefix {
|
|||||||
StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData);
|
StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData);
|
||||||
StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData);
|
StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData);
|
||||||
|
|
||||||
inline Error consume(BinaryStreamReader &Reader) { return Error::success(); }
|
inline Error consume(msf::StreamReader &Reader) { return Error::success(); }
|
||||||
|
|
||||||
/// Decodes a numeric "leaf" value. These are integer literals encountered in
|
/// Decodes a numeric "leaf" value. These are integer literals encountered in
|
||||||
/// the type stream. If the value is positive and less than LF_NUMERIC (1 <<
|
/// the type stream. If the value is positive and less than LF_NUMERIC (1 <<
|
||||||
/// 15), it is emitted directly in Data. Otherwise, it has a tag like LF_CHAR
|
/// 15), it is emitted directly in Data. Otherwise, it has a tag like LF_CHAR
|
||||||
/// that indicates the bitwidth and sign of the numeric data.
|
/// that indicates the bitwidth and sign of the numeric data.
|
||||||
Error consume(BinaryStreamReader &Reader, APSInt &Num);
|
Error consume(msf::StreamReader &Reader, APSInt &Num);
|
||||||
|
|
||||||
/// Decodes a numeric leaf value that is known to be a particular type.
|
/// Decodes a numeric leaf value that is known to be a particular type.
|
||||||
Error consume_numeric(BinaryStreamReader &Reader, uint64_t &Value);
|
Error consume_numeric(msf::StreamReader &Reader, uint64_t &Value);
|
||||||
|
|
||||||
/// Decodes signed and unsigned fixed-length integers.
|
/// Decodes signed and unsigned fixed-length integers.
|
||||||
Error consume(BinaryStreamReader &Reader, uint32_t &Item);
|
Error consume(msf::StreamReader &Reader, uint32_t &Item);
|
||||||
Error consume(BinaryStreamReader &Reader, int32_t &Item);
|
Error consume(msf::StreamReader &Reader, int32_t &Item);
|
||||||
|
|
||||||
/// Decodes a null terminated string.
|
/// Decodes a null terminated string.
|
||||||
Error consume(BinaryStreamReader &Reader, StringRef &Item);
|
Error consume(msf::StreamReader &Reader, StringRef &Item);
|
||||||
|
|
||||||
Error consume(StringRef &Data, APSInt &Num);
|
Error consume(StringRef &Data, APSInt &Num);
|
||||||
Error consume(StringRef &Data, uint32_t &Item);
|
Error consume(StringRef &Data, uint32_t &Item);
|
||||||
|
|
||||||
/// Decodes an arbitrary object whose layout matches that of the underlying
|
/// Decodes an arbitrary object whose layout matches that of the underlying
|
||||||
/// byte sequence, and returns a pointer to the object.
|
/// byte sequence, and returns a pointer to the object.
|
||||||
template <typename T> Error consume(BinaryStreamReader &Reader, T *&Item) {
|
template <typename T> Error consume(msf::StreamReader &Reader, T *&Item) {
|
||||||
return Reader.readObject(Item);
|
return Reader.readObject(Item);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename U> struct serialize_conditional_impl {
|
template <typename T, typename U> struct serialize_conditional_impl {
|
||||||
serialize_conditional_impl(T &Item, U Func) : Item(Item), Func(Func) {}
|
serialize_conditional_impl(T &Item, U Func) : Item(Item), Func(Func) {}
|
||||||
|
|
||||||
Error deserialize(BinaryStreamReader &Reader) const {
|
Error deserialize(msf::StreamReader &Reader) const {
|
||||||
if (!Func())
|
if (!Func())
|
||||||
return Error::success();
|
return Error::success();
|
||||||
return consume(Reader, Item);
|
return consume(Reader, Item);
|
||||||
@ -89,7 +89,7 @@ serialize_conditional_impl<T, U> serialize_conditional(T &Item, U Func) {
|
|||||||
template <typename T, typename U> struct serialize_array_impl {
|
template <typename T, typename U> struct serialize_array_impl {
|
||||||
serialize_array_impl(ArrayRef<T> &Item, U Func) : Item(Item), Func(Func) {}
|
serialize_array_impl(ArrayRef<T> &Item, U Func) : Item(Item), Func(Func) {}
|
||||||
|
|
||||||
Error deserialize(BinaryStreamReader &Reader) const {
|
Error deserialize(msf::StreamReader &Reader) const {
|
||||||
return Reader.readArray(Item, Func());
|
return Reader.readArray(Item, Func());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ template <typename T, typename U> struct serialize_array_impl {
|
|||||||
template <typename T> struct serialize_vector_tail_impl {
|
template <typename T> struct serialize_vector_tail_impl {
|
||||||
serialize_vector_tail_impl(std::vector<T> &Item) : Item(Item) {}
|
serialize_vector_tail_impl(std::vector<T> &Item) : Item(Item) {}
|
||||||
|
|
||||||
Error deserialize(BinaryStreamReader &Reader) const {
|
Error deserialize(msf::StreamReader &Reader) const {
|
||||||
T Field;
|
T Field;
|
||||||
// Stop when we run out of bytes or we hit record padding bytes.
|
// Stop when we run out of bytes or we hit record padding bytes.
|
||||||
while (!Reader.empty() && Reader.peek() < LF_PAD0) {
|
while (!Reader.empty() && Reader.peek() < LF_PAD0) {
|
||||||
@ -118,14 +118,14 @@ struct serialize_null_term_string_array_impl {
|
|||||||
serialize_null_term_string_array_impl(std::vector<StringRef> &Item)
|
serialize_null_term_string_array_impl(std::vector<StringRef> &Item)
|
||||||
: Item(Item) {}
|
: Item(Item) {}
|
||||||
|
|
||||||
Error deserialize(BinaryStreamReader &Reader) const {
|
Error deserialize(msf::StreamReader &Reader) const {
|
||||||
if (Reader.empty())
|
if (Reader.empty())
|
||||||
return make_error<CodeViewError>(cv_error_code::insufficient_buffer,
|
return make_error<CodeViewError>(cv_error_code::insufficient_buffer,
|
||||||
"Null terminated string is empty!");
|
"Null terminated string is empty!");
|
||||||
|
|
||||||
while (Reader.peek() != 0) {
|
while (Reader.peek() != 0) {
|
||||||
StringRef Field;
|
StringRef Field;
|
||||||
if (auto EC = Reader.readCString(Field))
|
if (auto EC = Reader.readZeroString(Field))
|
||||||
return EC;
|
return EC;
|
||||||
Item.push_back(Field);
|
Item.push_back(Field);
|
||||||
}
|
}
|
||||||
@ -138,7 +138,7 @@ struct serialize_null_term_string_array_impl {
|
|||||||
template <typename T> struct serialize_arrayref_tail_impl {
|
template <typename T> struct serialize_arrayref_tail_impl {
|
||||||
serialize_arrayref_tail_impl(ArrayRef<T> &Item) : Item(Item) {}
|
serialize_arrayref_tail_impl(ArrayRef<T> &Item) : Item(Item) {}
|
||||||
|
|
||||||
Error deserialize(BinaryStreamReader &Reader) const {
|
Error deserialize(msf::StreamReader &Reader) const {
|
||||||
uint32_t Count = Reader.bytesRemaining() / sizeof(T);
|
uint32_t Count = Reader.bytesRemaining() / sizeof(T);
|
||||||
return Reader.readArray(Item, Count);
|
return Reader.readArray(Item, Count);
|
||||||
}
|
}
|
||||||
@ -149,7 +149,7 @@ template <typename T> struct serialize_arrayref_tail_impl {
|
|||||||
template <typename T> struct serialize_numeric_impl {
|
template <typename T> struct serialize_numeric_impl {
|
||||||
serialize_numeric_impl(T &Item) : Item(Item) {}
|
serialize_numeric_impl(T &Item) : Item(Item) {}
|
||||||
|
|
||||||
Error deserialize(BinaryStreamReader &Reader) const {
|
Error deserialize(msf::StreamReader &Reader) const {
|
||||||
return consume_numeric(Reader, Item);
|
return consume_numeric(Reader, Item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,42 +201,42 @@ template <typename T> serialize_numeric_impl<T> serialize_numeric(T &Item) {
|
|||||||
#define CV_NUMERIC_FIELD(I) serialize_numeric(I)
|
#define CV_NUMERIC_FIELD(I) serialize_numeric(I)
|
||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
Error consume(BinaryStreamReader &Reader,
|
Error consume(msf::StreamReader &Reader,
|
||||||
const serialize_conditional_impl<T, U> &Item) {
|
const serialize_conditional_impl<T, U> &Item) {
|
||||||
return Item.deserialize(Reader);
|
return Item.deserialize(Reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
Error consume(BinaryStreamReader &Reader,
|
Error consume(msf::StreamReader &Reader,
|
||||||
const serialize_array_impl<T, U> &Item) {
|
const serialize_array_impl<T, U> &Item) {
|
||||||
return Item.deserialize(Reader);
|
return Item.deserialize(Reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Error consume(BinaryStreamReader &Reader,
|
inline Error consume(msf::StreamReader &Reader,
|
||||||
const serialize_null_term_string_array_impl &Item) {
|
const serialize_null_term_string_array_impl &Item) {
|
||||||
return Item.deserialize(Reader);
|
return Item.deserialize(Reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Error consume(BinaryStreamReader &Reader,
|
Error consume(msf::StreamReader &Reader,
|
||||||
const serialize_vector_tail_impl<T> &Item) {
|
const serialize_vector_tail_impl<T> &Item) {
|
||||||
return Item.deserialize(Reader);
|
return Item.deserialize(Reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Error consume(BinaryStreamReader &Reader,
|
Error consume(msf::StreamReader &Reader,
|
||||||
const serialize_arrayref_tail_impl<T> &Item) {
|
const serialize_arrayref_tail_impl<T> &Item) {
|
||||||
return Item.deserialize(Reader);
|
return Item.deserialize(Reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Error consume(BinaryStreamReader &Reader,
|
Error consume(msf::StreamReader &Reader,
|
||||||
const serialize_numeric_impl<T> &Item) {
|
const serialize_numeric_impl<T> &Item) {
|
||||||
return Item.deserialize(Reader);
|
return Item.deserialize(Reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename U, typename... Args>
|
template <typename T, typename U, typename... Args>
|
||||||
Error consume(BinaryStreamReader &Reader, T &&X, U &&Y, Args &&... Rest) {
|
Error consume(msf::StreamReader &Reader, T &&X, U &&Y, Args &&... Rest) {
|
||||||
if (auto EC = consume(Reader, X))
|
if (auto EC = consume(Reader, X))
|
||||||
return EC;
|
return EC;
|
||||||
return consume(Reader, Y, std::forward<Args>(Rest)...);
|
return consume(Reader, Y, std::forward<Args>(Rest)...);
|
||||||
|
@ -25,11 +25,10 @@ class SymbolVisitorDelegate;
|
|||||||
class SymbolDeserializer : public SymbolVisitorCallbacks {
|
class SymbolDeserializer : public SymbolVisitorCallbacks {
|
||||||
struct MappingInfo {
|
struct MappingInfo {
|
||||||
explicit MappingInfo(ArrayRef<uint8_t> RecordData)
|
explicit MappingInfo(ArrayRef<uint8_t> RecordData)
|
||||||
: Stream(RecordData, llvm::support::little), Reader(Stream),
|
: Stream(RecordData), Reader(Stream), Mapping(Reader) {}
|
||||||
Mapping(Reader) {}
|
|
||||||
|
|
||||||
BinaryByteStream Stream;
|
msf::ByteStream Stream;
|
||||||
BinaryStreamReader Reader;
|
msf::StreamReader Reader;
|
||||||
SymbolRecordMapping Mapping;
|
SymbolRecordMapping Mapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -938,7 +938,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef CVRecord<SymbolKind> CVSymbol;
|
typedef CVRecord<SymbolKind> CVSymbol;
|
||||||
typedef VarStreamArray<CVSymbol> CVSymbolArray;
|
typedef msf::VarStreamArray<CVSymbol> CVSymbolArray;
|
||||||
|
|
||||||
} // end namespace codeview
|
} // end namespace codeview
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@ -14,14 +14,16 @@
|
|||||||
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
|
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class BinaryStreamReader;
|
namespace msf {
|
||||||
class BinaryStreamWriter;
|
class StreamReader;
|
||||||
|
class StreamWriter;
|
||||||
|
}
|
||||||
|
|
||||||
namespace codeview {
|
namespace codeview {
|
||||||
class SymbolRecordMapping : public SymbolVisitorCallbacks {
|
class SymbolRecordMapping : public SymbolVisitorCallbacks {
|
||||||
public:
|
public:
|
||||||
explicit SymbolRecordMapping(BinaryStreamReader &Reader) : IO(Reader) {}
|
explicit SymbolRecordMapping(msf::StreamReader &Reader) : IO(Reader) {}
|
||||||
explicit SymbolRecordMapping(BinaryStreamWriter &Writer) : IO(Writer) {}
|
explicit SymbolRecordMapping(msf::StreamWriter &Writer) : IO(Writer) {}
|
||||||
|
|
||||||
Error visitSymbolBegin(CVSymbol &Record) override;
|
Error visitSymbolBegin(CVSymbol &Record) override;
|
||||||
Error visitSymbolEnd(CVSymbol &Record) override;
|
Error visitSymbolEnd(CVSymbol &Record) override;
|
||||||
|
@ -20,8 +20,6 @@
|
|||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/ADT/iterator_range.h"
|
#include "llvm/ADT/iterator_range.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryByteStream.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamWriter.h"
|
|
||||||
#include "llvm/Support/Allocator.h"
|
#include "llvm/Support/Allocator.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
|
|
||||||
@ -30,7 +28,7 @@ namespace codeview {
|
|||||||
|
|
||||||
class SymbolSerializer : public SymbolVisitorCallbacks {
|
class SymbolSerializer : public SymbolVisitorCallbacks {
|
||||||
uint32_t RecordStart = 0;
|
uint32_t RecordStart = 0;
|
||||||
BinaryStreamWriter &Writer;
|
msf::StreamWriter &Writer;
|
||||||
SymbolRecordMapping Mapping;
|
SymbolRecordMapping Mapping;
|
||||||
Optional<SymbolKind> CurrentSymbol;
|
Optional<SymbolKind> CurrentSymbol;
|
||||||
|
|
||||||
@ -44,7 +42,7 @@ class SymbolSerializer : public SymbolVisitorCallbacks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SymbolSerializer(BinaryStreamWriter &Writer)
|
explicit SymbolSerializer(msf::StreamWriter &Writer)
|
||||||
: Writer(Writer), Mapping(Writer) {}
|
: Writer(Writer), Mapping(Writer) {}
|
||||||
|
|
||||||
virtual Error visitSymbolBegin(CVSymbol &Record) override {
|
virtual Error visitSymbolBegin(CVSymbol &Record) override {
|
||||||
|
@ -15,7 +15,9 @@
|
|||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class BinaryStreamReader;
|
namespace msf {
|
||||||
|
class StreamReader;
|
||||||
|
} // end namespace msf
|
||||||
|
|
||||||
namespace codeview {
|
namespace codeview {
|
||||||
|
|
||||||
@ -23,7 +25,7 @@ class SymbolVisitorDelegate {
|
|||||||
public:
|
public:
|
||||||
virtual ~SymbolVisitorDelegate() = default;
|
virtual ~SymbolVisitorDelegate() = default;
|
||||||
|
|
||||||
virtual uint32_t getRecordOffset(BinaryStreamReader Reader) = 0;
|
virtual uint32_t getRecordOffset(msf::StreamReader Reader) = 0;
|
||||||
virtual StringRef getFileNameForFileOffset(uint32_t FileOffset) = 0;
|
virtual StringRef getFileNameForFileOffset(uint32_t FileOffset) = 0;
|
||||||
virtual StringRef getStringTable() = 0;
|
virtual StringRef getStringTable() = 0;
|
||||||
};
|
};
|
||||||
|
@ -29,11 +29,10 @@ namespace codeview {
|
|||||||
class TypeDeserializer : public TypeVisitorCallbacks {
|
class TypeDeserializer : public TypeVisitorCallbacks {
|
||||||
struct MappingInfo {
|
struct MappingInfo {
|
||||||
explicit MappingInfo(ArrayRef<uint8_t> RecordData)
|
explicit MappingInfo(ArrayRef<uint8_t> RecordData)
|
||||||
: Stream(RecordData, llvm::support::little), Reader(Stream),
|
: Stream(RecordData), Reader(Stream), Mapping(Reader) {}
|
||||||
Mapping(Reader) {}
|
|
||||||
|
|
||||||
BinaryByteStream Stream;
|
msf::ByteStream Stream;
|
||||||
BinaryStreamReader Reader;
|
msf::StreamReader Reader;
|
||||||
TypeRecordMapping Mapping;
|
TypeRecordMapping Mapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -73,16 +72,16 @@ private:
|
|||||||
|
|
||||||
class FieldListDeserializer : public TypeVisitorCallbacks {
|
class FieldListDeserializer : public TypeVisitorCallbacks {
|
||||||
struct MappingInfo {
|
struct MappingInfo {
|
||||||
explicit MappingInfo(BinaryStreamReader &R)
|
explicit MappingInfo(msf::StreamReader &R)
|
||||||
: Reader(R), Mapping(Reader), StartOffset(0) {}
|
: Reader(R), Mapping(Reader), StartOffset(0) {}
|
||||||
|
|
||||||
BinaryStreamReader &Reader;
|
msf::StreamReader &Reader;
|
||||||
TypeRecordMapping Mapping;
|
TypeRecordMapping Mapping;
|
||||||
uint32_t StartOffset;
|
uint32_t StartOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FieldListDeserializer(BinaryStreamReader &Reader) : Mapping(Reader) {
|
explicit FieldListDeserializer(msf::StreamReader &Reader) : Mapping(Reader) {
|
||||||
CVType FieldList;
|
CVType FieldList;
|
||||||
FieldList.Type = TypeLeafKind::LF_FIELDLIST;
|
FieldList.Type = TypeLeafKind::LF_FIELDLIST;
|
||||||
consumeError(Mapping.Mapping.visitTypeBegin(FieldList));
|
consumeError(Mapping.Mapping.visitTypeBegin(FieldList));
|
||||||
|
@ -26,7 +26,9 @@
|
|||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class BinaryStreamReader;
|
namespace msf {
|
||||||
|
class StreamReader;
|
||||||
|
} // end namespace msf
|
||||||
|
|
||||||
namespace codeview {
|
namespace codeview {
|
||||||
|
|
||||||
@ -40,7 +42,7 @@ struct CVMemberRecord {
|
|||||||
TypeLeafKind Kind;
|
TypeLeafKind Kind;
|
||||||
ArrayRef<uint8_t> Data;
|
ArrayRef<uint8_t> Data;
|
||||||
};
|
};
|
||||||
typedef VarStreamArray<CVType> CVTypeArray;
|
typedef msf::VarStreamArray<CVType> CVTypeArray;
|
||||||
typedef iterator_range<CVTypeArray::Iterator> CVTypeRange;
|
typedef iterator_range<CVTypeArray::Iterator> CVTypeRange;
|
||||||
|
|
||||||
/// Equvalent to CV_fldattr_t in cvinfo.h.
|
/// Equvalent to CV_fldattr_t in cvinfo.h.
|
||||||
|
@ -16,14 +16,15 @@
|
|||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class BinaryStreamReader;
|
namespace msf {
|
||||||
class BinaryStreamWriter;
|
class StreamReader;
|
||||||
|
class StreamWriter;
|
||||||
|
}
|
||||||
namespace codeview {
|
namespace codeview {
|
||||||
class TypeRecordMapping : public TypeVisitorCallbacks {
|
class TypeRecordMapping : public TypeVisitorCallbacks {
|
||||||
public:
|
public:
|
||||||
explicit TypeRecordMapping(BinaryStreamReader &Reader) : IO(Reader) {}
|
explicit TypeRecordMapping(msf::StreamReader &Reader) : IO(Reader) {}
|
||||||
explicit TypeRecordMapping(BinaryStreamWriter &Writer) : IO(Writer) {}
|
explicit TypeRecordMapping(msf::StreamWriter &Writer) : IO(Writer) {}
|
||||||
|
|
||||||
Error visitTypeBegin(CVType &Record) override;
|
Error visitTypeBegin(CVType &Record) override;
|
||||||
Error visitTypeEnd(CVType &Record) override;
|
Error visitTypeEnd(CVType &Record) override;
|
||||||
|
@ -56,8 +56,8 @@ class TypeSerializer : public TypeVisitorCallbacks {
|
|||||||
Optional<TypeLeafKind> TypeKind;
|
Optional<TypeLeafKind> TypeKind;
|
||||||
Optional<TypeLeafKind> MemberKind;
|
Optional<TypeLeafKind> MemberKind;
|
||||||
std::vector<uint8_t> RecordBuffer;
|
std::vector<uint8_t> RecordBuffer;
|
||||||
MutableBinaryByteStream Stream;
|
msf::MutableByteStream Stream;
|
||||||
BinaryStreamWriter Writer;
|
msf::StreamWriter Writer;
|
||||||
TypeRecordMapping Mapping;
|
TypeRecordMapping Mapping;
|
||||||
|
|
||||||
RecordList SeenRecords;
|
RecordList SeenRecords;
|
||||||
@ -109,7 +109,7 @@ private:
|
|||||||
Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
|
Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
|
||||||
assert(CVR.Kind == static_cast<TypeLeafKind>(Record.getKind()));
|
assert(CVR.Kind == static_cast<TypeLeafKind>(Record.getKind()));
|
||||||
|
|
||||||
if (auto EC = Writer.writeEnum(CVR.Kind))
|
if (auto EC = Writer.writeEnum(CVR.Kind, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
if (auto EC = Mapping.visitKnownMember(CVR, Record))
|
if (auto EC = Mapping.visitKnownMember(CVR, Record))
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
//===- BinaryByteStream.h ---------------------------------------*- C++ -*-===//
|
//===- ByteStream.h - Reads stream data from a byte sequence ----*- C++ -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
// This file is distributed under the University of Illinois Open Source
|
// This file is distributed under the University of Illinois Open Source
|
||||||
// License. See LICENSE.TXT for details.
|
// License. See LICENSE.TXT for details.
|
||||||
//===----------------------------------------------------------------------===//
|
//
|
||||||
// A BinaryStream which stores data in a single continguous memory buffer.
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LLVM_SUPPORT_BINARYBYTESTREAM_H
|
#ifndef LLVM_DEBUGINFO_MSF_BYTESTREAM_H
|
||||||
#define LLVM_SUPPORT_BINARYBYTESTREAM_H
|
#define LLVM_DEBUGINFO_MSF_BYTESTREAM_H
|
||||||
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
||||||
|
#include "llvm/DebugInfo/MSF/MSFError.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
#include "llvm/Support/FileOutputBuffer.h"
|
#include "llvm/Support/FileOutputBuffer.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
@ -23,40 +23,34 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
namespace msf {
|
||||||
|
|
||||||
/// \brief An implementation of BinaryStream which holds its entire data set
|
class ByteStream : public ReadableStream {
|
||||||
/// in a single contiguous buffer. BinaryByteStream guarantees that no read
|
|
||||||
/// operation will ever incur a copy. Note that BinaryByteStream does not
|
|
||||||
/// own the underlying buffer.
|
|
||||||
class BinaryByteStream : public BinaryStream {
|
|
||||||
public:
|
public:
|
||||||
BinaryByteStream() = default;
|
ByteStream() = default;
|
||||||
BinaryByteStream(ArrayRef<uint8_t> Data, llvm::support::endianness Endian)
|
explicit ByteStream(ArrayRef<uint8_t> Data) : Data(Data) {}
|
||||||
: Endian(Endian), Data(Data) {}
|
explicit ByteStream(StringRef Data)
|
||||||
BinaryByteStream(StringRef Data, llvm::support::endianness Endian)
|
: Data(Data.bytes_begin(), Data.bytes_end()) {}
|
||||||
: Endian(Endian), Data(Data.bytes_begin(), Data.bytes_end()) {}
|
|
||||||
|
|
||||||
llvm::support::endianness getEndian() const override { return Endian; }
|
|
||||||
|
|
||||||
Error readBytes(uint32_t Offset, uint32_t Size,
|
Error readBytes(uint32_t Offset, uint32_t Size,
|
||||||
ArrayRef<uint8_t> &Buffer) override {
|
ArrayRef<uint8_t> &Buffer) const override {
|
||||||
if (Offset > Data.size())
|
if (Offset > Data.size())
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
if (Data.size() < Size + Offset)
|
if (Data.size() < Size + Offset)
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
Buffer = Data.slice(Offset, Size);
|
Buffer = Data.slice(Offset, Size);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error readLongestContiguousChunk(uint32_t Offset,
|
Error readLongestContiguousChunk(uint32_t Offset,
|
||||||
ArrayRef<uint8_t> &Buffer) override {
|
ArrayRef<uint8_t> &Buffer) const override {
|
||||||
if (Offset >= Data.size())
|
if (Offset >= Data.size())
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
Buffer = Data.slice(Offset);
|
Buffer = Data.slice(Offset);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getLength() override { return Data.size(); }
|
uint32_t getLength() const override { return Data.size(); }
|
||||||
|
|
||||||
ArrayRef<uint8_t> data() const { return Data; }
|
ArrayRef<uint8_t> data() const { return Data; }
|
||||||
|
|
||||||
@ -66,91 +60,76 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
llvm::support::endianness Endian;
|
|
||||||
ArrayRef<uint8_t> Data;
|
ArrayRef<uint8_t> Data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief An implementation of BinaryStream whose data is backed by an llvm
|
// MemoryBufferByteStream behaves like a read-only ByteStream, but has its data
|
||||||
/// MemoryBuffer object. MemoryBufferByteStream owns the MemoryBuffer in
|
// backed by an llvm::MemoryBuffer. It also owns the underlying MemoryBuffer.
|
||||||
/// question. As with BinaryByteStream, reading from a MemoryBufferByteStream
|
class MemoryBufferByteStream : public ByteStream {
|
||||||
/// will never cause a copy.
|
|
||||||
class MemoryBufferByteStream : public BinaryByteStream {
|
|
||||||
public:
|
public:
|
||||||
explicit MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer,
|
explicit MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer)
|
||||||
llvm::support::endianness Endian)
|
: ByteStream(ArrayRef<uint8_t>(Buffer->getBuffer().bytes_begin(),
|
||||||
: BinaryByteStream(Buffer->getBuffer(), Endian),
|
Buffer->getBuffer().bytes_end())),
|
||||||
MemBuffer(std::move(Buffer)) {}
|
MemBuffer(std::move(Buffer)) {}
|
||||||
|
|
||||||
std::unique_ptr<MemoryBuffer> MemBuffer;
|
std::unique_ptr<MemoryBuffer> MemBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief An implementation of BinaryStream which holds its entire data set
|
class MutableByteStream : public WritableStream {
|
||||||
/// in a single contiguous buffer. As with BinaryByteStream, the mutable
|
|
||||||
/// version also guarantees that no read operation will ever incur a copy,
|
|
||||||
/// and similarly it does not own the underlying buffer.
|
|
||||||
class MutableBinaryByteStream : public WritableBinaryStream {
|
|
||||||
public:
|
public:
|
||||||
MutableBinaryByteStream() = default;
|
MutableByteStream() = default;
|
||||||
MutableBinaryByteStream(MutableArrayRef<uint8_t> Data,
|
explicit MutableByteStream(MutableArrayRef<uint8_t> Data)
|
||||||
llvm::support::endianness Endian)
|
: Data(Data), ImmutableStream(Data) {}
|
||||||
: Data(Data), ImmutableStream(Data, Endian) {}
|
|
||||||
|
|
||||||
llvm::support::endianness getEndian() const override {
|
|
||||||
return ImmutableStream.getEndian();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error readBytes(uint32_t Offset, uint32_t Size,
|
Error readBytes(uint32_t Offset, uint32_t Size,
|
||||||
ArrayRef<uint8_t> &Buffer) override {
|
ArrayRef<uint8_t> &Buffer) const override {
|
||||||
return ImmutableStream.readBytes(Offset, Size, Buffer);
|
return ImmutableStream.readBytes(Offset, Size, Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error readLongestContiguousChunk(uint32_t Offset,
|
Error readLongestContiguousChunk(uint32_t Offset,
|
||||||
ArrayRef<uint8_t> &Buffer) override {
|
ArrayRef<uint8_t> &Buffer) const override {
|
||||||
return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
|
return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getLength() override { return ImmutableStream.getLength(); }
|
uint32_t getLength() const override { return ImmutableStream.getLength(); }
|
||||||
|
|
||||||
Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) override {
|
Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) const override {
|
||||||
if (Buffer.empty())
|
if (Buffer.empty())
|
||||||
return Error::success();
|
return Error::success();
|
||||||
|
|
||||||
if (Data.size() < Buffer.size())
|
if (Data.size() < Buffer.size())
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
if (Offset > Buffer.size() - Data.size())
|
if (Offset > Buffer.size() - Data.size())
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
|
|
||||||
uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
|
uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
|
||||||
::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
|
::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error commit() override { return Error::success(); }
|
Error commit() const override { return Error::success(); }
|
||||||
|
|
||||||
MutableArrayRef<uint8_t> data() const { return Data; }
|
MutableArrayRef<uint8_t> data() const { return Data; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MutableArrayRef<uint8_t> Data;
|
MutableArrayRef<uint8_t> Data;
|
||||||
BinaryByteStream ImmutableStream;
|
ByteStream ImmutableStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief An implementation of WritableBinaryStream backed by an llvm
|
// A simple adapter that acts like a ByteStream but holds ownership over
|
||||||
/// FileOutputBuffer.
|
// and underlying FileOutputBuffer.
|
||||||
class FileBufferByteStream : public WritableBinaryStream {
|
class FileBufferByteStream : public WritableStream {
|
||||||
private:
|
private:
|
||||||
class StreamImpl : public MutableBinaryByteStream {
|
class StreamImpl : public MutableByteStream {
|
||||||
public:
|
public:
|
||||||
StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer,
|
StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer)
|
||||||
llvm::support::endianness Endian)
|
: MutableByteStream(MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
|
||||||
: MutableBinaryByteStream(
|
Buffer->getBufferEnd())),
|
||||||
MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
|
|
||||||
Buffer->getBufferEnd()),
|
|
||||||
Endian),
|
|
||||||
FileBuffer(std::move(Buffer)) {}
|
FileBuffer(std::move(Buffer)) {}
|
||||||
|
|
||||||
Error commit() override {
|
Error commit() const override {
|
||||||
if (FileBuffer->commit())
|
if (FileBuffer->commit())
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return llvm::make_error<MSFError>(msf_error_code::not_writable);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,36 +138,32 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer,
|
explicit FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer)
|
||||||
llvm::support::endianness Endian)
|
: Impl(std::move(Buffer)) {}
|
||||||
: Impl(std::move(Buffer), Endian) {}
|
|
||||||
|
|
||||||
llvm::support::endianness getEndian() const override {
|
|
||||||
return Impl.getEndian();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error readBytes(uint32_t Offset, uint32_t Size,
|
Error readBytes(uint32_t Offset, uint32_t Size,
|
||||||
ArrayRef<uint8_t> &Buffer) override {
|
ArrayRef<uint8_t> &Buffer) const override {
|
||||||
return Impl.readBytes(Offset, Size, Buffer);
|
return Impl.readBytes(Offset, Size, Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error readLongestContiguousChunk(uint32_t Offset,
|
Error readLongestContiguousChunk(uint32_t Offset,
|
||||||
ArrayRef<uint8_t> &Buffer) override {
|
ArrayRef<uint8_t> &Buffer) const override {
|
||||||
return Impl.readLongestContiguousChunk(Offset, Buffer);
|
return Impl.readLongestContiguousChunk(Offset, Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getLength() override { return Impl.getLength(); }
|
uint32_t getLength() const override { return Impl.getLength(); }
|
||||||
|
|
||||||
Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) override {
|
Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const override {
|
||||||
return Impl.writeBytes(Offset, Data);
|
return Impl.writeBytes(Offset, Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error commit() override { return Impl.commit(); }
|
Error commit() const override { return Impl.commit(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StreamImpl Impl;
|
StreamImpl Impl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end namespace msf
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_SUPPORT_BINARYBYTESTREAM_H
|
#endif // LLVM_DEBUGINFO_MSF_BYTESTREAM_H
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//===- BinaryItemStream.h ---------------------------------------*- C++ -*-===//
|
//===- SequencedItemStream.h ------------------------------------*- C++ -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
@ -7,96 +7,87 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LLVM_SUPPORT_BINARYITEMSTREAM_H
|
#ifndef LLVM_DEBUGINFO_MSF_SEQUENCEDITEMSTREAM_H
|
||||||
#define LLVM_SUPPORT_BINARYITEMSTREAM_H
|
#define LLVM_DEBUGINFO_MSF_SEQUENCEDITEMSTREAM_H
|
||||||
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
||||||
|
#include "llvm/DebugInfo/MSF/MSFError.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
namespace msf {
|
||||||
|
|
||||||
template <typename T> struct BinaryItemTraits {
|
template <typename T> struct SequencedItemTraits {
|
||||||
size_t length(const T &Item) = delete;
|
static size_t length(const T &Item) = delete;
|
||||||
ArrayRef<uint8_t> bytes(const T &Item) = delete;
|
static ArrayRef<uint8_t> bytes(const T &Item) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// BinaryItemStream represents a sequence of objects stored in some kind of
|
/// SequencedItemStream represents a sequence of objects stored in a
|
||||||
/// external container but for which it is useful to view as a stream of
|
/// standard container but for which it is useful to view as a stream of
|
||||||
/// contiguous bytes. An example of this might be if you have a collection of
|
/// contiguous bytes. An example of this might be if you have a std::vector
|
||||||
/// records and you serialize each one into a buffer, and store these serialized
|
/// of TPI records, where each record contains a byte sequence that
|
||||||
/// records in a container. The pointers themselves are not laid out
|
/// represents that one record serialized, but where each consecutive item
|
||||||
/// contiguously in memory, but we may wish to read from or write to these
|
/// might not be allocated immediately after the previous item. Using a
|
||||||
/// records as if they were.
|
/// SequencedItemStream, we can adapt the VarStreamArray class to trivially
|
||||||
template <typename T, typename ItemTraits = BinaryItemTraits<T>>
|
/// extract one item at a time, allowing the data to be used anywhere a
|
||||||
class BinaryItemStream : public BinaryStream {
|
/// VarStreamArray could be used.
|
||||||
|
template <typename T, typename Traits = SequencedItemTraits<T>>
|
||||||
|
class SequencedItemStream : public ReadableStream {
|
||||||
public:
|
public:
|
||||||
explicit BinaryItemStream(llvm::support::endianness Endian)
|
SequencedItemStream() = default;
|
||||||
: Endian(Endian) {}
|
|
||||||
|
|
||||||
llvm::support::endianness getEndian() const override { return Endian; }
|
|
||||||
|
|
||||||
Error readBytes(uint32_t Offset, uint32_t Size,
|
Error readBytes(uint32_t Offset, uint32_t Size,
|
||||||
ArrayRef<uint8_t> &Buffer) override {
|
ArrayRef<uint8_t> &Buffer) const override {
|
||||||
if (auto EC = readLongestContiguousChunk(Offset, Buffer))
|
auto ExpectedIndex = translateOffsetIndex(Offset);
|
||||||
return EC;
|
if (!ExpectedIndex)
|
||||||
|
return ExpectedIndex.takeError();
|
||||||
if (Size > Buffer.size())
|
const auto &Item = Items[*ExpectedIndex];
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
if (Size > Traits::length(Item))
|
||||||
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
Buffer = Buffer.take_front(Size);
|
Buffer = Traits::bytes(Item).take_front(Size);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error readLongestContiguousChunk(uint32_t Offset,
|
Error readLongestContiguousChunk(uint32_t Offset,
|
||||||
ArrayRef<uint8_t> &Buffer) override {
|
ArrayRef<uint8_t> &Buffer) const override {
|
||||||
uint32_t Index;
|
auto ExpectedIndex = translateOffsetIndex(Offset);
|
||||||
uint32_t ByteOffset;
|
if (!ExpectedIndex)
|
||||||
if (auto EC = translateOffsetIndex(Offset, Index, ByteOffset))
|
return ExpectedIndex.takeError();
|
||||||
return EC;
|
Buffer = Traits::bytes(Items[*ExpectedIndex]);
|
||||||
const auto &Item = Items[Index];
|
|
||||||
Buffer = Traits.bytes(Item).drop_front(ByteOffset);
|
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setItems(ArrayRef<T> ItemArray) { Items = ItemArray; }
|
void setItems(ArrayRef<T> ItemArray) { Items = ItemArray; }
|
||||||
|
|
||||||
uint32_t getLength() override {
|
uint32_t getLength() const override {
|
||||||
uint32_t Size = 0;
|
uint32_t Size = 0;
|
||||||
for (const auto &Item : Items)
|
for (const auto &Item : Items)
|
||||||
Size += Traits.length(Item);
|
Size += Traits::length(Item);
|
||||||
return Size;
|
return Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Error translateOffsetIndex(uint32_t Offset, uint32_t &ItemIndex,
|
Expected<uint32_t> translateOffsetIndex(uint32_t Offset) const {
|
||||||
uint32_t &ByteOffset) {
|
|
||||||
ItemIndex = 0;
|
|
||||||
ByteOffset = 0;
|
|
||||||
uint32_t PrevOffset = 0;
|
|
||||||
uint32_t CurrentOffset = 0;
|
uint32_t CurrentOffset = 0;
|
||||||
if (Offset > 0) {
|
uint32_t CurrentIndex = 0;
|
||||||
for (const auto &Item : Items) {
|
for (const auto &Item : Items) {
|
||||||
PrevOffset = CurrentOffset;
|
if (CurrentOffset >= Offset)
|
||||||
CurrentOffset += Traits.length(Item);
|
break;
|
||||||
if (CurrentOffset > Offset)
|
CurrentOffset += Traits::length(Item);
|
||||||
break;
|
++CurrentIndex;
|
||||||
++ItemIndex;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (CurrentOffset < Offset)
|
if (CurrentOffset != Offset)
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
ByteOffset = Offset - PrevOffset;
|
return CurrentIndex;
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::support::endianness Endian;
|
|
||||||
ItemTraits Traits;
|
|
||||||
ArrayRef<T> Items;
|
ArrayRef<T> Items;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end namespace msf
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_SUPPORT_BINARYITEMSTREAM_H
|
#endif // LLVM_DEBUGINFO_MSF_SEQUENCEDITEMSTREAM_H
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//===- BinaryStream.h - Base interface for a stream of data -----*- C++ -*-===//
|
//===- StreamInterface.h - Base interface for a stream of data --*- C++ -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
@ -7,62 +7,47 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LLVM_SUPPORT_BINARYSTREAM_H
|
#ifndef LLVM_DEBUGINFO_MSF_STREAMINTERFACE_H
|
||||||
#define LLVM_SUPPORT_BINARYSTREAM_H
|
#define LLVM_DEBUGINFO_MSF_STREAMINTERFACE_H
|
||||||
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/Support/Endian.h"
|
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
namespace msf {
|
||||||
|
|
||||||
/// \brief An interface for accessing data in a stream-like format, but which
|
class ReadableStream {
|
||||||
/// discourages copying. Instead of specifying a buffer in which to copy
|
|
||||||
/// data on a read, the API returns an ArrayRef to data owned by the stream's
|
|
||||||
/// implementation. Since implementations may not necessarily store data in a
|
|
||||||
/// single contiguous buffer (or even in memory at all), in such cases a it may
|
|
||||||
/// be necessary for an implementation to cache such a buffer so that it can
|
|
||||||
/// return it.
|
|
||||||
class BinaryStream {
|
|
||||||
public:
|
public:
|
||||||
virtual ~BinaryStream() = default;
|
virtual ~ReadableStream() = default;
|
||||||
|
|
||||||
virtual llvm::support::endianness getEndian() const = 0;
|
// 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
|
||||||
/// \brief Given an offset into the stream and a number of bytes, attempt to
|
// stream, without copying any data.
|
||||||
/// read the bytes and set the output ArrayRef to point to data owned by the
|
|
||||||
/// stream.
|
|
||||||
virtual Error readBytes(uint32_t Offset, uint32_t Size,
|
virtual Error readBytes(uint32_t Offset, uint32_t Size,
|
||||||
ArrayRef<uint8_t> &Buffer) = 0;
|
ArrayRef<uint8_t> &Buffer) const = 0;
|
||||||
|
|
||||||
/// \brief Given an offset into the stream, read as much as possible without
|
// Given an offset into the stream, read as much as possible without copying
|
||||||
/// copying any data.
|
// any data.
|
||||||
virtual Error readLongestContiguousChunk(uint32_t Offset,
|
virtual Error readLongestContiguousChunk(uint32_t Offset,
|
||||||
ArrayRef<uint8_t> &Buffer) = 0;
|
ArrayRef<uint8_t> &Buffer) const = 0;
|
||||||
|
|
||||||
/// \brief Return the number of bytes of data in this stream.
|
virtual uint32_t getLength() const = 0;
|
||||||
virtual uint32_t getLength() = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A BinaryStream which can be read from as well as written to. Note
|
class WritableStream : public ReadableStream {
|
||||||
/// that writing to a BinaryStream always necessitates copying from the input
|
|
||||||
/// buffer to the stream's backing store. Streams are assumed to be buffered
|
|
||||||
/// so that to be portable it is necessary to call commit() on the stream when
|
|
||||||
/// all data has been written.
|
|
||||||
class WritableBinaryStream : public BinaryStream {
|
|
||||||
public:
|
public:
|
||||||
~WritableBinaryStream() override = default;
|
~WritableStream() override = default;
|
||||||
|
|
||||||
/// \brief Attempt to write the given bytes into the stream at the desired
|
// Attempt to write the given bytes into the stream at the desired offset.
|
||||||
/// offset. This will always necessitate a copy. Cannot shrink or grow the
|
// This will always necessitate a copy. Cannot shrink or grow the stream,
|
||||||
/// stream, only writes into existing allocated space.
|
// only writes into existing allocated space.
|
||||||
virtual Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) = 0;
|
virtual Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const = 0;
|
||||||
|
|
||||||
/// \brief For buffered streams, commits changes to the backing store.
|
virtual Error commit() const = 0;
|
||||||
virtual Error commit() = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end namespace msf
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_SUPPORT_BINARYSTREAM_H
|
#endif // LLVM_DEBUGINFO_MSF_STREAMINTERFACE_H
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//===- BinaryStreamArray.h - Array backed by an arbitrary stream *- C++ -*-===//
|
//===- StreamArray.h - Array backed by an arbitrary stream ------*- C++ -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
@ -7,8 +7,8 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LLVM_SUPPORT_BINARYSTREAMARRAY_H
|
#ifndef LLVM_DEBUGINFO_MSF_STREAMARRAY_H
|
||||||
#define LLVM_SUPPORT_BINARYSTREAMARRAY_H
|
#define LLVM_DEBUGINFO_MSF_STREAMARRAY_H
|
||||||
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/iterator.h"
|
#include "llvm/ADT/iterator.h"
|
||||||
@ -17,20 +17,11 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
/// Lightweight arrays that are backed by an arbitrary BinaryStream. This file
|
|
||||||
/// provides two different array implementations.
|
|
||||||
///
|
|
||||||
/// VarStreamArray - Arrays of variable length records. The user specifies
|
|
||||||
/// an Extractor type that can extract a record from a given offset and
|
|
||||||
/// return the number of bytes consumed by the record.
|
|
||||||
///
|
|
||||||
/// FixedStreamArray - Arrays of fixed length records. This is similar in
|
|
||||||
/// spirit to ArrayRef<T>, but since it is backed by a BinaryStream, the
|
|
||||||
/// elements of the array need not be laid out in contiguous memory.
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
namespace msf {
|
||||||
|
|
||||||
/// VarStreamArrayExtractor is intended to be specialized to provide customized
|
/// VarStreamArrayExtractor is intended to be specialized to provide customized
|
||||||
/// extraction logic. On input it receives a BinaryStreamRef pointing to the
|
/// extraction logic. On input it receives a StreamRef pointing to the
|
||||||
/// beginning of the next record, but where the length of the record is not yet
|
/// beginning of the next record, but where the length of the record is not yet
|
||||||
/// known. Upon completion, it should return an appropriate Error instance if
|
/// known. Upon completion, it should return an appropriate Error instance if
|
||||||
/// a record could not be extracted, or if one could be extracted it should
|
/// a record could not be extracted, or if one could be extracted it should
|
||||||
@ -44,7 +35,7 @@ namespace llvm {
|
|||||||
template <typename T> struct VarStreamArrayExtractor {
|
template <typename T> struct VarStreamArrayExtractor {
|
||||||
// Method intentionally deleted. You must provide an explicit specialization
|
// Method intentionally deleted. You must provide an explicit specialization
|
||||||
// with the following method implemented.
|
// with the following method implemented.
|
||||||
Error operator()(BinaryStreamRef Stream, uint32_t &Len,
|
Error operator()(ReadableStreamRef Stream, uint32_t &Len,
|
||||||
T &Item) const = delete;
|
T &Item) const = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -58,10 +49,10 @@ template <typename T> struct VarStreamArrayExtractor {
|
|||||||
/// abstracting this out, we need not duplicate this memory, and we can
|
/// abstracting this out, we need not duplicate this memory, and we can
|
||||||
/// iterate over arrays in arbitrarily formatted streams. Elements are parsed
|
/// iterate over arrays in arbitrarily formatted streams. Elements are parsed
|
||||||
/// lazily on iteration, so there is no upfront cost associated with building
|
/// lazily on iteration, so there is no upfront cost associated with building
|
||||||
/// or copying a VarStreamArray, no matter how large it may be.
|
/// a VarStreamArray, no matter how large it may be.
|
||||||
///
|
///
|
||||||
/// You create a VarStreamArray by specifying a ValueType and an Extractor type.
|
/// You create a VarStreamArray by specifying a ValueType and an Extractor type.
|
||||||
/// If you do not specify an Extractor type, you are expected to specialize
|
/// If you do not specify an Extractor type, it expects you to specialize
|
||||||
/// VarStreamArrayExtractor<T> for your ValueType.
|
/// VarStreamArrayExtractor<T> for your ValueType.
|
||||||
///
|
///
|
||||||
/// By default an Extractor is default constructed in the class, but in some
|
/// By default an Extractor is default constructed in the class, but in some
|
||||||
@ -95,8 +86,8 @@ public:
|
|||||||
VarStreamArray() = default;
|
VarStreamArray() = default;
|
||||||
explicit VarStreamArray(const Extractor &E) : E(E) {}
|
explicit VarStreamArray(const Extractor &E) : E(E) {}
|
||||||
|
|
||||||
explicit VarStreamArray(BinaryStreamRef Stream) : Stream(Stream) {}
|
explicit VarStreamArray(ReadableStreamRef Stream) : Stream(Stream) {}
|
||||||
VarStreamArray(BinaryStreamRef Stream, const Extractor &E)
|
VarStreamArray(ReadableStreamRef Stream, const Extractor &E)
|
||||||
: Stream(Stream), E(E) {}
|
: Stream(Stream), E(E) {}
|
||||||
|
|
||||||
VarStreamArray(const VarStreamArray<ValueType, Extractor> &Other)
|
VarStreamArray(const VarStreamArray<ValueType, Extractor> &Other)
|
||||||
@ -110,10 +101,10 @@ public:
|
|||||||
|
|
||||||
const Extractor &getExtractor() const { return E; }
|
const Extractor &getExtractor() const { return E; }
|
||||||
|
|
||||||
BinaryStreamRef getUnderlyingStream() const { return Stream; }
|
ReadableStreamRef getUnderlyingStream() const { return Stream; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BinaryStreamRef Stream;
|
ReadableStreamRef Stream;
|
||||||
Extractor E;
|
Extractor E;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -162,25 +153,23 @@ public:
|
|||||||
return ThisValue;
|
return ThisValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
IterType &operator+=(unsigned N) {
|
IterType &operator++() {
|
||||||
for (unsigned I = 0; I < N; ++I) {
|
// We are done with the current record, discard it so that we are
|
||||||
// We are done with the current record, discard it so that we are
|
// positioned at the next record.
|
||||||
// positioned at the next record.
|
IterRef = IterRef.drop_front(ThisLen);
|
||||||
IterRef = IterRef.drop_front(ThisLen);
|
if (IterRef.getLength() == 0) {
|
||||||
if (IterRef.getLength() == 0) {
|
// There is nothing after the current record, we must make this an end
|
||||||
// There is nothing after the current record, we must make this an end
|
// iterator.
|
||||||
// iterator.
|
moveToEnd();
|
||||||
|
} else {
|
||||||
|
// There is some data after the current record.
|
||||||
|
auto EC = Extract(IterRef, ThisLen, ThisValue);
|
||||||
|
if (EC) {
|
||||||
|
consumeError(std::move(EC));
|
||||||
|
markError();
|
||||||
|
} else if (ThisLen == 0) {
|
||||||
|
// An empty record? Make this an end iterator.
|
||||||
moveToEnd();
|
moveToEnd();
|
||||||
} else {
|
|
||||||
// There is some data after the current record.
|
|
||||||
auto EC = Extract(IterRef, ThisLen, ThisValue);
|
|
||||||
if (EC) {
|
|
||||||
consumeError(std::move(EC));
|
|
||||||
markError();
|
|
||||||
} else if (ThisLen == 0) {
|
|
||||||
// An empty record? Make this an end iterator.
|
|
||||||
moveToEnd();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@ -199,7 +188,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
ValueType ThisValue;
|
ValueType ThisValue;
|
||||||
BinaryStreamRef IterRef;
|
ReadableStreamRef IterRef;
|
||||||
const ArrayType *Array{nullptr};
|
const ArrayType *Array{nullptr};
|
||||||
uint32_t ThisLen{0};
|
uint32_t ThisLen{0};
|
||||||
bool HasError{false};
|
bool HasError{false};
|
||||||
@ -209,17 +198,12 @@ private:
|
|||||||
|
|
||||||
template <typename T> class FixedStreamArrayIterator;
|
template <typename T> class FixedStreamArrayIterator;
|
||||||
|
|
||||||
/// FixedStreamArray is similar to VarStreamArray, except with each record
|
|
||||||
/// having a fixed-length. As with VarStreamArray, there is no upfront
|
|
||||||
/// cost associated with building or copying a FixedStreamArray, as the
|
|
||||||
/// memory for each element is not read from the backing stream until that
|
|
||||||
/// element is iterated.
|
|
||||||
template <typename T> class FixedStreamArray {
|
template <typename T> class FixedStreamArray {
|
||||||
friend class FixedStreamArrayIterator<T>;
|
friend class FixedStreamArrayIterator<T>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FixedStreamArray() = default;
|
FixedStreamArray() = default;
|
||||||
explicit FixedStreamArray(BinaryStreamRef Stream) : Stream(Stream) {
|
FixedStreamArray(ReadableStreamRef Stream) : Stream(Stream) {
|
||||||
assert(Stream.getLength() % sizeof(T) == 0);
|
assert(Stream.getLength() % sizeof(T) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,10 +242,10 @@ public:
|
|||||||
return FixedStreamArrayIterator<T>(*this, size());
|
return FixedStreamArrayIterator<T>(*this, size());
|
||||||
}
|
}
|
||||||
|
|
||||||
BinaryStreamRef getUnderlyingStream() const { return Stream; }
|
ReadableStreamRef getUnderlyingStream() const { return Stream; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BinaryStreamRef Stream;
|
ReadableStreamRef Stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -314,6 +298,7 @@ private:
|
|||||||
uint32_t Index;
|
uint32_t Index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace msf
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_SUPPORT_BINARYSTREAMARRAY_H
|
#endif // LLVM_DEBUGINFO_MSF_STREAMARRAY_H
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//===- BinaryStreamReader.h - Reads objects from a binary stream *- C++ -*-===//
|
//===- StreamReader.h - Reads bytes and objects from a stream ---*- C++ -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
@ -7,166 +7,71 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LLVM_SUPPORT_BINARYSTREAMREADER_H
|
#ifndef LLVM_DEBUGINFO_MSF_STREAMREADER_H
|
||||||
#define LLVM_SUPPORT_BINARYSTREAMREADER_H
|
#define LLVM_DEBUGINFO_MSF_STREAMREADER_H
|
||||||
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
|
||||||
|
#include "llvm/DebugInfo/MSF/MSFError.h"
|
||||||
#include "llvm/Support/Endian.h"
|
#include "llvm/Support/Endian.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
#include "llvm/Support/MathExtras.h"
|
|
||||||
#include "llvm/Support/type_traits.h"
|
#include "llvm/Support/type_traits.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
namespace msf {
|
||||||
|
|
||||||
/// \brief Provides read only access to a subclass of `BinaryStream`. Provides
|
class StreamReader {
|
||||||
/// bounds checking and helpers for writing certain common data types such as
|
|
||||||
/// null-terminated strings, integers in various flavors of endianness, etc.
|
|
||||||
/// Can be subclassed to provide reading of custom datatypes, although no
|
|
||||||
/// are overridable.
|
|
||||||
class BinaryStreamReader {
|
|
||||||
public:
|
public:
|
||||||
explicit BinaryStreamReader(BinaryStreamRef Stream);
|
StreamReader(ReadableStreamRef Stream);
|
||||||
virtual ~BinaryStreamReader() {}
|
|
||||||
|
|
||||||
/// Read as much as possible from the underlying string at the current offset
|
|
||||||
/// without invoking a copy, and set \p Buffer to the resulting data slice.
|
|
||||||
/// Updates the stream's offset to point after the newly read data.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully read, otherwise
|
|
||||||
/// returns an appropriate error code.
|
|
||||||
Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer);
|
Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer);
|
||||||
|
|
||||||
/// Read \p Size bytes from the underlying stream at the current offset and
|
|
||||||
/// and set \p Buffer to the resulting data slice. Whether a copy occurs
|
|
||||||
/// depends on the implementation of the underlying stream. Updates the
|
|
||||||
/// stream's offset to point after the newly read data.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully read, otherwise
|
|
||||||
/// returns an appropriate error code.
|
|
||||||
Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
|
Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
|
||||||
|
|
||||||
/// Read an integer of the specified endianness into \p Dest and update the
|
template <typename T>
|
||||||
/// stream's offset. The data is always copied from the stream's underlying
|
Error readInteger(T &Dest,
|
||||||
/// buffer into \p Dest. Updates the stream's offset to point after the newly
|
llvm::support::endianness Endian = llvm::support::native) {
|
||||||
/// read data.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully read, otherwise
|
|
||||||
/// returns an appropriate error code.
|
|
||||||
template <typename T> Error readInteger(T &Dest) {
|
|
||||||
static_assert(std::is_integral<T>::value,
|
static_assert(std::is_integral<T>::value,
|
||||||
"Cannot call readInteger with non-integral value!");
|
"Cannot call readInteger with non-integral value!");
|
||||||
|
|
||||||
ArrayRef<uint8_t> Bytes;
|
ArrayRef<uint8_t> Bytes;
|
||||||
if (auto EC = readBytes(Bytes, sizeof(T)))
|
if (auto EC = readBytes(Bytes, sizeof(T)))
|
||||||
return EC;
|
return EC;
|
||||||
readIntegersImpl(Bytes, Dest);
|
|
||||||
|
Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
|
||||||
|
Bytes.data(), Endian);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a list of integers into \p Dest and update the stream's offset.
|
Error readZeroString(StringRef &Dest);
|
||||||
/// The data is always copied from the stream's underlying into \p Dest.
|
Error readFixedString(StringRef &Dest, uint32_t Length);
|
||||||
/// Updates the stream's offset to point after the newly read data. Use of
|
Error readStreamRef(ReadableStreamRef &Ref);
|
||||||
/// this method is more efficient than calling `readInteger` multiple times
|
Error readStreamRef(ReadableStreamRef &Ref, uint32_t Length);
|
||||||
/// because this performs bounds checking only once, and requires only a
|
|
||||||
/// single error check by the user.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully read, otherwise
|
|
||||||
/// returns an appropriate error code.
|
|
||||||
template <typename... Ts> Error readIntegers(Ts &... Dest) {
|
|
||||||
const size_t Size = sizeof_sum<Ts...>::value;
|
|
||||||
ArrayRef<uint8_t> Bytes;
|
|
||||||
if (auto EC = readBytes(Bytes, Size))
|
|
||||||
return EC;
|
|
||||||
readIntegersImpl(Bytes, Dest...);
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read a \p ByteSize byte integer and store the result in \p Dest, updating
|
template <typename T>
|
||||||
/// the reader's position if successful.
|
Error readEnum(T &Dest,
|
||||||
///
|
llvm::support::endianness Endian = llvm::support::native) {
|
||||||
/// \returns a success error code if the data was successfully read, otherwise
|
|
||||||
/// returns an appropriate error code.
|
|
||||||
Error readInteger(uint64_t &Dest, uint32_t ByteSize);
|
|
||||||
|
|
||||||
/// Similar to readInteger.
|
|
||||||
template <typename T> Error readEnum(T &Dest) {
|
|
||||||
static_assert(std::is_enum<T>::value,
|
static_assert(std::is_enum<T>::value,
|
||||||
"Cannot call readEnum with non-enum value!");
|
"Cannot call readEnum with non-enum value!");
|
||||||
typename std::underlying_type<T>::type N;
|
typename std::underlying_type<T>::type N;
|
||||||
if (auto EC = readInteger(N))
|
if (auto EC = readInteger(N, Endian))
|
||||||
return EC;
|
return EC;
|
||||||
Dest = static_cast<T>(N);
|
Dest = static_cast<T>(N);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a null terminated string from \p Dest. Whether a copy occurs depends
|
|
||||||
/// on the implementation of the underlying stream. Updates the stream's
|
|
||||||
/// offset to point after the newly read data.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully read, otherwise
|
|
||||||
/// returns an appropriate error code.
|
|
||||||
Error readCString(StringRef &Dest);
|
|
||||||
|
|
||||||
/// Read a \p Length byte string into \p Dest. Whether a copy occurs depends
|
|
||||||
/// on the implementation of the underlying stream. Updates the stream's
|
|
||||||
/// offset to point after the newly read data.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully read, otherwise
|
|
||||||
/// returns an appropriate error code.
|
|
||||||
Error readFixedString(StringRef &Dest, uint32_t Length);
|
|
||||||
|
|
||||||
/// Read the entire remainder of the underlying stream into \p Ref. This is
|
|
||||||
/// equivalent to calling getUnderlyingStream().slice(Offset). Updates the
|
|
||||||
/// stream's offset to point to the end of the stream. Never causes a copy.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully read, otherwise
|
|
||||||
/// returns an appropriate error code.
|
|
||||||
Error readStreamRef(BinaryStreamRef &Ref);
|
|
||||||
|
|
||||||
/// Read \p Length bytes from the underlying stream into \p Ref. This is
|
|
||||||
/// equivalent to calling getUnderlyingStream().slice(Offset, Length).
|
|
||||||
/// Updates the stream's offset to point after the newly read object. Never
|
|
||||||
/// causes a copy.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully read, otherwise
|
|
||||||
/// returns an appropriate error code.
|
|
||||||
Error readStreamRef(BinaryStreamRef &Ref, uint32_t Length);
|
|
||||||
|
|
||||||
/// Get a pointer to an object of type T from the underlying stream, as if by
|
|
||||||
/// memcpy, and store the result into \p Dest. It is up to the caller to
|
|
||||||
/// ensure that objects of type T can be safely treated in this manner.
|
|
||||||
/// Updates the stream's offset to point after the newly read object. Whether
|
|
||||||
/// a copy occurs depends upon the implementation of the underlying
|
|
||||||
/// stream.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully read, otherwise
|
|
||||||
/// returns an appropriate error code.
|
|
||||||
template <typename T> Error readObject(const T *&Dest) {
|
template <typename T> Error readObject(const T *&Dest) {
|
||||||
ArrayRef<uint8_t> Buffer;
|
ArrayRef<uint8_t> Buffer;
|
||||||
if (auto EC = readBytes(Buffer, sizeof(T)))
|
if (auto EC = readBytes(Buffer, sizeof(T)))
|
||||||
return EC;
|
return EC;
|
||||||
assert(alignmentAdjustment(Buffer.data(), alignof(T)) == 0 &&
|
|
||||||
"Reading at invalid alignment!");
|
|
||||||
Dest = reinterpret_cast<const T *>(Buffer.data());
|
Dest = reinterpret_cast<const T *>(Buffer.data());
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a reference to a \p NumElements element array of objects of type T
|
|
||||||
/// from the underlying stream as if by memcpy, and store the resulting array
|
|
||||||
/// slice into \p array. It is up to the caller to ensure that objects of
|
|
||||||
/// type T can be safely treated in this manner. Updates the stream's offset
|
|
||||||
/// to point after the newly read object. Whether a copy occurs depends upon
|
|
||||||
/// the implementation of the underlying stream.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully read, otherwise
|
|
||||||
/// returns an appropriate error code.
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Error readArray(ArrayRef<T> &Array, uint32_t NumElements) {
|
Error readArray(ArrayRef<T> &Array, uint32_t NumElements) {
|
||||||
ArrayRef<uint8_t> Bytes;
|
ArrayRef<uint8_t> Bytes;
|
||||||
@ -176,43 +81,23 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (NumElements > UINT32_MAX / sizeof(T))
|
if (NumElements > UINT32_MAX / sizeof(T))
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
|
|
||||||
if (auto EC = readBytes(Bytes, NumElements * sizeof(T)))
|
if (auto EC = readBytes(Bytes, NumElements * sizeof(T)))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
assert(alignmentAdjustment(Bytes.data(), alignof(T)) == 0 &&
|
|
||||||
"Reading at invalid alignment!");
|
|
||||||
|
|
||||||
Array = ArrayRef<T>(reinterpret_cast<const T *>(Bytes.data()), NumElements);
|
Array = ArrayRef<T>(reinterpret_cast<const T *>(Bytes.data()), NumElements);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a VarStreamArray of size \p Size bytes and store the result into
|
|
||||||
/// \p Array. Updates the stream's offset to point after the newly read
|
|
||||||
/// array. Never causes a copy (although iterating the elements of the
|
|
||||||
/// VarStreamArray may, depending upon the implementation of the underlying
|
|
||||||
/// stream).
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully read, otherwise
|
|
||||||
/// returns an appropriate error code.
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
Error readArray(VarStreamArray<T, U> &Array, uint32_t Size) {
|
Error readArray(VarStreamArray<T, U> &Array, uint32_t Size) {
|
||||||
BinaryStreamRef S;
|
ReadableStreamRef S;
|
||||||
if (auto EC = readStreamRef(S, Size))
|
if (auto EC = readStreamRef(S, Size))
|
||||||
return EC;
|
return EC;
|
||||||
Array = VarStreamArray<T, U>(S, Array.getExtractor());
|
Array = VarStreamArray<T, U>(S, Array.getExtractor());
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a FixedStreamArray of \p NumItems elements and store the result into
|
|
||||||
/// \p Array. Updates the stream's offset to point after the newly read
|
|
||||||
/// array. Never causes a copy (although iterating the elements of the
|
|
||||||
/// FixedStreamArray may, depending upon the implementation of the underlying
|
|
||||||
/// stream).
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully read, otherwise
|
|
||||||
/// returns an appropriate error code.
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Error readArray(FixedStreamArray<T> &Array, uint32_t NumItems) {
|
Error readArray(FixedStreamArray<T> &Array, uint32_t NumItems) {
|
||||||
if (NumItems == 0) {
|
if (NumItems == 0) {
|
||||||
@ -221,11 +106,10 @@ public:
|
|||||||
}
|
}
|
||||||
uint32_t Length = NumItems * sizeof(T);
|
uint32_t Length = NumItems * sizeof(T);
|
||||||
if (Length / sizeof(T) != NumItems)
|
if (Length / sizeof(T) != NumItems)
|
||||||
return errorCodeToError(
|
return make_error<MSFError>(msf_error_code::invalid_format);
|
||||||
make_error_code(std::errc::illegal_byte_sequence));
|
|
||||||
if (Offset + Length > Stream.getLength())
|
if (Offset + Length > Stream.getLength())
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
BinaryStreamRef View = Stream.slice(Offset, Length);
|
ReadableStreamRef View = Stream.slice(Offset, Length);
|
||||||
Array = FixedStreamArray<T>(View);
|
Array = FixedStreamArray<T>(View);
|
||||||
Offset += Length;
|
Offset += Length;
|
||||||
return Error::success();
|
return Error::success();
|
||||||
@ -237,36 +121,15 @@ public:
|
|||||||
uint32_t getLength() const { return Stream.getLength(); }
|
uint32_t getLength() const { return Stream.getLength(); }
|
||||||
uint32_t bytesRemaining() const { return getLength() - getOffset(); }
|
uint32_t bytesRemaining() const { return getLength() - getOffset(); }
|
||||||
|
|
||||||
/// Advance the stream's offset by \p Amount bytes.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if at least \p Amount bytes remain in the
|
|
||||||
/// stream, otherwise returns an appropriate error code.
|
|
||||||
Error skip(uint32_t Amount);
|
Error skip(uint32_t Amount);
|
||||||
|
|
||||||
/// Examine the next byte of the underlying stream without advancing the
|
|
||||||
/// stream's offset. If the stream is empty the behavior is undefined.
|
|
||||||
///
|
|
||||||
/// \returns the next byte in the stream.
|
|
||||||
uint8_t peek() const;
|
uint8_t peek() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename T>
|
ReadableStreamRef Stream;
|
||||||
void readIntegersImpl(ArrayRef<uint8_t> Bytes, T &Dest) {
|
|
||||||
Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
|
|
||||||
Bytes.data(), Stream.getEndian());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename... Ts>
|
|
||||||
void readIntegersImpl(ArrayRef<uint8_t> Bytes, T &Dest, Ts &... Rest) {
|
|
||||||
auto Car = Bytes.take_front(sizeof(T));
|
|
||||||
auto Cdr = Bytes.drop_front(sizeof(T));
|
|
||||||
readIntegersImpl(Car, Dest);
|
|
||||||
readIntegersImpl(Cdr, Rest...);
|
|
||||||
}
|
|
||||||
|
|
||||||
BinaryStreamRef Stream;
|
|
||||||
uint32_t Offset;
|
uint32_t Offset;
|
||||||
};
|
};
|
||||||
|
} // namespace msf
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_SUPPORT_BINARYSTREAMREADER_H
|
#endif // LLVM_DEBUGINFO_MSF_STREAMREADER_H
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//===- BinaryStreamRef.h - A copyable reference to a stream -----*- C++ -*-===//
|
//===- StreamRef.h - A copyable reference to a stream -----------*- C++ -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
@ -7,30 +7,28 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LLVM_SUPPORT_BINARYSTREAMREF_H
|
#ifndef LLVM_DEBUGINFO_MSF_STREAMREF_H
|
||||||
#define LLVM_SUPPORT_BINARYSTREAMREF_H
|
#define LLVM_DEBUGINFO_MSF_STREAMREF_H
|
||||||
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
||||||
|
#include "llvm/DebugInfo/MSF/MSFError.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
namespace msf {
|
||||||
|
|
||||||
/// Common stuff for mutable and immutable StreamRefs.
|
template <class StreamType, class RefType> class StreamRefBase {
|
||||||
template <class StreamType, class RefType> class BinaryStreamRefBase {
|
|
||||||
public:
|
public:
|
||||||
BinaryStreamRefBase() : Stream(nullptr), ViewOffset(0), Length(0) {}
|
StreamRefBase() : Stream(nullptr), ViewOffset(0), Length(0) {}
|
||||||
BinaryStreamRefBase(StreamType &Stream, uint32_t Offset, uint32_t Length)
|
StreamRefBase(const StreamType &Stream, uint32_t Offset, uint32_t Length)
|
||||||
: Stream(&Stream), ViewOffset(Offset), Length(Length) {}
|
: Stream(&Stream), ViewOffset(Offset), Length(Length) {}
|
||||||
|
|
||||||
llvm::support::endianness getEndian() const { return Stream->getEndian(); }
|
|
||||||
|
|
||||||
uint32_t getLength() const { return Length; }
|
uint32_t getLength() const { return Length; }
|
||||||
const StreamType *getStream() const { return Stream; }
|
const StreamType *getStream() const { return Stream; }
|
||||||
|
|
||||||
/// Return a new BinaryStreamRef with the first \p N elements removed.
|
|
||||||
RefType drop_front(uint32_t N) const {
|
RefType drop_front(uint32_t N) const {
|
||||||
if (!Stream)
|
if (!Stream)
|
||||||
return RefType();
|
return RefType();
|
||||||
@ -39,7 +37,6 @@ public:
|
|||||||
return RefType(*Stream, ViewOffset + N, Length - N);
|
return RefType(*Stream, ViewOffset + N, Length - N);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a new BinaryStreamRef with only the first \p N elements remaining.
|
|
||||||
RefType keep_front(uint32_t N) const {
|
RefType keep_front(uint32_t N) const {
|
||||||
if (!Stream)
|
if (!Stream)
|
||||||
return RefType();
|
return RefType();
|
||||||
@ -47,8 +44,6 @@ public:
|
|||||||
return RefType(*Stream, ViewOffset, N);
|
return RefType(*Stream, ViewOffset, N);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a new BinaryStreamRef with the first \p Offset elements removed,
|
|
||||||
/// and retaining exactly \p Len elements.
|
|
||||||
RefType slice(uint32_t Offset, uint32_t Len) const {
|
RefType slice(uint32_t Offset, uint32_t Len) const {
|
||||||
return drop_front(Offset).keep_front(Len);
|
return drop_front(Offset).keep_front(Len);
|
||||||
}
|
}
|
||||||
@ -64,55 +59,40 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
StreamType *Stream;
|
const StreamType *Stream;
|
||||||
uint32_t ViewOffset;
|
uint32_t ViewOffset;
|
||||||
uint32_t Length;
|
uint32_t Length;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief BinaryStreamRef is to BinaryStream what ArrayRef is to an Array. It
|
class ReadableStreamRef
|
||||||
/// provides copy-semantics and read only access to a "window" of the underlying
|
: public StreamRefBase<ReadableStream, ReadableStreamRef> {
|
||||||
/// BinaryStream. Note that BinaryStreamRef is *not* a BinaryStream. That is to
|
|
||||||
/// say, it does not inherit and override the methods of BinaryStream. In
|
|
||||||
/// general, you should not pass around pointers or references to BinaryStreams
|
|
||||||
/// and use inheritance to achieve polymorphism. Instead, you should pass
|
|
||||||
/// around BinaryStreamRefs by value and achieve polymorphism that way.
|
|
||||||
class BinaryStreamRef
|
|
||||||
: public BinaryStreamRefBase<BinaryStream, BinaryStreamRef> {
|
|
||||||
public:
|
public:
|
||||||
BinaryStreamRef() = default;
|
ReadableStreamRef() = default;
|
||||||
BinaryStreamRef(BinaryStream &Stream)
|
ReadableStreamRef(const ReadableStream &Stream)
|
||||||
: BinaryStreamRefBase(Stream, 0, Stream.getLength()) {}
|
: StreamRefBase(Stream, 0, Stream.getLength()) {}
|
||||||
BinaryStreamRef(BinaryStream &Stream, uint32_t Offset, uint32_t Length)
|
ReadableStreamRef(const ReadableStream &Stream, uint32_t Offset,
|
||||||
: BinaryStreamRefBase(Stream, Offset, Length) {}
|
uint32_t Length)
|
||||||
|
: StreamRefBase(Stream, Offset, Length) {}
|
||||||
|
|
||||||
// Use BinaryStreamRef.slice() instead.
|
// Use StreamRef.slice() instead.
|
||||||
BinaryStreamRef(BinaryStreamRef &S, uint32_t Offset,
|
ReadableStreamRef(const ReadableStreamRef &S, uint32_t Offset,
|
||||||
uint32_t Length) = delete;
|
uint32_t Length) = delete;
|
||||||
|
|
||||||
/// Given an Offset into this StreamRef and a Size, return a reference to a
|
|
||||||
/// buffer owned by the stream.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the entire range of data is within the
|
|
||||||
/// bounds of this BinaryStreamRef's view and the implementation could read
|
|
||||||
/// the data, and an appropriate error code otherwise.
|
|
||||||
Error readBytes(uint32_t Offset, uint32_t Size,
|
Error readBytes(uint32_t Offset, uint32_t Size,
|
||||||
ArrayRef<uint8_t> &Buffer) const {
|
ArrayRef<uint8_t> &Buffer) const {
|
||||||
if (ViewOffset + Offset < Offset)
|
if (ViewOffset + Offset < Offset)
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
if (Size + Offset > Length)
|
if (Size + Offset > Length)
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
return Stream->readBytes(ViewOffset + Offset, Size, Buffer);
|
return Stream->readBytes(ViewOffset + Offset, Size, Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given an Offset into this BinaryStreamRef, return a reference to the
|
// Given an offset into the stream, read as much as possible without copying
|
||||||
/// largest buffer the stream could support without necessitating a copy.
|
// any data.
|
||||||
///
|
|
||||||
/// \returns a success error code if implementation could read the data,
|
|
||||||
/// and an appropriate error code otherwise.
|
|
||||||
Error readLongestContiguousChunk(uint32_t Offset,
|
Error readLongestContiguousChunk(uint32_t Offset,
|
||||||
ArrayRef<uint8_t> &Buffer) const {
|
ArrayRef<uint8_t> &Buffer) const {
|
||||||
if (Offset >= Length)
|
if (Offset >= Length)
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
|
|
||||||
if (auto EC = Stream->readLongestContiguousChunk(Offset, Buffer))
|
if (auto EC = Stream->readLongestContiguousChunk(Offset, Buffer))
|
||||||
return EC;
|
return EC;
|
||||||
@ -126,39 +106,30 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class WritableBinaryStreamRef
|
class WritableStreamRef
|
||||||
: public BinaryStreamRefBase<WritableBinaryStream,
|
: public StreamRefBase<WritableStream, WritableStreamRef> {
|
||||||
WritableBinaryStreamRef> {
|
|
||||||
public:
|
public:
|
||||||
WritableBinaryStreamRef() = default;
|
WritableStreamRef() = default;
|
||||||
WritableBinaryStreamRef(WritableBinaryStream &Stream)
|
WritableStreamRef(const WritableStream &Stream)
|
||||||
: BinaryStreamRefBase(Stream, 0, Stream.getLength()) {}
|
: StreamRefBase(Stream, 0, Stream.getLength()) {}
|
||||||
WritableBinaryStreamRef(WritableBinaryStream &Stream, uint32_t Offset,
|
WritableStreamRef(const WritableStream &Stream, uint32_t Offset,
|
||||||
uint32_t Length)
|
uint32_t Length)
|
||||||
: BinaryStreamRefBase(Stream, Offset, Length) {}
|
: StreamRefBase(Stream, Offset, Length) {}
|
||||||
|
|
||||||
// Use WritableBinaryStreamRef.slice() instead.
|
// Use StreamRef.slice() instead.
|
||||||
WritableBinaryStreamRef(WritableBinaryStreamRef &S, uint32_t Offset,
|
WritableStreamRef(const WritableStreamRef &S, uint32_t Offset,
|
||||||
uint32_t Length) = delete;
|
uint32_t Length) = delete;
|
||||||
|
|
||||||
/// Given an Offset into this WritableBinaryStreamRef and some input data,
|
|
||||||
/// writes the data to the underlying stream.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data could fit within the underlying
|
|
||||||
/// 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 {
|
Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const {
|
||||||
if (Data.size() + Offset > Length)
|
if (Data.size() + Offset > Length)
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
return Stream->writeBytes(ViewOffset + Offset, Data);
|
return Stream->writeBytes(ViewOffset + Offset, Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
operator BinaryStreamRef() { return BinaryStreamRef(*Stream); }
|
Error commit() const { return Stream->commit(); }
|
||||||
|
|
||||||
/// \brief For buffered streams, commits changes to the backing store.
|
|
||||||
Error commit() { return Stream->commit(); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end namespace msf
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_SUPPORT_BINARYSTREAMREF_H
|
#endif // LLVM_DEBUGINFO_MSF_STREAMREF_H
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//===- BinaryStreamWriter.h - Writes objects to a BinaryStream ---*- C++-*-===//
|
//===- StreamWriter.h - Writes bytes and objects to a stream ----*- C++ -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
@ -7,121 +7,55 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LLVM_SUPPORT_BINARYSTREAMWRITER_H
|
#ifndef LLVM_DEBUGINFO_MSF_STREAMWRITER_H
|
||||||
#define LLVM_SUPPORT_BINARYSTREAMWRITER_H
|
#define LLVM_DEBUGINFO_MSF_STREAMWRITER_H
|
||||||
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
|
||||||
|
#include "llvm/DebugInfo/MSF/MSFError.h"
|
||||||
#include "llvm/Support/Endian.h"
|
#include "llvm/Support/Endian.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
namespace msf {
|
||||||
|
|
||||||
/// \brief Provides write only access to a subclass of `WritableBinaryStream`.
|
class StreamWriter {
|
||||||
/// Provides bounds checking and helpers for writing certain common data types
|
|
||||||
/// such as null-terminated strings, integers in various flavors of endianness,
|
|
||||||
/// etc. Can be subclassed to provide reading and writing of custom datatypes,
|
|
||||||
/// although no methods are overridable.
|
|
||||||
class BinaryStreamWriter {
|
|
||||||
public:
|
public:
|
||||||
BinaryStreamWriter() = default;
|
StreamWriter() = default;
|
||||||
explicit BinaryStreamWriter(WritableBinaryStreamRef Stream);
|
explicit StreamWriter(WritableStreamRef Stream);
|
||||||
virtual ~BinaryStreamWriter() {}
|
|
||||||
|
|
||||||
/// Write the bytes specified in \p Buffer to the underlying stream.
|
|
||||||
/// On success, updates the offset so that subsequent writes will occur
|
|
||||||
/// at the next unwritten position.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully written,
|
|
||||||
/// otherwise returns an appropriate error code.
|
|
||||||
Error writeBytes(ArrayRef<uint8_t> Buffer);
|
Error writeBytes(ArrayRef<uint8_t> Buffer);
|
||||||
|
|
||||||
/// Write the the integer \p Value to the underlying stream in the
|
template <typename T>
|
||||||
/// specified endianness. On success, updates the offset so that
|
Error writeInteger(T Value,
|
||||||
/// subsequent writes occur at the next unwritten position.
|
llvm::support::endianness Endian = llvm::support::native) {
|
||||||
///
|
static_assert(std::is_integral<T>::value,
|
||||||
/// \returns a success error code if the data was successfully written,
|
"Cannot call writeInteger with non-integral value!");
|
||||||
/// otherwise returns an appropriate error code.
|
uint8_t Buffer[sizeof(T)];
|
||||||
template <typename T> Error writeInteger(T Value) {
|
llvm::support::endian::write<T, llvm::support::unaligned>(Buffer, Value,
|
||||||
return writeIntegers(Value);
|
Endian);
|
||||||
}
|
|
||||||
|
|
||||||
/// Write a \p ByteSize byte integer to the stream, updating the writer's
|
|
||||||
/// position if successful.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully written,
|
|
||||||
/// otherwise returns an appropriate error code.
|
|
||||||
Error writeInteger(uint64_t Value, uint32_t ByteSize);
|
|
||||||
|
|
||||||
/// Write a list of integers into the underlying stream and update the
|
|
||||||
/// stream's offset. On success, updates the offset so that subsequent writes
|
|
||||||
/// occur at the next unwritten position. Use of this method is more
|
|
||||||
/// efficient than calling `writeInteger` multiple times because this performs
|
|
||||||
/// bounds checking only once, and requires only a single error check by the
|
|
||||||
/// user.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully written,
|
|
||||||
/// otherwise returns an appropriate error code.
|
|
||||||
template <typename... Ts> Error writeIntegers(Ts... Ints) {
|
|
||||||
uint8_t Buffer[sizeof_sum<Ts...>::value];
|
|
||||||
|
|
||||||
writeIntegersImpl(Buffer, Ints...);
|
|
||||||
return writeBytes(Buffer);
|
return writeBytes(Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Similar to writeInteger
|
Error writeZeroString(StringRef Str);
|
||||||
template <typename T> Error writeEnum(T Num) {
|
Error writeFixedString(StringRef Str);
|
||||||
|
Error writeStreamRef(ReadableStreamRef Ref);
|
||||||
|
Error writeStreamRef(ReadableStreamRef Ref, uint32_t Size);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Error writeEnum(T Num,
|
||||||
|
llvm::support::endianness Endian = llvm::support::native) {
|
||||||
static_assert(std::is_enum<T>::value,
|
static_assert(std::is_enum<T>::value,
|
||||||
"Cannot call writeEnum with non-Enum type");
|
"Cannot call writeEnum with non-Enum type");
|
||||||
|
|
||||||
using U = typename std::underlying_type<T>::type;
|
using U = typename std::underlying_type<T>::type;
|
||||||
return writeInteger<U>(static_cast<U>(Num));
|
return writeInteger<U>(static_cast<U>(Num), Endian);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write the the string \p Str to the underlying stream followed by a null
|
|
||||||
/// terminator. On success, updates the offset so that subsequent writes
|
|
||||||
/// occur at the next unwritten position. \p Str need not be null terminated
|
|
||||||
/// on input.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully written,
|
|
||||||
/// otherwise returns an appropriate error code.
|
|
||||||
Error writeCString(StringRef Str);
|
|
||||||
|
|
||||||
/// Write the the string \p Str to the underlying stream without a null
|
|
||||||
/// terminator. On success, updates the offset so that subsequent writes
|
|
||||||
/// occur at the next unwritten position.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully written,
|
|
||||||
/// otherwise returns an appropriate error code.
|
|
||||||
Error writeFixedString(StringRef Str);
|
|
||||||
|
|
||||||
/// Efficiently reads all data from \p Ref, and writes it to this stream.
|
|
||||||
/// This operation will not invoke any copies of the source data, regardless
|
|
||||||
/// of the source stream's implementation.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully written,
|
|
||||||
/// otherwise returns an appropriate error code.
|
|
||||||
Error writeStreamRef(BinaryStreamRef Ref);
|
|
||||||
|
|
||||||
/// Efficiently reads \p Size bytes from \p Ref, and writes it to this stream.
|
|
||||||
/// This operation will not invoke any copies of the source data, regardless
|
|
||||||
/// of the source stream's implementation.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully written,
|
|
||||||
/// otherwise returns an appropriate error code.
|
|
||||||
Error writeStreamRef(BinaryStreamRef Ref, uint32_t Size);
|
|
||||||
|
|
||||||
/// Writes the object \p Obj to the underlying stream, as if by using memcpy.
|
|
||||||
/// It is up to the caller to ensure that type of \p Obj can be safely copied
|
|
||||||
/// in this fashion, as no checks are made to ensure that this is safe.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully written,
|
|
||||||
/// otherwise returns an appropriate error code.
|
|
||||||
template <typename T> Error writeObject(const T &Obj) {
|
template <typename T> Error writeObject(const T &Obj) {
|
||||||
static_assert(!std::is_pointer<T>::value,
|
static_assert(!std::is_pointer<T>::value,
|
||||||
"writeObject should not be used with pointers, to write "
|
"writeObject should not be used with pointers, to write "
|
||||||
@ -131,38 +65,23 @@ public:
|
|||||||
ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T)));
|
ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes an array of objects of type T to the underlying stream, as if by
|
|
||||||
/// using memcpy. It is up to the caller to ensure that type of \p Obj can
|
|
||||||
/// be safely copied in this fashion, as no checks are made to ensure that
|
|
||||||
/// this is safe.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully written,
|
|
||||||
/// otherwise returns an appropriate error code.
|
|
||||||
template <typename T> Error writeArray(ArrayRef<T> Array) {
|
template <typename T> Error writeArray(ArrayRef<T> Array) {
|
||||||
if (Array.empty())
|
if (Array.empty())
|
||||||
return Error::success();
|
return Error::success();
|
||||||
|
|
||||||
if (Array.size() > UINT32_MAX / sizeof(T))
|
if (Array.size() > UINT32_MAX / sizeof(T))
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
|
|
||||||
return writeBytes(
|
return writeBytes(
|
||||||
ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Array.data()),
|
ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Array.data()),
|
||||||
Array.size() * sizeof(T)));
|
Array.size() * sizeof(T)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes all data from the array \p Array to the underlying stream.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully written,
|
|
||||||
/// otherwise returns an appropriate error code.
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
Error writeArray(VarStreamArray<T, U> Array) {
|
Error writeArray(VarStreamArray<T, U> Array) {
|
||||||
return writeStreamRef(Array.getUnderlyingStream());
|
return writeStreamRef(Array.getUnderlyingStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes all elements from the array \p Array to the underlying stream.
|
|
||||||
///
|
|
||||||
/// \returns a success error code if the data was successfully written,
|
|
||||||
/// otherwise returns an appropriate error code.
|
|
||||||
template <typename T> Error writeArray(FixedStreamArray<T> Array) {
|
template <typename T> Error writeArray(FixedStreamArray<T> Array) {
|
||||||
return writeStreamRef(Array.getUnderlyingStream());
|
return writeStreamRef(Array.getUnderlyingStream());
|
||||||
}
|
}
|
||||||
@ -172,28 +91,12 @@ public:
|
|||||||
uint32_t getLength() const { return Stream.getLength(); }
|
uint32_t getLength() const { return Stream.getLength(); }
|
||||||
uint32_t bytesRemaining() const { return getLength() - getOffset(); }
|
uint32_t bytesRemaining() const { return getLength() - getOffset(); }
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
template <typename T>
|
WritableStreamRef Stream;
|
||||||
void writeIntegersImpl(MutableArrayRef<uint8_t> Buffer, T Value) {
|
|
||||||
static_assert(std::is_integral<T>::value,
|
|
||||||
"Cannot call writeInteger with non-integral value!");
|
|
||||||
assert(Buffer.size() == sizeof(T));
|
|
||||||
llvm::support::endian::write<T, llvm::support::unaligned>(
|
|
||||||
Buffer.data(), Value, Stream.getEndian());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename... Ts>
|
|
||||||
void writeIntegersImpl(MutableArrayRef<uint8_t> Buffer, T Car, Ts... Cdr) {
|
|
||||||
auto First = Buffer.take_front(sizeof(T));
|
|
||||||
auto Rest = Buffer.drop_front(sizeof(T));
|
|
||||||
writeIntegersImpl(First, Car);
|
|
||||||
writeIntegersImpl(Rest, Cdr...);
|
|
||||||
}
|
|
||||||
|
|
||||||
WritableBinaryStreamRef Stream;
|
|
||||||
uint32_t Offset = 0;
|
uint32_t Offset = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end namespace msf
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_SUPPORT_BINARYSTREAMWRITER_H
|
#endif // LLVM_DEBUGINFO_MSF_STREAMWRITER_H
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
|
#include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
|
||||||
#include "llvm/Support/Allocator.h"
|
#include "llvm/Support/Allocator.h"
|
||||||
#include "llvm/Support/Endian.h"
|
#include "llvm/Support/Endian.h"
|
||||||
@ -39,33 +37,29 @@ struct MSFLayout;
|
|||||||
/// the MSF. MappedBlockStream provides methods for reading from and writing
|
/// the MSF. MappedBlockStream provides methods for reading from and writing
|
||||||
/// to one of these streams transparently, as if it were a contiguous sequence
|
/// to one of these streams transparently, as if it were a contiguous sequence
|
||||||
/// of bytes.
|
/// of bytes.
|
||||||
class MappedBlockStream : public BinaryStream {
|
class MappedBlockStream : public ReadableStream {
|
||||||
friend class WritableMappedBlockStream;
|
friend class WritableMappedBlockStream;
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<MappedBlockStream>
|
static std::unique_ptr<MappedBlockStream>
|
||||||
createStream(uint32_t BlockSize, uint32_t NumBlocks,
|
createStream(uint32_t BlockSize, uint32_t NumBlocks,
|
||||||
const MSFStreamLayout &Layout, BinaryStreamRef MsfData);
|
const MSFStreamLayout &Layout, const ReadableStream &MsfData);
|
||||||
|
|
||||||
static std::unique_ptr<MappedBlockStream>
|
static std::unique_ptr<MappedBlockStream>
|
||||||
createIndexedStream(const MSFLayout &Layout, BinaryStreamRef MsfData,
|
createIndexedStream(const MSFLayout &Layout, const ReadableStream &MsfData,
|
||||||
uint32_t StreamIndex);
|
uint32_t StreamIndex);
|
||||||
|
|
||||||
static std::unique_ptr<MappedBlockStream>
|
static std::unique_ptr<MappedBlockStream>
|
||||||
createFpmStream(const MSFLayout &Layout, BinaryStreamRef MsfData);
|
createFpmStream(const MSFLayout &Layout, const ReadableStream &MsfData);
|
||||||
|
|
||||||
static std::unique_ptr<MappedBlockStream>
|
static std::unique_ptr<MappedBlockStream>
|
||||||
createDirectoryStream(const MSFLayout &Layout, BinaryStreamRef MsfData);
|
createDirectoryStream(const MSFLayout &Layout, const ReadableStream &MsfData);
|
||||||
|
|
||||||
llvm::support::endianness getEndian() const override {
|
|
||||||
return llvm::support::little;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error readBytes(uint32_t Offset, uint32_t Size,
|
Error readBytes(uint32_t Offset, uint32_t Size,
|
||||||
ArrayRef<uint8_t> &Buffer) override;
|
ArrayRef<uint8_t> &Buffer) const override;
|
||||||
Error readLongestContiguousChunk(uint32_t Offset,
|
Error readLongestContiguousChunk(uint32_t Offset,
|
||||||
ArrayRef<uint8_t> &Buffer) override;
|
ArrayRef<uint8_t> &Buffer) const override;
|
||||||
|
|
||||||
uint32_t getLength() override;
|
uint32_t getLength() const override;
|
||||||
|
|
||||||
uint32_t getNumBytesCopied() const;
|
uint32_t getNumBytesCopied() const;
|
||||||
|
|
||||||
@ -80,56 +74,51 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
MappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks,
|
MappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks,
|
||||||
const MSFStreamLayout &StreamLayout,
|
const MSFStreamLayout &StreamLayout,
|
||||||
BinaryStreamRef MsfData);
|
const ReadableStream &MsfData);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const MSFStreamLayout &getStreamLayout() const { return StreamLayout; }
|
const MSFStreamLayout &getStreamLayout() const { return StreamLayout; }
|
||||||
void fixCacheAfterWrite(uint32_t Offset, ArrayRef<uint8_t> Data) const;
|
void fixCacheAfterWrite(uint32_t Offset, ArrayRef<uint8_t> Data) const;
|
||||||
|
|
||||||
Error readBytes(uint32_t Offset, MutableArrayRef<uint8_t> Buffer);
|
Error readBytes(uint32_t Offset, MutableArrayRef<uint8_t> Buffer) const;
|
||||||
bool tryReadContiguously(uint32_t Offset, uint32_t Size,
|
bool tryReadContiguously(uint32_t Offset, uint32_t Size,
|
||||||
ArrayRef<uint8_t> &Buffer);
|
ArrayRef<uint8_t> &Buffer) const;
|
||||||
|
|
||||||
const uint32_t BlockSize;
|
const uint32_t BlockSize;
|
||||||
const uint32_t NumBlocks;
|
const uint32_t NumBlocks;
|
||||||
const MSFStreamLayout StreamLayout;
|
const MSFStreamLayout StreamLayout;
|
||||||
BinaryStreamRef MsfData;
|
const ReadableStream &MsfData;
|
||||||
|
|
||||||
typedef MutableArrayRef<uint8_t> CacheEntry;
|
typedef MutableArrayRef<uint8_t> CacheEntry;
|
||||||
llvm::BumpPtrAllocator Pool;
|
mutable llvm::BumpPtrAllocator Pool;
|
||||||
DenseMap<uint32_t, std::vector<CacheEntry>> CacheMap;
|
mutable DenseMap<uint32_t, std::vector<CacheEntry>> CacheMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WritableMappedBlockStream : public WritableBinaryStream {
|
class WritableMappedBlockStream : public WritableStream {
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<WritableMappedBlockStream>
|
static std::unique_ptr<WritableMappedBlockStream>
|
||||||
createStream(uint32_t BlockSize, uint32_t NumBlocks,
|
createStream(uint32_t BlockSize, uint32_t NumBlocks,
|
||||||
const MSFStreamLayout &Layout, WritableBinaryStreamRef MsfData);
|
const MSFStreamLayout &Layout, const WritableStream &MsfData);
|
||||||
|
|
||||||
static std::unique_ptr<WritableMappedBlockStream>
|
static std::unique_ptr<WritableMappedBlockStream>
|
||||||
createIndexedStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData,
|
createIndexedStream(const MSFLayout &Layout, const WritableStream &MsfData,
|
||||||
uint32_t StreamIndex);
|
uint32_t StreamIndex);
|
||||||
|
|
||||||
static std::unique_ptr<WritableMappedBlockStream>
|
static std::unique_ptr<WritableMappedBlockStream>
|
||||||
createDirectoryStream(const MSFLayout &Layout,
|
createDirectoryStream(const MSFLayout &Layout, const WritableStream &MsfData);
|
||||||
WritableBinaryStreamRef MsfData);
|
|
||||||
|
|
||||||
static std::unique_ptr<WritableMappedBlockStream>
|
static std::unique_ptr<WritableMappedBlockStream>
|
||||||
createFpmStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData);
|
createFpmStream(const MSFLayout &Layout, const WritableStream &MsfData);
|
||||||
|
|
||||||
llvm::support::endianness getEndian() const override {
|
|
||||||
return llvm::support::little;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error readBytes(uint32_t Offset, uint32_t Size,
|
Error readBytes(uint32_t Offset, uint32_t Size,
|
||||||
ArrayRef<uint8_t> &Buffer) override;
|
ArrayRef<uint8_t> &Buffer) const override;
|
||||||
Error readLongestContiguousChunk(uint32_t Offset,
|
Error readLongestContiguousChunk(uint32_t Offset,
|
||||||
ArrayRef<uint8_t> &Buffer) override;
|
ArrayRef<uint8_t> &Buffer) const override;
|
||||||
uint32_t getLength() override;
|
uint32_t getLength() const override;
|
||||||
|
|
||||||
Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) override;
|
Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) const override;
|
||||||
|
|
||||||
Error commit() override;
|
Error commit() const override;
|
||||||
|
|
||||||
const MSFStreamLayout &getStreamLayout() const {
|
const MSFStreamLayout &getStreamLayout() const {
|
||||||
return ReadInterface.getStreamLayout();
|
return ReadInterface.getStreamLayout();
|
||||||
@ -141,12 +130,12 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
WritableMappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks,
|
WritableMappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks,
|
||||||
const MSFStreamLayout &StreamLayout,
|
const MSFStreamLayout &StreamLayout,
|
||||||
WritableBinaryStreamRef MsfData);
|
const WritableStream &MsfData);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MappedBlockStream ReadInterface;
|
MappedBlockStream ReadInterface;
|
||||||
|
|
||||||
WritableBinaryStreamRef WriteInterface;
|
const WritableStream &WriteInterface;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace pdb
|
} // end namespace pdb
|
||||||
|
@ -12,8 +12,6 @@
|
|||||||
|
|
||||||
#include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
|
#include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
|
||||||
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/ModInfo.h"
|
#include "llvm/DebugInfo/PDB/Native/ModInfo.h"
|
||||||
@ -72,11 +70,11 @@ public:
|
|||||||
|
|
||||||
Expected<StringRef> getFileNameForIndex(uint32_t Index) const;
|
Expected<StringRef> getFileNameForIndex(uint32_t Index) const;
|
||||||
|
|
||||||
FixedStreamArray<object::coff_section> getSectionHeaders();
|
msf::FixedStreamArray<object::coff_section> getSectionHeaders();
|
||||||
|
|
||||||
FixedStreamArray<object::FpoData> getFpoRecords();
|
msf::FixedStreamArray<object::FpoData> getFpoRecords();
|
||||||
|
|
||||||
FixedStreamArray<SecMapEntry> getSectionMap() const;
|
msf::FixedStreamArray<SecMapEntry> getSectionMap() const;
|
||||||
void visitSectionContributions(ISectionContribVisitor &Visitor) const;
|
void visitSectionContributions(ISectionContribVisitor &Visitor) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -93,28 +91,28 @@ private:
|
|||||||
std::vector<ModuleInfoEx> ModuleInfos;
|
std::vector<ModuleInfoEx> ModuleInfos;
|
||||||
StringTable ECNames;
|
StringTable ECNames;
|
||||||
|
|
||||||
BinaryStreamRef ModInfoSubstream;
|
msf::ReadableStreamRef ModInfoSubstream;
|
||||||
BinaryStreamRef SecContrSubstream;
|
msf::ReadableStreamRef SecContrSubstream;
|
||||||
BinaryStreamRef SecMapSubstream;
|
msf::ReadableStreamRef SecMapSubstream;
|
||||||
BinaryStreamRef FileInfoSubstream;
|
msf::ReadableStreamRef FileInfoSubstream;
|
||||||
BinaryStreamRef TypeServerMapSubstream;
|
msf::ReadableStreamRef TypeServerMapSubstream;
|
||||||
BinaryStreamRef ECSubstream;
|
msf::ReadableStreamRef ECSubstream;
|
||||||
|
|
||||||
BinaryStreamRef NamesBuffer;
|
msf::ReadableStreamRef NamesBuffer;
|
||||||
|
|
||||||
FixedStreamArray<support::ulittle16_t> DbgStreams;
|
msf::FixedStreamArray<support::ulittle16_t> DbgStreams;
|
||||||
|
|
||||||
PdbRaw_DbiSecContribVer SectionContribVersion;
|
PdbRaw_DbiSecContribVer SectionContribVersion;
|
||||||
FixedStreamArray<SectionContrib> SectionContribs;
|
msf::FixedStreamArray<SectionContrib> SectionContribs;
|
||||||
FixedStreamArray<SectionContrib2> SectionContribs2;
|
msf::FixedStreamArray<SectionContrib2> SectionContribs2;
|
||||||
FixedStreamArray<SecMapEntry> SectionMap;
|
msf::FixedStreamArray<SecMapEntry> SectionMap;
|
||||||
FixedStreamArray<support::little32_t> FileNameOffsets;
|
msf::FixedStreamArray<support::little32_t> FileNameOffsets;
|
||||||
|
|
||||||
std::unique_ptr<msf::MappedBlockStream> SectionHeaderStream;
|
std::unique_ptr<msf::MappedBlockStream> SectionHeaderStream;
|
||||||
FixedStreamArray<object::coff_section> SectionHeaders;
|
msf::FixedStreamArray<object::coff_section> SectionHeaders;
|
||||||
|
|
||||||
std::unique_ptr<msf::MappedBlockStream> FpoStream;
|
std::unique_ptr<msf::MappedBlockStream> FpoStream;
|
||||||
FixedStreamArray<object::FpoData> FpoRecords;
|
msf::FixedStreamArray<object::FpoData> FpoRecords;
|
||||||
|
|
||||||
const DbiStreamHeader *Header;
|
const DbiStreamHeader *Header;
|
||||||
};
|
};
|
||||||
|
@ -60,7 +60,7 @@ public:
|
|||||||
|
|
||||||
Error finalizeMsfLayout();
|
Error finalizeMsfLayout();
|
||||||
|
|
||||||
Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer);
|
Error commit(const msf::MSFLayout &Layout, const msf::WritableStream &Buffer);
|
||||||
|
|
||||||
// A helper function to create Section Contributions from COFF input
|
// A helper function to create Section Contributions from COFF input
|
||||||
// section headers.
|
// section headers.
|
||||||
@ -112,9 +112,9 @@ private:
|
|||||||
|
|
||||||
StringMap<uint32_t> SourceFileNames;
|
StringMap<uint32_t> SourceFileNames;
|
||||||
|
|
||||||
WritableBinaryStreamRef NamesBuffer;
|
msf::WritableStreamRef NamesBuffer;
|
||||||
MutableBinaryByteStream ModInfoBuffer;
|
msf::MutableByteStream ModInfoBuffer;
|
||||||
MutableBinaryByteStream FileInfoBuffer;
|
msf::MutableByteStream FileInfoBuffer;
|
||||||
ArrayRef<SectionContrib> SectionContribs;
|
ArrayRef<SectionContrib> SectionContribs;
|
||||||
ArrayRef<SecMapEntry> SectionMap;
|
ArrayRef<SecMapEntry> SectionMap;
|
||||||
llvm::SmallVector<DebugStream, (int)DbgHeaderType::Max> DbgStreams;
|
llvm::SmallVector<DebugStream, (int)DbgHeaderType::Max> DbgStreams;
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#ifndef LLVM_DEBUGINFO_PDB_RAW_GLOBALS_STREAM_H
|
#ifndef LLVM_DEBUGINFO_PDB_RAW_GLOBALS_STREAM_H
|
||||||
#define LLVM_DEBUGINFO_PDB_RAW_GLOBALS_STREAM_H
|
#define LLVM_DEBUGINFO_PDB_RAW_GLOBALS_STREAM_H
|
||||||
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
||||||
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
|
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
|
||||||
@ -28,15 +27,15 @@ public:
|
|||||||
explicit GlobalsStream(std::unique_ptr<msf::MappedBlockStream> Stream);
|
explicit GlobalsStream(std::unique_ptr<msf::MappedBlockStream> Stream);
|
||||||
~GlobalsStream();
|
~GlobalsStream();
|
||||||
Error commit();
|
Error commit();
|
||||||
FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
|
msf::FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
|
||||||
return HashBuckets;
|
return HashBuckets;
|
||||||
}
|
}
|
||||||
uint32_t getNumBuckets() const { return NumBuckets; }
|
uint32_t getNumBuckets() const { return NumBuckets; }
|
||||||
Error reload();
|
Error reload();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FixedStreamArray<support::ulittle32_t> HashBuckets;
|
msf::FixedStreamArray<support::ulittle32_t> HashBuckets;
|
||||||
FixedStreamArray<PSHashRecord> HashRecords;
|
msf::FixedStreamArray<PSHashRecord> HashRecords;
|
||||||
uint32_t NumBuckets;
|
uint32_t NumBuckets;
|
||||||
std::unique_ptr<msf::MappedBlockStream> Stream;
|
std::unique_ptr<msf::MappedBlockStream> Stream;
|
||||||
};
|
};
|
||||||
|
@ -42,10 +42,10 @@ public:
|
|||||||
HashTable();
|
HashTable();
|
||||||
explicit HashTable(uint32_t Capacity);
|
explicit HashTable(uint32_t Capacity);
|
||||||
|
|
||||||
Error load(BinaryStreamReader &Stream);
|
Error load(msf::StreamReader &Stream);
|
||||||
|
|
||||||
uint32_t calculateSerializedLength() const;
|
uint32_t calculateSerializedLength() const;
|
||||||
Error commit(BinaryStreamWriter &Writer) const;
|
Error commit(msf::StreamWriter &Writer) const;
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
@ -71,9 +71,9 @@ private:
|
|||||||
static uint32_t maxLoad(uint32_t capacity);
|
static uint32_t maxLoad(uint32_t capacity);
|
||||||
void grow();
|
void grow();
|
||||||
|
|
||||||
static Error readSparseBitVector(BinaryStreamReader &Stream,
|
static Error readSparseBitVector(msf::StreamReader &Stream,
|
||||||
SparseBitVector<> &V);
|
SparseBitVector<> &V);
|
||||||
static Error writeSparseBitVector(BinaryStreamWriter &Writer,
|
static Error writeSparseBitVector(msf::StreamWriter &Writer,
|
||||||
SparseBitVector<> &Vec);
|
SparseBitVector<> &Vec);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,10 +19,9 @@
|
|||||||
#include "llvm/DebugInfo/PDB/PDBTypes.h"
|
#include "llvm/DebugInfo/PDB/PDBTypes.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class WritableBinaryStream;
|
|
||||||
|
|
||||||
namespace msf {
|
namespace msf {
|
||||||
class MSFBuilder;
|
class MSFBuilder;
|
||||||
|
class StreamWriter;
|
||||||
}
|
}
|
||||||
namespace pdb {
|
namespace pdb {
|
||||||
class PDBFile;
|
class PDBFile;
|
||||||
@ -44,7 +43,7 @@ public:
|
|||||||
Error finalizeMsfLayout();
|
Error finalizeMsfLayout();
|
||||||
|
|
||||||
Error commit(const msf::MSFLayout &Layout,
|
Error commit(const msf::MSFLayout &Layout,
|
||||||
WritableBinaryStreamRef Buffer) const;
|
const msf::WritableStream &Buffer) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
msf::MSFBuilder &Msf;
|
msf::MSFBuilder &Msf;
|
||||||
|
@ -30,7 +30,7 @@ public:
|
|||||||
ModInfo(const ModInfo &Info);
|
ModInfo(const ModInfo &Info);
|
||||||
~ModInfo();
|
~ModInfo();
|
||||||
|
|
||||||
static Error initialize(BinaryStreamRef Stream, ModInfo &Info);
|
static Error initialize(msf::ReadableStreamRef Stream, ModInfo &Info);
|
||||||
|
|
||||||
bool hasECInfo() const;
|
bool hasECInfo() const;
|
||||||
uint16_t getTypeServerIndex() const;
|
uint16_t getTypeServerIndex() const;
|
||||||
@ -63,8 +63,10 @@ struct ModuleInfoEx {
|
|||||||
|
|
||||||
} // end namespace pdb
|
} // end namespace pdb
|
||||||
|
|
||||||
|
namespace msf {
|
||||||
|
|
||||||
template <> struct VarStreamArrayExtractor<pdb::ModInfo> {
|
template <> struct VarStreamArrayExtractor<pdb::ModInfo> {
|
||||||
Error operator()(BinaryStreamRef Stream, uint32_t &Length,
|
Error operator()(ReadableStreamRef Stream, uint32_t &Length,
|
||||||
pdb::ModInfo &Info) const {
|
pdb::ModInfo &Info) const {
|
||||||
if (auto EC = pdb::ModInfo::initialize(Stream, Info))
|
if (auto EC = pdb::ModInfo::initialize(Stream, Info))
|
||||||
return EC;
|
return EC;
|
||||||
@ -73,6 +75,8 @@ template <> struct VarStreamArrayExtractor<pdb::ModInfo> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end namespace msf
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_DEBUGINFO_PDB_RAW_MODINFO_H
|
#endif // LLVM_DEBUGINFO_PDB_RAW_MODINFO_H
|
||||||
|
@ -50,9 +50,9 @@ private:
|
|||||||
std::unique_ptr<msf::MappedBlockStream> Stream;
|
std::unique_ptr<msf::MappedBlockStream> Stream;
|
||||||
|
|
||||||
codeview::CVSymbolArray SymbolsSubstream;
|
codeview::CVSymbolArray SymbolsSubstream;
|
||||||
BinaryStreamRef LinesSubstream;
|
msf::ReadableStreamRef LinesSubstream;
|
||||||
BinaryStreamRef C13LinesSubstream;
|
msf::ReadableStreamRef C13LinesSubstream;
|
||||||
BinaryStreamRef GlobalRefsSubstream;
|
msf::ReadableStreamRef GlobalRefsSubstream;
|
||||||
|
|
||||||
codeview::ModuleSubstreamArray LineInfo;
|
codeview::ModuleSubstreamArray LineInfo;
|
||||||
};
|
};
|
||||||
|
@ -17,9 +17,10 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class BinaryStreamReader;
|
namespace msf {
|
||||||
class BinaryStreamWriter;
|
class StreamReader;
|
||||||
|
class StreamWriter;
|
||||||
|
}
|
||||||
namespace pdb {
|
namespace pdb {
|
||||||
class NamedStreamMapBuilder;
|
class NamedStreamMapBuilder;
|
||||||
class NamedStreamMap {
|
class NamedStreamMap {
|
||||||
@ -32,8 +33,8 @@ class NamedStreamMap {
|
|||||||
public:
|
public:
|
||||||
NamedStreamMap();
|
NamedStreamMap();
|
||||||
|
|
||||||
Error load(BinaryStreamReader &Stream);
|
Error load(msf::StreamReader &Stream);
|
||||||
Error commit(BinaryStreamWriter &Writer) const;
|
Error commit(msf::StreamWriter &Writer) const;
|
||||||
uint32_t finalize();
|
uint32_t finalize();
|
||||||
|
|
||||||
bool get(StringRef Stream, uint32_t &StreamNo) const;
|
bool get(StringRef Stream, uint32_t &StreamNo) const;
|
||||||
|
@ -12,8 +12,6 @@
|
|||||||
|
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
||||||
#include "llvm/DebugInfo/MSF/IMSFFile.h"
|
#include "llvm/DebugInfo/MSF/IMSFFile.h"
|
||||||
#include "llvm/DebugInfo/MSF/MSFCommon.h"
|
#include "llvm/DebugInfo/MSF/MSFCommon.h"
|
||||||
@ -44,7 +42,7 @@ class PDBFile : public msf::IMSFFile {
|
|||||||
friend PDBFileBuilder;
|
friend PDBFileBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PDBFile(StringRef Path, std::unique_ptr<BinaryStream> PdbFileBuffer,
|
PDBFile(StringRef Path, std::unique_ptr<msf::ReadableStream> PdbFileBuffer,
|
||||||
BumpPtrAllocator &Allocator);
|
BumpPtrAllocator &Allocator);
|
||||||
~PDBFile() override;
|
~PDBFile() override;
|
||||||
|
|
||||||
@ -82,7 +80,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const msf::MSFLayout &getMsfLayout() const { return ContainerLayout; }
|
const msf::MSFLayout &getMsfLayout() const { return ContainerLayout; }
|
||||||
BinaryStreamRef getMsfBuffer() const { return *Buffer; }
|
const msf::ReadableStream &getMsfBuffer() const { return *Buffer; }
|
||||||
|
|
||||||
ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const;
|
ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const;
|
||||||
|
|
||||||
@ -112,13 +110,13 @@ public:
|
|||||||
private:
|
private:
|
||||||
Expected<std::unique_ptr<msf::MappedBlockStream>>
|
Expected<std::unique_ptr<msf::MappedBlockStream>>
|
||||||
safelyCreateIndexedStream(const msf::MSFLayout &Layout,
|
safelyCreateIndexedStream(const msf::MSFLayout &Layout,
|
||||||
BinaryStreamRef MsfData,
|
const msf::ReadableStream &MsfData,
|
||||||
uint32_t StreamIndex) const;
|
uint32_t StreamIndex) const;
|
||||||
|
|
||||||
std::string FilePath;
|
std::string FilePath;
|
||||||
BumpPtrAllocator &Allocator;
|
BumpPtrAllocator &Allocator;
|
||||||
|
|
||||||
std::unique_ptr<BinaryStream> Buffer;
|
std::unique_ptr<msf::ReadableStream> Buffer;
|
||||||
|
|
||||||
std::vector<uint32_t> FpmPages;
|
std::vector<uint32_t> FpmPages;
|
||||||
msf::MSFLayout ContainerLayout;
|
msf::MSFLayout ContainerLayout;
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
|
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
|
||||||
#include "llvm/DebugInfo/PDB/PDBTypes.h"
|
#include "llvm/DebugInfo/PDB/PDBTypes.h"
|
||||||
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
@ -39,16 +38,16 @@ public:
|
|||||||
uint32_t getNumBuckets() const { return NumBuckets; }
|
uint32_t getNumBuckets() const { return NumBuckets; }
|
||||||
iterator_range<codeview::CVSymbolArray::Iterator>
|
iterator_range<codeview::CVSymbolArray::Iterator>
|
||||||
getSymbols(bool *HadError) const;
|
getSymbols(bool *HadError) const;
|
||||||
FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
|
msf::FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
|
||||||
return HashBuckets;
|
return HashBuckets;
|
||||||
}
|
}
|
||||||
FixedStreamArray<support::ulittle32_t> getAddressMap() const {
|
msf::FixedStreamArray<support::ulittle32_t> getAddressMap() const {
|
||||||
return AddressMap;
|
return AddressMap;
|
||||||
}
|
}
|
||||||
FixedStreamArray<support::ulittle32_t> getThunkMap() const {
|
msf::FixedStreamArray<support::ulittle32_t> getThunkMap() const {
|
||||||
return ThunkMap;
|
return ThunkMap;
|
||||||
}
|
}
|
||||||
FixedStreamArray<SectionOffset> getSectionOffsets() const {
|
msf::FixedStreamArray<SectionOffset> getSectionOffsets() const {
|
||||||
return SectionOffsets;
|
return SectionOffsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,11 +59,11 @@ private:
|
|||||||
std::unique_ptr<msf::MappedBlockStream> Stream;
|
std::unique_ptr<msf::MappedBlockStream> Stream;
|
||||||
uint32_t NumBuckets = 0;
|
uint32_t NumBuckets = 0;
|
||||||
ArrayRef<uint8_t> Bitmap;
|
ArrayRef<uint8_t> Bitmap;
|
||||||
FixedStreamArray<PSHashRecord> HashRecords;
|
msf::FixedStreamArray<PSHashRecord> HashRecords;
|
||||||
FixedStreamArray<support::ulittle32_t> HashBuckets;
|
msf::FixedStreamArray<support::ulittle32_t> HashBuckets;
|
||||||
FixedStreamArray<support::ulittle32_t> AddressMap;
|
msf::FixedStreamArray<support::ulittle32_t> AddressMap;
|
||||||
FixedStreamArray<support::ulittle32_t> ThunkMap;
|
msf::FixedStreamArray<support::ulittle32_t> ThunkMap;
|
||||||
FixedStreamArray<SectionOffset> SectionOffsets;
|
msf::FixedStreamArray<SectionOffset> SectionOffsets;
|
||||||
|
|
||||||
const HeaderInfo *Header;
|
const HeaderInfo *Header;
|
||||||
const GSIHashHeader *HashHdr;
|
const GSIHashHeader *HashHdr;
|
||||||
|
@ -20,15 +20,16 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class BinaryStreamReader;
|
namespace msf {
|
||||||
|
class StreamReader;
|
||||||
|
}
|
||||||
namespace pdb {
|
namespace pdb {
|
||||||
|
|
||||||
class StringTable {
|
class StringTable {
|
||||||
public:
|
public:
|
||||||
StringTable();
|
StringTable();
|
||||||
|
|
||||||
Error load(BinaryStreamReader &Stream);
|
Error load(msf::StreamReader &Stream);
|
||||||
|
|
||||||
uint32_t getNameCount() const { return NameCount; }
|
uint32_t getNameCount() const { return NameCount; }
|
||||||
uint32_t getHashVersion() const { return HashVersion; }
|
uint32_t getHashVersion() const { return HashVersion; }
|
||||||
@ -37,11 +38,11 @@ public:
|
|||||||
StringRef getStringForID(uint32_t ID) const;
|
StringRef getStringForID(uint32_t ID) const;
|
||||||
uint32_t getIDForString(StringRef Str) const;
|
uint32_t getIDForString(StringRef Str) const;
|
||||||
|
|
||||||
FixedStreamArray<support::ulittle32_t> name_ids() const;
|
msf::FixedStreamArray<support::ulittle32_t> name_ids() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BinaryStreamRef NamesBuffer;
|
msf::ReadableStreamRef NamesBuffer;
|
||||||
FixedStreamArray<support::ulittle32_t> IDs;
|
msf::FixedStreamArray<support::ulittle32_t> IDs;
|
||||||
uint32_t Signature;
|
uint32_t Signature;
|
||||||
uint32_t HashVersion;
|
uint32_t HashVersion;
|
||||||
uint32_t NameCount;
|
uint32_t NameCount;
|
||||||
|
@ -20,8 +20,9 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class BinaryStreamWriter;
|
namespace msf {
|
||||||
|
class StreamWriter;
|
||||||
|
}
|
||||||
namespace pdb {
|
namespace pdb {
|
||||||
|
|
||||||
class StringTableBuilder {
|
class StringTableBuilder {
|
||||||
@ -31,7 +32,7 @@ public:
|
|||||||
uint32_t insert(StringRef S);
|
uint32_t insert(StringRef S);
|
||||||
|
|
||||||
uint32_t finalize();
|
uint32_t finalize();
|
||||||
Error commit(BinaryStreamWriter &Writer) const;
|
Error commit(msf::StreamWriter &Writer) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DenseMap<StringRef, uint32_t> Strings;
|
DenseMap<StringRef, uint32_t> Strings;
|
||||||
|
@ -57,7 +57,7 @@ private:
|
|||||||
|
|
||||||
class TpiHashVerifier : public codeview::TypeVisitorCallbacks {
|
class TpiHashVerifier : public codeview::TypeVisitorCallbacks {
|
||||||
public:
|
public:
|
||||||
TpiHashVerifier(FixedStreamArray<support::ulittle32_t> &HashValues,
|
TpiHashVerifier(msf::FixedStreamArray<support::ulittle32_t> &HashValues,
|
||||||
uint32_t NumHashBuckets)
|
uint32_t NumHashBuckets)
|
||||||
: HashValues(HashValues), NumHashBuckets(NumHashBuckets) {}
|
: HashValues(HashValues), NumHashBuckets(NumHashBuckets) {}
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ private:
|
|||||||
utohexstr(codeview::TypeIndex::FirstNonSimpleIndex + Index));
|
utohexstr(codeview::TypeIndex::FirstNonSimpleIndex + Index));
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedStreamArray<support::ulittle32_t> HashValues;
|
msf::FixedStreamArray<support::ulittle32_t> HashValues;
|
||||||
codeview::CVType RawRecord;
|
codeview::CVType RawRecord;
|
||||||
uint32_t NumHashBuckets;
|
uint32_t NumHashBuckets;
|
||||||
uint32_t Index = -1;
|
uint32_t Index = -1;
|
||||||
|
@ -46,8 +46,8 @@ public:
|
|||||||
|
|
||||||
uint32_t getHashKeySize() const;
|
uint32_t getHashKeySize() const;
|
||||||
uint32_t NumHashBuckets() const;
|
uint32_t NumHashBuckets() const;
|
||||||
FixedStreamArray<support::ulittle32_t> getHashValues() const;
|
msf::FixedStreamArray<support::ulittle32_t> getHashValues() const;
|
||||||
FixedStreamArray<TypeIndexOffset> getTypeIndexOffsets() const;
|
msf::FixedStreamArray<TypeIndexOffset> getTypeIndexOffsets() const;
|
||||||
HashTable &getHashAdjusters();
|
HashTable &getHashAdjusters();
|
||||||
|
|
||||||
codeview::CVTypeRange types(bool *HadError) const;
|
codeview::CVTypeRange types(bool *HadError) const;
|
||||||
@ -62,9 +62,9 @@ private:
|
|||||||
|
|
||||||
codeview::CVTypeArray TypeRecords;
|
codeview::CVTypeArray TypeRecords;
|
||||||
|
|
||||||
std::unique_ptr<BinaryStream> HashStream;
|
std::unique_ptr<msf::ReadableStream> HashStream;
|
||||||
FixedStreamArray<support::ulittle32_t> HashValues;
|
msf::FixedStreamArray<support::ulittle32_t> HashValues;
|
||||||
FixedStreamArray<TypeIndexOffset> TypeIndexOffsets;
|
msf::FixedStreamArray<TypeIndexOffset> TypeIndexOffsets;
|
||||||
HashTable HashAdjusters;
|
HashTable HashAdjusters;
|
||||||
|
|
||||||
const TpiStreamHeader *Header;
|
const TpiStreamHeader *Header;
|
||||||
|
@ -21,22 +21,22 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class BinaryStreamRef;
|
namespace codeview {
|
||||||
class WritableBinaryStream;
|
class TypeRecord;
|
||||||
|
}
|
||||||
|
namespace msf {
|
||||||
|
class ByteStream;
|
||||||
|
class MSFBuilder;
|
||||||
|
struct MSFLayout;
|
||||||
|
class ReadableStreamRef;
|
||||||
|
class WritableStream;
|
||||||
|
|
||||||
template <> struct BinaryItemTraits<llvm::codeview::CVType> {
|
template <> struct SequencedItemTraits<llvm::codeview::CVType> {
|
||||||
static size_t length(const codeview::CVType &Item) { return Item.length(); }
|
static size_t length(const codeview::CVType &Item) { return Item.length(); }
|
||||||
static ArrayRef<uint8_t> bytes(const codeview::CVType &Item) {
|
static ArrayRef<uint8_t> bytes(const codeview::CVType &Item) {
|
||||||
return Item.data();
|
return Item.data();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace codeview {
|
|
||||||
class TypeRecord;
|
|
||||||
}
|
|
||||||
namespace msf {
|
|
||||||
class MSFBuilder;
|
|
||||||
struct MSFLayout;
|
|
||||||
}
|
}
|
||||||
namespace pdb {
|
namespace pdb {
|
||||||
class PDBFile;
|
class PDBFile;
|
||||||
@ -56,9 +56,9 @@ public:
|
|||||||
|
|
||||||
Error finalizeMsfLayout();
|
Error finalizeMsfLayout();
|
||||||
|
|
||||||
Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer);
|
Error commit(const msf::MSFLayout &Layout, const msf::WritableStream &Buffer);
|
||||||
|
|
||||||
uint32_t calculateSerializedLength();
|
uint32_t calculateSerializedLength() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t calculateHashBufferSize() const;
|
uint32_t calculateHashBufferSize() const;
|
||||||
@ -69,9 +69,9 @@ private:
|
|||||||
|
|
||||||
Optional<PdbRaw_TpiVer> VerHeader;
|
Optional<PdbRaw_TpiVer> VerHeader;
|
||||||
std::vector<codeview::CVType> TypeRecords;
|
std::vector<codeview::CVType> TypeRecords;
|
||||||
BinaryItemStream<codeview::CVType> TypeRecordStream;
|
msf::SequencedItemStream<codeview::CVType> TypeRecordStream;
|
||||||
uint32_t HashStreamIndex = kInvalidStreamIndex;
|
uint32_t HashStreamIndex = kInvalidStreamIndex;
|
||||||
std::unique_ptr<BinaryByteStream> HashValueStream;
|
std::unique_ptr<msf::ByteStream> HashValueStream;
|
||||||
|
|
||||||
const TpiStreamHeader *Header;
|
const TpiStreamHeader *Header;
|
||||||
uint32_t Idx;
|
uint32_t Idx;
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::codeview;
|
using namespace llvm::codeview;
|
||||||
|
using namespace llvm::msf;
|
||||||
|
|
||||||
CodeViewDebug::CodeViewDebug(AsmPrinter *AP)
|
CodeViewDebug::CodeViewDebug(AsmPrinter *AP)
|
||||||
: DebugHandlerBase(AP), OS(*Asm->OutStreamer), Allocator(),
|
: DebugHandlerBase(AP), OS(*Asm->OutStreamer), Allocator(),
|
||||||
@ -494,9 +495,9 @@ void CodeViewDebug::emitTypeInformation() {
|
|||||||
// comments. The MSVC linker doesn't do much type record validation,
|
// comments. The MSVC linker doesn't do much type record validation,
|
||||||
// so the first link of an invalid type record can succeed while
|
// so the first link of an invalid type record can succeed while
|
||||||
// subsequent links will fail with LNK1285.
|
// subsequent links will fail with LNK1285.
|
||||||
BinaryByteStream Stream(Record, llvm::support::little);
|
ByteStream Stream(Record);
|
||||||
CVTypeArray Types;
|
CVTypeArray Types;
|
||||||
BinaryStreamReader Reader(Stream);
|
StreamReader Reader(Stream);
|
||||||
Error E = Reader.readArray(Types, Reader.getLength());
|
Error E = Reader.readArray(Types, Reader.getLength());
|
||||||
if (!E) {
|
if (!E) {
|
||||||
TypeVisitorCallbacks C;
|
TypeVisitorCallbacks C;
|
||||||
|
@ -56,9 +56,9 @@ Error CVTypeDumper::dump(const CVTypeArray &Types,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Error CVTypeDumper::dump(ArrayRef<uint8_t> Data, TypeVisitorCallbacks &Dumper) {
|
Error CVTypeDumper::dump(ArrayRef<uint8_t> Data, TypeVisitorCallbacks &Dumper) {
|
||||||
BinaryByteStream Stream(Data, llvm::support::little);
|
msf::ByteStream Stream(Data);
|
||||||
CVTypeArray Types;
|
CVTypeArray Types;
|
||||||
BinaryStreamReader Reader(Stream);
|
msf::StreamReader Reader(Stream);
|
||||||
if (auto EC = Reader.readArray(Types, Reader.getLength()))
|
if (auto EC = Reader.readArray(Types, Reader.getLength()))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ Error CVTypeVisitor::visitTypeStream(CVTypeRange Types) {
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader Reader) {
|
Error CVTypeVisitor::visitFieldListMemberStream(msf::StreamReader Reader) {
|
||||||
FieldListDeserializer Deserializer(Reader);
|
FieldListDeserializer Deserializer(Reader);
|
||||||
TypeVisitorCallbackPipeline Pipeline;
|
TypeVisitorCallbackPipeline Pipeline;
|
||||||
Pipeline.addCallbackToPipeline(Deserializer);
|
Pipeline.addCallbackToPipeline(Deserializer);
|
||||||
@ -182,7 +182,7 @@ Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader Reader) {
|
|||||||
|
|
||||||
TypeLeafKind Leaf;
|
TypeLeafKind Leaf;
|
||||||
while (!Reader.empty()) {
|
while (!Reader.empty()) {
|
||||||
if (auto EC = Reader.readEnum(Leaf))
|
if (auto EC = Reader.readEnum(Leaf, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
CVMemberRecord Record;
|
CVMemberRecord Record;
|
||||||
@ -195,7 +195,7 @@ Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader Reader) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
|
Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
|
||||||
BinaryByteStream S(Data, llvm::support::little);
|
msf::ByteStream S(Data);
|
||||||
BinaryStreamReader SR(S);
|
msf::StreamReader SR(S);
|
||||||
return visitFieldListMemberStream(SR);
|
return visitFieldListMemberStream(SR);
|
||||||
}
|
}
|
||||||
|
@ -87,13 +87,14 @@ Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes) {
|
|||||||
|
|
||||||
Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) {
|
Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) {
|
||||||
if (isWriting()) {
|
if (isWriting()) {
|
||||||
if (auto EC = Writer->writeInteger(TypeInd.getIndex()))
|
if (auto EC =
|
||||||
|
Writer->writeInteger(TypeInd.getIndex(), llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t I;
|
uint32_t I;
|
||||||
if (auto EC = Reader->readInteger(I))
|
if (auto EC = Reader->readInteger(I, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
TypeInd.setIndex(I);
|
TypeInd.setIndex(I);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
@ -145,10 +146,10 @@ Error CodeViewRecordIO::mapStringZ(StringRef &Value) {
|
|||||||
if (isWriting()) {
|
if (isWriting()) {
|
||||||
// Truncate if we attempt to write too much.
|
// Truncate if we attempt to write too much.
|
||||||
StringRef S = Value.take_front(maxFieldLength() - 1);
|
StringRef S = Value.take_front(maxFieldLength() - 1);
|
||||||
if (auto EC = Writer->writeCString(S))
|
if (auto EC = Writer->writeZeroString(S))
|
||||||
return EC;
|
return EC;
|
||||||
} else {
|
} else {
|
||||||
if (auto EC = Reader->readCString(Value))
|
if (auto EC = Reader->readZeroString(Value))
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
return Error::success();
|
return Error::success();
|
||||||
@ -176,7 +177,7 @@ Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) {
|
|||||||
if (auto EC = mapStringZ(V))
|
if (auto EC = mapStringZ(V))
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
if (auto EC = Writer->writeInteger<uint8_t>(0))
|
if (auto EC = Writer->writeInteger<uint8_t>(0, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
} else {
|
} else {
|
||||||
StringRef S;
|
StringRef S;
|
||||||
@ -194,24 +195,28 @@ Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) {
|
|||||||
Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
|
Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
|
||||||
assert(Value < 0 && "Encoded integer is not signed!");
|
assert(Value < 0 && "Encoded integer is not signed!");
|
||||||
if (Value >= std::numeric_limits<int8_t>::min()) {
|
if (Value >= std::numeric_limits<int8_t>::min()) {
|
||||||
if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR))
|
if (auto EC =
|
||||||
|
Writer->writeInteger<uint16_t>(LF_CHAR, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = Writer->writeInteger<int8_t>(Value))
|
if (auto EC = Writer->writeInteger<int8_t>(Value, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
} else if (Value >= std::numeric_limits<int16_t>::min()) {
|
} else if (Value >= std::numeric_limits<int16_t>::min()) {
|
||||||
if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT))
|
if (auto EC =
|
||||||
|
Writer->writeInteger<uint16_t>(LF_SHORT, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = Writer->writeInteger<int16_t>(Value))
|
if (auto EC = Writer->writeInteger<int16_t>(Value, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
} else if (Value >= std::numeric_limits<int32_t>::min()) {
|
} else if (Value >= std::numeric_limits<int32_t>::min()) {
|
||||||
if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG))
|
if (auto EC =
|
||||||
|
Writer->writeInteger<uint16_t>(LF_LONG, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = Writer->writeInteger<int32_t>(Value))
|
if (auto EC = Writer->writeInteger<int32_t>(Value, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
} else {
|
} else {
|
||||||
if (auto EC = Writer->writeInteger<uint16_t>(LF_QUADWORD))
|
if (auto EC =
|
||||||
|
Writer->writeInteger<uint16_t>(LF_QUADWORD, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = Writer->writeInteger(Value))
|
if (auto EC = Writer->writeInteger(Value, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
return Error::success();
|
return Error::success();
|
||||||
@ -219,22 +224,25 @@ Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
|
|||||||
|
|
||||||
Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) {
|
Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) {
|
||||||
if (Value < LF_NUMERIC) {
|
if (Value < LF_NUMERIC) {
|
||||||
if (auto EC = Writer->writeInteger<uint16_t>(Value))
|
if (auto EC = Writer->writeInteger<uint16_t>(Value, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
} else if (Value <= std::numeric_limits<uint16_t>::max()) {
|
} else if (Value <= std::numeric_limits<uint16_t>::max()) {
|
||||||
if (auto EC = Writer->writeInteger<uint16_t>(LF_USHORT))
|
if (auto EC =
|
||||||
|
Writer->writeInteger<uint16_t>(LF_USHORT, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = Writer->writeInteger<uint16_t>(Value))
|
if (auto EC = Writer->writeInteger<uint16_t>(Value, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
} else if (Value <= std::numeric_limits<uint32_t>::max()) {
|
} else if (Value <= std::numeric_limits<uint32_t>::max()) {
|
||||||
if (auto EC = Writer->writeInteger<uint16_t>(LF_ULONG))
|
if (auto EC =
|
||||||
|
Writer->writeInteger<uint16_t>(LF_ULONG, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = Writer->writeInteger<uint32_t>(Value))
|
if (auto EC = Writer->writeInteger<uint32_t>(Value, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
} else {
|
} else {
|
||||||
if (auto EC = Writer->writeInteger<uint16_t>(LF_UQUADWORD))
|
if (auto EC =
|
||||||
|
Writer->writeInteger<uint16_t>(LF_UQUADWORD, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = Writer->writeInteger(Value))
|
if (auto EC = Writer->writeInteger(Value, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,16 +13,18 @@
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::codeview;
|
using namespace llvm::codeview;
|
||||||
|
using namespace llvm::msf;
|
||||||
|
|
||||||
ModuleSubstream::ModuleSubstream() : Kind(ModuleSubstreamKind::None) {}
|
ModuleSubstream::ModuleSubstream() : Kind(ModuleSubstreamKind::None) {}
|
||||||
|
|
||||||
ModuleSubstream::ModuleSubstream(ModuleSubstreamKind Kind, BinaryStreamRef Data)
|
ModuleSubstream::ModuleSubstream(ModuleSubstreamKind Kind,
|
||||||
|
ReadableStreamRef Data)
|
||||||
: Kind(Kind), Data(Data) {}
|
: Kind(Kind), Data(Data) {}
|
||||||
|
|
||||||
Error ModuleSubstream::initialize(BinaryStreamRef Stream,
|
Error ModuleSubstream::initialize(ReadableStreamRef Stream,
|
||||||
ModuleSubstream &Info) {
|
ModuleSubstream &Info) {
|
||||||
const ModuleSubsectionHeader *Header;
|
const ModuleSubsectionHeader *Header;
|
||||||
BinaryStreamReader Reader(Stream);
|
StreamReader Reader(Stream);
|
||||||
if (auto EC = Reader.readObject(Header))
|
if (auto EC = Reader.readObject(Header))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
@ -40,4 +42,4 @@ uint32_t ModuleSubstream::getRecordLength() const {
|
|||||||
|
|
||||||
ModuleSubstreamKind ModuleSubstream::getSubstreamKind() const { return Kind; }
|
ModuleSubstreamKind ModuleSubstream::getSubstreamKind() const { return Kind; }
|
||||||
|
|
||||||
BinaryStreamRef ModuleSubstream::getRecordData() const { return Data; }
|
ReadableStreamRef ModuleSubstream::getRecordData() const { return Data; }
|
||||||
|
@ -13,47 +13,49 @@
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::codeview;
|
using namespace llvm::codeview;
|
||||||
|
using namespace llvm::msf;
|
||||||
|
|
||||||
Error IModuleSubstreamVisitor::visitSymbols(BinaryStreamRef Data) {
|
Error IModuleSubstreamVisitor::visitSymbols(ReadableStreamRef Data) {
|
||||||
return visitUnknown(ModuleSubstreamKind::Symbols, Data);
|
return visitUnknown(ModuleSubstreamKind::Symbols, Data);
|
||||||
}
|
}
|
||||||
Error IModuleSubstreamVisitor::visitLines(BinaryStreamRef Data,
|
Error IModuleSubstreamVisitor::visitLines(ReadableStreamRef Data,
|
||||||
const LineSubstreamHeader *Header,
|
const LineSubstreamHeader *Header,
|
||||||
const LineInfoArray &Lines) {
|
const LineInfoArray &Lines) {
|
||||||
return visitUnknown(ModuleSubstreamKind::Lines, Data);
|
return visitUnknown(ModuleSubstreamKind::Lines, Data);
|
||||||
}
|
}
|
||||||
Error IModuleSubstreamVisitor::visitStringTable(BinaryStreamRef Data) {
|
Error IModuleSubstreamVisitor::visitStringTable(ReadableStreamRef Data) {
|
||||||
return visitUnknown(ModuleSubstreamKind::StringTable, Data);
|
return visitUnknown(ModuleSubstreamKind::StringTable, Data);
|
||||||
}
|
}
|
||||||
Error IModuleSubstreamVisitor::visitFileChecksums(
|
Error IModuleSubstreamVisitor::visitFileChecksums(
|
||||||
BinaryStreamRef Data, const FileChecksumArray &Checksums) {
|
ReadableStreamRef Data, const FileChecksumArray &Checksums) {
|
||||||
return visitUnknown(ModuleSubstreamKind::FileChecksums, Data);
|
return visitUnknown(ModuleSubstreamKind::FileChecksums, Data);
|
||||||
}
|
}
|
||||||
Error IModuleSubstreamVisitor::visitFrameData(BinaryStreamRef Data) {
|
Error IModuleSubstreamVisitor::visitFrameData(ReadableStreamRef Data) {
|
||||||
return visitUnknown(ModuleSubstreamKind::FrameData, Data);
|
return visitUnknown(ModuleSubstreamKind::FrameData, Data);
|
||||||
}
|
}
|
||||||
Error IModuleSubstreamVisitor::visitInlineeLines(BinaryStreamRef Data) {
|
Error IModuleSubstreamVisitor::visitInlineeLines(ReadableStreamRef Data) {
|
||||||
return visitUnknown(ModuleSubstreamKind::InlineeLines, Data);
|
return visitUnknown(ModuleSubstreamKind::InlineeLines, Data);
|
||||||
}
|
}
|
||||||
Error IModuleSubstreamVisitor::visitCrossScopeImports(BinaryStreamRef Data) {
|
Error IModuleSubstreamVisitor::visitCrossScopeImports(ReadableStreamRef Data) {
|
||||||
return visitUnknown(ModuleSubstreamKind::CrossScopeExports, Data);
|
return visitUnknown(ModuleSubstreamKind::CrossScopeExports, Data);
|
||||||
}
|
}
|
||||||
Error IModuleSubstreamVisitor::visitCrossScopeExports(BinaryStreamRef Data) {
|
Error IModuleSubstreamVisitor::visitCrossScopeExports(ReadableStreamRef Data) {
|
||||||
return visitUnknown(ModuleSubstreamKind::CrossScopeImports, Data);
|
return visitUnknown(ModuleSubstreamKind::CrossScopeImports, Data);
|
||||||
}
|
}
|
||||||
Error IModuleSubstreamVisitor::visitILLines(BinaryStreamRef Data) {
|
Error IModuleSubstreamVisitor::visitILLines(ReadableStreamRef Data) {
|
||||||
return visitUnknown(ModuleSubstreamKind::ILLines, Data);
|
return visitUnknown(ModuleSubstreamKind::ILLines, Data);
|
||||||
}
|
}
|
||||||
Error IModuleSubstreamVisitor::visitFuncMDTokenMap(BinaryStreamRef Data) {
|
Error IModuleSubstreamVisitor::visitFuncMDTokenMap(ReadableStreamRef Data) {
|
||||||
return visitUnknown(ModuleSubstreamKind::FuncMDTokenMap, Data);
|
return visitUnknown(ModuleSubstreamKind::FuncMDTokenMap, Data);
|
||||||
}
|
}
|
||||||
Error IModuleSubstreamVisitor::visitTypeMDTokenMap(BinaryStreamRef Data) {
|
Error IModuleSubstreamVisitor::visitTypeMDTokenMap(ReadableStreamRef Data) {
|
||||||
return visitUnknown(ModuleSubstreamKind::TypeMDTokenMap, Data);
|
return visitUnknown(ModuleSubstreamKind::TypeMDTokenMap, Data);
|
||||||
}
|
}
|
||||||
Error IModuleSubstreamVisitor::visitMergedAssemblyInput(BinaryStreamRef Data) {
|
Error IModuleSubstreamVisitor::visitMergedAssemblyInput(
|
||||||
|
ReadableStreamRef Data) {
|
||||||
return visitUnknown(ModuleSubstreamKind::MergedAssemblyInput, Data);
|
return visitUnknown(ModuleSubstreamKind::MergedAssemblyInput, Data);
|
||||||
}
|
}
|
||||||
Error IModuleSubstreamVisitor::visitCoffSymbolRVA(BinaryStreamRef Data) {
|
Error IModuleSubstreamVisitor::visitCoffSymbolRVA(ReadableStreamRef Data) {
|
||||||
return visitUnknown(ModuleSubstreamKind::CoffSymbolRVA, Data);
|
return visitUnknown(ModuleSubstreamKind::CoffSymbolRVA, Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +65,7 @@ Error llvm::codeview::visitModuleSubstream(const ModuleSubstream &R,
|
|||||||
case ModuleSubstreamKind::Symbols:
|
case ModuleSubstreamKind::Symbols:
|
||||||
return V.visitSymbols(R.getRecordData());
|
return V.visitSymbols(R.getRecordData());
|
||||||
case ModuleSubstreamKind::Lines: {
|
case ModuleSubstreamKind::Lines: {
|
||||||
BinaryStreamReader Reader(R.getRecordData());
|
StreamReader Reader(R.getRecordData());
|
||||||
const LineSubstreamHeader *Header;
|
const LineSubstreamHeader *Header;
|
||||||
if (auto EC = Reader.readObject(Header))
|
if (auto EC = Reader.readObject(Header))
|
||||||
return EC;
|
return EC;
|
||||||
@ -76,7 +78,7 @@ Error llvm::codeview::visitModuleSubstream(const ModuleSubstream &R,
|
|||||||
case ModuleSubstreamKind::StringTable:
|
case ModuleSubstreamKind::StringTable:
|
||||||
return V.visitStringTable(R.getRecordData());
|
return V.visitStringTable(R.getRecordData());
|
||||||
case ModuleSubstreamKind::FileChecksums: {
|
case ModuleSubstreamKind::FileChecksums: {
|
||||||
BinaryStreamReader Reader(R.getRecordData());
|
StreamReader Reader(R.getRecordData());
|
||||||
FileChecksumArray Checksums;
|
FileChecksumArray Checksums;
|
||||||
if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining()))
|
if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining()))
|
||||||
return EC;
|
return EC;
|
||||||
|
@ -33,11 +33,11 @@ StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
|
|||||||
return getBytesAsCharacters(LeafData).split('\0').first;
|
return getBytesAsCharacters(LeafData).split('\0').first;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error llvm::codeview::consume(BinaryStreamReader &Reader, APSInt &Num) {
|
Error llvm::codeview::consume(msf::StreamReader &Reader, APSInt &Num) {
|
||||||
// Used to avoid overload ambiguity on APInt construtor.
|
// Used to avoid overload ambiguity on APInt construtor.
|
||||||
bool FalseVal = false;
|
bool FalseVal = false;
|
||||||
uint16_t Short;
|
uint16_t Short;
|
||||||
if (auto EC = Reader.readInteger(Short))
|
if (auto EC = Reader.readInteger(Short, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
if (Short < LF_NUMERIC) {
|
if (Short < LF_NUMERIC) {
|
||||||
@ -49,49 +49,49 @@ Error llvm::codeview::consume(BinaryStreamReader &Reader, APSInt &Num) {
|
|||||||
switch (Short) {
|
switch (Short) {
|
||||||
case LF_CHAR: {
|
case LF_CHAR: {
|
||||||
int8_t N;
|
int8_t N;
|
||||||
if (auto EC = Reader.readInteger(N))
|
if (auto EC = Reader.readInteger(N, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
Num = APSInt(APInt(8, N, true), false);
|
Num = APSInt(APInt(8, N, true), false);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
case LF_SHORT: {
|
case LF_SHORT: {
|
||||||
int16_t N;
|
int16_t N;
|
||||||
if (auto EC = Reader.readInteger(N))
|
if (auto EC = Reader.readInteger(N, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
Num = APSInt(APInt(16, N, true), false);
|
Num = APSInt(APInt(16, N, true), false);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
case LF_USHORT: {
|
case LF_USHORT: {
|
||||||
uint16_t N;
|
uint16_t N;
|
||||||
if (auto EC = Reader.readInteger(N))
|
if (auto EC = Reader.readInteger(N, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
Num = APSInt(APInt(16, N, false), true);
|
Num = APSInt(APInt(16, N, false), true);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
case LF_LONG: {
|
case LF_LONG: {
|
||||||
int32_t N;
|
int32_t N;
|
||||||
if (auto EC = Reader.readInteger(N))
|
if (auto EC = Reader.readInteger(N, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
Num = APSInt(APInt(32, N, true), false);
|
Num = APSInt(APInt(32, N, true), false);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
case LF_ULONG: {
|
case LF_ULONG: {
|
||||||
uint32_t N;
|
uint32_t N;
|
||||||
if (auto EC = Reader.readInteger(N))
|
if (auto EC = Reader.readInteger(N, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
Num = APSInt(APInt(32, N, FalseVal), true);
|
Num = APSInt(APInt(32, N, FalseVal), true);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
case LF_QUADWORD: {
|
case LF_QUADWORD: {
|
||||||
int64_t N;
|
int64_t N;
|
||||||
if (auto EC = Reader.readInteger(N))
|
if (auto EC = Reader.readInteger(N, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
Num = APSInt(APInt(64, N, true), false);
|
Num = APSInt(APInt(64, N, true), false);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
case LF_UQUADWORD: {
|
case LF_UQUADWORD: {
|
||||||
uint64_t N;
|
uint64_t N;
|
||||||
if (auto EC = Reader.readInteger(N))
|
if (auto EC = Reader.readInteger(N, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
Num = APSInt(APInt(64, N, false), true);
|
Num = APSInt(APInt(64, N, false), true);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
@ -103,15 +103,15 @@ Error llvm::codeview::consume(BinaryStreamReader &Reader, APSInt &Num) {
|
|||||||
|
|
||||||
Error llvm::codeview::consume(StringRef &Data, APSInt &Num) {
|
Error llvm::codeview::consume(StringRef &Data, APSInt &Num) {
|
||||||
ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
|
ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
|
||||||
BinaryByteStream S(Bytes, llvm::support::little);
|
msf::ByteStream S(Bytes);
|
||||||
BinaryStreamReader SR(S);
|
msf::StreamReader SR(S);
|
||||||
auto EC = consume(SR, Num);
|
auto EC = consume(SR, Num);
|
||||||
Data = Data.take_back(SR.bytesRemaining());
|
Data = Data.take_back(SR.bytesRemaining());
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decode a numeric leaf value that is known to be a uint64_t.
|
/// Decode a numeric leaf value that is known to be a uint64_t.
|
||||||
Error llvm::codeview::consume_numeric(BinaryStreamReader &Reader,
|
Error llvm::codeview::consume_numeric(msf::StreamReader &Reader,
|
||||||
uint64_t &Num) {
|
uint64_t &Num) {
|
||||||
APSInt N;
|
APSInt N;
|
||||||
if (auto EC = consume(Reader, N))
|
if (auto EC = consume(Reader, N))
|
||||||
@ -123,27 +123,27 @@ Error llvm::codeview::consume_numeric(BinaryStreamReader &Reader,
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error llvm::codeview::consume(BinaryStreamReader &Reader, uint32_t &Item) {
|
Error llvm::codeview::consume(msf::StreamReader &Reader, uint32_t &Item) {
|
||||||
return Reader.readInteger(Item);
|
return Reader.readInteger(Item, llvm::support::little);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
|
Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
|
||||||
ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
|
ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
|
||||||
BinaryByteStream S(Bytes, llvm::support::little);
|
msf::ByteStream S(Bytes);
|
||||||
BinaryStreamReader SR(S);
|
msf::StreamReader SR(S);
|
||||||
auto EC = consume(SR, Item);
|
auto EC = consume(SR, Item);
|
||||||
Data = Data.take_back(SR.bytesRemaining());
|
Data = Data.take_back(SR.bytesRemaining());
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error llvm::codeview::consume(BinaryStreamReader &Reader, int32_t &Item) {
|
Error llvm::codeview::consume(msf::StreamReader &Reader, int32_t &Item) {
|
||||||
return Reader.readInteger(Item);
|
return Reader.readInteger(Item, llvm::support::little);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error llvm::codeview::consume(BinaryStreamReader &Reader, StringRef &Item) {
|
Error llvm::codeview::consume(msf::StreamReader &Reader, StringRef &Item) {
|
||||||
if (Reader.empty())
|
if (Reader.empty())
|
||||||
return make_error<CodeViewError>(cv_error_code::corrupt_record,
|
return make_error<CodeViewError>(cv_error_code::corrupt_record,
|
||||||
"Null terminated string buffer is empty!");
|
"Null terminated string buffer is empty!");
|
||||||
|
|
||||||
return Reader.readCString(Item);
|
return Reader.readZeroString(Item);
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ TypeSerializer::addPadding(MutableArrayRef<uint8_t> Record) {
|
|||||||
int N = PaddingBytes;
|
int N = PaddingBytes;
|
||||||
while (PaddingBytes > 0) {
|
while (PaddingBytes > 0) {
|
||||||
uint8_t Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes);
|
uint8_t Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes);
|
||||||
if (auto EC = Writer.writeInteger(Pad))
|
if (auto EC = Writer.writeInteger(Pad, llvm::support::little))
|
||||||
return std::move(EC);
|
return std::move(EC);
|
||||||
--PaddingBytes;
|
--PaddingBytes;
|
||||||
}
|
}
|
||||||
@ -85,8 +85,7 @@ TypeSerializer::addPadding(MutableArrayRef<uint8_t> Record) {
|
|||||||
|
|
||||||
TypeSerializer::TypeSerializer(BumpPtrAllocator &Storage)
|
TypeSerializer::TypeSerializer(BumpPtrAllocator &Storage)
|
||||||
: RecordStorage(Storage), LastTypeIndex(),
|
: RecordStorage(Storage), LastTypeIndex(),
|
||||||
RecordBuffer(MaxRecordLength * 2),
|
RecordBuffer(MaxRecordLength * 2), Stream(RecordBuffer), Writer(Stream),
|
||||||
Stream(RecordBuffer, llvm::support::little), Writer(Stream),
|
|
||||||
Mapping(Writer) {
|
Mapping(Writer) {
|
||||||
// RecordBuffer needs to be able to hold enough data so that if we are 1
|
// RecordBuffer needs to be able to hold enough data so that if we are 1
|
||||||
// byte short of MaxRecordLen, and then we try to write MaxRecordLen bytes,
|
// byte short of MaxRecordLen, and then we try to write MaxRecordLen bytes,
|
||||||
@ -204,15 +203,15 @@ Error TypeSerializer::visitMemberEnd(CVMemberRecord &Record) {
|
|||||||
|
|
||||||
uint8_t *SegmentBytes = RecordStorage.Allocate<uint8_t>(LengthWithSize);
|
uint8_t *SegmentBytes = RecordStorage.Allocate<uint8_t>(LengthWithSize);
|
||||||
auto SavedSegment = MutableArrayRef<uint8_t>(SegmentBytes, LengthWithSize);
|
auto SavedSegment = MutableArrayRef<uint8_t>(SegmentBytes, LengthWithSize);
|
||||||
MutableBinaryByteStream CS(SavedSegment, llvm::support::little);
|
msf::MutableByteStream CS(SavedSegment);
|
||||||
BinaryStreamWriter CW(CS);
|
msf::StreamWriter CW(CS);
|
||||||
if (auto EC = CW.writeBytes(CopyData))
|
if (auto EC = CW.writeBytes(CopyData))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = CW.writeEnum(TypeLeafKind::LF_INDEX))
|
if (auto EC = CW.writeEnum(TypeLeafKind::LF_INDEX, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = CW.writeInteger<uint16_t>(0))
|
if (auto EC = CW.writeInteger<uint16_t>(0, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = CW.writeInteger<uint32_t>(0xB0C0B0C0))
|
if (auto EC = CW.writeInteger<uint32_t>(0xB0C0B0C0, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
FieldListSegments.push_back(SavedSegment);
|
FieldListSegments.push_back(SavedSegment);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//===- BinaryStreamReader.cpp - Reads objects from a binary stream --------===//
|
//===- StreamReader.cpp - Reads bytes and objects from a stream -----------===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
@ -10,79 +10,53 @@
|
|||||||
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
||||||
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
|
||||||
|
#include "llvm/DebugInfo/MSF/MSFError.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace llvm::msf;
|
||||||
|
|
||||||
BinaryStreamReader::BinaryStreamReader(BinaryStreamRef S)
|
StreamReader::StreamReader(ReadableStreamRef S) : Stream(S), Offset(0) {}
|
||||||
: Stream(S), Offset(0) {}
|
|
||||||
|
|
||||||
Error BinaryStreamReader::readLongestContiguousChunk(
|
Error StreamReader::readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer) {
|
||||||
ArrayRef<uint8_t> &Buffer) {
|
|
||||||
if (auto EC = Stream.readLongestContiguousChunk(Offset, Buffer))
|
if (auto EC = Stream.readLongestContiguousChunk(Offset, Buffer))
|
||||||
return EC;
|
return EC;
|
||||||
Offset += Buffer.size();
|
Offset += Buffer.size();
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error BinaryStreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
|
Error StreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
|
||||||
if (auto EC = Stream.readBytes(Offset, Size, Buffer))
|
if (auto EC = Stream.readBytes(Offset, Size, Buffer))
|
||||||
return EC;
|
return EC;
|
||||||
Offset += Size;
|
Offset += Size;
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error BinaryStreamReader::readInteger(uint64_t &Dest, uint32_t ByteSize) {
|
Error StreamReader::readZeroString(StringRef &Dest) {
|
||||||
assert(ByteSize == 1 || ByteSize == 2 || ByteSize == 4 || ByteSize == 8);
|
|
||||||
ArrayRef<uint8_t> Bytes;
|
|
||||||
|
|
||||||
if (auto EC = readBytes(Bytes, ByteSize))
|
|
||||||
return EC;
|
|
||||||
switch (ByteSize) {
|
|
||||||
case 1:
|
|
||||||
Dest = Bytes[0];
|
|
||||||
return Error::success();
|
|
||||||
case 2:
|
|
||||||
Dest = llvm::support::endian::read16(Bytes.data(), Stream.getEndian());
|
|
||||||
return Error::success();
|
|
||||||
case 4:
|
|
||||||
Dest = llvm::support::endian::read32(Bytes.data(), Stream.getEndian());
|
|
||||||
return Error::success();
|
|
||||||
case 8:
|
|
||||||
Dest = llvm::support::endian::read64(Bytes.data(), Stream.getEndian());
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
llvm_unreachable("Unreachable!");
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error BinaryStreamReader::readCString(StringRef &Dest) {
|
|
||||||
// TODO: This could be made more efficient by using readLongestContiguousChunk
|
|
||||||
// and searching for null terminators in the resulting buffer.
|
|
||||||
|
|
||||||
uint32_t Length = 0;
|
uint32_t Length = 0;
|
||||||
// First compute the length of the string by reading 1 byte at a time.
|
// First compute the length of the string by reading 1 byte at a time.
|
||||||
uint32_t OriginalOffset = getOffset();
|
uint32_t OriginalOffset = getOffset();
|
||||||
const char *C;
|
const char *C;
|
||||||
while (true) {
|
do {
|
||||||
if (auto EC = readObject(C))
|
if (auto EC = readObject(C))
|
||||||
return EC;
|
return EC;
|
||||||
if (*C == '\0')
|
if (*C != '\0')
|
||||||
break;
|
++Length;
|
||||||
++Length;
|
} while (*C != '\0');
|
||||||
}
|
|
||||||
// Now go back and request a reference for that many bytes.
|
// Now go back and request a reference for that many bytes.
|
||||||
uint32_t NewOffset = getOffset();
|
uint32_t NewOffset = getOffset();
|
||||||
setOffset(OriginalOffset);
|
setOffset(OriginalOffset);
|
||||||
|
|
||||||
if (auto EC = readFixedString(Dest, Length))
|
ArrayRef<uint8_t> Data;
|
||||||
|
if (auto EC = readBytes(Data, Length))
|
||||||
return EC;
|
return EC;
|
||||||
|
Dest = StringRef(reinterpret_cast<const char *>(Data.begin()), Data.size());
|
||||||
|
|
||||||
// Now set the offset back to where it was after we calculated the length.
|
// Now set the offset back to where it was after we calculated the length.
|
||||||
setOffset(NewOffset);
|
setOffset(NewOffset);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error BinaryStreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
|
Error StreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
|
||||||
ArrayRef<uint8_t> Bytes;
|
ArrayRef<uint8_t> Bytes;
|
||||||
if (auto EC = readBytes(Bytes, Length))
|
if (auto EC = readBytes(Bytes, Length))
|
||||||
return EC;
|
return EC;
|
||||||
@ -90,26 +64,26 @@ Error BinaryStreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref) {
|
Error StreamReader::readStreamRef(ReadableStreamRef &Ref) {
|
||||||
return readStreamRef(Ref, bytesRemaining());
|
return readStreamRef(Ref, bytesRemaining());
|
||||||
}
|
}
|
||||||
|
|
||||||
Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref, uint32_t Length) {
|
Error StreamReader::readStreamRef(ReadableStreamRef &Ref, uint32_t Length) {
|
||||||
if (bytesRemaining() < Length)
|
if (bytesRemaining() < Length)
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
Ref = Stream.slice(Offset, Length);
|
Ref = Stream.slice(Offset, Length);
|
||||||
Offset += Length;
|
Offset += Length;
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error BinaryStreamReader::skip(uint32_t Amount) {
|
Error StreamReader::skip(uint32_t Amount) {
|
||||||
if (Amount > bytesRemaining())
|
if (Amount > bytesRemaining())
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
Offset += Amount;
|
Offset += Amount;
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t BinaryStreamReader::peek() const {
|
uint8_t StreamReader::peek() const {
|
||||||
ArrayRef<uint8_t> Buffer;
|
ArrayRef<uint8_t> Buffer;
|
||||||
auto EC = Stream.readBytes(Offset, 1, Buffer);
|
auto EC = Stream.readBytes(Offset, 1, Buffer);
|
||||||
assert(!EC && "Cannot peek an empty buffer!");
|
assert(!EC && "Cannot peek an empty buffer!");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//===- BinaryStreamWriter.cpp - Writes objects to a BinaryStream ----------===//
|
//===- StreamWrite.cpp - Writes bytes and objects to a stream -------------===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
@ -11,42 +11,21 @@
|
|||||||
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
|
||||||
|
#include "llvm/DebugInfo/MSF/MSFError.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace llvm::msf;
|
||||||
|
|
||||||
BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStreamRef S)
|
StreamWriter::StreamWriter(WritableStreamRef S) : Stream(S), Offset(0) {}
|
||||||
: Stream(S), Offset(0) {}
|
|
||||||
|
|
||||||
Error BinaryStreamWriter::writeBytes(ArrayRef<uint8_t> Buffer) {
|
Error StreamWriter::writeBytes(ArrayRef<uint8_t> Buffer) {
|
||||||
if (auto EC = Stream.writeBytes(Offset, Buffer))
|
if (auto EC = Stream.writeBytes(Offset, Buffer))
|
||||||
return EC;
|
return EC;
|
||||||
Offset += Buffer.size();
|
Offset += Buffer.size();
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error BinaryStreamWriter::writeInteger(uint64_t Value, uint32_t ByteSize) {
|
Error StreamWriter::writeZeroString(StringRef Str) {
|
||||||
assert(ByteSize == 1 || ByteSize == 2 || ByteSize == 4 || ByteSize == 8);
|
|
||||||
uint8_t Bytes[8];
|
|
||||||
MutableArrayRef<uint8_t> Buffer(Bytes);
|
|
||||||
Buffer = Buffer.take_front(ByteSize);
|
|
||||||
switch (ByteSize) {
|
|
||||||
case 1:
|
|
||||||
Buffer[0] = static_cast<uint8_t>(Value);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
llvm::support::endian::write16(Buffer.data(), Value, Stream.getEndian());
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
llvm::support::endian::write32(Buffer.data(), Value, Stream.getEndian());
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
llvm::support::endian::write64(Buffer.data(), Value, Stream.getEndian());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return writeBytes(Buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error BinaryStreamWriter::writeCString(StringRef Str) {
|
|
||||||
if (auto EC = writeFixedString(Str))
|
if (auto EC = writeFixedString(Str))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = writeObject('\0'))
|
if (auto EC = writeObject('\0'))
|
||||||
@ -55,21 +34,31 @@ Error BinaryStreamWriter::writeCString(StringRef Str) {
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error BinaryStreamWriter::writeFixedString(StringRef Str) {
|
Error StreamWriter::writeFixedString(StringRef Str) {
|
||||||
return writeBytes(ArrayRef<uint8_t>(Str.bytes_begin(), Str.bytes_end()));
|
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 BinaryStreamWriter::writeStreamRef(BinaryStreamRef Ref) {
|
Error StreamWriter::writeStreamRef(ReadableStreamRef Ref) {
|
||||||
return writeStreamRef(Ref, Ref.getLength());
|
if (auto EC = writeStreamRef(Ref, Ref.getLength()))
|
||||||
|
return EC;
|
||||||
|
// Don't increment Offset here, it is done by the overloaded call to
|
||||||
|
// writeStreamRef.
|
||||||
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error BinaryStreamWriter::writeStreamRef(BinaryStreamRef Ref, uint32_t Length) {
|
Error StreamWriter::writeStreamRef(ReadableStreamRef Ref, uint32_t Length) {
|
||||||
BinaryStreamReader SrcReader(Ref.slice(0, Length));
|
Ref = Ref.slice(0, Length);
|
||||||
|
|
||||||
|
StreamReader SrcReader(Ref);
|
||||||
// This is a bit tricky. If we just call readBytes, we are requiring that it
|
// This is a bit tricky. If we just call readBytes, we are requiring that it
|
||||||
// return us the entire stream as a contiguous buffer. There is no guarantee
|
// return us the entire stream as a contiguous buffer. For large streams this
|
||||||
// this can be satisfied by returning a reference straight from the buffer, as
|
// will allocate a huge amount of space from the pool. Instead, iterate over
|
||||||
// an implementation may not store all data in a single contiguous buffer. So
|
// each contiguous chunk until we've consumed the entire stream.
|
||||||
// we iterate over each contiguous chunk, writing each one in succession.
|
|
||||||
while (SrcReader.bytesRemaining() > 0) {
|
while (SrcReader.bytesRemaining() > 0) {
|
||||||
ArrayRef<uint8_t> Chunk;
|
ArrayRef<uint8_t> Chunk;
|
||||||
if (auto EC = SrcReader.readLongestContiguousChunk(Chunk))
|
if (auto EC = SrcReader.readLongestContiguousChunk(Chunk))
|
||||||
|
@ -47,20 +47,22 @@ static Interval intersect(const Interval &I1, const Interval &I2) {
|
|||||||
|
|
||||||
MappedBlockStream::MappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks,
|
MappedBlockStream::MappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks,
|
||||||
const MSFStreamLayout &Layout,
|
const MSFStreamLayout &Layout,
|
||||||
BinaryStreamRef MsfData)
|
const ReadableStream &MsfData)
|
||||||
: BlockSize(BlockSize), NumBlocks(NumBlocks), StreamLayout(Layout),
|
: BlockSize(BlockSize), NumBlocks(NumBlocks), StreamLayout(Layout),
|
||||||
MsfData(MsfData) {}
|
MsfData(MsfData) {}
|
||||||
|
|
||||||
std::unique_ptr<MappedBlockStream>
|
std::unique_ptr<MappedBlockStream>
|
||||||
MappedBlockStream::createStream(uint32_t BlockSize, uint32_t NumBlocks,
|
MappedBlockStream::createStream(uint32_t BlockSize, uint32_t NumBlocks,
|
||||||
const MSFStreamLayout &Layout,
|
const MSFStreamLayout &Layout,
|
||||||
BinaryStreamRef MsfData) {
|
const ReadableStream &MsfData) {
|
||||||
return llvm::make_unique<MappedBlockStreamImpl<MappedBlockStream>>(
|
return llvm::make_unique<MappedBlockStreamImpl<MappedBlockStream>>(
|
||||||
BlockSize, NumBlocks, Layout, MsfData);
|
BlockSize, NumBlocks, Layout, MsfData);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<MappedBlockStream> MappedBlockStream::createIndexedStream(
|
std::unique_ptr<MappedBlockStream>
|
||||||
const MSFLayout &Layout, BinaryStreamRef MsfData, uint32_t StreamIndex) {
|
MappedBlockStream::createIndexedStream(const MSFLayout &Layout,
|
||||||
|
const ReadableStream &MsfData,
|
||||||
|
uint32_t StreamIndex) {
|
||||||
assert(StreamIndex < Layout.StreamMap.size() && "Invalid stream index");
|
assert(StreamIndex < Layout.StreamMap.size() && "Invalid stream index");
|
||||||
MSFStreamLayout SL;
|
MSFStreamLayout SL;
|
||||||
SL.Blocks = Layout.StreamMap[StreamIndex];
|
SL.Blocks = Layout.StreamMap[StreamIndex];
|
||||||
@ -71,7 +73,7 @@ std::unique_ptr<MappedBlockStream> MappedBlockStream::createIndexedStream(
|
|||||||
|
|
||||||
std::unique_ptr<MappedBlockStream>
|
std::unique_ptr<MappedBlockStream>
|
||||||
MappedBlockStream::createDirectoryStream(const MSFLayout &Layout,
|
MappedBlockStream::createDirectoryStream(const MSFLayout &Layout,
|
||||||
BinaryStreamRef MsfData) {
|
const ReadableStream &MsfData) {
|
||||||
MSFStreamLayout SL;
|
MSFStreamLayout SL;
|
||||||
SL.Blocks = Layout.DirectoryBlocks;
|
SL.Blocks = Layout.DirectoryBlocks;
|
||||||
SL.Length = Layout.SB->NumDirectoryBytes;
|
SL.Length = Layout.SB->NumDirectoryBytes;
|
||||||
@ -80,14 +82,14 @@ MappedBlockStream::createDirectoryStream(const MSFLayout &Layout,
|
|||||||
|
|
||||||
std::unique_ptr<MappedBlockStream>
|
std::unique_ptr<MappedBlockStream>
|
||||||
MappedBlockStream::createFpmStream(const MSFLayout &Layout,
|
MappedBlockStream::createFpmStream(const MSFLayout &Layout,
|
||||||
BinaryStreamRef MsfData) {
|
const ReadableStream &MsfData) {
|
||||||
MSFStreamLayout SL;
|
MSFStreamLayout SL;
|
||||||
initializeFpmStreamLayout(Layout, SL);
|
initializeFpmStreamLayout(Layout, SL);
|
||||||
return createStream(Layout.SB->BlockSize, Layout.SB->NumBlocks, SL, MsfData);
|
return createStream(Layout.SB->BlockSize, Layout.SB->NumBlocks, SL, MsfData);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
|
Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
|
||||||
ArrayRef<uint8_t> &Buffer) {
|
ArrayRef<uint8_t> &Buffer) const {
|
||||||
// Make sure we aren't trying to read beyond the end of the stream.
|
// Make sure we aren't trying to read beyond the end of the stream.
|
||||||
if (Size > StreamLayout.Length)
|
if (Size > StreamLayout.Length)
|
||||||
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
@ -166,8 +168,8 @@ Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error MappedBlockStream::readLongestContiguousChunk(uint32_t Offset,
|
Error MappedBlockStream::readLongestContiguousChunk(
|
||||||
ArrayRef<uint8_t> &Buffer) {
|
uint32_t Offset, ArrayRef<uint8_t> &Buffer) const {
|
||||||
// Make sure we aren't trying to read beyond the end of the stream.
|
// Make sure we aren't trying to read beyond the end of the stream.
|
||||||
if (Offset >= StreamLayout.Length)
|
if (Offset >= StreamLayout.Length)
|
||||||
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
@ -195,10 +197,10 @@ Error MappedBlockStream::readLongestContiguousChunk(uint32_t Offset,
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t MappedBlockStream::getLength() { return StreamLayout.Length; }
|
uint32_t MappedBlockStream::getLength() const { return StreamLayout.Length; }
|
||||||
|
|
||||||
bool MappedBlockStream::tryReadContiguously(uint32_t Offset, uint32_t Size,
|
bool MappedBlockStream::tryReadContiguously(uint32_t Offset, uint32_t Size,
|
||||||
ArrayRef<uint8_t> &Buffer) {
|
ArrayRef<uint8_t> &Buffer) const {
|
||||||
if (Size == 0) {
|
if (Size == 0) {
|
||||||
Buffer = ArrayRef<uint8_t>();
|
Buffer = ArrayRef<uint8_t>();
|
||||||
return true;
|
return true;
|
||||||
@ -239,7 +241,7 @@ bool MappedBlockStream::tryReadContiguously(uint32_t Offset, uint32_t Size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Error MappedBlockStream::readBytes(uint32_t Offset,
|
Error MappedBlockStream::readBytes(uint32_t Offset,
|
||||||
MutableArrayRef<uint8_t> Buffer) {
|
MutableArrayRef<uint8_t> Buffer) const {
|
||||||
uint32_t BlockNum = Offset / BlockSize;
|
uint32_t BlockNum = Offset / BlockSize;
|
||||||
uint32_t OffsetInBlock = Offset % BlockSize;
|
uint32_t OffsetInBlock = Offset % BlockSize;
|
||||||
|
|
||||||
@ -317,21 +319,21 @@ void MappedBlockStream::fixCacheAfterWrite(uint32_t Offset,
|
|||||||
|
|
||||||
WritableMappedBlockStream::WritableMappedBlockStream(
|
WritableMappedBlockStream::WritableMappedBlockStream(
|
||||||
uint32_t BlockSize, uint32_t NumBlocks, const MSFStreamLayout &Layout,
|
uint32_t BlockSize, uint32_t NumBlocks, const MSFStreamLayout &Layout,
|
||||||
WritableBinaryStreamRef MsfData)
|
const WritableStream &MsfData)
|
||||||
: ReadInterface(BlockSize, NumBlocks, Layout, MsfData),
|
: ReadInterface(BlockSize, NumBlocks, Layout, MsfData),
|
||||||
WriteInterface(MsfData) {}
|
WriteInterface(MsfData) {}
|
||||||
|
|
||||||
std::unique_ptr<WritableMappedBlockStream>
|
std::unique_ptr<WritableMappedBlockStream>
|
||||||
WritableMappedBlockStream::createStream(uint32_t BlockSize, uint32_t NumBlocks,
|
WritableMappedBlockStream::createStream(uint32_t BlockSize, uint32_t NumBlocks,
|
||||||
const MSFStreamLayout &Layout,
|
const MSFStreamLayout &Layout,
|
||||||
WritableBinaryStreamRef MsfData) {
|
const WritableStream &MsfData) {
|
||||||
return llvm::make_unique<MappedBlockStreamImpl<WritableMappedBlockStream>>(
|
return llvm::make_unique<MappedBlockStreamImpl<WritableMappedBlockStream>>(
|
||||||
BlockSize, NumBlocks, Layout, MsfData);
|
BlockSize, NumBlocks, Layout, MsfData);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<WritableMappedBlockStream>
|
std::unique_ptr<WritableMappedBlockStream>
|
||||||
WritableMappedBlockStream::createIndexedStream(const MSFLayout &Layout,
|
WritableMappedBlockStream::createIndexedStream(const MSFLayout &Layout,
|
||||||
WritableBinaryStreamRef MsfData,
|
const WritableStream &MsfData,
|
||||||
uint32_t StreamIndex) {
|
uint32_t StreamIndex) {
|
||||||
assert(StreamIndex < Layout.StreamMap.size() && "Invalid stream index");
|
assert(StreamIndex < Layout.StreamMap.size() && "Invalid stream index");
|
||||||
MSFStreamLayout SL;
|
MSFStreamLayout SL;
|
||||||
@ -342,7 +344,7 @@ WritableMappedBlockStream::createIndexedStream(const MSFLayout &Layout,
|
|||||||
|
|
||||||
std::unique_ptr<WritableMappedBlockStream>
|
std::unique_ptr<WritableMappedBlockStream>
|
||||||
WritableMappedBlockStream::createDirectoryStream(
|
WritableMappedBlockStream::createDirectoryStream(
|
||||||
const MSFLayout &Layout, WritableBinaryStreamRef MsfData) {
|
const MSFLayout &Layout, const WritableStream &MsfData) {
|
||||||
MSFStreamLayout SL;
|
MSFStreamLayout SL;
|
||||||
SL.Blocks = Layout.DirectoryBlocks;
|
SL.Blocks = Layout.DirectoryBlocks;
|
||||||
SL.Length = Layout.SB->NumDirectoryBytes;
|
SL.Length = Layout.SB->NumDirectoryBytes;
|
||||||
@ -351,28 +353,28 @@ WritableMappedBlockStream::createDirectoryStream(
|
|||||||
|
|
||||||
std::unique_ptr<WritableMappedBlockStream>
|
std::unique_ptr<WritableMappedBlockStream>
|
||||||
WritableMappedBlockStream::createFpmStream(const MSFLayout &Layout,
|
WritableMappedBlockStream::createFpmStream(const MSFLayout &Layout,
|
||||||
WritableBinaryStreamRef MsfData) {
|
const WritableStream &MsfData) {
|
||||||
MSFStreamLayout SL;
|
MSFStreamLayout SL;
|
||||||
initializeFpmStreamLayout(Layout, SL);
|
initializeFpmStreamLayout(Layout, SL);
|
||||||
return createStream(Layout.SB->BlockSize, Layout.SB->NumBlocks, SL, MsfData);
|
return createStream(Layout.SB->BlockSize, Layout.SB->NumBlocks, SL, MsfData);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error WritableMappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
|
Error WritableMappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
|
||||||
ArrayRef<uint8_t> &Buffer) {
|
ArrayRef<uint8_t> &Buffer) const {
|
||||||
return ReadInterface.readBytes(Offset, Size, Buffer);
|
return ReadInterface.readBytes(Offset, Size, Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error WritableMappedBlockStream::readLongestContiguousChunk(
|
Error WritableMappedBlockStream::readLongestContiguousChunk(
|
||||||
uint32_t Offset, ArrayRef<uint8_t> &Buffer) {
|
uint32_t Offset, ArrayRef<uint8_t> &Buffer) const {
|
||||||
return ReadInterface.readLongestContiguousChunk(Offset, Buffer);
|
return ReadInterface.readLongestContiguousChunk(Offset, Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t WritableMappedBlockStream::getLength() {
|
uint32_t WritableMappedBlockStream::getLength() const {
|
||||||
return ReadInterface.getLength();
|
return ReadInterface.getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error WritableMappedBlockStream::writeBytes(uint32_t Offset,
|
Error WritableMappedBlockStream::writeBytes(uint32_t Offset,
|
||||||
ArrayRef<uint8_t> Buffer) {
|
ArrayRef<uint8_t> Buffer) const {
|
||||||
// Make sure we aren't trying to write beyond the end of the stream.
|
// Make sure we aren't trying to write beyond the end of the stream.
|
||||||
if (Buffer.size() > getStreamLength())
|
if (Buffer.size() > getStreamLength())
|
||||||
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
@ -408,4 +410,6 @@ Error WritableMappedBlockStream::writeBytes(uint32_t Offset,
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error WritableMappedBlockStream::commit() { return WriteInterface.commit(); }
|
Error WritableMappedBlockStream::commit() const {
|
||||||
|
return WriteInterface.commit();
|
||||||
|
}
|
||||||
|
@ -10,8 +10,6 @@
|
|||||||
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
|
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
||||||
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
|
#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
|
||||||
@ -36,7 +34,7 @@ using namespace llvm::support;
|
|||||||
|
|
||||||
template <typename ContribType>
|
template <typename ContribType>
|
||||||
static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
|
static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
|
||||||
BinaryStreamReader &Reader) {
|
StreamReader &Reader) {
|
||||||
if (Reader.bytesRemaining() % sizeof(ContribType) != 0)
|
if (Reader.bytesRemaining() % sizeof(ContribType) != 0)
|
||||||
return make_error<RawError>(
|
return make_error<RawError>(
|
||||||
raw_error_code::corrupt_file,
|
raw_error_code::corrupt_file,
|
||||||
@ -54,7 +52,7 @@ DbiStream::DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
|
|||||||
DbiStream::~DbiStream() = default;
|
DbiStream::~DbiStream() = default;
|
||||||
|
|
||||||
Error DbiStream::reload() {
|
Error DbiStream::reload() {
|
||||||
BinaryStreamReader Reader(*Stream);
|
StreamReader Reader(*Stream);
|
||||||
|
|
||||||
if (Stream->getLength() < sizeof(DbiStreamHeader))
|
if (Stream->getLength() < sizeof(DbiStreamHeader))
|
||||||
return make_error<RawError>(raw_error_code::corrupt_file,
|
return make_error<RawError>(raw_error_code::corrupt_file,
|
||||||
@ -147,7 +145,7 @@ Error DbiStream::reload() {
|
|||||||
"Found unexpected bytes in DBI Stream.");
|
"Found unexpected bytes in DBI Stream.");
|
||||||
|
|
||||||
if (ECSubstream.getLength() > 0) {
|
if (ECSubstream.getLength() > 0) {
|
||||||
BinaryStreamReader ECReader(ECSubstream);
|
StreamReader ECReader(ECSubstream);
|
||||||
if (auto EC = ECNames.load(ECReader))
|
if (auto EC = ECNames.load(ECReader))
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
@ -209,16 +207,16 @@ PDB_Machine DbiStream::getMachineType() const {
|
|||||||
return static_cast<PDB_Machine>(Machine);
|
return static_cast<PDB_Machine>(Machine);
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() {
|
msf::FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() {
|
||||||
return SectionHeaders;
|
return SectionHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() {
|
msf::FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() {
|
||||||
return FpoRecords;
|
return FpoRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<ModuleInfoEx> DbiStream::modules() const { return ModuleInfos; }
|
ArrayRef<ModuleInfoEx> DbiStream::modules() const { return ModuleInfos; }
|
||||||
FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
|
msf::FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
|
||||||
return SectionMap;
|
return SectionMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,8 +235,8 @@ Error DbiStream::initializeSectionContributionData() {
|
|||||||
if (SecContrSubstream.getLength() == 0)
|
if (SecContrSubstream.getLength() == 0)
|
||||||
return Error::success();
|
return Error::success();
|
||||||
|
|
||||||
BinaryStreamReader SCReader(SecContrSubstream);
|
StreamReader SCReader(SecContrSubstream);
|
||||||
if (auto EC = SCReader.readEnum(SectionContribVersion))
|
if (auto EC = SCReader.readEnum(SectionContribVersion, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
if (SectionContribVersion == DbiSecContribVer60)
|
if (SectionContribVersion == DbiSecContribVer60)
|
||||||
@ -256,7 +254,7 @@ Error DbiStream::initializeModInfoArray() {
|
|||||||
|
|
||||||
// Since each ModInfo in the stream is a variable length, we have to iterate
|
// Since each ModInfo in the stream is a variable length, we have to iterate
|
||||||
// them to know how many there actually are.
|
// them to know how many there actually are.
|
||||||
BinaryStreamReader Reader(ModInfoSubstream);
|
StreamReader Reader(ModInfoSubstream);
|
||||||
|
|
||||||
VarStreamArray<ModInfo> ModInfoArray;
|
VarStreamArray<ModInfo> ModInfoArray;
|
||||||
if (auto EC = Reader.readArray(ModInfoArray, ModInfoSubstream.getLength()))
|
if (auto EC = Reader.readArray(ModInfoArray, ModInfoSubstream.getLength()))
|
||||||
@ -286,7 +284,7 @@ Error DbiStream::initializeSectionHeadersData() {
|
|||||||
"Corrupted section header stream.");
|
"Corrupted section header stream.");
|
||||||
|
|
||||||
size_t NumSections = StreamLen / sizeof(object::coff_section);
|
size_t NumSections = StreamLen / sizeof(object::coff_section);
|
||||||
BinaryStreamReader Reader(*SHS);
|
msf::StreamReader Reader(*SHS);
|
||||||
if (auto EC = Reader.readArray(SectionHeaders, NumSections))
|
if (auto EC = Reader.readArray(SectionHeaders, NumSections))
|
||||||
return make_error<RawError>(raw_error_code::corrupt_file,
|
return make_error<RawError>(raw_error_code::corrupt_file,
|
||||||
"Could not read a bitmap.");
|
"Could not read a bitmap.");
|
||||||
@ -318,7 +316,7 @@ Error DbiStream::initializeFpoRecords() {
|
|||||||
"Corrupted New FPO stream.");
|
"Corrupted New FPO stream.");
|
||||||
|
|
||||||
size_t NumRecords = StreamLen / sizeof(object::FpoData);
|
size_t NumRecords = StreamLen / sizeof(object::FpoData);
|
||||||
BinaryStreamReader Reader(*FS);
|
msf::StreamReader Reader(*FS);
|
||||||
if (auto EC = Reader.readArray(FpoRecords, NumRecords))
|
if (auto EC = Reader.readArray(FpoRecords, NumRecords))
|
||||||
return make_error<RawError>(raw_error_code::corrupt_file,
|
return make_error<RawError>(raw_error_code::corrupt_file,
|
||||||
"Corrupted New FPO stream.");
|
"Corrupted New FPO stream.");
|
||||||
@ -330,7 +328,7 @@ Error DbiStream::initializeSectionMapData() {
|
|||||||
if (SecMapSubstream.getLength() == 0)
|
if (SecMapSubstream.getLength() == 0)
|
||||||
return Error::success();
|
return Error::success();
|
||||||
|
|
||||||
BinaryStreamReader SMReader(SecMapSubstream);
|
StreamReader SMReader(SecMapSubstream);
|
||||||
const SecMapHeader *Header;
|
const SecMapHeader *Header;
|
||||||
if (auto EC = SMReader.readObject(Header))
|
if (auto EC = SMReader.readObject(Header))
|
||||||
return EC;
|
return EC;
|
||||||
@ -344,7 +342,7 @@ Error DbiStream::initializeFileInfo() {
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
|
|
||||||
const FileInfoSubstreamHeader *FH;
|
const FileInfoSubstreamHeader *FH;
|
||||||
BinaryStreamReader FISR(FileInfoSubstream);
|
StreamReader FISR(FileInfoSubstream);
|
||||||
if (auto EC = FISR.readObject(FH))
|
if (auto EC = FISR.readObject(FH))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
@ -413,14 +411,14 @@ uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const {
|
Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const {
|
||||||
BinaryStreamReader Names(NamesBuffer);
|
StreamReader Names(NamesBuffer);
|
||||||
if (Index >= FileNameOffsets.size())
|
if (Index >= FileNameOffsets.size())
|
||||||
return make_error<RawError>(raw_error_code::index_out_of_bounds);
|
return make_error<RawError>(raw_error_code::index_out_of_bounds);
|
||||||
|
|
||||||
uint32_t FileOffset = FileNameOffsets[Index];
|
uint32_t FileOffset = FileNameOffsets[Index];
|
||||||
Names.setOffset(FileOffset);
|
Names.setOffset(FileOffset);
|
||||||
StringRef Name;
|
StringRef Name;
|
||||||
if (auto EC = Names.readCString(Name))
|
if (auto EC = Names.readZeroString(Name))
|
||||||
return std::move(EC);
|
return std::move(EC);
|
||||||
return Name;
|
return Name;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamWriter.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamWriter.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamWriter.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
|
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
|
||||||
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
|
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
|
||||||
@ -154,19 +153,18 @@ Error DbiStreamBuilder::generateModiSubstream() {
|
|||||||
uint32_t Size = calculateModiSubstreamSize();
|
uint32_t Size = calculateModiSubstreamSize();
|
||||||
auto Data = Allocator.Allocate<uint8_t>(Size);
|
auto Data = Allocator.Allocate<uint8_t>(Size);
|
||||||
|
|
||||||
ModInfoBuffer = MutableBinaryByteStream(MutableArrayRef<uint8_t>(Data, Size),
|
ModInfoBuffer = MutableByteStream(MutableArrayRef<uint8_t>(Data, Size));
|
||||||
llvm::support::little);
|
|
||||||
|
|
||||||
BinaryStreamWriter ModiWriter(ModInfoBuffer);
|
StreamWriter ModiWriter(ModInfoBuffer);
|
||||||
for (const auto &M : ModuleInfoList) {
|
for (const auto &M : ModuleInfoList) {
|
||||||
ModuleInfoHeader Layout = {};
|
ModuleInfoHeader Layout = {};
|
||||||
Layout.ModDiStream = kInvalidStreamIndex;
|
Layout.ModDiStream = kInvalidStreamIndex;
|
||||||
Layout.NumFiles = M->SourceFiles.size();
|
Layout.NumFiles = M->SourceFiles.size();
|
||||||
if (auto EC = ModiWriter.writeObject(Layout))
|
if (auto EC = ModiWriter.writeObject(Layout))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = ModiWriter.writeCString(M->Mod))
|
if (auto EC = ModiWriter.writeZeroString(M->Mod))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = ModiWriter.writeCString(M->Obj))
|
if (auto EC = ModiWriter.writeZeroString(M->Obj))
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
if (ModiWriter.bytesRemaining() > sizeof(uint32_t))
|
if (ModiWriter.bytesRemaining() > sizeof(uint32_t))
|
||||||
@ -181,26 +179,29 @@ Error DbiStreamBuilder::generateFileInfoSubstream() {
|
|||||||
auto Data = Allocator.Allocate<uint8_t>(Size);
|
auto Data = Allocator.Allocate<uint8_t>(Size);
|
||||||
uint32_t NamesOffset = Size - NameSize;
|
uint32_t NamesOffset = Size - NameSize;
|
||||||
|
|
||||||
FileInfoBuffer = MutableBinaryByteStream(MutableArrayRef<uint8_t>(Data, Size),
|
FileInfoBuffer = MutableByteStream(MutableArrayRef<uint8_t>(Data, Size));
|
||||||
llvm::support::little);
|
|
||||||
|
|
||||||
WritableBinaryStreamRef MetadataBuffer =
|
WritableStreamRef MetadataBuffer =
|
||||||
WritableBinaryStreamRef(FileInfoBuffer).keep_front(NamesOffset);
|
WritableStreamRef(FileInfoBuffer).keep_front(NamesOffset);
|
||||||
BinaryStreamWriter MetadataWriter(MetadataBuffer);
|
StreamWriter MetadataWriter(MetadataBuffer);
|
||||||
|
|
||||||
uint16_t ModiCount = std::min<uint32_t>(UINT16_MAX, ModuleInfos.size());
|
uint16_t ModiCount = std::min<uint32_t>(UINT16_MAX, ModuleInfos.size());
|
||||||
uint16_t FileCount = std::min<uint32_t>(UINT16_MAX, SourceFileNames.size());
|
uint16_t FileCount = std::min<uint32_t>(UINT16_MAX, SourceFileNames.size());
|
||||||
if (auto EC = MetadataWriter.writeInteger(ModiCount)) // NumModules
|
if (auto EC = MetadataWriter.writeInteger(
|
||||||
|
ModiCount, llvm::support::little)) // NumModules
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = MetadataWriter.writeInteger(FileCount)) // NumSourceFiles
|
if (auto EC = MetadataWriter.writeInteger(
|
||||||
|
FileCount, llvm::support::little)) // NumSourceFiles
|
||||||
return EC;
|
return EC;
|
||||||
for (uint16_t I = 0; I < ModiCount; ++I) {
|
for (uint16_t I = 0; I < ModiCount; ++I) {
|
||||||
if (auto EC = MetadataWriter.writeInteger(I)) // Mod Indices
|
if (auto EC = MetadataWriter.writeInteger(
|
||||||
|
I, llvm::support::little)) // Mod Indices
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
for (const auto MI : ModuleInfoList) {
|
for (const auto MI : ModuleInfoList) {
|
||||||
FileCount = static_cast<uint16_t>(MI->SourceFiles.size());
|
FileCount = static_cast<uint16_t>(MI->SourceFiles.size());
|
||||||
if (auto EC = MetadataWriter.writeInteger(FileCount)) // Mod File Counts
|
if (auto EC = MetadataWriter.writeInteger(
|
||||||
|
FileCount, llvm::support::little)) // Mod File Counts
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,11 +209,11 @@ Error DbiStreamBuilder::generateFileInfoSubstream() {
|
|||||||
// A side effect of this is that this will actually compute the various
|
// A side effect of this is that this will actually compute the various
|
||||||
// file name offsets, so we can then go back and write the FileNameOffsets
|
// file name offsets, so we can then go back and write the FileNameOffsets
|
||||||
// array to the other substream.
|
// array to the other substream.
|
||||||
NamesBuffer = WritableBinaryStreamRef(FileInfoBuffer).drop_front(NamesOffset);
|
NamesBuffer = WritableStreamRef(FileInfoBuffer).drop_front(NamesOffset);
|
||||||
BinaryStreamWriter NameBufferWriter(NamesBuffer);
|
StreamWriter NameBufferWriter(NamesBuffer);
|
||||||
for (auto &Name : SourceFileNames) {
|
for (auto &Name : SourceFileNames) {
|
||||||
Name.second = NameBufferWriter.getOffset();
|
Name.second = NameBufferWriter.getOffset();
|
||||||
if (auto EC = NameBufferWriter.writeCString(Name.getKey()))
|
if (auto EC = NameBufferWriter.writeZeroString(Name.getKey()))
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +223,8 @@ Error DbiStreamBuilder::generateFileInfoSubstream() {
|
|||||||
if (Result == SourceFileNames.end())
|
if (Result == SourceFileNames.end())
|
||||||
return make_error<RawError>(raw_error_code::no_entry,
|
return make_error<RawError>(raw_error_code::no_entry,
|
||||||
"The source file was not found.");
|
"The source file was not found.");
|
||||||
if (auto EC = MetadataWriter.writeInteger(Result->second))
|
if (auto EC = MetadataWriter.writeInteger(Result->second,
|
||||||
|
llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -361,14 +363,14 @@ std::vector<SecMapEntry> DbiStreamBuilder::createSectionMap(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
|
Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
|
||||||
WritableBinaryStreamRef Buffer) {
|
const msf::WritableStream &Buffer) {
|
||||||
if (auto EC = finalize())
|
if (auto EC = finalize())
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
auto InfoS =
|
auto InfoS =
|
||||||
WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamDBI);
|
WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamDBI);
|
||||||
|
|
||||||
BinaryStreamWriter Writer(*InfoS);
|
StreamWriter Writer(*InfoS);
|
||||||
if (auto EC = Writer.writeObject(*Header))
|
if (auto EC = Writer.writeObject(*Header))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
@ -376,7 +378,7 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
|
|||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
if (!SectionContribs.empty()) {
|
if (!SectionContribs.empty()) {
|
||||||
if (auto EC = Writer.writeEnum(DbiSecContribVer60))
|
if (auto EC = Writer.writeEnum(DbiSecContribVer60, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = Writer.writeArray(SectionContribs))
|
if (auto EC = Writer.writeArray(SectionContribs))
|
||||||
return EC;
|
return EC;
|
||||||
@ -395,7 +397,8 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
|
|||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
for (auto &Stream : DbgStreams)
|
for (auto &Stream : DbgStreams)
|
||||||
if (auto EC = Writer.writeInteger(Stream.StreamNumber))
|
if (auto EC =
|
||||||
|
Writer.writeInteger(Stream.StreamNumber, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
for (auto &Stream : DbgStreams) {
|
for (auto &Stream : DbgStreams) {
|
||||||
@ -403,7 +406,7 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
|
|||||||
continue;
|
continue;
|
||||||
auto WritableStream = WritableMappedBlockStream::createIndexedStream(
|
auto WritableStream = WritableMappedBlockStream::createIndexedStream(
|
||||||
Layout, Buffer, Stream.StreamNumber);
|
Layout, Buffer, Stream.StreamNumber);
|
||||||
BinaryStreamWriter DbgStreamWriter(*WritableStream);
|
StreamWriter DbgStreamWriter(*WritableStream);
|
||||||
if (auto EC = DbgStreamWriter.writeArray(Stream.Data))
|
if (auto EC = DbgStreamWriter.writeArray(Stream.Data))
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
|
@ -28,9 +28,9 @@ static Error checkHashHdrVersion(const GSIHashHeader *HashHdr) {
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets,
|
Error readGSIHashBuckets(
|
||||||
const GSIHashHeader *HashHdr,
|
msf::FixedStreamArray<support::ulittle32_t> &HashBuckets,
|
||||||
BinaryStreamReader &Reader) {
|
const GSIHashHeader *HashHdr, msf::StreamReader &Reader) {
|
||||||
if (auto EC = checkHashHdrVersion(HashHdr))
|
if (auto EC = checkHashHdrVersion(HashHdr))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ Error readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Error readGSIHashHeader(const GSIHashHeader *&HashHdr,
|
Error readGSIHashHeader(const GSIHashHeader *&HashHdr,
|
||||||
BinaryStreamReader &Reader) {
|
msf::StreamReader &Reader) {
|
||||||
if (Reader.readObject(HashHdr))
|
if (Reader.readObject(HashHdr))
|
||||||
return make_error<RawError>(raw_error_code::corrupt_file,
|
return make_error<RawError>(raw_error_code::corrupt_file,
|
||||||
"Stream does not contain a GSIHashHeader.");
|
"Stream does not contain a GSIHashHeader.");
|
||||||
@ -70,9 +70,9 @@ Error readGSIHashHeader(const GSIHashHeader *&HashHdr,
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error readGSIHashRecords(FixedStreamArray<PSHashRecord> &HashRecords,
|
Error readGSIHashRecords(msf::FixedStreamArray<PSHashRecord> &HashRecords,
|
||||||
const GSIHashHeader *HashHdr,
|
const GSIHashHeader *HashHdr,
|
||||||
BinaryStreamReader &Reader) {
|
msf::StreamReader &Reader) {
|
||||||
if (auto EC = checkHashHdrVersion(HashHdr))
|
if (auto EC = checkHashHdrVersion(HashHdr))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
|
@ -33,7 +33,9 @@
|
|||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class BinaryStreamReader;
|
namespace msf {
|
||||||
|
class StreamReader;
|
||||||
|
}
|
||||||
|
|
||||||
namespace pdb {
|
namespace pdb {
|
||||||
|
|
||||||
@ -54,14 +56,14 @@ struct GSIHashHeader {
|
|||||||
support::ulittle32_t NumBuckets;
|
support::ulittle32_t NumBuckets;
|
||||||
};
|
};
|
||||||
|
|
||||||
Error readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets,
|
Error readGSIHashBuckets(
|
||||||
const GSIHashHeader *HashHdr,
|
msf::FixedStreamArray<support::ulittle32_t> &HashBuckets,
|
||||||
BinaryStreamReader &Reader);
|
const GSIHashHeader *HashHdr, msf::StreamReader &Reader);
|
||||||
Error readGSIHashHeader(const GSIHashHeader *&HashHdr,
|
Error readGSIHashHeader(const GSIHashHeader *&HashHdr,
|
||||||
BinaryStreamReader &Reader);
|
msf::StreamReader &Reader);
|
||||||
Error readGSIHashRecords(FixedStreamArray<PSHashRecord> &HashRecords,
|
Error readGSIHashRecords(msf::FixedStreamArray<PSHashRecord> &HashRecords,
|
||||||
const GSIHashHeader *HashHdr,
|
const GSIHashHeader *HashHdr,
|
||||||
BinaryStreamReader &Reader);
|
msf::StreamReader &Reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ GlobalsStream::GlobalsStream(std::unique_ptr<MappedBlockStream> Stream)
|
|||||||
GlobalsStream::~GlobalsStream() = default;
|
GlobalsStream::~GlobalsStream() = default;
|
||||||
|
|
||||||
Error GlobalsStream::reload() {
|
Error GlobalsStream::reload() {
|
||||||
BinaryStreamReader Reader(*Stream);
|
StreamReader Reader(*Stream);
|
||||||
|
|
||||||
const GSIHashHeader *HashHdr;
|
const GSIHashHeader *HashHdr;
|
||||||
if (auto EC = readGSIHashHeader(HashHdr, Reader))
|
if (auto EC = readGSIHashHeader(HashHdr, Reader))
|
||||||
|
@ -22,7 +22,7 @@ HashTable::HashTable() : HashTable(8) {}
|
|||||||
|
|
||||||
HashTable::HashTable(uint32_t Capacity) { Buckets.resize(Capacity); }
|
HashTable::HashTable(uint32_t Capacity) { Buckets.resize(Capacity); }
|
||||||
|
|
||||||
Error HashTable::load(BinaryStreamReader &Stream) {
|
Error HashTable::load(msf::StreamReader &Stream) {
|
||||||
const Header *H;
|
const Header *H;
|
||||||
if (auto EC = Stream.readObject(H))
|
if (auto EC = Stream.readObject(H))
|
||||||
return EC;
|
return EC;
|
||||||
@ -48,9 +48,9 @@ Error HashTable::load(BinaryStreamReader &Stream) {
|
|||||||
"Present bit vector interesects deleted!");
|
"Present bit vector interesects deleted!");
|
||||||
|
|
||||||
for (uint32_t P : Present) {
|
for (uint32_t P : Present) {
|
||||||
if (auto EC = Stream.readInteger(Buckets[P].first))
|
if (auto EC = Stream.readInteger(Buckets[P].first, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = Stream.readInteger(Buckets[P].second))
|
if (auto EC = Stream.readInteger(Buckets[P].second, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ uint32_t HashTable::calculateSerializedLength() const {
|
|||||||
return Size;
|
return Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error HashTable::commit(BinaryStreamWriter &Writer) const {
|
Error HashTable::commit(msf::StreamWriter &Writer) const {
|
||||||
Header H;
|
Header H;
|
||||||
H.Size = size();
|
H.Size = size();
|
||||||
H.Capacity = capacity();
|
H.Capacity = capacity();
|
||||||
@ -91,9 +91,9 @@ Error HashTable::commit(BinaryStreamWriter &Writer) const {
|
|||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
for (const auto &Entry : *this) {
|
for (const auto &Entry : *this) {
|
||||||
if (auto EC = Writer.writeInteger(Entry.first))
|
if (auto EC = Writer.writeInteger(Entry.first, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = Writer.writeInteger(Entry.second))
|
if (auto EC = Writer.writeInteger(Entry.second, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
return Error::success();
|
return Error::success();
|
||||||
@ -209,10 +209,10 @@ void HashTable::grow() {
|
|||||||
assert(size() == S);
|
assert(size() == S);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error HashTable::readSparseBitVector(BinaryStreamReader &Stream,
|
Error HashTable::readSparseBitVector(msf::StreamReader &Stream,
|
||||||
SparseBitVector<> &V) {
|
SparseBitVector<> &V) {
|
||||||
uint32_t NumWords;
|
uint32_t NumWords;
|
||||||
if (auto EC = Stream.readInteger(NumWords))
|
if (auto EC = Stream.readInteger(NumWords, llvm::support::little))
|
||||||
return joinErrors(
|
return joinErrors(
|
||||||
std::move(EC),
|
std::move(EC),
|
||||||
make_error<RawError>(raw_error_code::corrupt_file,
|
make_error<RawError>(raw_error_code::corrupt_file,
|
||||||
@ -220,7 +220,7 @@ Error HashTable::readSparseBitVector(BinaryStreamReader &Stream,
|
|||||||
|
|
||||||
for (uint32_t I = 0; I != NumWords; ++I) {
|
for (uint32_t I = 0; I != NumWords; ++I) {
|
||||||
uint32_t Word;
|
uint32_t Word;
|
||||||
if (auto EC = Stream.readInteger(Word))
|
if (auto EC = Stream.readInteger(Word, llvm::support::little))
|
||||||
return joinErrors(std::move(EC),
|
return joinErrors(std::move(EC),
|
||||||
make_error<RawError>(raw_error_code::corrupt_file,
|
make_error<RawError>(raw_error_code::corrupt_file,
|
||||||
"Expected hash table word"));
|
"Expected hash table word"));
|
||||||
@ -231,11 +231,11 @@ Error HashTable::readSparseBitVector(BinaryStreamReader &Stream,
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error HashTable::writeSparseBitVector(BinaryStreamWriter &Writer,
|
Error HashTable::writeSparseBitVector(msf::StreamWriter &Writer,
|
||||||
SparseBitVector<> &Vec) {
|
SparseBitVector<> &Vec) {
|
||||||
int ReqBits = Vec.find_last() + 1;
|
int ReqBits = Vec.find_last() + 1;
|
||||||
uint32_t NumWords = alignTo(ReqBits, sizeof(uint32_t)) / sizeof(uint32_t);
|
uint32_t NumWords = alignTo(ReqBits, sizeof(uint32_t)) / sizeof(uint32_t);
|
||||||
if (auto EC = Writer.writeInteger(NumWords))
|
if (auto EC = Writer.writeInteger(NumWords, llvm::support::little))
|
||||||
return joinErrors(
|
return joinErrors(
|
||||||
std::move(EC),
|
std::move(EC),
|
||||||
make_error<RawError>(raw_error_code::corrupt_file,
|
make_error<RawError>(raw_error_code::corrupt_file,
|
||||||
@ -248,7 +248,7 @@ Error HashTable::writeSparseBitVector(BinaryStreamWriter &Writer,
|
|||||||
if (Vec.test(Idx))
|
if (Vec.test(Idx))
|
||||||
Word |= (1 << WordIdx);
|
Word |= (1 << WordIdx);
|
||||||
}
|
}
|
||||||
if (auto EC = Writer.writeInteger(Word))
|
if (auto EC = Writer.writeInteger(Word, llvm::support::little))
|
||||||
return joinErrors(std::move(EC), make_error<RawError>(
|
return joinErrors(std::move(EC), make_error<RawError>(
|
||||||
raw_error_code::corrupt_file,
|
raw_error_code::corrupt_file,
|
||||||
"Could not write linear map word"));
|
"Could not write linear map word"));
|
||||||
|
@ -26,7 +26,7 @@ InfoStream::InfoStream(std::unique_ptr<MappedBlockStream> Stream)
|
|||||||
: Stream(std::move(Stream)) {}
|
: Stream(std::move(Stream)) {}
|
||||||
|
|
||||||
Error InfoStream::reload() {
|
Error InfoStream::reload() {
|
||||||
BinaryStreamReader Reader(*Stream);
|
StreamReader Reader(*Stream);
|
||||||
|
|
||||||
const InfoStreamHeader *H;
|
const InfoStreamHeader *H;
|
||||||
if (auto EC = Reader.readObject(H))
|
if (auto EC = Reader.readObject(H))
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
|
#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
|
||||||
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamWriter.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamWriter.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamWriter.h"
|
||||||
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
|
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
|
||||||
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
||||||
@ -45,10 +44,10 @@ Error InfoStreamBuilder::finalizeMsfLayout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Error InfoStreamBuilder::commit(const msf::MSFLayout &Layout,
|
Error InfoStreamBuilder::commit(const msf::MSFLayout &Layout,
|
||||||
WritableBinaryStreamRef Buffer) const {
|
const msf::WritableStream &Buffer) const {
|
||||||
auto InfoS =
|
auto InfoS =
|
||||||
WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamPDB);
|
WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamPDB);
|
||||||
BinaryStreamWriter Writer(*InfoS);
|
StreamWriter Writer(*InfoS);
|
||||||
|
|
||||||
InfoStreamHeader H;
|
InfoStreamHeader H;
|
||||||
H.Age = Age;
|
H.Age = Age;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace llvm::msf;
|
||||||
using namespace llvm::pdb;
|
using namespace llvm::pdb;
|
||||||
using namespace llvm::support;
|
using namespace llvm::support;
|
||||||
|
|
||||||
@ -25,15 +26,15 @@ ModInfo::ModInfo(const ModInfo &Info) = default;
|
|||||||
|
|
||||||
ModInfo::~ModInfo() = default;
|
ModInfo::~ModInfo() = default;
|
||||||
|
|
||||||
Error ModInfo::initialize(BinaryStreamRef Stream, ModInfo &Info) {
|
Error ModInfo::initialize(ReadableStreamRef Stream, ModInfo &Info) {
|
||||||
BinaryStreamReader Reader(Stream);
|
StreamReader Reader(Stream);
|
||||||
if (auto EC = Reader.readObject(Info.Layout))
|
if (auto EC = Reader.readObject(Info.Layout))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
if (auto EC = Reader.readCString(Info.ModuleName))
|
if (auto EC = Reader.readZeroString(Info.ModuleName))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
if (auto EC = Reader.readCString(Info.ObjFileName))
|
if (auto EC = Reader.readZeroString(Info.ObjFileName))
|
||||||
return EC;
|
return EC;
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ ModStream::ModStream(const ModInfo &Module,
|
|||||||
ModStream::~ModStream() = default;
|
ModStream::~ModStream() = default;
|
||||||
|
|
||||||
Error ModStream::reload() {
|
Error ModStream::reload() {
|
||||||
BinaryStreamReader Reader(*Stream);
|
StreamReader Reader(*Stream);
|
||||||
|
|
||||||
uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize();
|
uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize();
|
||||||
uint32_t C11Size = Mod.getLineInfoByteSize();
|
uint32_t C11Size = Mod.getLineInfoByteSize();
|
||||||
@ -41,9 +41,9 @@ Error ModStream::reload() {
|
|||||||
return make_error<RawError>(raw_error_code::corrupt_file,
|
return make_error<RawError>(raw_error_code::corrupt_file,
|
||||||
"Module has both C11 and C13 line info");
|
"Module has both C11 and C13 line info");
|
||||||
|
|
||||||
BinaryStreamRef S;
|
ReadableStreamRef S;
|
||||||
|
|
||||||
if (auto EC = Reader.readInteger(Signature))
|
if (auto EC = Reader.readInteger(Signature, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = Reader.readArray(SymbolsSubstream, SymbolSize - 4))
|
if (auto EC = Reader.readArray(SymbolsSubstream, SymbolSize - 4))
|
||||||
return EC;
|
return EC;
|
||||||
@ -53,12 +53,12 @@ Error ModStream::reload() {
|
|||||||
if (auto EC = Reader.readStreamRef(C13LinesSubstream, C13Size))
|
if (auto EC = Reader.readStreamRef(C13LinesSubstream, C13Size))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
BinaryStreamReader LineReader(C13LinesSubstream);
|
StreamReader LineReader(C13LinesSubstream);
|
||||||
if (auto EC = LineReader.readArray(LineInfo, LineReader.bytesRemaining()))
|
if (auto EC = LineReader.readArray(LineInfo, LineReader.bytesRemaining()))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
uint32_t GlobalRefsSize;
|
uint32_t GlobalRefsSize;
|
||||||
if (auto EC = Reader.readInteger(GlobalRefsSize))
|
if (auto EC = Reader.readInteger(GlobalRefsSize, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = Reader.readStreamRef(GlobalRefsSubstream, GlobalRefsSize))
|
if (auto EC = Reader.readStreamRef(GlobalRefsSubstream, GlobalRefsSize))
|
||||||
return EC;
|
return EC;
|
||||||
|
@ -21,22 +21,23 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace llvm::msf;
|
||||||
using namespace llvm::pdb;
|
using namespace llvm::pdb;
|
||||||
|
|
||||||
NamedStreamMap::NamedStreamMap() = default;
|
NamedStreamMap::NamedStreamMap() = default;
|
||||||
|
|
||||||
Error NamedStreamMap::load(BinaryStreamReader &Stream) {
|
Error NamedStreamMap::load(StreamReader &Stream) {
|
||||||
Mapping.clear();
|
Mapping.clear();
|
||||||
FinalizedHashTable.clear();
|
FinalizedHashTable.clear();
|
||||||
FinalizedInfo.reset();
|
FinalizedInfo.reset();
|
||||||
|
|
||||||
uint32_t StringBufferSize;
|
uint32_t StringBufferSize;
|
||||||
if (auto EC = Stream.readInteger(StringBufferSize))
|
if (auto EC = Stream.readInteger(StringBufferSize, llvm::support::little))
|
||||||
return joinErrors(std::move(EC),
|
return joinErrors(std::move(EC),
|
||||||
make_error<RawError>(raw_error_code::corrupt_file,
|
make_error<RawError>(raw_error_code::corrupt_file,
|
||||||
"Expected string buffer size"));
|
"Expected string buffer size"));
|
||||||
|
|
||||||
BinaryStreamRef StringsBuffer;
|
msf::ReadableStreamRef StringsBuffer;
|
||||||
if (auto EC = Stream.readStreamRef(StringsBuffer, StringBufferSize))
|
if (auto EC = Stream.readStreamRef(StringsBuffer, StringBufferSize))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
@ -50,11 +51,11 @@ Error NamedStreamMap::load(BinaryStreamReader &Stream) {
|
|||||||
std::tie(NameOffset, NameIndex) = Entry;
|
std::tie(NameOffset, NameIndex) = Entry;
|
||||||
|
|
||||||
// Compute the offset of the start of the string relative to the stream.
|
// Compute the offset of the start of the string relative to the stream.
|
||||||
BinaryStreamReader NameReader(StringsBuffer);
|
msf::StreamReader NameReader(StringsBuffer);
|
||||||
NameReader.setOffset(NameOffset);
|
NameReader.setOffset(NameOffset);
|
||||||
// Pump out our c-string from the stream.
|
// Pump out our c-string from the stream.
|
||||||
StringRef Str;
|
StringRef Str;
|
||||||
if (auto EC = NameReader.readCString(Str))
|
if (auto EC = NameReader.readZeroString(Str))
|
||||||
return joinErrors(std::move(EC),
|
return joinErrors(std::move(EC),
|
||||||
make_error<RawError>(raw_error_code::corrupt_file,
|
make_error<RawError>(raw_error_code::corrupt_file,
|
||||||
"Expected name map name"));
|
"Expected name map name"));
|
||||||
@ -66,16 +67,17 @@ Error NamedStreamMap::load(BinaryStreamReader &Stream) {
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error NamedStreamMap::commit(BinaryStreamWriter &Writer) const {
|
Error NamedStreamMap::commit(msf::StreamWriter &Writer) const {
|
||||||
assert(FinalizedInfo.hasValue());
|
assert(FinalizedInfo.hasValue());
|
||||||
|
|
||||||
// The first field is the number of bytes of string data.
|
// The first field is the number of bytes of string data.
|
||||||
if (auto EC = Writer.writeInteger(FinalizedInfo->StringDataBytes))
|
if (auto EC = Writer.writeInteger(FinalizedInfo->StringDataBytes,
|
||||||
|
llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
// Now all of the string data itself.
|
// Now all of the string data itself.
|
||||||
for (const auto &Item : Mapping) {
|
for (const auto &Item : Mapping) {
|
||||||
if (auto EC = Writer.writeCString(Item.getKey()))
|
if (auto EC = Writer.writeZeroString(Item.getKey()))
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,8 +45,7 @@ Error NativeSession::createFromPdb(StringRef Path,
|
|||||||
return make_error<GenericError>(generic_error_code::invalid_path);
|
return make_error<GenericError>(generic_error_code::invalid_path);
|
||||||
|
|
||||||
std::unique_ptr<MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
|
std::unique_ptr<MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
|
||||||
auto Stream = llvm::make_unique<MemoryBufferByteStream>(
|
auto Stream = llvm::make_unique<MemoryBufferByteStream>(std::move(Buffer));
|
||||||
std::move(Buffer), llvm::support::little);
|
|
||||||
|
|
||||||
auto Allocator = llvm::make_unique<BumpPtrAllocator>();
|
auto Allocator = llvm::make_unique<BumpPtrAllocator>();
|
||||||
auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), *Allocator);
|
auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), *Allocator);
|
||||||
|
@ -11,10 +11,7 @@
|
|||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
||||||
#include "llvm/DebugInfo/MSF/MSFCommon.h"
|
#include "llvm/DebugInfo/MSF/MSFCommon.h"
|
||||||
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
||||||
@ -42,7 +39,7 @@ namespace {
|
|||||||
typedef FixedStreamArray<support::ulittle32_t> ulittle_array;
|
typedef FixedStreamArray<support::ulittle32_t> ulittle_array;
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
PDBFile::PDBFile(StringRef Path, std::unique_ptr<BinaryStream> PdbFileBuffer,
|
PDBFile::PDBFile(StringRef Path, std::unique_ptr<ReadableStream> PdbFileBuffer,
|
||||||
BumpPtrAllocator &Allocator)
|
BumpPtrAllocator &Allocator)
|
||||||
: FilePath(Path), Allocator(Allocator), Buffer(std::move(PdbFileBuffer)) {}
|
: FilePath(Path), Allocator(Allocator), Buffer(std::move(PdbFileBuffer)) {}
|
||||||
|
|
||||||
@ -116,7 +113,7 @@ Error PDBFile::setBlockData(uint32_t BlockIndex, uint32_t Offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Error PDBFile::parseFileHeaders() {
|
Error PDBFile::parseFileHeaders() {
|
||||||
BinaryStreamReader Reader(*Buffer);
|
StreamReader Reader(*Buffer);
|
||||||
|
|
||||||
// Initialize SB.
|
// Initialize SB.
|
||||||
const msf::SuperBlock *SB = nullptr;
|
const msf::SuperBlock *SB = nullptr;
|
||||||
@ -150,7 +147,7 @@ Error PDBFile::parseFileHeaders() {
|
|||||||
// See the function fpmPn() for more information:
|
// See the function fpmPn() for more information:
|
||||||
// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/msf/msf.cpp#L489
|
// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/msf/msf.cpp#L489
|
||||||
auto FpmStream = MappedBlockStream::createFpmStream(ContainerLayout, *Buffer);
|
auto FpmStream = MappedBlockStream::createFpmStream(ContainerLayout, *Buffer);
|
||||||
BinaryStreamReader FpmReader(*FpmStream);
|
StreamReader FpmReader(*FpmStream);
|
||||||
ArrayRef<uint8_t> FpmBytes;
|
ArrayRef<uint8_t> FpmBytes;
|
||||||
if (auto EC = FpmReader.readBytes(FpmBytes,
|
if (auto EC = FpmReader.readBytes(FpmBytes,
|
||||||
msf::getFullFpmByteSize(ContainerLayout)))
|
msf::getFullFpmByteSize(ContainerLayout)))
|
||||||
@ -188,8 +185,8 @@ Error PDBFile::parseStreamData() {
|
|||||||
// subclass of IPDBStreamData which only accesses the fields that have already
|
// subclass of IPDBStreamData which only accesses the fields that have already
|
||||||
// been parsed, we can avoid this and reuse MappedBlockStream.
|
// been parsed, we can avoid this and reuse MappedBlockStream.
|
||||||
auto DS = MappedBlockStream::createDirectoryStream(ContainerLayout, *Buffer);
|
auto DS = MappedBlockStream::createDirectoryStream(ContainerLayout, *Buffer);
|
||||||
BinaryStreamReader Reader(*DS);
|
StreamReader Reader(*DS);
|
||||||
if (auto EC = Reader.readInteger(NumStreams))
|
if (auto EC = Reader.readInteger(NumStreams, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
if (auto EC = Reader.readArray(ContainerLayout.StreamSizes, NumStreams))
|
if (auto EC = Reader.readArray(ContainerLayout.StreamSizes, NumStreams))
|
||||||
@ -353,7 +350,7 @@ Expected<StringTable &> PDBFile::getStringTable() {
|
|||||||
if (!NS)
|
if (!NS)
|
||||||
return NS.takeError();
|
return NS.takeError();
|
||||||
|
|
||||||
BinaryStreamReader Reader(**NS);
|
StreamReader Reader(**NS);
|
||||||
auto N = llvm::make_unique<StringTable>();
|
auto N = llvm::make_unique<StringTable>();
|
||||||
if (auto EC = N->load(Reader))
|
if (auto EC = N->load(Reader))
|
||||||
return std::move(EC);
|
return std::move(EC);
|
||||||
@ -406,7 +403,7 @@ bool PDBFile::hasStringTable() {
|
|||||||
/// contain the stream returned by createIndexedStream().
|
/// contain the stream returned by createIndexedStream().
|
||||||
Expected<std::unique_ptr<MappedBlockStream>>
|
Expected<std::unique_ptr<MappedBlockStream>>
|
||||||
PDBFile::safelyCreateIndexedStream(const MSFLayout &Layout,
|
PDBFile::safelyCreateIndexedStream(const MSFLayout &Layout,
|
||||||
BinaryStreamRef MsfData,
|
const ReadableStream &MsfData,
|
||||||
uint32_t StreamIndex) const {
|
uint32_t StreamIndex) const {
|
||||||
if (StreamIndex >= getNumStreams())
|
if (StreamIndex >= getNumStreams())
|
||||||
return make_error<RawError>(raw_error_code::no_stream);
|
return make_error<RawError>(raw_error_code::no_stream);
|
||||||
|
@ -12,8 +12,6 @@
|
|||||||
#include "llvm/ADT/BitVector.h"
|
#include "llvm/ADT/BitVector.h"
|
||||||
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamWriter.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamWriter.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamWriter.h"
|
||||||
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
|
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
|
||||||
#include "llvm/DebugInfo/PDB/GenericError.h"
|
#include "llvm/DebugInfo/PDB/GenericError.h"
|
||||||
@ -120,9 +118,8 @@ Error PDBFileBuilder::commit(StringRef Filename) {
|
|||||||
if (OutFileOrError.getError())
|
if (OutFileOrError.getError())
|
||||||
return llvm::make_error<pdb::GenericError>(generic_error_code::invalid_path,
|
return llvm::make_error<pdb::GenericError>(generic_error_code::invalid_path,
|
||||||
Filename);
|
Filename);
|
||||||
FileBufferByteStream Buffer(std::move(*OutFileOrError),
|
FileBufferByteStream Buffer(std::move(*OutFileOrError));
|
||||||
llvm::support::little);
|
StreamWriter Writer(Buffer);
|
||||||
BinaryStreamWriter Writer(Buffer);
|
|
||||||
|
|
||||||
if (auto EC = Writer.writeObject(*Layout.SB))
|
if (auto EC = Writer.writeObject(*Layout.SB))
|
||||||
return EC;
|
return EC;
|
||||||
@ -134,8 +131,9 @@ Error PDBFileBuilder::commit(StringRef Filename) {
|
|||||||
|
|
||||||
auto DirStream =
|
auto DirStream =
|
||||||
WritableMappedBlockStream::createDirectoryStream(Layout, Buffer);
|
WritableMappedBlockStream::createDirectoryStream(Layout, Buffer);
|
||||||
BinaryStreamWriter DW(*DirStream);
|
StreamWriter DW(*DirStream);
|
||||||
if (auto EC = DW.writeInteger<uint32_t>(Layout.StreamSizes.size()))
|
if (auto EC = DW.writeInteger<uint32_t>(Layout.StreamSizes.size(),
|
||||||
|
llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
if (auto EC = DW.writeArray(Layout.StreamSizes))
|
if (auto EC = DW.writeArray(Layout.StreamSizes))
|
||||||
@ -152,7 +150,7 @@ Error PDBFileBuilder::commit(StringRef Filename) {
|
|||||||
|
|
||||||
auto NS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
|
auto NS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
|
||||||
StringTableStreamNo);
|
StringTableStreamNo);
|
||||||
BinaryStreamWriter NSWriter(*NS);
|
StreamWriter NSWriter(*NS);
|
||||||
if (auto EC = Strings.commit(NSWriter))
|
if (auto EC = Strings.commit(NSWriter))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#include "llvm/ADT/iterator_range.h"
|
#include "llvm/ADT/iterator_range.h"
|
||||||
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
|
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/RawError.h"
|
#include "llvm/DebugInfo/PDB/Native/RawError.h"
|
||||||
@ -70,7 +69,7 @@ uint32_t PublicsStream::getAddrMap() const { return Header->AddrMap; }
|
|||||||
// we skip over the hash table which we believe contains information about
|
// we skip over the hash table which we believe contains information about
|
||||||
// public symbols.
|
// public symbols.
|
||||||
Error PublicsStream::reload() {
|
Error PublicsStream::reload() {
|
||||||
BinaryStreamReader Reader(*Stream);
|
StreamReader Reader(*Stream);
|
||||||
|
|
||||||
// Check stream size.
|
// Check stream size.
|
||||||
if (Reader.bytesRemaining() < sizeof(HeaderInfo) + sizeof(GSIHashHeader))
|
if (Reader.bytesRemaining() < sizeof(HeaderInfo) + sizeof(GSIHashHeader))
|
||||||
|
@ -17,12 +17,13 @@
|
|||||||
#include "llvm/Support/Endian.h"
|
#include "llvm/Support/Endian.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace llvm::msf;
|
||||||
using namespace llvm::support;
|
using namespace llvm::support;
|
||||||
using namespace llvm::pdb;
|
using namespace llvm::pdb;
|
||||||
|
|
||||||
StringTable::StringTable() : Signature(0), HashVersion(0), NameCount(0) {}
|
StringTable::StringTable() : Signature(0), HashVersion(0), NameCount(0) {}
|
||||||
|
|
||||||
Error StringTable::load(BinaryStreamReader &Stream) {
|
Error StringTable::load(StreamReader &Stream) {
|
||||||
const StringTableHeader *H;
|
const StringTableHeader *H;
|
||||||
if (auto EC = Stream.readObject(H))
|
if (auto EC = Stream.readObject(H))
|
||||||
return EC;
|
return EC;
|
||||||
@ -54,7 +55,7 @@ Error StringTable::load(BinaryStreamReader &Stream) {
|
|||||||
return make_error<RawError>(raw_error_code::corrupt_file,
|
return make_error<RawError>(raw_error_code::corrupt_file,
|
||||||
"Missing name count");
|
"Missing name count");
|
||||||
|
|
||||||
if (auto EC = Stream.readInteger(NameCount))
|
if (auto EC = Stream.readInteger(NameCount, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
@ -67,9 +68,9 @@ StringRef StringTable::getStringForID(uint32_t ID) const {
|
|||||||
// the starting offset of the string we're looking for. So just seek into
|
// the starting offset of the string we're looking for. So just seek into
|
||||||
// the desired offset and a read a null terminated stream from that offset.
|
// the desired offset and a read a null terminated stream from that offset.
|
||||||
StringRef Result;
|
StringRef Result;
|
||||||
BinaryStreamReader NameReader(NamesBuffer);
|
StreamReader NameReader(NamesBuffer);
|
||||||
NameReader.setOffset(ID);
|
NameReader.setOffset(ID);
|
||||||
if (auto EC = NameReader.readCString(Result))
|
if (auto EC = NameReader.readZeroString(Result))
|
||||||
consumeError(std::move(EC));
|
consumeError(std::move(EC));
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ uint32_t StringTableBuilder::finalize() {
|
|||||||
return Size;
|
return Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error StringTableBuilder::commit(BinaryStreamWriter &Writer) const {
|
Error StringTableBuilder::commit(msf::StreamWriter &Writer) const {
|
||||||
// Write a header
|
// Write a header
|
||||||
StringTableHeader H;
|
StringTableHeader H;
|
||||||
H.Signature = StringTableSignature;
|
H.Signature = StringTableSignature;
|
||||||
@ -67,14 +67,14 @@ Error StringTableBuilder::commit(BinaryStreamWriter &Writer) const {
|
|||||||
StringRef S = Pair.first;
|
StringRef S = Pair.first;
|
||||||
uint32_t Offset = Pair.second;
|
uint32_t Offset = Pair.second;
|
||||||
Writer.setOffset(StringStart + Offset);
|
Writer.setOffset(StringStart + Offset);
|
||||||
if (auto EC = Writer.writeCString(S))
|
if (auto EC = Writer.writeZeroString(S))
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
Writer.setOffset(StringStart + StringSize);
|
Writer.setOffset(StringStart + StringSize);
|
||||||
|
|
||||||
// Write a hash table.
|
// Write a hash table.
|
||||||
uint32_t BucketCount = computeBucketCount(Strings.size());
|
uint32_t BucketCount = computeBucketCount(Strings.size());
|
||||||
if (auto EC = Writer.writeInteger(BucketCount))
|
if (auto EC = Writer.writeInteger(BucketCount, llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
std::vector<ulittle32_t> Buckets(BucketCount);
|
std::vector<ulittle32_t> Buckets(BucketCount);
|
||||||
|
|
||||||
@ -96,7 +96,8 @@ Error StringTableBuilder::commit(BinaryStreamWriter &Writer) const {
|
|||||||
|
|
||||||
if (auto EC = Writer.writeArray(ArrayRef<ulittle32_t>(Buckets)))
|
if (auto EC = Writer.writeArray(ArrayRef<ulittle32_t>(Buckets)))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = Writer.writeInteger(static_cast<uint32_t>(Strings.size())))
|
if (auto EC = Writer.writeInteger(static_cast<uint32_t>(Strings.size()),
|
||||||
|
llvm::support::little))
|
||||||
return EC;
|
return EC;
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
|
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/RawError.h"
|
#include "llvm/DebugInfo/PDB/Native/RawError.h"
|
||||||
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
|
||||||
#include "llvm/Support/Endian.h"
|
#include "llvm/Support/Endian.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
@ -31,7 +30,7 @@ SymbolStream::SymbolStream(std::unique_ptr<MappedBlockStream> Stream)
|
|||||||
SymbolStream::~SymbolStream() {}
|
SymbolStream::~SymbolStream() {}
|
||||||
|
|
||||||
Error SymbolStream::reload() {
|
Error SymbolStream::reload() {
|
||||||
BinaryStreamReader Reader(*Stream);
|
StreamReader Reader(*Stream);
|
||||||
|
|
||||||
if (auto EC = Reader.readArray(SymbolRecords, Stream->getLength()))
|
if (auto EC = Reader.readArray(SymbolRecords, Stream->getLength()))
|
||||||
return EC;
|
return EC;
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||||
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
|
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
|
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
|
#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
|
||||||
@ -55,7 +54,7 @@ Error TpiStream::verifyHashValues() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Error TpiStream::reload() {
|
Error TpiStream::reload() {
|
||||||
BinaryStreamReader Reader(*Stream);
|
StreamReader Reader(*Stream);
|
||||||
|
|
||||||
if (Reader.bytesRemaining() < sizeof(TpiStreamHeader))
|
if (Reader.bytesRemaining() < sizeof(TpiStreamHeader))
|
||||||
return make_error<RawError>(raw_error_code::corrupt_file,
|
return make_error<RawError>(raw_error_code::corrupt_file,
|
||||||
@ -94,7 +93,7 @@ Error TpiStream::reload() {
|
|||||||
|
|
||||||
auto HS = MappedBlockStream::createIndexedStream(
|
auto HS = MappedBlockStream::createIndexedStream(
|
||||||
Pdb.getMsfLayout(), Pdb.getMsfBuffer(), Header->HashStreamIndex);
|
Pdb.getMsfLayout(), Pdb.getMsfBuffer(), Header->HashStreamIndex);
|
||||||
BinaryStreamReader HSR(*HS);
|
StreamReader HSR(*HS);
|
||||||
|
|
||||||
uint32_t NumHashValues =
|
uint32_t NumHashValues =
|
||||||
Header->HashValueBuffer.Length / sizeof(ulittle32_t);
|
Header->HashValueBuffer.Length / sizeof(ulittle32_t);
|
||||||
|
@ -34,8 +34,7 @@ using namespace llvm::pdb;
|
|||||||
using namespace llvm::support;
|
using namespace llvm::support;
|
||||||
|
|
||||||
TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf, uint32_t StreamIdx)
|
TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf, uint32_t StreamIdx)
|
||||||
: Msf(Msf), Allocator(Msf.getAllocator()),
|
: Msf(Msf), Allocator(Msf.getAllocator()), Header(nullptr), Idx(StreamIdx) {
|
||||||
TypeRecordStream(llvm::support::little), Header(nullptr), Idx(StreamIdx) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TpiStreamBuilder::~TpiStreamBuilder() = default;
|
TpiStreamBuilder::~TpiStreamBuilder() = default;
|
||||||
@ -83,7 +82,7 @@ Error TpiStreamBuilder::finalize() {
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t TpiStreamBuilder::calculateSerializedLength() {
|
uint32_t TpiStreamBuilder::calculateSerializedLength() const {
|
||||||
return sizeof(TpiStreamHeader) + TypeRecordStream.getLength();
|
return sizeof(TpiStreamHeader) + TypeRecordStream.getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,20 +113,19 @@ Error TpiStreamBuilder::finalizeMsfLayout() {
|
|||||||
}
|
}
|
||||||
ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(HashBuffer.data()),
|
ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(HashBuffer.data()),
|
||||||
HashBufferSize);
|
HashBufferSize);
|
||||||
HashValueStream =
|
HashValueStream = llvm::make_unique<ByteStream>(Bytes);
|
||||||
llvm::make_unique<BinaryByteStream>(Bytes, llvm::support::little);
|
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout,
|
Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout,
|
||||||
WritableBinaryStreamRef Buffer) {
|
const msf::WritableStream &Buffer) {
|
||||||
if (auto EC = finalize())
|
if (auto EC = finalize())
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
auto InfoS =
|
auto InfoS =
|
||||||
WritableMappedBlockStream::createIndexedStream(Layout, Buffer, Idx);
|
WritableMappedBlockStream::createIndexedStream(Layout, Buffer, Idx);
|
||||||
|
|
||||||
BinaryStreamWriter Writer(*InfoS);
|
StreamWriter Writer(*InfoS);
|
||||||
if (auto EC = Writer.writeObject(*Header))
|
if (auto EC = Writer.writeObject(*Header))
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
@ -138,7 +136,7 @@ Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout,
|
|||||||
if (HashStreamIndex != kInvalidStreamIndex) {
|
if (HashStreamIndex != kInvalidStreamIndex) {
|
||||||
auto HVS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
|
auto HVS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
|
||||||
HashStreamIndex);
|
HashStreamIndex);
|
||||||
BinaryStreamWriter HW(*HVS);
|
StreamWriter HW(*HVS);
|
||||||
if (auto EC = HW.writeStreamRef(*HashValueStream))
|
if (auto EC = HW.writeStreamRef(*HashValueStream))
|
||||||
return EC;
|
return EC;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
|
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
|
||||||
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
|
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
|
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/EnumTables.h"
|
#include "llvm/DebugInfo/PDB/Native/EnumTables.h"
|
||||||
@ -451,7 +450,7 @@ Error LLVMOutputStyle::dumpStreamBytes() {
|
|||||||
auto Blocks = File.getMsfLayout().StreamMap[SI];
|
auto Blocks = File.getMsfLayout().StreamMap[SI];
|
||||||
P.printList("Blocks", Blocks);
|
P.printList("Blocks", Blocks);
|
||||||
|
|
||||||
BinaryStreamReader R(*S);
|
StreamReader R(*S);
|
||||||
ArrayRef<uint8_t> StreamData;
|
ArrayRef<uint8_t> StreamData;
|
||||||
if (auto EC = R.readBytes(StreamData, S->getLength()))
|
if (auto EC = R.readBytes(StreamData, S->getLength()))
|
||||||
return EC;
|
return EC;
|
||||||
@ -746,10 +745,10 @@ Error LLVMOutputStyle::dumpDbiStream() {
|
|||||||
public:
|
public:
|
||||||
RecordVisitor(ScopedPrinter &P, PDBFile &F) : P(P), F(F) {}
|
RecordVisitor(ScopedPrinter &P, PDBFile &F) : P(P), F(F) {}
|
||||||
Error visitUnknown(ModuleSubstreamKind Kind,
|
Error visitUnknown(ModuleSubstreamKind Kind,
|
||||||
BinaryStreamRef Stream) override {
|
ReadableStreamRef Stream) override {
|
||||||
DictScope DD(P, "Unknown");
|
DictScope DD(P, "Unknown");
|
||||||
ArrayRef<uint8_t> Data;
|
ArrayRef<uint8_t> Data;
|
||||||
BinaryStreamReader R(Stream);
|
StreamReader R(Stream);
|
||||||
if (auto EC = R.readBytes(Data, R.bytesRemaining())) {
|
if (auto EC = R.readBytes(Data, R.bytesRemaining())) {
|
||||||
return make_error<RawError>(
|
return make_error<RawError>(
|
||||||
raw_error_code::corrupt_file,
|
raw_error_code::corrupt_file,
|
||||||
@ -759,7 +758,7 @@ Error LLVMOutputStyle::dumpDbiStream() {
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
Error
|
Error
|
||||||
visitFileChecksums(BinaryStreamRef Data,
|
visitFileChecksums(ReadableStreamRef Data,
|
||||||
const FileChecksumArray &Checksums) override {
|
const FileChecksumArray &Checksums) override {
|
||||||
DictScope DD(P, "FileChecksums");
|
DictScope DD(P, "FileChecksums");
|
||||||
for (const auto &C : Checksums) {
|
for (const auto &C : Checksums) {
|
||||||
@ -775,7 +774,7 @@ Error LLVMOutputStyle::dumpDbiStream() {
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error visitLines(BinaryStreamRef Data,
|
Error visitLines(ReadableStreamRef Data,
|
||||||
const LineSubstreamHeader *Header,
|
const LineSubstreamHeader *Header,
|
||||||
const LineInfoArray &Lines) override {
|
const LineInfoArray &Lines) override {
|
||||||
DictScope DD(P, "Lines");
|
DictScope DD(P, "Lines");
|
||||||
|
@ -573,8 +573,8 @@ struct MappingContextTraits<pdb::yaml::PdbTpiFieldListRecord,
|
|||||||
assert(IO.outputting());
|
assert(IO.outputting());
|
||||||
codeview::TypeVisitorCallbackPipeline Pipeline;
|
codeview::TypeVisitorCallbackPipeline Pipeline;
|
||||||
|
|
||||||
BinaryByteStream Data(Obj.Record.Data, llvm::support::little);
|
msf::ByteStream Data(Obj.Record.Data);
|
||||||
BinaryStreamReader FieldReader(Data);
|
msf::StreamReader FieldReader(Data);
|
||||||
codeview::FieldListDeserializer Deserializer(FieldReader);
|
codeview::FieldListDeserializer Deserializer(FieldReader);
|
||||||
|
|
||||||
// For PDB to Yaml, deserialize into a high level record type, then dump
|
// For PDB to Yaml, deserialize into a high level record type, then dump
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::object;
|
using namespace llvm::object;
|
||||||
using namespace llvm::codeview;
|
using namespace llvm::codeview;
|
||||||
|
using namespace llvm::msf;
|
||||||
using namespace llvm::support;
|
using namespace llvm::support;
|
||||||
using namespace llvm::Win64EH;
|
using namespace llvm::Win64EH;
|
||||||
|
|
||||||
@ -154,7 +155,7 @@ public:
|
|||||||
Sec = Obj->getCOFFSection(SR);
|
Sec = Obj->getCOFFSection(SR);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getRecordOffset(BinaryStreamReader Reader) override {
|
uint32_t getRecordOffset(msf::StreamReader Reader) override {
|
||||||
ArrayRef<uint8_t> Data;
|
ArrayRef<uint8_t> Data;
|
||||||
if (auto EC = Reader.readLongestContiguousChunk(Data)) {
|
if (auto EC = Reader.readLongestContiguousChunk(Data)) {
|
||||||
llvm::consumeError(std::move(EC));
|
llvm::consumeError(std::move(EC));
|
||||||
@ -840,13 +841,13 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
|
|||||||
}
|
}
|
||||||
case ModuleSubstreamKind::FrameData: {
|
case ModuleSubstreamKind::FrameData: {
|
||||||
// First four bytes is a relocation against the function.
|
// First four bytes is a relocation against the function.
|
||||||
BinaryByteStream S(Contents, llvm::support::little);
|
msf::ByteStream S(Contents);
|
||||||
BinaryStreamReader SR(S);
|
msf::StreamReader SR(S);
|
||||||
StringRef CodePtr;
|
const uint32_t *CodePtr;
|
||||||
error(SR.readFixedString(CodePtr, 4));
|
error(SR.readObject(CodePtr));
|
||||||
StringRef LinkageName;
|
StringRef LinkageName;
|
||||||
error(resolveSymbolName(Obj->getCOFFSection(Section), SectionContents,
|
error(resolveSymbolName(Obj->getCOFFSection(Section), SectionContents,
|
||||||
CodePtr.data(), LinkageName));
|
CodePtr, LinkageName));
|
||||||
W.printString("LinkageName", LinkageName);
|
W.printString("LinkageName", LinkageName);
|
||||||
|
|
||||||
// To find the active frame description, search this array for the
|
// To find the active frame description, search this array for the
|
||||||
@ -965,9 +966,9 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
|
|||||||
|
|
||||||
CVSymbolDumper CVSD(W, TypeDB, std::move(CODD),
|
CVSymbolDumper CVSD(W, TypeDB, std::move(CODD),
|
||||||
opts::CodeViewSubsectionBytes);
|
opts::CodeViewSubsectionBytes);
|
||||||
BinaryByteStream Stream(BinaryData, llvm::support::little);
|
ByteStream Stream(BinaryData);
|
||||||
CVSymbolArray Symbols;
|
CVSymbolArray Symbols;
|
||||||
BinaryStreamReader Reader(Stream);
|
StreamReader Reader(Stream);
|
||||||
if (auto EC = Reader.readArray(Symbols, Reader.getLength())) {
|
if (auto EC = Reader.readArray(Symbols, Reader.getLength())) {
|
||||||
consumeError(std::move(EC));
|
consumeError(std::move(EC));
|
||||||
W.flush();
|
W.flush();
|
||||||
@ -982,8 +983,8 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {
|
void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {
|
||||||
BinaryByteStream S(Subsection, llvm::support::little);
|
msf::ByteStream S(Subsection);
|
||||||
BinaryStreamReader SR(S);
|
msf::StreamReader SR(S);
|
||||||
while (!SR.empty()) {
|
while (!SR.empty()) {
|
||||||
DictScope S(W, "FileChecksum");
|
DictScope S(W, "FileChecksum");
|
||||||
const FileChecksum *FC;
|
const FileChecksum *FC;
|
||||||
@ -1011,10 +1012,10 @@ void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
|
void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
|
||||||
BinaryByteStream S(Subsection, llvm::support::little);
|
msf::ByteStream S(Subsection);
|
||||||
BinaryStreamReader SR(S);
|
msf::StreamReader SR(S);
|
||||||
uint32_t Signature;
|
uint32_t Signature;
|
||||||
error(SR.readInteger(Signature));
|
error(SR.readInteger(Signature, llvm::support::little));
|
||||||
bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles);
|
bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles);
|
||||||
|
|
||||||
while (!SR.empty()) {
|
while (!SR.empty()) {
|
||||||
@ -1027,12 +1028,12 @@ void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
|
|||||||
|
|
||||||
if (HasExtraFiles) {
|
if (HasExtraFiles) {
|
||||||
uint32_t ExtraFileCount;
|
uint32_t ExtraFileCount;
|
||||||
error(SR.readInteger(ExtraFileCount));
|
error(SR.readInteger(ExtraFileCount, llvm::support::little));
|
||||||
W.printNumber("ExtraFileCount", ExtraFileCount);
|
W.printNumber("ExtraFileCount", ExtraFileCount);
|
||||||
ListScope ExtraFiles(W, "ExtraFiles");
|
ListScope ExtraFiles(W, "ExtraFiles");
|
||||||
for (unsigned I = 0; I < ExtraFileCount; ++I) {
|
for (unsigned I = 0; I < ExtraFileCount; ++I) {
|
||||||
uint32_t FileID;
|
uint32_t FileID;
|
||||||
error(SR.readInteger(FileID));
|
error(SR.readInteger(FileID, llvm::support::little));
|
||||||
printFileNameForOffset("FileID", FileID);
|
printFileNameForOffset("FileID", FileID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1077,9 +1078,9 @@ void COFFDumper::mergeCodeViewTypes(TypeTableBuilder &CVTypes) {
|
|||||||
error(object_error::parse_failed);
|
error(object_error::parse_failed);
|
||||||
ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(Data.data()),
|
ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(Data.data()),
|
||||||
Data.size());
|
Data.size());
|
||||||
BinaryByteStream Stream(Bytes, llvm::support::little);
|
ByteStream Stream(Bytes);
|
||||||
CVTypeArray Types;
|
CVTypeArray Types;
|
||||||
BinaryStreamReader Reader(Stream);
|
StreamReader Reader(Stream);
|
||||||
if (auto EC = Reader.readArray(Types, Reader.getLength())) {
|
if (auto EC = Reader.readArray(Types, Reader.getLength())) {
|
||||||
consumeError(std::move(EC));
|
consumeError(std::move(EC));
|
||||||
W.flush();
|
W.flush();
|
||||||
|
@ -1,758 +0,0 @@
|
|||||||
//===- llvm/unittest/Support/BinaryStreamTest.cpp -------------------------===//
|
|
||||||
//
|
|
||||||
// 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/BinaryByteStream.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryItemStream.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
|
|
||||||
#include "llvm/DebugInfo/MSF/BinaryStreamWriter.h"
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
using namespace llvm;
|
|
||||||
using namespace llvm::support;
|
|
||||||
|
|
||||||
#define EXPECT_NO_ERROR(Err) \
|
|
||||||
{ \
|
|
||||||
auto E = Err; \
|
|
||||||
EXPECT_FALSE(static_cast<bool>(E)); \
|
|
||||||
if (E) \
|
|
||||||
consumeError(std::move(E)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ASSERT_NO_ERROR(Err) \
|
|
||||||
{ \
|
|
||||||
auto E = Err; \
|
|
||||||
ASSERT_FALSE(static_cast<bool>(E)); \
|
|
||||||
if (E) \
|
|
||||||
consumeError(std::move(E)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define EXPECT_ERROR(Err) \
|
|
||||||
{ \
|
|
||||||
auto E = Err; \
|
|
||||||
EXPECT_TRUE(static_cast<bool>(E)); \
|
|
||||||
if (E) \
|
|
||||||
consumeError(std::move(E)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class DiscontiguousStream : public WritableBinaryStream {
|
|
||||||
public:
|
|
||||||
explicit DiscontiguousStream(uint32_t Size = 0) : PartitionIndex(Size / 2) {
|
|
||||||
Data.resize(Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
endianness getEndian() const override { return little; }
|
|
||||||
|
|
||||||
Error readBytes(uint32_t Offset, uint32_t Size,
|
|
||||||
ArrayRef<uint8_t> &Buffer) override {
|
|
||||||
if (Offset + Size > Data.size())
|
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
|
||||||
uint32_t S = startIndex(Offset);
|
|
||||||
auto Ref = makeArrayRef(Data).drop_front(S);
|
|
||||||
if (Ref.size() >= Size) {
|
|
||||||
Buffer = Ref.take_front(Size);
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t BytesLeft = Size - Ref.size();
|
|
||||||
uint8_t *Ptr = Allocator.Allocate<uint8_t>(Size);
|
|
||||||
::memcpy(Ptr, Ref.data(), Ref.size());
|
|
||||||
::memcpy(Ptr + Ref.size(), Data.data(), BytesLeft);
|
|
||||||
Buffer = makeArrayRef<uint8_t>(Ptr, Size);
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error readLongestContiguousChunk(uint32_t Offset,
|
|
||||||
ArrayRef<uint8_t> &Buffer) override {
|
|
||||||
if (Offset >= Data.size())
|
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
|
||||||
uint32_t S = startIndex(Offset);
|
|
||||||
Buffer = makeArrayRef(Data).drop_front(S);
|
|
||||||
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 errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
|
||||||
if (SrcData.empty())
|
|
||||||
return Error::success();
|
|
||||||
|
|
||||||
uint32_t S = startIndex(Offset);
|
|
||||||
MutableArrayRef<uint8_t> Ref(Data);
|
|
||||||
Ref = Ref.drop_front(S);
|
|
||||||
if (Ref.size() >= SrcData.size()) {
|
|
||||||
::memcpy(Ref.data(), SrcData.data(), SrcData.size());
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t BytesLeft = SrcData.size() - Ref.size();
|
|
||||||
::memcpy(Ref.data(), SrcData.data(), Ref.size());
|
|
||||||
::memcpy(&Data[0], SrcData.data() + Ref.size(), BytesLeft);
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
Error commit() override { return Error::success(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t startIndex(uint32_t Offset) const {
|
|
||||||
return (Offset + PartitionIndex) % Data.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t endIndex(uint32_t Offset, uint32_t Size) const {
|
|
||||||
return (startIndex(Offset) + Size - 1) % Data.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t PartitionIndex = 0;
|
|
||||||
// Buffer is organized like this:
|
|
||||||
// -------------------------------------------------
|
|
||||||
// | N/2 | N/2+1 | ... | N-1 | 0 | 1 | ... | N-2-1 |
|
|
||||||
// -------------------------------------------------
|
|
||||||
// So reads from the beginning actually come from the middle.
|
|
||||||
std::vector<uint8_t> Data;
|
|
||||||
BumpPtrAllocator Allocator;
|
|
||||||
};
|
|
||||||
|
|
||||||
class BinaryStreamTest : public testing::Test {
|
|
||||||
public:
|
|
||||||
BinaryStreamTest() {}
|
|
||||||
|
|
||||||
void SetUp() override {
|
|
||||||
InputData.clear();
|
|
||||||
OutputData.clear();
|
|
||||||
InputByteStream = BinaryByteStream();
|
|
||||||
InputBrokenStream = DiscontiguousStream();
|
|
||||||
OutputByteStream = MutableBinaryByteStream();
|
|
||||||
OutputBrokenStream = DiscontiguousStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void initialize(ArrayRef<uint8_t> Input, uint32_t OutputSize) {
|
|
||||||
InputData = Input;
|
|
||||||
|
|
||||||
InputByteStream = BinaryByteStream(InputData, little);
|
|
||||||
InputBrokenStream = DiscontiguousStream(InputData.size());
|
|
||||||
consumeError(InputBrokenStream.writeBytes(0, Input));
|
|
||||||
|
|
||||||
OutputData.resize(OutputSize);
|
|
||||||
OutputByteStream = MutableBinaryByteStream(OutputData, little);
|
|
||||||
OutputBrokenStream = DiscontiguousStream(OutputSize);
|
|
||||||
|
|
||||||
InputStreams.push_back(&InputByteStream);
|
|
||||||
InputStreams.push_back(&InputBrokenStream);
|
|
||||||
OutputStreams.push_back(&OutputByteStream);
|
|
||||||
OutputStreams.push_back(&OutputBrokenStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
void initialize(uint32_t OutputSize) {
|
|
||||||
OutputData.resize(OutputSize);
|
|
||||||
OutputByteStream = MutableBinaryByteStream(OutputData, little);
|
|
||||||
OutputBrokenStream = DiscontiguousStream(OutputSize);
|
|
||||||
OutputStreams.push_back(&OutputByteStream);
|
|
||||||
OutputStreams.push_back(&OutputBrokenStream);
|
|
||||||
|
|
||||||
InputByteStream = BinaryByteStream(OutputData, little);
|
|
||||||
InputBrokenStream = DiscontiguousStream(OutputData.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint8_t> InputData;
|
|
||||||
std::vector<uint8_t> OutputData;
|
|
||||||
|
|
||||||
BinaryByteStream InputByteStream;
|
|
||||||
DiscontiguousStream InputBrokenStream;
|
|
||||||
|
|
||||||
MutableBinaryByteStream OutputByteStream;
|
|
||||||
DiscontiguousStream OutputBrokenStream;
|
|
||||||
|
|
||||||
std::vector<BinaryStream *> InputStreams;
|
|
||||||
std::vector<WritableBinaryStream *> OutputStreams;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Tests that a we can read from a BinaryByteStream without a StreamReader.
|
|
||||||
TEST_F(BinaryStreamTest, BinaryByteStreamProperties) {
|
|
||||||
std::vector<uint8_t> InputData = {1, 2, 3, 4, 5};
|
|
||||||
initialize(InputData, InputData.size());
|
|
||||||
|
|
||||||
for (auto Stream : InputStreams) {
|
|
||||||
ArrayRef<uint8_t> Buffer;
|
|
||||||
|
|
||||||
// 1. If the read fits it should work.
|
|
||||||
ASSERT_EQ(InputData.size(), Stream->getLength());
|
|
||||||
ASSERT_NO_ERROR(Stream->readBytes(2, 1, Buffer));
|
|
||||||
EXPECT_EQ(makeArrayRef(InputData).slice(2, 1), Buffer);
|
|
||||||
ASSERT_NO_ERROR(Stream->readBytes(0, 4, Buffer));
|
|
||||||
EXPECT_EQ(makeArrayRef(InputData).slice(0, 4), Buffer);
|
|
||||||
|
|
||||||
// 2. Reading past the bounds of the input should fail.
|
|
||||||
EXPECT_ERROR(Stream->readBytes(4, 2, Buffer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that we can write to a BinaryStream without a StreamWriter.
|
|
||||||
TEST_F(BinaryStreamTest, MutableBinaryByteStreamProperties) {
|
|
||||||
std::vector<uint8_t> InputData = {'T', 'e', 's', 't', '\0'};
|
|
||||||
initialize(InputData, InputData.size());
|
|
||||||
ASSERT_EQ(2U, InputStreams.size());
|
|
||||||
ASSERT_EQ(2U, OutputStreams.size());
|
|
||||||
|
|
||||||
// For every combination of input stream and output stream.
|
|
||||||
for (auto IS : InputStreams) {
|
|
||||||
MutableArrayRef<uint8_t> Buffer;
|
|
||||||
ASSERT_EQ(InputData.size(), IS->getLength());
|
|
||||||
|
|
||||||
for (auto OS : OutputStreams) {
|
|
||||||
|
|
||||||
// 1. Try two reads that are supposed to work. One from offset 0, and one
|
|
||||||
// from the middle.
|
|
||||||
uint32_t Offsets[] = {0, 3};
|
|
||||||
for (auto Offset : Offsets) {
|
|
||||||
uint32_t ExpectedSize = IS->getLength() - Offset;
|
|
||||||
|
|
||||||
// Read everything from Offset until the end of the input data.
|
|
||||||
ArrayRef<uint8_t> Data;
|
|
||||||
ASSERT_NO_ERROR(IS->readBytes(Offset, ExpectedSize, Data));
|
|
||||||
ASSERT_EQ(ExpectedSize, Data.size());
|
|
||||||
|
|
||||||
// Then write it to the destination.
|
|
||||||
ASSERT_NO_ERROR(OS->writeBytes(0, Data));
|
|
||||||
|
|
||||||
// Then we read back what we wrote, it should match the corresponding
|
|
||||||
// slice
|
|
||||||
// of the original input data.
|
|
||||||
ArrayRef<uint8_t> Data2;
|
|
||||||
ASSERT_NO_ERROR(OS->readBytes(Offset, ExpectedSize, Data2));
|
|
||||||
EXPECT_EQ(makeArrayRef(InputData).drop_front(Offset), Data2);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint8_t> BigData = {0, 1, 2, 3, 4};
|
|
||||||
// 2. If the write is too big, it should fail.
|
|
||||||
EXPECT_ERROR(OS->writeBytes(3, BigData));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that FixedStreamArray works correctly.
|
|
||||||
TEST_F(BinaryStreamTest, FixedStreamArray) {
|
|
||||||
std::vector<uint32_t> Ints = {90823, 12908, 109823, 209823};
|
|
||||||
ArrayRef<uint8_t> IntBytes(reinterpret_cast<uint8_t *>(Ints.data()),
|
|
||||||
Ints.size() * sizeof(uint32_t));
|
|
||||||
|
|
||||||
initialize(IntBytes, 0);
|
|
||||||
ASSERT_EQ(2U, InputStreams.size());
|
|
||||||
|
|
||||||
for (auto IS : InputStreams) {
|
|
||||||
MutableArrayRef<uint8_t> Buffer;
|
|
||||||
ASSERT_EQ(InputData.size(), IS->getLength());
|
|
||||||
|
|
||||||
FixedStreamArray<uint32_t> Array(*IS);
|
|
||||||
auto Iter = Array.begin();
|
|
||||||
ASSERT_EQ(Ints[0], *Iter++);
|
|
||||||
ASSERT_EQ(Ints[1], *Iter++);
|
|
||||||
ASSERT_EQ(Ints[2], *Iter++);
|
|
||||||
ASSERT_EQ(Ints[3], *Iter++);
|
|
||||||
ASSERT_EQ(Array.end(), Iter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that VarStreamArray works correctly.
|
|
||||||
TEST_F(BinaryStreamTest, VarStreamArray) {
|
|
||||||
StringLiteral Strings("1. Test2. Longer Test3. Really Long Test4. Super "
|
|
||||||
"Extra Longest Test Of All");
|
|
||||||
ArrayRef<uint8_t> StringBytes(
|
|
||||||
reinterpret_cast<const uint8_t *>(Strings.data()), Strings.size());
|
|
||||||
initialize(StringBytes, 0);
|
|
||||||
|
|
||||||
struct StringExtractor {
|
|
||||||
public:
|
|
||||||
Error operator()(BinaryStreamRef Stream, uint32_t &Len, StringRef &Item) {
|
|
||||||
if (Index == 0)
|
|
||||||
Len = strlen("1. Test");
|
|
||||||
else if (Index == 1)
|
|
||||||
Len = strlen("2. Longer Test");
|
|
||||||
else if (Index == 2)
|
|
||||||
Len = strlen("3. Really Long Test");
|
|
||||||
else
|
|
||||||
Len = strlen("4. Super Extra Longest Test Of All");
|
|
||||||
ArrayRef<uint8_t> Bytes;
|
|
||||||
if (auto EC = Stream.readBytes(0, Len, Bytes))
|
|
||||||
return EC;
|
|
||||||
Item =
|
|
||||||
StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
|
|
||||||
++Index;
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t Index = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (auto IS : InputStreams) {
|
|
||||||
VarStreamArray<StringRef, StringExtractor> Array(*IS);
|
|
||||||
auto Iter = Array.begin();
|
|
||||||
ASSERT_EQ("1. Test", *Iter++);
|
|
||||||
ASSERT_EQ("2. Longer Test", *Iter++);
|
|
||||||
ASSERT_EQ("3. Really Long Test", *Iter++);
|
|
||||||
ASSERT_EQ("4. Super Extra Longest Test Of All", *Iter++);
|
|
||||||
ASSERT_EQ(Array.end(), Iter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BinaryStreamTest, StreamReaderBounds) {
|
|
||||||
std::vector<uint8_t> Bytes;
|
|
||||||
|
|
||||||
initialize(Bytes, 0);
|
|
||||||
for (auto IS : InputStreams) {
|
|
||||||
StringRef S;
|
|
||||||
BinaryStreamReader Reader(*IS);
|
|
||||||
EXPECT_EQ(0U, Reader.bytesRemaining());
|
|
||||||
EXPECT_ERROR(Reader.readFixedString(S, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
Bytes.resize(5);
|
|
||||||
initialize(Bytes, 0);
|
|
||||||
for (auto IS : InputStreams) {
|
|
||||||
StringRef S;
|
|
||||||
BinaryStreamReader Reader(*IS);
|
|
||||||
EXPECT_EQ(Bytes.size(), Reader.bytesRemaining());
|
|
||||||
EXPECT_NO_ERROR(Reader.readFixedString(S, 5));
|
|
||||||
EXPECT_ERROR(Reader.readFixedString(S, 6));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BinaryStreamTest, DISABLED_StreamReaderIntegers) {
|
|
||||||
support::ulittle64_t Little{908234};
|
|
||||||
support::ubig32_t Big{28907823};
|
|
||||||
short NS = 2897;
|
|
||||||
int NI = -89723;
|
|
||||||
unsigned long NUL = 902309023UL;
|
|
||||||
constexpr uint32_t Size =
|
|
||||||
sizeof(Little) + sizeof(Big) + sizeof(NS) + sizeof(NI) + sizeof(NUL);
|
|
||||||
std::vector<uint8_t> Bytes(Size);
|
|
||||||
uint8_t *Ptr = &Bytes[0];
|
|
||||||
memcpy(Ptr, &Little, sizeof(Little));
|
|
||||||
Ptr += sizeof(Little);
|
|
||||||
memcpy(Ptr, &Big, sizeof(Big));
|
|
||||||
Ptr += sizeof(Big);
|
|
||||||
memcpy(Ptr, &NS, sizeof(NS));
|
|
||||||
Ptr += sizeof(NS);
|
|
||||||
memcpy(Ptr, &NI, sizeof(NI));
|
|
||||||
Ptr += sizeof(NI);
|
|
||||||
memcpy(Ptr, &NUL, sizeof(NUL));
|
|
||||||
Ptr += sizeof(NUL);
|
|
||||||
|
|
||||||
initialize(Bytes, 0);
|
|
||||||
for (auto IS : InputStreams) {
|
|
||||||
const support::ulittle64_t *Little2;
|
|
||||||
const support::ubig32_t *Big2;
|
|
||||||
short NS2;
|
|
||||||
int NI2;
|
|
||||||
unsigned long NUL2;
|
|
||||||
|
|
||||||
// 1. Reading fields individually.
|
|
||||||
BinaryStreamReader Reader(*IS);
|
|
||||||
ASSERT_NO_ERROR(Reader.readObject(Little2));
|
|
||||||
ASSERT_NO_ERROR(Reader.readObject(Big2));
|
|
||||||
ASSERT_NO_ERROR(Reader.readInteger(NS2));
|
|
||||||
ASSERT_NO_ERROR(Reader.readInteger(NI2));
|
|
||||||
ASSERT_NO_ERROR(Reader.readInteger(NUL2));
|
|
||||||
ASSERT_EQ(0U, Reader.bytesRemaining());
|
|
||||||
|
|
||||||
EXPECT_EQ(Little, *Little2);
|
|
||||||
EXPECT_EQ(Big, *Big2);
|
|
||||||
EXPECT_EQ(NS, NS2);
|
|
||||||
EXPECT_EQ(NI, NI2);
|
|
||||||
EXPECT_EQ(NUL, NUL2);
|
|
||||||
|
|
||||||
// 2. Reading with explicit endianness.
|
|
||||||
Reader.setOffset(0);
|
|
||||||
const ulittle64_t *Little3;
|
|
||||||
const ubig32_t *Big3;
|
|
||||||
ASSERT_NO_ERROR(Reader.readObject(Little3));
|
|
||||||
ASSERT_NO_ERROR(Reader.readObject(Big3));
|
|
||||||
EXPECT_EQ(Little, *Little3);
|
|
||||||
EXPECT_EQ(Big, *Big3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BinaryStreamTest, StreamReaderIntegerArray) {
|
|
||||||
// 1. Arrays of integers
|
|
||||||
std::vector<int> Ints = {1, 2, 3, 4, 5};
|
|
||||||
ArrayRef<uint8_t> IntBytes(reinterpret_cast<uint8_t *>(&Ints[0]),
|
|
||||||
Ints.size() * sizeof(int));
|
|
||||||
initialize(IntBytes, 0);
|
|
||||||
for (auto IS : InputStreams) {
|
|
||||||
BinaryStreamReader Reader(*IS);
|
|
||||||
ArrayRef<int> IntsRef;
|
|
||||||
ASSERT_NO_ERROR(Reader.readArray(IntsRef, Ints.size()));
|
|
||||||
ASSERT_EQ(0U, Reader.bytesRemaining());
|
|
||||||
EXPECT_EQ(makeArrayRef(Ints), IntsRef);
|
|
||||||
|
|
||||||
Reader.setOffset(0);
|
|
||||||
FixedStreamArray<int> FixedIntsRef;
|
|
||||||
ASSERT_NO_ERROR(Reader.readArray(FixedIntsRef, Ints.size()));
|
|
||||||
ASSERT_EQ(0U, Reader.bytesRemaining());
|
|
||||||
ASSERT_EQ(Ints, std::vector<int>(FixedIntsRef.begin(), FixedIntsRef.end()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BinaryStreamTest, DISABLED_StreamReaderEnum) {
|
|
||||||
enum class MyEnum : int64_t { Foo = -10, Bar = 0, Baz = 10 };
|
|
||||||
|
|
||||||
std::vector<MyEnum> Enums = {MyEnum::Bar, MyEnum::Baz, MyEnum::Foo};
|
|
||||||
|
|
||||||
ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(&Enums[0]),
|
|
||||||
sizeof(MyEnum) * Enums.size());
|
|
||||||
|
|
||||||
initialize(Bytes, 0);
|
|
||||||
for (auto IS : InputStreams) {
|
|
||||||
BinaryStreamReader Reader(*IS);
|
|
||||||
|
|
||||||
MyEnum V1;
|
|
||||||
MyEnum V2;
|
|
||||||
MyEnum V3;
|
|
||||||
ArrayRef<MyEnum> Array;
|
|
||||||
FixedStreamArray<MyEnum> FSA;
|
|
||||||
|
|
||||||
ASSERT_NO_ERROR(Reader.readEnum(V1));
|
|
||||||
ASSERT_NO_ERROR(Reader.readEnum(V2));
|
|
||||||
ASSERT_NO_ERROR(Reader.readEnum(V3));
|
|
||||||
ASSERT_EQ(0U, Reader.bytesRemaining());
|
|
||||||
|
|
||||||
EXPECT_EQ(MyEnum::Bar, V1);
|
|
||||||
EXPECT_EQ(MyEnum::Baz, V2);
|
|
||||||
EXPECT_EQ(MyEnum::Foo, V3);
|
|
||||||
|
|
||||||
Reader.setOffset(0);
|
|
||||||
ASSERT_NO_ERROR(Reader.readArray(Array, 3));
|
|
||||||
EXPECT_EQ(makeArrayRef(Enums), Array);
|
|
||||||
|
|
||||||
Reader.setOffset(0);
|
|
||||||
ASSERT_NO_ERROR(Reader.readArray(FSA, 3));
|
|
||||||
EXPECT_EQ(Enums, std::vector<MyEnum>(FSA.begin(), FSA.end()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BinaryStreamTest, StreamReaderObject) {
|
|
||||||
struct Foo {
|
|
||||||
int X;
|
|
||||||
double Y;
|
|
||||||
char Z;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<Foo> Foos;
|
|
||||||
Foos.push_back({-42, 42.42, 42});
|
|
||||||
Foos.push_back({100, 3.1415, static_cast<char>(-89)});
|
|
||||||
|
|
||||||
const uint8_t *Bytes = reinterpret_cast<const uint8_t *>(&Foos[0]);
|
|
||||||
|
|
||||||
initialize(makeArrayRef(Bytes, 2 * sizeof(Foo)), 0);
|
|
||||||
|
|
||||||
for (auto IS : InputStreams) {
|
|
||||||
// 1. Reading object pointers.
|
|
||||||
BinaryStreamReader Reader(*IS);
|
|
||||||
const Foo *FPtrOut = nullptr;
|
|
||||||
const Foo *GPtrOut = nullptr;
|
|
||||||
ASSERT_NO_ERROR(Reader.readObject(FPtrOut));
|
|
||||||
ASSERT_NO_ERROR(Reader.readObject(GPtrOut));
|
|
||||||
EXPECT_EQ(0U, Reader.bytesRemaining());
|
|
||||||
EXPECT_EQ(0, ::memcmp(&Foos[0], FPtrOut, sizeof(Foo)));
|
|
||||||
EXPECT_EQ(0, ::memcmp(&Foos[1], GPtrOut, sizeof(Foo)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BinaryStreamTest, StreamReaderStrings) {
|
|
||||||
std::vector<uint8_t> Bytes = {'O', 'n', 'e', '\0', 'T', 'w', 'o',
|
|
||||||
'\0', 'T', 'h', 'r', 'e', 'e', '\0',
|
|
||||||
'F', 'o', 'u', 'r', '\0'};
|
|
||||||
initialize(Bytes, 0);
|
|
||||||
|
|
||||||
for (auto IS : InputStreams) {
|
|
||||||
BinaryStreamReader Reader(*IS);
|
|
||||||
|
|
||||||
StringRef S1;
|
|
||||||
StringRef S2;
|
|
||||||
StringRef S3;
|
|
||||||
StringRef S4;
|
|
||||||
ASSERT_NO_ERROR(Reader.readCString(S1));
|
|
||||||
ASSERT_NO_ERROR(Reader.readCString(S2));
|
|
||||||
ASSERT_NO_ERROR(Reader.readCString(S3));
|
|
||||||
ASSERT_NO_ERROR(Reader.readCString(S4));
|
|
||||||
ASSERT_EQ(0U, Reader.bytesRemaining());
|
|
||||||
|
|
||||||
EXPECT_EQ("One", S1);
|
|
||||||
EXPECT_EQ("Two", S2);
|
|
||||||
EXPECT_EQ("Three", S3);
|
|
||||||
EXPECT_EQ("Four", S4);
|
|
||||||
|
|
||||||
S1 = S2 = S3 = S4 = "";
|
|
||||||
Reader.setOffset(0);
|
|
||||||
ASSERT_NO_ERROR(Reader.readFixedString(S1, 3));
|
|
||||||
ASSERT_NO_ERROR(Reader.skip(1));
|
|
||||||
ASSERT_NO_ERROR(Reader.readFixedString(S2, 3));
|
|
||||||
ASSERT_NO_ERROR(Reader.skip(1));
|
|
||||||
ASSERT_NO_ERROR(Reader.readFixedString(S3, 5));
|
|
||||||
ASSERT_NO_ERROR(Reader.skip(1));
|
|
||||||
ASSERT_NO_ERROR(Reader.readFixedString(S4, 4));
|
|
||||||
ASSERT_NO_ERROR(Reader.skip(1));
|
|
||||||
ASSERT_EQ(0U, Reader.bytesRemaining());
|
|
||||||
|
|
||||||
EXPECT_EQ("One", S1);
|
|
||||||
EXPECT_EQ("Two", S2);
|
|
||||||
EXPECT_EQ("Three", S3);
|
|
||||||
EXPECT_EQ("Four", S4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BinaryStreamTest, StreamWriterBounds) {
|
|
||||||
initialize(5);
|
|
||||||
|
|
||||||
for (auto OS : OutputStreams) {
|
|
||||||
BinaryStreamWriter Writer(*OS);
|
|
||||||
|
|
||||||
// 1. Can write a string that exactly fills the buffer.
|
|
||||||
EXPECT_EQ(5U, Writer.bytesRemaining());
|
|
||||||
EXPECT_NO_ERROR(Writer.writeFixedString("abcde"));
|
|
||||||
EXPECT_EQ(0U, Writer.bytesRemaining());
|
|
||||||
|
|
||||||
// 2. Can write an empty string even when you're full
|
|
||||||
EXPECT_NO_ERROR(Writer.writeFixedString(""));
|
|
||||||
EXPECT_ERROR(Writer.writeFixedString("a"));
|
|
||||||
|
|
||||||
// 3. Can't write a string that is one character too long.
|
|
||||||
Writer.setOffset(0);
|
|
||||||
EXPECT_ERROR(Writer.writeFixedString("abcdef"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BinaryStreamTest, StreamWriterIntegers) {
|
|
||||||
support::ulittle64_t Little{908234};
|
|
||||||
support::ubig32_t Big{28907823};
|
|
||||||
short NS = 2897;
|
|
||||||
int NI = -89723;
|
|
||||||
unsigned long NUL = 902309023UL;
|
|
||||||
constexpr uint32_t Size =
|
|
||||||
sizeof(Little) + sizeof(Big) + sizeof(NS) + sizeof(NI) + sizeof(NUL);
|
|
||||||
|
|
||||||
initialize(Size);
|
|
||||||
|
|
||||||
for (auto OS : OutputStreams) {
|
|
||||||
BinaryStreamWriter Writer(*OS);
|
|
||||||
|
|
||||||
// 1. Writing fields individually.
|
|
||||||
ASSERT_NO_ERROR(Writer.writeObject(Little));
|
|
||||||
ASSERT_NO_ERROR(Writer.writeObject(Big));
|
|
||||||
ASSERT_NO_ERROR(Writer.writeInteger(NS));
|
|
||||||
ASSERT_NO_ERROR(Writer.writeInteger(NI));
|
|
||||||
ASSERT_NO_ERROR(Writer.writeInteger(NUL));
|
|
||||||
ASSERT_EQ(0U, Writer.bytesRemaining());
|
|
||||||
|
|
||||||
// Read them back in and confirm they're correct.
|
|
||||||
const ulittle64_t *Little2;
|
|
||||||
const ubig32_t *Big2;
|
|
||||||
short NS2;
|
|
||||||
int NI2;
|
|
||||||
unsigned long NUL2;
|
|
||||||
BinaryStreamReader Reader(*OS);
|
|
||||||
ASSERT_NO_ERROR(Reader.readObject(Little2));
|
|
||||||
ASSERT_NO_ERROR(Reader.readObject(Big2));
|
|
||||||
ASSERT_NO_ERROR(Reader.readInteger(NS2));
|
|
||||||
ASSERT_NO_ERROR(Reader.readInteger(NI2));
|
|
||||||
ASSERT_NO_ERROR(Reader.readInteger(NUL2));
|
|
||||||
EXPECT_EQ(Little, *Little2);
|
|
||||||
EXPECT_EQ(Big, *Big2);
|
|
||||||
EXPECT_EQ(NS, NS2);
|
|
||||||
EXPECT_EQ(NI, NI2);
|
|
||||||
EXPECT_EQ(NUL, NUL2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BinaryStreamTest, StreamWriterIntegerArrays) {
|
|
||||||
// 3. Arrays of integers
|
|
||||||
std::vector<int> SourceInts = {1, 2, 3, 4, 5};
|
|
||||||
ArrayRef<uint8_t> SourceBytes(reinterpret_cast<uint8_t *>(&SourceInts[0]),
|
|
||||||
SourceInts.size() * sizeof(int));
|
|
||||||
|
|
||||||
initialize(SourceBytes, SourceBytes.size());
|
|
||||||
|
|
||||||
for (auto IS : InputStreams) {
|
|
||||||
for (auto OS : OutputStreams) {
|
|
||||||
BinaryStreamReader Reader(*IS);
|
|
||||||
BinaryStreamWriter Writer(*OS);
|
|
||||||
ArrayRef<int> Ints;
|
|
||||||
ArrayRef<int> Ints2;
|
|
||||||
// First read them, then write them, then read them back.
|
|
||||||
ASSERT_NO_ERROR(Reader.readArray(Ints, SourceInts.size()));
|
|
||||||
ASSERT_NO_ERROR(Writer.writeArray(Ints));
|
|
||||||
|
|
||||||
BinaryStreamReader ReaderBacker(*OS);
|
|
||||||
ASSERT_NO_ERROR(ReaderBacker.readArray(Ints2, SourceInts.size()));
|
|
||||||
|
|
||||||
EXPECT_EQ(makeArrayRef(SourceInts), Ints2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BinaryStreamTest, DISABLED_StreamWriterEnum) {
|
|
||||||
enum class MyEnum : int64_t { Foo = -10, Bar = 0, Baz = 10 };
|
|
||||||
|
|
||||||
std::vector<MyEnum> Expected = {MyEnum::Bar, MyEnum::Foo, MyEnum::Baz};
|
|
||||||
|
|
||||||
initialize(Expected.size() * sizeof(MyEnum));
|
|
||||||
|
|
||||||
for (auto OS : OutputStreams) {
|
|
||||||
BinaryStreamWriter Writer(*OS);
|
|
||||||
ArrayRef<MyEnum> Enums;
|
|
||||||
ArrayRef<MyEnum> Enums2;
|
|
||||||
|
|
||||||
// First read them, then write them, then read them back.
|
|
||||||
for (auto ME : Expected)
|
|
||||||
ASSERT_NO_ERROR(Writer.writeEnum(ME));
|
|
||||||
|
|
||||||
ArrayRef<MyEnum> Array;
|
|
||||||
BinaryStreamReader Reader(*OS);
|
|
||||||
ASSERT_NO_ERROR(Reader.readArray(Array, Expected.size()));
|
|
||||||
|
|
||||||
EXPECT_EQ(makeArrayRef(Expected), Array);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BinaryStreamTest, StringWriterStrings) {
|
|
||||||
StringRef Strings[] = {"First", "Second", "Third", "Fourth"};
|
|
||||||
|
|
||||||
size_t Length = 0;
|
|
||||||
for (auto S : Strings)
|
|
||||||
Length += S.size() + 1;
|
|
||||||
initialize(Length);
|
|
||||||
|
|
||||||
for (auto OS : OutputStreams) {
|
|
||||||
BinaryStreamWriter Writer(*OS);
|
|
||||||
for (auto S : Strings)
|
|
||||||
ASSERT_NO_ERROR(Writer.writeCString(S));
|
|
||||||
|
|
||||||
for (auto IS : InputStreams) {
|
|
||||||
std::vector<StringRef> InStrings;
|
|
||||||
BinaryStreamReader Reader(*IS);
|
|
||||||
while (!Reader.empty()) {
|
|
||||||
StringRef S;
|
|
||||||
ASSERT_NO_ERROR(Reader.readCString(S));
|
|
||||||
InStrings.push_back(S);
|
|
||||||
}
|
|
||||||
EXPECT_EQ(makeArrayRef(Strings), makeArrayRef(InStrings));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BinaryStreamTest, StreamReaderIntegersVariadic) {
|
|
||||||
uint8_t A = 201;
|
|
||||||
int8_t A2 = -92;
|
|
||||||
uint16_t B = 20823;
|
|
||||||
int16_t B2 = -20823;
|
|
||||||
uint32_t C = 8978251;
|
|
||||||
int32_t C2 = -8978251;
|
|
||||||
uint64_t D = 90278410232ULL;
|
|
||||||
int64_t D2 = -90278410232LL;
|
|
||||||
|
|
||||||
initialize(2 * (sizeof(A) + sizeof(B) + sizeof(C) + sizeof(D)));
|
|
||||||
|
|
||||||
for (auto OS : OutputStreams) {
|
|
||||||
BinaryStreamWriter Writer(*OS);
|
|
||||||
ASSERT_NO_ERROR(Writer.writeIntegers(A, A2, B, B2, C, C2, D, D2));
|
|
||||||
|
|
||||||
for (auto IS : InputStreams) {
|
|
||||||
BinaryStreamReader Reader(*IS);
|
|
||||||
uint8_t AX;
|
|
||||||
int8_t AX2;
|
|
||||||
uint16_t BX;
|
|
||||||
int16_t BX2;
|
|
||||||
uint32_t CX;
|
|
||||||
int32_t CX2;
|
|
||||||
uint64_t DX;
|
|
||||||
int64_t DX2;
|
|
||||||
|
|
||||||
ASSERT_NO_ERROR(Reader.readIntegers(AX, AX2, BX, BX2, CX, CX2, DX, DX2));
|
|
||||||
EXPECT_EQ(A, AX);
|
|
||||||
EXPECT_EQ(A2, AX2);
|
|
||||||
EXPECT_EQ(B, BX);
|
|
||||||
EXPECT_EQ(B2, BX2);
|
|
||||||
EXPECT_EQ(C, CX);
|
|
||||||
EXPECT_EQ(C2, CX2);
|
|
||||||
EXPECT_EQ(D, DX);
|
|
||||||
EXPECT_EQ(D2, DX2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
struct BinaryItemStreamObject {
|
|
||||||
BinaryItemStreamObject(int X, float Y) : X(X), Y(Y) {}
|
|
||||||
|
|
||||||
int X;
|
|
||||||
float Y;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
template <> struct BinaryItemTraits<std::unique_ptr<BinaryItemStreamObject>> {
|
|
||||||
size_t length(const std::unique_ptr<BinaryItemStreamObject> &Item) {
|
|
||||||
size_t S = sizeof(Item->X);
|
|
||||||
S += sizeof(Item->Y);
|
|
||||||
return S;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayRef<uint8_t> bytes(const std::unique_ptr<BinaryItemStreamObject> &Item) {
|
|
||||||
// In practice we probably would use a more cheaply serializable type,
|
|
||||||
// or at the very least not allocate every single time. This is just
|
|
||||||
// for illustration and testing though.
|
|
||||||
size_t Size = length(Item);
|
|
||||||
uint8_t *Buffer = Alloc.Allocate<uint8_t>(Size);
|
|
||||||
MutableBinaryByteStream Stream(MutableArrayRef<uint8_t>(Buffer, Size),
|
|
||||||
little);
|
|
||||||
BinaryStreamWriter Writer(Stream);
|
|
||||||
consumeError(Writer.writeInteger(Item->X));
|
|
||||||
consumeError(Writer.writeObject(Item->Y));
|
|
||||||
return makeArrayRef(Buffer, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
BumpPtrAllocator Alloc;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
TEST_F(BinaryStreamTest, BinaryItemStream) {
|
|
||||||
// Note that this is a vector of pointers, so individual records do not live
|
|
||||||
// contiguously in memory.
|
|
||||||
std::vector<std::unique_ptr<BinaryItemStreamObject>> Objects;
|
|
||||||
Objects.push_back(llvm::make_unique<BinaryItemStreamObject>(1, 1.0));
|
|
||||||
Objects.push_back(llvm::make_unique<BinaryItemStreamObject>(2, 2.0));
|
|
||||||
Objects.push_back(llvm::make_unique<BinaryItemStreamObject>(3, 3.0));
|
|
||||||
|
|
||||||
BinaryItemStream<std::unique_ptr<BinaryItemStreamObject>> ItemStream(little);
|
|
||||||
ItemStream.setItems(Objects);
|
|
||||||
BinaryStreamReader Reader(ItemStream);
|
|
||||||
|
|
||||||
for (int I = 0; I < 3; ++I) {
|
|
||||||
int X;
|
|
||||||
const float *Y;
|
|
||||||
ASSERT_NO_ERROR(Reader.readInteger(X));
|
|
||||||
ASSERT_NO_ERROR(Reader.readObject(Y));
|
|
||||||
|
|
||||||
EXPECT_EQ(Objects[I]->X, X);
|
|
||||||
EXPECT_DOUBLE_EQ(Objects[I]->Y, *Y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end anonymous namespace
|
|
@ -5,7 +5,6 @@ set(LLVM_LINK_COMPONENTS
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(DebugInfoPDBSources
|
set(DebugInfoPDBSources
|
||||||
BinaryStreamTest.cpp
|
|
||||||
HashTableTest.cpp
|
HashTableTest.cpp
|
||||||
MappedBlockStreamTest.cpp
|
MappedBlockStreamTest.cpp
|
||||||
StringTableBuilderTest.cpp
|
StringTableBuilderTest.cpp
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::pdb;
|
using namespace llvm::pdb;
|
||||||
using namespace llvm::support;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class HashTableInternals : public HashTable {
|
class HashTableInternals : public HashTable {
|
||||||
@ -148,14 +147,14 @@ TEST(HashTableTest, Serialization) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> Buffer(Table.calculateSerializedLength());
|
std::vector<uint8_t> Buffer(Table.calculateSerializedLength());
|
||||||
MutableBinaryByteStream Stream(Buffer, little);
|
msf::MutableByteStream Stream(Buffer);
|
||||||
BinaryStreamWriter Writer(Stream);
|
msf::StreamWriter Writer(Stream);
|
||||||
EXPECT_NO_ERROR(Table.commit(Writer));
|
EXPECT_NO_ERROR(Table.commit(Writer));
|
||||||
// We should have written precisely the number of bytes we calculated earlier.
|
// We should have written precisely the number of bytes we calculated earlier.
|
||||||
EXPECT_EQ(Buffer.size(), Writer.getOffset());
|
EXPECT_EQ(Buffer.size(), Writer.getOffset());
|
||||||
|
|
||||||
HashTableInternals Table2;
|
HashTableInternals Table2;
|
||||||
BinaryStreamReader Reader(Stream);
|
msf::StreamReader Reader(Stream);
|
||||||
EXPECT_NO_ERROR(Table2.load(Reader));
|
EXPECT_NO_ERROR(Table2.load(Reader));
|
||||||
// We should have read precisely the number of bytes we calculated earlier.
|
// We should have read precisely the number of bytes we calculated earlier.
|
||||||
EXPECT_EQ(Buffer.size(), Reader.getOffset());
|
EXPECT_EQ(Buffer.size(), Reader.getOffset());
|
||||||
|
@ -22,14 +22,13 @@
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::msf;
|
using namespace llvm::msf;
|
||||||
using namespace llvm::support;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
static const uint32_t BlocksAry[] = {0, 1, 2, 5, 4, 3, 6, 7, 8, 9};
|
static const uint32_t BlocksAry[] = {0, 1, 2, 5, 4, 3, 6, 7, 8, 9};
|
||||||
static uint8_t DataAry[] = {'A', 'B', 'C', 'F', 'E', 'D', 'G', 'H', 'I', 'J'};
|
static uint8_t DataAry[] = {'A', 'B', 'C', 'F', 'E', 'D', 'G', 'H', 'I', 'J'};
|
||||||
|
|
||||||
class DiscontiguousStream : public WritableBinaryStream {
|
class DiscontiguousStream : public WritableStream {
|
||||||
public:
|
public:
|
||||||
DiscontiguousStream(ArrayRef<uint32_t> Blocks, MutableArrayRef<uint8_t> Data)
|
DiscontiguousStream(ArrayRef<uint32_t> Blocks, MutableArrayRef<uint8_t> Data)
|
||||||
: Blocks(Blocks.begin(), Blocks.end()), Data(Data.begin(), Data.end()) {}
|
: Blocks(Blocks.begin(), Blocks.end()), Data(Data.begin(), Data.end()) {}
|
||||||
@ -37,33 +36,31 @@ public:
|
|||||||
uint32_t block_size() const { return 1; }
|
uint32_t block_size() const { return 1; }
|
||||||
uint32_t block_count() const { return Blocks.size(); }
|
uint32_t block_count() const { return Blocks.size(); }
|
||||||
|
|
||||||
endianness getEndian() const override { return little; }
|
|
||||||
|
|
||||||
Error readBytes(uint32_t Offset, uint32_t Size,
|
Error readBytes(uint32_t Offset, uint32_t Size,
|
||||||
ArrayRef<uint8_t> &Buffer) override {
|
ArrayRef<uint8_t> &Buffer) const override {
|
||||||
if (Offset + Size > Data.size())
|
if (Offset + Size > Data.size())
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
Buffer = Data.slice(Offset, Size);
|
Buffer = Data.slice(Offset, Size);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error readLongestContiguousChunk(uint32_t Offset,
|
Error readLongestContiguousChunk(uint32_t Offset,
|
||||||
ArrayRef<uint8_t> &Buffer) override {
|
ArrayRef<uint8_t> &Buffer) const override {
|
||||||
if (Offset >= Data.size())
|
if (Offset >= Data.size())
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
Buffer = Data.drop_front(Offset);
|
Buffer = Data.drop_front(Offset);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getLength() override { return Data.size(); }
|
uint32_t getLength() const override { return Data.size(); }
|
||||||
|
|
||||||
Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> SrcData) override {
|
Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> SrcData) const override {
|
||||||
if (Offset + SrcData.size() > Data.size())
|
if (Offset + SrcData.size() > Data.size())
|
||||||
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
||||||
::memcpy(&Data[Offset], SrcData.data(), SrcData.size());
|
::memcpy(&Data[Offset], SrcData.data(), SrcData.size());
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
Error commit() override { return Error::success(); }
|
Error commit() const override { return Error::success(); }
|
||||||
|
|
||||||
MSFStreamLayout layout() const {
|
MSFStreamLayout layout() const {
|
||||||
return MSFStreamLayout{static_cast<uint32_t>(Data.size()), Blocks};
|
return MSFStreamLayout{static_cast<uint32_t>(Data.size()), Blocks};
|
||||||
@ -81,8 +78,8 @@ TEST(MappedBlockStreamTest, ReadBeyondEndOfStreamRef) {
|
|||||||
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
||||||
F.layout(), F);
|
F.layout(), F);
|
||||||
|
|
||||||
BinaryStreamReader R(*S);
|
StreamReader R(*S);
|
||||||
BinaryStreamRef SR;
|
ReadableStreamRef SR;
|
||||||
EXPECT_NO_ERROR(R.readStreamRef(SR, 0U));
|
EXPECT_NO_ERROR(R.readStreamRef(SR, 0U));
|
||||||
ArrayRef<uint8_t> Buffer;
|
ArrayRef<uint8_t> Buffer;
|
||||||
EXPECT_ERROR(SR.readBytes(0U, 1U, Buffer));
|
EXPECT_ERROR(SR.readBytes(0U, 1U, Buffer));
|
||||||
@ -97,7 +94,7 @@ TEST(MappedBlockStreamTest, ReadOntoNonEmptyBuffer) {
|
|||||||
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
||||||
F.layout(), F);
|
F.layout(), F);
|
||||||
|
|
||||||
BinaryStreamReader R(*S);
|
StreamReader R(*S);
|
||||||
StringRef Str = "ZYXWVUTSRQPONMLKJIHGFEDCBA";
|
StringRef Str = "ZYXWVUTSRQPONMLKJIHGFEDCBA";
|
||||||
EXPECT_NO_ERROR(R.readFixedString(Str, 1));
|
EXPECT_NO_ERROR(R.readFixedString(Str, 1));
|
||||||
EXPECT_EQ(Str, StringRef("A"));
|
EXPECT_EQ(Str, StringRef("A"));
|
||||||
@ -111,7 +108,7 @@ TEST(MappedBlockStreamTest, ZeroCopyReadContiguousBreak) {
|
|||||||
DiscontiguousStream F(BlocksAry, DataAry);
|
DiscontiguousStream F(BlocksAry, DataAry);
|
||||||
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
||||||
F.layout(), F);
|
F.layout(), F);
|
||||||
BinaryStreamReader R(*S);
|
StreamReader R(*S);
|
||||||
StringRef Str;
|
StringRef Str;
|
||||||
EXPECT_NO_ERROR(R.readFixedString(Str, 2));
|
EXPECT_NO_ERROR(R.readFixedString(Str, 2));
|
||||||
EXPECT_EQ(Str, StringRef("AB"));
|
EXPECT_EQ(Str, StringRef("AB"));
|
||||||
@ -130,7 +127,7 @@ TEST(MappedBlockStreamTest, CopyReadNonContiguousBreak) {
|
|||||||
DiscontiguousStream F(BlocksAry, DataAry);
|
DiscontiguousStream F(BlocksAry, DataAry);
|
||||||
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
||||||
F.layout(), F);
|
F.layout(), F);
|
||||||
BinaryStreamReader R(*S);
|
StreamReader R(*S);
|
||||||
StringRef Str;
|
StringRef Str;
|
||||||
EXPECT_NO_ERROR(R.readFixedString(Str, 10));
|
EXPECT_NO_ERROR(R.readFixedString(Str, 10));
|
||||||
EXPECT_EQ(Str, StringRef("ABCDEFGHIJ"));
|
EXPECT_EQ(Str, StringRef("ABCDEFGHIJ"));
|
||||||
@ -143,7 +140,7 @@ TEST(MappedBlockStreamTest, InvalidReadSizeNoBreak) {
|
|||||||
DiscontiguousStream F(BlocksAry, DataAry);
|
DiscontiguousStream F(BlocksAry, DataAry);
|
||||||
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
||||||
F.layout(), F);
|
F.layout(), F);
|
||||||
BinaryStreamReader R(*S);
|
StreamReader R(*S);
|
||||||
StringRef Str;
|
StringRef Str;
|
||||||
|
|
||||||
R.setOffset(10);
|
R.setOffset(10);
|
||||||
@ -157,7 +154,7 @@ TEST(MappedBlockStreamTest, InvalidReadSizeContiguousBreak) {
|
|||||||
DiscontiguousStream F(BlocksAry, DataAry);
|
DiscontiguousStream F(BlocksAry, DataAry);
|
||||||
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
||||||
F.layout(), F);
|
F.layout(), F);
|
||||||
BinaryStreamReader R(*S);
|
StreamReader R(*S);
|
||||||
StringRef Str;
|
StringRef Str;
|
||||||
|
|
||||||
R.setOffset(6);
|
R.setOffset(6);
|
||||||
@ -171,7 +168,7 @@ TEST(MappedBlockStreamTest, InvalidReadSizeNonContiguousBreak) {
|
|||||||
DiscontiguousStream F(BlocksAry, DataAry);
|
DiscontiguousStream F(BlocksAry, DataAry);
|
||||||
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
||||||
F.layout(), F);
|
F.layout(), F);
|
||||||
BinaryStreamReader R(*S);
|
StreamReader R(*S);
|
||||||
StringRef Str;
|
StringRef Str;
|
||||||
|
|
||||||
EXPECT_ERROR(R.readFixedString(Str, 11));
|
EXPECT_ERROR(R.readFixedString(Str, 11));
|
||||||
@ -184,7 +181,7 @@ TEST(MappedBlockStreamTest, ZeroCopyReadNoBreak) {
|
|||||||
DiscontiguousStream F(BlocksAry, DataAry);
|
DiscontiguousStream F(BlocksAry, DataAry);
|
||||||
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
||||||
F.layout(), F);
|
F.layout(), F);
|
||||||
BinaryStreamReader R(*S);
|
StreamReader R(*S);
|
||||||
StringRef Str;
|
StringRef Str;
|
||||||
EXPECT_NO_ERROR(R.readFixedString(Str, 1));
|
EXPECT_NO_ERROR(R.readFixedString(Str, 1));
|
||||||
EXPECT_EQ(Str, StringRef("A"));
|
EXPECT_EQ(Str, StringRef("A"));
|
||||||
@ -198,7 +195,7 @@ TEST(MappedBlockStreamTest, UnalignedOverlappingRead) {
|
|||||||
DiscontiguousStream F(BlocksAry, DataAry);
|
DiscontiguousStream F(BlocksAry, DataAry);
|
||||||
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
||||||
F.layout(), F);
|
F.layout(), F);
|
||||||
BinaryStreamReader R(*S);
|
StreamReader R(*S);
|
||||||
StringRef Str1;
|
StringRef Str1;
|
||||||
StringRef Str2;
|
StringRef Str2;
|
||||||
EXPECT_NO_ERROR(R.readFixedString(Str1, 7));
|
EXPECT_NO_ERROR(R.readFixedString(Str1, 7));
|
||||||
@ -219,7 +216,7 @@ TEST(MappedBlockStreamTest, UnalignedOverlappingReadFail) {
|
|||||||
DiscontiguousStream F(BlocksAry, DataAry);
|
DiscontiguousStream F(BlocksAry, DataAry);
|
||||||
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
|
||||||
F.layout(), F);
|
F.layout(), F);
|
||||||
BinaryStreamReader R(*S);
|
StreamReader R(*S);
|
||||||
StringRef Str1;
|
StringRef Str1;
|
||||||
StringRef Str2;
|
StringRef Str2;
|
||||||
EXPECT_NO_ERROR(R.readFixedString(Str1, 6));
|
EXPECT_NO_ERROR(R.readFixedString(Str1, 6));
|
||||||
@ -326,10 +323,10 @@ TEST(MappedBlockStreamTest, TestWriteThenRead) {
|
|||||||
uint32_t intArr1[] = {890723408, 29082234};
|
uint32_t intArr1[] = {890723408, 29082234};
|
||||||
ArrayRef<uint32_t> intArray[] = {intArr0, intArr1};
|
ArrayRef<uint32_t> intArray[] = {intArr0, intArr1};
|
||||||
|
|
||||||
BinaryStreamReader Reader(*S);
|
StreamReader Reader(*S);
|
||||||
BinaryStreamWriter Writer(*S);
|
StreamWriter Writer(*S);
|
||||||
EXPECT_NO_ERROR(Writer.writeInteger(u16[0]));
|
EXPECT_NO_ERROR(Writer.writeInteger(u16[0], llvm::support::little));
|
||||||
EXPECT_NO_ERROR(Reader.readInteger(u16[1]));
|
EXPECT_NO_ERROR(Reader.readInteger(u16[1], llvm::support::little));
|
||||||
EXPECT_EQ(u16[0], u16[1]);
|
EXPECT_EQ(u16[0], u16[1]);
|
||||||
EXPECT_EQ(std::vector<uint8_t>({0, 0x7A, 0xEC, 0, 0, 0, 0, 0, 0, 0}),
|
EXPECT_EQ(std::vector<uint8_t>({0, 0x7A, 0xEC, 0, 0, 0, 0, 0, 0, 0}),
|
||||||
DataBytes);
|
DataBytes);
|
||||||
@ -337,8 +334,8 @@ TEST(MappedBlockStreamTest, TestWriteThenRead) {
|
|||||||
Reader.setOffset(0);
|
Reader.setOffset(0);
|
||||||
Writer.setOffset(0);
|
Writer.setOffset(0);
|
||||||
::memset(DataBytes.data(), 0, 10);
|
::memset(DataBytes.data(), 0, 10);
|
||||||
EXPECT_NO_ERROR(Writer.writeInteger(u32[0]));
|
EXPECT_NO_ERROR(Writer.writeInteger(u32[0], llvm::support::little));
|
||||||
EXPECT_NO_ERROR(Reader.readInteger(u32[1]));
|
EXPECT_NO_ERROR(Reader.readInteger(u32[1], llvm::support::little));
|
||||||
EXPECT_EQ(u32[0], u32[1]);
|
EXPECT_EQ(u32[0], u32[1]);
|
||||||
EXPECT_EQ(std::vector<uint8_t>({0x17, 0x5C, 0x50, 0, 0, 0, 0x35, 0, 0, 0}),
|
EXPECT_EQ(std::vector<uint8_t>({0x17, 0x5C, 0x50, 0, 0, 0, 0x35, 0, 0, 0}),
|
||||||
DataBytes);
|
DataBytes);
|
||||||
@ -346,8 +343,8 @@ TEST(MappedBlockStreamTest, TestWriteThenRead) {
|
|||||||
Reader.setOffset(0);
|
Reader.setOffset(0);
|
||||||
Writer.setOffset(0);
|
Writer.setOffset(0);
|
||||||
::memset(DataBytes.data(), 0, 10);
|
::memset(DataBytes.data(), 0, 10);
|
||||||
EXPECT_NO_ERROR(Writer.writeEnum(Enum[0]));
|
EXPECT_NO_ERROR(Writer.writeEnum(Enum[0], llvm::support::little));
|
||||||
EXPECT_NO_ERROR(Reader.readEnum(Enum[1]));
|
EXPECT_NO_ERROR(Reader.readEnum(Enum[1], llvm::support::little));
|
||||||
EXPECT_EQ(Enum[0], Enum[1]);
|
EXPECT_EQ(Enum[0], Enum[1]);
|
||||||
EXPECT_EQ(std::vector<uint8_t>({0x2C, 0x60, 0x4A, 0, 0, 0, 0, 0, 0, 0}),
|
EXPECT_EQ(std::vector<uint8_t>({0x2C, 0x60, 0x4A, 0, 0, 0, 0, 0, 0, 0}),
|
||||||
DataBytes);
|
DataBytes);
|
||||||
@ -355,8 +352,8 @@ TEST(MappedBlockStreamTest, TestWriteThenRead) {
|
|||||||
Reader.setOffset(0);
|
Reader.setOffset(0);
|
||||||
Writer.setOffset(0);
|
Writer.setOffset(0);
|
||||||
::memset(DataBytes.data(), 0, 10);
|
::memset(DataBytes.data(), 0, 10);
|
||||||
EXPECT_NO_ERROR(Writer.writeCString(ZStr[0]));
|
EXPECT_NO_ERROR(Writer.writeZeroString(ZStr[0]));
|
||||||
EXPECT_NO_ERROR(Reader.readCString(ZStr[1]));
|
EXPECT_NO_ERROR(Reader.readZeroString(ZStr[1]));
|
||||||
EXPECT_EQ(ZStr[0], ZStr[1]);
|
EXPECT_EQ(ZStr[0], ZStr[1]);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
std::vector<uint8_t>({'r', 'e', 'Z', ' ', 'S', 't', 'o', 'r', 0, 0}),
|
std::vector<uint8_t>({'r', 'e', 'Z', ' ', 'S', 't', 'o', 'r', 0, 0}),
|
||||||
@ -402,22 +399,22 @@ TEST(MappedBlockStreamTest, TestWriteContiguousStreamRef) {
|
|||||||
F.block_size(), F.block_count(), F.layout(), F);
|
F.block_size(), F.block_count(), F.layout(), F);
|
||||||
|
|
||||||
// First write "Test Str" into the source stream.
|
// First write "Test Str" into the source stream.
|
||||||
MutableBinaryByteStream SourceStream(SrcData, little);
|
MutableByteStream SourceStream(SrcData);
|
||||||
BinaryStreamWriter SourceWriter(SourceStream);
|
StreamWriter SourceWriter(SourceStream);
|
||||||
EXPECT_NO_ERROR(SourceWriter.writeCString("Test Str"));
|
EXPECT_NO_ERROR(SourceWriter.writeZeroString("Test Str"));
|
||||||
EXPECT_EQ(SrcDataBytes, std::vector<uint8_t>(
|
EXPECT_EQ(SrcDataBytes, std::vector<uint8_t>(
|
||||||
{'T', 'e', 's', 't', ' ', 'S', 't', 'r', 0, 0}));
|
{'T', 'e', 's', 't', ' ', 'S', 't', 'r', 0, 0}));
|
||||||
|
|
||||||
// Then write the source stream into the dest stream.
|
// Then write the source stream into the dest stream.
|
||||||
BinaryStreamWriter DestWriter(*DestStream);
|
StreamWriter DestWriter(*DestStream);
|
||||||
EXPECT_NO_ERROR(DestWriter.writeStreamRef(SourceStream));
|
EXPECT_NO_ERROR(DestWriter.writeStreamRef(SourceStream));
|
||||||
EXPECT_EQ(DestDataBytes, std::vector<uint8_t>(
|
EXPECT_EQ(DestDataBytes, std::vector<uint8_t>(
|
||||||
{'s', 'e', 'T', ' ', 'S', 't', 't', 'r', 0, 0}));
|
{'s', 'e', 'T', ' ', 'S', 't', 't', 'r', 0, 0}));
|
||||||
|
|
||||||
// Then read the string back out of the dest stream.
|
// Then read the string back out of the dest stream.
|
||||||
StringRef Result;
|
StringRef Result;
|
||||||
BinaryStreamReader DestReader(*DestStream);
|
StreamReader DestReader(*DestStream);
|
||||||
EXPECT_NO_ERROR(DestReader.readCString(Result));
|
EXPECT_NO_ERROR(DestReader.readZeroString(Result));
|
||||||
EXPECT_EQ(Result, "Test Str");
|
EXPECT_EQ(Result, "Test Str");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,21 +436,21 @@ TEST(MappedBlockStreamTest, TestWriteDiscontiguousStreamRef) {
|
|||||||
SrcF.block_size(), SrcF.block_count(), SrcF.layout(), SrcF);
|
SrcF.block_size(), SrcF.block_count(), SrcF.layout(), SrcF);
|
||||||
|
|
||||||
// First write "Test Str" into the source stream.
|
// First write "Test Str" into the source stream.
|
||||||
BinaryStreamWriter SourceWriter(*Src);
|
StreamWriter SourceWriter(*Src);
|
||||||
EXPECT_NO_ERROR(SourceWriter.writeCString("Test Str"));
|
EXPECT_NO_ERROR(SourceWriter.writeZeroString("Test Str"));
|
||||||
EXPECT_EQ(SrcDataBytes, std::vector<uint8_t>(
|
EXPECT_EQ(SrcDataBytes, std::vector<uint8_t>(
|
||||||
{'e', 'T', 't', 't', ' ', 'S', 's', 'r', 0, 0}));
|
{'e', 'T', 't', 't', ' ', 'S', 's', 'r', 0, 0}));
|
||||||
|
|
||||||
// Then write the source stream into the dest stream.
|
// Then write the source stream into the dest stream.
|
||||||
BinaryStreamWriter DestWriter(*Dest);
|
StreamWriter DestWriter(*Dest);
|
||||||
EXPECT_NO_ERROR(DestWriter.writeStreamRef(*Src));
|
EXPECT_NO_ERROR(DestWriter.writeStreamRef(*Src));
|
||||||
EXPECT_EQ(DestDataBytes, std::vector<uint8_t>(
|
EXPECT_EQ(DestDataBytes, std::vector<uint8_t>(
|
||||||
{'s', 'e', 'T', ' ', 'S', 't', 't', 'r', 0, 0}));
|
{'s', 'e', 'T', ' ', 'S', 't', 't', 'r', 0, 0}));
|
||||||
|
|
||||||
// Then read the string back out of the dest stream.
|
// Then read the string back out of the dest stream.
|
||||||
StringRef Result;
|
StringRef Result;
|
||||||
BinaryStreamReader DestReader(*Dest);
|
StreamReader DestReader(*Dest);
|
||||||
EXPECT_NO_ERROR(DestReader.readCString(Result));
|
EXPECT_NO_ERROR(DestReader.readZeroString(Result));
|
||||||
EXPECT_EQ(Result, "Test Str");
|
EXPECT_EQ(Result, "Test Str");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::pdb;
|
using namespace llvm::pdb;
|
||||||
using namespace llvm::support;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class StringTableBuilderTest : public ::testing::Test {};
|
class StringTableBuilderTest : public ::testing::Test {};
|
||||||
@ -34,13 +33,13 @@ TEST_F(StringTableBuilderTest, Simple) {
|
|||||||
EXPECT_EQ(9U, Builder.insert("baz"));
|
EXPECT_EQ(9U, Builder.insert("baz"));
|
||||||
|
|
||||||
std::vector<uint8_t> Buffer(Builder.finalize());
|
std::vector<uint8_t> Buffer(Builder.finalize());
|
||||||
MutableBinaryByteStream OutStream(Buffer, little);
|
msf::MutableByteStream OutStream(Buffer);
|
||||||
BinaryStreamWriter Writer(OutStream);
|
msf::StreamWriter Writer(OutStream);
|
||||||
EXPECT_NO_ERROR(Builder.commit(Writer));
|
EXPECT_NO_ERROR(Builder.commit(Writer));
|
||||||
|
|
||||||
// Reads the contents back.
|
// Reads the contents back.
|
||||||
BinaryByteStream InStream(Buffer, little);
|
msf::ByteStream InStream(Buffer);
|
||||||
BinaryStreamReader Reader(InStream);
|
msf::StreamReader Reader(InStream);
|
||||||
StringTable Table;
|
StringTable Table;
|
||||||
EXPECT_NO_ERROR(Table.load(Reader));
|
EXPECT_NO_ERROR(Table.load(Reader));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user