Home | History | Annotate | Line # | Download | only in llvm-pdbutil
      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 #include "FormatUtil.h"
     11 
     12 #include "llvm/ADT/DenseMap.h"
     13 #include "llvm/ADT/DenseMapInfo.h"
     14 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
     15 #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
     16 #include "llvm/DebugInfo/PDB/Native/DbiStream.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 (uint16_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