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