blob: 5591df5993e6a35b61e05d266a11576bcef481e0 [file] [log] [blame]
Zachary Turnerc6d54da2016-09-09 17:46:17 +00001#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h"
2
3#include "llvm/DebugInfo/CodeView/TypeIndex.h"
4#include "llvm/DebugInfo/CodeView/TypeRecord.h"
5#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
6#include "llvm/DebugInfo/MSF/StreamWriter.h"
7#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
8#include "llvm/DebugInfo/PDB/Raw/RawError.h"
9#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
10#include "llvm/Support/Allocator.h"
11
12using namespace llvm;
13using namespace llvm::msf;
14using namespace llvm::pdb;
15using namespace llvm::support;
16
17TpiStreamBuilder::TpiStreamBuilder(BumpPtrAllocator &Allocator)
18 : Allocator(Allocator), Header(nullptr) {}
19
20TpiStreamBuilder::~TpiStreamBuilder() {}
21
22void TpiStreamBuilder::setVersionHeader(PdbRaw_TpiVer Version) {
23 VerHeader = Version;
24}
25
26void TpiStreamBuilder::addTypeRecord(const codeview::CVType &Record) {
27 TypeRecords.push_back(Record);
28 TypeRecordStream.setItems(TypeRecords);
29}
30
31Error TpiStreamBuilder::finalize() {
32 if (Header)
33 return Error::success();
34
35 TpiStreamHeader *H = Allocator.Allocate<TpiStreamHeader>();
36
37 uint32_t Count = TypeRecords.size();
38
39 H->Version = *VerHeader;
40 H->HeaderSize = sizeof(TpiStreamHeader);
41 H->TypeIndexBegin = codeview::TypeIndex::FirstNonSimpleIndex;
42 H->TypeIndexEnd = H->TypeIndexBegin + Count;
43 H->TypeRecordBytes = TypeRecordStream.getLength();
44
45 H->HashStreamIndex = kInvalidStreamIndex;
46 H->HashAuxStreamIndex = kInvalidStreamIndex;
47 H->HashKeySize = sizeof(ulittle32_t);
48 H->NumHashBuckets = MinTpiHashBuckets;
49
50 H->HashValueBuffer.Length = 0;
51 H->HashAdjBuffer.Length = 0;
52 H->IndexOffsetBuffer.Length = 0;
53
54 Header = H;
55 return Error::success();
56}
57
58uint32_t TpiStreamBuilder::calculateSerializedLength() const {
59 return sizeof(TpiStreamHeader) + TypeRecordStream.getLength();
60}
61
62Expected<std::unique_ptr<TpiStream>>
63TpiStreamBuilder::build(PDBFile &File, const msf::WritableStream &Buffer) {
64 if (!VerHeader.hasValue())
65 return make_error<RawError>(raw_error_code::unspecified,
66 "Missing TPI Stream Version");
67 if (auto EC = finalize())
68 return std::move(EC);
69
70 auto StreamData = MappedBlockStream::createIndexedStream(File.getMsfLayout(),
71 Buffer, StreamTPI);
72 auto Tpi = llvm::make_unique<TpiStream>(File, std::move(StreamData));
73 Tpi->Header = Header;
74 Tpi->TypeRecords = VarStreamArray<codeview::CVType>(TypeRecordStream);
75 return std::move(Tpi);
76}
77
78Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout,
79 const msf::WritableStream &Buffer) {
80 if (auto EC = finalize())
81 return EC;
82
83 auto InfoS =
84 WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamTPI);
85
86 StreamWriter Writer(*InfoS);
87 if (auto EC = Writer.writeObject(*Header))
88 return EC;
89
90 auto RecordArray = VarStreamArray<codeview::CVType>(TypeRecordStream);
91 if (auto EC = Writer.writeArray(RecordArray))
92 return EC;
93
94 return Error::success();
95}