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 void llvm::pdb::discoverStreamPurposes(PDBFile &File,
26                                        SmallVectorImpl<std::string> &Purposes,
27                                        uint32_t MaxLen) {
28 
29   // It's OK if we fail to load some of these streams, we still attempt to print
30   // what we can.
31   auto Dbi = File.getPDBDbiStream();
32   auto Tpi = File.getPDBTpiStream();
33   auto Ipi = File.getPDBIpiStream();
34   auto Info = File.getPDBInfoStream();
35 
36   uint32_t StreamCount = File.getNumStreams();
37   DenseMap<uint16_t, DbiModuleDescriptor> ModStreams;
38   DenseMap<uint16_t, std::string> NamedStreams;
39 
40   if (Dbi) {
41     const DbiModuleList &Modules = Dbi->modules();
42     for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {
43       DbiModuleDescriptor Descriptor = Modules.getModuleDescriptor(I);
44       uint16_t SN = Descriptor.getModuleStreamIndex();
45       if (SN != kInvalidStreamIndex)
46         ModStreams[SN] = Descriptor;
47     }
48   }
49   if (Info) {
50     for (auto &NSE : Info->named_streams()) {
51       if (NSE.second != kInvalidStreamIndex)
52         NamedStreams[NSE.second] = NSE.first();
53     }
54   }
55 
56   Purposes.resize(StreamCount);
57   for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
58     std::string Value;
59     if (StreamIdx == OldMSFDirectory)
60       Value = truncateStringBack("Old MSF Directory", MaxLen);
61     else if (StreamIdx == StreamPDB)
62       Value = truncateStringBack("PDB Stream", MaxLen);
63     else if (StreamIdx == StreamDBI)
64       Value = truncateStringBack("DBI Stream", MaxLen);
65     else if (StreamIdx == StreamTPI)
66       Value = truncateStringBack("TPI Stream", MaxLen);
67     else if (StreamIdx == StreamIPI)
68       Value = truncateStringBack("IPI Stream", MaxLen);
69     else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex())
70       Value = truncateStringBack("Global Symbol Hash", MaxLen);
71     else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex())
72       Value = truncateStringBack("Public Symbol Hash", MaxLen);
73     else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex())
74       Value = truncateStringBack("Public Symbol Records", MaxLen);
75     else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex())
76       Value = truncateStringBack("TPI Hash", MaxLen);
77     else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex())
78       Value = truncateStringBack("TPI Aux Hash", MaxLen);
79     else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex())
80       Value = truncateStringBack("IPI Hash", MaxLen);
81     else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex())
82       Value = truncateStringBack("IPI Aux Hash", MaxLen);
83     else if (Dbi &&
84              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception))
85       Value = truncateStringBack("Exception Data", MaxLen);
86     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup))
87       Value = truncateStringBack("Fixup Data", MaxLen);
88     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO))
89       Value = truncateStringBack("FPO Data", MaxLen);
90     else if (Dbi &&
91              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO))
92       Value = truncateStringBack("New FPO Data", MaxLen);
93     else if (Dbi &&
94              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
95       Value = truncateStringBack("Omap From Source Data", MaxLen);
96     else if (Dbi &&
97              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc))
98       Value = truncateStringBack("Omap To Source Data", MaxLen);
99     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata))
100       Value = truncateStringBack("Pdata", MaxLen);
101     else if (Dbi &&
102              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr))
103       Value = truncateStringBack("Section Header Data", MaxLen);
104     else if (Dbi &&
105              StreamIdx ==
106                  Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
107       Value = truncateStringBack("Section Header Original Data", MaxLen);
108     else if (Dbi &&
109              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap))
110       Value = truncateStringBack("Token Rid Data", MaxLen);
111     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata))
112       Value = truncateStringBack("Xdata", MaxLen);
113     else {
114       auto ModIter = ModStreams.find(StreamIdx);
115       auto NSIter = NamedStreams.find(StreamIdx);
116       if (ModIter != ModStreams.end()) {
117         Value = truncateQuotedNameFront(
118             "Module", ModIter->second.getModuleName(), MaxLen);
119       } else if (NSIter != NamedStreams.end()) {
120         Value = truncateQuotedNameBack("Named Stream", NSIter->second, MaxLen);
121       } else {
122         Value = "???";
123       }
124     }
125     Purposes[StreamIdx] = Value;
126   }
127 
128   // Consume errors from missing streams.
129   if (!Dbi)
130     consumeError(Dbi.takeError());
131   if (!Tpi)
132     consumeError(Tpi.takeError());
133   if (!Ipi)
134     consumeError(Ipi.takeError());
135   if (!Info)
136     consumeError(Info.takeError());
137 }
138