blob: 28c3d64e882fb423188faecb956745cb538702aa [file] [log] [blame]
Zachary Turnerf5c59652016-05-03 00:28:21 +00001//===- TpiStream.cpp - PDB Type Info (TPI) Stream 2 Access ----------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
11
12#include "llvm/DebugInfo/CodeView/CodeView.h"
Zachary Turnerd5d37dc2016-05-25 20:37:03 +000013#include "llvm/DebugInfo/CodeView/StreamReader.h"
Zachary Turnerf5c59652016-05-03 00:28:21 +000014#include "llvm/DebugInfo/CodeView/TypeRecord.h"
15#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
Zachary Turner90b8b8d2016-05-31 22:41:52 +000016#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
Zachary Turnerf5c59652016-05-03 00:28:21 +000017#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
Zachary Turner819e77d2016-05-06 20:51:57 +000018#include "llvm/DebugInfo/PDB/Raw/RawError.h"
Zachary Turnerf5c59652016-05-03 00:28:21 +000019
20#include "llvm/Support/Endian.h"
21
22using namespace llvm;
23using namespace llvm::support;
24using namespace llvm::pdb;
25
26namespace {
Zachary Turnerf5c59652016-05-03 00:28:21 +000027const uint32_t MinHashBuckets = 0x1000;
28const uint32_t MaxHashBuckets = 0x40000;
29}
30
31static uint32_t HashBufferV8(uint8_t *buffer, uint32_t NumBuckets) {
32 // Not yet implemented, this is probably some variation of CRC32 but we need
33 // to be sure of the precise implementation otherwise we won't be able to work
34 // with persisted hash values.
35 return 0;
36}
37
38struct TpiStream::HeaderInfo {
39 struct EmbeddedBuf {
40 little32_t Off;
41 ulittle32_t Length;
42 };
43
44 ulittle32_t Version;
45 ulittle32_t HeaderSize;
46 ulittle32_t TypeIndexBegin;
47 ulittle32_t TypeIndexEnd;
48 ulittle32_t TypeRecordBytes;
49
50 ulittle16_t HashStreamIndex;
51 ulittle16_t HashAuxStreamIndex;
52 ulittle32_t HashKeySize;
53 ulittle32_t NumHashBuckets;
54
55 EmbeddedBuf HashValueBuffer;
56 EmbeddedBuf IndexOffsetBuffer;
57 EmbeddedBuf HashAdjBuffer;
58};
59
Zachary Turnerc9972c62016-05-25 04:35:22 +000060TpiStream::TpiStream(PDBFile &File, uint32_t StreamIdx)
61 : Pdb(File), Stream(StreamIdx, File), HashFunction(nullptr) {}
Zachary Turnerf5c59652016-05-03 00:28:21 +000062
63TpiStream::~TpiStream() {}
64
Zachary Turner819e77d2016-05-06 20:51:57 +000065Error TpiStream::reload() {
Zachary Turnerd5d37dc2016-05-25 20:37:03 +000066 codeview::StreamReader Reader(Stream);
Zachary Turnerf5c59652016-05-03 00:28:21 +000067
68 if (Reader.bytesRemaining() < sizeof(HeaderInfo))
Zachary Turner819e77d2016-05-06 20:51:57 +000069 return make_error<RawError>(raw_error_code::corrupt_file,
70 "TPI Stream does not contain a header.");
Zachary Turnerf5c59652016-05-03 00:28:21 +000071
Zachary Turner8dbe3622016-05-27 01:54:44 +000072 if (Reader.readObject(Header))
Zachary Turner819e77d2016-05-06 20:51:57 +000073 return make_error<RawError>(raw_error_code::corrupt_file,
74 "TPI Stream does not contain a header.");
Zachary Turnerf5c59652016-05-03 00:28:21 +000075
76 if (Header->Version != PdbTpiV80)
Zachary Turner819e77d2016-05-06 20:51:57 +000077 return make_error<RawError>(raw_error_code::corrupt_file,
78 "Unsupported TPI Version.");
Zachary Turnerf5c59652016-05-03 00:28:21 +000079
80 if (Header->HeaderSize != sizeof(HeaderInfo))
Zachary Turner819e77d2016-05-06 20:51:57 +000081 return make_error<RawError>(raw_error_code::corrupt_file,
82 "Corrupt TPI Header size.");
Zachary Turnerf5c59652016-05-03 00:28:21 +000083
84 if (Header->HashKeySize != sizeof(ulittle32_t))
Zachary Turner819e77d2016-05-06 20:51:57 +000085 return make_error<RawError>(raw_error_code::corrupt_file,
86 "TPI Stream expected 4 byte hash key size.");
Zachary Turnerf5c59652016-05-03 00:28:21 +000087
88 if (Header->NumHashBuckets < MinHashBuckets ||
89 Header->NumHashBuckets > MaxHashBuckets)
Zachary Turner819e77d2016-05-06 20:51:57 +000090 return make_error<RawError>(raw_error_code::corrupt_file,
91 "TPI Stream Invalid number of hash buckets.");
Zachary Turnerf5c59652016-05-03 00:28:21 +000092
93 HashFunction = HashBufferV8;
94
95 // The actual type records themselves come from this stream
Zachary Turner0d43c1c2016-05-28 05:21:57 +000096 if (auto EC = Reader.readArray(TypeRecords, Header->TypeRecordBytes))
Zachary Turner819e77d2016-05-06 20:51:57 +000097 return EC;
Zachary Turnerf5c59652016-05-03 00:28:21 +000098
99 // Hash indices, hash values, etc come from the hash stream.
100 MappedBlockStream HS(Header->HashStreamIndex, Pdb);
Zachary Turnerd5d37dc2016-05-25 20:37:03 +0000101 codeview::StreamReader HSR(HS);
Zachary Turnerf5c59652016-05-03 00:28:21 +0000102 HSR.setOffset(Header->HashValueBuffer.Off);
Zachary Turner819e77d2016-05-06 20:51:57 +0000103 if (auto EC =
Zachary Turner8dbe3622016-05-27 01:54:44 +0000104 HSR.readStreamRef(HashValuesBuffer, Header->HashValueBuffer.Length))
Zachary Turner819e77d2016-05-06 20:51:57 +0000105 return EC;
Zachary Turnerf5c59652016-05-03 00:28:21 +0000106
107 HSR.setOffset(Header->HashAdjBuffer.Off);
Zachary Turner8dbe3622016-05-27 01:54:44 +0000108 if (auto EC = HSR.readStreamRef(HashAdjBuffer, Header->HashAdjBuffer.Length))
Zachary Turner819e77d2016-05-06 20:51:57 +0000109 return EC;
Zachary Turnerf5c59652016-05-03 00:28:21 +0000110
111 HSR.setOffset(Header->IndexOffsetBuffer.Off);
Zachary Turner8dbe3622016-05-27 01:54:44 +0000112 if (auto EC = HSR.readStreamRef(TypeIndexOffsetBuffer,
113 Header->IndexOffsetBuffer.Length))
Zachary Turner819e77d2016-05-06 20:51:57 +0000114 return EC;
Zachary Turnerf5c59652016-05-03 00:28:21 +0000115
Zachary Turner819e77d2016-05-06 20:51:57 +0000116 return Error::success();
Zachary Turnerf5c59652016-05-03 00:28:21 +0000117}
118
119PdbRaw_TpiVer TpiStream::getTpiVersion() const {
120 uint32_t Value = Header->Version;
121 return static_cast<PdbRaw_TpiVer>(Value);
122}
123
124uint32_t TpiStream::TypeIndexBegin() const { return Header->TypeIndexBegin; }
125
126uint32_t TpiStream::TypeIndexEnd() const { return Header->TypeIndexEnd; }
127
128uint32_t TpiStream::NumTypeRecords() const {
129 return TypeIndexEnd() - TypeIndexBegin();
130}
131
Zachary Turner85ed80b2016-05-25 03:43:17 +0000132uint16_t TpiStream::getTypeHashStreamIndex() const {
133 return Header->HashStreamIndex;
134}
135
136uint16_t TpiStream::getTypeHashStreamAuxIndex() const {
137 return Header->HashAuxStreamIndex;
138}
139
Zachary Turner0d43c1c2016-05-28 05:21:57 +0000140iterator_range<codeview::CVTypeArray::Iterator>
141TpiStream::types(bool *HadError) const {
142 return llvm::make_range(TypeRecords.begin(HadError), TypeRecords.end());
Zachary Turnerf5c59652016-05-03 00:28:21 +0000143}