1 //===- InfoStream.cpp - PDB Info Stream (Stream 1) Access -------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
10 #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
11 #include "llvm/DebugInfo/PDB/Native/RawError.h"
12 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
13 #include "llvm/Support/BinaryStreamReader.h"
14 
15 using namespace llvm;
16 using namespace llvm::codeview;
17 // using namespace llvm::msf;
18 using namespace llvm::pdb;
19 
20 InfoStream::InfoStream(std::unique_ptr<BinaryStream> Stream)
21     : Stream(std::move(Stream)), Header(nullptr) {}
22 
23 Error InfoStream::reload() {
24   BinaryStreamReader Reader(*Stream);
25 
26   if (auto EC = Reader.readObject(Header))
27     return joinErrors(
28         std::move(EC),
29         make_error<RawError>(raw_error_code::corrupt_file,
30                              "PDB Stream does not contain a header."));
31 
32   switch (Header->Version) {
33   case PdbImplVC70:
34   case PdbImplVC80:
35   case PdbImplVC110:
36   case PdbImplVC140:
37     break;
38   default:
39     return make_error<RawError>(raw_error_code::corrupt_file,
40                                 "Unsupported PDB stream version.");
41   }
42 
43   uint32_t Offset = Reader.getOffset();
44   if (auto EC = NamedStreams.load(Reader))
45     return EC;
46   uint32_t NewOffset = Reader.getOffset();
47   NamedStreamMapByteSize = NewOffset - Offset;
48 
49   Reader.setOffset(Offset);
50   if (auto EC = Reader.readSubstream(SubNamedStreams, NamedStreamMapByteSize))
51     return EC;
52 
53   bool Stop = false;
54   while (!Stop && !Reader.empty()) {
55     PdbRaw_FeatureSig Sig;
56     if (auto EC = Reader.readEnum(Sig))
57       return EC;
58     // Since this value comes from a file, it's possible we have some strange
59     // value which doesn't correspond to any value.  We don't want to warn on
60     // -Wcovered-switch-default in this case, so switch on the integral value
61     // instead of the enumeration value.
62     switch (uint32_t(Sig)) {
63     case uint32_t(PdbRaw_FeatureSig::VC110):
64       // No other flags for VC110 PDB.
65       Stop = true;
66       LLVM_FALLTHROUGH;
67     case uint32_t(PdbRaw_FeatureSig::VC140):
68       Features |= PdbFeatureContainsIdStream;
69       break;
70     case uint32_t(PdbRaw_FeatureSig::NoTypeMerge):
71       Features |= PdbFeatureNoTypeMerging;
72       break;
73     case uint32_t(PdbRaw_FeatureSig::MinimalDebugInfo):
74       Features |= PdbFeatureMinimalDebugInfo;
75       break;
76     default:
77       continue;
78     }
79     FeatureSignatures.push_back(Sig);
80   }
81   return Error::success();
82 }
83 
84 uint32_t InfoStream::getStreamSize() const { return Stream->getLength(); }
85 
86 Expected<uint32_t> InfoStream::getNamedStreamIndex(llvm::StringRef Name) const {
87   uint32_t Result;
88   if (!NamedStreams.get(Name, Result))
89     return make_error<RawError>(raw_error_code::no_stream);
90   return Result;
91 }
92 
93 StringMap<uint32_t> InfoStream::named_streams() const {
94   return NamedStreams.entries();
95 }
96 
97 bool InfoStream::containsIdStream() const {
98   return !!(Features & PdbFeatureContainsIdStream);
99 }
100 
101 PdbRaw_ImplVer InfoStream::getVersion() const {
102   return static_cast<PdbRaw_ImplVer>(uint32_t(Header->Version));
103 }
104 
105 uint32_t InfoStream::getSignature() const {
106   return uint32_t(Header->Signature);
107 }
108 
109 uint32_t InfoStream::getAge() const { return uint32_t(Header->Age); }
110 
111 GUID InfoStream::getGuid() const { return Header->Guid; }
112 
113 uint32_t InfoStream::getNamedStreamMapByteSize() const {
114   return NamedStreamMapByteSize;
115 }
116 
117 PdbRaw_Features InfoStream::getFeatures() const { return Features; }
118 
119 ArrayRef<PdbRaw_FeatureSig> InfoStream::getFeatureSignatures() const {
120   return FeatureSignatures;
121 }
122 
123 const NamedStreamMap &InfoStream::getNamedStreams() const {
124   return NamedStreams;
125 }
126 
127 BinarySubstreamRef InfoStream::getNamedStreamsBuffer() const {
128   return SubNamedStreams;
129 }
130