194 lines · cpp
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-exception6//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 20using namespace llvm;21using namespace llvm::pdb;22 23std::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 31StreamInfo 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 40StreamInfo 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 50static inline StreamInfo stream(StreamPurpose Purpose, StringRef Label,51 uint32_t Idx) {52 return StreamInfo::createStream(Purpose, Label, Idx);53}54 55static inline StreamInfo moduleStream(StringRef Label, uint32_t StreamIdx,56 uint32_t Modi) {57 return StreamInfo::createModuleStream(Label, StreamIdx, Modi);58}59 60struct IndexedModuleDescriptor {61 uint32_t Modi;62 DbiModuleDescriptor Descriptor;63};64 65void 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 print68 // 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