LLVM  15.0.0git
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 
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);
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 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  BucketMap[I] = CompressedBucketIdx++;
152  } else {
153  BucketMap[I] = -1;
154  }
155  }
156 
157  uint32_t NumBuckets = 0;
158  for (uint32_t B : HashBitmap)
159  NumBuckets += countPopulation(B);
160 
161  // Hash buckets follow.
162  if (auto EC = Reader.readArray(HashBuckets, NumBuckets))
163  return joinErrors(std::move(EC),
164  make_error<RawError>(raw_error_code::corrupt_file,
165  "Hash buckets corrupted."));
166 
167  return Error::success();
168 }
169 
171  if (auto EC = readGSIHashHeader(HashHdr, Reader))
172  return EC;
173  if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader))
174  return EC;
175  if (HashHdr->HrSize > 0)
177  BucketMap, Reader))
178  return EC;
179  return Error::success();
180 }
llvm::alignTo
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:156
llvm::pdb::GSIHashTable::HashBuckets
FixedStreamArray< support::ulittle32_t > HashBuckets
Definition: GlobalsStream.h:55
BinaryStreamReader.h
llvm::pdb::GSIHashTable::HashBitmap
FixedStreamArray< support::ulittle32_t > HashBitmap
Definition: GlobalsStream.h:54
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
readGSIHashBuckets
static Error readGSIHashBuckets(FixedStreamArray< support::ulittle32_t > &HashBuckets, FixedStreamArray< support::ulittle32_t > &HashBitmap, const GSIHashHeader *HashHdr, MutableArrayRef< int32_t > BucketMap, BinaryStreamReader &Reader)
Definition: GlobalsStream.cpp:129
llvm::pdb::GSIHashHeader::HrSize
support::ulittle32_t HrSize
Definition: RawTypes.h:35
llvm::pdb::SymbolStream
Definition: SymbolStream.h:22
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
Error.h
llvm::pdb::GSIHashHeader::VerSignature
support::ulittle32_t VerSignature
Definition: RawTypes.h:33
RecordName.h
llvm::pdb::GSIHashTable::BucketMap
std::array< int32_t, IPHR_HASH+1 > BucketMap
Definition: GlobalsStream.h:56
RawError.h
llvm::FixedStreamArray< PSHashRecord >
llvm::msf
Definition: IMSFFile.h:18
llvm::pdb::GSIHashHeader
Header of the hash tables found in the globals and publics sections.
Definition: RawTypes.h:28
GlobalsStream.h
llvm::MutableArrayRef
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:306
llvm::pdb::raw_error_code::corrupt_file
@ corrupt_file
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::pdb
Definition: ConcreteSymbolEnumerator.h:20
llvm::BinaryStreamReader
Provides read only access to a subclass of BinaryStream.
Definition: BinaryStreamReader.h:29
readGSIHashHeader
static Error readGSIHashHeader(const GSIHashHeader *&HashHdr, BinaryStreamReader &Reader)
Definition: GlobalsStream.cpp:94
llvm::pdb::GSIHashHeader::VerHdr
support::ulittle32_t VerHdr
Definition: RawTypes.h:34
llvm::pdb::PSHashRecord
Definition: RawTypes.h:40
llvm::pdb::GSIHashHeader::HdrSignature
@ HdrSignature
Definition: RawTypes.h:30
llvm::pdb::IPHR_HASH
@ IPHR_HASH
Definition: GlobalsStream.h:45
llvm::countPopulation
unsigned countPopulation(T Value)
Count the number of set bits in a value.
Definition: MathExtras.h:567
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
I
#define I(x, y, z)
Definition: MD5.cpp:58
readGSIHashRecords
static Error readGSIHashRecords(FixedStreamArray< PSHashRecord > &HashRecords, const GSIHashHeader *HashHdr, BinaryStreamReader &Reader)
Definition: GlobalsStream.cpp:108
llvm::joinErrors
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:426
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:1675
llvm::pdb::GlobalsStream::findRecordsByName
std::vector< std::pair< uint32_t, codeview::CVSymbol > > findRecordsByName(StringRef Name, const SymbolStream &Symbols) const
Definition: GlobalsStream.cpp:49
llvm::pdb::raw_error_code::feature_unsupported
@ feature_unsupported
llvm::pdb::GlobalsStream::~GlobalsStream
~GlobalsStream()
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:162
llvm::Record
Definition: Record.h:1543
llvm::pdb::PSHashRecord::Off
support::ulittle32_t Off
Definition: RawTypes.h:41
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::codeview::CVRecord
CVRecord is a fat pointer (base + size pair) to a symbol or type record.
Definition: CVRecord.h:29
llvm::pdb::GSIHashHeader::HdrVersion
@ HdrVersion
Definition: RawTypes.h:31
uint32_t
llvm::pdb::GSIHashTable::HashHdr
const GSIHashHeader * HashHdr
Definition: GlobalsStream.h:52
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
std
Definition: BitVector.h:851
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
checkHashHdrVersion
static Error checkHashHdrVersion(const GSIHashHeader *HashHdr)
Definition: GlobalsStream.cpp:85
llvm::FixedStreamArray::size
uint32_t size() const
Definition: BinaryStreamArray.h:295
llvm::codeview::getSymbolName
StringRef getSymbolName(CVSymbol Sym)
Definition: RecordName.cpp:323
LLVM_LIKELY
#define LLVM_LIKELY(EXPR)
Definition: Compiler.h:219
Hash.h
SymbolStream.h
llvm::pdb::GSIHashTable::HashRecords
FixedStreamArray< PSHashRecord > HashRecords
Definition: GlobalsStream.h:53
llvm::pdb::GlobalsStream::reload
Error reload()
Definition: GlobalsStream.cpp:41
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:180
llvm::pdb::GSIHashTable::read
Error read(BinaryStreamReader &Reader)
Definition: GlobalsStream.cpp:170
llvm::pdb::hashStringV1
uint32_t hashStringV1(StringRef Str)
Definition: Hash.cpp:20