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