[pdb] Finish conversion to zero copy pdb access.

This converts remaining uses of ByteStream, which was still
left in the symbol stream and type stream, to using the new
StreamInterface zero-copy classes.

RecordIterator is finally deleted, so this is the only way left
now.  Additionally, more error checking is added when iterating
the various streams.

With this, the transition to zero copy pdb access is complete.

llvm-svn: 271101
This commit is contained in:
Zachary Turner 2016-05-28 05:21:57 +00:00
parent 9a9a3169e3
commit 0d43c1c339
33 changed files with 228 additions and 350 deletions

View File

@ -24,16 +24,9 @@ class StreamReader;
class ByteStream : public StreamInterface {
public:
ByteStream();
explicit ByteStream(MutableArrayRef<uint8_t> Data);
explicit ByteStream(ArrayRef<uint8_t> Data);
~ByteStream() override;
void reset();
void load(uint32_t Length);
Error load(StreamReader &Reader, uint32_t Length);
Error readBytes(uint32_t Offset,
MutableArrayRef<uint8_t> Buffer) const override;
Error readBytes(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) const override;
@ -43,8 +36,7 @@ public:
StringRef str() const;
private:
MutableArrayRef<uint8_t> Data;
std::unique_ptr<uint8_t[]> Ownership;
ArrayRef<uint8_t> Data;
};
} // end namespace pdb

View File

@ -0,0 +1,47 @@
//===- RecordIterator.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H
#define LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
#include "llvm/DebugInfo/CodeView/StreamInterface.h"
#include "llvm/DebugInfo/CodeView/StreamReader.h"
#include "llvm/Support/Endian.h"
namespace llvm {
namespace codeview {
template <typename Kind> struct CVRecord {
uint32_t Length;
Kind Type;
ArrayRef<uint8_t> Data;
};
template <typename Kind> struct VarStreamArrayExtractor<CVRecord<Kind>> {
Error operator()(const StreamInterface &Stream, uint32_t &Len,
CVRecord<Kind> &Item) const {
const RecordPrefix *Prefix = nullptr;
StreamReader Reader(Stream);
if (auto EC = Reader.readObject(Prefix))
return EC;
Item.Length = Prefix->RecordLen;
Item.Type = static_cast<Kind>(uint16_t(Prefix->RecordKind));
if (auto EC = Reader.readBytes(Item.Data, Item.Length - 2))
return EC;
Len = Prefix->RecordLen + 2;
return Error::success();
}
};
}
}
#endif

View File

@ -10,8 +10,8 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H
#define LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/RecordIterator.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h"
#include "llvm/Support/ErrorOr.h"
@ -72,8 +72,8 @@ public:
}
/// Visits the symbol records in Data. Sets the error flag on parse failures.
void visitSymbolStream(ArrayRef<uint8_t> Data) {
for (const auto &I : makeSymbolRange(Data, &HadError)) {
void visitSymbolStream(const CVSymbolArray &Symbols) {
for (const auto &I : Symbols) {
visitSymbolRecord(I);
if (hadError())
break;

View File

@ -10,11 +10,10 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
#define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/RecordIterator.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeStream.h"
#include "llvm/Support/ErrorOr.h"
namespace llvm {
@ -81,8 +80,8 @@ public:
}
/// Visits the type records in Data. Sets the error flag on parse failures.
void visitTypeStream(ArrayRef<uint8_t> Data) {
for (const auto &I : makeTypeRange(Data, &HadError)) {
void visitTypeStream(const CVTypeArray &Types) {
for (const auto &I : Types) {
visitTypeRecord(I);
if (hadError())
break;

View File

@ -1,143 +0,0 @@
//===- RecordIterator.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H
#define LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
#include "llvm/DebugInfo/CodeView/StreamInterface.h"
#include "llvm/DebugInfo/CodeView/StreamReader.h"
#include "llvm/Support/Endian.h"
namespace llvm {
namespace codeview {
template <typename Kind> struct CVRecord {
uint32_t Length;
Kind Type;
ArrayRef<uint8_t> Data;
};
template <typename Kind> struct VarStreamArrayExtractor<CVRecord<Kind>> {
uint32_t operator()(const StreamInterface &Stream,
CVRecord<Kind> &Item) const {
const RecordPrefix *Prefix = nullptr;
StreamReader Reader(Stream);
if (auto EC = Reader.readObject(Prefix)) {
consumeError(std::move(EC));
return 0;
}
Item.Length = Prefix->RecordLen;
Item.Type = static_cast<Kind>(uint16_t(Prefix->RecordKind));
if (auto EC = Reader.readBytes(Item.Length - 2, Item.Data)) {
consumeError(std::move(EC));
return 0;
}
return Prefix->RecordLen + 2;
}
};
// A const input iterator interface to the CodeView record stream.
template <typename Kind> class RecordIterator {
public:
explicit RecordIterator(const ArrayRef<uint8_t> &RecordBytes, bool *HadError)
: HadError(HadError), Data(RecordBytes), AtEnd(false) {
next(); // Prime the pump
}
RecordIterator() : HadError(nullptr), AtEnd(true) {}
// For iterators to compare equal, they must both point at the same record
// in the same data stream, or they must both be at the end of a stream.
friend bool operator==(const RecordIterator<Kind> &lhs,
const RecordIterator<Kind> &rhs) {
return (lhs.Data.begin() == rhs.Data.begin()) || (lhs.AtEnd && rhs.AtEnd);
}
friend bool operator!=(const RecordIterator<Kind> &lhs,
const RecordIterator<Kind> &rhs) {
return !(lhs == rhs);
}
const CVRecord<Kind> &operator*() const {
assert(!AtEnd);
return Current;
}
const CVRecord<Kind> *operator->() const {
assert(!AtEnd);
return &Current;
}
RecordIterator<Kind> &operator++() {
next();
return *this;
}
RecordIterator<Kind> operator++(int) {
RecordIterator<Kind> Original = *this;
++*this;
return Original;
}
private:
void next() {
assert(!AtEnd && "Attempted to advance more than one past the last rec");
if (Data.empty()) {
// We've advanced past the last record.
AtEnd = true;
return;
}
// FIXME: Use consumeObject when it deals in ArrayRef<uint8_t>.
if (Data.size() < sizeof(RecordPrefix))
return parseError();
const auto *Rec = reinterpret_cast<const RecordPrefix *>(Data.data());
Data = Data.drop_front(sizeof(RecordPrefix));
Current.Length = Rec->RecordLen;
Current.Type = static_cast<Kind>(uint16_t(Rec->RecordKind));
size_t RecLen = Current.Length - 2;
if (RecLen > Data.size())
return parseError();
Current.Data = Data.slice(0, RecLen);
// The next record starts immediately after this one.
Data = Data.drop_front(Current.Data.size());
// FIXME: The stream contains LF_PAD bytes that we need to ignore, but those
// are typically included in LeafData. We may need to call skipPadding() if
// we ever find a record that doesn't count those bytes.
return;
}
void parseError() {
if (HadError)
*HadError = true;
}
bool *HadError;
ArrayRef<uint8_t> Data;
CVRecord<Kind> Current;
bool AtEnd;
};
template <typename Kind>
inline iterator_range<RecordIterator<Kind>>
makeRecordRange(ArrayRef<uint8_t> Data, bool *HadError) {
return make_range(RecordIterator<Kind>(Data, HadError), RecordIterator<Kind>());
}
}
}
#endif

View File

@ -11,6 +11,7 @@
#define LLVM_DEBUGINFO_CODEVIEW_STREAMARRAY_H
#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include "llvm/Support/Error.h"
#include <functional>
#include <type_traits>
@ -25,8 +26,11 @@ namespace codeview {
/// value type.
template <typename T> struct VarStreamArrayExtractor {
// Method intentionally deleted. You must provide an explicit specialization
// with the following method implemented.
uint32_t operator()(const StreamInterface &Stream, T &t) const = delete;
// with the following method implemented. On output return `Len` should
// contain the number of bytes to consume from the stream, and `Item` should
// be initialized with the proper value.
Error operator()(const StreamInterface &Stream, uint32_t &Len,
T &Item) const = delete;
};
/// VarStreamArray represents an array of variable length records backed by a
@ -52,7 +56,9 @@ public:
VarStreamArray(StreamRef Stream) : Stream(Stream) {}
Iterator begin() const { return Iterator(*this); }
Iterator begin(bool *HadError = nullptr) const {
return Iterator(*this, HadError);
}
Iterator end() const { return Iterator(); }
@ -65,11 +71,20 @@ template <typename ValueType, typename Extractor> class VarStreamArrayIterator {
typedef VarStreamArray<ValueType, Extractor> ArrayType;
public:
VarStreamArrayIterator(const ArrayType &Array)
: Array(&Array), IterRef(Array.Stream) {
ThisLen = Extract(IterRef, ThisValue);
VarStreamArrayIterator(const ArrayType &Array, bool *HadError = nullptr)
: Array(&Array), IterRef(Array.Stream), HasError(false),
HadError(HadError) {
auto EC = Extract(IterRef, ThisLen, ThisValue);
if (EC) {
consumeError(std::move(EC));
HasError = true;
if (HadError)
*HadError = true;
}
}
VarStreamArrayIterator() : Array(nullptr), IterRef() {}
VarStreamArrayIterator() : Array(nullptr), IterRef(), HasError(false) {}
~VarStreamArrayIterator() {}
bool operator==(const IterType &R) const {
if (Array && R.Array) {
// Both have a valid array, make sure they're same.
@ -87,19 +102,30 @@ public:
bool operator!=(const IterType &R) { return !(*this == R); }
const ValueType &operator*() const { return ThisValue; }
const ValueType &operator*() const {
assert(Array && !HasError);
return ThisValue;
}
IterType &operator++() {
if (!Array || IterRef.getLength() == 0 || ThisLen == 0)
if (!Array || IterRef.getLength() == 0 || ThisLen == 0 || HasError)
return *this;
IterRef = IterRef.drop_front(ThisLen);
if (IterRef.getLength() == 0)
ThisLen = 0;
else
// TODO: We should report an error if Extract fails.
ThisLen = Extract(IterRef, ThisValue);
if (ThisLen == 0)
else {
auto EC = Extract(IterRef, ThisLen, ThisValue);
if (EC) {
consumeError(std::move(EC));
HasError = true;
if (HadError)
*HadError = true;
}
}
if (ThisLen == 0 || HasError) {
Array = nullptr;
ThisLen = 0;
}
return *this;
}
@ -114,6 +140,8 @@ private:
uint32_t ThisLen;
ValueType ThisValue;
StreamRef IterRef;
bool HasError;
bool *HadError;
Extractor Extract;
};

View File

@ -28,8 +28,6 @@ class StreamInterface {
public:
virtual ~StreamInterface() {}
virtual Error readBytes(uint32_t Offset,
MutableArrayRef<uint8_t> Buffer) const = 0;
virtual Error readBytes(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) const = 0;

View File

@ -28,18 +28,17 @@ class StreamReader {
public:
StreamReader(const StreamInterface &S);
Error readBytes(uint32_t Size, ArrayRef<uint8_t> &Buffer);
Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
Error readInteger(uint16_t &Dest);
Error readInteger(uint32_t &Dest);
Error readZeroString(StringRef &Dest);
Error readFixedString(StringRef &Dest, uint32_t Length);
Error readStreamRef(StreamRef &Ref);
Error readStreamRef(StreamRef &Ref, uint32_t Length);
Error readBytes(MutableArrayRef<uint8_t> Buffer);
template <typename T> Error readObject(const T *&Dest) {
ArrayRef<uint8_t> Buffer;
if (auto EC = readBytes(sizeof(T), Buffer))
if (auto EC = readBytes(Buffer, sizeof(T)))
return EC;
Dest = reinterpret_cast<const T *>(Buffer.data());
return Error::success();

View File

@ -26,11 +26,6 @@ public:
: Stream(Other.Stream), ViewOffset(Other.ViewOffset),
Length(Other.Length) {}
Error readBytes(uint32_t Offset,
MutableArrayRef<uint8_t> Buffer) const override {
return Stream->readBytes(ViewOffset + Offset, Buffer);
}
Error readBytes(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) const override {
return Stream->readBytes(ViewOffset + Offset, Size, Buffer);

View File

@ -39,7 +39,7 @@ public:
/// Dumps the type records in Data. Returns false if there was a type stream
/// parse error, and true otherwise.
bool dump(ArrayRef<uint8_t> Data);
bool dump(const CVSymbolArray &Symbols);
private:
ScopedPrinter &W;

View File

@ -12,8 +12,8 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/Optional.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/RecordIterator.h"
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
#include "llvm/DebugInfo/CodeView/StreamArray.h"
#include "llvm/DebugInfo/CodeView/StreamInterface.h"
@ -1442,15 +1442,9 @@ public:
StringRef Name;
};
typedef RecordIterator<SymbolKind> SymbolIterator;
typedef CVRecord<SymbolKind> CVSymbol;
typedef VarStreamArray<CVSymbol> CVSymbolArray;
inline iterator_range<SymbolIterator> makeSymbolRange(ArrayRef<uint8_t> Data,
bool *HadError) {
return make_range(SymbolIterator(Data, HadError), SymbolIterator());
}
} // namespace codeview
} // namespace llvm

View File

@ -14,7 +14,6 @@
#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeStream.h"
namespace llvm {
class ScopedPrinter;
@ -38,7 +37,7 @@ public:
/// Dumps the type records in Data. Returns false if there was a type stream
/// parse error, and true otherwise.
bool dump(ArrayRef<uint8_t> Data);
bool dump(const CVTypeArray &Types);
/// Gets the type index for the next type record.
unsigned getNextTypeIndex() const {

View File

@ -13,8 +13,10 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
#include "llvm/DebugInfo/CodeView/StreamArray.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/Support/ErrorOr.h"
#include <cinttypes>
@ -1398,6 +1400,9 @@ private:
uint64_t VBPtrOffset;
uint64_t VTableIndex;
};
typedef CVRecord<TypeLeafKind> CVType;
typedef VarStreamArray<CVType> CVTypeArray;
}
}

View File

@ -1,37 +0,0 @@
//===- TypeStream.h ---------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPESTREAM_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPESTREAM_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/RecordIterator.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/Support/Endian.h"
#include <cstdint>
#include <system_error>
namespace llvm {
class APSInt;
namespace codeview {
typedef RecordIterator<TypeLeafKind> TypeIterator;
inline iterator_range<TypeIterator> makeTypeRange(ArrayRef<uint8_t> Data, bool *HadError) {
return make_range(TypeIterator(Data, HadError), TypeIterator());
}
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_TYPESTREAM_H

View File

@ -18,8 +18,7 @@ namespace llvm {
namespace codeview {
/// Merges one type stream into another. Returns true on success.
bool mergeTypeStreams(TypeTableBuilder &DestStream,
ArrayRef<uint8_t> SrcStream);
bool mergeTypeStreams(TypeTableBuilder &DestStream, const CVTypeArray &Types);
} // end namespace codeview
} // end namespace llvm

View File

@ -27,14 +27,13 @@ class MappedBlockStream : public codeview::StreamInterface {
public:
MappedBlockStream(uint32_t StreamIdx, const PDBFile &File);
Error readBytes(uint32_t Offset,
MutableArrayRef<uint8_t> Buffer) const override;
Error readBytes(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) const override;
uint32_t getLength() const override { return StreamLength; }
private:
Error readBytes(uint32_t Offset, MutableArrayRef<uint8_t> Buffer) const;
bool tryReadContiguously(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) const;

View File

@ -25,10 +25,11 @@ private:
public:
ModInfo();
ModInfo(codeview::StreamRef Stream);
ModInfo(const ModInfo &Info);
~ModInfo();
static Error initialize(codeview::StreamRef Stream, ModInfo &Info);
bool hasECInfo() const;
uint16_t getTypeServerIndex() const;
uint16_t getModuleStreamIndex() const;
@ -51,7 +52,6 @@ private:
};
struct ModuleInfoEx {
ModuleInfoEx(codeview::StreamRef Stream) : Info(Stream) {}
ModuleInfoEx(const ModInfo &Info) : Info(Info) {}
ModuleInfoEx(const ModuleInfoEx &Ex)
: Info(Ex.Info), SourceFiles(Ex.SourceFiles) {}
@ -64,9 +64,12 @@ struct ModuleInfoEx {
namespace codeview {
template <> struct VarStreamArrayExtractor<pdb::ModInfo> {
uint32_t operator()(const StreamInterface &Stream, pdb::ModInfo &Info) const {
Info = pdb::ModInfo(Stream);
return Info.getRecordLength();
Error operator()(const StreamInterface &Stream, uint32_t &Length,
pdb::ModInfo &Info) const {
if (auto EC = pdb::ModInfo::initialize(Stream, Info))
return EC;
Length = Info.getRecordLength();
return Error::success();
}
};
}

View File

@ -11,7 +11,7 @@
#define LLVM_DEBUGINFO_PDB_RAW_MODSTREAM_H
#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/RecordIterator.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
@ -29,7 +29,8 @@ public:
Error reload();
iterator_range<codeview::CVSymbolArray::Iterator> symbols() const;
iterator_range<codeview::CVSymbolArray::Iterator>
symbols(bool *HadError) const;
private:
const ModInfo &Mod;

View File

@ -12,7 +12,6 @@
#include "llvm/DebugInfo/CodeView/StreamArray.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/TypeStream.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
@ -37,7 +36,8 @@ public:
uint32_t getSymHash() const;
uint32_t getAddrMap() const;
uint32_t getNumBuckets() const { return NumBuckets; }
iterator_range<codeview::SymbolIterator> getSymbols() const;
iterator_range<codeview::CVSymbolArray::Iterator>
getSymbols(bool *HadError) const;
codeview::FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
return HashBuckets;
}
@ -52,8 +52,6 @@ public:
}
private:
Error readSymbols();
PDBFile &Pdb;
uint32_t StreamNum;

View File

@ -10,7 +10,7 @@
#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBSYMBOLSTREAM_H
#define LLVM_DEBUGINFO_PDB_RAW_PDBSYMBOLSTREAM_H
#include "llvm/DebugInfo/CodeView/ByteStream.h"
#include "llvm/DebugInfo/CodeView/StreamArray.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
@ -26,10 +26,11 @@ public:
~SymbolStream();
Error reload();
iterator_range<codeview::SymbolIterator> getSymbols() const;
iterator_range<codeview::CVSymbolArray::Iterator>
getSymbols(bool *HadError) const;
private:
codeview::ByteStream Stream;
codeview::CVSymbolArray SymbolRecords;
MappedBlockStream MappedStream;
};
}

View File

@ -10,9 +10,9 @@
#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H
#define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H
#include "llvm/DebugInfo/CodeView/ByteStream.h"
#include "llvm/DebugInfo/CodeView/StreamArray.h"
#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include "llvm/DebugInfo/CodeView/TypeStream.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
@ -41,14 +41,14 @@ public:
uint16_t getTypeHashStreamIndex() const;
uint16_t getTypeHashStreamAuxIndex() const;
iterator_range<codeview::TypeIterator> types(bool *HadError) const;
iterator_range<codeview::CVTypeArray::Iterator> types(bool *HadError) const;
private:
PDBFile &Pdb;
MappedBlockStream Stream;
HashFunctionType HashFunction;
codeview::ByteStream RecordsBuffer;
codeview::CVTypeArray TypeRecords;
codeview::StreamRef TypeIndexOffsetBuffer;
codeview::StreamRef HashValuesBuffer;
codeview::StreamRef HashAdjBuffer;

View File

@ -17,41 +17,13 @@ using namespace llvm::codeview;
ByteStream::ByteStream() {}
ByteStream::ByteStream(MutableArrayRef<uint8_t> Data) : Data(Data) {}
ByteStream::ByteStream(ArrayRef<uint8_t> Data) : Data(Data) {}
ByteStream::~ByteStream() {}
void ByteStream::reset() {
Ownership.reset();
Data = MutableArrayRef<uint8_t>();
}
void ByteStream::load(uint32_t Length) {
reset();
if (Length > 0)
Data = MutableArrayRef<uint8_t>(new uint8_t[Length], Length);
Ownership.reset(Data.data());
}
Error ByteStream::load(StreamReader &Reader, uint32_t Length) {
load(Length);
auto EC = Reader.readBytes(Data);
if (EC)
reset();
return EC;
}
Error ByteStream::readBytes(uint32_t Offset,
MutableArrayRef<uint8_t> Buffer) const {
if (Data.size() < Buffer.size() + Offset)
return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
::memcpy(Buffer.data() + Offset, Data.data(), Buffer.size());
return Error::success();
}
Error ByteStream::readBytes(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) const {
if (Data.size() < Buffer.size() + Offset)
if (Data.size() < Size + Offset)
return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
Buffer = Data.slice(Offset, Size);
return Error::success();

View File

@ -17,20 +17,13 @@ using namespace llvm::codeview;
StreamReader::StreamReader(const StreamInterface &S) : Stream(S), Offset(0) {}
Error StreamReader::readBytes(uint32_t Size, ArrayRef<uint8_t> &Buffer) {
Error StreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
if (auto EC = Stream.readBytes(Offset, Size, Buffer))
return EC;
Offset += Size;
return Error::success();
}
Error StreamReader::readBytes(MutableArrayRef<uint8_t> Buffer) {
if (auto EC = Stream.readBytes(Offset, Buffer))
return EC;
Offset += Buffer.size();
return Error::success();
}
Error StreamReader::readInteger(uint16_t &Dest) {
const support::ulittle16_t *P;
if (auto EC = readObject(P))
@ -63,7 +56,7 @@ Error StreamReader::readZeroString(StringRef &Dest) {
setOffset(OriginalOffset);
ArrayRef<uint8_t> Data;
if (auto EC = readBytes(Length, Data))
if (auto EC = readBytes(Data, Length))
return EC;
Dest = StringRef(reinterpret_cast<const char *>(Data.begin()), Data.size());
@ -74,7 +67,7 @@ Error StreamReader::readZeroString(StringRef &Dest) {
Error StreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
ArrayRef<uint8_t> Bytes;
if (auto EC = readBytes(Length, Bytes))
if (auto EC = readBytes(Bytes, Length))
return EC;
Dest = StringRef(reinterpret_cast<const char *>(Bytes.begin()), Bytes.size());
return Error::success();

View File

@ -872,8 +872,8 @@ bool CVSymbolDumper::dump(const CVRecord<SymbolKind> &Record) {
return !Dumper.hadError();
}
bool CVSymbolDumper::dump(ArrayRef<uint8_t> Data) {
bool CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
Dumper.visitSymbolStream(Data);
Dumper.visitSymbolStream(Symbols);
return !Dumper.hadError();
}

View File

@ -12,7 +12,6 @@
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeStream.h"
#include "llvm/Support/ScopedPrinter.h"
using namespace llvm;
@ -683,10 +682,10 @@ bool CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) {
return !Dumper.hadError();
}
bool CVTypeDumper::dump(ArrayRef<uint8_t> Data) {
bool CVTypeDumper::dump(const CVTypeArray &Types) {
assert(W && "printer should not be null");
CVTypeDumperImpl Dumper(*this, *W, PrintRecordBytes);
Dumper.visitTypeStream(Data);
Dumper.visitTypeStream(Types);
return !Dumper.hadError();
}

View File

@ -12,9 +12,9 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeStream.h"
#include "llvm/Support/ScopedPrinter.h"
using namespace llvm;
@ -71,7 +71,7 @@ public:
void visitFieldList(TypeLeafKind Leaf, ArrayRef<uint8_t> FieldData);
bool mergeStream(ArrayRef<uint8_t> SrcStream);
bool mergeStream(const CVTypeArray &Types);
private:
bool hadError() { return FoundBadTypeIndex || CVTypeVisitor::hadError(); }
@ -131,14 +131,14 @@ void TypeStreamMerger::visitUnknownMember(TypeLeafKind LF) {
parseError();
}
bool TypeStreamMerger::mergeStream(ArrayRef<uint8_t> SrcStream) {
bool TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
assert(IndexMap.empty());
visitTypeStream(SrcStream);
visitTypeStream(Types);
IndexMap.clear();
return !hadError();
}
bool llvm::codeview::mergeTypeStreams(TypeTableBuilder &DestStream,
ArrayRef<uint8_t> SrcStream) {
return TypeStreamMerger(DestStream).mergeStream(SrcStream);
const CVTypeArray &Types) {
return TypeStreamMerger(DestStream).mergeStream(Types);
}

View File

@ -69,28 +69,25 @@ struct ModInfo::FileLayout {
ModInfo::ModInfo() : Layout(nullptr) {}
ModInfo::ModInfo(codeview::StreamRef Stream) : Layout(nullptr) {
codeview::StreamReader Reader(Stream);
if (auto EC = Reader.readObject(Layout)) {
consumeError(std::move(EC));
return;
}
if (auto EC = Reader.readZeroString(ModuleName)) {
consumeError(std::move(EC));
return;
}
if (auto EC = Reader.readZeroString(ObjFileName)) {
consumeError(std::move(EC));
return;
}
}
ModInfo::ModInfo(const ModInfo &Info)
: ModuleName(Info.ModuleName), ObjFileName(Info.ObjFileName),
Layout(Info.Layout) {}
ModInfo::~ModInfo() {}
Error ModInfo::initialize(codeview::StreamRef Stream, ModInfo &Info) {
codeview::StreamReader Reader(Stream);
if (auto EC = Reader.readObject(Info.Layout))
return EC;
if (auto EC = Reader.readZeroString(Info.ModuleName))
return EC;
if (auto EC = Reader.readZeroString(Info.ObjFileName))
return EC;
return Error::success();
}
bool ModInfo::hasECInfo() const { return (Layout->Flags & HasECFlagMask) != 0; }
uint16_t ModInfo::getTypeServerIndex() const {

View File

@ -9,7 +9,6 @@
#include "llvm/DebugInfo/PDB/Raw/ModStream.h"
#include "llvm/DebugInfo/CodeView/RecordIterator.h"
#include "llvm/DebugInfo/CodeView/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
@ -58,6 +57,7 @@ Error ModStream::reload() {
return Error::success();
}
iterator_range<codeview::CVSymbolArray::Iterator> ModStream::symbols() const {
iterator_range<codeview::CVSymbolArray::Iterator>
ModStream::symbols(bool *HadError) const {
return llvm::make_range(SymbolsSubstream.begin(), SymbolsSubstream.end());
}

View File

@ -113,7 +113,7 @@ Error PublicsStream::reload() {
// A bitmap of a fixed length follows.
size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32);
uint32_t NumBitmapEntries = BitmapSizeInBits / 8;
if (auto EC = Reader.readBytes(NumBitmapEntries, Bitmap))
if (auto EC = Reader.readBytes(Bitmap, NumBitmapEntries))
return joinErrors(std::move(EC),
make_error<RawError>(raw_error_code::corrupt_file,
"Could not read a bitmap."));
@ -156,13 +156,14 @@ Error PublicsStream::reload() {
return Error::success();
}
iterator_range<codeview::SymbolIterator> PublicsStream::getSymbols() const {
using codeview::SymbolIterator;
iterator_range<codeview::CVSymbolArray::Iterator>
PublicsStream::getSymbols(bool *HadError) const {
auto SymbolS = Pdb.getPDBSymbolStream();
if (SymbolS.takeError()) {
return llvm::make_range<SymbolIterator>(SymbolIterator(), SymbolIterator());
codeview::CVSymbolArray::Iterator Iter;
return llvm::make_range(Iter, Iter);
}
SymbolStream &SS = SymbolS.get();
return SS.getSymbols();
return SS.getSymbols(HadError);
}

View File

@ -30,20 +30,13 @@ SymbolStream::~SymbolStream() {}
Error SymbolStream::reload() {
codeview::StreamReader Reader(MappedStream);
if (Stream.load(Reader, MappedStream.getLength()))
return make_error<RawError>(raw_error_code::corrupt_file,
"Could not load symbol stream.");
if (auto EC = Reader.readArray(SymbolRecords, MappedStream.getLength()))
return EC;
return Error::success();
}
iterator_range<codeview::SymbolIterator> SymbolStream::getSymbols() const {
using codeview::SymbolIterator;
ArrayRef<uint8_t> Data;
if (auto Error = Stream.readBytes(0, Stream.getLength(), Data)) {
consumeError(std::move(Error));
return iterator_range<SymbolIterator>(SymbolIterator(), SymbolIterator());
}
return codeview::makeSymbolRange(Data, nullptr);
iterator_range<codeview::CVSymbolArray::Iterator>
SymbolStream::getSymbols(bool *HadError) const {
return llvm::make_range(SymbolRecords.begin(HadError), SymbolRecords.end());
}

View File

@ -92,7 +92,7 @@ Error TpiStream::reload() {
HashFunction = HashBufferV8;
// The actual type records themselves come from this stream
if (auto EC = RecordsBuffer.load(Reader, Header->TypeRecordBytes))
if (auto EC = Reader.readArray(TypeRecords, Header->TypeRecordBytes))
return EC;
// Hash indices, hash values, etc come from the hash stream.
@ -136,6 +136,7 @@ uint16_t TpiStream::getTypeHashStreamAuxIndex() const {
return Header->HashAuxStreamIndex;
}
iterator_range<codeview::TypeIterator> TpiStream::types(bool *HadError) const {
return codeview::makeTypeRange(RecordsBuffer.data(), /*HadError=*/HadError);
iterator_range<codeview::CVTypeArray::Iterator>
TpiStream::types(bool *HadError) const {
return llvm::make_range(TypeRecords.begin(HadError), TypeRecords.end());
}

View File

@ -354,7 +354,7 @@ static Error dumpStreamData(ScopedPrinter &P, PDBFile &File) {
ArrayRef<uint8_t> Data;
uint32_t BytesToReadInBlock = std::min(
R.bytesRemaining(), static_cast<uint32_t>(File.getBlockSize()));
if (auto EC = R.readBytes(BytesToReadInBlock, Data))
if (auto EC = R.readBytes(Data, BytesToReadInBlock))
return EC;
P.printBinaryBlock(
"Data",
@ -485,7 +485,8 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File,
return EC;
codeview::CVSymbolDumper SD(P, TD, nullptr, false);
for (auto &S : ModS.symbols()) {
bool HadError = false;
for (auto &S : ModS.symbols(&HadError)) {
DictScope DD(P, "");
if (opts::DumpModuleSyms)
@ -493,6 +494,9 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File,
if (opts::DumpSymRecordBytes)
P.printBinaryBlock("Bytes", S.Data);
}
if (HadError)
return make_error<RawError>(raw_error_code::corrupt_file,
"DBI stream contained corrupt record");
}
}
}
@ -509,7 +513,7 @@ static Error dumpTpiStream(ScopedPrinter &P, PDBFile &File,
StringRef VerLabel;
if (StreamIdx == StreamTPI) {
DumpRecordBytes = opts::DumpTpiRecordBytes;
DumpRecords = opts::DumpTpiRecordBytes;
DumpRecords = opts::DumpTpiRecords;
Label = "Type Info Stream (TPI)";
VerLabel = "TPI Version";
} else if (StreamIdx == StreamIPI) {
@ -595,13 +599,19 @@ static Error dumpPublicsStream(ScopedPrinter &P, PDBFile &File,
printSectionOffset);
ListScope L(P, "Symbols");
codeview::CVSymbolDumper SD(P, TD, nullptr, false);
for (auto S : Publics.getSymbols()) {
bool HadError = false;
for (auto S : Publics.getSymbols(&HadError)) {
DictScope DD(P, "");
SD.dump(S);
if (opts::DumpSymRecordBytes)
P.printBinaryBlock("Bytes", S.Data);
}
if (HadError)
return make_error<RawError>(
raw_error_code::corrupt_file,
"Public symbol stream contained corrupt record");
return Error::success();
}

View File

@ -22,6 +22,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/CodeView/ByteStream.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h"
@ -32,7 +33,6 @@
#include "llvm/DebugInfo/CodeView/TypeDumper.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeStream.h"
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/ObjectFile.h"
@ -898,8 +898,16 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
SectionContents);
CVSymbolDumper CVSD(W, CVTD, std::move(CODD), opts::CodeViewSubsectionBytes);
ByteStream Stream(BinaryData);
CVSymbolArray Symbols;
StreamReader Reader(Stream);
if (auto EC = Reader.readArray(Symbols, Reader.getLength())) {
consumeError(std::move(EC));
W.flush();
error(object_error::parse_failed);
}
if (!CVSD.dump(BinaryData)) {
if (!CVSD.dump(Symbols)) {
W.flush();
error(object_error::parse_failed);
}
@ -996,7 +1004,16 @@ void COFFDumper::mergeCodeViewTypes(MemoryTypeTableBuilder &CVTypes) {
Data = Data.drop_front(4);
ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(Data.data()),
Data.size());
if (!mergeTypeStreams(CVTypes, Bytes))
ByteStream Stream(Bytes);
CVTypeArray Types;
StreamReader Reader(Stream);
if (auto EC = Reader.readArray(Types, Reader.getLength())) {
consumeError(std::move(EC));
W.flush();
error(object_error::parse_failed);
}
if (!mergeTypeStreams(CVTypes, Types))
return error(object_error::parse_failed);
}
}
@ -1020,7 +1037,16 @@ void COFFDumper::printCodeViewTypeSection(StringRef SectionName,
ArrayRef<uint8_t> BinaryData(reinterpret_cast<const uint8_t *>(Data.data()),
Data.size());
if (!CVTD.dump(BinaryData)) {
ByteStream Stream(BinaryData);
CVTypeArray Types;
StreamReader Reader(Stream);
if (auto EC = Reader.readArray(Types, Reader.getLength())) {
consumeError(std::move(EC));
W.flush();
error(object_error::parse_failed);
}
if (!CVTD.dump(Types)) {
W.flush();
error(object_error::parse_failed);
}
@ -1472,7 +1498,16 @@ void llvm::dumpCodeViewMergedTypes(
CVTypeDumper CVTD(Writer, opts::CodeViewSubsectionBytes);
ArrayRef<uint8_t> BinaryData(reinterpret_cast<const uint8_t *>(Buf.data()),
Buf.size());
if (!CVTD.dump(BinaryData)) {
ByteStream Stream(BinaryData);
CVTypeArray Types;
StreamReader Reader(Stream);
if (auto EC = Reader.readArray(Types, Reader.getLength())) {
consumeError(std::move(EC));
Writer.flush();
error(object_error::parse_failed);
}
if (!CVTD.dump(Types)) {
Writer.flush();
error(object_error::parse_failed);
}