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