]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/DebugInfo/PDB/Native/GlobalsStream.cpp
MFV r336490:
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / DebugInfo / PDB / Native / GlobalsStream.cpp
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
22 #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
23 #include "llvm/DebugInfo/PDB/Native/RawError.h"
24 #include "llvm/Support/BinaryStreamReader.h"
25 #include "llvm/Support/Error.h"
26 #include <algorithm>
27
28 using namespace llvm;
29 using namespace llvm::msf;
30 using namespace llvm::pdb;
31
32 GlobalsStream::GlobalsStream(std::unique_ptr<MappedBlockStream> Stream)
33     : Stream(std::move(Stream)) {}
34
35 GlobalsStream::~GlobalsStream() = default;
36
37 Error GlobalsStream::reload() {
38   BinaryStreamReader Reader(*Stream);
39   if (auto E = GlobalsTable.read(Reader))
40     return E;
41   return Error::success();
42 }
43
44 static Error checkHashHdrVersion(const GSIHashHeader *HashHdr) {
45   if (HashHdr->VerHdr != GSIHashHeader::HdrVersion)
46     return make_error<RawError>(
47         raw_error_code::feature_unsupported,
48         "Encountered unsupported globals stream version.");
49
50   return Error::success();
51 }
52
53 static Error readGSIHashHeader(const GSIHashHeader *&HashHdr,
54                                BinaryStreamReader &Reader) {
55   if (Reader.readObject(HashHdr))
56     return make_error<RawError>(raw_error_code::corrupt_file,
57                                 "Stream does not contain a GSIHashHeader.");
58
59   if (HashHdr->VerSignature != GSIHashHeader::HdrSignature)
60     return make_error<RawError>(
61         raw_error_code::feature_unsupported,
62         "GSIHashHeader signature (0xffffffff) not found.");
63
64   return Error::success();
65 }
66
67 static Error readGSIHashRecords(FixedStreamArray<PSHashRecord> &HashRecords,
68                                 const GSIHashHeader *HashHdr,
69                                 BinaryStreamReader &Reader) {
70   if (auto EC = checkHashHdrVersion(HashHdr))
71     return EC;
72
73   // HashHdr->HrSize specifies the number of bytes of PSHashRecords we have.
74   // Verify that we can read them all.
75   if (HashHdr->HrSize % sizeof(PSHashRecord))
76     return make_error<RawError>(raw_error_code::corrupt_file,
77                                 "Invalid HR array size.");
78   uint32_t NumHashRecords = HashHdr->HrSize / sizeof(PSHashRecord);
79   if (auto EC = Reader.readArray(HashRecords, NumHashRecords))
80     return joinErrors(std::move(EC),
81                       make_error<RawError>(raw_error_code::corrupt_file,
82                                            "Error reading hash records."));
83
84   return Error::success();
85 }
86
87 static Error
88 readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets,
89                    ArrayRef<uint8_t> &HashBitmap, const GSIHashHeader *HashHdr,
90                    BinaryStreamReader &Reader) {
91   if (auto EC = checkHashHdrVersion(HashHdr))
92     return EC;
93
94   // Before the actual hash buckets, there is a bitmap of length determined by
95   // IPHR_HASH.
96   size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32);
97   uint32_t NumBitmapEntries = BitmapSizeInBits / 8;
98   if (auto EC = Reader.readBytes(HashBitmap, NumBitmapEntries))
99     return joinErrors(std::move(EC),
100                       make_error<RawError>(raw_error_code::corrupt_file,
101                                            "Could not read a bitmap."));
102   uint32_t NumBuckets = 0;
103   for (uint8_t B : HashBitmap)
104     NumBuckets += countPopulation(B);
105
106   // Hash buckets follow.
107   if (auto EC = Reader.readArray(HashBuckets, NumBuckets))
108     return joinErrors(std::move(EC),
109                       make_error<RawError>(raw_error_code::corrupt_file,
110                                            "Hash buckets corrupted."));
111
112   return Error::success();
113 }
114
115 Error GSIHashTable::read(BinaryStreamReader &Reader) {
116   if (auto EC = readGSIHashHeader(HashHdr, Reader))
117     return EC;
118   if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader))
119     return EC;
120   if (HashHdr->HrSize > 0)
121     if (auto EC = readGSIHashBuckets(HashBuckets, HashBitmap, HashHdr, Reader))
122       return EC;
123   return Error::success();
124 }