Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/tools/llvm-pdbutil/YAMLOutputStyle.cpp
35259 views
1
//===- YAMLOutputStyle.cpp ------------------------------------ *- 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 "YAMLOutputStyle.h"
10
11
#include "PdbYaml.h"
12
#include "llvm-pdbutil.h"
13
14
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
15
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
16
#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
17
#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
18
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
19
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
20
#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
21
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
22
#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
23
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
24
#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
25
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
26
#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
27
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
28
29
using namespace llvm;
30
using namespace llvm::codeview;
31
using namespace llvm::pdb;
32
33
static bool checkModuleSubsection(opts::ModuleSubsection MS) {
34
return any_of(opts::pdb2yaml::DumpModuleSubsections,
35
[=](opts::ModuleSubsection M) {
36
return M == MS || M == opts::ModuleSubsection::All;
37
});
38
}
39
40
YAMLOutputStyle::YAMLOutputStyle(PDBFile &File)
41
: File(File), Out(outs()), Obj(File.getAllocator()) {
42
Out.setWriteDefaultValues(!opts::pdb2yaml::Minimal);
43
}
44
45
Error YAMLOutputStyle::dump() {
46
if (opts::pdb2yaml::StreamDirectory)
47
opts::pdb2yaml::StreamMetadata = true;
48
49
if (auto EC = dumpFileHeaders())
50
return EC;
51
52
if (auto EC = dumpStreamMetadata())
53
return EC;
54
55
if (auto EC = dumpStreamDirectory())
56
return EC;
57
58
if (auto EC = dumpStringTable())
59
return EC;
60
61
if (auto EC = dumpPDBStream())
62
return EC;
63
64
if (auto EC = dumpDbiStream())
65
return EC;
66
67
if (auto EC = dumpTpiStream())
68
return EC;
69
70
if (auto EC = dumpIpiStream())
71
return EC;
72
73
if (auto EC = dumpPublics())
74
return EC;
75
76
flush();
77
return Error::success();
78
}
79
80
81
Error YAMLOutputStyle::dumpFileHeaders() {
82
if (opts::pdb2yaml::NoFileHeaders)
83
return Error::success();
84
85
yaml::MSFHeaders Headers;
86
Obj.Headers.emplace();
87
Obj.Headers->SuperBlock.NumBlocks = File.getBlockCount();
88
Obj.Headers->SuperBlock.BlockMapAddr = File.getBlockMapIndex();
89
Obj.Headers->SuperBlock.BlockSize = File.getBlockSize();
90
auto Blocks = File.getDirectoryBlockArray();
91
Obj.Headers->DirectoryBlocks.assign(Blocks.begin(), Blocks.end());
92
Obj.Headers->NumDirectoryBlocks = File.getNumDirectoryBlocks();
93
Obj.Headers->SuperBlock.NumDirectoryBytes = File.getNumDirectoryBytes();
94
Obj.Headers->NumStreams =
95
opts::pdb2yaml::StreamMetadata ? File.getNumStreams() : 0;
96
Obj.Headers->SuperBlock.FreeBlockMapBlock = File.getFreeBlockMapBlock();
97
Obj.Headers->SuperBlock.Unknown1 = File.getUnknown1();
98
Obj.Headers->FileSize = File.getFileSize();
99
100
return Error::success();
101
}
102
103
Error YAMLOutputStyle::dumpStringTable() {
104
bool RequiresStringTable = opts::pdb2yaml::DumpModuleFiles ||
105
!opts::pdb2yaml::DumpModuleSubsections.empty();
106
bool RequestedStringTable = opts::pdb2yaml::StringTable;
107
if (!RequiresStringTable && !RequestedStringTable)
108
return Error::success();
109
110
auto ExpectedST = File.getStringTable();
111
if (!ExpectedST)
112
return ExpectedST.takeError();
113
114
Obj.StringTable.emplace();
115
const auto &ST = ExpectedST.get();
116
for (auto ID : ST.name_ids()) {
117
auto S = ST.getStringForID(ID);
118
if (!S)
119
return S.takeError();
120
if (S->empty())
121
continue;
122
Obj.StringTable->push_back(*S);
123
}
124
return Error::success();
125
}
126
127
Error YAMLOutputStyle::dumpStreamMetadata() {
128
if (!opts::pdb2yaml::StreamMetadata)
129
return Error::success();
130
131
Obj.StreamSizes.emplace();
132
Obj.StreamSizes->assign(File.getStreamSizes().begin(),
133
File.getStreamSizes().end());
134
return Error::success();
135
}
136
137
Error YAMLOutputStyle::dumpStreamDirectory() {
138
if (!opts::pdb2yaml::StreamDirectory)
139
return Error::success();
140
141
auto StreamMap = File.getStreamMap();
142
Obj.StreamMap.emplace();
143
for (auto &Stream : StreamMap) {
144
pdb::yaml::StreamBlockList BlockList;
145
BlockList.Blocks.assign(Stream.begin(), Stream.end());
146
Obj.StreamMap->push_back(BlockList);
147
}
148
149
return Error::success();
150
}
151
152
Error YAMLOutputStyle::dumpPDBStream() {
153
if (!opts::pdb2yaml::PdbStream)
154
return Error::success();
155
156
auto IS = File.getPDBInfoStream();
157
if (!IS)
158
return IS.takeError();
159
160
auto &InfoS = IS.get();
161
Obj.PdbStream.emplace();
162
Obj.PdbStream->Age = InfoS.getAge();
163
Obj.PdbStream->Guid = InfoS.getGuid();
164
Obj.PdbStream->Signature = InfoS.getSignature();
165
Obj.PdbStream->Version = InfoS.getVersion();
166
Obj.PdbStream->Features = InfoS.getFeatureSignatures();
167
168
return Error::success();
169
}
170
171
static opts::ModuleSubsection convertSubsectionKind(DebugSubsectionKind K) {
172
switch (K) {
173
case DebugSubsectionKind::CrossScopeExports:
174
return opts::ModuleSubsection::CrossScopeExports;
175
case DebugSubsectionKind::CrossScopeImports:
176
return opts::ModuleSubsection::CrossScopeImports;
177
case DebugSubsectionKind::FileChecksums:
178
return opts::ModuleSubsection::FileChecksums;
179
case DebugSubsectionKind::InlineeLines:
180
return opts::ModuleSubsection::InlineeLines;
181
case DebugSubsectionKind::Lines:
182
return opts::ModuleSubsection::Lines;
183
case DebugSubsectionKind::Symbols:
184
return opts::ModuleSubsection::Symbols;
185
case DebugSubsectionKind::StringTable:
186
return opts::ModuleSubsection::StringTable;
187
case DebugSubsectionKind::FrameData:
188
return opts::ModuleSubsection::FrameData;
189
default:
190
return opts::ModuleSubsection::Unknown;
191
}
192
llvm_unreachable("Unreachable!");
193
}
194
195
Error YAMLOutputStyle::dumpDbiStream() {
196
if (!opts::pdb2yaml::DbiStream)
197
return Error::success();
198
199
if (!File.hasPDBDbiStream())
200
return Error::success();
201
202
auto DbiS = File.getPDBDbiStream();
203
if (!DbiS)
204
return DbiS.takeError();
205
206
auto &DS = DbiS.get();
207
Obj.DbiStream.emplace();
208
Obj.DbiStream->Age = DS.getAge();
209
Obj.DbiStream->BuildNumber = DS.getBuildNumber();
210
Obj.DbiStream->Flags = DS.getFlags();
211
Obj.DbiStream->MachineType = DS.getMachineType();
212
Obj.DbiStream->PdbDllRbld = DS.getPdbDllRbld();
213
Obj.DbiStream->PdbDllVersion = DS.getPdbDllVersion();
214
Obj.DbiStream->VerHeader = DS.getDbiVersion();
215
if (opts::pdb2yaml::DumpModules) {
216
const auto &Modules = DS.modules();
217
for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {
218
DbiModuleDescriptor MI = Modules.getModuleDescriptor(I);
219
220
Obj.DbiStream->ModInfos.emplace_back();
221
yaml::PdbDbiModuleInfo &DMI = Obj.DbiStream->ModInfos.back();
222
223
DMI.Mod = MI.getModuleName();
224
DMI.Obj = MI.getObjFileName();
225
if (opts::pdb2yaml::DumpModuleFiles) {
226
auto Files = Modules.source_files(I);
227
DMI.SourceFiles.assign(Files.begin(), Files.end());
228
}
229
230
uint16_t ModiStream = MI.getModuleStreamIndex();
231
if (ModiStream == kInvalidStreamIndex)
232
continue;
233
234
auto ModStreamData = File.createIndexedStream(ModiStream);
235
pdb::ModuleDebugStreamRef ModS(MI, std::move(ModStreamData));
236
if (auto EC = ModS.reload())
237
return EC;
238
239
auto ExpectedST = File.getStringTable();
240
if (!ExpectedST)
241
return ExpectedST.takeError();
242
if (!opts::pdb2yaml::DumpModuleSubsections.empty() &&
243
ModS.hasDebugSubsections()) {
244
auto ExpectedChecksums = ModS.findChecksumsSubsection();
245
if (!ExpectedChecksums)
246
return ExpectedChecksums.takeError();
247
248
StringsAndChecksumsRef SC(ExpectedST->getStringTable(),
249
*ExpectedChecksums);
250
251
for (const auto &SS : ModS.subsections()) {
252
opts::ModuleSubsection OptionKind = convertSubsectionKind(SS.kind());
253
if (!checkModuleSubsection(OptionKind))
254
continue;
255
256
auto Converted =
257
CodeViewYAML::YAMLDebugSubsection::fromCodeViewSubection(SC, SS);
258
if (!Converted)
259
return Converted.takeError();
260
DMI.Subsections.push_back(*Converted);
261
}
262
}
263
264
if (opts::pdb2yaml::DumpModuleSyms) {
265
DMI.Modi.emplace();
266
267
DMI.Modi->Signature = ModS.signature();
268
bool HadError = false;
269
for (auto &Sym : ModS.symbols(&HadError)) {
270
auto ES = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(Sym);
271
if (!ES)
272
return ES.takeError();
273
274
DMI.Modi->Symbols.push_back(*ES);
275
}
276
}
277
}
278
}
279
return Error::success();
280
}
281
282
Error YAMLOutputStyle::dumpTpiStream() {
283
if (!opts::pdb2yaml::TpiStream)
284
return Error::success();
285
286
auto TpiS = File.getPDBTpiStream();
287
if (!TpiS)
288
return TpiS.takeError();
289
290
auto &TS = TpiS.get();
291
Obj.TpiStream.emplace();
292
Obj.TpiStream->Version = TS.getTpiVersion();
293
for (auto &Record : TS.types(nullptr)) {
294
auto ExpectedRecord = CodeViewYAML::LeafRecord::fromCodeViewRecord(Record);
295
if (!ExpectedRecord)
296
return ExpectedRecord.takeError();
297
Obj.TpiStream->Records.push_back(*ExpectedRecord);
298
}
299
300
return Error::success();
301
}
302
303
Error YAMLOutputStyle::dumpIpiStream() {
304
if (!opts::pdb2yaml::IpiStream)
305
return Error::success();
306
307
auto InfoS = File.getPDBInfoStream();
308
if (!InfoS)
309
return InfoS.takeError();
310
if (!InfoS->containsIdStream())
311
return Error::success();
312
313
auto IpiS = File.getPDBIpiStream();
314
if (!IpiS)
315
return IpiS.takeError();
316
317
auto &IS = IpiS.get();
318
Obj.IpiStream.emplace();
319
Obj.IpiStream->Version = IS.getTpiVersion();
320
for (auto &Record : IS.types(nullptr)) {
321
auto ExpectedRecord = CodeViewYAML::LeafRecord::fromCodeViewRecord(Record);
322
if (!ExpectedRecord)
323
return ExpectedRecord.takeError();
324
325
Obj.IpiStream->Records.push_back(*ExpectedRecord);
326
}
327
328
return Error::success();
329
}
330
331
Error YAMLOutputStyle::dumpPublics() {
332
if (!opts::pdb2yaml::PublicsStream)
333
return Error::success();
334
335
Obj.PublicsStream.emplace();
336
auto ExpectedPublics = File.getPDBPublicsStream();
337
if (!ExpectedPublics) {
338
llvm::consumeError(ExpectedPublics.takeError());
339
return Error::success();
340
}
341
342
PublicsStream &Publics = *ExpectedPublics;
343
const GSIHashTable &PublicsTable = Publics.getPublicsTable();
344
345
auto ExpectedSyms = File.getPDBSymbolStream();
346
if (!ExpectedSyms) {
347
llvm::consumeError(ExpectedSyms.takeError());
348
return Error::success();
349
}
350
351
BinaryStreamRef SymStream =
352
ExpectedSyms->getSymbolArray().getUnderlyingStream();
353
for (uint32_t PubSymOff : PublicsTable) {
354
Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, PubSymOff);
355
if (!Sym)
356
return Sym.takeError();
357
auto ES = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(*Sym);
358
if (!ES)
359
return ES.takeError();
360
361
Obj.PublicsStream->PubSyms.push_back(*ES);
362
}
363
364
return Error::success();
365
}
366
367
void YAMLOutputStyle::flush() {
368
Out << Obj;
369
outs().flush();
370
}
371
372