1 //===- StreamUtil.cpp - PDB stream utilities --------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "StreamUtil.h"
10 #include "FormatUtil.h"
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"
22 using namespace llvm::pdb
;
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();
32 StreamInfo
StreamInfo::createStream(StreamPurpose Purpose
, StringRef Name
,
33 uint32_t StreamIndex
) {
36 Result
.StreamIndex
= StreamIndex
;
37 Result
.Purpose
= Purpose
;
41 StreamInfo
StreamInfo::createModuleStream(StringRef Module
,
42 uint32_t StreamIndex
, uint32_t Modi
) {
45 Result
.StreamIndex
= StreamIndex
;
46 Result
.ModuleIndex
= Modi
;
47 Result
.Purpose
= StreamPurpose::ModuleStream
;
51 static inline StreamInfo
stream(StreamPurpose Purpose
, StringRef Label
,
53 return StreamInfo::createStream(Purpose
, Label
, Idx
);
56 static inline StreamInfo
moduleStream(StringRef Label
, uint32_t StreamIdx
,
58 return StreamInfo::createModuleStream(Label
, StreamIdx
, Modi
);
61 struct IndexedModuleDescriptor
{
63 DbiModuleDescriptor Descriptor
;
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
70 auto Dbi
= File
.getPDBDbiStream();
71 auto Tpi
= File
.getPDBTpiStream();
72 auto Ipi
= File
.getPDBIpiStream();
73 auto Info
= File
.getPDBInfoStream();
75 uint32_t StreamCount
= File
.getNumStreams();
76 DenseMap
<uint16_t, IndexedModuleDescriptor
> ModStreams
;
77 DenseMap
<uint16_t, std::string
> NamedStreams
;
80 const DbiModuleList
&Modules
= Dbi
->modules();
81 for (uint32_t I
= 0; I
< Modules
.getModuleCount(); ++I
) {
82 IndexedModuleDescriptor IMD
;
84 IMD
.Descriptor
= Modules
.getModuleDescriptor(I
);
85 uint16_t SN
= IMD
.Descriptor
.getModuleStreamIndex();
86 if (SN
!= kInvalidStreamIndex
)
91 for (auto &NSE
: Info
->named_streams()) {
92 if (NSE
.second
!= kInvalidStreamIndex
)
93 NamedStreams
[NSE
.second
] = NSE
.first();
97 Streams
.resize(StreamCount
);
98 for (uint16_t StreamIdx
= 0; StreamIdx
< StreamCount
; ++StreamIdx
) {
99 if (StreamIdx
== OldMSFDirectory
)
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())
112 stream(StreamPurpose::GlobalHash
, "Global Symbol Hash", StreamIdx
);
113 else if (Dbi
&& StreamIdx
== Dbi
->getPublicSymbolStreamIndex())
115 stream(StreamPurpose::PublicHash
, "Public Symbol Hash", StreamIdx
);
116 else if (Dbi
&& StreamIdx
== Dbi
->getSymRecordStreamIndex())
118 stream(StreamPurpose::Symbols
, "Symbol Records", StreamIdx
);
119 else if (Tpi
&& StreamIdx
== Tpi
->getTypeHashStreamIndex())
121 stream(StreamPurpose::TpiHash
, "TPI Hash", StreamIdx
);
122 else if (Tpi
&& StreamIdx
== Tpi
->getTypeHashStreamAuxIndex())
124 stream(StreamPurpose::Other
, "TPI Aux Hash", StreamIdx
);
125 else if (Ipi
&& StreamIdx
== Ipi
->getTypeHashStreamIndex())
127 stream(StreamPurpose::IpiHash
, "IPI Hash", StreamIdx
);
128 else if (Ipi
&& StreamIdx
== Ipi
->getTypeHashStreamAuxIndex())
130 stream(StreamPurpose::Other
, "IPI Aux Hash", StreamIdx
);
132 StreamIdx
== Dbi
->getDebugStreamIndex(DbgHeaderType::Exception
))
134 stream(StreamPurpose::Other
, "Exception Data", StreamIdx
);
135 else if (Dbi
&& StreamIdx
== Dbi
->getDebugStreamIndex(DbgHeaderType::Fixup
))
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
);
141 StreamIdx
== Dbi
->getDebugStreamIndex(DbgHeaderType::NewFPO
))
143 stream(StreamPurpose::Other
, "New FPO Data", StreamIdx
);
145 StreamIdx
== Dbi
->getDebugStreamIndex(DbgHeaderType::OmapFromSrc
))
147 stream(StreamPurpose::Other
, "Omap From Source Data", StreamIdx
);
149 StreamIdx
== Dbi
->getDebugStreamIndex(DbgHeaderType::OmapToSrc
))
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
);
155 StreamIdx
== Dbi
->getDebugStreamIndex(DbgHeaderType::SectionHdr
))
157 stream(StreamPurpose::Other
, "Section Header Data", StreamIdx
);
160 Dbi
->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig
))
161 Streams
[StreamIdx
] = stream(StreamPurpose::Other
,
162 "Section Header Original Data", StreamIdx
);
164 StreamIdx
== Dbi
->getDebugStreamIndex(DbgHeaderType::TokenRidMap
))
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
);
170 auto ModIter
= ModStreams
.find(StreamIdx
);
171 auto NSIter
= NamedStreams
.find(StreamIdx
);
172 if (ModIter
!= ModStreams
.end()) {
174 moduleStream(ModIter
->second
.Descriptor
.getModuleName(), StreamIdx
,
175 ModIter
->second
.Modi
);
176 } else if (NSIter
!= NamedStreams
.end()) {
178 stream(StreamPurpose::NamedStream
, NSIter
->second
, StreamIdx
);
180 Streams
[StreamIdx
] = stream(StreamPurpose::Other
, "???", StreamIdx
);
185 // Consume errors from missing streams.
187 consumeError(Dbi
.takeError());
189 consumeError(Tpi
.takeError());
191 consumeError(Ipi
.takeError());
193 consumeError(Info
.takeError());