diff options
author | Zachary Turner <zturner@google.com> | 2016-09-09 17:46:17 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2016-09-09 17:46:17 +0000 |
commit | c6d54da891b5b7f6634d41a1c59eab4d5e226711 (patch) | |
tree | 5d14cccb65e640255902a1280afc4ff91ee13245 /llvm/lib | |
parent | d938dfb308fe288605c6a24773ab77db8334c54a (diff) | |
download | bcm5719-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.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h | 1 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/CMakeLists.txt | 3 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp | 25 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp | 109 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp | 95 |
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(); +} |