1 //===- StreamUtil.cpp - PDB stream utilities --------------------*- 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 "StreamUtil.h" 10 11 #include "llvm/ADT/DenseMap.h" 12 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" 13 #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h" 14 #include "llvm/DebugInfo/PDB/Native/DbiStream.h" 15 #include "llvm/DebugInfo/PDB/Native/FormatUtil.h" 16 #include "llvm/DebugInfo/PDB/Native/InfoStream.h" 17 #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 18 #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 19 20 using namespace llvm; 21 using namespace llvm::pdb; 22 23 std::string StreamInfo::getLongName() const { 24 if (Purpose == StreamPurpose::NamedStream) 25 return formatv("Named Stream \"{0}\"", Name).str(); 26 if (Purpose == StreamPurpose::ModuleStream) 27 return formatv("Module \"{0}\"", Name).str(); 28 return Name; 29 } 30 31 StreamInfo StreamInfo::createStream(StreamPurpose Purpose, StringRef Name, 32 uint32_t StreamIndex) { 33 StreamInfo Result; 34 Result.Name = std::string(Name); 35 Result.StreamIndex = StreamIndex; 36 Result.Purpose = Purpose; 37 return Result; 38 } 39 40 StreamInfo StreamInfo::createModuleStream(StringRef Module, 41 uint32_t StreamIndex, uint32_t Modi) { 42 StreamInfo Result; 43 Result.Name = std::string(Module); 44 Result.StreamIndex = StreamIndex; 45 Result.ModuleIndex = Modi; 46 Result.Purpose = StreamPurpose::ModuleStream; 47 return Result; 48 } 49 50 static inline StreamInfo stream(StreamPurpose Purpose, StringRef Label, 51 uint32_t Idx) { 52 return StreamInfo::createStream(Purpose, Label, Idx); 53 } 54 55 static inline StreamInfo moduleStream(StringRef Label, uint32_t StreamIdx, 56 uint32_t Modi) { 57 return StreamInfo::createModuleStream(Label, StreamIdx, Modi); 58 } 59 60 struct IndexedModuleDescriptor { 61 uint32_t Modi; 62 DbiModuleDescriptor Descriptor; 63 }; 64 65 void llvm::pdb::discoverStreamPurposes(PDBFile &File, 66 SmallVectorImpl<StreamInfo> &Streams) { 67 // It's OK if we fail to load some of these streams, we still attempt to print 68 // what we can. 69 auto Dbi = File.getPDBDbiStream(); 70 auto Tpi = File.getPDBTpiStream(); 71 auto Ipi = File.getPDBIpiStream(); 72 auto Info = File.getPDBInfoStream(); 73 74 uint32_t StreamCount = File.getNumStreams(); 75 DenseMap<uint16_t, IndexedModuleDescriptor> ModStreams; 76 DenseMap<uint16_t, std::string> NamedStreams; 77 78 if (Dbi) { 79 const DbiModuleList &Modules = Dbi->modules(); 80 for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) { 81 IndexedModuleDescriptor IMD; 82 IMD.Modi = I; 83 IMD.Descriptor = Modules.getModuleDescriptor(I); 84 uint16_t SN = IMD.Descriptor.getModuleStreamIndex(); 85 if (SN != kInvalidStreamIndex) 86 ModStreams[SN] = IMD; 87 } 88 } 89 if (Info) { 90 for (auto &NSE : Info->named_streams()) { 91 if (NSE.second != kInvalidStreamIndex) 92 NamedStreams[NSE.second] = std::string(NSE.first()); 93 } 94 } 95 96 Streams.resize(StreamCount); 97 for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) { 98 if (StreamIdx == OldMSFDirectory) 99 Streams[StreamIdx] = 100 stream(StreamPurpose::Other, "Old MSF Directory", StreamIdx); 101 else if (StreamIdx == StreamPDB) 102 Streams[StreamIdx] = stream(StreamPurpose::PDB, "PDB Stream", StreamIdx); 103 else if (StreamIdx == StreamDBI) 104 Streams[StreamIdx] = stream(StreamPurpose::DBI, "DBI Stream", StreamIdx); 105 else if (StreamIdx == StreamTPI) 106 Streams[StreamIdx] = stream(StreamPurpose::TPI, "TPI Stream", StreamIdx); 107 else if (StreamIdx == StreamIPI) 108 Streams[StreamIdx] = stream(StreamPurpose::IPI, "IPI Stream", StreamIdx); 109 else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex()) 110 Streams[StreamIdx] = 111 stream(StreamPurpose::GlobalHash, "Global Symbol Hash", StreamIdx); 112 else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex()) 113 Streams[StreamIdx] = 114 stream(StreamPurpose::PublicHash, "Public Symbol Hash", StreamIdx); 115 else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex()) 116 Streams[StreamIdx] = 117 stream(StreamPurpose::Symbols, "Symbol Records", StreamIdx); 118 else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex()) 119 Streams[StreamIdx] = 120 stream(StreamPurpose::TpiHash, "TPI Hash", StreamIdx); 121 else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex()) 122 Streams[StreamIdx] = 123 stream(StreamPurpose::Other, "TPI Aux Hash", StreamIdx); 124 else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex()) 125 Streams[StreamIdx] = 126 stream(StreamPurpose::IpiHash, "IPI Hash", StreamIdx); 127 else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex()) 128 Streams[StreamIdx] = 129 stream(StreamPurpose::Other, "IPI Aux Hash", StreamIdx); 130 else if (Dbi && 131 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception)) 132 Streams[StreamIdx] = 133 stream(StreamPurpose::Other, "Exception Data", StreamIdx); 134 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup)) 135 Streams[StreamIdx] = 136 stream(StreamPurpose::Other, "Fixup Data", StreamIdx); 137 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO)) 138 Streams[StreamIdx] = stream(StreamPurpose::Other, "FPO Data", StreamIdx); 139 else if (Dbi && 140 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO)) 141 Streams[StreamIdx] = 142 stream(StreamPurpose::Other, "New FPO Data", StreamIdx); 143 else if (Dbi && 144 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc)) 145 Streams[StreamIdx] = 146 stream(StreamPurpose::Other, "Omap From Source Data", StreamIdx); 147 else if (Dbi && 148 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc)) 149 Streams[StreamIdx] = 150 stream(StreamPurpose::Other, "Omap To Source Data", StreamIdx); 151 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata)) 152 Streams[StreamIdx] = stream(StreamPurpose::Other, "Pdata", StreamIdx); 153 else if (Dbi && 154 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr)) 155 Streams[StreamIdx] = 156 stream(StreamPurpose::Other, "Section Header Data", StreamIdx); 157 else if (Dbi && 158 StreamIdx == 159 Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig)) 160 Streams[StreamIdx] = stream(StreamPurpose::Other, 161 "Section Header Original Data", StreamIdx); 162 else if (Dbi && 163 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap)) 164 Streams[StreamIdx] = 165 stream(StreamPurpose::Other, "Token Rid Data", StreamIdx); 166 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata)) 167 Streams[StreamIdx] = stream(StreamPurpose::Other, "Xdata", StreamIdx); 168 else { 169 auto ModIter = ModStreams.find(StreamIdx); 170 auto NSIter = NamedStreams.find(StreamIdx); 171 if (ModIter != ModStreams.end()) { 172 Streams[StreamIdx] = 173 moduleStream(ModIter->second.Descriptor.getModuleName(), StreamIdx, 174 ModIter->second.Modi); 175 } else if (NSIter != NamedStreams.end()) { 176 Streams[StreamIdx] = 177 stream(StreamPurpose::NamedStream, NSIter->second, StreamIdx); 178 } else { 179 Streams[StreamIdx] = stream(StreamPurpose::Other, "???", StreamIdx); 180 } 181 } 182 } 183 184 // Consume errors from missing streams. 185 if (!Dbi) 186 consumeError(Dbi.takeError()); 187 if (!Tpi) 188 consumeError(Tpi.takeError()); 189 if (!Ipi) 190 consumeError(Ipi.takeError()); 191 if (!Info) 192 consumeError(Info.takeError()); 193 } 194