LLVM  10.0.0svn
GlobalsStream.cpp
Go to the documentation of this file.
1 //===- GlobalsStream.cpp - PDB Index of Symbols by Name ---------*- C++ -*-===//
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 //
9 // The on-disk structores used in this file are based on the reference
10 // implementation which is available at
11 // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
12 //
13 // When you are reading the reference source code, you'd find the
14 // information below useful.
15 //
16 // - ppdb1->m_fMinimalDbgInfo seems to be always true.
17 // - SMALLBUCKETS macro is defined.
18 //
19 //===----------------------------------------------------------------------===//
20 
22 
28 #include "llvm/Support/Error.h"
29 #include <algorithm>
30 
31 using namespace llvm;
32 using namespace llvm::msf;
33 using namespace llvm::pdb;
34 
35 GlobalsStream::GlobalsStream(std::unique_ptr<MappedBlockStream> Stream)
36  : Stream(std::move(Stream)) {}
37 
39 
41  BinaryStreamReader Reader(*Stream);
42  if (auto E = GlobalsTable.read(Reader))
43  return E;
44  return Error::success();
45 }
46 
47 std::vector<std::pair<uint32_t, codeview::CVSymbol>>
49  const SymbolStream &Symbols) const {
50  std::vector<std::pair<uint32_t, codeview::CVSymbol>> Result;
51 
52  // Hash the name to figure out which bucket this goes into.
53  size_t ExpandedBucketIndex = hashStringV1(Name) % IPHR_HASH;
54  int32_t CompressedBucketIndex = GlobalsTable.BucketMap[ExpandedBucketIndex];
55  if (CompressedBucketIndex == -1)
56  return Result;
57 
58  uint32_t LastBucketIndex = GlobalsTable.HashBuckets.size() - 1;
59  uint32_t StartRecordIndex =
60  GlobalsTable.HashBuckets[CompressedBucketIndex] / 12;
61  uint32_t EndRecordIndex = 0;
62  if (LLVM_LIKELY(uint32_t(CompressedBucketIndex) < LastBucketIndex)) {
63  EndRecordIndex = GlobalsTable.HashBuckets[CompressedBucketIndex + 1];
64  } else {
65  // If this is the last bucket, it consists of all hash records until the end
66  // of the HashRecords array.
67  EndRecordIndex = GlobalsTable.HashRecords.size() * 12;
68  }
69 
70  EndRecordIndex /= 12;
71 
72  assert(EndRecordIndex <= GlobalsTable.HashRecords.size());
73  while (StartRecordIndex < EndRecordIndex) {
74  PSHashRecord PSH = GlobalsTable.HashRecords[StartRecordIndex];
75  uint32_t Off = PSH.Off - 1;
76  codeview::CVSymbol Record = Symbols.readRecord(Off);
77  if (codeview::getSymbolName(Record) == Name)
78  Result.push_back(std::make_pair(Off, std::move(Record)));
79  ++StartRecordIndex;
80  }
81  return Result;
82 }
83 
84 static Error checkHashHdrVersion(const GSIHashHeader *HashHdr) {
85  if (HashHdr->VerHdr != GSIHashHeader::HdrVersion)
86  return make_error<RawError>(
88  "Encountered unsupported globals stream version.");
89 
90  return Error::success();
91 }
92 
93 static Error readGSIHashHeader(const GSIHashHeader *&HashHdr,
94  BinaryStreamReader &Reader) {
95  if (Reader.readObject(HashHdr))
96  return make_error<RawError>(raw_error_code::corrupt_file,
97  "Stream does not contain a GSIHashHeader.");
98 
100  return make_error<RawError>(
102  "GSIHashHeader signature (0xffffffff) not found.");
103 
104  return Error::success();
105 }
106 
108  const GSIHashHeader *HashHdr,
109  BinaryStreamReader &Reader) {
110  if (auto EC = checkHashHdrVersion(HashHdr))
111  return EC;
112 
113  // HashHdr->HrSize specifies the number of bytes of PSHashRecords we have.
114  // Verify that we can read them all.
115  if (HashHdr->HrSize % sizeof(PSHashRecord))
116  return make_error<RawError>(raw_error_code::corrupt_file,
117  "Invalid HR array size.");
118  uint32_t NumHashRecords = HashHdr->HrSize / sizeof(PSHashRecord);
119  if (auto EC = Reader.readArray(HashRecords, NumHashRecords))
120  return joinErrors(std::move(EC),
121  make_error<RawError>(raw_error_code::corrupt_file,
122  "Error reading hash records."));
123 
124  return Error::success();
125 }
126 
127 static Error
130  const GSIHashHeader *HashHdr,
131  MutableArrayRef<int32_t> BucketMap,
132  BinaryStreamReader &Reader) {
133  if (auto EC = checkHashHdrVersion(HashHdr))
134  return EC;
135 
136  // Before the actual hash buckets, there is a bitmap of length determined by
137  // IPHR_HASH.
138  size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32);
139  uint32_t NumBitmapEntries = BitmapSizeInBits / 32;
140  if (auto EC = Reader.readArray(HashBitmap, NumBitmapEntries))
141  return joinErrors(std::move(EC),
142  make_error<RawError>(raw_error_code::corrupt_file,
143  "Could not read a bitmap."));
144  uint32_t NumBuckets1 = 0;
145  uint32_t CompressedBucketIdx = 0;
146  for (uint32_t I = 0; I <= IPHR_HASH; ++I) {
147  uint8_t WordIdx = I / 32;
148  uint8_t BitIdx = I % 32;
149  bool IsSet = HashBitmap[WordIdx] & (1U << BitIdx);
150  if (IsSet) {
151  ++NumBuckets1;
152  BucketMap[I] = CompressedBucketIdx++;
153  } else {
154  BucketMap[I] = -1;
155  }
156  }
157 
158  uint32_t NumBuckets = 0;
159  for (uint32_t B : HashBitmap)
160  NumBuckets += countPopulation(B);
161 
162  // Hash buckets follow.
163  if (auto EC = Reader.readArray(HashBuckets, NumBuckets))
164  return joinErrors(std::move(EC),
165  make_error<RawError>(raw_error_code::corrupt_file,
166  "Hash buckets corrupted."));
167 
168  return Error::success();
169 }
170 
172  if (auto EC = readGSIHashHeader(HashHdr, Reader))
173  return EC;
174  if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader))
175  return EC;
176  if (HashHdr->HrSize > 0)
177  if (auto EC = readGSIHashBuckets(HashBuckets, HashBitmap, HashHdr,
178  BucketMap, Reader))
179  return EC;
180  return Error::success();
181 }
static Error readGSIHashBuckets(FixedStreamArray< support::ulittle32_t > &HashBuckets, FixedStreamArray< support::ulittle32_t > &HashBitmap, const GSIHashHeader *HashHdr, MutableArrayRef< int32_t > BucketMap, BinaryStreamReader &Reader)
support::ulittle32_t VerSignature
Definition: RawTypes.h:33
This class represents lattice values for constants.
Definition: AllocatorList.h:23
#define LLVM_LIKELY(EXPR)
Definition: Compiler.h:211
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
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...
support::ulittle32_t VerHdr
Definition: RawTypes.h:34
Definition: BitVector.h:937
static Error checkHashHdrVersion(const GSIHashHeader *HashHdr)
Header of the hash tables found in the globals and publics sections.
Definition: RawTypes.h:28
std::vector< std::pair< uint32_t, codeview::CVSymbol > > findRecordsByName(StringRef Name, const SymbolStream &Symbols) const
support::ulittle32_t Off
Definition: RawTypes.h:41
Error read(BinaryStreamReader &Reader)
std::array< int32_t, IPHR_HASH+1 > BucketMap
Definition: GlobalsStream.h:56
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:290
uint32_t hashStringV1(StringRef Str)
Definition: Hash.cpp:20
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static Error readGSIHashRecords(FixedStreamArray< PSHashRecord > &HashRecords, const GSIHashHeader *HashHdr, BinaryStreamReader &Reader)
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
unsigned countPopulation(T Value)
Count the number of set bits in a value.
Definition: MathExtras.h:556
FixedStreamArray< support::ulittle32_t > HashBuckets
Definition: GlobalsStream.h:55
codeview::CVSymbol readRecord(uint32_t Offset) const
static Error readGSIHashHeader(const GSIHashHeader *&HashHdr, BinaryStreamReader &Reader)
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:163
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:423
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
FixedStreamArray< PSHashRecord > HashRecords
Definition: GlobalsStream.h:53
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
Provides read only access to a subclass of BinaryStream.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
support::ulittle32_t HrSize
Definition: RawTypes.h:35
CVRecord is a fat pointer (base + size pair) to a symbol or type record.
Definition: CVRecord.h:30
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 ...
StringRef getSymbolName(CVSymbol Sym)
Definition: RecordName.cpp:317