LLVM  13.0.0git
TpiStream.cpp
Go to the documentation of this file.
1 //===- TpiStream.cpp - PDB Type Info (TPI) Stream 2 Access ----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 
24 #include "llvm/Support/Endian.h"
25 #include "llvm/Support/Error.h"
26 #include <algorithm>
27 #include <cstdint>
28 #include <vector>
29 
30 using namespace llvm;
31 using namespace llvm::codeview;
32 using namespace llvm::support;
33 using namespace llvm::msf;
34 using namespace llvm::pdb;
35 
36 TpiStream::TpiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
37  : Pdb(File), Stream(std::move(Stream)) {}
38 
39 TpiStream::~TpiStream() = default;
40 
42  BinaryStreamReader Reader(*Stream);
43 
44  if (Reader.bytesRemaining() < sizeof(TpiStreamHeader))
45  return make_error<RawError>(raw_error_code::corrupt_file,
46  "TPI Stream does not contain a header.");
47 
48  if (Reader.readObject(Header))
49  return make_error<RawError>(raw_error_code::corrupt_file,
50  "TPI Stream does not contain a header.");
51 
52  if (Header->Version != PdbTpiV80)
53  return make_error<RawError>(raw_error_code::corrupt_file,
54  "Unsupported TPI Version.");
55 
56  if (Header->HeaderSize != sizeof(TpiStreamHeader))
57  return make_error<RawError>(raw_error_code::corrupt_file,
58  "Corrupt TPI Header size.");
59 
60  if (Header->HashKeySize != sizeof(ulittle32_t))
61  return make_error<RawError>(raw_error_code::corrupt_file,
62  "TPI Stream expected 4 byte hash key size.");
63 
64  if (Header->NumHashBuckets < MinTpiHashBuckets ||
66  return make_error<RawError>(raw_error_code::corrupt_file,
67  "TPI Stream Invalid number of hash buckets.");
68 
69  // The actual type records themselves come from this stream
70  if (auto EC =
71  Reader.readSubstream(TypeRecordsSubstream, Header->TypeRecordBytes))
72  return EC;
73 
74  BinaryStreamReader RecordReader(TypeRecordsSubstream.StreamData);
75  if (auto EC =
76  RecordReader.readArray(TypeRecords, TypeRecordsSubstream.size()))
77  return EC;
78 
79  // Hash indices, hash values, etc come from the hash stream.
80  if (Header->HashStreamIndex != kInvalidStreamIndex) {
81  auto HS = Pdb.safelyCreateIndexedStream(Header->HashStreamIndex);
82  if (!HS) {
83  consumeError(HS.takeError());
84  return make_error<RawError>(raw_error_code::corrupt_file,
85  "Invalid TPI hash stream index.");
86  }
87  BinaryStreamReader HSR(**HS);
88 
89  // There should be a hash value for every type record, or no hashes at all.
90  uint32_t NumHashValues =
91  Header->HashValueBuffer.Length / sizeof(ulittle32_t);
92  if (NumHashValues != getNumTypeRecords() && NumHashValues != 0)
93  return make_error<RawError>(
95  "TPI hash count does not match with the number of type records.");
96  HSR.setOffset(Header->HashValueBuffer.Off);
97  if (auto EC = HSR.readArray(HashValues, NumHashValues))
98  return EC;
99 
100  HSR.setOffset(Header->IndexOffsetBuffer.Off);
101  uint32_t NumTypeIndexOffsets =
102  Header->IndexOffsetBuffer.Length / sizeof(TypeIndexOffset);
103  if (auto EC = HSR.readArray(TypeIndexOffsets, NumTypeIndexOffsets))
104  return EC;
105 
106  if (Header->HashAdjBuffer.Length > 0) {
107  HSR.setOffset(Header->HashAdjBuffer.Off);
108  if (auto EC = HashAdjusters.load(HSR))
109  return EC;
110  }
111 
112  HashStream = std::move(*HS);
113  }
114 
115  Types = std::make_unique<LazyRandomTypeCollection>(
116  TypeRecords, getNumTypeRecords(), getTypeIndexOffsets());
117  return Error::success();
118 }
119 
121  uint32_t Value = Header->Version;
122  return static_cast<PdbRaw_TpiVer>(Value);
123 }
124 
126 
127 uint32_t TpiStream::TypeIndexEnd() const { return Header->TypeIndexEnd; }
128 
130  return TypeIndexEnd() - TypeIndexBegin();
131 }
132 
134  return Header->HashStreamIndex;
135 }
136 
138  return Header->HashAuxStreamIndex;
139 }
140 
142 uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; }
143 
145  if (!HashMap.empty())
146  return;
147  if (HashValues.empty())
148  return;
149 
150  HashMap.resize(Header->NumHashBuckets);
151 
152  TypeIndex TIB{Header->TypeIndexBegin};
153  TypeIndex TIE{Header->TypeIndexEnd};
154  while (TIB < TIE) {
155  uint32_t HV = HashValues[TIB.toArrayIndex()];
156  HashMap[HV].push_back(TIB++);
157  }
158 }
159 
160 std::vector<TypeIndex> TpiStream::findRecordsByName(StringRef Name) const {
161  if (!supportsTypeLookup())
162  const_cast<TpiStream*>(this)->buildHashMap();
163 
164  uint32_t Bucket = hashStringV1(Name) % Header->NumHashBuckets;
165  if (Bucket > HashMap.size())
166  return {};
167 
168  std::vector<TypeIndex> Result;
169  for (TypeIndex TI : HashMap[Bucket]) {
170  std::string ThisName = computeTypeName(*Types, TI);
171  if (ThisName == Name)
172  Result.push_back(TI);
173  }
174  return Result;
175 }
176 
177 bool TpiStream::supportsTypeLookup() const { return !HashMap.empty(); }
178 
181  if (!supportsTypeLookup())
182  const_cast<TpiStream*>(this)->buildHashMap();
183 
184  CVType F = Types->getType(ForwardRefTI);
185  if (!isUdtForwardRef(F))
186  return ForwardRefTI;
187 
189  if (!ForwardTRH)
190  return ForwardTRH.takeError();
191 
192  uint32_t BucketIdx = ForwardTRH->FullRecordHash % Header->NumHashBuckets;
193 
194  for (TypeIndex TI : HashMap[BucketIdx]) {
195  CVType CVT = Types->getType(TI);
196  if (CVT.kind() != F.kind())
197  continue;
198 
199  Expected<TagRecordHash> FullTRH = hashTagRecord(CVT);
200  if (!FullTRH)
201  return FullTRH.takeError();
202  if (ForwardTRH->FullRecordHash != FullTRH->FullRecordHash)
203  continue;
204  TagRecord &ForwardTR = ForwardTRH->getRecord();
205  TagRecord &FullTR = FullTRH->getRecord();
206 
207  if (!ForwardTR.hasUniqueName()) {
208  if (ForwardTR.getName() == FullTR.getName())
209  return TI;
210  continue;
211  }
212 
213  if (!FullTR.hasUniqueName())
214  continue;
215  if (ForwardTR.getUniqueName() == FullTR.getUniqueName())
216  return TI;
217  }
218  return ForwardRefTI;
219 }
220 
222  assert(!Index.isSimple());
223  return Types->getType(Index);
224 }
225 
227  return TypeRecordsSubstream;
228 }
229 
231  return HashValues;
232 }
233 
235  return TypeIndexOffsets;
236 }
237 
239  return HashAdjusters;
240 }
241 
242 CVTypeRange TpiStream::types(bool *HadError) const {
243  return make_range(TypeRecords.begin(HadError), TypeRecords.end());
244 }
245 
BinaryStreamReader.h
llvm::BinaryStreamReader::bytesRemaining
uint32_t bytesRemaining() const
Definition: BinaryStreamReader.h:257
llvm::pdb::TpiStream::TypeIndexEnd
uint32_t TypeIndexEnd() const
Definition: TpiStream.cpp:127
RawConstants.h
llvm::codeview::TagRecord
Definition: TypeRecord.h:415
llvm
Definition: AllocatorList.h:23
llvm::codeview::computeTypeName
std::string computeTypeName(TypeCollection &Types, TypeIndex Index)
Definition: RecordName.cpp:250
llvm::make_range
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Definition: iterator_range.h:53
llvm::pdb::TpiStreamHeader::IndexOffsetBuffer
EmbeddedBuf IndexOffsetBuffer
Definition: RawTypes.h:296
llvm::codeview::TagRecord::hasUniqueName
bool hasUniqueName() const
Definition: TypeRecord.h:430
llvm::FixedStreamArray::empty
bool empty() const
Definition: BinaryStreamArray.h:300
llvm::codeview::TagRecord::getUniqueName
StringRef getUniqueName() const
Definition: TypeRecord.h:454
TpiStream.h
llvm::support::detail::packed_endian_specific_integral
Definition: Endian.h:206
RawTypes.h
llvm::pdb::TpiStream::supportsTypeLookup
bool supportsTypeLookup() const
Definition: TpiStream.cpp:177
llvm::pdb::TpiStream::getTypeRecordsSubstream
BinarySubstreamRef getTypeRecordsSubstream() const
Definition: TpiStream.cpp:226
llvm::pdb::TpiStream::getTypeHashStreamAuxIndex
uint16_t getTypeHashStreamAuxIndex() const
Definition: TpiStream.cpp:137
llvm::pdb::MaxTpiHashBuckets
const uint32_t MaxTpiHashBuckets
Definition: RawTypes.h:301
llvm::pdb::TpiStreamHeader::EmbeddedBuf::Length
support::ulittle32_t Length
Definition: RawTypes.h:280
llvm::pdb::TpiStreamHeader::HashStreamIndex
support::ulittle16_t HashStreamIndex
Definition: RawTypes.h:290
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:332
llvm::BinaryStreamReader::setOffset
void setOffset(uint32_t Off)
Definition: BinaryStreamReader.h:254
llvm::pdb::kInvalidStreamIndex
const uint16_t kInvalidStreamIndex
Definition: RawConstants.h:19
Error.h
llvm::pdb::TpiStream::getTypeHashStreamIndex
uint16_t getTypeHashStreamIndex() const
Definition: TpiStream.cpp:133
llvm::pdb::TpiStream::getTpiVersion
PdbRaw_TpiVer getTpiVersion() const
Definition: TpiStream.cpp:120
RecordName.h
llvm::codeview::isUdtForwardRef
bool isUdtForwardRef(CVType CVT)
Given an arbitrary codeview type, determine if it is an LF_STRUCTURE, LF_CLASS, LF_INTERFACE,...
Definition: TypeRecordHelpers.cpp:27
llvm::VarStreamArray::end
Iterator end() const
Definition: BinaryStreamArray.h:115
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
RawError.h
llvm::FixedStreamArray< support::ulittle32_t >
llvm::consumeError
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1006
llvm::pdb::PdbTpiV80
@ PdbTpiV80
Definition: RawConstants.h:64
llvm::pdb::TpiStreamHeader::HashKeySize
support::ulittle32_t HashKeySize
Definition: RawTypes.h:292
llvm::msf
Definition: IMSFFile.h:18
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::pdb::TpiStreamHeader::HashAuxStreamIndex
support::ulittle16_t HashAuxStreamIndex
Definition: RawTypes.h:291
llvm::pdb::TpiStream::reload
Error reload()
Definition: TpiStream.cpp:41
llvm::pdb::TpiStream::getHashAdjusters
HashTable< support::ulittle32_t > & getHashAdjusters()
Definition: TpiStream.cpp:238
llvm::pdb::raw_error_code::corrupt_file
@ corrupt_file
llvm::pdb::TpiStream::commit
Error commit()
Definition: TpiStream.cpp:246
LazyRandomTypeCollection.h
llvm::BinarySubstreamRef
Definition: BinaryStreamRef.h:200
llvm::pdb::hashTagRecord
Expected< TagRecordHash > hashTagRecord(const codeview::CVType &Type)
Given a CVType referring to a class, structure, union, or enum, compute the hash of its forward decl ...
Definition: TpiHashing.cpp:88
llvm::pdb::PDBFile::safelyCreateIndexedStream
Expected< std::unique_ptr< msf::MappedBlockStream > > safelyCreateIndexedStream(uint32_t StreamIndex) const
Wrapper around MappedBlockStream::createIndexedStream() that checks if a stream with that index actua...
Definition: PDBFile.cpp:489
llvm::BinarySubstreamRef::StreamData
BinaryStreamRef StreamData
Definition: BinaryStreamRef.h:202
llvm::pdb::PdbRaw_TpiVer
PdbRaw_TpiVer
Definition: RawConstants.h:59
llvm::AArch64CC::HS
@ HS
Definition: AArch64BaseInfo.h:238
llvm::pdb::TpiStream::getType
codeview::CVType getType(codeview::TypeIndex Index)
Definition: TpiStream.cpp:221
llvm::BinaryStreamReader::readSubstream
Error readSubstream(BinarySubstreamRef &Ref, uint32_t Length)
Read Length bytes from the underlying stream into Ref.
Definition: BinaryStreamReader.cpp:142
llvm::codeview::CodeViewContainer::Pdb
@ Pdb
llvm::pdb
Definition: ConcreteSymbolEnumerator.h:20
llvm::BinaryStreamReader
Provides read only access to a subclass of BinaryStream.
Definition: BinaryStreamReader.h:31
llvm::support::ulittle32_t
detail::packed_endian_specific_integral< uint32_t, little, unaligned > ulittle32_t
Definition: Endian.h:272
llvm::codeview::TagRecord::getName
StringRef getName() const
Definition: TypeRecord.h:453
llvm::pdb::TpiStream::getHashValues
FixedStreamArray< support::ulittle32_t > getHashValues() const
Definition: TpiStream.cpp:230
llvm::pdb::TpiStreamHeader::NumHashBuckets
support::ulittle32_t NumHashBuckets
Definition: RawTypes.h:293
Index
uint32_t Index
Definition: ELFObjHandler.cpp:84
TypeRecord.h
llvm::pdb::TpiStream::TypeIndexBegin
uint32_t TypeIndexBegin() const
Definition: TpiStream.cpp:125
llvm::BinarySubstreamRef::size
uint32_t size() const
Definition: BinaryStreamRef.h:218
llvm::codeview::CVRecord::kind
Kind kind() const
Definition: CVRecord.h:43
llvm::pdb::TpiStreamHeader::HashAdjBuffer
EmbeddedBuf HashAdjBuffer
Definition: RawTypes.h:297
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::pdb::TpiStream::getHashKeySize
uint32_t getHashKeySize() const
Definition: TpiStream.cpp:142
TpiHashing.h
llvm::pdb::TpiStreamHeader::TypeIndexBegin
support::ulittle32_t TypeIndexBegin
Definition: RawTypes.h:285
MappedBlockStream.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1540
TypeRecordHelpers.h
llvm::codeview::CompileSym2Flags::EC
@ EC
iterator_range.h
llvm::BinaryStreamReader::readObject
Error readObject(const T *&Dest)
Get a pointer to an object of type T from the underlying stream, as if by memcpy, and store the resul...
Definition: BinaryStreamReader.h:169
llvm::pdb::TpiStream::buildHashMap
void buildHashMap()
Definition: TpiStream.cpp:144
llvm::pdb::TpiStreamHeader::HashValueBuffer
EmbeddedBuf HashValueBuffer
Definition: RawTypes.h:295
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::codeview::CVRecord< TypeLeafKind >
uint32_t
llvm::VarStreamArray::begin
Iterator begin(bool *HadError=nullptr) const
Definition: BinaryStreamArray.h:108
llvm::pdb::TpiStream::findFullDeclForForwardRef
Expected< codeview::TypeIndex > findFullDeclForForwardRef(codeview::TypeIndex ForwardRefTI) const
Definition: TpiStream.cpp:180
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
std
Definition: BitVector.h:838
llvm::pdb::TpiStream::getNumHashBuckets
uint32_t getNumHashBuckets() const
Definition: TpiStream.cpp:141
uint16_t
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::support
Definition: Endian.h:25
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::pdb::HashTable
Definition: HashTable.h:34
llvm::pdb::TpiStreamHeader::HeaderSize
support::ulittle32_t HeaderSize
Definition: RawTypes.h:284
llvm::codeview
Definition: AppendingTypeTableBuilder.h:22
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:557
llvm::pdb::TpiStream::getNumTypeRecords
uint32_t getNumTypeRecords() const
Definition: TpiStream.cpp:129
llvm::pdb::PDBFile
Definition: PDBFile.h:42
PDBFile.h
llvm::pdb::TpiStreamHeader
Definition: RawTypes.h:277
llvm::pdb::TpiStream
Definition: TpiStream.h:33
llvm::pdb::TpiStreamHeader::TypeIndexEnd
support::ulittle32_t TypeIndexEnd
Definition: RawTypes.h:286
llvm::iterator_range
A range adaptor for a pair of iterators.
Definition: iterator_range.h:30
llvm::pdb::MinTpiHashBuckets
const uint32_t MinTpiHashBuckets
Definition: RawTypes.h:300
Hash.h
llvm::codeview::TypeIndex
A 32-bit type reference.
Definition: TypeIndex.h:95
llvm::pdb::TpiStream::types
codeview::CVTypeRange types(bool *HadError) const
Definition: TpiStream.cpp:242
llvm::codeview::TypeIndexOffset
Definition: TypeIndex.h:281
llvm::pdb::TpiStream::findRecordsByName
std::vector< codeview::TypeIndex > findRecordsByName(StringRef Name) const
Definition: TpiStream.cpp:160
llvm::pdb::TpiStreamHeader::Version
support::ulittle32_t Version
Definition: RawTypes.h:283
Endian.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::pdb::TpiStream::~TpiStream
~TpiStream()
File
Instrumentation for Order File
Definition: InstrOrderFile.cpp:206
llvm::pdb::TpiStreamHeader::EmbeddedBuf::Off
support::little32_t Off
Definition: RawTypes.h:279
llvm::BinaryStreamReader::readArray
Error readArray(ArrayRef< T > &Array, uint32_t NumElements)
Get a reference to a NumElements element array of objects of type T from the underlying stream as if ...
Definition: BinaryStreamReader.h:187
llvm::pdb::TpiStreamHeader::TypeRecordBytes
support::ulittle32_t TypeRecordBytes
Definition: RawTypes.h:287
llvm::pdb::TpiStream::getTypeIndexOffsets
FixedStreamArray< codeview::TypeIndexOffset > getTypeIndexOffsets() const
Definition: TpiStream.cpp:234
llvm::pdb::hashStringV1
uint32_t hashStringV1(StringRef Str)
Definition: Hash.cpp:20