xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-pdbutil/StreamUtil.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===- StreamUtil.cpp - PDB stream utilities --------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "StreamUtil.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
120b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
130b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
140b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
15*81ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/Native/FormatUtil.h"
160b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
170b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
180b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric using namespace llvm;
210b57cec5SDimitry Andric using namespace llvm::pdb;
220b57cec5SDimitry Andric 
getLongName() const230b57cec5SDimitry Andric std::string StreamInfo::getLongName() const {
240b57cec5SDimitry Andric   if (Purpose == StreamPurpose::NamedStream)
250b57cec5SDimitry Andric     return formatv("Named Stream \"{0}\"", Name).str();
260b57cec5SDimitry Andric   if (Purpose == StreamPurpose::ModuleStream)
270b57cec5SDimitry Andric     return formatv("Module \"{0}\"", Name).str();
280b57cec5SDimitry Andric   return Name;
290b57cec5SDimitry Andric }
300b57cec5SDimitry Andric 
createStream(StreamPurpose Purpose,StringRef Name,uint32_t StreamIndex)310b57cec5SDimitry Andric StreamInfo StreamInfo::createStream(StreamPurpose Purpose, StringRef Name,
320b57cec5SDimitry Andric                                     uint32_t StreamIndex) {
330b57cec5SDimitry Andric   StreamInfo Result;
345ffd83dbSDimitry Andric   Result.Name = std::string(Name);
350b57cec5SDimitry Andric   Result.StreamIndex = StreamIndex;
360b57cec5SDimitry Andric   Result.Purpose = Purpose;
370b57cec5SDimitry Andric   return Result;
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric 
createModuleStream(StringRef Module,uint32_t StreamIndex,uint32_t Modi)400b57cec5SDimitry Andric StreamInfo StreamInfo::createModuleStream(StringRef Module,
410b57cec5SDimitry Andric                                           uint32_t StreamIndex, uint32_t Modi) {
420b57cec5SDimitry Andric   StreamInfo Result;
435ffd83dbSDimitry Andric   Result.Name = std::string(Module);
440b57cec5SDimitry Andric   Result.StreamIndex = StreamIndex;
450b57cec5SDimitry Andric   Result.ModuleIndex = Modi;
460b57cec5SDimitry Andric   Result.Purpose = StreamPurpose::ModuleStream;
470b57cec5SDimitry Andric   return Result;
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
stream(StreamPurpose Purpose,StringRef Label,uint32_t Idx)500b57cec5SDimitry Andric static inline StreamInfo stream(StreamPurpose Purpose, StringRef Label,
510b57cec5SDimitry Andric                                 uint32_t Idx) {
520b57cec5SDimitry Andric   return StreamInfo::createStream(Purpose, Label, Idx);
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric 
moduleStream(StringRef Label,uint32_t StreamIdx,uint32_t Modi)550b57cec5SDimitry Andric static inline StreamInfo moduleStream(StringRef Label, uint32_t StreamIdx,
560b57cec5SDimitry Andric                                       uint32_t Modi) {
570b57cec5SDimitry Andric   return StreamInfo::createModuleStream(Label, StreamIdx, Modi);
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric struct IndexedModuleDescriptor {
610b57cec5SDimitry Andric   uint32_t Modi;
620b57cec5SDimitry Andric   DbiModuleDescriptor Descriptor;
630b57cec5SDimitry Andric };
640b57cec5SDimitry Andric 
discoverStreamPurposes(PDBFile & File,SmallVectorImpl<StreamInfo> & Streams)650b57cec5SDimitry Andric void llvm::pdb::discoverStreamPurposes(PDBFile &File,
660b57cec5SDimitry Andric                                        SmallVectorImpl<StreamInfo> &Streams) {
670b57cec5SDimitry Andric   // It's OK if we fail to load some of these streams, we still attempt to print
680b57cec5SDimitry Andric   // what we can.
690b57cec5SDimitry Andric   auto Dbi = File.getPDBDbiStream();
700b57cec5SDimitry Andric   auto Tpi = File.getPDBTpiStream();
710b57cec5SDimitry Andric   auto Ipi = File.getPDBIpiStream();
720b57cec5SDimitry Andric   auto Info = File.getPDBInfoStream();
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   uint32_t StreamCount = File.getNumStreams();
750b57cec5SDimitry Andric   DenseMap<uint16_t, IndexedModuleDescriptor> ModStreams;
760b57cec5SDimitry Andric   DenseMap<uint16_t, std::string> NamedStreams;
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   if (Dbi) {
790b57cec5SDimitry Andric     const DbiModuleList &Modules = Dbi->modules();
800b57cec5SDimitry Andric     for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {
810b57cec5SDimitry Andric       IndexedModuleDescriptor IMD;
820b57cec5SDimitry Andric       IMD.Modi = I;
830b57cec5SDimitry Andric       IMD.Descriptor = Modules.getModuleDescriptor(I);
840b57cec5SDimitry Andric       uint16_t SN = IMD.Descriptor.getModuleStreamIndex();
850b57cec5SDimitry Andric       if (SN != kInvalidStreamIndex)
860b57cec5SDimitry Andric         ModStreams[SN] = IMD;
870b57cec5SDimitry Andric     }
880b57cec5SDimitry Andric   }
890b57cec5SDimitry Andric   if (Info) {
900b57cec5SDimitry Andric     for (auto &NSE : Info->named_streams()) {
910b57cec5SDimitry Andric       if (NSE.second != kInvalidStreamIndex)
925ffd83dbSDimitry Andric         NamedStreams[NSE.second] = std::string(NSE.first());
930b57cec5SDimitry Andric     }
940b57cec5SDimitry Andric   }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   Streams.resize(StreamCount);
97*81ad6265SDimitry Andric   for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
980b57cec5SDimitry Andric     if (StreamIdx == OldMSFDirectory)
990b57cec5SDimitry Andric       Streams[StreamIdx] =
1000b57cec5SDimitry Andric           stream(StreamPurpose::Other, "Old MSF Directory", StreamIdx);
1010b57cec5SDimitry Andric     else if (StreamIdx == StreamPDB)
1020b57cec5SDimitry Andric       Streams[StreamIdx] = stream(StreamPurpose::PDB, "PDB Stream", StreamIdx);
1030b57cec5SDimitry Andric     else if (StreamIdx == StreamDBI)
1040b57cec5SDimitry Andric       Streams[StreamIdx] = stream(StreamPurpose::DBI, "DBI Stream", StreamIdx);
1050b57cec5SDimitry Andric     else if (StreamIdx == StreamTPI)
1060b57cec5SDimitry Andric       Streams[StreamIdx] = stream(StreamPurpose::TPI, "TPI Stream", StreamIdx);
1070b57cec5SDimitry Andric     else if (StreamIdx == StreamIPI)
1080b57cec5SDimitry Andric       Streams[StreamIdx] = stream(StreamPurpose::IPI, "IPI Stream", StreamIdx);
1090b57cec5SDimitry Andric     else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex())
1100b57cec5SDimitry Andric       Streams[StreamIdx] =
1110b57cec5SDimitry Andric           stream(StreamPurpose::GlobalHash, "Global Symbol Hash", StreamIdx);
1120b57cec5SDimitry Andric     else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex())
1130b57cec5SDimitry Andric       Streams[StreamIdx] =
1140b57cec5SDimitry Andric           stream(StreamPurpose::PublicHash, "Public Symbol Hash", StreamIdx);
1150b57cec5SDimitry Andric     else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex())
1160b57cec5SDimitry Andric       Streams[StreamIdx] =
1170b57cec5SDimitry Andric           stream(StreamPurpose::Symbols, "Symbol Records", StreamIdx);
1180b57cec5SDimitry Andric     else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex())
1190b57cec5SDimitry Andric       Streams[StreamIdx] =
1200b57cec5SDimitry Andric           stream(StreamPurpose::TpiHash, "TPI Hash", StreamIdx);
1210b57cec5SDimitry Andric     else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex())
1220b57cec5SDimitry Andric       Streams[StreamIdx] =
1230b57cec5SDimitry Andric           stream(StreamPurpose::Other, "TPI Aux Hash", StreamIdx);
1240b57cec5SDimitry Andric     else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex())
1250b57cec5SDimitry Andric       Streams[StreamIdx] =
1260b57cec5SDimitry Andric           stream(StreamPurpose::IpiHash, "IPI Hash", StreamIdx);
1270b57cec5SDimitry Andric     else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex())
1280b57cec5SDimitry Andric       Streams[StreamIdx] =
1290b57cec5SDimitry Andric           stream(StreamPurpose::Other, "IPI Aux Hash", StreamIdx);
1300b57cec5SDimitry Andric     else if (Dbi &&
1310b57cec5SDimitry Andric              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception))
1320b57cec5SDimitry Andric       Streams[StreamIdx] =
1330b57cec5SDimitry Andric           stream(StreamPurpose::Other, "Exception Data", StreamIdx);
1340b57cec5SDimitry Andric     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup))
1350b57cec5SDimitry Andric       Streams[StreamIdx] =
1360b57cec5SDimitry Andric           stream(StreamPurpose::Other, "Fixup Data", StreamIdx);
1370b57cec5SDimitry Andric     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO))
1380b57cec5SDimitry Andric       Streams[StreamIdx] = stream(StreamPurpose::Other, "FPO Data", StreamIdx);
1390b57cec5SDimitry Andric     else if (Dbi &&
1400b57cec5SDimitry Andric              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO))
1410b57cec5SDimitry Andric       Streams[StreamIdx] =
1420b57cec5SDimitry Andric           stream(StreamPurpose::Other, "New FPO Data", StreamIdx);
1430b57cec5SDimitry Andric     else if (Dbi &&
1440b57cec5SDimitry Andric              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
1450b57cec5SDimitry Andric       Streams[StreamIdx] =
1460b57cec5SDimitry Andric           stream(StreamPurpose::Other, "Omap From Source Data", StreamIdx);
1470b57cec5SDimitry Andric     else if (Dbi &&
1480b57cec5SDimitry Andric              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc))
1490b57cec5SDimitry Andric       Streams[StreamIdx] =
1500b57cec5SDimitry Andric           stream(StreamPurpose::Other, "Omap To Source Data", StreamIdx);
1510b57cec5SDimitry Andric     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata))
1520b57cec5SDimitry Andric       Streams[StreamIdx] = stream(StreamPurpose::Other, "Pdata", StreamIdx);
1530b57cec5SDimitry Andric     else if (Dbi &&
1540b57cec5SDimitry Andric              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr))
1550b57cec5SDimitry Andric       Streams[StreamIdx] =
1560b57cec5SDimitry Andric           stream(StreamPurpose::Other, "Section Header Data", StreamIdx);
1570b57cec5SDimitry Andric     else if (Dbi &&
1580b57cec5SDimitry Andric              StreamIdx ==
1590b57cec5SDimitry Andric                  Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
1600b57cec5SDimitry Andric       Streams[StreamIdx] = stream(StreamPurpose::Other,
1610b57cec5SDimitry Andric                                   "Section Header Original Data", StreamIdx);
1620b57cec5SDimitry Andric     else if (Dbi &&
1630b57cec5SDimitry Andric              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap))
1640b57cec5SDimitry Andric       Streams[StreamIdx] =
1650b57cec5SDimitry Andric           stream(StreamPurpose::Other, "Token Rid Data", StreamIdx);
1660b57cec5SDimitry Andric     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata))
1670b57cec5SDimitry Andric       Streams[StreamIdx] = stream(StreamPurpose::Other, "Xdata", StreamIdx);
1680b57cec5SDimitry Andric     else {
1690b57cec5SDimitry Andric       auto ModIter = ModStreams.find(StreamIdx);
1700b57cec5SDimitry Andric       auto NSIter = NamedStreams.find(StreamIdx);
1710b57cec5SDimitry Andric       if (ModIter != ModStreams.end()) {
1720b57cec5SDimitry Andric         Streams[StreamIdx] =
1730b57cec5SDimitry Andric             moduleStream(ModIter->second.Descriptor.getModuleName(), StreamIdx,
1740b57cec5SDimitry Andric                          ModIter->second.Modi);
1750b57cec5SDimitry Andric       } else if (NSIter != NamedStreams.end()) {
1760b57cec5SDimitry Andric         Streams[StreamIdx] =
1770b57cec5SDimitry Andric             stream(StreamPurpose::NamedStream, NSIter->second, StreamIdx);
1780b57cec5SDimitry Andric       } else {
1790b57cec5SDimitry Andric         Streams[StreamIdx] = stream(StreamPurpose::Other, "???", StreamIdx);
1800b57cec5SDimitry Andric       }
1810b57cec5SDimitry Andric     }
1820b57cec5SDimitry Andric   }
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   // Consume errors from missing streams.
1850b57cec5SDimitry Andric   if (!Dbi)
1860b57cec5SDimitry Andric     consumeError(Dbi.takeError());
1870b57cec5SDimitry Andric   if (!Tpi)
1880b57cec5SDimitry Andric     consumeError(Tpi.takeError());
1890b57cec5SDimitry Andric   if (!Ipi)
1900b57cec5SDimitry Andric     consumeError(Ipi.takeError());
1910b57cec5SDimitry Andric   if (!Info)
1920b57cec5SDimitry Andric     consumeError(Info.takeError());
1930b57cec5SDimitry Andric }
194