LLVM 20.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
31using namespace llvm;
32using namespace llvm::msf;
33using namespace llvm::pdb;
34
35GlobalsStream::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
47std::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);
78 Result.push_back(std::make_pair(Off, std::move(Record)));
79 ++StartRecordIndex;
80 }
81 return Result;
82}
83
84static 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
93static 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
127static 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 CompressedBucketIdx = 0;
145 for (uint32_t I = 0; I <= IPHR_HASH; ++I) {
146 uint8_t WordIdx = I / 32;
147 uint8_t BitIdx = I % 32;
148 bool IsSet = HashBitmap[WordIdx] & (1U << BitIdx);
149 if (IsSet) {
150 BucketMap[I] = CompressedBucketIdx++;
151 } else {
152 BucketMap[I] = -1;
153 }
154 }
155
156 uint32_t NumBuckets = 0;
157 for (uint32_t B : HashBitmap)
158 NumBuckets += llvm::popcount(B);
159
160 // Hash buckets follow.
161 if (auto EC = Reader.readArray(HashBuckets, NumBuckets))
162 return joinErrors(std::move(EC),
163 make_error<RawError>(raw_error_code::corrupt_file,
164 "Hash buckets corrupted."));
165
166 return Error::success();
167}
168
170 if (auto EC = readGSIHashHeader(HashHdr, Reader))
171 return EC;
172 if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader))
173 return EC;
174 if (HashHdr->HrSize > 0)
176 BucketMap, Reader))
177 return EC;
178 return Error::success();
179}
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_LIKELY(EXPR)
Definition: Compiler.h:319
std::string Name
static Error readGSIHashHeader(const GSIHashHeader *&HashHdr, BinaryStreamReader &Reader)
static Error readGSIHashBuckets(FixedStreamArray< support::ulittle32_t > &HashBuckets, FixedStreamArray< support::ulittle32_t > &HashBitmap, const GSIHashHeader *HashHdr, MutableArrayRef< int32_t > BucketMap, BinaryStreamReader &Reader)
static Error readGSIHashRecords(FixedStreamArray< PSHashRecord > &HashRecords, const GSIHashHeader *HashHdr, BinaryStreamReader &Reader)
static Error checkHashHdrVersion(const GSIHashHeader *HashHdr)
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Provides read only access to a subclass of BinaryStream.
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...
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 ...
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
FixedStreamArray is similar to VarStreamArray, except with each record having a fixed-length.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:310
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
CVRecord is a fat pointer (base + size pair) to a symbol or type record.
Definition: CVRecord.h:29
const GSIHashHeader * HashHdr
Definition: GlobalsStream.h:52
Error read(BinaryStreamReader &Reader)
std::array< int32_t, IPHR_HASH+1 > BucketMap
Definition: GlobalsStream.h:56
FixedStreamArray< support::ulittle32_t > HashBuckets
Definition: GlobalsStream.h:55
FixedStreamArray< support::ulittle32_t > HashBitmap
Definition: GlobalsStream.h:54
FixedStreamArray< PSHashRecord > HashRecords
Definition: GlobalsStream.h:53
std::vector< std::pair< uint32_t, codeview::CVSymbol > > findRecordsByName(StringRef Name, const SymbolStream &Symbols) const
GlobalsStream(std::unique_ptr< msf::MappedBlockStream > Stream)
StringRef getSymbolName(CVSymbol Sym)
Definition: RecordName.cpp:323
uint32_t hashStringV1(StringRef Str)
Definition: Hash.cpp:20
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition: bit.h:385
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:438
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
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:1873
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
Header of the hash tables found in the globals and publics sections.
Definition: RawTypes.h:28
support::ulittle32_t HrSize
Definition: RawTypes.h:35
support::ulittle32_t VerHdr
Definition: RawTypes.h:34
support::ulittle32_t VerSignature
Definition: RawTypes.h:33
support::ulittle32_t Off
Definition: RawTypes.h:41