summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2016-09-09 17:46:17 +0000
committerZachary Turner <zturner@google.com>2016-09-09 17:46:17 +0000
commitc6d54da891b5b7f6634d41a1c59eab4d5e226711 (patch)
tree5d14cccb65e640255902a1280afc4ff91ee13245 /llvm/lib
parentd938dfb308fe288605c6a24773ab77db8334c54a (diff)
downloadbcm5719-llvm-c6d54da891b5b7f6634d41a1c59eab4d5e226711.tar.gz
bcm5719-llvm-c6d54da891b5b7f6634d41a1c59eab4d5e226711.zip
[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 llvm-svn: 281063
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp3
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h1
-rw-r--r--llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp9
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp2
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp4
-rw-r--r--llvm/lib/DebugInfo/PDB/CMakeLists.txt3
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp25
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp109
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp95
9 files changed, 177 insertions, 74 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 52165773012..017fc208870 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -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") ||
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
index 2dc33235d80..729012bbd0f 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -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.
diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
index b4c3a9f4c21..f14a49c6ca2 100644
--- a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
+++ b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
@@ -81,14 +81,17 @@ Error CVTypeVisitor::visitTypeRecord(const CVRecord<TypeLeafKind> &Record) {
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(const CVRecord<TypeLeafKind> &Record) {
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
}
- if (auto EC = Callbacks.visitTypeEnd(Record))
+ if (auto EC = Callbacks.visitTypeEnd(RecordCopy))
return EC;
return Error::success();
diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
index 112612cc85e..88fbb233097 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
@@ -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);
}
diff --git a/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp b/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
index 0fcf4f92d43..45b9b3fe2da 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
@@ -257,7 +257,9 @@ TypeIndex TypeTableBuilder::writeKnownType(const BuildInfoRecord &Record) {
}
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) {
diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
index 126be38167b..76ab4d67628 100644
--- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
@@ -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")
diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
index 6e4bb16479f..ebe88dfa587 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
@@ -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::getDbiBuilder() {
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::finalizeMsfLayout() const {
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<msf::WritableStream> PdbFileBuffer) {
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::WritableStream &Buffer) {
return EC;
}
+ if (Tpi) {
+ if (auto EC = Tpi->commit(Layout, Buffer))
+ return EC;
+ }
+
return Buffer.commit();
} \ No newline at end of file
diff --git a/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp
index 6214e633b74..ce645eb592e 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp
@@ -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();
}
diff --git a/llvm/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp
new file mode 100644
index 00000000000..5591df5993e
--- /dev/null
+++ b/llvm/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp
@@ -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();
+}
OpenPOWER on IntegriCloud