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