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 if (Stream->getLength() != 76 sizeof(DbiStreamHeader) + Header->ModiSubstreamSize + 77 Header->SecContrSubstreamSize + Header->SectionMapSize + 78 Header->FileInfoSize + Header->TypeServerSize + 79 Header->OptionalDbgHdrSize + Header->ECSubstreamSize) 80 return make_error<RawError>(raw_error_code::corrupt_file, 81 "DBI Length does not equal sum of substreams."); 82 83 // Only certain substreams are guaranteed to be aligned. Validate 84 // them here. 85 if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0) 86 return make_error<RawError>(raw_error_code::corrupt_file, 87 "DBI MODI substream not aligned."); 88 if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0) 89 return make_error<RawError>( 90 raw_error_code::corrupt_file, 91 "DBI section contribution substream not aligned."); 92 if (Header->SectionMapSize % sizeof(uint32_t) != 0) 93 return make_error<RawError>(raw_error_code::corrupt_file, 94 "DBI section map substream not aligned."); 95 if (Header->FileInfoSize % sizeof(uint32_t) != 0) 96 return make_error<RawError>(raw_error_code::corrupt_file, 97 "DBI file info substream not aligned."); 98 if (Header->TypeServerSize % sizeof(uint32_t) != 0) 99 return make_error<RawError>(raw_error_code::corrupt_file, 100 "DBI type server substream not aligned."); 101 102 if (auto EC = Reader.readSubstream(ModiSubstream, Header->ModiSubstreamSize)) 103 return EC; 104 105 if (auto EC = Reader.readSubstream(SecContrSubstream, 106 Header->SecContrSubstreamSize)) 107 return EC; 108 if (auto EC = Reader.readSubstream(SecMapSubstream, Header->SectionMapSize)) 109 return EC; 110 if (auto EC = Reader.readSubstream(FileInfoSubstream, Header->FileInfoSize)) 111 return EC; 112 if (auto EC = 113 Reader.readSubstream(TypeServerMapSubstream, Header->TypeServerSize)) 114 return EC; 115 if (auto EC = Reader.readSubstream(ECSubstream, Header->ECSubstreamSize)) 116 return EC; 117 if (auto EC = Reader.readArray( 118 DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t))) 119 return EC; 120 121 if (auto EC = Modules.initialize(ModiSubstream.StreamData, 122 FileInfoSubstream.StreamData)) 123 return EC; 124 125 if (auto EC = initializeSectionContributionData()) 126 return EC; 127 if (auto EC = initializeSectionHeadersData()) 128 return EC; 129 if (auto EC = initializeSectionMapData()) 130 return EC; 131 if (auto EC = initializeFpoRecords()) 132 return EC; 133 134 if (Reader.bytesRemaining() > 0) 135 return make_error<RawError>(raw_error_code::corrupt_file, 136 "Found unexpected bytes in DBI Stream."); 137 138 if (!ECSubstream.empty()) { 139 BinaryStreamReader ECReader(ECSubstream.StreamData); 140 if (auto EC = ECNames.reload(ECReader)) 141 return EC; 142 } 143 144 return Error::success(); 145 } 146 147 PdbRaw_DbiVer DbiStream::getDbiVersion() const { 148 uint32_t Value = Header->VersionHeader; 149 return static_cast<PdbRaw_DbiVer>(Value); 150 } 151 152 uint32_t DbiStream::getAge() const { return Header->Age; } 153 154 uint16_t DbiStream::getPublicSymbolStreamIndex() const { 155 return Header->PublicSymbolStreamIndex; 156 } 157 158 uint16_t DbiStream::getGlobalSymbolStreamIndex() const { 159 return Header->GlobalSymbolStreamIndex; 160 } 161 162 uint16_t DbiStream::getFlags() const { return Header->Flags; } 163 164 bool DbiStream::isIncrementallyLinked() const { 165 return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0; 166 } 167 168 bool DbiStream::hasCTypes() const { 169 return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0; 170 } 171 172 bool DbiStream::isStripped() const { 173 return (Header->Flags & DbiFlags::FlagStrippedMask) != 0; 174 } 175 176 uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; } 177 178 uint16_t DbiStream::getBuildMajorVersion() const { 179 return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >> 180 DbiBuildNo::BuildMajorShift; 181 } 182 183 uint16_t DbiStream::getBuildMinorVersion() const { 184 return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >> 185 DbiBuildNo::BuildMinorShift; 186 } 187 188 uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; } 189 190 uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; } 191 192 uint32_t DbiStream::getSymRecordStreamIndex() const { 193 return Header->SymRecordStreamIndex; 194 } 195 196 PDB_Machine DbiStream::getMachineType() const { 197 uint16_t Machine = Header->MachineType; 198 return static_cast<PDB_Machine>(Machine); 199 } 200 201 FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() { 202 return SectionHeaders; 203 } 204 205 FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() { 206 return FpoRecords; 207 } 208 209 const DbiModuleList &DbiStream::modules() const { return Modules; } 210 211 FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const { 212 return SectionMap; 213 } 214 215 void DbiStream::visitSectionContributions( 216 ISectionContribVisitor &Visitor) const { 217 if (!SectionContribs.empty()) { 218 assert(SectionContribVersion == DbiSecContribVer60); 219 for (auto &SC : SectionContribs) 220 Visitor.visit(SC); 221 } else if (!SectionContribs2.empty()) { 222 assert(SectionContribVersion == DbiSecContribV2); 223 for (auto &SC : SectionContribs2) 224 Visitor.visit(SC); 225 } 226 } 227 228 Expected<StringRef> DbiStream::getECName(uint32_t NI) const { 229 return ECNames.getStringForID(NI); 230 } 231 232 Error DbiStream::initializeSectionContributionData() { 233 if (SecContrSubstream.empty()) 234 return Error::success(); 235 236 BinaryStreamReader SCReader(SecContrSubstream.StreamData); 237 if (auto EC = SCReader.readEnum(SectionContribVersion)) 238 return EC; 239 240 if (SectionContribVersion == DbiSecContribVer60) 241 return loadSectionContribs<SectionContrib>(SectionContribs, SCReader); 242 if (SectionContribVersion == DbiSecContribV2) 243 return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader); 244 245 return make_error<RawError>(raw_error_code::feature_unsupported, 246 "Unsupported DBI Section Contribution version"); 247 } 248 249 // Initializes this->SectionHeaders. 250 Error DbiStream::initializeSectionHeadersData() { 251 if (DbgStreams.size() == 0) 252 return Error::success(); 253 254 uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::SectionHdr); 255 if (StreamNum == kInvalidStreamIndex) 256 return Error::success(); 257 258 if (StreamNum >= Pdb.getNumStreams()) 259 return make_error<RawError>(raw_error_code::no_stream); 260 261 auto SHS = MappedBlockStream::createIndexedStream( 262 Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator()); 263 264 size_t StreamLen = SHS->getLength(); 265 if (StreamLen % sizeof(object::coff_section)) 266 return make_error<RawError>(raw_error_code::corrupt_file, 267 "Corrupted section header stream."); 268 269 size_t NumSections = StreamLen / sizeof(object::coff_section); 270 BinaryStreamReader Reader(*SHS); 271 if (auto EC = Reader.readArray(SectionHeaders, NumSections)) 272 return make_error<RawError>(raw_error_code::corrupt_file, 273 "Could not read a bitmap."); 274 275 SectionHeaderStream = std::move(SHS); 276 return Error::success(); 277 } 278 279 // Initializes this->Fpos. 280 Error DbiStream::initializeFpoRecords() { 281 if (DbgStreams.size() == 0) 282 return Error::success(); 283 284 uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::NewFPO); 285 286 // This means there is no FPO data. 287 if (StreamNum == kInvalidStreamIndex) 288 return Error::success(); 289 290 if (StreamNum >= Pdb.getNumStreams()) 291 return make_error<RawError>(raw_error_code::no_stream); 292 293 auto FS = MappedBlockStream::createIndexedStream( 294 Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator()); 295 296 size_t StreamLen = FS->getLength(); 297 if (StreamLen % sizeof(object::FpoData)) 298 return make_error<RawError>(raw_error_code::corrupt_file, 299 "Corrupted New FPO stream."); 300 301 size_t NumRecords = StreamLen / sizeof(object::FpoData); 302 BinaryStreamReader Reader(*FS); 303 if (auto EC = Reader.readArray(FpoRecords, NumRecords)) 304 return make_error<RawError>(raw_error_code::corrupt_file, 305 "Corrupted New FPO stream."); 306 FpoStream = std::move(FS); 307 return Error::success(); 308 } 309 310 BinarySubstreamRef DbiStream::getSectionContributionData() const { 311 return SecContrSubstream; 312 } 313 314 BinarySubstreamRef DbiStream::getSecMapSubstreamData() const { 315 return SecMapSubstream; 316 } 317 318 BinarySubstreamRef DbiStream::getModiSubstreamData() const { 319 return ModiSubstream; 320 } 321 322 BinarySubstreamRef DbiStream::getFileInfoSubstreamData() const { 323 return FileInfoSubstream; 324 } 325 326 BinarySubstreamRef DbiStream::getTypeServerMapSubstreamData() const { 327 return TypeServerMapSubstream; 328 } 329 330 BinarySubstreamRef DbiStream::getECSubstreamData() const { return ECSubstream; } 331 332 Error DbiStream::initializeSectionMapData() { 333 if (SecMapSubstream.empty()) 334 return Error::success(); 335 336 BinaryStreamReader SMReader(SecMapSubstream.StreamData); 337 const SecMapHeader *Header; 338 if (auto EC = SMReader.readObject(Header)) 339 return EC; 340 if (auto EC = SMReader.readArray(SectionMap, Header->SecCount)) 341 return EC; 342 return Error::success(); 343 } 344 345 uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const { 346 uint16_t T = static_cast<uint16_t>(Type); 347 if (T >= DbgStreams.size()) 348 return kInvalidStreamIndex; 349 return DbgStreams[T]; 350 } 351