class ByteStream : public StreamInterface {
public:
ByteStream();
- explicit ByteStream(MutableArrayRef<uint8_t> Bytes);
- explicit ByteStream(uint32_t Length);
+ explicit ByteStream(MutableArrayRef<uint8_t> Data);
~ByteStream() override;
void reset();
- void initialize(MutableArrayRef<uint8_t> Bytes);
- void initialize(uint32_t Length);
- Error initialize(StreamReader &Reader, uint32_t Length);
+
+ void load(uint32_t Length);
+ Error load(StreamReader &Reader, uint32_t Length);
Error readBytes(uint32_t Offset,
MutableArrayRef<uint8_t> Buffer) const override;
-
- Error getArrayRef(uint32_t Offset, ArrayRef<uint8_t> &Buffer,
- uint32_t Length) const override;
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const override;
uint32_t getLength() const override;
--- /dev/null
+//===- StreamArray.h - Array backed by an arbitrary stream ----------------===//
+//
+// 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_STREAMARRAY_H
+#define LLVM_DEBUGINFO_CODEVIEW_STREAMARRAY_H
+
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
+
+#include <functional>
+
+namespace llvm {
+namespace codeview {
+
+/// VarStreamArray represents an array of variable length records backed by a
+/// stream. This could be a contiguous sequence of bytes in memory, it could
+/// be a file on disk, or it could be a PDB stream where bytes are stored as
+/// discontiguous blocks in a file. Usually it is desirable to treat arrays
+/// as contiguous blocks of memory, but doing so with large PDB files, for
+/// example, could mean allocating huge amounts of memory just to allow
+/// re-ordering of stream data to be contiguous before iterating over it. By
+/// abstracting this out, we need not duplicate this memory, and we can
+/// iterate over arrays in arbitrarily formatted streams.
+class VarStreamArrayIterator;
+
+class VarStreamArray {
+ friend class VarStreamArrayIterator;
+ typedef std::function<uint32_t(const StreamInterface &)> LengthFuncType;
+
+public:
+ template <typename LengthFunc>
+ VarStreamArray(StreamRef Stream, const LengthFunc &Len)
+ : Stream(Stream), Len(Len) {}
+
+ VarStreamArrayIterator begin() const;
+ VarStreamArrayIterator end() const;
+
+private:
+ StreamRef Stream;
+ LengthFuncType Len; // Function used to calculate legth of a record
+};
+
+class VarStreamArrayIterator {
+public:
+ VarStreamArrayIterator(const VarStreamArray &Array)
+ : Array(&Array), IterRef(Array.Stream) {
+ ThisLen = Array.Len(IterRef);
+ }
+ VarStreamArrayIterator() : Array(nullptr), IterRef() {}
+ bool operator==(const VarStreamArrayIterator &R) const {
+ if (Array && R.Array) {
+ // Both have a valid array, make sure they're same.
+ assert(Array == R.Array);
+ return IterRef == R.IterRef;
+ }
+
+ // Both iterators are at the end.
+ if (!Array && !R.Array)
+ return true;
+
+ // One is not at the end and one is.
+ return false;
+ }
+
+ bool operator!=(const VarStreamArrayIterator &R) { return !(*this == R); }
+
+ StreamRef operator*() const {
+ ArrayRef<uint8_t> Result;
+ return IterRef.keep_front(ThisLen);
+ }
+
+ VarStreamArrayIterator &operator++() {
+ if (!Array || IterRef.getLength() == 0)
+ return *this;
+ IterRef = IterRef.drop_front(ThisLen);
+ if (IterRef.getLength() == 0) {
+ Array = nullptr;
+ ThisLen = 0;
+ } else {
+ ThisLen = Array->Len(IterRef);
+ }
+ return *this;
+ }
+
+ VarStreamArrayIterator operator++(int) {
+ VarStreamArrayIterator Original = *this;
+ ++*this;
+ return Original;
+ }
+
+private:
+ const VarStreamArray *Array;
+ uint32_t ThisLen;
+ StreamRef IterRef;
+};
+
+inline VarStreamArrayIterator VarStreamArray::begin() const {
+ return VarStreamArrayIterator(*this);
+}
+inline VarStreamArrayIterator VarStreamArray::end() const {
+ return VarStreamArrayIterator();
+}
+
+template <typename T> class FixedStreamArrayIterator;
+
+template <typename T> class FixedStreamArray {
+ friend class FixedStreamArrayIterator<T>;
+ static_assert(std::is_trivially_constructible<T>::value,
+ "FixedStreamArray must be used with trivial types");
+
+public:
+ FixedStreamArray() : Stream() {}
+ FixedStreamArray(StreamRef Stream) : Stream(Stream) {
+ assert(Stream.getLength() % sizeof(T) == 0);
+ }
+
+ const T &operator[](uint32_t Index) const {
+ assert(Index < size());
+ uint32_t Off = Index * sizeof(T);
+ ArrayRef<uint8_t> Data;
+ if (auto EC = Stream.readBytes(Off, sizeof(T), Data)) {
+ assert(false && "Unexpected failure reading from stream");
+ // This should never happen since we asserted that the stream length was
+ // an exact multiple of the element size.
+ consumeError(std::move(EC));
+ }
+ return *reinterpret_cast<const T *>(Data.data());
+ }
+
+ uint32_t size() const { return Stream.getLength() / sizeof(T); }
+
+ FixedStreamArrayIterator<T> begin() const {
+ return FixedStreamArrayIterator<T>(*this, 0);
+ }
+ FixedStreamArrayIterator<T> end() const {
+ return FixedStreamArrayIterator<T>(*this);
+ }
+
+private:
+ StreamRef Stream;
+};
+
+template <typename T> class FixedStreamArrayIterator {
+public:
+ FixedStreamArrayIterator(const FixedStreamArray<T> &Array)
+ : Array(Array), Index(uint32_t(-1)) {}
+ FixedStreamArrayIterator(const FixedStreamArray<T> &Array, uint32_t Index)
+ : Array(Array), Index(Index) {}
+
+ bool operator==(const FixedStreamArrayIterator<T> &R) {
+ assert(&Array == &R.Array);
+ return Index == R.Index;
+ }
+
+ bool operator!=(const FixedStreamArrayIterator<T> &R) {
+ return !(*this == R);
+ }
+
+ const T &operator*() const { return Array[Index]; }
+
+ FixedStreamArrayIterator<T> &operator++() {
+ if (Index == uint32_t(-1))
+ return *this;
+ if (++Index >= Array.size())
+ Index = uint32_t(-1);
+ return *this;
+ }
+
+ FixedStreamArrayIterator<T> operator++(int) {
+ FixedStreamArrayIterator<T> Original = *this;
+ ++*this;
+ return Original;
+ }
+
+private:
+ const FixedStreamArray<T> &Array;
+ uint32_t Index;
+};
+
+} // namespace codeview
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMARRAY_H
namespace llvm {
namespace codeview {
+/// StreamInterface abstracts the notion of a data stream. This way, an
+/// implementation could implement trivial reading from a contiguous memory
+/// buffer or, as in the case of PDB files, reading from a set of possibly
+/// discontiguous blocks. The implementation is required to return references
+/// to stable memory, so if this is not possible (for example in the case of
+/// a PDB file with discontiguous blocks, it must keep its own pool of temp
+/// storage.
class StreamInterface {
public:
virtual ~StreamInterface() {}
virtual Error readBytes(uint32_t Offset,
MutableArrayRef<uint8_t> Buffer) const = 0;
- virtual Error getArrayRef(uint32_t Offset, ArrayRef<uint8_t> &Buffer,
- uint32_t Length) const = 0;
+ virtual Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const = 0;
virtual uint32_t getLength() const = 0;
};
#define LLVM_DEBUGINFO_CODEVIEW_STREAMREADER_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
#include "llvm/DebugInfo/CodeView/StreamInterface.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
namespace llvm {
namespace codeview {
+class StreamRef;
+
class StreamReader {
public:
StreamReader(const StreamInterface &S);
+ Error readBytes(uint32_t Size, ArrayRef<uint8_t> &Buffer);
Error readBytes(MutableArrayRef<uint8_t> Buffer);
+ Error readInteger(uint16_t &Dest);
Error readInteger(uint32_t &Dest);
- Error readZeroString(std::string &Dest);
+ Error readZeroString(StringRef &Dest);
+ Error readFixedString(StringRef &Dest, uint32_t Length);
+ Error readStreamRef(StreamRef &Ref);
+ Error readStreamRef(StreamRef &Ref, uint32_t Length);
+
+ template <typename T> Error readObject(const T *&Dest) {
+ ArrayRef<uint8_t> Buffer;
+ if (auto EC = readBytes(sizeof(T), Buffer))
+ return EC;
+ Dest = reinterpret_cast<const T *>(Buffer.data());
+ return Error::success();
+ }
- template <typename T> Error readObject(T *Dest) {
- MutableArrayRef<uint8_t> Buffer(reinterpret_cast<uint8_t *>(Dest),
- sizeof(T));
- return readBytes(Buffer);
+ template <typename T>
+ Error readArray(FixedStreamArray<T> &Array, uint32_t NumItems) {
+ if (NumItems == 0) {
+ Array = FixedStreamArray<T>();
+ return Error::success();
+ }
+ uint32_t Length = NumItems * sizeof(T);
+ if (Offset + Length > Stream.getLength())
+ return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+ StreamRef View(Stream, Offset, Length);
+ Array = FixedStreamArray<T>(View);
+ Offset += Length;
+ return Error::success();
}
template <typename T> Error readArray(MutableArrayRef<T> Array) {
return readBytes(Casted);
}
- Error getArrayRef(ArrayRef<uint8_t> &Array, uint32_t Length);
-
void setOffset(uint32_t Off) { Offset = Off; }
uint32_t getOffset() const { return Offset; }
uint32_t getLength() const { return Stream.getLength(); }
--- /dev/null
+//===- StreamRef.h - A copyable reference to a stream -----------*- 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_STREAMREF_H
+#define LLVM_DEBUGINFO_CODEVIEW_STREAMREF_H
+
+#include "llvm/DebugInfo/CodeView/StreamInterface.h"
+
+namespace llvm {
+namespace codeview {
+
+class StreamRef : public StreamInterface {
+public:
+ StreamRef() : Stream(nullptr), ViewOffset(0), Length(0) {}
+ StreamRef(const StreamInterface &Stream)
+ : Stream(&Stream), ViewOffset(0), Length(Stream.getLength()) {}
+ StreamRef(const StreamInterface &Stream, uint32_t Offset, uint32_t Length)
+ : Stream(&Stream), ViewOffset(Offset), Length(Length) {}
+ StreamRef(const StreamRef &Other)
+ : 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);
+ }
+
+ uint32_t getLength() const override { return Length; }
+ StreamRef drop_front(uint32_t N) const {
+ if (!Stream)
+ return StreamRef();
+
+ N = std::min(N, Length);
+ return StreamRef(*Stream, ViewOffset + N, Length - N);
+ }
+
+ StreamRef keep_front(uint32_t N) const {
+ if (!Stream)
+ return StreamRef();
+ N = std::min(N, Length);
+ return StreamRef(*Stream, ViewOffset, N);
+ }
+
+ bool operator==(const StreamRef &Other) const {
+ if (Stream != Other.Stream)
+ return false;
+ if (ViewOffset != Other.ViewOffset)
+ return false;
+ if (Length != Other.Length)
+ return false;
+ return true;
+ }
+
+ bool operator!=(const StreamRef &Other) const { return !(*this == Other); }
+
+ StreamRef &operator=(const StreamRef &Other) {
+ Stream = Other.Stream;
+ ViewOffset = Other.ViewOffset;
+ Length = Other.Length;
+ return *this;
+ }
+
+private:
+ const StreamInterface *Stream;
+ uint32_t ViewOffset;
+ uint32_t Length;
+};
+}
+}
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMREF_H
\ No newline at end of file
#define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H
#include "llvm/DebugInfo/CodeView/ByteStream.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
std::vector<ModuleInfoEx> ModuleInfos;
NameHashTable ECNames;
- codeview::ByteStream ModInfoSubstream;
- codeview::ByteStream SecContrSubstream;
- codeview::ByteStream SecMapSubstream;
- codeview::ByteStream FileInfoSubstream;
- codeview::ByteStream TypeServerMapSubstream;
- codeview::ByteStream ECSubstream;
- codeview::ByteStream DbgHeader;
+ codeview::StreamRef ModInfoSubstream;
+ codeview::StreamRef SecContrSubstream;
+ codeview::StreamRef SecMapSubstream;
+ codeview::StreamRef FileInfoSubstream;
+ codeview::StreamRef TypeServerMapSubstream;
+ codeview::StreamRef ECSubstream;
- std::unique_ptr<HeaderInfo> Header;
+ codeview::FixedStreamArray<support::ulittle16_t> DbgStreams;
+
+ const HeaderInfo *Header;
};
}
}
#define LLVM_DEBUGINFO_PDB_RAW_MAPPEDBLOCKSTREAM_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/DebugInfo/CodeView/StreamInterface.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <vector>
Error readBytes(uint32_t Offset,
MutableArrayRef<uint8_t> Buffer) const override;
- Error getArrayRef(uint32_t Offset, ArrayRef<uint8_t> &Buffer,
- uint32_t Length) const override;
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const override;
uint32_t getLength() const override { return StreamLength; }
private:
+ bool tryReadContiguously(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const;
+
uint32_t StreamLength;
std::vector<uint32_t> BlockList;
+ mutable llvm::BumpPtrAllocator Pool;
+ mutable DenseMap<uint32_t, uint8_t *> CacheMap;
const PDBFile &Pdb;
};
#define LLVM_DEBUGINFO_PDB_RAW_MODINFO_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include <cstdint>
#include <vector>
struct FileLayout;
public:
- ModInfo(const uint8_t *Bytes);
+ ModInfo(codeview::StreamRef Stream);
+ ModInfo(const ModInfo &Info);
~ModInfo();
bool hasECInfo() const;
StringRef getModuleName() const;
StringRef getObjFileName() const;
+ uint32_t getRecordLength() const;
+
private:
+ StringRef ModuleName;
+ StringRef ObjFileName;
const FileLayout *Layout;
};
struct ModuleInfoEx {
- ModuleInfoEx(ModInfo Module) : Info(Module) {}
+ ModuleInfoEx(codeview::StreamRef Stream) : Info(Stream) {}
+ ModuleInfoEx(const ModuleInfoEx &Ex)
+ : Info(Ex.Info), SourceFiles(Ex.SourceFiles) {}
ModInfo Info;
std::vector<StringRef> SourceFiles;
};
-class ModInfoIterator {
-public:
- ModInfoIterator(const uint8_t *Stream);
- ModInfoIterator(const ModInfoIterator &Other);
-
- ModInfo operator*();
- ModInfoIterator &operator++();
- ModInfoIterator operator++(int);
- bool operator==(const ModInfoIterator &Other);
- bool operator!=(const ModInfoIterator &Other);
- ModInfoIterator &operator=(const ModInfoIterator &Other);
-
-private:
- const uint8_t *Bytes;
-};
+inline uint32_t ModInfoRecordLength(const codeview::StreamInterface &Stream) {
+ return ModInfo(Stream).getRecordLength();
+}
} // end namespace pdb
} // end namespace llvm
#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/ByteStream.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/Support/Error.h"
MappedBlockStream Stream;
codeview::ByteStream SymbolsSubstream;
- codeview::ByteStream LinesSubstream;
- codeview::ByteStream C13LinesSubstream;
- codeview::ByteStream GlobalRefsSubstream;
+ codeview::StreamRef LinesSubstream;
+ codeview::StreamRef C13LinesSubstream;
+ codeview::StreamRef GlobalRefsSubstream;
};
}
}
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/DebugInfo/CodeView/ByteStream.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <vector>
ArrayRef<uint32_t> name_ids() const;
private:
- codeview::ByteStream NamesBuffer;
+ codeview::StreamRef NamesBuffer;
std::vector<uint32_t> IDs;
uint32_t Signature;
uint32_t HashVersion;
std::vector<uint32_t> ThunkMap;
std::vector<uint32_t> SectionOffsets;
- std::unique_ptr<HeaderInfo> Header;
- std::unique_ptr<GSIHashHeader> HashHdr;
+ const HeaderInfo *Header;
+ const GSIHashHeader *HashHdr;
};
}
}
#define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H
#include "llvm/DebugInfo/CodeView/ByteStream.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include "llvm/DebugInfo/CodeView/TypeStream.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
HashFunctionType HashFunction;
codeview::ByteStream RecordsBuffer;
- codeview::ByteStream TypeIndexOffsetBuffer;
- codeview::ByteStream HashValuesBuffer;
- codeview::ByteStream HashAdjBuffer;
+ codeview::StreamRef TypeIndexOffsetBuffer;
+ codeview::StreamRef HashValuesBuffer;
+ codeview::StreamRef HashAdjBuffer;
- std::unique_ptr<HeaderInfo> Header;
+ const HeaderInfo *Header;
};
}
}
ByteStream::ByteStream() {}
-ByteStream::ByteStream(MutableArrayRef<uint8_t> Bytes) { initialize(Bytes); }
+ByteStream::ByteStream(MutableArrayRef<uint8_t> Data) : Data(Data) {}
-ByteStream::ByteStream(uint32_t Length) { initialize(Length); }
-
-ByteStream::~ByteStream() { reset(); }
+ByteStream::~ByteStream() {}
void ByteStream::reset() {
Ownership.reset();
Data = MutableArrayRef<uint8_t>();
}
-void ByteStream::initialize(MutableArrayRef<uint8_t> Bytes) {
- reset();
- Data = Bytes;
-}
-
-void ByteStream::initialize(uint32_t Length) {
+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::initialize(StreamReader &Reader, uint32_t Length) {
- initialize(Length);
+Error ByteStream::load(StreamReader &Reader, uint32_t Length) {
+ load(Length);
auto EC = Reader.readBytes(Data);
if (EC)
reset();
MutableArrayRef<uint8_t> Buffer) const {
if (Data.size() < Buffer.size() + Offset)
return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- ::memcpy(Buffer.data(), Data.data() + Offset, Buffer.size());
+ ::memcpy(Buffer.data() + Offset, Data.data(), Buffer.size());
return Error::success();
}
-Error ByteStream::getArrayRef(uint32_t Offset, ArrayRef<uint8_t> &Buffer,
- uint32_t Length) const {
- if (Data.size() < Length + Offset)
+Error ByteStream::readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const {
+ if (Data.size() < Buffer.size() + Offset)
return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- Buffer = Data.slice(Offset, Length);
+ Buffer = Data.slice(Offset, Size);
return Error::success();
}
#include "llvm/DebugInfo/CodeView/StreamReader.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
using namespace llvm;
using namespace llvm::codeview;
StreamReader::StreamReader(const StreamInterface &S) : Stream(S), Offset(0) {}
+Error StreamReader::readBytes(uint32_t Size, ArrayRef<uint8_t> &Buffer) {
+ 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;
return Error::success();
}
+Error StreamReader::readInteger(uint16_t &Dest) {
+ const support::ulittle16_t *P;
+ if (auto EC = readObject(P))
+ return EC;
+ Dest = *P;
+ return Error::success();
+}
+
Error StreamReader::readInteger(uint32_t &Dest) {
- support::ulittle32_t P;
- if (auto EC = readObject(&P))
+ const support::ulittle32_t *P;
+ if (auto EC = readObject(P))
return EC;
- Dest = P;
+ Dest = *P;
return Error::success();
}
-Error StreamReader::readZeroString(std::string &Dest) {
- Dest.clear();
- char C;
+Error StreamReader::readZeroString(StringRef &Dest) {
+ uint32_t Length = 0;
+ // First compute the length of the string by reading 1 byte at a time.
+ uint32_t OriginalOffset = getOffset();
+ const char *C;
do {
- if (auto EC = readObject(&C))
+ if (auto EC = readObject(C))
return EC;
- if (C != '\0')
- Dest.push_back(C);
- } while (C != '\0');
+ if (*C != '\0')
+ ++Length;
+ } while (*C != '\0');
+ // Now go back and request a reference for that many bytes.
+ uint32_t NewOffset = getOffset();
+ setOffset(OriginalOffset);
+
+ ArrayRef<uint8_t> Data;
+ if (auto EC = readBytes(Length, Data))
+ 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.
+ setOffset(NewOffset);
return Error::success();
}
-Error StreamReader::getArrayRef(ArrayRef<uint8_t> &Array, uint32_t Length) {
- if (auto EC = Stream.getArrayRef(Offset, Array, Length))
+Error StreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
+ ArrayRef<uint8_t> Bytes;
+ if (auto EC = readBytes(Length, Bytes))
return EC;
+ Dest = StringRef(reinterpret_cast<const char *>(Bytes.begin()), Bytes.size());
+ return Error::success();
+}
+
+Error StreamReader::readStreamRef(StreamRef &Ref) {
+ return readStreamRef(Ref, bytesRemaining());
+}
+
+Error StreamReader::readStreamRef(StreamRef &Ref, uint32_t Length) {
+ if (bytesRemaining() < Length)
+ return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+ Ref = StreamRef(Stream, Offset, Length);
Offset += Length;
return Error::success();
}
Raw/SymbolStream.cpp
Raw/TpiStream.cpp)
+list(APPEND LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB/Raw")
list(APPEND LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB")
add_llvm_library(LLVMDebugInfoPDB
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
#include "llvm/DebugInfo/CodeView/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
ulittle32_t Reserved; // Pad to 64 bytes
};
-DbiStream::DbiStream(PDBFile &File) : Pdb(File), Stream(StreamDBI, File) {
+DbiStream::DbiStream(PDBFile &File)
+ : Pdb(File), Stream(StreamDBI, File), Header(nullptr) {
static_assert(sizeof(HeaderInfo) == 64, "Invalid HeaderInfo size!");
}
Error DbiStream::reload() {
codeview::StreamReader Reader(Stream);
- Header.reset(new HeaderInfo());
-
if (Stream.getLength() < sizeof(HeaderInfo))
return make_error<RawError>(raw_error_code::corrupt_file,
"DBI Stream does not contain a header.");
- if (auto EC = Reader.readObject(Header.get()))
+ if (auto EC = Reader.readObject(Header))
return make_error<RawError>(raw_error_code::corrupt_file,
"DBI Stream does not contain a header.");
return make_error<RawError>(raw_error_code::corrupt_file,
"DBI type server substream not aligned.");
- if (auto EC = ModInfoSubstream.initialize(Reader, Header->ModiSubstreamSize))
+ if (auto EC =
+ Reader.readStreamRef(ModInfoSubstream, Header->ModiSubstreamSize))
return EC;
// Since each ModInfo in the stream is a variable length, we have to iterate
// them to know how many there actually are.
- auto Range =
- llvm::make_range(ModInfoIterator(&ModInfoSubstream.data().front()),
- ModInfoIterator(&ModInfoSubstream.data().back() + 1));
- for (auto Info : Range)
- ModuleInfos.push_back(ModuleInfoEx(Info));
+ codeview::VarStreamArray ModInfoArray(ModInfoSubstream, ModInfoRecordLength);
+ for (auto Info : ModInfoArray) {
+ ModuleInfos.emplace_back(Info);
+ }
- if (auto EC =
- SecContrSubstream.initialize(Reader, Header->SecContrSubstreamSize))
+ if (auto EC = Reader.readStreamRef(SecContrSubstream,
+ Header->SecContrSubstreamSize))
return EC;
- if (auto EC = SecMapSubstream.initialize(Reader, Header->SectionMapSize))
+ if (auto EC = Reader.readStreamRef(SecMapSubstream, Header->SectionMapSize))
return EC;
- if (auto EC = FileInfoSubstream.initialize(Reader, Header->FileInfoSize))
+ if (auto EC = Reader.readStreamRef(FileInfoSubstream, Header->FileInfoSize))
return EC;
if (auto EC =
- TypeServerMapSubstream.initialize(Reader, Header->TypeServerSize))
+ Reader.readStreamRef(TypeServerMapSubstream, Header->TypeServerSize))
return EC;
- if (auto EC = ECSubstream.initialize(Reader, Header->ECSubstreamSize))
+ if (auto EC = Reader.readStreamRef(ECSubstream, Header->ECSubstreamSize))
return EC;
- if (auto EC = DbgHeader.initialize(Reader, Header->OptionalDbgHdrSize))
+ if (auto EC = Reader.readArray(DbgStreams, Header->OptionalDbgHdrSize /
+ sizeof(ulittle16_t)))
return EC;
if (auto EC = initializeFileInfo())
// with the caveat that `NumSourceFiles` cannot be trusted, so
// it is computed by summing `ModFileCounts`.
//
- const uint8_t *Buf = &FileInfoSubstream.data().front();
- auto FI = reinterpret_cast<const FileInfoSubstreamHeader *>(Buf);
- Buf += sizeof(FileInfoSubstreamHeader);
+ const FileInfoSubstreamHeader *FH;
+ codeview::StreamReader FISR(FileInfoSubstream);
+ if (auto EC = FISR.readObject(FH))
+ return EC;
+
// The number of modules in the stream should be the same as reported by
// the FileInfoSubstreamHeader.
- if (FI->NumModules != ModuleInfos.size())
+ if (FH->NumModules != ModuleInfos.size())
return make_error<RawError>(raw_error_code::corrupt_file,
"FileInfo substream count doesn't match DBI.");
+ codeview::FixedStreamArray<ulittle16_t> ModIndexArray;
+ codeview::FixedStreamArray<ulittle16_t> ModFileCountArray;
+ codeview::FixedStreamArray<little32_t> FileNameOffsets;
+
// First is an array of `NumModules` module indices. This is not used for the
// same reason that `NumSourceFiles` is not used. It's an array of uint16's,
// but it's possible there are more than 64k source files, which would imply
// more than 64k modules (e.g. object files) as well. So we ignore this
// field.
- llvm::ArrayRef<ulittle16_t> ModIndexArray(
- reinterpret_cast<const ulittle16_t *>(Buf), ModuleInfos.size());
-
- llvm::ArrayRef<ulittle16_t> ModFileCountArray(ModIndexArray.end(),
- ModuleInfos.size());
+ if (auto EC = FISR.readArray(ModIndexArray, ModuleInfos.size()))
+ return EC;
+ if (auto EC = FISR.readArray(ModFileCountArray, ModuleInfos.size()))
+ return EC;
// Compute the real number of source files.
uint32_t NumSourceFiles = 0;
// them in `ModuleInfoEx`. The value written to and read from the file is
// not used anyway, it is only there as a way to store the offsets for the
// purposes of later accessing the names at runtime.
- llvm::ArrayRef<little32_t> FileNameOffsets(
- reinterpret_cast<const little32_t *>(ModFileCountArray.end()),
- NumSourceFiles);
+ if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles))
+ return EC;
- const char *Names = reinterpret_cast<const char *>(FileNameOffsets.end());
+ codeview::StreamRef NamesBufferRef;
+ if (auto EC = FISR.readStreamRef(NamesBufferRef))
+ return EC;
+ codeview::StreamReader Names(NamesBufferRef);
// We go through each ModuleInfo, determine the number N of source files for
// that module, and then get the next N offsets from the Offsets array, using
uint32_t NumFiles = ModFileCountArray[I];
ModuleInfos[I].SourceFiles.resize(NumFiles);
for (size_t J = 0; J < NumFiles; ++J, ++NextFileIndex) {
- uint32_t FileIndex = FileNameOffsets[NextFileIndex];
- ModuleInfos[I].SourceFiles[J] = StringRef(Names + FileIndex);
+ uint32_t FileOffset = FileNameOffsets[NextFileIndex];
+ Names.setOffset(FileOffset);
+ if (auto EC = Names.readZeroString(ModuleInfos[I].SourceFiles[J]))
+ return EC;
}
}
}
uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
- ArrayRef<uint8_t> DbgData;
- if (auto EC = DbgHeader.getArrayRef(0, DbgData, DbgHeader.getLength())) {
- consumeError(std::move(EC));
- return uint32_t(-1);
- }
- ArrayRef<ulittle16_t> DebugStreams(
- reinterpret_cast<const ulittle16_t *>(DbgData.data()),
- DbgData.size() / sizeof(ulittle16_t));
- return DebugStreams[static_cast<uint16_t>(Type)];
+ return DbgStreams[static_cast<uint16_t>(Type)];
}
PDB_UniqueId Guid;
};
- Header H;
- if (auto EC = Reader.readObject(&H))
+ const Header *H;
+ if (auto EC = Reader.readObject(H))
return make_error<RawError>(raw_error_code::corrupt_file,
"PDB Stream does not contain a header.");
- if (H.Version < PdbRaw_ImplVer::PdbImplVC70)
+ if (H->Version < PdbRaw_ImplVer::PdbImplVC70)
return make_error<RawError>(raw_error_code::corrupt_file,
"Unsupported PDB stream version.");
- Version = H.Version;
- Signature = H.Signature;
- Age = H.Age;
- Guid = H.Guid;
+ Version = H->Version;
+ Signature = H->Signature;
+ Age = H->Age;
+ Guid = H->Guid;
return NamedStreams.load(Reader);
}
}
}
+Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const {
+ // Make sure we aren't trying to read beyond the end of the stream.
+ if (Buffer.size() > StreamLength)
+ return make_error<RawError>(raw_error_code::insufficient_buffer);
+ if (Offset > StreamLength - Buffer.size())
+ return make_error<RawError>(raw_error_code::insufficient_buffer);
+
+ if (tryReadContiguously(Offset, Size, Buffer))
+ return Error::success();
+
+ auto CacheIter = CacheMap.find(Offset);
+ if (CacheIter != CacheMap.end()) {
+ // In a more general solution, we would need to guarantee that the
+ // cached allocation is at least the requested size. In practice, since
+ // these are CodeView / PDB records, we know they are always formatted
+ // the same way and never change, so we should never be requesting two
+ // allocations from the same address with different sizes.
+ Buffer = ArrayRef<uint8_t>(CacheIter->second, Size);
+ return Error::success();
+ }
+
+ // Otherwise allocate a large enough buffer in the pool, memcpy the data
+ // into it, and return an ArrayRef to that.
+ uint8_t *WriteBuffer = Pool.Allocate<uint8_t>(Size);
+
+ if (auto EC = readBytes(Offset, MutableArrayRef<uint8_t>(WriteBuffer, Size)))
+ return EC;
+ CacheMap.insert(std::make_pair(Offset, WriteBuffer));
+ Buffer = ArrayRef<uint8_t>(WriteBuffer, Size);
+ return Error::success();
+}
+
+bool MappedBlockStream::tryReadContiguously(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const {
+ // Attempt to fulfill the request with a reference directly into the stream.
+ // This can work even if the request crosses a block boundary, provided that
+ // all subsequent blocks are contiguous. For example, a 10k read with a 4k
+ // block size can be filled with a reference if, from the starting offset,
+ // 3 blocks in a row are contiguous.
+ uint32_t BlockNum = Offset / Pdb.getBlockSize();
+ uint32_t OffsetInBlock = Offset % Pdb.getBlockSize();
+ uint32_t BytesFromFirstBlock =
+ std::min(Size, Pdb.getBlockSize() - OffsetInBlock);
+ uint32_t NumAdditionalBlocks =
+ llvm::alignTo(Size - BytesFromFirstBlock, Pdb.getBlockSize()) /
+ Pdb.getBlockSize();
+
+ uint32_t RequiredContiguousBlocks = NumAdditionalBlocks + 1;
+ uint32_t E = BlockList[BlockNum];
+ for (uint32_t I = 0; I < RequiredContiguousBlocks; ++I, ++E) {
+ if (BlockList[I + BlockNum] != E)
+ return false;
+ }
+
+ uint32_t FirstBlockAddr = BlockList[BlockNum];
+ StringRef Str = Pdb.getBlockData(FirstBlockAddr, Pdb.getBlockSize());
+ Str = Str.drop_front(OffsetInBlock);
+ Buffer =
+ ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Str.data()), Size);
+ return true;
+}
+
Error MappedBlockStream::readBytes(uint32_t Offset,
MutableArrayRef<uint8_t> Buffer) const {
uint32_t BlockNum = Offset / Pdb.getBlockSize();
}
return Error::success();
-}
-Error MappedBlockStream::getArrayRef(uint32_t Offset, ArrayRef<uint8_t> &Buffer,
- uint32_t Length) const {
- uint32_t BlockNum = Offset / Pdb.getBlockSize();
- uint32_t OffsetInBlock = Offset % Pdb.getBlockSize();
- uint32_t BytesAvailableInBlock = Pdb.getBlockSize() - OffsetInBlock;
-
- // If this is the last block in the stream, not all of the data is valid.
- if (BlockNum == BlockList.size() - 1) {
- uint32_t AllocatedBytesInBlock = StreamLength % Pdb.getBlockSize();
- if (AllocatedBytesInBlock < BytesAvailableInBlock)
- BytesAvailableInBlock = AllocatedBytesInBlock;
- }
- if (BytesAvailableInBlock < Length)
- return make_error<RawError>(raw_error_code::feature_unsupported);
-
- uint32_t StreamBlockAddr = BlockList[BlockNum];
- StringRef Data = Pdb.getBlockData(StreamBlockAddr, Pdb.getBlockSize());
- Data = Data.substr(OffsetInBlock, Length);
-
- Buffer = ArrayRef<uint8_t>(Data.bytes_begin(), Data.bytes_end());
- return Error::success();
}
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
+
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/Support/Endian.h"
using namespace llvm::support;
namespace {
+
struct SCBytes {
ulittle16_t Section;
char Padding1[2];
// for now since it is unused.
ulittle32_t SrcFileNameNI; // Name Index for src file name
ulittle32_t PdbFilePathNI; // Name Index for path to compiler PDB
- char VarInfo[1]; // Module name followed by Obj File Name
-
- StringRef getModuleName() const { return StringRef(VarInfo); }
+ // Null terminated Module name
+ // Null terminated Obj File Name
+};
- StringRef getObjectFileName() const {
- return StringRef(getModuleName().end() + 1);
+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 uint8_t *Bytes)
- : Layout(reinterpret_cast<const FileLayout *>(Bytes)) {}
+ModInfo::ModInfo(const ModInfo &Info)
+ : ModuleName(Info.ModuleName), ObjFileName(Info.ObjFileName),
+ Layout(Info.Layout) {}
ModInfo::~ModInfo() {}
return Layout->PdbFilePathNI;
}
-llvm::StringRef ModInfo::getModuleName() const {
- return Layout->getModuleName();
-}
-
-llvm::StringRef ModInfo::getObjFileName() const {
- return Layout->getObjectFileName();
-}
-
-ModInfoIterator::ModInfoIterator(const uint8_t *Stream) : Bytes(Stream) {}
-
-ModInfoIterator::ModInfoIterator(const ModInfoIterator &Other)
- : Bytes(Other.Bytes) {}
-
-ModInfo ModInfoIterator::operator*() { return ModInfo(Bytes); }
-
-ModInfoIterator &ModInfoIterator::operator++() {
- StringRef Obj = ModInfo(Bytes).getObjFileName();
- Bytes = Obj.bytes_end() + 1;
- Bytes = reinterpret_cast<const uint8_t *>(llvm::alignAddr(Bytes, 4));
-
- return *this;
-}
+StringRef ModInfo::getModuleName() const { return ModuleName; }
-ModInfoIterator ModInfoIterator::operator++(int) {
- ModInfoIterator Copy(*this);
- ++(*this);
- return Copy;
-}
-
-bool ModInfoIterator::operator==(const ModInfoIterator &Other) {
- return Bytes == Other.Bytes;
-}
-
-bool ModInfoIterator::operator!=(const ModInfoIterator &Other) {
- return !(*this == Other);
-}
+StringRef ModInfo::getObjFileName() const { return ObjFileName; }
-ModInfoIterator &ModInfoIterator::operator=(const ModInfoIterator &Other) {
- Bytes = Other.Bytes;
- return *this;
+uint32_t ModInfo::getRecordLength() const {
+ uint32_t M = ModuleName.str().size() + 1;
+ uint32_t O = ObjFileName.str().size() + 1;
+ uint32_t Size = sizeof(FileLayout) + M + O;
+ Size = llvm::alignTo(Size, 4);
+ return Size;
}
return llvm::make_error<RawError>(raw_error_code::corrupt_file,
"Module has both C11 and C13 line info");
- if (auto EC = SymbolsSubstream.initialize(Reader, SymbolSize))
+ if (auto EC = SymbolsSubstream.load(Reader, SymbolSize))
return EC;
- if (auto EC = LinesSubstream.initialize(Reader, C11Size))
+ if (auto EC = Reader.readStreamRef(LinesSubstream, C11Size))
return EC;
- if (auto EC = C13LinesSubstream.initialize(Reader, C13Size))
+ if (auto EC = Reader.readStreamRef(C13LinesSubstream, C13Size))
return EC;
uint32_t GlobalRefsSize;
if (auto EC = Reader.readInteger(GlobalRefsSize))
return EC;
- if (auto EC = GlobalRefsSubstream.initialize(Reader, GlobalRefsSize))
+ if (auto EC = Reader.readStreamRef(GlobalRefsSubstream, GlobalRefsSize))
return EC;
if (Reader.bytesRemaining() > 0)
return llvm::make_error<RawError>(raw_error_code::corrupt_file,
support::ulittle32_t ByteSize;
};
- Header H;
- if (auto EC = Stream.readObject(&H))
+ const Header *H;
+ if (auto EC = Stream.readObject(H))
return EC;
- if (H.Signature != 0xEFFEEFFE)
+ if (H->Signature != 0xEFFEEFFE)
return make_error<RawError>(raw_error_code::corrupt_file,
"Invalid hash table signature");
- if (H.HashVersion != 1 && H.HashVersion != 2)
+ if (H->HashVersion != 1 && H->HashVersion != 2)
return make_error<RawError>(raw_error_code::corrupt_file,
"Unsupported hash version");
- Signature = H.Signature;
- HashVersion = H.HashVersion;
- if (auto EC = NamesBuffer.initialize(Stream, H.ByteSize))
+ Signature = H->Signature;
+ HashVersion = H->HashVersion;
+ if (auto EC = Stream.readStreamRef(NamesBuffer, H->ByteSize))
return make_error<RawError>(raw_error_code::corrupt_file,
"Invalid hash table byte length");
- support::ulittle32_t HashCount;
- if (auto EC = Stream.readObject(&HashCount))
+ const support::ulittle32_t *HashCount;
+ if (auto EC = Stream.readObject(HashCount))
return EC;
- std::vector<support::ulittle32_t> BucketArray(HashCount);
+ std::vector<support::ulittle32_t> BucketArray(*HashCount);
if (auto EC = Stream.readArray<support::ulittle32_t>(BucketArray))
return make_error<RawError>(raw_error_code::corrupt_file,
"Could not read bucket array");
if (ID == IDs[0])
return StringRef();
- return StringRef(NamesBuffer.str().begin() + ID);
+ // NamesBuffer is a buffer of null terminated strings back to back. ID is
+ // 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.
+ StringRef Result;
+ codeview::StreamReader NameReader(NamesBuffer);
+ NameReader.setOffset(ID);
+ if (auto EC = NameReader.readZeroString(Result))
+ consumeError(std::move(EC));
+ return Result;
}
uint32_t NameHashTable::getIDForString(StringRef Str) const {
uint32_t StringOffset = StringsOffset + NameOffset;
uint32_t OldOffset = Stream.getOffset();
// Pump out our c-string from the stream.
- std::string Str;
+ StringRef Str;
Stream.setOffset(StringOffset);
if (Stream.readZeroString(Str))
return make_error<RawError>(raw_error_code::corrupt_file,
"Publics Stream does not contain a header.");
// Read PSGSIHDR and GSIHashHdr structs.
- Header.reset(new HeaderInfo());
- if (Reader.readObject(Header.get()))
+ if (Reader.readObject(Header))
return make_error<RawError>(raw_error_code::corrupt_file,
"Publics Stream does not contain a header.");
- HashHdr.reset(new GSIHashHeader());
- if (Reader.readObject(HashHdr.get()))
+
+ if (Reader.readObject(HashHdr))
return make_error<RawError>(raw_error_code::corrupt_file,
"Publics Stream does not contain a header.");
Error SymbolStream::reload() {
codeview::StreamReader Reader(MappedStream);
- if (Stream.initialize(Reader, MappedStream.getLength()))
+ if (Stream.load(Reader, MappedStream.getLength()))
return make_error<RawError>(raw_error_code::corrupt_file,
"Could not load symbol stream.");
iterator_range<codeview::SymbolIterator> SymbolStream::getSymbols() const {
using codeview::SymbolIterator;
ArrayRef<uint8_t> Data;
- if (auto Error = Stream.getArrayRef(0, Data, Stream.getLength())) {
+ if (auto Error = Stream.readBytes(0, Stream.getLength(), Data)) {
consumeError(std::move(Error));
return iterator_range<SymbolIterator>(SymbolIterator(), SymbolIterator());
}
return make_error<RawError>(raw_error_code::corrupt_file,
"TPI Stream does not contain a header.");
- Header.reset(new HeaderInfo());
- if (Reader.readObject(Header.get()))
+ if (Reader.readObject(Header))
return make_error<RawError>(raw_error_code::corrupt_file,
"TPI Stream does not contain a header.");
HashFunction = HashBufferV8;
// The actual type records themselves come from this stream
- if (auto EC = RecordsBuffer.initialize(Reader, Header->TypeRecordBytes))
+ if (auto EC = RecordsBuffer.load(Reader, Header->TypeRecordBytes))
return EC;
// Hash indices, hash values, etc come from the hash stream.
codeview::StreamReader HSR(HS);
HSR.setOffset(Header->HashValueBuffer.Off);
if (auto EC =
- HashValuesBuffer.initialize(HSR, Header->HashValueBuffer.Length))
+ HSR.readStreamRef(HashValuesBuffer, Header->HashValueBuffer.Length))
return EC;
HSR.setOffset(Header->HashAdjBuffer.Off);
- if (auto EC = HashAdjBuffer.initialize(HSR, Header->HashAdjBuffer.Length))
+ if (auto EC = HSR.readStreamRef(HashAdjBuffer, Header->HashAdjBuffer.Length))
return EC;
HSR.setOffset(Header->IndexOffsetBuffer.Off);
- if (auto EC = TypeIndexOffsetBuffer.initialize(
- HSR, Header->IndexOffsetBuffer.Length))
+ if (auto EC = HSR.readStreamRef(TypeIndexOffsetBuffer,
+ Header->IndexOffsetBuffer.Length))
return EC;
return Error::success();
auto NSIter = NamedStreams.find(StreamIdx);
if (ModIter != ModStreams.end()) {
Value = "Module \"";
- Value += ModIter->second->Info.getModuleName();
+ Value += ModIter->second->Info.getModuleName().str();
Value += "\"";
} else if (NSIter != NamedStreams.end()) {
Value = "Named Stream \"";
ArrayRef<uint8_t> Data;
uint32_t BytesToReadInBlock = std::min(
R.bytesRemaining(), static_cast<uint32_t>(File.getBlockSize()));
- if (auto EC = R.getArrayRef(Data, BytesToReadInBlock))
+ if (auto EC = R.readBytes(BytesToReadInBlock, Data))
return EC;
P.printBinaryBlock(
"Data",
ListScope L(P, "Modules");
for (auto &Modi : DS.modules()) {
DictScope DD(P);
- P.printString("Name", Modi.Info.getModuleName());
+ P.printString("Name", Modi.Info.getModuleName().str());
P.printNumber("Debug Stream Index", Modi.Info.getModuleStreamIndex());
- P.printString("Object File Name", Modi.Info.getObjFileName());
+ P.printString("Object File Name", Modi.Info.getObjFileName().str());
P.printNumber("Num Files", Modi.Info.getNumberOfFiles());
P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex());
P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex());
to_string(Modi.SourceFiles.size()) + " Contributing Source Files";
ListScope LL(P, FileListName);
for (auto File : Modi.SourceFiles)
- P.printString(File);
+ P.printString(File.str());
}
bool HasModuleDI =
(Modi.Info.getModuleStreamIndex() < File.getNumStreams());