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