llvm.org GIT mirror llvm / 505c76a
[PDB] Don't build the entire source file list up front. I tried to run llvm-pdbdump on a very large (~1.5GB) PDB to try and identify show-stopping performance problems. This patch addresses the first such problem. When loading the DBI stream, before anyone has even tried to access a single record, we build an in memory map of every source file for every module. In the particular PDB I was using, this was over 85 million files. Specifically, the complexity is O(m*n) where m is the number of modules and n is the average number of source files (including headers) per module. The whole reason for doing this was so that we could have constant time access to any module and any of its source file lists. However, we can still get O(1) access to the source file list for a given module with a simple O(m) precomputation, and access to the list of modules is already O(1) anyway. So this patches reduces the O(m*n) up-front precomputation to an O(m) one, where n is ~6,500 and n*m is about 85 million in my pathological test case. Differential Revision: https://reviews.llvm.org/D32870 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@302205 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 3 years ago
16 changed file(s) with 475 addition(s) and 183 deletion(s). Raw diff Collapse all Expand all
5252 const ModuleInfoHeader *Layout = nullptr;
5353 };
5454
55 struct ModuleInfoEx {
56 ModuleInfoEx(const DbiModuleDescriptor &Info) : Info(Info) {}
57 ModuleInfoEx(const ModuleInfoEx &Ex) = default;
58
59 DbiModuleDescriptor Info;
60 std::vector SourceFiles;
61 };
62
6355 } // end namespace pdb
6456
6557 template <> struct VarStreamArrayExtractor {
0 //===- DbiModuleList.h - PDB module information list ------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_DEBUGINFO_PDB_RAW_DBIMODULELIST_H
10 #define LLVM_DEBUGINFO_PDB_RAW_DBIMODULELIST_H
11
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/ADT/iterator.h"
14 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
15 #include "llvm/Support/BinaryStreamArray.h"
16 #include "llvm/Support/BinaryStreamRef.h"
17 #include "llvm/Support/Endian.h"
18 #include "llvm/Support/Error.h"
19 #include
20 #include
21
22 namespace llvm {
23 namespace pdb {
24
25 class DbiModuleList;
26 struct FileInfoSubstreamHeader;
27
28 class DbiModuleSourceFilesIterator
29 : public iterator_facade_base
30 std::random_access_iterator_tag, StringRef> {
31 typedef iterator_facade_base
32 std::random_access_iterator_tag, StringRef>
33 BaseType;
34
35 public:
36 DbiModuleSourceFilesIterator(const DbiModuleList &Modules, uint32_t Modi,
37 uint16_t Filei);
38 DbiModuleSourceFilesIterator() = default;
39 DbiModuleSourceFilesIterator &
40 operator=(const DbiModuleSourceFilesIterator &R) = default;
41
42 bool operator==(const DbiModuleSourceFilesIterator &R) const;
43
44 const StringRef &operator*() const { return ThisValue; }
45 StringRef &operator*() { return ThisValue; }
46
47 bool operator<(const DbiModuleSourceFilesIterator &RHS) const;
48 std::ptrdiff_t operator-(const DbiModuleSourceFilesIterator &R) const;
49 DbiModuleSourceFilesIterator &operator+=(std::ptrdiff_t N);
50 DbiModuleSourceFilesIterator &operator-=(std::ptrdiff_t N);
51
52 private:
53 void setValue();
54
55 bool isEnd() const;
56 bool isCompatible(const DbiModuleSourceFilesIterator &R) const;
57 bool isUniversalEnd() const;
58
59 StringRef ThisValue;
60 const DbiModuleList *Modules{nullptr};
61 uint32_t Modi{0};
62 uint16_t Filei{0};
63 };
64
65 class DbiModuleList {
66 friend DbiModuleSourceFilesIterator;
67
68 public:
69 Error initialize(BinaryStreamRef ModInfo, BinaryStreamRef FileInfo);
70
71 Expected getFileName(uint32_t Index) const;
72 uint32_t getModuleCount() const;
73 uint32_t getSourceFileCount() const;
74 uint16_t getSourceFileCount(uint32_t Modi) const;
75
76 iterator_range
77 source_files(uint32_t Modi) const;
78
79 DbiModuleDescriptor getModuleDescriptor(uint32_t Modi) const;
80
81 private:
82 Error initializeModInfo(BinaryStreamRef ModInfo);
83 Error initializeFileInfo(BinaryStreamRef FileInfo);
84
85 VarStreamArray Descriptors;
86
87 FixedStreamArray FileNameOffsets;
88 FixedStreamArray ModFileCountArray;
89
90 // For each module, there are multiple filenames, which can be obtained by
91 // knowing the index of the file. Given the index of the file, one can use
92 // that as an offset into the FileNameOffsets array, which contains the
93 // absolute offset of the file name in NamesBuffer. Thus, for each module
94 // we store the first index in the FileNameOffsets array for this module.
95 // The number of files for the corresponding module is stored in
96 // ModFileCountArray.
97 std::vector ModuleInitialFileIndex;
98
99 // In order to provide random access into the Descriptors array, we iterate it
100 // once up front to find the offsets of the individual items and store them in
101 // this array.
102 std::vector ModuleDescriptorOffsets;
103
104 const FileInfoSubstreamHeader *FileInfoHeader = nullptr;
105
106 BinaryStreamRef ModInfoSubstream;
107 BinaryStreamRef FileInfoSubstream;
108 BinaryStreamRef NamesBuffer;
109 };
110 }
111 }
112
113 #endif // LLVM_DEBUGINFO_PDB_RAW_DBIMODULELIST_H
1212 #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
1313 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
1414 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
15 #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
1516 #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
1617 #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
1718 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
6768 /// not present, returns InvalidStreamIndex.
6869 uint32_t getDebugStreamIndex(DbgHeaderType Type) const;
6970
70 ArrayRef modules() const;
71
72 Expected getFileNameForIndex(uint32_t Index) const;
71 const DbiModuleList &modules() const;
7372
7473 FixedStreamArray getSectionHeaders();
7574
7978 void visitSectionContributions(ISectionContribVisitor &Visitor) const;
8079
8180 private:
82 Error initializeModInfoArray();
8381 Error initializeSectionContributionData();
8482 Error initializeSectionHeadersData();
8583 Error initializeSectionMapData();
86 Error initializeFileInfo();
8784 Error initializeFpoRecords();
8885
8986 PDBFile &Pdb;
9087 std::unique_ptr Stream;
9188
92 std::vector ModuleInfos;
9389 PDBStringTable ECNames;
9490
95 BinaryStreamRef ModInfoSubstream;
9691 BinaryStreamRef SecContrSubstream;
9792 BinaryStreamRef SecMapSubstream;
98 BinaryStreamRef FileInfoSubstream;
9993 BinaryStreamRef TypeServerMapSubstream;
10094 BinaryStreamRef ECSubstream;
10195
102 BinaryStreamRef NamesBuffer;
96 DbiModuleList Modules;
10397
10498 FixedStreamArray DbgStreams;
10599
107101 FixedStreamArray SectionContribs;
108102 FixedStreamArray SectionContribs2;
109103 FixedStreamArray SectionMap;
110 FixedStreamArray FileNameOffsets;
111104
112105 std::unique_ptr SectionHeaderStream;
113106 FixedStreamArray SectionHeaders;
1717
1818 class NativeCompilandSymbol : public NativeRawSymbol {
1919 public:
20 NativeCompilandSymbol(NativeSession &Session, const ModuleInfoEx &MI);
20 NativeCompilandSymbol(NativeSession &Session, DbiModuleDescriptor MI);
2121 PDB_SymType getSymTag() const override;
2222 bool isEditAndContinueEnabled() const override;
2323 uint32_t getLexicalParentId() const override;
2525 std::string getName() const override;
2626
2727 private:
28 ModuleInfoEx Module;
28 DbiModuleDescriptor Module;
2929 };
3030
3131 } // namespace pdb
1515 namespace llvm {
1616 namespace pdb {
1717
18 class DbiModuleList;
1819 class NativeSession;
1920
2021 class NativeEnumModules : public IPDBEnumChildren {
2122 public:
22 explicit NativeEnumModules(NativeSession &Session,
23 ArrayRef Modules,
24 uint32_t Index = 0);
23 NativeEnumModules(NativeSession &Session, const DbiModuleList &Modules,
24 uint32_t Index = 0);
2525
2626 uint32_t getChildCount() const override;
2727 std::unique_ptr getChildAtIndex(uint32_t Index) const override;
3131
3232 private:
3333 NativeSession &Session;
34 ArrayRef Modules;
34 const DbiModuleList &Modules;
3535 uint32_t Index;
3636 };
3737 }
210210 };
211211
212212 /// The header preceeding each entry in the Module Info substream of the DBI
213 /// stream.
213 /// stream. Corresponds to the type MODI in the reference implementation.
214214 struct ModuleInfoHeader {
215215 /// Currently opened module. This field is a pointer in the reference
216216 /// implementation, but that won't work on 64-bit systems, and anyway it
242242 /// Padding so the next field is 4-byte aligned.
243243 char Padding1[2];
244244
245 /// Array of [0..NumFiles) DBI name buffer offsets. This field is a pointer
246 /// in the reference implementation, but as with `Mod`, we ignore it for now
247 /// since it is unused.
245 /// Array of [0..NumFiles) DBI name buffer offsets. In the reference
246 /// implementation this field is a pointer. But since you can't portably
247 /// serialize a pointer, on 64-bit platforms they copy all the values except
248 /// this one into the 32-bit version of the struct and use that for
249 /// serialization. Regardless, this field is unused, it is only there to
250 /// store a pointer that can be accessed at runtime.
248251 support::ulittle32_t FileNameOffs;
249252
250253 /// Name Index for src file name
114114 for (unsigned I = 0; I < N; ++I) {
115115 // We are done with the current record, discard it so that we are
116116 // positioned at the next record.
117 AbsOffset += ThisLen;
117118 IterRef = IterRef.drop_front(ThisLen);
118119 if (IterRef.getLength() == 0) {
119120 // There is nothing after the current record, we must make this an end
134135 return *this;
135136 }
136137
138 uint32_t offset() const { return AbsOffset; }
139
137140 private:
138141 void moveToEnd() {
139142 Array = nullptr;
151154 const WrappedCtx *Ctx{nullptr};
152155 const ArrayType *Array{nullptr};
153156 uint32_t ThisLen{0};
157 uint32_t AbsOffset{0};
154158 bool HasError{false};
155159 bool *HadError{nullptr};
156160 };
2929 add_pdb_impl_folder(Native
3030 Native/DbiModuleDescriptor.cpp
3131 Native/DbiModuleDescriptorBuilder.cpp
32 Native/DbiModuleList.cpp
3233 Native/DbiStream.cpp
3334 Native/DbiStreamBuilder.cpp
3435 Native/EnumTables.cpp
0 //===- DbiModuleList.cpp - PDB module information list ----------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
9
10 #include "llvm/DebugInfo/PDB/Native/RawError.h"
11 #include "llvm/Support/Error.h"
12
13 using namespace llvm;
14 using namespace llvm::pdb;
15
16 DbiModuleSourceFilesIterator::DbiModuleSourceFilesIterator(
17 const DbiModuleList &Modules, uint32_t Modi, uint16_t Filei)
18 : Modules(&Modules), Modi(Modi), Filei(Filei) {
19 setValue();
20 }
21
22 bool DbiModuleSourceFilesIterator::
23 operator==(const DbiModuleSourceFilesIterator &R) const {
24 // incompatible iterators are never equal
25 if (!isCompatible(R))
26 return false;
27
28 // If they're compatible, and they're both ends, then they're equal.
29 if (isEnd() && R.isEnd())
30 return true;
31
32 // If one is an end and the other is not, they're not equal.
33 if (isEnd() != R.isEnd())
34 return false;
35
36 // Now we know:
37 // - They're compatible
38 // - They're not *both* end iterators
39 // - Their endness is the same.
40 // Thus, they're compatible iterators pointing to a valid file on the same
41 // module. All we need to check are the file indices.
42 assert(Modules == R.Modules);
43 assert(Modi == R.Modi);
44 assert(!isEnd());
45 assert(!R.isEnd());
46
47 return (Filei == R.Filei);
48 }
49
50 bool DbiModuleSourceFilesIterator::
51 operator<(const DbiModuleSourceFilesIterator &R) const {
52 assert(isCompatible(R));
53
54 // It's not sufficient to compare the file indices, because default
55 // constructed iterators could be equal to iterators with valid indices. To
56 // account for this, early-out if they're equal.
57 if (*this == R)
58 return false;
59
60 return Filei < R.Filei;
61 }
62
63 std::ptrdiff_t DbiModuleSourceFilesIterator::
64 operator-(const DbiModuleSourceFilesIterator &R) const {
65 assert(isCompatible(R));
66 assert(!(*this < R));
67
68 // If they're both end iterators, the distance is 0.
69 if (isEnd() && R.isEnd())
70 return 0;
71
72 assert(!R.isEnd());
73
74 // At this point, R cannot be end, but *this can, which means that *this
75 // might be a universal end iterator with none of its fields set. So in that
76 // case have to rely on R as the authority to figure out how many files there
77 // are to compute the distance.
78 uint32_t Thisi = Filei;
79 if (isEnd()) {
80 uint32_t RealModi = R.Modi;
81 Thisi = R.Modules->getSourceFileCount(RealModi);
82 }
83
84 assert(Thisi >= R.Filei);
85 return Thisi - R.Filei;
86 }
87
88 DbiModuleSourceFilesIterator &DbiModuleSourceFilesIterator::
89 operator+=(std::ptrdiff_t N) {
90 assert(!isEnd());
91
92 Filei += N;
93 assert(Filei <= Modules->getSourceFileCount(Modi));
94 setValue();
95 return *this;
96 }
97
98 DbiModuleSourceFilesIterator &DbiModuleSourceFilesIterator::
99 operator-=(std::ptrdiff_t N) {
100 // Note that we can subtract from an end iterator, but not a universal end
101 // iterator.
102 assert(!isUniversalEnd());
103
104 assert(N <= Filei);
105
106 Filei -= N;
107 return *this;
108 }
109
110 void DbiModuleSourceFilesIterator::setValue() {
111 if (isEnd()) {
112 ThisValue = "";
113 return;
114 }
115
116 uint32_t Off = Modules->ModuleInitialFileIndex[Modi] + Filei;
117 auto ExpectedValue = Modules->getFileName(Off);
118 if (!ExpectedValue) {
119 consumeError(ExpectedValue.takeError());
120 Filei = Modules->getSourceFileCount(Modi);
121 } else
122 ThisValue = *ExpectedValue;
123 }
124
125 bool DbiModuleSourceFilesIterator::isEnd() const {
126 if (isUniversalEnd())
127 return true;
128
129 assert(Modules);
130 assert(Modi <= Modules->getModuleCount());
131 assert(Filei <= Modules->getSourceFileCount(Modi));
132
133 if (Modi == Modules->getModuleCount())
134 return true;
135 if (Filei == Modules->getSourceFileCount(Modi))
136 return true;
137 return false;
138 }
139
140 bool DbiModuleSourceFilesIterator::isUniversalEnd() const { return !Modules; }
141
142 bool DbiModuleSourceFilesIterator::isCompatible(
143 const DbiModuleSourceFilesIterator &R) const {
144 // Universal iterators are compatible with any other iterator.
145 if (isUniversalEnd() || R.isUniversalEnd())
146 return true;
147
148 // At this point, neither iterator is a universal end iterator, although one
149 // or both might be non-universal end iterators. Regardless, the module index
150 // is valid, so they are compatible if and only if they refer to the same
151 // module.
152 return Modi == R.Modi;
153 }
154
155 Error DbiModuleList::initialize(BinaryStreamRef ModInfo,
156 BinaryStreamRef FileInfo) {
157 if (auto EC = initializeModInfo(ModInfo))
158 return EC;
159 if (auto EC = initializeFileInfo(FileInfo))
160 return EC;
161
162 return Error::success();
163 }
164
165 Error DbiModuleList::initializeModInfo(BinaryStreamRef ModInfo) {
166 ModInfoSubstream = ModInfo;
167
168 if (ModInfo.getLength() == 0)
169 return Error::success();
170
171 BinaryStreamReader Reader(ModInfo);
172
173 if (auto EC = Reader.readArray(Descriptors, ModInfo.getLength()))
174 return EC;
175
176 return Error::success();
177 }
178
179 Error DbiModuleList::initializeFileInfo(BinaryStreamRef FileInfo) {
180 FileInfoSubstream = FileInfo;
181
182 if (FileInfo.getLength() == 0)
183 return Error::success();
184
185 BinaryStreamReader FISR(FileInfo);
186 if (auto EC = FISR.readObject(FileInfoHeader))
187 return EC;
188
189 // First is an array of `NumModules` module indices. This does not seem to be
190 // used for anything meaningful, so we ignore it.
191 FixedStreamArray ModuleIndices;
192 if (auto EC = FISR.readArray(ModuleIndices, FileInfoHeader->NumModules))
193 return EC;
194 if (auto EC = FISR.readArray(ModFileCountArray, FileInfoHeader->NumModules))
195 return EC;
196
197 // Compute the real number of source files. We can't trust the value in
198 // `FileInfoHeader->NumSourceFiles` because it is a unit16, and the sum of all
199 // source file counts might be larger than a unit16. So we compute the real
200 // count by summing up the individual counts.
201 uint32_t NumSourceFiles = 0;
202 for (auto Count : ModFileCountArray)
203 NumSourceFiles += Count;
204
205 // In the reference implementation, this array is where the pointer documented
206 // at the definition of ModuleInfoHeader::FileNameOffs points to. Note that
207 // although the field in ModuleInfoHeader is ignored this array is not, as it
208 // is the authority on where each filename begins in the names buffer.
209 if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles))
210 return EC;
211
212 if (auto EC = FISR.readStreamRef(NamesBuffer))
213 return EC;
214
215 auto DescriptorIter = Descriptors.begin();
216 uint32_t NextFileIndex = 0;
217 ModuleInitialFileIndex.resize(FileInfoHeader->NumModules);
218 ModuleDescriptorOffsets.resize(FileInfoHeader->NumModules);
219 for (size_t I = 0; I < FileInfoHeader->NumModules; ++I) {
220 assert(DescriptorIter != Descriptors.end());
221 ModuleInitialFileIndex[I] = NextFileIndex;
222 ModuleDescriptorOffsets[I] = DescriptorIter.offset();
223
224 NextFileIndex += ModFileCountArray[I];
225 ++DescriptorIter;
226 }
227
228 assert(DescriptorIter == Descriptors.end());
229 assert(NextFileIndex == NumSourceFiles);
230
231 return Error::success();
232 }
233
234 uint32_t DbiModuleList::getModuleCount() const {
235 return FileInfoHeader->NumModules;
236 }
237
238 uint32_t DbiModuleList::getSourceFileCount() const {
239 return FileNameOffsets.size();
240 }
241
242 uint16_t DbiModuleList::getSourceFileCount(uint32_t Modi) const {
243 return ModFileCountArray[Modi];
244 }
245
246 DbiModuleDescriptor DbiModuleList::getModuleDescriptor(uint32_t Modi) const {
247 assert(Modi < getModuleCount());
248 uint32_t Offset = ModuleDescriptorOffsets[Modi];
249 auto Iter = Descriptors.at(Offset);
250 assert(Iter != Descriptors.end());
251 return *Iter;
252 }
253
254 iterator_range
255 DbiModuleList::source_files(uint32_t Modi) const {
256 return make_range(
257 DbiModuleSourceFilesIterator(*this, Modi, 0),
258 DbiModuleSourceFilesIterator());
259 }
260
261 Expected DbiModuleList::getFileName(uint32_t Index) const {
262 BinaryStreamReader Names(NamesBuffer);
263 if (Index >= getSourceFileCount())
264 return make_error(raw_error_code::index_out_of_bounds);
265
266 uint32_t FileOffset = FileNameOffsets[Index];
267 Names.setOffset(FileOffset);
268 StringRef Name;
269 if (auto EC = Names.readCString(Name))
270 return std::move(EC);
271 return Name;
272 }
106106 return make_error(raw_error_code::corrupt_file,
107107 "DBI type server substream not aligned.");
108108
109 BinaryStreamRef ModInfoSubstream;
110 BinaryStreamRef FileInfoSubstream;
109111 if (auto EC =
110112 Reader.readStreamRef(ModInfoSubstream, Header->ModiSubstreamSize))
111113 return EC;
112 if (auto EC = initializeModInfoArray())
113 return EC;
114114
115115 if (auto EC = Reader.readStreamRef(SecContrSubstream,
116116 Header->SecContrSubstreamSize))
128128 DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))
129129 return EC;
130130
131 if (auto EC = Modules.initialize(ModInfoSubstream, FileInfoSubstream))
132 return EC;
133
131134 if (auto EC = initializeSectionContributionData())
132135 return EC;
133136 if (auto EC = initializeSectionHeadersData())
134137 return EC;
135138 if (auto EC = initializeSectionMapData())
136 return EC;
137 if (auto EC = initializeFileInfo())
138139 return EC;
139140 if (auto EC = initializeFpoRecords())
140141 return EC;
214215 return FpoRecords;
215216 }
216217
217 ArrayRef DbiStream::modules() const { return ModuleInfos; }
218 const DbiModuleList &DbiStream::modules() const { return Modules; }
219
218220 FixedStreamArray DbiStream::getSectionMap() const {
219221 return SectionMap;
220222 }
247249 "Unsupported DBI Section Contribution version");
248250 }
249251
250 Error DbiStream::initializeModInfoArray() {
251 if (ModInfoSubstream.getLength() == 0)
252 return Error::success();
253
254 // Since each DbiModuleDescriptor in the stream is a variable length, we have
255 // to iterate
256 // them to know how many there actually are.
257 BinaryStreamReader Reader(ModInfoSubstream);
258
259 VarStreamArray ModInfoArray;
260 if (auto EC = Reader.readArray(ModInfoArray, ModInfoSubstream.getLength()))
261 return EC;
262 for (auto &Info : ModInfoArray) {
263 ModuleInfos.emplace_back(Info);
264 }
265
266 return Error::success();
267 }
268
269252 // Initializes this->SectionHeaders.
270253 Error DbiStream::initializeSectionHeadersData() {
271254 if (DbgStreams.size() == 0)
334317 return EC;
335318 if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
336319 return EC;
337 return Error::success();
338 }
339
340 Error DbiStream::initializeFileInfo() {
341 if (FileInfoSubstream.getLength() == 0)
342 return Error::success();
343
344 const FileInfoSubstreamHeader *FH;
345 BinaryStreamReader FISR(FileInfoSubstream);
346 if (auto EC = FISR.readObject(FH))
347 return EC;
348
349 // The number of modules in the stream should be the same as reported by
350 // the FileInfoSubstreamHeader.
351 if (FH->NumModules != ModuleInfos.size())
352 return make_error(raw_error_code::corrupt_file,
353 "FileInfo substream count doesn't match DBI.");
354
355 FixedStreamArray ModIndexArray;
356 FixedStreamArray ModFileCountArray;
357
358 // First is an array of `NumModules` module indices. This is not used for the
359 // same reason that `NumSourceFiles` is not used. It's an array of uint16's,
360 // but it's possible there are more than 64k source files, which would imply
361 // more than 64k modules (e.g. object files) as well. So we ignore this
362 // field.
363 if (auto EC = FISR.readArray(ModIndexArray, ModuleInfos.size()))
364 return EC;
365 if (auto EC = FISR.readArray(ModFileCountArray, ModuleInfos.size()))
366 return EC;
367
368 // Compute the real number of source files.
369 uint32_t NumSourceFiles = 0;
370 for (auto Count : ModFileCountArray)
371 NumSourceFiles += Count;
372
373 // This is the array that in the reference implementation corresponds to
374 // `DbiModuleDescriptor::FileLayout::FileNameOffs`, which is commented there
375 // as being a
376 // pointer. Due to the mentioned problems of pointers causing difficulty
377 // when reading from the file on 64-bit systems, we continue to ignore that
378 // field in `DbiModuleDescriptor`, and instead build a vector of StringRefs
379 // and stores
380 // them in `ModuleInfoEx`. The value written to and read from the file is
381 // not used anyway, it is only there as a way to store the offsets for the
382 // purposes of later accessing the names at runtime.
383 if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles))
384 return EC;
385
386 if (auto EC = FISR.readStreamRef(NamesBuffer))
387 return EC;
388
389 // We go through each ModuleInfo, determine the number N of source files for
390 // that module, and then get the next N offsets from the Offsets array, using
391 // them to get the corresponding N names from the Names buffer and associating
392 // each one with the corresponding module.
393 uint32_t NextFileIndex = 0;
394 for (size_t I = 0; I < ModuleInfos.size(); ++I) {
395 uint32_t NumFiles = ModFileCountArray[I];
396 ModuleInfos[I].SourceFiles.resize(NumFiles);
397 for (size_t J = 0; J < NumFiles; ++J, ++NextFileIndex) {
398 auto ThisName = getFileNameForIndex(NextFileIndex);
399 if (!ThisName)
400 return ThisName.takeError();
401 ModuleInfos[I].SourceFiles[J] = *ThisName;
402 }
403 }
404
405320 return Error::success();
406321 }
407322
411326 return kInvalidStreamIndex;
412327 return DbgStreams[T];
413328 }
414
415 Expected DbiStream::getFileNameForIndex(uint32_t Index) const {
416 BinaryStreamReader Names(NamesBuffer);
417 if (Index >= FileNameOffsets.size())
418 return make_error(raw_error_code::index_out_of_bounds);
419
420 uint32_t FileOffset = FileNameOffsets[Index];
421 Names.setOffset(FileOffset);
422 StringRef Name;
423 if (auto EC = Names.readCString(Name))
424 return std::move(EC);
425 return Name;
426 }
1212 namespace pdb {
1313
1414 NativeCompilandSymbol::NativeCompilandSymbol(NativeSession &Session,
15 const ModuleInfoEx &MI)
15 DbiModuleDescriptor MI)
1616 : NativeRawSymbol(Session), Module(MI) {}
1717
1818 PDB_SymType NativeCompilandSymbol::getSymTag() const {
2020 }
2121
2222 bool NativeCompilandSymbol::isEditAndContinueEnabled() const {
23 return Module.Info.hasECInfo();
23 return Module.hasECInfo();
2424 }
2525
2626 uint32_t NativeCompilandSymbol::getLexicalParentId() const { return 0; }
3131 // this potential confusion.
3232
3333 std::string NativeCompilandSymbol::getLibraryName() const {
34 return Module.Info.getObjFileName();
34 return Module.getObjFileName();
3535 }
3636
3737 std::string NativeCompilandSymbol::getName() const {
38 return Module.Info.getModuleName();
38 return Module.getModuleName();
3939 }
4040
4141 } // namespace pdb
99 #include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h"
1010
1111 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
12 #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
1213 #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
1314 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
1415 #include "llvm/DebugInfo/PDB/PDBSymbol.h"
1819 namespace pdb {
1920
2021 NativeEnumModules::NativeEnumModules(NativeSession &PDBSession,
21 ArrayRef Modules,
22 const DbiModuleList &Modules,
2223 uint32_t Index)
2324 : Session(PDBSession), Modules(Modules), Index(Index) {}
2425
2526 uint32_t NativeEnumModules::getChildCount() const {
26 return static_cast(Modules.size());
27 return static_cast(Modules.getModuleCount());
2728 }
2829
2930 std::unique_ptr
3031 NativeEnumModules::getChildAtIndex(uint32_t Index) const {
31 if (Index >= Modules.size())
32 if (Index >= Modules.getModuleCount())
3233 return nullptr;
33 return std::unique_ptr(new PDBSymbolCompiland(Session,
34 std::unique_ptr(
35 new NativeCompilandSymbol(Session, Modules[Index]))));
34 return std::unique_ptr(new PDBSymbolCompiland(
35 Session, std::unique_ptr(new NativeCompilandSymbol(
36 Session, Modules.getModuleDescriptor(Index)))));
3637 }
3738
3839 std::unique_ptr NativeEnumModules::getNext() {
39 if (Index >= Modules.size())
40 if (Index >= Modules.getModuleCount())
4041 return nullptr;
4142 return getChildAtIndex(Index++);
4243 }
2525 case PDB_SymType::Compiland: {
2626 auto Dbi = File.getPDBDbiStream();
2727 if (Dbi) {
28 const auto Modules = Dbi->modules();
28 const DbiModuleList &Modules = Dbi->modules();
2929 return std::unique_ptr(
3030 new NativeEnumModules(Session, Modules));
3131 }
774774
775775 if (DumpModules) {
776776 ListScope L(P, "Modules");
777 for (auto &Modi : DS->modules()) {
777 const DbiModuleList &Modules = DS->modules();
778 for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {
779 const DbiModuleDescriptor &Modi = Modules.getModuleDescriptor(I);
778780 DictScope DD(P);
779 P.printString("Name", Modi.Info.getModuleName().str());
780 P.printNumber("Debug Stream Index", Modi.Info.getModuleStreamIndex());
781 P.printString("Object File Name", Modi.Info.getObjFileName().str());
782 P.printNumber("Num Files", Modi.Info.getNumberOfFiles());
783 P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex());
784 P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex());
785 P.printNumber("Line Info Byte Size", Modi.Info.getC11LineInfoByteSize());
786 P.printNumber("C13 Line Info Byte Size",
787 Modi.Info.getC13LineInfoByteSize());
788 P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize());
789 P.printNumber("Type Server Index", Modi.Info.getTypeServerIndex());
790 P.printBoolean("Has EC Info", Modi.Info.hasECInfo());
781 P.printString("Name", Modi.getModuleName().str());
782 P.printNumber("Debug Stream Index", Modi.getModuleStreamIndex());
783 P.printString("Object File Name", Modi.getObjFileName().str());
784 P.printNumber("Num Files", Modi.getNumberOfFiles());
785 P.printNumber("Source File Name Idx", Modi.getSourceFileNameIndex());
786 P.printNumber("Pdb File Name Idx", Modi.getPdbFilePathNameIndex());
787 P.printNumber("Line Info Byte Size", Modi.getC11LineInfoByteSize());
788 P.printNumber("C13 Line Info Byte Size", Modi.getC13LineInfoByteSize());
789 P.printNumber("Symbol Byte Size", Modi.getSymbolDebugInfoByteSize());
790 P.printNumber("Type Server Index", Modi.getTypeServerIndex());
791 P.printBoolean("Has EC Info", Modi.hasECInfo());
791792 if (opts::raw::DumpModuleFiles) {
792 std::string FileListName =
793 to_string(Modi.SourceFiles.size()) + " Contributing Source Files";
793 std::string FileListName = to_string(Modules.getSourceFileCount(I)) +
794 " Contributing Source Files";
794795 ListScope LL(P, FileListName);
795 for (auto File : Modi.SourceFiles)
796 P.printString(File.str());
796 for (auto File : Modules.source_files(I))
797 P.printString(File);
797798 }
798 bool HasModuleDI =
799 (Modi.Info.getModuleStreamIndex() < File.getNumStreams());
799 bool HasModuleDI = (Modi.getModuleStreamIndex() < File.getNumStreams());
800800 bool ShouldDumpSymbols =
801801 (opts::raw::DumpModuleSyms || opts::raw::DumpSymRecordBytes);
802802 if (HasModuleDI && (ShouldDumpSymbols || opts::raw::DumpLineInfo)) {
803803 auto ModStreamData = MappedBlockStream::createIndexedStream(
804804 File.getMsfLayout(), File.getMsfBuffer(),
805 Modi.Info.getModuleStreamIndex());
806
807 ModuleDebugStreamRef ModS(Modi.Info, std::move(ModStreamData));
805 Modi.getModuleStreamIndex());
806
807 ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
808808 if (auto EC = ModS.reload())
809809 return EC;
810810
875875 {
876876 DictScope DD(P, "Module");
877877 P.printNumber("Index", SC.Imod);
878 auto M = DS.modules();
879 if (M.size() > SC.Imod) {
880 P.printString("Name", M[SC.Imod].Info.getModuleName());
878 const DbiModuleList &Modules = DS.modules();
879 if (Modules.getModuleCount() > SC.Imod) {
880 P.printString("Name",
881 Modules.getModuleDescriptor(SC.Imod).getModuleName());
881882 }
882883 }
883884 P.printNumber("Data CRC", SC.DataCrc);
1111 #include "llvm/ADT/DenseMap.h"
1212 #include "llvm/ADT/DenseMapInfo.h"
1313 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
14 #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
1415 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
1516 #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
1617 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
2930 auto Info = File.getPDBInfoStream();
3031
3132 uint32_t StreamCount = File.getNumStreams();
32 DenseMapconst ModuleInfoEx *> ModStreams;
33 DenseMapDbiModuleDescriptor> ModStreams;
3334 DenseMap NamedStreams;
3435
3536 if (Dbi) {
36 for (auto &ModI : Dbi->modules()) {
37 uint16_t SN = ModI.Info.getModuleStreamIndex();
37 const DbiModuleList &Modules = Dbi->modules();
38 for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {
39 DbiModuleDescriptor Descriptor = Modules.getModuleDescriptor(I);
40 uint16_t SN = Descriptor.getModuleStreamIndex();
3841 if (SN != kInvalidStreamIndex)
39 ModStreams[SN] = &ModI;
42 ModStreams[SN] = Descriptor;
4043 }
4144 }
4245 if (Info) {
108111 auto NSIter = NamedStreams.find(StreamIdx);
109112 if (ModIter != ModStreams.end()) {
110113 Value = "Module \"";
111 Value += ModIter->second->Info.getModuleName().str();
114 Value += ModIter->second.getModuleName();
112115 Value += "\"";
113116 } else if (NSIter != NamedStreams.end()) {
114117 Value = "Named Stream \"";
304304 Obj.DbiStream->PdbDllVersion = DS.getPdbDllVersion();
305305 Obj.DbiStream->VerHeader = DS.getDbiVersion();
306306 if (opts::pdb2yaml::DbiModuleInfo) {
307 for (const auto &MI : DS.modules()) {
307 const auto &Modules = DS.modules();
308 for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {
309 DbiModuleDescriptor MI = Modules.getModuleDescriptor(I);
310
308311 Obj.DbiStream->ModInfos.emplace_back();
309312 yaml::PdbDbiModuleInfo &DMI = Obj.DbiStream->ModInfos.back();
310313
311 DMI.Mod = MI.Info.getModuleName();
312 DMI.Obj = MI.Info.getObjFileName();
313 if (opts::pdb2yaml::DbiModuleSourceFileInfo)
314 DMI.SourceFiles = MI.SourceFiles;
315
316 uint16_t ModiStream = MI.Info.getModuleStreamIndex();
314 DMI.Mod = MI.getModuleName();
315 DMI.Obj = MI.getObjFileName();
316 if (opts::pdb2yaml::DbiModuleSourceFileInfo) {
317 auto Files = Modules.source_files(I);
318 DMI.SourceFiles.assign(Files.begin(), Files.end());
319 }
320
321 uint16_t ModiStream = MI.getModuleStreamIndex();
317322 if (ModiStream == kInvalidStreamIndex)
318323 continue;
319324
320325 auto ModStreamData = msf::MappedBlockStream::createIndexedStream(
321326 File.getMsfLayout(), File.getMsfBuffer(), ModiStream);
322327
323 pdb::ModuleDebugStreamRef ModS(MI.Info, std::move(ModStreamData));
328 pdb::ModuleDebugStreamRef ModS(MI, std::move(ModStreamData));
324329 if (auto EC = ModS.reload())
325330 return EC;
326331