xref: /aosp_15_r20/external/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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