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;
StringRef str() const;
private:
- MutableArrayRef<uint8_t> Data;
- std::unique_ptr<uint8_t[]> Ownership;
+ ArrayRef<uint8_t> Data;
};
} // end namespace pdb
--- /dev/null
+//===- 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
#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"
}
/// 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;
#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 {
}
/// 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;
+++ /dev/null
-//===- 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
#define LLVM_DEBUGINFO_CODEVIEW_STREAMARRAY_H
#include "llvm/DebugInfo/CodeView/StreamRef.h"
+#include "llvm/Support/Error.h"
#include <functional>
#include <type_traits>
/// 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
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(); }
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.
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;
}
uint32_t ThisLen;
ValueType ThisValue;
StreamRef IterRef;
+ bool HasError;
+ bool *HadError;
Extractor Extract;
};
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;
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();
: 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);
/// 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;
#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"
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
#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;
/// 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 {
#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>
uint64_t VBPtrOffset;
uint64_t VTableIndex;
};
+
+typedef CVRecord<TypeLeafKind> CVType;
+typedef VarStreamArray<CVType> CVTypeArray;
}
}
+++ /dev/null
-//===- 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
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
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;
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;
};
struct ModuleInfoEx {
- ModuleInfoEx(codeview::StreamRef Stream) : Info(Stream) {}
ModuleInfoEx(const ModInfo &Info) : Info(Info) {}
ModuleInfoEx(const ModuleInfoEx &Ex)
: Info(Ex.Info), SourceFiles(Ex.SourceFiles) {}
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();
}
};
}
#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"
Error reload();
- iterator_range<codeview::CVSymbolArray::Iterator> symbols() const;
+ iterator_range<codeview::CVSymbolArray::Iterator>
+ symbols(bool *HadError) const;
private:
const ModInfo &Mod;
#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"
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;
}
}
private:
- Error readSymbols();
-
PDBFile &Pdb;
uint32_t StreamNum;
#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"
~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;
};
}
#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"
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;
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();
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))
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());
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();
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();
}
#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;
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();
}
#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;
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(); }
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);
}
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 {
#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"
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());
}
// 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."));
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);
}
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());
}
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.
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());
}
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",
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)
if (opts::DumpSymRecordBytes)
P.printBinaryBlock("Bytes", S.Data);
}
+ if (HadError)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "DBI stream contained corrupt record");
}
}
}
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) {
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();
}
#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"
#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"
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);
}
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);
}
}
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);
}
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);
}