xref: /aosp_15_r20/external/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- PublicsStream.cpp - PDB Public Symbol Stream -----------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // The data structures defined in this file are based on the reference
11*9880d681SAndroid Build Coastguard Worker // implementation which is available at
12*9880d681SAndroid Build Coastguard Worker // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
13*9880d681SAndroid Build Coastguard Worker //
14*9880d681SAndroid Build Coastguard Worker // When you are reading the reference source code, you'd find the
15*9880d681SAndroid Build Coastguard Worker // information below useful.
16*9880d681SAndroid Build Coastguard Worker //
17*9880d681SAndroid Build Coastguard Worker //  - ppdb1->m_fMinimalDbgInfo seems to be always true.
18*9880d681SAndroid Build Coastguard Worker //  - SMALLBUCKETS macro is defined.
19*9880d681SAndroid Build Coastguard Worker //
20*9880d681SAndroid Build Coastguard Worker // The reference doesn't compile, so I learned just by reading code.
21*9880d681SAndroid Build Coastguard Worker // It's not guaranteed to be correct.
22*9880d681SAndroid Build Coastguard Worker //
23*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
24*9880d681SAndroid Build Coastguard Worker 
25*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
26*9880d681SAndroid Build Coastguard Worker 
27*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/CodeView.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/StreamReader.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/TypeRecord.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/RawError.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/SymbolStream.h"
36*9880d681SAndroid Build Coastguard Worker 
37*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/BitVector.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Endian.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Format.h"
40*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MathExtras.h"
41*9880d681SAndroid Build Coastguard Worker 
42*9880d681SAndroid Build Coastguard Worker using namespace llvm;
43*9880d681SAndroid Build Coastguard Worker using namespace llvm::support;
44*9880d681SAndroid Build Coastguard Worker using namespace llvm::pdb;
45*9880d681SAndroid Build Coastguard Worker 
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker static const unsigned IPHR_HASH = 4096;
48*9880d681SAndroid Build Coastguard Worker 
49*9880d681SAndroid Build Coastguard Worker // This is PSGSIHDR struct defined in
50*9880d681SAndroid Build Coastguard Worker // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
51*9880d681SAndroid Build Coastguard Worker struct PublicsStream::HeaderInfo {
52*9880d681SAndroid Build Coastguard Worker   ulittle32_t SymHash;
53*9880d681SAndroid Build Coastguard Worker   ulittle32_t AddrMap;
54*9880d681SAndroid Build Coastguard Worker   ulittle32_t NumThunks;
55*9880d681SAndroid Build Coastguard Worker   ulittle32_t SizeOfThunk;
56*9880d681SAndroid Build Coastguard Worker   ulittle16_t ISectThunkTable;
57*9880d681SAndroid Build Coastguard Worker   char Padding[2];
58*9880d681SAndroid Build Coastguard Worker   ulittle32_t OffThunkTable;
59*9880d681SAndroid Build Coastguard Worker   ulittle32_t NumSections;
60*9880d681SAndroid Build Coastguard Worker };
61*9880d681SAndroid Build Coastguard Worker 
62*9880d681SAndroid Build Coastguard Worker // This is GSIHashHdr.
63*9880d681SAndroid Build Coastguard Worker struct PublicsStream::GSIHashHeader {
64*9880d681SAndroid Build Coastguard Worker   enum : unsigned {
65*9880d681SAndroid Build Coastguard Worker     HdrSignature = ~0U,
66*9880d681SAndroid Build Coastguard Worker     HdrVersion = 0xeffe0000 + 19990810,
67*9880d681SAndroid Build Coastguard Worker   };
68*9880d681SAndroid Build Coastguard Worker   ulittle32_t VerSignature;
69*9880d681SAndroid Build Coastguard Worker   ulittle32_t VerHdr;
70*9880d681SAndroid Build Coastguard Worker   ulittle32_t HrSize;
71*9880d681SAndroid Build Coastguard Worker   ulittle32_t NumBuckets;
72*9880d681SAndroid Build Coastguard Worker };
73*9880d681SAndroid Build Coastguard Worker 
PublicsStream(PDBFile & File,std::unique_ptr<MappedBlockStream> Stream)74*9880d681SAndroid Build Coastguard Worker PublicsStream::PublicsStream(PDBFile &File,
75*9880d681SAndroid Build Coastguard Worker                              std::unique_ptr<MappedBlockStream> Stream)
76*9880d681SAndroid Build Coastguard Worker     : Pdb(File), Stream(std::move(Stream)) {}
77*9880d681SAndroid Build Coastguard Worker 
~PublicsStream()78*9880d681SAndroid Build Coastguard Worker PublicsStream::~PublicsStream() {}
79*9880d681SAndroid Build Coastguard Worker 
getSymHash() const80*9880d681SAndroid Build Coastguard Worker uint32_t PublicsStream::getSymHash() const { return Header->SymHash; }
getAddrMap() const81*9880d681SAndroid Build Coastguard Worker uint32_t PublicsStream::getAddrMap() const { return Header->AddrMap; }
82*9880d681SAndroid Build Coastguard Worker 
83*9880d681SAndroid Build Coastguard Worker // Publics stream contains fixed-size headers and a serialized hash table.
84*9880d681SAndroid Build Coastguard Worker // This implementation is not complete yet. It reads till the end of the
85*9880d681SAndroid Build Coastguard Worker // stream so that we verify the stream is at least not corrupted. However,
86*9880d681SAndroid Build Coastguard Worker // we skip over the hash table which we believe contains information about
87*9880d681SAndroid Build Coastguard Worker // public symbols.
reload()88*9880d681SAndroid Build Coastguard Worker Error PublicsStream::reload() {
89*9880d681SAndroid Build Coastguard Worker   codeview::StreamReader Reader(*Stream);
90*9880d681SAndroid Build Coastguard Worker 
91*9880d681SAndroid Build Coastguard Worker   // Check stream size.
92*9880d681SAndroid Build Coastguard Worker   if (Reader.bytesRemaining() < sizeof(HeaderInfo) + sizeof(GSIHashHeader))
93*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::corrupt_file,
94*9880d681SAndroid Build Coastguard Worker                                 "Publics Stream does not contain a header.");
95*9880d681SAndroid Build Coastguard Worker 
96*9880d681SAndroid Build Coastguard Worker   // Read PSGSIHDR and GSIHashHdr structs.
97*9880d681SAndroid Build Coastguard Worker   if (Reader.readObject(Header))
98*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::corrupt_file,
99*9880d681SAndroid Build Coastguard Worker                                 "Publics Stream does not contain a header.");
100*9880d681SAndroid Build Coastguard Worker 
101*9880d681SAndroid Build Coastguard Worker   if (Reader.readObject(HashHdr))
102*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::corrupt_file,
103*9880d681SAndroid Build Coastguard Worker                                 "Publics Stream does not contain a header.");
104*9880d681SAndroid Build Coastguard Worker 
105*9880d681SAndroid Build Coastguard Worker   // An array of HashRecord follows. Read them.
106*9880d681SAndroid Build Coastguard Worker   if (HashHdr->HrSize % sizeof(PSHashRecord))
107*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::corrupt_file,
108*9880d681SAndroid Build Coastguard Worker                                 "Invalid HR array size.");
109*9880d681SAndroid Build Coastguard Worker   uint32_t NumHashRecords = HashHdr->HrSize / sizeof(PSHashRecord);
110*9880d681SAndroid Build Coastguard Worker   if (auto EC = Reader.readArray(HashRecords, NumHashRecords))
111*9880d681SAndroid Build Coastguard Worker     return joinErrors(std::move(EC),
112*9880d681SAndroid Build Coastguard Worker                       make_error<RawError>(raw_error_code::corrupt_file,
113*9880d681SAndroid Build Coastguard Worker                                            "Could not read an HR array"));
114*9880d681SAndroid Build Coastguard Worker 
115*9880d681SAndroid Build Coastguard Worker   // A bitmap of a fixed length follows.
116*9880d681SAndroid Build Coastguard Worker   size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32);
117*9880d681SAndroid Build Coastguard Worker   uint32_t NumBitmapEntries = BitmapSizeInBits / 8;
118*9880d681SAndroid Build Coastguard Worker   if (auto EC = Reader.readBytes(Bitmap, NumBitmapEntries))
119*9880d681SAndroid Build Coastguard Worker     return joinErrors(std::move(EC),
120*9880d681SAndroid Build Coastguard Worker                       make_error<RawError>(raw_error_code::corrupt_file,
121*9880d681SAndroid Build Coastguard Worker                                            "Could not read a bitmap."));
122*9880d681SAndroid Build Coastguard Worker   for (uint8_t B : Bitmap)
123*9880d681SAndroid Build Coastguard Worker     NumBuckets += countPopulation(B);
124*9880d681SAndroid Build Coastguard Worker 
125*9880d681SAndroid Build Coastguard Worker   // We don't yet understand the following data structures completely,
126*9880d681SAndroid Build Coastguard Worker   // but we at least know the types and sizes. Here we are trying
127*9880d681SAndroid Build Coastguard Worker   // to read the stream till end so that we at least can detect
128*9880d681SAndroid Build Coastguard Worker   // corrupted streams.
129*9880d681SAndroid Build Coastguard Worker 
130*9880d681SAndroid Build Coastguard Worker   // Hash buckets follow.
131*9880d681SAndroid Build Coastguard Worker   if (auto EC = Reader.readArray(HashBuckets, NumBuckets))
132*9880d681SAndroid Build Coastguard Worker     return joinErrors(std::move(EC),
133*9880d681SAndroid Build Coastguard Worker                       make_error<RawError>(raw_error_code::corrupt_file,
134*9880d681SAndroid Build Coastguard Worker                                            "Hash buckets corrupted."));
135*9880d681SAndroid Build Coastguard Worker 
136*9880d681SAndroid Build Coastguard Worker   // Something called "address map" follows.
137*9880d681SAndroid Build Coastguard Worker   uint32_t NumAddressMapEntries = Header->AddrMap / sizeof(uint32_t);
138*9880d681SAndroid Build Coastguard Worker   if (auto EC = Reader.readArray(AddressMap, NumAddressMapEntries))
139*9880d681SAndroid Build Coastguard Worker     return joinErrors(std::move(EC),
140*9880d681SAndroid Build Coastguard Worker                       make_error<RawError>(raw_error_code::corrupt_file,
141*9880d681SAndroid Build Coastguard Worker                                            "Could not read an address map."));
142*9880d681SAndroid Build Coastguard Worker 
143*9880d681SAndroid Build Coastguard Worker   // Something called "thunk map" follows.
144*9880d681SAndroid Build Coastguard Worker   if (auto EC = Reader.readArray(ThunkMap, Header->NumThunks))
145*9880d681SAndroid Build Coastguard Worker     return joinErrors(std::move(EC),
146*9880d681SAndroid Build Coastguard Worker                       make_error<RawError>(raw_error_code::corrupt_file,
147*9880d681SAndroid Build Coastguard Worker                                            "Could not read a thunk map."));
148*9880d681SAndroid Build Coastguard Worker 
149*9880d681SAndroid Build Coastguard Worker   // Something called "section map" follows.
150*9880d681SAndroid Build Coastguard Worker   if (auto EC = Reader.readArray(SectionOffsets, Header->NumSections))
151*9880d681SAndroid Build Coastguard Worker     return joinErrors(std::move(EC),
152*9880d681SAndroid Build Coastguard Worker                       make_error<RawError>(raw_error_code::corrupt_file,
153*9880d681SAndroid Build Coastguard Worker                                            "Could not read a section map."));
154*9880d681SAndroid Build Coastguard Worker 
155*9880d681SAndroid Build Coastguard Worker   if (Reader.bytesRemaining() > 0)
156*9880d681SAndroid Build Coastguard Worker     return make_error<RawError>(raw_error_code::corrupt_file,
157*9880d681SAndroid Build Coastguard Worker                                 "Corrupted publics stream.");
158*9880d681SAndroid Build Coastguard Worker   return Error::success();
159*9880d681SAndroid Build Coastguard Worker }
160*9880d681SAndroid Build Coastguard Worker 
161*9880d681SAndroid Build Coastguard Worker iterator_range<codeview::CVSymbolArray::Iterator>
getSymbols(bool * HadError) const162*9880d681SAndroid Build Coastguard Worker PublicsStream::getSymbols(bool *HadError) const {
163*9880d681SAndroid Build Coastguard Worker   auto SymbolS = Pdb.getPDBSymbolStream();
164*9880d681SAndroid Build Coastguard Worker   if (SymbolS.takeError()) {
165*9880d681SAndroid Build Coastguard Worker     codeview::CVSymbolArray::Iterator Iter;
166*9880d681SAndroid Build Coastguard Worker     return llvm::make_range(Iter, Iter);
167*9880d681SAndroid Build Coastguard Worker   }
168*9880d681SAndroid Build Coastguard Worker   SymbolStream &SS = SymbolS.get();
169*9880d681SAndroid Build Coastguard Worker 
170*9880d681SAndroid Build Coastguard Worker   return SS.getSymbols(HadError);
171*9880d681SAndroid Build Coastguard Worker }
172*9880d681SAndroid Build Coastguard Worker 
commit()173*9880d681SAndroid Build Coastguard Worker Error PublicsStream::commit() { return Error::success(); }
174