}
static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
- codeview::TypeTableBuilder &TypeTable,
- std::vector<uint8_t> &Data) {
+ codeview::TypeTableBuilder &TypeTable) {
// Start the TPI or IPI stream header.
TpiBuilder.setVersionHeader(pdb::PdbTpiV80);
// Flatten the in memory type table.
- // FIXME: Avoid this copy.
TypeTable.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Rec) {
- Data.insert(Data.end(), Rec.begin(), Rec.end());
+ // FIXME: Hash types.
+ TpiBuilder.addTypeRecord(Rec, None);
});
-
- BinaryByteStream Stream(Data, support::little);
- codeview::CVTypeArray Records;
- BinaryStreamReader Reader(Stream);
- if (auto EC = Reader.readArray(Records, Reader.getLength()))
- fatal(EC, "Reader.readArray failed");
- for (const codeview::CVType &Rec : Records)
- TpiBuilder.addTypeRecord(Rec);
}
// Merge .debug$T sections into IpiData and TpiData.
static void mergeDebugT(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
- std::vector<uint8_t> &TpiData,
- std::vector<uint8_t> &IpiData) {
+ codeview::TypeTableBuilder &TypeTable,
+ codeview::TypeTableBuilder &IDTable) {
// Visit all .debug$T sections to add them to Builder.
- codeview::TypeTableBuilder IDTable(BAlloc);
- codeview::TypeTableBuilder TypeTable(BAlloc);
for (ObjectFile *File : Symtab->ObjectFiles) {
ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
if (Data.empty())
}
// Construct TPI stream contents.
- addTypeInfo(Builder.getTpiBuilder(), TypeTable, TpiData);
+ addTypeInfo(Builder.getTpiBuilder(), TypeTable);
// Construct IPI stream contents.
- addTypeInfo(Builder.getIpiBuilder(), IDTable, IpiData);
+ addTypeInfo(Builder.getIpiBuilder(), IDTable);
}
static void dumpDebugT(ScopedPrinter &W, ObjectFile *File) {
auto &DbiBuilder = Builder.getDbiBuilder();
DbiBuilder.setVersionHeader(pdb::PdbDbiV110);
- std::vector<uint8_t> TpiData;
- std::vector<uint8_t> IpiData;
- mergeDebugT(Symtab, Builder, TpiData, IpiData);
+ codeview::TypeTableBuilder TypeTable(BAlloc);
+ codeview::TypeTableBuilder IDTable(BAlloc);
+ mergeDebugT(Symtab, Builder, TypeTable, IDTable);
// Add Section Contributions.
std::vector<pdb::SectionContrib> Contribs =
TpiStreamBuilder &operator=(const TpiStreamBuilder &) = delete;
void setVersionHeader(PdbRaw_TpiVer Version);
- void addTypeRecord(const codeview::CVType &Record);
+ void addTypeRecord(ArrayRef<uint8_t> Type, Optional<uint32_t> Hash);
Error finalizeMsfLayout();
msf::MSFBuilder &Msf;
BumpPtrAllocator &Allocator;
+ size_t TypeRecordBytes = 0;
+
Optional<PdbRaw_TpiVer> VerHeader;
- std::vector<codeview::CVType> TypeRecords;
- BinaryItemStream<codeview::CVType> TypeRecordStream;
+ std::vector<ArrayRef<uint8_t>> TypeRecords;
+ std::vector<uint32_t> TypeHashes;
uint32_t HashStreamIndex = kInvalidStreamIndex;
std::unique_ptr<BinaryByteStream> HashValueStream;
using namespace llvm::support;
TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf, uint32_t StreamIdx)
- : Msf(Msf), Allocator(Msf.getAllocator()),
- TypeRecordStream(llvm::support::little), Header(nullptr), Idx(StreamIdx) {
+ : Msf(Msf), Allocator(Msf.getAllocator()), Header(nullptr), Idx(StreamIdx) {
}
TpiStreamBuilder::~TpiStreamBuilder() = default;
VerHeader = Version;
}
-void TpiStreamBuilder::addTypeRecord(const codeview::CVType &Record) {
+void TpiStreamBuilder::addTypeRecord(ArrayRef<uint8_t> Record,
+ Optional<uint32_t> Hash) {
+ TypeRecordBytes += Record.size();
TypeRecords.push_back(Record);
- TypeRecordStream.setItems(TypeRecords);
+ if (Hash)
+ TypeHashes.push_back(*Hash);
}
Error TpiStreamBuilder::finalize() {
H->HeaderSize = sizeof(TpiStreamHeader);
H->TypeIndexBegin = codeview::TypeIndex::FirstNonSimpleIndex;
H->TypeIndexEnd = H->TypeIndexBegin + Count;
- H->TypeRecordBytes = TypeRecordStream.getLength();
+ H->TypeRecordBytes = TypeRecordBytes;
H->HashStreamIndex = HashStreamIndex;
H->HashAuxStreamIndex = kInvalidStreamIndex;
}
uint32_t TpiStreamBuilder::calculateSerializedLength() {
- return sizeof(TpiStreamHeader) + TypeRecordStream.getLength();
+ return sizeof(TpiStreamHeader) + TypeRecordBytes;
}
uint32_t TpiStreamBuilder::calculateHashBufferSize() const {
- if (TypeRecords.empty() || !TypeRecords[0].Hash.hasValue())
- return 0;
- return TypeRecords.size() * sizeof(ulittle32_t);
+ assert(TypeHashes.size() == TypeHashes.size() &&
+ "either all or no type records should have hashes");
+ return TypeHashes.size() * sizeof(ulittle32_t);
}
Error TpiStreamBuilder::finalizeMsfLayout() {
if (!ExpectedIndex)
return ExpectedIndex.takeError();
HashStreamIndex = *ExpectedIndex;
- ulittle32_t *H = Allocator.Allocate<ulittle32_t>(TypeRecords.size());
- MutableArrayRef<ulittle32_t> HashBuffer(H, TypeRecords.size());
- for (uint32_t I = 0; I < TypeRecords.size(); ++I) {
- HashBuffer[I] = *TypeRecords[I].Hash % MinTpiHashBuckets;
+ ulittle32_t *H = Allocator.Allocate<ulittle32_t>(TypeHashes.size());
+ MutableArrayRef<ulittle32_t> HashBuffer(H, TypeHashes.size());
+ for (uint32_t I = 0; I < TypeHashes.size(); ++I) {
+ HashBuffer[I] = TypeHashes[I] % MinTpiHashBuckets;
}
ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(HashBuffer.data()),
HashBufferSize);
if (auto EC = Writer.writeObject(*Header))
return EC;
- auto RecordArray = VarStreamArray<codeview::CVType>(TypeRecordStream);
- if (auto EC = Writer.writeArray(RecordArray))
- return EC;
+ for (auto Rec : TypeRecords)
+ if (auto EC = Writer.writeBytes(Rec))
+ return EC;
if (HashStreamIndex != kInvalidStreamIndex) {
auto HVS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
const auto &Tpi = YamlObj.TpiStream.getValueOr(DefaultTpiStream);
TpiBuilder.setVersionHeader(Tpi.Version);
for (const auto &R : Tpi.Records)
- TpiBuilder.addTypeRecord(R.Record);
+ TpiBuilder.addTypeRecord(R.Record.data(), R.Record.Hash);
const auto &Ipi = YamlObj.IpiStream.getValueOr(DefaultTpiStream);
auto &IpiBuilder = Builder.getIpiBuilder();
IpiBuilder.setVersionHeader(Ipi.Version);
for (const auto &R : Ipi.Records)
- IpiBuilder.addTypeRecord(R.Record);
+ TpiBuilder.addTypeRecord(R.Record.data(), R.Record.Hash);
ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile));
}