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/DbiModuleDescriptor.h"
14 #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
15 #include "llvm/DebugInfo/PDB/Native/InfoStream.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 DbiModuleDescriptor in the stream is a variable length, we have
256   // to iterate
257   // them to know how many there actually are.
258   BinaryStreamReader Reader(ModInfoSubstream);
259 
260   VarStreamArray<DbiModuleDescriptor> ModInfoArray;
261   if (auto EC = Reader.readArray(ModInfoArray, ModInfoSubstream.getLength()))
262     return EC;
263   for (auto &Info : ModInfoArray) {
264     ModuleInfos.emplace_back(Info);
265   }
266 
267   return Error::success();
268 }
269 
270 // Initializes this->SectionHeaders.
271 Error DbiStream::initializeSectionHeadersData() {
272   if (DbgStreams.size() == 0)
273     return Error::success();
274 
275   uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::SectionHdr);
276   if (StreamNum >= Pdb.getNumStreams())
277     return make_error<RawError>(raw_error_code::no_stream);
278 
279   auto SHS = MappedBlockStream::createIndexedStream(
280       Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum);
281 
282   size_t StreamLen = SHS->getLength();
283   if (StreamLen % sizeof(object::coff_section))
284     return make_error<RawError>(raw_error_code::corrupt_file,
285                                 "Corrupted section header stream.");
286 
287   size_t NumSections = StreamLen / sizeof(object::coff_section);
288   BinaryStreamReader Reader(*SHS);
289   if (auto EC = Reader.readArray(SectionHeaders, NumSections))
290     return make_error<RawError>(raw_error_code::corrupt_file,
291                                 "Could not read a bitmap.");
292 
293   SectionHeaderStream = std::move(SHS);
294   return Error::success();
295 }
296 
297 // Initializes this->Fpos.
298 Error DbiStream::initializeFpoRecords() {
299   if (DbgStreams.size() == 0)
300     return Error::success();
301 
302   uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::NewFPO);
303 
304   // This means there is no FPO data.
305   if (StreamNum == kInvalidStreamIndex)
306     return Error::success();
307 
308   if (StreamNum >= Pdb.getNumStreams())
309     return make_error<RawError>(raw_error_code::no_stream);
310 
311   auto FS = MappedBlockStream::createIndexedStream(
312       Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum);
313 
314   size_t StreamLen = FS->getLength();
315   if (StreamLen % sizeof(object::FpoData))
316     return make_error<RawError>(raw_error_code::corrupt_file,
317                                 "Corrupted New FPO stream.");
318 
319   size_t NumRecords = StreamLen / sizeof(object::FpoData);
320   BinaryStreamReader Reader(*FS);
321   if (auto EC = Reader.readArray(FpoRecords, NumRecords))
322     return make_error<RawError>(raw_error_code::corrupt_file,
323                                 "Corrupted New FPO stream.");
324   FpoStream = std::move(FS);
325   return Error::success();
326 }
327 
328 Error DbiStream::initializeSectionMapData() {
329   if (SecMapSubstream.getLength() == 0)
330     return Error::success();
331 
332   BinaryStreamReader SMReader(SecMapSubstream);
333   const SecMapHeader *Header;
334   if (auto EC = SMReader.readObject(Header))
335     return EC;
336   if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
337     return EC;
338   return Error::success();
339 }
340 
341 Error DbiStream::initializeFileInfo() {
342   if (FileInfoSubstream.getLength() == 0)
343     return Error::success();
344 
345   const FileInfoSubstreamHeader *FH;
346   BinaryStreamReader FISR(FileInfoSubstream);
347   if (auto EC = FISR.readObject(FH))
348     return EC;
349 
350   // The number of modules in the stream should be the same as reported by
351   // the FileInfoSubstreamHeader.
352   if (FH->NumModules != ModuleInfos.size())
353     return make_error<RawError>(raw_error_code::corrupt_file,
354                                 "FileInfo substream count doesn't match DBI.");
355 
356   FixedStreamArray<ulittle16_t> ModIndexArray;
357   FixedStreamArray<ulittle16_t> ModFileCountArray;
358 
359   // First is an array of `NumModules` module indices.  This is not used for the
360   // same reason that `NumSourceFiles` is not used.  It's an array of uint16's,
361   // but it's possible there are more than 64k source files, which would imply
362   // more than 64k modules (e.g. object files) as well.  So we ignore this
363   // field.
364   if (auto EC = FISR.readArray(ModIndexArray, ModuleInfos.size()))
365     return EC;
366   if (auto EC = FISR.readArray(ModFileCountArray, ModuleInfos.size()))
367     return EC;
368 
369   // Compute the real number of source files.
370   uint32_t NumSourceFiles = 0;
371   for (auto Count : ModFileCountArray)
372     NumSourceFiles += Count;
373 
374   // This is the array that in the reference implementation corresponds to
375   // `DbiModuleDescriptor::FileLayout::FileNameOffs`, which is commented there
376   // as being a
377   // pointer. Due to the mentioned problems of pointers causing difficulty
378   // when reading from the file on 64-bit systems, we continue to ignore that
379   // field in `DbiModuleDescriptor`, and instead build a vector of StringRefs
380   // and stores
381   // them in `ModuleInfoEx`.  The value written to and read from the file is
382   // not used anyway, it is only there as a way to store the offsets for the
383   // purposes of later accessing the names at runtime.
384   if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles))
385     return EC;
386 
387   if (auto EC = FISR.readStreamRef(NamesBuffer))
388     return EC;
389 
390   // We go through each ModuleInfo, determine the number N of source files for
391   // that module, and then get the next N offsets from the Offsets array, using
392   // them to get the corresponding N names from the Names buffer and associating
393   // each one with the corresponding module.
394   uint32_t NextFileIndex = 0;
395   for (size_t I = 0; I < ModuleInfos.size(); ++I) {
396     uint32_t NumFiles = ModFileCountArray[I];
397     ModuleInfos[I].SourceFiles.resize(NumFiles);
398     for (size_t J = 0; J < NumFiles; ++J, ++NextFileIndex) {
399       auto ThisName = getFileNameForIndex(NextFileIndex);
400       if (!ThisName)
401         return ThisName.takeError();
402       ModuleInfos[I].SourceFiles[J] = *ThisName;
403     }
404   }
405 
406   return Error::success();
407 }
408 
409 uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
410   uint16_t T = static_cast<uint16_t>(Type);
411   if (T >= DbgStreams.size())
412     return kInvalidStreamIndex;
413   return DbgStreams[T];
414 }
415 
416 Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const {
417   BinaryStreamReader Names(NamesBuffer);
418   if (Index >= FileNameOffsets.size())
419     return make_error<RawError>(raw_error_code::index_out_of_bounds);
420 
421   uint32_t FileOffset = FileNameOffsets[Index];
422   Names.setOffset(FileOffset);
423   StringRef Name;
424   if (auto EC = Names.readCString(Name))
425     return std::move(EC);
426   return Name;
427 }
428