1*9880d681SAndroid Build Coastguard Worker //===- NameMap.cpp - PDB Name Map -------------------------------*- C++ -*-===//
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 #include "llvm/DebugInfo/PDB/Raw/NameMap.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SparseBitVector.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/StreamReader.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/StreamWriter.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/RawError.h"
15*9880d681SAndroid Build Coastguard Worker
16*9880d681SAndroid Build Coastguard Worker using namespace llvm;
17*9880d681SAndroid Build Coastguard Worker using namespace llvm::codeview;
18*9880d681SAndroid Build Coastguard Worker using namespace llvm::pdb;
19*9880d681SAndroid Build Coastguard Worker
NameMap()20*9880d681SAndroid Build Coastguard Worker NameMap::NameMap() {}
21*9880d681SAndroid Build Coastguard Worker
load(codeview::StreamReader & Stream)22*9880d681SAndroid Build Coastguard Worker Error NameMap::load(codeview::StreamReader &Stream) {
23*9880d681SAndroid Build Coastguard Worker
24*9880d681SAndroid Build Coastguard Worker // This is some sort of weird string-set/hash table encoded in the stream.
25*9880d681SAndroid Build Coastguard Worker // It starts with the number of bytes in the table.
26*9880d681SAndroid Build Coastguard Worker uint32_t NumberOfBytes;
27*9880d681SAndroid Build Coastguard Worker if (auto EC = Stream.readInteger(NumberOfBytes))
28*9880d681SAndroid Build Coastguard Worker return joinErrors(std::move(EC),
29*9880d681SAndroid Build Coastguard Worker make_error<RawError>(raw_error_code::corrupt_file,
30*9880d681SAndroid Build Coastguard Worker "Expected name map length"));
31*9880d681SAndroid Build Coastguard Worker if (Stream.bytesRemaining() < NumberOfBytes)
32*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(raw_error_code::corrupt_file,
33*9880d681SAndroid Build Coastguard Worker "Invalid name map length");
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard Worker // Following that field is the starting offset of strings in the name table.
36*9880d681SAndroid Build Coastguard Worker uint32_t StringsOffset = Stream.getOffset();
37*9880d681SAndroid Build Coastguard Worker Stream.setOffset(StringsOffset + NumberOfBytes);
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker // This appears to be equivalent to the total number of strings *actually*
40*9880d681SAndroid Build Coastguard Worker // in the name table.
41*9880d681SAndroid Build Coastguard Worker uint32_t HashSize;
42*9880d681SAndroid Build Coastguard Worker if (auto EC = Stream.readInteger(HashSize))
43*9880d681SAndroid Build Coastguard Worker return joinErrors(std::move(EC),
44*9880d681SAndroid Build Coastguard Worker make_error<RawError>(raw_error_code::corrupt_file,
45*9880d681SAndroid Build Coastguard Worker "Expected name map hash size"));
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Worker // This appears to be an upper bound on the number of strings in the name
48*9880d681SAndroid Build Coastguard Worker // table.
49*9880d681SAndroid Build Coastguard Worker uint32_t MaxNumberOfStrings;
50*9880d681SAndroid Build Coastguard Worker if (auto EC = Stream.readInteger(MaxNumberOfStrings))
51*9880d681SAndroid Build Coastguard Worker return joinErrors(std::move(EC),
52*9880d681SAndroid Build Coastguard Worker make_error<RawError>(raw_error_code::corrupt_file,
53*9880d681SAndroid Build Coastguard Worker "Expected name map max strings"));
54*9880d681SAndroid Build Coastguard Worker
55*9880d681SAndroid Build Coastguard Worker if (MaxNumberOfStrings > (UINT32_MAX / sizeof(uint32_t)))
56*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(raw_error_code::corrupt_file,
57*9880d681SAndroid Build Coastguard Worker "Implausible number of strings");
58*9880d681SAndroid Build Coastguard Worker
59*9880d681SAndroid Build Coastguard Worker const uint32_t MaxNumberOfWords = UINT32_MAX / (sizeof(uint32_t) * 8);
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker // This appears to be a hash table which uses bitfields to determine whether
62*9880d681SAndroid Build Coastguard Worker // or not a bucket is 'present'.
63*9880d681SAndroid Build Coastguard Worker uint32_t NumPresentWords;
64*9880d681SAndroid Build Coastguard Worker if (auto EC = Stream.readInteger(NumPresentWords))
65*9880d681SAndroid Build Coastguard Worker return joinErrors(std::move(EC),
66*9880d681SAndroid Build Coastguard Worker make_error<RawError>(raw_error_code::corrupt_file,
67*9880d681SAndroid Build Coastguard Worker "Expected name map num words"));
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker if (NumPresentWords > MaxNumberOfWords)
70*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(raw_error_code::corrupt_file,
71*9880d681SAndroid Build Coastguard Worker "Number of present words is too large");
72*9880d681SAndroid Build Coastguard Worker
73*9880d681SAndroid Build Coastguard Worker SparseBitVector<> Present;
74*9880d681SAndroid Build Coastguard Worker for (uint32_t I = 0; I != NumPresentWords; ++I) {
75*9880d681SAndroid Build Coastguard Worker uint32_t Word;
76*9880d681SAndroid Build Coastguard Worker if (auto EC = Stream.readInteger(Word))
77*9880d681SAndroid Build Coastguard Worker return joinErrors(std::move(EC),
78*9880d681SAndroid Build Coastguard Worker make_error<RawError>(raw_error_code::corrupt_file,
79*9880d681SAndroid Build Coastguard Worker "Expected name map word"));
80*9880d681SAndroid Build Coastguard Worker for (unsigned Idx = 0; Idx < 32; ++Idx)
81*9880d681SAndroid Build Coastguard Worker if (Word & (1U << Idx))
82*9880d681SAndroid Build Coastguard Worker Present.set((I * 32) + Idx);
83*9880d681SAndroid Build Coastguard Worker }
84*9880d681SAndroid Build Coastguard Worker
85*9880d681SAndroid Build Coastguard Worker // This appears to be a hash table which uses bitfields to determine whether
86*9880d681SAndroid Build Coastguard Worker // or not a bucket is 'deleted'.
87*9880d681SAndroid Build Coastguard Worker uint32_t NumDeletedWords;
88*9880d681SAndroid Build Coastguard Worker if (auto EC = Stream.readInteger(NumDeletedWords))
89*9880d681SAndroid Build Coastguard Worker return joinErrors(
90*9880d681SAndroid Build Coastguard Worker std::move(EC),
91*9880d681SAndroid Build Coastguard Worker make_error<RawError>(raw_error_code::corrupt_file,
92*9880d681SAndroid Build Coastguard Worker "Expected name map num deleted words"));
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker if (NumDeletedWords > MaxNumberOfWords)
95*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(raw_error_code::corrupt_file,
96*9880d681SAndroid Build Coastguard Worker "Number of deleted words is too large");
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker SparseBitVector<> Deleted;
99*9880d681SAndroid Build Coastguard Worker for (uint32_t I = 0; I != NumDeletedWords; ++I) {
100*9880d681SAndroid Build Coastguard Worker uint32_t Word;
101*9880d681SAndroid Build Coastguard Worker if (auto EC = Stream.readInteger(Word))
102*9880d681SAndroid Build Coastguard Worker return joinErrors(std::move(EC),
103*9880d681SAndroid Build Coastguard Worker make_error<RawError>(raw_error_code::corrupt_file,
104*9880d681SAndroid Build Coastguard Worker "Expected name map word"));
105*9880d681SAndroid Build Coastguard Worker for (unsigned Idx = 0; Idx < 32; ++Idx)
106*9880d681SAndroid Build Coastguard Worker if (Word & (1U << Idx))
107*9880d681SAndroid Build Coastguard Worker Deleted.set((I * 32) + Idx);
108*9880d681SAndroid Build Coastguard Worker }
109*9880d681SAndroid Build Coastguard Worker
110*9880d681SAndroid Build Coastguard Worker for (unsigned I : Present) {
111*9880d681SAndroid Build Coastguard Worker // For all present entries, dump out their mapping.
112*9880d681SAndroid Build Coastguard Worker (void)I;
113*9880d681SAndroid Build Coastguard Worker
114*9880d681SAndroid Build Coastguard Worker // This appears to be an offset relative to the start of the strings.
115*9880d681SAndroid Build Coastguard Worker // It tells us where the null-terminated string begins.
116*9880d681SAndroid Build Coastguard Worker uint32_t NameOffset;
117*9880d681SAndroid Build Coastguard Worker if (auto EC = Stream.readInteger(NameOffset))
118*9880d681SAndroid Build Coastguard Worker return joinErrors(std::move(EC),
119*9880d681SAndroid Build Coastguard Worker make_error<RawError>(raw_error_code::corrupt_file,
120*9880d681SAndroid Build Coastguard Worker "Expected name map name offset"));
121*9880d681SAndroid Build Coastguard Worker
122*9880d681SAndroid Build Coastguard Worker // This appears to be a stream number into the stream directory.
123*9880d681SAndroid Build Coastguard Worker uint32_t NameIndex;
124*9880d681SAndroid Build Coastguard Worker if (auto EC = Stream.readInteger(NameIndex))
125*9880d681SAndroid Build Coastguard Worker return joinErrors(std::move(EC),
126*9880d681SAndroid Build Coastguard Worker make_error<RawError>(raw_error_code::corrupt_file,
127*9880d681SAndroid Build Coastguard Worker "Expected name map name index"));
128*9880d681SAndroid Build Coastguard Worker
129*9880d681SAndroid Build Coastguard Worker // Compute the offset of the start of the string relative to the stream.
130*9880d681SAndroid Build Coastguard Worker uint32_t StringOffset = StringsOffset + NameOffset;
131*9880d681SAndroid Build Coastguard Worker uint32_t OldOffset = Stream.getOffset();
132*9880d681SAndroid Build Coastguard Worker // Pump out our c-string from the stream.
133*9880d681SAndroid Build Coastguard Worker StringRef Str;
134*9880d681SAndroid Build Coastguard Worker Stream.setOffset(StringOffset);
135*9880d681SAndroid Build Coastguard Worker if (auto EC = Stream.readZeroString(Str))
136*9880d681SAndroid Build Coastguard Worker return joinErrors(std::move(EC),
137*9880d681SAndroid Build Coastguard Worker make_error<RawError>(raw_error_code::corrupt_file,
138*9880d681SAndroid Build Coastguard Worker "Expected name map name"));
139*9880d681SAndroid Build Coastguard Worker
140*9880d681SAndroid Build Coastguard Worker Stream.setOffset(OldOffset);
141*9880d681SAndroid Build Coastguard Worker // Add this to a string-map from name to stream number.
142*9880d681SAndroid Build Coastguard Worker Mapping.insert({Str, NameIndex});
143*9880d681SAndroid Build Coastguard Worker }
144*9880d681SAndroid Build Coastguard Worker
145*9880d681SAndroid Build Coastguard Worker return Error::success();
146*9880d681SAndroid Build Coastguard Worker }
147*9880d681SAndroid Build Coastguard Worker
commit(codeview::StreamWriter & Writer)148*9880d681SAndroid Build Coastguard Worker Error NameMap::commit(codeview::StreamWriter &Writer) {
149*9880d681SAndroid Build Coastguard Worker if (auto EC = Writer.writeInteger(0U)) // Number of bytes in table
150*9880d681SAndroid Build Coastguard Worker return EC;
151*9880d681SAndroid Build Coastguard Worker
152*9880d681SAndroid Build Coastguard Worker if (auto EC = Writer.writeInteger(0U)) // Hash Size
153*9880d681SAndroid Build Coastguard Worker return EC;
154*9880d681SAndroid Build Coastguard Worker
155*9880d681SAndroid Build Coastguard Worker if (auto EC = Writer.writeInteger(0U)) // Max Number of Strings
156*9880d681SAndroid Build Coastguard Worker return EC;
157*9880d681SAndroid Build Coastguard Worker
158*9880d681SAndroid Build Coastguard Worker if (auto EC = Writer.writeInteger(0U)) // Num Present Words
159*9880d681SAndroid Build Coastguard Worker return EC;
160*9880d681SAndroid Build Coastguard Worker
161*9880d681SAndroid Build Coastguard Worker if (auto EC = Writer.writeInteger(0U)) // Num Deleted Words
162*9880d681SAndroid Build Coastguard Worker return EC;
163*9880d681SAndroid Build Coastguard Worker return Error::success();
164*9880d681SAndroid Build Coastguard Worker }
165*9880d681SAndroid Build Coastguard Worker
entries() const166*9880d681SAndroid Build Coastguard Worker iterator_range<StringMapConstIterator<uint32_t>> NameMap::entries() const {
167*9880d681SAndroid Build Coastguard Worker return llvm::make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(),
168*9880d681SAndroid Build Coastguard Worker Mapping.end());
169*9880d681SAndroid Build Coastguard Worker }
170*9880d681SAndroid Build Coastguard Worker
tryGetValue(StringRef Name,uint32_t & Value) const171*9880d681SAndroid Build Coastguard Worker bool NameMap::tryGetValue(StringRef Name, uint32_t &Value) const {
172*9880d681SAndroid Build Coastguard Worker auto Iter = Mapping.find(Name);
173*9880d681SAndroid Build Coastguard Worker if (Iter == Mapping.end())
174*9880d681SAndroid Build Coastguard Worker return false;
175*9880d681SAndroid Build Coastguard Worker Value = Iter->second;
176*9880d681SAndroid Build Coastguard Worker return true;
177*9880d681SAndroid Build Coastguard Worker }
178