]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r301441, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / DebugInfo / PDB / Native / DbiStream.cpp
1 //===- DbiStream.cpp - PDB Dbi Stream (Stream 3) Access -------------------===//
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 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
13 #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
14 #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
15 #include "llvm/DebugInfo/PDB/Native/ModInfo.h"
16 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
17 #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
18 #include "llvm/DebugInfo/PDB/Native/RawError.h"
19 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
20 #include "llvm/DebugInfo/PDB/PDBTypes.h"
21 #include "llvm/Object/COFF.h"
22 #include "llvm/Support/BinaryStreamArray.h"
23 #include "llvm/Support/BinaryStreamReader.h"
24 #include "llvm/Support/Error.h"
25 #include <algorithm>
26 #include <cstddef>
27 #include <cstdint>
28
29 using namespace llvm;
30 using namespace llvm::codeview;
31 using namespace llvm::msf;
32 using namespace llvm::pdb;
33 using namespace llvm::support;
34
35 template <typename ContribType>
36 static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
37                                  BinaryStreamReader &Reader) {
38   if (Reader.bytesRemaining() % sizeof(ContribType) != 0)
39     return make_error<RawError>(
40         raw_error_code::corrupt_file,
41         "Invalid number of bytes of section contributions");
42
43   uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);
44   if (auto EC = Reader.readArray(Output, Count))
45     return EC;
46   return Error::success();
47 }
48
49 DbiStream::DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
50     : Pdb(File), Stream(std::move(Stream)), Header(nullptr) {}
51
52 DbiStream::~DbiStream() = default;
53
54 Error DbiStream::reload() {
55   BinaryStreamReader Reader(*Stream);
56
57   if (Stream->getLength() < sizeof(DbiStreamHeader))
58     return make_error<RawError>(raw_error_code::corrupt_file,
59                                 "DBI Stream does not contain a header.");
60   if (auto EC = Reader.readObject(Header))
61     return make_error<RawError>(raw_error_code::corrupt_file,
62                                 "DBI Stream does not contain a header.");
63
64   if (Header->VersionSignature != -1)
65     return make_error<RawError>(raw_error_code::corrupt_file,
66                                 "Invalid DBI version signature.");
67
68   // Require at least version 7, which should be present in all PDBs
69   // produced in the last decade and allows us to avoid having to
70   // special case all kinds of complicated arcane formats.
71   if (Header->VersionHeader < PdbDbiV70)
72     return make_error<RawError>(raw_error_code::feature_unsupported,
73                                 "Unsupported DBI version.");
74
75   auto IS = Pdb.getPDBInfoStream();
76   if (!IS)
77     return IS.takeError();
78
79   if (Header->Age != IS->getAge())
80     return make_error<RawError>(raw_error_code::corrupt_file,
81                                 "DBI Age does not match PDB Age.");
82
83   if (Stream->getLength() !=
84       sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
85           Header->SecContrSubstreamSize + Header->SectionMapSize +
86           Header->FileInfoSize + Header->TypeServerSize +
87           Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
88     return make_error<RawError>(raw_error_code::corrupt_file,
89                                 "DBI Length does not equal sum of substreams.");
90
91   // Only certain substreams are guaranteed to be aligned.  Validate
92   // them here.
93   if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
94     return make_error<RawError>(raw_error_code::corrupt_file,
95                                 "DBI MODI substream not aligned.");
96   if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)
97     return make_error<RawError>(
98         raw_error_code::corrupt_file,
99         "DBI section contribution substream not aligned.");
100   if (Header->SectionMapSize % sizeof(uint32_t) != 0)
101     return make_error<RawError>(raw_error_code::corrupt_file,
102                                 "DBI section map substream not aligned.");
103   if (Header->FileInfoSize % sizeof(uint32_t) != 0)
104     return make_error<RawError>(raw_error_code::corrupt_file,
105                                 "DBI file info substream not aligned.");
106   if (Header->TypeServerSize % sizeof(uint32_t) != 0)
107     return make_error<RawError>(raw_error_code::corrupt_file,
108                                 "DBI type server substream not aligned.");
109
110   if (auto EC =
111           Reader.readStreamRef(ModInfoSubstream, Header->ModiSubstreamSize))
112     return EC;
113   if (auto EC = initializeModInfoArray())
114     return EC;
115
116   if (auto EC = Reader.readStreamRef(SecContrSubstream,
117                                      Header->SecContrSubstreamSize))
118     return EC;
119   if (auto EC = Reader.readStreamRef(SecMapSubstream, Header->SectionMapSize))
120     return EC;
121   if (auto EC = Reader.readStreamRef(FileInfoSubstream, Header->FileInfoSize))
122     return EC;
123   if (auto EC =
124           Reader.readStreamRef(TypeServerMapSubstream, Header->TypeServerSize))
125     return EC;
126   if (auto EC = Reader.readStreamRef(ECSubstream, Header->ECSubstreamSize))
127     return EC;
128   if (auto EC = Reader.readArray(
129           DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))
130     return EC;
131
132   if (auto EC = initializeSectionContributionData())
133     return EC;
134   if (auto EC = initializeSectionHeadersData())
135     return EC;
136   if (auto EC = initializeSectionMapData())
137     return EC;
138   if (auto EC = initializeFileInfo())
139     return EC;
140   if (auto EC = initializeFpoRecords())
141     return EC;
142
143   if (Reader.bytesRemaining() > 0)
144     return make_error<RawError>(raw_error_code::corrupt_file,
145                                 "Found unexpected bytes in DBI Stream.");
146
147   if (ECSubstream.getLength() > 0) {
148     BinaryStreamReader ECReader(ECSubstream);
149     if (auto EC = ECNames.load(ECReader))
150       return EC;
151   }
152
153   return Error::success();
154 }
155
156 PdbRaw_DbiVer DbiStream::getDbiVersion() const {
157   uint32_t Value = Header->VersionHeader;
158   return static_cast<PdbRaw_DbiVer>(Value);
159 }
160
161 uint32_t DbiStream::getAge() const { return Header->Age; }
162
163 uint16_t DbiStream::getPublicSymbolStreamIndex() const {
164   return Header->PublicSymbolStreamIndex;
165 }
166
167 uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
168   return Header->GlobalSymbolStreamIndex;
169 }
170
171 uint16_t DbiStream::getFlags() const { return Header->Flags; }
172
173 bool DbiStream::isIncrementallyLinked() const {
174   return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;
175 }
176
177 bool DbiStream::hasCTypes() const {
178   return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;
179 }
180
181 bool DbiStream::isStripped() const {
182   return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;
183 }
184
185 uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
186
187 uint16_t DbiStream::getBuildMajorVersion() const {
188   return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>
189          DbiBuildNo::BuildMajorShift;
190 }
191
192 uint16_t DbiStream::getBuildMinorVersion() const {
193   return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>
194          DbiBuildNo::BuildMinorShift;
195 }
196
197 uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
198
199 uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }
200
201 uint32_t DbiStream::getSymRecordStreamIndex() const {
202   return Header->SymRecordStreamIndex;
203 }
204
205 PDB_Machine DbiStream::getMachineType() const {
206   uint16_t Machine = Header->MachineType;
207   return static_cast<PDB_Machine>(Machine);
208 }
209
210 FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() {
211   return SectionHeaders;
212 }
213
214 FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() {
215   return FpoRecords;
216 }
217
218 ArrayRef<ModuleInfoEx> DbiStream::modules() const { return ModuleInfos; }
219 FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
220   return SectionMap;
221 }
222
223 void DbiStream::visitSectionContributions(
224     ISectionContribVisitor &Visitor) const {
225   if (SectionContribVersion == DbiSecContribVer60) {
226     for (auto &SC : SectionContribs)
227       Visitor.visit(SC);
228   } else if (SectionContribVersion == DbiSecContribV2) {
229     for (auto &SC : SectionContribs2)
230       Visitor.visit(SC);
231   }
232 }
233
234 Error DbiStream::initializeSectionContributionData() {
235   if (SecContrSubstream.getLength() == 0)
236     return Error::success();
237
238   BinaryStreamReader SCReader(SecContrSubstream);
239   if (auto EC = SCReader.readEnum(SectionContribVersion))
240     return EC;
241
242   if (SectionContribVersion == DbiSecContribVer60)
243     return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);
244   if (SectionContribVersion == DbiSecContribV2)
245     return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);
246
247   return make_error<RawError>(raw_error_code::feature_unsupported,
248                               "Unsupported DBI Section Contribution version");
249 }
250
251 Error DbiStream::initializeModInfoArray() {
252   if (ModInfoSubstream.getLength() == 0)
253     return Error::success();
254
255   // Since each ModInfo in the stream is a variable length, we have to iterate
256   // them to know how many there actually are.
257   BinaryStreamReader Reader(ModInfoSubstream);
258
259   VarStreamArray<ModInfo> 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
269 // Initializes this->SectionHeaders.
270 Error DbiStream::initializeSectionHeadersData() {
271   if (DbgStreams.size() == 0)
272     return Error::success();
273
274   uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::SectionHdr);
275   if (StreamNum >= Pdb.getNumStreams())
276     return make_error<RawError>(raw_error_code::no_stream);
277
278   auto SHS = MappedBlockStream::createIndexedStream(
279       Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum);
280
281   size_t StreamLen = SHS->getLength();
282   if (StreamLen % sizeof(object::coff_section))
283     return make_error<RawError>(raw_error_code::corrupt_file,
284                                 "Corrupted section header stream.");
285
286   size_t NumSections = StreamLen / sizeof(object::coff_section);
287   BinaryStreamReader Reader(*SHS);
288   if (auto EC = Reader.readArray(SectionHeaders, NumSections))
289     return make_error<RawError>(raw_error_code::corrupt_file,
290                                 "Could not read a bitmap.");
291
292   SectionHeaderStream = std::move(SHS);
293   return Error::success();
294 }
295
296 // Initializes this->Fpos.
297 Error DbiStream::initializeFpoRecords() {
298   if (DbgStreams.size() == 0)
299     return Error::success();
300
301   uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::NewFPO);
302
303   // This means there is no FPO data.
304   if (StreamNum == kInvalidStreamIndex)
305     return Error::success();
306
307   if (StreamNum >= Pdb.getNumStreams())
308     return make_error<RawError>(raw_error_code::no_stream);
309
310   auto FS = MappedBlockStream::createIndexedStream(
311       Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum);
312
313   size_t StreamLen = FS->getLength();
314   if (StreamLen % sizeof(object::FpoData))
315     return make_error<RawError>(raw_error_code::corrupt_file,
316                                 "Corrupted New FPO stream.");
317
318   size_t NumRecords = StreamLen / sizeof(object::FpoData);
319   BinaryStreamReader Reader(*FS);
320   if (auto EC = Reader.readArray(FpoRecords, NumRecords))
321     return make_error<RawError>(raw_error_code::corrupt_file,
322                                 "Corrupted New FPO stream.");
323   FpoStream = std::move(FS);
324   return Error::success();
325 }
326
327 Error DbiStream::initializeSectionMapData() {
328   if (SecMapSubstream.getLength() == 0)
329     return Error::success();
330
331   BinaryStreamReader SMReader(SecMapSubstream);
332   const SecMapHeader *Header;
333   if (auto EC = SMReader.readObject(Header))
334     return EC;
335   if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
336     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<RawError>(raw_error_code::corrupt_file,
353                                 "FileInfo substream count doesn't match DBI.");
354
355   FixedStreamArray<ulittle16_t> ModIndexArray;
356   FixedStreamArray<ulittle16_t> 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   // `ModInfo::FileLayout::FileNameOffs`, which is commented there as being a
375   // pointer. Due to the mentioned problems of pointers causing difficulty
376   // when reading from the file on 64-bit systems, we continue to ignore that
377   // field in `ModInfo`, and instead build a vector of StringRefs and stores
378   // them in `ModuleInfoEx`.  The value written to and read from the file is
379   // not used anyway, it is only there as a way to store the offsets for the
380   // purposes of later accessing the names at runtime.
381   if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles))
382     return EC;
383
384   if (auto EC = FISR.readStreamRef(NamesBuffer))
385     return EC;
386
387   // We go through each ModuleInfo, determine the number N of source files for
388   // that module, and then get the next N offsets from the Offsets array, using
389   // them to get the corresponding N names from the Names buffer and associating
390   // each one with the corresponding module.
391   uint32_t NextFileIndex = 0;
392   for (size_t I = 0; I < ModuleInfos.size(); ++I) {
393     uint32_t NumFiles = ModFileCountArray[I];
394     ModuleInfos[I].SourceFiles.resize(NumFiles);
395     for (size_t J = 0; J < NumFiles; ++J, ++NextFileIndex) {
396       auto ThisName = getFileNameForIndex(NextFileIndex);
397       if (!ThisName)
398         return ThisName.takeError();
399       ModuleInfos[I].SourceFiles[J] = *ThisName;
400     }
401   }
402
403   return Error::success();
404 }
405
406 uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
407   uint16_t T = static_cast<uint16_t>(Type);
408   if (T >= DbgStreams.size())
409     return kInvalidStreamIndex;
410   return DbgStreams[T];
411 }
412
413 Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const {
414   BinaryStreamReader Names(NamesBuffer);
415   if (Index >= FileNameOffsets.size())
416     return make_error<RawError>(raw_error_code::index_out_of_bounds);
417
418   uint32_t FileOffset = FileNameOffsets[Index];
419   Names.setOffset(FileOffset);
420   StringRef Name;
421   if (auto EC = Names.readCString(Name))
422     return std::move(EC);
423   return Name;
424 }