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"
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"
21 using namespace llvm::pdb
;
23 std::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();
31 StreamInfo
StreamInfo::createStream(StreamPurpose Purpose
, StringRef Name
,
32 uint32_t StreamIndex
) {
34 Result
.Name
= std::string(Name
);
35 Result
.StreamIndex
= StreamIndex
;
36 Result
.Purpose
= Purpose
;
40 StreamInfo
StreamInfo::createModuleStream(StringRef Module
,
41 uint32_t StreamIndex
, uint32_t Modi
) {
43 Result
.Name
= std::string(Module
);
44 Result
.StreamIndex
= StreamIndex
;
45 Result
.ModuleIndex
= Modi
;
46 Result
.Purpose
= StreamPurpose::ModuleStream
;
50 static inline StreamInfo
stream(StreamPurpose Purpose
, StringRef Label
,
52 return StreamInfo::createStream(Purpose
, Label
, Idx
);
55 static inline StreamInfo
moduleStream(StringRef Label
, uint32_t StreamIdx
,
57 return StreamInfo::createModuleStream(Label
, StreamIdx
, Modi
);
60 struct IndexedModuleDescriptor
{
62 DbiModuleDescriptor Descriptor
;
65 void 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 print
69 auto Dbi
= File
.getPDBDbiStream();
70 auto Tpi
= File
.getPDBTpiStream();
71 auto Ipi
= File
.getPDBIpiStream();
72 auto Info
= File
.getPDBInfoStream();
74 uint32_t StreamCount
= File
.getNumStreams();
75 DenseMap
<uint16_t, IndexedModuleDescriptor
> ModStreams
;
76 DenseMap
<uint16_t, std::string
> NamedStreams
;
79 const DbiModuleList
&Modules
= Dbi
->modules();
80 for (uint32_t I
= 0; I
< Modules
.getModuleCount(); ++I
) {
81 IndexedModuleDescriptor IMD
;
83 IMD
.Descriptor
= Modules
.getModuleDescriptor(I
);
84 uint16_t SN
= IMD
.Descriptor
.getModuleStreamIndex();
85 if (SN
!= kInvalidStreamIndex
)
90 for (auto &NSE
: Info
->named_streams()) {
91 if (NSE
.second
!= kInvalidStreamIndex
)
92 NamedStreams
[NSE
.second
] = std::string(NSE
.first());
96 Streams
.resize(StreamCount
);
97 for (uint32_t StreamIdx
= 0; StreamIdx
< StreamCount
; ++StreamIdx
) {
98 if (StreamIdx
== OldMSFDirectory
)
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())
111 stream(StreamPurpose::GlobalHash
, "Global Symbol Hash", StreamIdx
);
112 else if (Dbi
&& StreamIdx
== Dbi
->getPublicSymbolStreamIndex())
114 stream(StreamPurpose::PublicHash
, "Public Symbol Hash", StreamIdx
);
115 else if (Dbi
&& StreamIdx
== Dbi
->getSymRecordStreamIndex())
117 stream(StreamPurpose::Symbols
, "Symbol Records", StreamIdx
);
118 else if (Tpi
&& StreamIdx
== Tpi
->getTypeHashStreamIndex())
120 stream(StreamPurpose::TpiHash
, "TPI Hash", StreamIdx
);
121 else if (Tpi
&& StreamIdx
== Tpi
->getTypeHashStreamAuxIndex())
123 stream(StreamPurpose::Other
, "TPI Aux Hash", StreamIdx
);
124 else if (Ipi
&& StreamIdx
== Ipi
->getTypeHashStreamIndex())
126 stream(StreamPurpose::IpiHash
, "IPI Hash", StreamIdx
);
127 else if (Ipi
&& StreamIdx
== Ipi
->getTypeHashStreamAuxIndex())
129 stream(StreamPurpose::Other
, "IPI Aux Hash", StreamIdx
);
131 StreamIdx
== Dbi
->getDebugStreamIndex(DbgHeaderType::Exception
))
133 stream(StreamPurpose::Other
, "Exception Data", StreamIdx
);
134 else if (Dbi
&& StreamIdx
== Dbi
->getDebugStreamIndex(DbgHeaderType::Fixup
))
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
);
140 StreamIdx
== Dbi
->getDebugStreamIndex(DbgHeaderType::NewFPO
))
142 stream(StreamPurpose::Other
, "New FPO Data", StreamIdx
);
144 StreamIdx
== Dbi
->getDebugStreamIndex(DbgHeaderType::OmapFromSrc
))
146 stream(StreamPurpose::Other
, "Omap From Source Data", StreamIdx
);
148 StreamIdx
== Dbi
->getDebugStreamIndex(DbgHeaderType::OmapToSrc
))
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
);
154 StreamIdx
== Dbi
->getDebugStreamIndex(DbgHeaderType::SectionHdr
))
156 stream(StreamPurpose::Other
, "Section Header Data", StreamIdx
);
159 Dbi
->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig
))
160 Streams
[StreamIdx
] = stream(StreamPurpose::Other
,
161 "Section Header Original Data", StreamIdx
);
163 StreamIdx
== Dbi
->getDebugStreamIndex(DbgHeaderType::TokenRidMap
))
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
);
169 auto ModIter
= ModStreams
.find(StreamIdx
);
170 auto NSIter
= NamedStreams
.find(StreamIdx
);
171 if (ModIter
!= ModStreams
.end()) {
173 moduleStream(ModIter
->second
.Descriptor
.getModuleName(), StreamIdx
,
174 ModIter
->second
.Modi
);
175 } else if (NSIter
!= NamedStreams
.end()) {
177 stream(StreamPurpose::NamedStream
, NSIter
->second
, StreamIdx
);
179 Streams
[StreamIdx
] = stream(StreamPurpose::Other
, "???", StreamIdx
);
184 // Consume errors from missing streams.
186 consumeError(Dbi
.takeError());
188 consumeError(Tpi
.takeError());
190 consumeError(Ipi
.takeError());
192 consumeError(Info
.takeError());