[llvm] r281063 - [pdb] Write PDB TPI Stream from Yaml.
Zachary Turner via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 9 10:46:18 PDT 2016
Author: zturner
Date: Fri Sep 9 12:46:17 2016
New Revision: 281063
URL: http://llvm.org/viewvc/llvm-project?rev=281063&view=rev
Log:
[pdb] Write PDB TPI Stream from Yaml.
This writes the full sequence of type records described in
Yaml to the TPI stream of the PDB file.
Reviewed By: rnk
Differential Revision: https://reviews.llvm.org/D24316
Added:
llvm/trunk/include/llvm/DebugInfo/CodeView/TypeSerializationVisitor.h
llvm/trunk/include/llvm/DebugInfo/MSF/SequencedItemStream.h
llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h
llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp
llvm/trunk/tools/llvm-pdbdump/YamlSerializationContext.h
Modified:
llvm/trunk/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h
llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h
llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
llvm/trunk/include/llvm/DebugInfo/MSF/StreamArray.h
llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h
llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h
llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawTypes.h
llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h
llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
llvm/trunk/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt
llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp
llvm/trunk/test/DebugInfo/PDB/pdbdump-readwrite.test
llvm/trunk/test/DebugInfo/PDB/pdbdump-write.test
llvm/trunk/tools/llvm-pdbdump/CodeViewYaml.cpp
llvm/trunk/tools/llvm-pdbdump/CodeViewYaml.h
llvm/trunk/tools/llvm-pdbdump/PdbYaml.cpp
llvm/trunk/tools/llvm-pdbdump/PdbYaml.h
llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp
llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp
llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h Fri Sep 9 12:46:17 2016
@@ -20,7 +20,8 @@ namespace codeview {
class MemoryTypeTableBuilder : public TypeTableBuilder {
public:
- MemoryTypeTableBuilder() {}
+ explicit MemoryTypeTableBuilder(BumpPtrAllocator &Allocator)
+ : RecordStorage(Allocator) {}
bool empty() const { return Records.empty(); }
@@ -33,12 +34,13 @@ public:
}
}
-protected:
TypeIndex writeRecord(llvm::StringRef Data) override;
+ ArrayRef<StringRef> getRecords() const { return Records; }
+
private:
std::vector<StringRef> Records;
- BumpPtrAllocator RecordStorage;
+ BumpPtrAllocator &RecordStorage;
DenseMap<StringRef, TypeIndex> HashedRecords;
};
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h Fri Sep 9 12:46:17 2016
@@ -47,6 +47,7 @@ public:
llvm::StringRef str();
uint64_t size() const { return Stream.tell(); }
+ TypeRecordKind kind() const { return Kind; }
void truncate(uint64_t Size) {
// This works because raw_svector_ostream is not buffered.
@@ -56,10 +57,12 @@ public:
void reset(TypeRecordKind K) {
Buffer.clear();
+ Kind = K;
writeTypeRecordKind(K);
}
private:
+ TypeRecordKind Kind;
llvm::SmallVector<char, 256> Buffer;
llvm::raw_svector_ostream Stream;
llvm::support::endian::Writer<llvm::support::endianness::little> Writer;
Added: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeSerializationVisitor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeSerializationVisitor.h?rev=281063&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeSerializationVisitor.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeSerializationVisitor.h Fri Sep 9 12:46:17 2016
@@ -0,0 +1,74 @@
+//===- TypeSerializationVisitor.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_TYPESERIALIZATIONVISITOR_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZATIONVISITOR_H
+
+#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
+#include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+namespace codeview {
+
+class TypeSerializationVisitor : public TypeVisitorCallbacks {
+public:
+ TypeSerializationVisitor(FieldListRecordBuilder &FieldListBuilder,
+ MemoryTypeTableBuilder &TypeTableBuilder)
+ : FieldListBuilder(FieldListBuilder), TypeTableBuilder(TypeTableBuilder) {
+ }
+
+ virtual Expected<TypeLeafKind> visitTypeBegin(const CVType &Record) override {
+ if (Record.Type == TypeLeafKind::LF_FIELDLIST)
+ FieldListBuilder.reset();
+ return Record.Type;
+ }
+
+ virtual Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override {
+ if (Record.Type == TypeLeafKind::LF_FIELDLIST)
+ TypeTableBuilder.writeFieldList(FieldListBuilder);
+ return Error::success();
+ }
+
+#define TYPE_RECORD(EnumName, EnumVal, Name) \
+ virtual Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, \
+ Name##Record &Record) override { \
+ visitKnownRecordImpl(Record); \
+ return Error::success(); \
+ }
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#define MEMBER_RECORD(EnumName, EnumVal, Name) \
+ virtual Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, \
+ Name##Record &Record) override { \
+ visitMemberRecordImpl(Record); \
+ return Error::success(); \
+ }
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+
+private:
+ template <typename RecordKind> void visitKnownRecordImpl(RecordKind &Record) {
+ TypeTableBuilder.writeKnownType(Record);
+ }
+ template <typename RecordKind>
+ void visitMemberRecordImpl(RecordKind &Record) {
+ FieldListBuilder.writeMemberType(Record);
+ }
+
+ void visitKnownRecordImpl(FieldListRecord &FieldList) {}
+
+ FieldListRecordBuilder &FieldListBuilder;
+ MemoryTypeTableBuilder &TypeTableBuilder;
+};
+}
+}
+
+#endif
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h Fri Sep 9 12:46:17 2016
@@ -63,6 +63,11 @@ public:
TypeIndex writeRecord(TypeRecordBuilder &builder);
virtual TypeIndex writeRecord(llvm::StringRef record) = 0;
+
+ ArrayRef<TypeRecordKind> getRecordKinds() const { return RecordKinds; }
+
+private:
+ std::vector<TypeRecordKind> RecordKinds;
};
}
}
Added: llvm/trunk/include/llvm/DebugInfo/MSF/SequencedItemStream.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/MSF/SequencedItemStream.h?rev=281063&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/MSF/SequencedItemStream.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/MSF/SequencedItemStream.h Fri Sep 9 12:46:17 2016
@@ -0,0 +1,91 @@
+//===- SequencedItemStream.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_MSF_SEQUENCEDITEMSTREAM_H
+#define LLVM_DEBUGINFO_MSF_SEQUENCEDITEMSTREAM_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/MSF/MSFError.h"
+#include "llvm/DebugInfo/MSF/StreamInterface.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+#include <memory>
+#include <type_traits>
+
+namespace llvm {
+namespace msf {
+template <typename T> struct SequencedItemTraits {
+ static size_t length(const T &Item) = delete;
+ static ArrayRef<uint8_t> bytes(const T &Item) = delete;
+};
+
+/// SequencedItemStream represents a sequence of objects stored in a
+/// standard container but for which it is useful to view as a stream of
+/// contiguous bytes. An example of this might be if you have a std::vector
+/// of TPI records, where each record contains a byte sequence that
+/// represents that one record serialized, but where each consecutive item
+/// might not be allocated immediately after the previous item. Using a
+/// SequencedItemStream, we can adapt the VarStreamArray class to trivially
+/// extract one item at a time, allowing the data to be used anywhere a
+/// VarStreamArray could be used.
+template <typename T, typename Traits = SequencedItemTraits<T>>
+class SequencedItemStream : public ReadableStream {
+public:
+ SequencedItemStream() {}
+
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const override {
+ auto ExpectedIndex = translateOffsetIndex(Offset);
+ if (!ExpectedIndex)
+ return ExpectedIndex.takeError();
+ const auto &Item = Items[*ExpectedIndex];
+ if (Size > Traits::length(Item))
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ Buffer = Traits::bytes(Item).take_front(Size);
+ return Error::success();
+ }
+
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) const override {
+ auto ExpectedIndex = translateOffsetIndex(Offset);
+ if (!ExpectedIndex)
+ return ExpectedIndex.takeError();
+ Buffer = Traits::bytes(Items[*ExpectedIndex]);
+ return Error::success();
+ }
+
+ void setItems(ArrayRef<T> ItemArray) { Items = ItemArray; }
+
+ uint32_t getLength() const override {
+ uint32_t Size = 0;
+ for (const auto &Item : Items)
+ Size += Traits::length(Item);
+ return Size;
+ }
+
+private:
+ Expected<uint32_t> translateOffsetIndex(uint32_t Offset) const {
+ uint32_t CurrentOffset = 0;
+ uint32_t CurrentIndex = 0;
+ for (const auto &Item : Items) {
+ if (CurrentOffset >= Offset)
+ break;
+ CurrentOffset += Traits::length(Item);
+ ++CurrentIndex;
+ }
+ if (CurrentOffset != Offset)
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ return CurrentIndex;
+ }
+ ArrayRef<T> Items;
+};
+} // end namespace msf
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_MSF_SEQUENCEDITEMSTREAM_H
Modified: llvm/trunk/include/llvm/DebugInfo/MSF/StreamArray.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/MSF/StreamArray.h?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/MSF/StreamArray.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/MSF/StreamArray.h Fri Sep 9 12:46:17 2016
@@ -10,6 +10,7 @@
#ifndef LLVM_DEBUGINFO_MSF_STREAMARRAY_H
#define LLVM_DEBUGINFO_MSF_STREAMARRAY_H
+#include "llvm/DebugInfo/MSF/SequencedItemStream.h"
#include "llvm/DebugInfo/MSF/StreamRef.h"
#include "llvm/Support/Error.h"
Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h Fri Sep 9 12:46:17 2016
@@ -92,6 +92,8 @@ public:
Expected<SymbolStream &> getPDBSymbolStream();
Expected<NameHashTable &> getStringTable();
+ BumpPtrAllocator &getAllocator() { return Allocator; }
+
private:
BumpPtrAllocator &Allocator;
Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h Fri Sep 9 12:46:17 2016
@@ -28,6 +28,7 @@ class MSFBuilder;
namespace pdb {
class DbiStreamBuilder;
class InfoStreamBuilder;
+class TpiStreamBuilder;
class PDBFileBuilder {
public:
@@ -40,6 +41,7 @@ public:
msf::MSFBuilder &getMsfBuilder();
InfoStreamBuilder &getInfoBuilder();
DbiStreamBuilder &getDbiBuilder();
+ TpiStreamBuilder &getTpiBuilder();
Expected<std::unique_ptr<PDBFile>>
build(std::unique_ptr<msf::WritableStream> PdbFileBuffer);
@@ -54,6 +56,7 @@ private:
std::unique_ptr<msf::MSFBuilder> Msf;
std::unique_ptr<InfoStreamBuilder> Info;
std::unique_ptr<DbiStreamBuilder> Dbi;
+ std::unique_ptr<TpiStreamBuilder> Tpi;
};
}
}
Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawTypes.h?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawTypes.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawTypes.h Fri Sep 9 12:46:17 2016
@@ -266,6 +266,34 @@ struct PDB_UniqueId {
char Guid[16];
};
+// The header preceeding the global TPI stream.
+// This corresponds to `HDR` in PDB/dbi/tpi.h.
+struct TpiStreamHeader {
+ struct EmbeddedBuf {
+ support::little32_t Off;
+ support::ulittle32_t Length;
+ };
+
+ support::ulittle32_t Version;
+ support::ulittle32_t HeaderSize;
+ support::ulittle32_t TypeIndexBegin;
+ support::ulittle32_t TypeIndexEnd;
+ support::ulittle32_t TypeRecordBytes;
+
+ // The following members correspond to `TpiHash` in PDB/dbi/tpi.h.
+ support::ulittle16_t HashStreamIndex;
+ support::ulittle16_t HashAuxStreamIndex;
+ support::ulittle32_t HashKeySize;
+ support::ulittle32_t NumHashBuckets;
+
+ EmbeddedBuf HashValueBuffer;
+ EmbeddedBuf IndexOffsetBuffer;
+ EmbeddedBuf HashAdjBuffer;
+};
+
+const uint32_t MinTpiHashBuckets = 0x1000;
+const uint32_t MaxTpiHashBuckets = 0x40000;
+
/// The header preceeding the global PDB Stream (Stream 1)
struct InfoStreamHeader {
support::ulittle32_t Version;
Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h Fri Sep 9 12:46:17 2016
@@ -27,7 +27,7 @@ namespace pdb {
class PDBFile;
class TpiStream {
- struct HeaderInfo;
+ friend class TpiStreamBuilder;
public:
TpiStream(const PDBFile &File,
@@ -66,7 +66,7 @@ private:
msf::FixedStreamArray<TypeIndexOffset> TypeIndexOffsets;
msf::FixedStreamArray<TypeIndexOffset> HashAdjustments;
- const HeaderInfo *Header;
+ const TpiStreamHeader *Header;
};
}
}
Added: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h?rev=281063&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h Fri Sep 9 12:46:17 2016
@@ -0,0 +1,76 @@
+//===- TpiStreamBuilder.h - PDB Tpi Stream Creation -------------*- 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_PDB_RAW_PDBTPISTREAMBUILDER_H
+#define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAMBUILDER_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
+#include "llvm/DebugInfo/MSF/SequencedItemStream.h"
+#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Error.h"
+
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+class TypeRecord;
+}
+namespace msf {
+struct MSFLayout;
+class ReadableStreamRef;
+class WritableStream;
+
+template <> struct SequencedItemTraits<llvm::codeview::CVType> {
+ static size_t length(const codeview::CVType &Item) { return Item.Length; }
+ static ArrayRef<uint8_t> bytes(const codeview::CVType &Item) {
+ return Item.RawData;
+ }
+};
+}
+namespace pdb {
+class PDBFile;
+class TpiStream;
+struct TpiStreamHeader;
+
+class TpiStreamBuilder {
+public:
+ explicit TpiStreamBuilder(BumpPtrAllocator &Allocator);
+ ~TpiStreamBuilder();
+
+ TpiStreamBuilder(const TpiStreamBuilder &) = delete;
+ TpiStreamBuilder &operator=(const TpiStreamBuilder &) = delete;
+
+ void setVersionHeader(PdbRaw_TpiVer Version);
+ void addTypeRecord(const codeview::CVType &Record);
+
+ Expected<std::unique_ptr<TpiStream>> build(PDBFile &File,
+ const msf::WritableStream &Buffer);
+
+ Error commit(const msf::MSFLayout &Layout, const msf::WritableStream &Buffer);
+
+ uint32_t calculateSerializedLength() const;
+
+private:
+ Error finalize();
+
+ BumpPtrAllocator &Allocator;
+
+ Optional<PdbRaw_TpiVer> VerHeader;
+ std::vector<codeview::CVType> TypeRecords;
+ msf::SequencedItemStream<codeview::CVType> TypeRecordStream;
+
+ const TpiStreamHeader *Header;
+};
+}
+}
+
+#endif
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Fri Sep 9 12:46:17 2016
@@ -40,7 +40,8 @@ using namespace llvm::codeview;
using namespace llvm::msf;
CodeViewDebug::CodeViewDebug(AsmPrinter *AP)
- : DebugHandlerBase(AP), OS(*Asm->OutStreamer), CurFn(nullptr) {
+ : DebugHandlerBase(AP), OS(*Asm->OutStreamer), Allocator(),
+ TypeTable(Allocator), CurFn(nullptr) {
// If module doesn't have named metadata anchors or COFF debug section
// is not available, skip any debug info related stuff.
if (!MMI->getModule()->getNamedMetadata("llvm.dbg.cu") ||
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h Fri Sep 9 12:46:17 2016
@@ -36,6 +36,7 @@ struct ClassInfo;
/// \brief Collects and handles line tables information in a CodeView format.
class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
MCStreamer &OS;
+ llvm::BumpPtrAllocator Allocator;
codeview::MemoryTypeTableBuilder TypeTable;
/// Represents the most general definition range.
Modified: llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp Fri Sep 9 12:46:17 2016
@@ -81,14 +81,17 @@ Error CVTypeVisitor::visitTypeRecord(con
else
return ExpectedKind.takeError();
+ CVType RecordCopy = Record;
+ RecordCopy.Type = Kind;
+
switch (Kind) {
default:
- if (auto EC = Callbacks.visitUnknownType(Record))
+ if (auto EC = Callbacks.visitUnknownType(RecordCopy))
return EC;
break;
#define TYPE_RECORD(EnumName, EnumVal, Name) \
case EnumName: { \
- if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks)) \
+ if (auto EC = visitKnownRecord<Name##Record>(RecordCopy, Callbacks)) \
return EC; \
break; \
}
@@ -101,7 +104,7 @@ Error CVTypeVisitor::visitTypeRecord(con
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
}
- if (auto EC = Callbacks.visitTypeEnd(Record))
+ if (auto EC = Callbacks.visitTypeEnd(RecordCopy))
return EC;
return Error::success();
Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp Fri Sep 9 12:46:17 2016
@@ -13,7 +13,7 @@ using namespace llvm;
using namespace codeview;
TypeRecordBuilder::TypeRecordBuilder(TypeRecordKind Kind)
- : Stream(Buffer), Writer(Stream) {
+ : Kind(Kind), Stream(Buffer), Writer(Stream) {
writeTypeRecordKind(Kind);
}
Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp Fri Sep 9 12:46:17 2016
@@ -257,7 +257,9 @@ TypeIndex TypeTableBuilder::writeKnownTy
}
TypeIndex TypeTableBuilder::writeRecord(TypeRecordBuilder &Builder) {
- return writeRecord(Builder.str());
+ TypeIndex I = writeRecord(Builder.str());
+ RecordKinds.push_back(Builder.kind());
+ return I;
}
TypeIndex TypeTableBuilder::writeFieldList(FieldListRecordBuilder &FieldList) {
Modified: llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt (original)
+++ llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt Fri Sep 9 12:46:17 2016
@@ -45,7 +45,8 @@ add_pdb_impl_folder(Raw
Raw/RawError.cpp
Raw/RawSession.cpp
Raw/SymbolStream.cpp
- Raw/TpiStream.cpp)
+ Raw/TpiStream.cpp
+ Raw/TpiStreamBuilder.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")
Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp Fri Sep 9 12:46:17 2016
@@ -19,6 +19,8 @@
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
+#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
+#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h"
using namespace llvm;
using namespace llvm::codeview;
@@ -58,6 +60,12 @@ DbiStreamBuilder &PDBFileBuilder::getDbi
return *Dbi;
}
+TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
+ if (!Tpi)
+ Tpi = llvm::make_unique<TpiStreamBuilder>(Allocator);
+ return *Tpi;
+}
+
Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() const {
if (Info) {
uint32_t Length = Info->calculateSerializedLength();
@@ -69,6 +77,11 @@ Expected<msf::MSFLayout> PDBFileBuilder:
if (auto EC = Msf->setStreamSize(StreamDBI, Length))
return std::move(EC);
}
+ if (Tpi) {
+ uint32_t Length = Tpi->calculateSerializedLength();
+ if (auto EC = Msf->setStreamSize(StreamTPI, Length))
+ return std::move(EC);
+ }
return Msf->build();
}
@@ -96,6 +109,13 @@ PDBFileBuilder::build(std::unique_ptr<ms
File->Dbi = std::move(*ExpectedDbi);
}
+ if (Tpi) {
+ auto ExpectedTpi = Tpi->build(*File, *PdbFileBuffer);
+ if (!ExpectedTpi)
+ return ExpectedTpi.takeError();
+ File->Tpi = std::move(*ExpectedTpi);
+ }
+
if (File->Info && File->Dbi && File->Info->getAge() != File->Dbi->getAge())
return llvm::make_error<RawError>(
raw_error_code::corrupt_file,
@@ -144,5 +164,10 @@ Error PDBFileBuilder::commit(const msf::
return EC;
}
+ if (Tpi) {
+ if (auto EC = Tpi->commit(Layout, Buffer))
+ return EC;
+ }
+
return Buffer.commit();
}
\ No newline at end of file
Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp Fri Sep 9 12:46:17 2016
@@ -31,35 +31,6 @@ using namespace llvm::support;
using namespace llvm::msf;
using namespace llvm::pdb;
-namespace {
-const uint32_t MinHashBuckets = 0x1000;
-const uint32_t MaxHashBuckets = 0x40000;
-}
-
-// This corresponds to `HDR` in PDB/dbi/tpi.h.
-struct TpiStream::HeaderInfo {
- struct EmbeddedBuf {
- little32_t Off;
- ulittle32_t Length;
- };
-
- ulittle32_t Version;
- ulittle32_t HeaderSize;
- ulittle32_t TypeIndexBegin;
- ulittle32_t TypeIndexEnd;
- ulittle32_t TypeRecordBytes;
-
- // The following members correspond to `TpiHash` in PDB/dbi/tpi.h.
- ulittle16_t HashStreamIndex;
- ulittle16_t HashAuxStreamIndex;
- ulittle32_t HashKeySize;
- ulittle32_t NumHashBuckets;
-
- EmbeddedBuf HashValueBuffer;
- EmbeddedBuf IndexOffsetBuffer;
- EmbeddedBuf HashAdjBuffer;
-};
-
TpiStream::TpiStream(const PDBFile &File,
std::unique_ptr<MappedBlockStream> Stream)
: Pdb(File), Stream(std::move(Stream)) {}
@@ -175,7 +146,7 @@ Error TpiStream::verifyHashValues() {
Error TpiStream::reload() {
StreamReader Reader(*Stream);
- if (Reader.bytesRemaining() < sizeof(HeaderInfo))
+ if (Reader.bytesRemaining() < sizeof(TpiStreamHeader))
return make_error<RawError>(raw_error_code::corrupt_file,
"TPI Stream does not contain a header.");
@@ -187,7 +158,7 @@ Error TpiStream::reload() {
return make_error<RawError>(raw_error_code::corrupt_file,
"Unsupported TPI Version.");
- if (Header->HeaderSize != sizeof(HeaderInfo))
+ if (Header->HeaderSize != sizeof(TpiStreamHeader))
return make_error<RawError>(raw_error_code::corrupt_file,
"Corrupt TPI Header size.");
@@ -195,8 +166,8 @@ Error TpiStream::reload() {
return make_error<RawError>(raw_error_code::corrupt_file,
"TPI Stream expected 4 byte hash key size.");
- if (Header->NumHashBuckets < MinHashBuckets ||
- Header->NumHashBuckets > MaxHashBuckets)
+ if (Header->NumHashBuckets < MinTpiHashBuckets ||
+ Header->NumHashBuckets > MaxTpiHashBuckets)
return make_error<RawError>(raw_error_code::corrupt_file,
"TPI Stream Invalid number of hash buckets.");
@@ -205,40 +176,44 @@ Error TpiStream::reload() {
return EC;
// Hash indices, hash values, etc come from the hash stream.
- if (Header->HashStreamIndex >= Pdb.getNumStreams())
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Invalid TPI hash stream index.");
- auto HS = MappedBlockStream::createIndexedStream(
- Pdb.getMsfLayout(), Pdb.getMsfBuffer(), Header->HashStreamIndex);
- StreamReader HSR(*HS);
-
- uint32_t NumHashValues = Header->HashValueBuffer.Length / sizeof(ulittle32_t);
- if (NumHashValues != NumTypeRecords())
- return make_error<RawError>(
- raw_error_code::corrupt_file,
- "TPI hash count does not match with the number of type records.");
- HSR.setOffset(Header->HashValueBuffer.Off);
- if (auto EC = HSR.readArray(HashValues, NumHashValues))
- return EC;
-
- HSR.setOffset(Header->IndexOffsetBuffer.Off);
- uint32_t NumTypeIndexOffsets =
- Header->IndexOffsetBuffer.Length / sizeof(TypeIndexOffset);
- if (auto EC = HSR.readArray(TypeIndexOffsets, NumTypeIndexOffsets))
- return EC;
-
- HSR.setOffset(Header->HashAdjBuffer.Off);
- uint32_t NumHashAdjustments =
- Header->HashAdjBuffer.Length / sizeof(TypeIndexOffset);
- if (auto EC = HSR.readArray(HashAdjustments, NumHashAdjustments))
- return EC;
-
- HashStream = std::move(HS);
-
- // TPI hash table is a parallel array for the type records.
- // Verify that the hash values match with type records.
- if (auto EC = verifyHashValues())
- return EC;
+ if (Header->HashStreamIndex != kInvalidStreamIndex) {
+ if (Header->HashStreamIndex >= Pdb.getNumStreams())
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid TPI hash stream index.");
+
+ auto HS = MappedBlockStream::createIndexedStream(
+ Pdb.getMsfLayout(), Pdb.getMsfBuffer(), Header->HashStreamIndex);
+ StreamReader HSR(*HS);
+
+ uint32_t NumHashValues =
+ Header->HashValueBuffer.Length / sizeof(ulittle32_t);
+ if (NumHashValues != NumTypeRecords())
+ return make_error<RawError>(
+ raw_error_code::corrupt_file,
+ "TPI hash count does not match with the number of type records.");
+ HSR.setOffset(Header->HashValueBuffer.Off);
+ if (auto EC = HSR.readArray(HashValues, NumHashValues))
+ return EC;
+
+ HSR.setOffset(Header->IndexOffsetBuffer.Off);
+ uint32_t NumTypeIndexOffsets =
+ Header->IndexOffsetBuffer.Length / sizeof(TypeIndexOffset);
+ if (auto EC = HSR.readArray(TypeIndexOffsets, NumTypeIndexOffsets))
+ return EC;
+
+ HSR.setOffset(Header->HashAdjBuffer.Off);
+ uint32_t NumHashAdjustments =
+ Header->HashAdjBuffer.Length / sizeof(TypeIndexOffset);
+ if (auto EC = HSR.readArray(HashAdjustments, NumHashAdjustments))
+ return EC;
+
+ HashStream = std::move(HS);
+
+ // TPI hash table is a parallel array for the type records.
+ // Verify that the hash values match with type records.
+ if (auto EC = verifyHashValues())
+ return EC;
+ }
return Error::success();
}
Added: llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp?rev=281063&view=auto
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp (added)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp Fri Sep 9 12:46:17 2016
@@ -0,0 +1,95 @@
+#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h"
+
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/MSF/StreamWriter.h"
+#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Raw/RawError.h"
+#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
+#include "llvm/Support/Allocator.h"
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+using namespace llvm::support;
+
+TpiStreamBuilder::TpiStreamBuilder(BumpPtrAllocator &Allocator)
+ : Allocator(Allocator), Header(nullptr) {}
+
+TpiStreamBuilder::~TpiStreamBuilder() {}
+
+void TpiStreamBuilder::setVersionHeader(PdbRaw_TpiVer Version) {
+ VerHeader = Version;
+}
+
+void TpiStreamBuilder::addTypeRecord(const codeview::CVType &Record) {
+ TypeRecords.push_back(Record);
+ TypeRecordStream.setItems(TypeRecords);
+}
+
+Error TpiStreamBuilder::finalize() {
+ if (Header)
+ return Error::success();
+
+ TpiStreamHeader *H = Allocator.Allocate<TpiStreamHeader>();
+
+ uint32_t Count = TypeRecords.size();
+
+ H->Version = *VerHeader;
+ H->HeaderSize = sizeof(TpiStreamHeader);
+ H->TypeIndexBegin = codeview::TypeIndex::FirstNonSimpleIndex;
+ H->TypeIndexEnd = H->TypeIndexBegin + Count;
+ H->TypeRecordBytes = TypeRecordStream.getLength();
+
+ H->HashStreamIndex = kInvalidStreamIndex;
+ H->HashAuxStreamIndex = kInvalidStreamIndex;
+ H->HashKeySize = sizeof(ulittle32_t);
+ H->NumHashBuckets = MinTpiHashBuckets;
+
+ H->HashValueBuffer.Length = 0;
+ H->HashAdjBuffer.Length = 0;
+ H->IndexOffsetBuffer.Length = 0;
+
+ Header = H;
+ return Error::success();
+}
+
+uint32_t TpiStreamBuilder::calculateSerializedLength() const {
+ return sizeof(TpiStreamHeader) + TypeRecordStream.getLength();
+}
+
+Expected<std::unique_ptr<TpiStream>>
+TpiStreamBuilder::build(PDBFile &File, const msf::WritableStream &Buffer) {
+ if (!VerHeader.hasValue())
+ return make_error<RawError>(raw_error_code::unspecified,
+ "Missing TPI Stream Version");
+ if (auto EC = finalize())
+ return std::move(EC);
+
+ auto StreamData = MappedBlockStream::createIndexedStream(File.getMsfLayout(),
+ Buffer, StreamTPI);
+ auto Tpi = llvm::make_unique<TpiStream>(File, std::move(StreamData));
+ Tpi->Header = Header;
+ Tpi->TypeRecords = VarStreamArray<codeview::CVType>(TypeRecordStream);
+ return std::move(Tpi);
+}
+
+Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout,
+ const msf::WritableStream &Buffer) {
+ if (auto EC = finalize())
+ return EC;
+
+ auto InfoS =
+ WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamTPI);
+
+ StreamWriter Writer(*InfoS);
+ if (auto EC = Writer.writeObject(*Header))
+ return EC;
+
+ auto RecordArray = VarStreamArray<codeview::CVType>(TypeRecordStream);
+ if (auto EC = Writer.writeArray(RecordArray))
+ return EC;
+
+ return Error::success();
+}
Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-readwrite.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-readwrite.test?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-readwrite.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-readwrite.test Fri Sep 9 12:46:17 2016
@@ -1,10 +1,10 @@
RUN: llvm-pdbdump pdb2yaml -dbi-module-info -dbi-module-source-info \
-RUN: -dbi-stream -pdb-stream -stream-directory -stream-metadata \
-RUN: %p/Inputs/empty.pdb > %t.1
+RUN: -dbi-stream -pdb-stream -tpi-stream -stream-directory \
+RUN: -stream-metadata %p/Inputs/empty.pdb > %t.1
RUN: llvm-pdbdump yaml2pdb -pdb=%t.2 %t.1
-RUN: llvm-pdbdump raw -headers %p/Inputs/empty.pdb | FileCheck %s
-RUN: llvm-pdbdump raw -headers %t.2 | FileCheck %s
+RUN: llvm-pdbdump raw -headers -tpi-records %p/Inputs/empty.pdb | FileCheck %s
+RUN: llvm-pdbdump raw -headers -tpi-records %t.2 | FileCheck %s
CHECK: FileHeaders {
CHECK-NEXT: BlockSize: 4096
@@ -17,13 +17,16 @@ CHECK-NEXT: NumDirectoryBlocks: 1
CHECK-NEXT: DirectoryBlocks: [23]
CHECK-NEXT: NumStreams: 17
CHECK-NEXT: }
-CHECK-NEXT: PDB Stream {
+CHECK: PDB Stream {
CHECK-NEXT: Version: 20000404
CHECK-NEXT: Signature: 0x54E507E2
CHECK-NEXT: Age: 1
CHECK-NEXT: Guid: {0B355641-86A0-A249-896F-9988FAE52FF0}
CHECK-NEXT: }
-CHECK-NEXT: DBI Stream {
+CHECK: Type Info Stream (TPI) {
+CHECK-NEXT: TPI Version: 20040203
+CHECK-NEXT: Record count: 75
+CHECK: DBI Stream {
CHECK-NEXT: Dbi Version: 19990903
CHECK-NEXT: Age: 1
CHECK-NEXT: Incremental Linking: Yes
Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-write.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-write.test?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-write.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-write.test Fri Sep 9 12:46:17 2016
@@ -10,8 +10,8 @@
; stream metadata, since the layout of the MSF file might be different
; (for example if we don't write the entire stream)
;
-; RUN: llvm-pdbdump pdb2yaml -stream-metadata -stream-directory -pdb-stream %p/Inputs/empty.pdb > %t.1
+; RUN: llvm-pdbdump pdb2yaml -stream-metadata -stream-directory -pdb-stream -tpi-stream %p/Inputs/empty.pdb > %t.1
; RUN: llvm-pdbdump yaml2pdb -pdb=%t.2 %t.1
-; RUN: llvm-pdbdump pdb2yaml -pdb-stream %p/Inputs/empty.pdb > %t.3
-; RUN: llvm-pdbdump pdb2yaml -pdb-stream %t.2 > %t.4
+; RUN: llvm-pdbdump pdb2yaml -pdb-stream -tpi-stream %p/Inputs/empty.pdb > %t.3
+; RUN: llvm-pdbdump pdb2yaml -pdb-stream -tpi-stream %t.2 > %t.4
; RUN: diff %t.3 %t.4
Modified: llvm/trunk/tools/llvm-pdbdump/CodeViewYaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/CodeViewYaml.cpp?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/CodeViewYaml.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/CodeViewYaml.cpp Fri Sep 9 12:46:17 2016
@@ -9,6 +9,7 @@
#include "CodeViewYaml.h"
#include "PdbYaml.h"
+#include "YamlSerializationContext.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
@@ -269,34 +270,20 @@ template <> struct ScalarTraits<APSInt>
static bool mustQuote(StringRef Scalar) { return false; }
};
-void MappingContextTraits<CVType, YamlTypeDumperCallbacks>::mapping(
- IO &IO, CVType &Record, YamlTypeDumperCallbacks &Dumper) {
+void MappingContextTraits<CVType, pdb::yaml::SerializationContext>::mapping(
+ IO &IO, CVType &Record, pdb::yaml::SerializationContext &Context) {
if (IO.outputting()) {
codeview::TypeDeserializer Deserializer;
codeview::TypeVisitorCallbackPipeline Pipeline;
Pipeline.addCallbackToPipeline(Deserializer);
- Pipeline.addCallbackToPipeline(Dumper);
+ Pipeline.addCallbackToPipeline(Context.Dumper);
codeview::CVTypeVisitor Visitor(Pipeline);
consumeError(Visitor.visitTypeRecord(Record));
}
}
-void MappingContextTraits<FieldListRecord, YamlTypeDumperCallbacks>::mapping(
- IO &IO, FieldListRecord &FieldList, YamlTypeDumperCallbacks &Dumper) {
- if (IO.outputting()) {
- codeview::TypeDeserializer Deserializer;
-
- codeview::TypeVisitorCallbackPipeline Pipeline;
- Pipeline.addCallbackToPipeline(Deserializer);
- Pipeline.addCallbackToPipeline(Dumper);
-
- codeview::CVTypeVisitor Visitor(Pipeline);
- consumeError(Visitor.visitFieldListMemberStream(FieldList.Data));
- }
-}
-
void MappingTraits<StringIdRecord>::mapping(IO &IO, StringIdRecord &String) {
IO.mapRequired("Id", String.Id);
IO.mapRequired("String", String.String);
@@ -549,13 +536,23 @@ llvm::codeview::yaml::YamlTypeDumperCall
}
void llvm::codeview::yaml::YamlTypeDumperCallbacks::visitKnownRecordImpl(
- const char *Name, const CVType &Type, FieldListRecord &FieldList) {
-
- std::vector<llvm::pdb::yaml::PdbTpiRecord> Records;
+ const char *Name, const CVType &CVR, FieldListRecord &FieldList) {
+ std::vector<llvm::pdb::yaml::PdbTpiRecord> FieldListRecords;
if (YamlIO.outputting()) {
- FieldListRecordSplitter Splitter(Records);
+ // If we are outputting, then `FieldList.Data` contains a huge chunk of data
+ // representing the serialized list of members. We need to split it up into
+ // individual CVType records where each record represents an individual
+ // member. This way, we can simply map the entire thing as a Yaml sequence,
+ // which will recurse back to the standard handler for top-level fields
+ // (top-level and member fields all have the exact same Yaml syntax so use
+ // the same parser).
+ //
+ // If we are not outputting, then the array contains no data starting out,
+ // and is instead populated from the sequence represented by the yaml --
+ // again, using the same logic that we use for top-level records.
+ FieldListRecordSplitter Splitter(FieldListRecords);
CVTypeVisitor V(Splitter);
consumeError(V.visitFieldListMemberStream(FieldList.Data));
}
- YamlIO.mapRequired(Name, Records);
+ YamlIO.mapRequired("FieldList", FieldListRecords, Context);
}
Modified: llvm/trunk/tools/llvm-pdbdump/CodeViewYaml.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/CodeViewYaml.h?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/CodeViewYaml.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/CodeViewYaml.h Fri Sep 9 12:46:17 2016
@@ -11,15 +11,23 @@
#define LLVM_TOOLS_LLVMPDBDUMP_CODEVIEWYAML_H
#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/Support/YAMLTraits.h"
namespace llvm {
+namespace pdb {
+namespace yaml {
+struct SerializationContext;
+}
+}
namespace codeview {
namespace yaml {
class YamlTypeDumperCallbacks : public TypeVisitorCallbacks {
public:
- YamlTypeDumperCallbacks(llvm::yaml::IO &IO) : YamlIO(IO) {}
+ YamlTypeDumperCallbacks(llvm::yaml::IO &IO,
+ llvm::pdb::yaml::SerializationContext &Context)
+ : YamlIO(IO), Context(Context) {}
virtual Expected<TypeLeafKind>
visitTypeBegin(const CVRecord<TypeLeafKind> &Record) override;
@@ -42,13 +50,19 @@ private:
YamlIO.mapRequired(Name, Record);
}
- void visitKnownRecordImpl(const char *Name, const CVType &Type,
+ void visitKnownRecordImpl(const char *Name, const CVType &CVR,
FieldListRecord &FieldList);
llvm::yaml::IO &YamlIO;
+ llvm::pdb::yaml::SerializationContext &Context;
};
}
}
+namespace pdb {
+namespace yaml {
+struct SerializationContext;
+}
+}
}
namespace llvm {
@@ -58,10 +72,9 @@ template <> struct MappingTraits<codevie
};
template <>
-struct MappingContextTraits<codeview::CVType,
- codeview::yaml::YamlTypeDumperCallbacks> {
+struct MappingContextTraits<codeview::CVType, pdb::yaml::SerializationContext> {
static void mapping(IO &IO, codeview::CVType &Obj,
- codeview::yaml::YamlTypeDumperCallbacks &Context);
+ pdb::yaml::SerializationContext &Context);
};
template <> struct ScalarEnumerationTraits<codeview::TypeLeafKind> {
@@ -77,13 +90,6 @@ template <> struct ScalarEnumerationTrai
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
-
-template <>
-struct MappingContextTraits<codeview::FieldListRecord,
- codeview::yaml::YamlTypeDumperCallbacks> {
- static void mapping(IO &IO, codeview::FieldListRecord &Record,
- codeview::yaml::YamlTypeDumperCallbacks &Context);
-};
}
}
Modified: llvm/trunk/tools/llvm-pdbdump/PdbYaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PdbYaml.cpp?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PdbYaml.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/PdbYaml.cpp Fri Sep 9 12:46:17 2016
@@ -10,9 +10,11 @@
#include "PdbYaml.h"
#include "CodeViewYaml.h"
+#include "YamlSerializationContext.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeSerializationVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/PDB/PDBExtras.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
@@ -134,7 +136,7 @@ void MappingTraits<PdbObject>::mapping(I
IO.mapOptional("StreamMap", Obj.StreamMap);
IO.mapOptional("PdbStream", Obj.PdbStream);
IO.mapOptional("DbiStream", Obj.DbiStream);
- IO.mapOptional("TpiStream", Obj.TpiStream);
+ IO.mapOptionalWithContext("TpiStream", Obj.TpiStream, Obj.Allocator);
}
void MappingTraits<MSFHeaders>::mapping(IO &IO, MSFHeaders &Obj) {
@@ -181,10 +183,18 @@ void MappingTraits<PdbDbiStream>::mappin
IO.mapOptional("Modules", Obj.ModInfos);
}
-void MappingTraits<PdbTpiStream>::mapping(IO &IO,
- pdb::yaml::PdbTpiStream &Obj) {
+void MappingContextTraits<PdbTpiStream, BumpPtrAllocator>::mapping(
+ IO &IO, pdb::yaml::PdbTpiStream &Obj, BumpPtrAllocator &Allocator) {
+ // Create a single serialization context that will be passed through the
+ // entire process of serializing / deserializing a Tpi Stream. This is
+ // especially important when we are going from Pdb -> Yaml because we need
+ // to maintain state in a TypeTableBuilder across mappings, and at the end of
+ // the entire process, we need to have one TypeTableBuilder that has every
+ // record.
+ pdb::yaml::SerializationContext Context(IO, Allocator);
+
IO.mapRequired("Version", Obj.Version);
- IO.mapRequired("Records", Obj.Records);
+ IO.mapRequired("Records", Obj.Records, Context);
}
void MappingTraits<NamedStreamMapping>::mapping(IO &IO,
@@ -199,21 +209,40 @@ void MappingTraits<PdbDbiModuleInfo>::ma
IO.mapOptional("SourceFiles", Obj.SourceFiles);
}
-void MappingTraits<PdbTpiRecord>::mapping(IO &IO,
- pdb::yaml::PdbTpiRecord &Obj) {
- if (IO.outputting()) {
- codeview::TypeDeserializer Deserializer;
- codeview::yaml::YamlTypeDumperCallbacks Callbacks(IO);
+void MappingContextTraits<PdbTpiRecord, pdb::yaml::SerializationContext>::
+ mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj,
+ pdb::yaml::SerializationContext &Context) {
+ codeview::TypeVisitorCallbackPipeline Pipeline;
+ codeview::TypeDeserializer Deserializer;
+ codeview::TypeSerializationVisitor Serializer(Context.FieldListBuilder,
+ Context.TypeTableBuilder);
- codeview::TypeVisitorCallbackPipeline Pipeline;
+ if (IO.outputting()) {
+ // For PDB to Yaml, deserialize into a high level record type, then dump it.
Pipeline.addCallbackToPipeline(Deserializer);
- Pipeline.addCallbackToPipeline(Callbacks);
-
- codeview::CVTypeVisitor Visitor(Pipeline);
- consumeError(Visitor.visitTypeRecord(Obj.Record));
+ Pipeline.addCallbackToPipeline(Context.Dumper);
} else {
- codeview::yaml::YamlTypeDumperCallbacks Callbacks(IO);
- codeview::CVTypeVisitor Visitor(Callbacks);
- consumeError(Visitor.visitTypeRecord(Obj.Record));
+ // For Yaml to PDB, extract from the high level record type, then write it
+ // to bytes.
+ Pipeline.addCallbackToPipeline(Context.Dumper);
+ Pipeline.addCallbackToPipeline(Serializer);
+ }
+
+ codeview::CVTypeVisitor Visitor(Pipeline);
+ consumeError(Visitor.visitTypeRecord(Obj.Record));
+
+ if (!IO.outputting()) {
+ // For Yaml to PDB, we need to update the input Object with the bytes for
+ // this record.
+ ArrayRef<StringRef> Records = Context.TypeTableBuilder.getRecords();
+ ArrayRef<codeview::TypeRecordKind> Kinds =
+ Context.TypeTableBuilder.getRecordKinds();
+
+ StringRef ThisRecord = Records.back();
+ Obj.Record.Type = static_cast<codeview::TypeLeafKind>(Kinds.back());
+ Obj.Record.Data =
+ ArrayRef<uint8_t>(ThisRecord.bytes_begin(), ThisRecord.bytes_end());
+ Obj.Record.RawData = Obj.Record.Data;
+ Obj.Record.Length = ThisRecord.size();
}
}
Modified: llvm/trunk/tools/llvm-pdbdump/PdbYaml.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PdbYaml.h?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PdbYaml.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/PdbYaml.h Fri Sep 9 12:46:17 2016
@@ -26,6 +26,8 @@ namespace llvm {
namespace pdb {
namespace yaml {
+struct SerializationContext;
+
struct MSFHeaders {
msf::SuperBlock SuperBlock;
uint32_t NumDirectoryBlocks;
@@ -79,12 +81,16 @@ struct PdbTpiStream {
};
struct PdbObject {
+ explicit PdbObject(BumpPtrAllocator &Allocator) : Allocator(Allocator) {}
+
Optional<MSFHeaders> Headers;
Optional<std::vector<uint32_t>> StreamSizes;
Optional<std::vector<StreamBlockList>> StreamMap;
Optional<PdbInfoStream> PdbStream;
Optional<PdbDbiStream> DbiStream;
Optional<PdbTpiStream> TpiStream;
+
+ BumpPtrAllocator &Allocator;
};
}
}
@@ -117,8 +123,10 @@ template <> struct MappingTraits<pdb::ya
static void mapping(IO &IO, pdb::yaml::PdbDbiStream &Obj);
};
-template <> struct MappingTraits<pdb::yaml::PdbTpiStream> {
- static void mapping(IO &IO, pdb::yaml::PdbTpiStream &Obj);
+template <>
+struct MappingContextTraits<pdb::yaml::PdbTpiStream, llvm::BumpPtrAllocator> {
+ static void mapping(IO &IO, pdb::yaml::PdbTpiStream &Obj,
+ llvm::BumpPtrAllocator &Allocator);
};
template <> struct MappingTraits<pdb::yaml::NamedStreamMapping> {
@@ -129,8 +137,11 @@ template <> struct MappingTraits<pdb::ya
static void mapping(IO &IO, pdb::yaml::PdbDbiModuleInfo &Obj);
};
-template <> struct MappingTraits<pdb::yaml::PdbTpiRecord> {
- static void mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj);
+template <>
+struct MappingContextTraits<pdb::yaml::PdbTpiRecord,
+ pdb::yaml::SerializationContext> {
+ static void mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj,
+ pdb::yaml::SerializationContext &Context);
};
}
}
Modified: llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp Fri Sep 9 12:46:17 2016
@@ -21,7 +21,8 @@
using namespace llvm;
using namespace llvm::pdb;
-YAMLOutputStyle::YAMLOutputStyle(PDBFile &File) : File(File), Out(outs()) {}
+YAMLOutputStyle::YAMLOutputStyle(PDBFile &File)
+ : File(File), Out(outs()), Obj(File.getAllocator()) {}
Error YAMLOutputStyle::dump() {
if (opts::pdb2yaml::StreamDirectory)
Added: llvm/trunk/tools/llvm-pdbdump/YamlSerializationContext.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/YamlSerializationContext.h?rev=281063&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/YamlSerializationContext.h (added)
+++ llvm/trunk/tools/llvm-pdbdump/YamlSerializationContext.h Fri Sep 9 12:46:17 2016
@@ -0,0 +1,36 @@
+//===- YamlSerializationContext.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_TOOLS_LLVMPDBDUMP_YAMLSERIALIZATIONCONTEXT_H
+#define LLVM_TOOLS_LLVMPDBDUMP_YAMLSERIALIZATIONCONTEXT_H
+
+#include "CodeViewYaml.h"
+#include "PdbYaml.h"
+#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
+#include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h"
+
+namespace llvm {
+namespace yaml {
+class IO;
+}
+
+namespace pdb {
+namespace yaml {
+struct SerializationContext {
+ explicit SerializationContext(llvm::yaml::IO &IO, BumpPtrAllocator &Allocator)
+ : Dumper(IO, *this), TypeTableBuilder(Allocator) {}
+ codeview::yaml::YamlTypeDumperCallbacks Dumper;
+ codeview::MemoryTypeTableBuilder TypeTableBuilder;
+ codeview::FieldListRecordBuilder FieldListBuilder;
+};
+}
+}
+}
+
+#endif
\ No newline at end of file
Modified: llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp Fri Sep 9 12:46:17 2016
@@ -50,6 +50,8 @@
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/RawSession.h"
+#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
+#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h"
#include "llvm/Support/COM.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConvertUTF.h"
@@ -306,7 +308,7 @@ static void yamlToPdb(StringRef Path) {
std::unique_ptr<MemoryBuffer> &Buffer = ErrorOrBuffer.get();
llvm::yaml::Input In(Buffer->getBuffer());
- pdb::yaml::PdbObject YamlObj;
+ pdb::yaml::PdbObject YamlObj(Allocator);
In >> YamlObj;
if (!YamlObj.Headers.hasValue())
ExitOnErr(make_error<GenericError>(generic_error_code::unspecified,
@@ -382,6 +384,13 @@ static void yamlToPdb(StringRef Path) {
}
}
+ if (YamlObj.TpiStream.hasValue()) {
+ auto &TpiBuilder = Builder.getTpiBuilder();
+ TpiBuilder.setVersionHeader(YamlObj.TpiStream->Version);
+ for (const auto &R : YamlObj.TpiStream->Records)
+ TpiBuilder.addTypeRecord(R.Record);
+ }
+
ExitOnErr(Builder.commit(*FileByteStream));
}
Modified: llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp?rev=281063&r1=281062&r2=281063&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp Fri Sep 9 12:46:17 2016
@@ -331,8 +331,15 @@ static bool isMipsArch(unsigned Arch) {
return false;
}
}
-
-static llvm::codeview::MemoryTypeTableBuilder CVTypes;
+namespace {
+struct TypeTableBuilder {
+ TypeTableBuilder() : Allocator(), Builder(Allocator) {}
+
+ llvm::BumpPtrAllocator Allocator;
+ llvm::codeview::MemoryTypeTableBuilder Builder;
+};
+}
+static TypeTableBuilder CVTypes;
/// @brief Creates an format-specific object file dumper.
static std::error_code createDumper(const ObjectFile *Obj,
@@ -429,7 +436,7 @@ static void dumpObject(const ObjectFile
if (opts::CodeView)
Dumper->printCodeViewDebugInfo();
if (opts::CodeViewMergedTypes)
- Dumper->mergeCodeViewTypes(CVTypes);
+ Dumper->mergeCodeViewTypes(CVTypes.Builder);
}
if (Obj->isMachO()) {
if (opts::MachODataInCode)
@@ -534,7 +541,7 @@ int main(int argc, const char *argv[]) {
if (opts::CodeViewMergedTypes) {
ScopedPrinter W(outs());
- dumpCodeViewMergedTypes(W, CVTypes);
+ dumpCodeViewMergedTypes(W, CVTypes.Builder);
}
return 0;
More information about the llvm-commits
mailing list