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 [[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