1 //===- CodeViewYAMLDebugSections.cpp - CodeView YAMLIO debug sections -----===//
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 // This file defines classes for handling the YAML representation of CodeView
11 // Debug Info.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h"
16 
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/ADT/StringSwitch.h"
19 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
20 #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
21 #include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
22 #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
23 #include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
24 #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
25 #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
26 #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
27 #include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
28 #include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
29 #include "llvm/DebugInfo/CodeView/EnumTables.h"
30 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
31 #include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
32 #include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
33 #include "llvm/Support/BinaryStreamWriter.h"
34 using namespace llvm;
35 using namespace llvm::codeview;
36 using namespace llvm::CodeViewYAML;
37 using namespace llvm::CodeViewYAML::detail;
38 using namespace llvm::yaml;
39 
40 LLVM_YAML_IS_SEQUENCE_VECTOR(SourceFileChecksumEntry)
41 LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineEntry)
42 LLVM_YAML_IS_SEQUENCE_VECTOR(SourceColumnEntry)
43 LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineBlock)
44 LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineInfo)
45 LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeSite)
46 LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeInfo)
47 LLVM_YAML_IS_SEQUENCE_VECTOR(CrossModuleExport)
48 LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLCrossModuleImport)
49 LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
50 LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLFrameData)
51 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t)
52 
53 LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, false)
54 LLVM_YAML_DECLARE_ENUM_TRAITS(DebugSubsectionKind)
55 LLVM_YAML_DECLARE_ENUM_TRAITS(FileChecksumKind)
56 LLVM_YAML_DECLARE_BITSET_TRAITS(LineFlags)
57 
58 LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleExport)
59 LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLFrameData)
60 LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLCrossModuleImport)
61 LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleImportItem)
62 LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineEntry)
63 LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceColumnEntry)
64 LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceFileChecksumEntry)
65 LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineBlock)
66 LLVM_YAML_DECLARE_MAPPING_TRAITS(InlineeSite)
67 
68 namespace llvm {
69 namespace CodeViewYAML {
70 namespace detail {
71 struct YAMLSubsectionBase {
72   explicit YAMLSubsectionBase(DebugSubsectionKind Kind) : Kind(Kind) {}
73   DebugSubsectionKind Kind;
74   virtual ~YAMLSubsectionBase() {}
75 
76   virtual void map(IO &IO) = 0;
77   virtual std::unique_ptr<DebugSubsection>
78   toCodeViewSubsection(BumpPtrAllocator &Allocator,
79                        DebugStringTableSubsection *UseStrings,
80                        DebugChecksumsSubsection *UseChecksums) const = 0;
81 };
82 }
83 }
84 }
85 
86 namespace {
87 struct YAMLChecksumsSubsection : public YAMLSubsectionBase {
88   YAMLChecksumsSubsection()
89       : YAMLSubsectionBase(DebugSubsectionKind::FileChecksums) {}
90 
91   void map(IO &IO) override;
92   std::unique_ptr<DebugSubsection>
93   toCodeViewSubsection(BumpPtrAllocator &Allocator,
94                        DebugStringTableSubsection *Strings,
95                        DebugChecksumsSubsection *Checksums) const override;
96   static Expected<std::shared_ptr<YAMLChecksumsSubsection>>
97   fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
98                          const DebugChecksumsSubsectionRef &FC);
99 
100   std::vector<SourceFileChecksumEntry> Checksums;
101 };
102 
103 struct YAMLLinesSubsection : public YAMLSubsectionBase {
104   YAMLLinesSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Lines) {}
105 
106   void map(IO &IO) override;
107   std::unique_ptr<DebugSubsection>
108   toCodeViewSubsection(BumpPtrAllocator &Allocator,
109                        DebugStringTableSubsection *Strings,
110                        DebugChecksumsSubsection *Checksums) const override;
111   static Expected<std::shared_ptr<YAMLLinesSubsection>>
112   fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
113                          const DebugChecksumsSubsectionRef &Checksums,
114                          const DebugLinesSubsectionRef &Lines);
115 
116   SourceLineInfo Lines;
117 };
118 
119 struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase {
120   YAMLInlineeLinesSubsection()
121       : YAMLSubsectionBase(DebugSubsectionKind::InlineeLines) {}
122 
123   void map(IO &IO) override;
124   std::unique_ptr<DebugSubsection>
125   toCodeViewSubsection(BumpPtrAllocator &Allocator,
126                        DebugStringTableSubsection *Strings,
127                        DebugChecksumsSubsection *Checksums) const override;
128   static Expected<std::shared_ptr<YAMLInlineeLinesSubsection>>
129   fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
130                          const DebugChecksumsSubsectionRef &Checksums,
131                          const DebugInlineeLinesSubsectionRef &Lines);
132 
133   InlineeInfo InlineeLines;
134 };
135 
136 struct YAMLCrossModuleExportsSubsection : public YAMLSubsectionBase {
137   YAMLCrossModuleExportsSubsection()
138       : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeExports) {}
139 
140   void map(IO &IO) override;
141   std::unique_ptr<DebugSubsection>
142   toCodeViewSubsection(BumpPtrAllocator &Allocator,
143                        DebugStringTableSubsection *Strings,
144                        DebugChecksumsSubsection *Checksums) const override;
145   static Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>>
146   fromCodeViewSubsection(const DebugCrossModuleExportsSubsectionRef &Exports);
147 
148   std::vector<CrossModuleExport> Exports;
149 };
150 
151 struct YAMLCrossModuleImportsSubsection : public YAMLSubsectionBase {
152   YAMLCrossModuleImportsSubsection()
153       : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeImports) {}
154 
155   void map(IO &IO) override;
156   std::unique_ptr<DebugSubsection>
157   toCodeViewSubsection(BumpPtrAllocator &Allocator,
158                        DebugStringTableSubsection *Strings,
159                        DebugChecksumsSubsection *Checksums) const override;
160   static Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>>
161   fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
162                          const DebugCrossModuleImportsSubsectionRef &Imports);
163 
164   std::vector<YAMLCrossModuleImport> Imports;
165 };
166 
167 struct YAMLSymbolsSubsection : public YAMLSubsectionBase {
168   YAMLSymbolsSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Symbols) {}
169 
170   void map(IO &IO) override;
171   std::unique_ptr<DebugSubsection>
172   toCodeViewSubsection(BumpPtrAllocator &Allocator,
173                        DebugStringTableSubsection *Strings,
174                        DebugChecksumsSubsection *Checksums) const override;
175   static Expected<std::shared_ptr<YAMLSymbolsSubsection>>
176   fromCodeViewSubsection(const DebugSymbolsSubsectionRef &Symbols);
177 
178   std::vector<CodeViewYAML::SymbolRecord> Symbols;
179 };
180 
181 struct YAMLStringTableSubsection : public YAMLSubsectionBase {
182   YAMLStringTableSubsection()
183       : YAMLSubsectionBase(DebugSubsectionKind::StringTable) {}
184 
185   void map(IO &IO) override;
186   std::unique_ptr<DebugSubsection>
187   toCodeViewSubsection(BumpPtrAllocator &Allocator,
188                        DebugStringTableSubsection *Strings,
189                        DebugChecksumsSubsection *Checksums) const override;
190   static Expected<std::shared_ptr<YAMLStringTableSubsection>>
191   fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings);
192 
193   std::vector<StringRef> Strings;
194 };
195 
196 struct YAMLFrameDataSubsection : public YAMLSubsectionBase {
197   YAMLFrameDataSubsection()
198       : YAMLSubsectionBase(DebugSubsectionKind::FrameData) {}
199 
200   void map(IO &IO) override;
201   std::unique_ptr<DebugSubsection>
202   toCodeViewSubsection(BumpPtrAllocator &Allocator,
203                        DebugStringTableSubsection *Strings,
204                        DebugChecksumsSubsection *Checksums) const override;
205   static Expected<std::shared_ptr<YAMLFrameDataSubsection>>
206   fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
207                          const DebugFrameDataSubsectionRef &Frames);
208 
209   std::vector<YAMLFrameData> Frames;
210 };
211 }
212 
213 void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) {
214   io.bitSetCase(Flags, "HasColumnInfo", LF_HaveColumns);
215   io.enumFallback<Hex16>(Flags);
216 }
217 
218 void ScalarEnumerationTraits<FileChecksumKind>::enumeration(
219     IO &io, FileChecksumKind &Kind) {
220   io.enumCase(Kind, "None", FileChecksumKind::None);
221   io.enumCase(Kind, "MD5", FileChecksumKind::MD5);
222   io.enumCase(Kind, "SHA1", FileChecksumKind::SHA1);
223   io.enumCase(Kind, "SHA256", FileChecksumKind::SHA256);
224 }
225 
226 void ScalarTraits<HexFormattedString>::output(const HexFormattedString &Value,
227                                               void *ctx, raw_ostream &Out) {
228   StringRef Bytes(reinterpret_cast<const char *>(Value.Bytes.data()),
229                   Value.Bytes.size());
230   Out << toHex(Bytes);
231 }
232 
233 StringRef ScalarTraits<HexFormattedString>::input(StringRef Scalar, void *ctxt,
234                                                   HexFormattedString &Value) {
235   std::string H = fromHex(Scalar);
236   Value.Bytes.assign(H.begin(), H.end());
237   return StringRef();
238 }
239 
240 void MappingTraits<SourceLineEntry>::mapping(IO &IO, SourceLineEntry &Obj) {
241   IO.mapRequired("Offset", Obj.Offset);
242   IO.mapRequired("LineStart", Obj.LineStart);
243   IO.mapRequired("IsStatement", Obj.IsStatement);
244   IO.mapRequired("EndDelta", Obj.EndDelta);
245 }
246 
247 void MappingTraits<SourceColumnEntry>::mapping(IO &IO, SourceColumnEntry &Obj) {
248   IO.mapRequired("StartColumn", Obj.StartColumn);
249   IO.mapRequired("EndColumn", Obj.EndColumn);
250 }
251 
252 void MappingTraits<SourceLineBlock>::mapping(IO &IO, SourceLineBlock &Obj) {
253   IO.mapRequired("FileName", Obj.FileName);
254   IO.mapRequired("Lines", Obj.Lines);
255   IO.mapRequired("Columns", Obj.Columns);
256 }
257 
258 void MappingTraits<CrossModuleExport>::mapping(IO &IO, CrossModuleExport &Obj) {
259   IO.mapRequired("LocalId", Obj.Local);
260   IO.mapRequired("GlobalId", Obj.Global);
261 }
262 
263 void MappingTraits<YAMLCrossModuleImport>::mapping(IO &IO,
264                                                    YAMLCrossModuleImport &Obj) {
265   IO.mapRequired("Module", Obj.ModuleName);
266   IO.mapRequired("Imports", Obj.ImportIds);
267 }
268 
269 void MappingTraits<SourceFileChecksumEntry>::mapping(
270     IO &IO, SourceFileChecksumEntry &Obj) {
271   IO.mapRequired("FileName", Obj.FileName);
272   IO.mapRequired("Kind", Obj.Kind);
273   IO.mapRequired("Checksum", Obj.ChecksumBytes);
274 }
275 
276 void MappingTraits<InlineeSite>::mapping(IO &IO, InlineeSite &Obj) {
277   IO.mapRequired("FileName", Obj.FileName);
278   IO.mapRequired("LineNum", Obj.SourceLineNum);
279   IO.mapRequired("Inlinee", Obj.Inlinee);
280   IO.mapOptional("ExtraFiles", Obj.ExtraFiles);
281 }
282 
283 void MappingTraits<YAMLFrameData>::mapping(IO &IO, YAMLFrameData &Obj) {
284   IO.mapRequired("CodeSize", Obj.CodeSize);
285   IO.mapRequired("FrameFunc", Obj.FrameFunc);
286   IO.mapRequired("LocalSize", Obj.LocalSize);
287   IO.mapOptional("MaxStackSize", Obj.MaxStackSize);
288   IO.mapOptional("ParamsSize", Obj.ParamsSize);
289   IO.mapOptional("PrologSize", Obj.PrologSize);
290   IO.mapOptional("RvaStart", Obj.RvaStart);
291   IO.mapOptional("SavedRegsSize", Obj.SavedRegsSize);
292 }
293 
294 void YAMLChecksumsSubsection::map(IO &IO) {
295   IO.mapTag("!FileChecksums", true);
296   IO.mapRequired("Checksums", Checksums);
297 }
298 
299 void YAMLLinesSubsection::map(IO &IO) {
300   IO.mapTag("!Lines", true);
301   IO.mapRequired("CodeSize", Lines.CodeSize);
302 
303   IO.mapRequired("Flags", Lines.Flags);
304   IO.mapRequired("RelocOffset", Lines.RelocOffset);
305   IO.mapRequired("RelocSegment", Lines.RelocSegment);
306   IO.mapRequired("Blocks", Lines.Blocks);
307 }
308 
309 void YAMLInlineeLinesSubsection::map(IO &IO) {
310   IO.mapTag("!InlineeLines", true);
311   IO.mapRequired("HasExtraFiles", InlineeLines.HasExtraFiles);
312   IO.mapRequired("Sites", InlineeLines.Sites);
313 }
314 
315 void YAMLCrossModuleExportsSubsection::map(IO &IO) {
316   IO.mapTag("!CrossModuleExports", true);
317   IO.mapOptional("Exports", Exports);
318 }
319 
320 void YAMLCrossModuleImportsSubsection::map(IO &IO) {
321   IO.mapTag("!CrossModuleImports", true);
322   IO.mapOptional("Imports", Imports);
323 }
324 
325 void YAMLSymbolsSubsection::map(IO &IO) {
326   IO.mapTag("!Symbols", true);
327   IO.mapRequired("Records", Symbols);
328 }
329 
330 void YAMLStringTableSubsection::map(IO &IO) {
331   IO.mapTag("!StringTable", true);
332   IO.mapRequired("Strings", Strings);
333 }
334 
335 void YAMLFrameDataSubsection::map(IO &IO) {
336   IO.mapTag("!FrameData", true);
337   IO.mapRequired("Frames", Frames);
338 }
339 
340 void MappingTraits<YAMLDebugSubsection>::mapping(
341     IO &IO, YAMLDebugSubsection &Subsection) {
342   if (!IO.outputting()) {
343     if (IO.mapTag("!FileChecksums")) {
344       auto SS = std::make_shared<YAMLChecksumsSubsection>();
345       Subsection.Subsection = SS;
346     } else if (IO.mapTag("!Lines")) {
347       Subsection.Subsection = std::make_shared<YAMLLinesSubsection>();
348     } else if (IO.mapTag("!InlineeLines")) {
349       Subsection.Subsection = std::make_shared<YAMLInlineeLinesSubsection>();
350     } else if (IO.mapTag("!CrossModuleExports")) {
351       Subsection.Subsection =
352           std::make_shared<YAMLCrossModuleExportsSubsection>();
353     } else if (IO.mapTag("!CrossModuleImports")) {
354       Subsection.Subsection =
355           std::make_shared<YAMLCrossModuleImportsSubsection>();
356     } else if (IO.mapTag("!Symbols")) {
357       Subsection.Subsection = std::make_shared<YAMLSymbolsSubsection>();
358     } else if (IO.mapTag("!StringTable")) {
359       Subsection.Subsection = std::make_shared<YAMLStringTableSubsection>();
360     } else if (IO.mapTag("!FrameData")) {
361       Subsection.Subsection = std::make_shared<YAMLFrameDataSubsection>();
362     } else {
363       llvm_unreachable("Unexpected subsection tag!");
364     }
365   }
366   Subsection.Subsection->map(IO);
367 }
368 
369 static std::shared_ptr<YAMLChecksumsSubsection>
370 findChecksums(ArrayRef<YAMLDebugSubsection> Subsections) {
371   for (const auto &SS : Subsections) {
372     if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) {
373       return std::static_pointer_cast<YAMLChecksumsSubsection>(SS.Subsection);
374     }
375   }
376 
377   return nullptr;
378 }
379 
380 std::unique_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection(
381     BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
382     DebugChecksumsSubsection *UseChecksums) const {
383   assert(UseStrings && !UseChecksums);
384   auto Result = llvm::make_unique<DebugChecksumsSubsection>(*UseStrings);
385   for (const auto &CS : Checksums) {
386     Result->addChecksum(CS.FileName, CS.Kind, CS.ChecksumBytes.Bytes);
387   }
388   return std::move(Result);
389 }
390 
391 std::unique_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection(
392     BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
393     DebugChecksumsSubsection *UseChecksums) const {
394   assert(UseStrings && UseChecksums);
395   auto Result =
396       llvm::make_unique<DebugLinesSubsection>(*UseChecksums, *UseStrings);
397   Result->setCodeSize(Lines.CodeSize);
398   Result->setRelocationAddress(Lines.RelocSegment, Lines.RelocOffset);
399   Result->setFlags(Lines.Flags);
400   for (const auto &LC : Lines.Blocks) {
401     Result->createBlock(LC.FileName);
402     if (Result->hasColumnInfo()) {
403       for (const auto &Item : zip(LC.Lines, LC.Columns)) {
404         auto &L = std::get<0>(Item);
405         auto &C = std::get<1>(Item);
406         uint32_t LE = L.LineStart + L.EndDelta;
407         Result->addLineAndColumnInfo(L.Offset,
408                                      LineInfo(L.LineStart, LE, L.IsStatement),
409                                      C.StartColumn, C.EndColumn);
410       }
411     } else {
412       for (const auto &L : LC.Lines) {
413         uint32_t LE = L.LineStart + L.EndDelta;
414         Result->addLineInfo(L.Offset, LineInfo(L.LineStart, LE, L.IsStatement));
415       }
416     }
417   }
418   return llvm::cast<DebugSubsection>(std::move(Result));
419 }
420 
421 std::unique_ptr<DebugSubsection>
422 YAMLInlineeLinesSubsection::toCodeViewSubsection(
423     BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
424     DebugChecksumsSubsection *UseChecksums) const {
425   assert(UseChecksums);
426   auto Result = llvm::make_unique<DebugInlineeLinesSubsection>(
427       *UseChecksums, InlineeLines.HasExtraFiles);
428 
429   for (const auto &Site : InlineeLines.Sites) {
430     Result->addInlineSite(TypeIndex(Site.Inlinee), Site.FileName,
431                           Site.SourceLineNum);
432     if (!InlineeLines.HasExtraFiles)
433       continue;
434 
435     for (auto EF : Site.ExtraFiles) {
436       Result->addExtraFile(EF);
437     }
438   }
439   return llvm::cast<DebugSubsection>(std::move(Result));
440 }
441 
442 std::unique_ptr<DebugSubsection>
443 YAMLCrossModuleExportsSubsection::toCodeViewSubsection(
444     BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
445     DebugChecksumsSubsection *Checksums) const {
446   auto Result = llvm::make_unique<DebugCrossModuleExportsSubsection>();
447   for (const auto &M : Exports)
448     Result->addMapping(M.Local, M.Global);
449   return llvm::cast<DebugSubsection>(std::move(Result));
450 }
451 
452 std::unique_ptr<DebugSubsection>
453 YAMLCrossModuleImportsSubsection::toCodeViewSubsection(
454     BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
455     DebugChecksumsSubsection *Checksums) const {
456   auto Result = llvm::make_unique<DebugCrossModuleImportsSubsection>(*Strings);
457   for (const auto &M : Imports) {
458     for (const auto Id : M.ImportIds)
459       Result->addImport(M.ModuleName, Id);
460   }
461   return llvm::cast<DebugSubsection>(std::move(Result));
462 }
463 
464 std::unique_ptr<DebugSubsection> YAMLSymbolsSubsection::toCodeViewSubsection(
465     BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
466     DebugChecksumsSubsection *Checksums) const {
467   auto Result = llvm::make_unique<DebugSymbolsSubsection>();
468   for (const auto &Sym : Symbols)
469     Result->addSymbol(
470         Sym.toCodeViewSymbol(Allocator, CodeViewContainer::ObjectFile));
471   return std::move(Result);
472 }
473 
474 std::unique_ptr<DebugSubsection>
475 YAMLStringTableSubsection::toCodeViewSubsection(
476     BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
477     DebugChecksumsSubsection *Checksums) const {
478   auto Result = llvm::make_unique<DebugStringTableSubsection>();
479   for (const auto &Str : this->Strings)
480     Result->insert(Str);
481   return std::move(Result);
482 }
483 
484 std::unique_ptr<DebugSubsection> YAMLFrameDataSubsection::toCodeViewSubsection(
485     BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
486     DebugChecksumsSubsection *Checksums) const {
487   assert(Strings);
488   auto Result = llvm::make_unique<DebugFrameDataSubsection>();
489   for (const auto &YF : Frames) {
490     codeview::FrameData F;
491     F.CodeSize = YF.CodeSize;
492     F.Flags = YF.Flags;
493     F.LocalSize = YF.LocalSize;
494     F.MaxStackSize = YF.MaxStackSize;
495     F.ParamsSize = YF.ParamsSize;
496     F.PrologSize = YF.PrologSize;
497     F.RvaStart = YF.RvaStart;
498     F.SavedRegsSize = YF.SavedRegsSize;
499     F.FrameFunc = Strings->insert(YF.FrameFunc);
500     Result->addFrameData(F);
501   }
502   return std::move(Result);
503 }
504 
505 static Expected<SourceFileChecksumEntry>
506 convertOneChecksum(const DebugStringTableSubsectionRef &Strings,
507                    const FileChecksumEntry &CS) {
508   auto ExpectedString = Strings.getString(CS.FileNameOffset);
509   if (!ExpectedString)
510     return ExpectedString.takeError();
511 
512   SourceFileChecksumEntry Result;
513   Result.ChecksumBytes.Bytes = CS.Checksum;
514   Result.Kind = CS.Kind;
515   Result.FileName = *ExpectedString;
516   return Result;
517 }
518 
519 static Expected<StringRef>
520 getFileName(const DebugStringTableSubsectionRef &Strings,
521             const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) {
522   auto Iter = Checksums.getArray().at(FileID);
523   if (Iter == Checksums.getArray().end())
524     return make_error<CodeViewError>(cv_error_code::no_records);
525   uint32_t Offset = Iter->FileNameOffset;
526   return Strings.getString(Offset);
527 }
528 
529 Expected<std::shared_ptr<YAMLChecksumsSubsection>>
530 YAMLChecksumsSubsection::fromCodeViewSubsection(
531     const DebugStringTableSubsectionRef &Strings,
532     const DebugChecksumsSubsectionRef &FC) {
533   auto Result = std::make_shared<YAMLChecksumsSubsection>();
534 
535   for (const auto &CS : FC) {
536     auto ConvertedCS = convertOneChecksum(Strings, CS);
537     if (!ConvertedCS)
538       return ConvertedCS.takeError();
539     Result->Checksums.push_back(*ConvertedCS);
540   }
541   return Result;
542 }
543 
544 Expected<std::shared_ptr<YAMLLinesSubsection>>
545 YAMLLinesSubsection::fromCodeViewSubsection(
546     const DebugStringTableSubsectionRef &Strings,
547     const DebugChecksumsSubsectionRef &Checksums,
548     const DebugLinesSubsectionRef &Lines) {
549   auto Result = std::make_shared<YAMLLinesSubsection>();
550   Result->Lines.CodeSize = Lines.header()->CodeSize;
551   Result->Lines.RelocOffset = Lines.header()->RelocOffset;
552   Result->Lines.RelocSegment = Lines.header()->RelocSegment;
553   Result->Lines.Flags = static_cast<LineFlags>(uint16_t(Lines.header()->Flags));
554   for (const auto &L : Lines) {
555     SourceLineBlock Block;
556     auto EF = getFileName(Strings, Checksums, L.NameIndex);
557     if (!EF)
558       return EF.takeError();
559     Block.FileName = *EF;
560     if (Lines.hasColumnInfo()) {
561       for (const auto &C : L.Columns) {
562         SourceColumnEntry SCE;
563         SCE.EndColumn = C.EndColumn;
564         SCE.StartColumn = C.StartColumn;
565         Block.Columns.push_back(SCE);
566       }
567     }
568     for (const auto &LN : L.LineNumbers) {
569       SourceLineEntry SLE;
570       LineInfo LI(LN.Flags);
571       SLE.Offset = LN.Offset;
572       SLE.LineStart = LI.getStartLine();
573       SLE.EndDelta = LI.getLineDelta();
574       SLE.IsStatement = LI.isStatement();
575       Block.Lines.push_back(SLE);
576     }
577     Result->Lines.Blocks.push_back(Block);
578   }
579   return Result;
580 }
581 
582 Expected<std::shared_ptr<YAMLInlineeLinesSubsection>>
583 YAMLInlineeLinesSubsection::fromCodeViewSubsection(
584     const DebugStringTableSubsectionRef &Strings,
585     const DebugChecksumsSubsectionRef &Checksums,
586     const DebugInlineeLinesSubsectionRef &Lines) {
587   auto Result = std::make_shared<YAMLInlineeLinesSubsection>();
588 
589   Result->InlineeLines.HasExtraFiles = Lines.hasExtraFiles();
590   for (const auto &IL : Lines) {
591     InlineeSite Site;
592     auto ExpF = getFileName(Strings, Checksums, IL.Header->FileID);
593     if (!ExpF)
594       return ExpF.takeError();
595     Site.FileName = *ExpF;
596     Site.Inlinee = IL.Header->Inlinee.getIndex();
597     Site.SourceLineNum = IL.Header->SourceLineNum;
598     if (Lines.hasExtraFiles()) {
599       for (const auto EF : IL.ExtraFiles) {
600         auto ExpF2 = getFileName(Strings, Checksums, EF);
601         if (!ExpF2)
602           return ExpF2.takeError();
603         Site.ExtraFiles.push_back(*ExpF2);
604       }
605     }
606     Result->InlineeLines.Sites.push_back(Site);
607   }
608   return Result;
609 }
610 
611 Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>>
612 YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(
613     const DebugCrossModuleExportsSubsectionRef &Exports) {
614   auto Result = std::make_shared<YAMLCrossModuleExportsSubsection>();
615   Result->Exports.assign(Exports.begin(), Exports.end());
616   return Result;
617 }
618 
619 Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>>
620 YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
621     const DebugStringTableSubsectionRef &Strings,
622     const DebugCrossModuleImportsSubsectionRef &Imports) {
623   auto Result = std::make_shared<YAMLCrossModuleImportsSubsection>();
624   for (const auto &CMI : Imports) {
625     YAMLCrossModuleImport YCMI;
626     auto ExpectedStr = Strings.getString(CMI.Header->ModuleNameOffset);
627     if (!ExpectedStr)
628       return ExpectedStr.takeError();
629     YCMI.ModuleName = *ExpectedStr;
630     YCMI.ImportIds.assign(CMI.Imports.begin(), CMI.Imports.end());
631     Result->Imports.push_back(YCMI);
632   }
633   return Result;
634 }
635 
636 Expected<std::shared_ptr<YAMLSymbolsSubsection>>
637 YAMLSymbolsSubsection::fromCodeViewSubsection(
638     const DebugSymbolsSubsectionRef &Symbols) {
639   auto Result = std::make_shared<YAMLSymbolsSubsection>();
640   for (const auto &Sym : Symbols) {
641     auto S = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(Sym);
642     if (!S)
643       return joinErrors(make_error<CodeViewError>(
644                             cv_error_code::corrupt_record,
645                             "Invalid CodeView Symbol Record in SymbolRecord "
646                             "subsection of .debug$S while converting to YAML!"),
647                         S.takeError());
648 
649     Result->Symbols.push_back(*S);
650   }
651   return Result;
652 }
653 
654 Expected<std::shared_ptr<YAMLStringTableSubsection>>
655 YAMLStringTableSubsection::fromCodeViewSubsection(
656     const DebugStringTableSubsectionRef &Strings) {
657   auto Result = std::make_shared<YAMLStringTableSubsection>();
658   BinaryStreamReader Reader(Strings.getBuffer());
659   StringRef S;
660   // First item is a single null string, skip it.
661   if (auto EC = Reader.readCString(S))
662     return std::move(EC);
663   assert(S.empty());
664   while (Reader.bytesRemaining() > 0) {
665     if (auto EC = Reader.readCString(S))
666       return std::move(EC);
667     Result->Strings.push_back(S);
668   }
669   return Result;
670 }
671 
672 Expected<std::shared_ptr<YAMLFrameDataSubsection>>
673 YAMLFrameDataSubsection::fromCodeViewSubsection(
674     const DebugStringTableSubsectionRef &Strings,
675     const DebugFrameDataSubsectionRef &Frames) {
676   auto Result = std::make_shared<YAMLFrameDataSubsection>();
677   for (const auto &F : Frames) {
678     YAMLFrameData YF;
679     YF.CodeSize = F.CodeSize;
680     YF.Flags = F.Flags;
681     YF.LocalSize = F.LocalSize;
682     YF.MaxStackSize = F.MaxStackSize;
683     YF.ParamsSize = F.ParamsSize;
684     YF.PrologSize = F.PrologSize;
685     YF.RvaStart = F.RvaStart;
686     YF.SavedRegsSize = F.SavedRegsSize;
687 
688     auto ES = Strings.getString(F.FrameFunc);
689     if (!ES)
690       return joinErrors(
691           make_error<CodeViewError>(
692               cv_error_code::no_records,
693               "Could not find string for string id while mapping FrameData!"),
694           ES.takeError());
695     YF.FrameFunc = *ES;
696     Result->Frames.push_back(YF);
697   }
698   return Result;
699 }
700 
701 Expected<std::vector<std::unique_ptr<DebugSubsection>>>
702 llvm::CodeViewYAML::toCodeViewSubsectionList(
703     BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections,
704     DebugStringTableSubsection &Strings) {
705   std::vector<std::unique_ptr<DebugSubsection>> Result;
706   if (Subsections.empty())
707     return std::move(Result);
708 
709   auto Checksums = findChecksums(Subsections);
710   std::unique_ptr<DebugSubsection> ChecksumsBase;
711   if (Checksums)
712     ChecksumsBase =
713         Checksums->toCodeViewSubsection(Allocator, &Strings, nullptr);
714   DebugChecksumsSubsection *CS =
715       static_cast<DebugChecksumsSubsection *>(ChecksumsBase.get());
716   for (const auto &SS : Subsections) {
717     // We've already converted the checksums subsection, don't do it
718     // twice.
719     std::unique_ptr<DebugSubsection> CVS;
720     if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums)
721       CVS = std::move(ChecksumsBase);
722     else
723       CVS = SS.Subsection->toCodeViewSubsection(Allocator, &Strings, CS);
724     assert(CVS != nullptr);
725     Result.push_back(std::move(CVS));
726   }
727   return std::move(Result);
728 }
729 
730 Expected<std::vector<std::unique_ptr<codeview::DebugSubsection>>>
731 llvm::CodeViewYAML::toCodeViewSubsectionList(
732     BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections,
733     std::unique_ptr<DebugStringTableSubsection> &TakeStrings,
734     DebugStringTableSubsection *StringsRef) {
735   std::vector<std::unique_ptr<DebugSubsection>> Result;
736   if (Subsections.empty())
737     return std::move(Result);
738 
739   auto Checksums = findChecksums(Subsections);
740 
741   std::unique_ptr<DebugSubsection> ChecksumsBase;
742   if (Checksums)
743     ChecksumsBase =
744         Checksums->toCodeViewSubsection(Allocator, StringsRef, nullptr);
745   DebugChecksumsSubsection *CS =
746       static_cast<DebugChecksumsSubsection *>(ChecksumsBase.get());
747   for (const auto &SS : Subsections) {
748     // We've already converted the checksums and string table subsection, don't
749     // do it twice.
750     std::unique_ptr<DebugSubsection> CVS;
751     if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums)
752       CVS = std::move(ChecksumsBase);
753     else if (SS.Subsection->Kind == DebugSubsectionKind::StringTable) {
754       assert(TakeStrings && "No string table!");
755       CVS = std::move(TakeStrings);
756     } else
757       CVS = SS.Subsection->toCodeViewSubsection(Allocator, StringsRef, CS);
758     assert(CVS != nullptr);
759     Result.push_back(std::move(CVS));
760   }
761   return std::move(Result);
762 }
763 
764 namespace {
765 struct SubsectionConversionVisitor : public DebugSubsectionVisitor {
766   SubsectionConversionVisitor() {}
767 
768   Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override;
769   Error visitLines(DebugLinesSubsectionRef &Lines,
770                    const DebugSubsectionState &State) override;
771   Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
772                            const DebugSubsectionState &State) override;
773   Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
774                           const DebugSubsectionState &State) override;
775   Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &Checksums,
776                                 const DebugSubsectionState &State) override;
777   Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees,
778                                 const DebugSubsectionState &State) override;
779   Error visitStringTable(DebugStringTableSubsectionRef &ST,
780                          const DebugSubsectionState &State) override;
781   Error visitSymbols(DebugSymbolsSubsectionRef &Symbols,
782                      const DebugSubsectionState &State) override;
783   Error visitFrameData(DebugFrameDataSubsectionRef &Symbols,
784                        const DebugSubsectionState &State) override;
785 
786   YAMLDebugSubsection Subsection;
787 };
788 
789 Error SubsectionConversionVisitor::visitUnknown(
790     DebugUnknownSubsectionRef &Unknown) {
791   return make_error<CodeViewError>(cv_error_code::operation_unsupported);
792 }
793 
794 Error SubsectionConversionVisitor::visitLines(
795     DebugLinesSubsectionRef &Lines, const DebugSubsectionState &State) {
796   auto Result = YAMLLinesSubsection::fromCodeViewSubsection(
797       State.strings(), State.checksums(), Lines);
798   if (!Result)
799     return Result.takeError();
800   Subsection.Subsection = *Result;
801   return Error::success();
802 }
803 
804 Error SubsectionConversionVisitor::visitFileChecksums(
805     DebugChecksumsSubsectionRef &Checksums, const DebugSubsectionState &State) {
806   auto Result = YAMLChecksumsSubsection::fromCodeViewSubsection(State.strings(),
807                                                                 Checksums);
808   if (!Result)
809     return Result.takeError();
810   Subsection.Subsection = *Result;
811   return Error::success();
812 }
813 
814 Error SubsectionConversionVisitor::visitInlineeLines(
815     DebugInlineeLinesSubsectionRef &Inlinees,
816     const DebugSubsectionState &State) {
817   auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection(
818       State.strings(), State.checksums(), Inlinees);
819   if (!Result)
820     return Result.takeError();
821   Subsection.Subsection = *Result;
822   return Error::success();
823 }
824 
825 Error SubsectionConversionVisitor::visitCrossModuleExports(
826     DebugCrossModuleExportsSubsectionRef &Exports,
827     const DebugSubsectionState &State) {
828   auto Result =
829       YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(Exports);
830   if (!Result)
831     return Result.takeError();
832   Subsection.Subsection = *Result;
833   return Error::success();
834 }
835 
836 Error SubsectionConversionVisitor::visitCrossModuleImports(
837     DebugCrossModuleImportsSubsectionRef &Imports,
838     const DebugSubsectionState &State) {
839   auto Result = YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
840       State.strings(), Imports);
841   if (!Result)
842     return Result.takeError();
843   Subsection.Subsection = *Result;
844   return Error::success();
845 }
846 
847 Error SubsectionConversionVisitor::visitStringTable(
848     DebugStringTableSubsectionRef &Strings, const DebugSubsectionState &State) {
849   auto Result = YAMLStringTableSubsection::fromCodeViewSubsection(Strings);
850   if (!Result)
851     return Result.takeError();
852   Subsection.Subsection = *Result;
853   return Error::success();
854 }
855 
856 Error SubsectionConversionVisitor::visitSymbols(
857     DebugSymbolsSubsectionRef &Symbols, const DebugSubsectionState &State) {
858   auto Result = YAMLSymbolsSubsection::fromCodeViewSubsection(Symbols);
859   if (!Result)
860     return Result.takeError();
861   Subsection.Subsection = *Result;
862   return Error::success();
863 }
864 
865 Error SubsectionConversionVisitor::visitFrameData(
866     DebugFrameDataSubsectionRef &Frames, const DebugSubsectionState &State) {
867   auto Result =
868       YAMLFrameDataSubsection::fromCodeViewSubsection(State.strings(), Frames);
869   if (!Result)
870     return Result.takeError();
871   Subsection.Subsection = *Result;
872   return Error::success();
873 }
874 }
875 
876 Expected<YAMLDebugSubsection> YAMLDebugSubsection::fromCodeViewSubection(
877     const DebugStringTableSubsectionRef &Strings,
878     const DebugChecksumsSubsectionRef &Checksums,
879     const DebugSubsectionRecord &SS) {
880   DebugSubsectionState State(Strings, Checksums);
881   SubsectionConversionVisitor V;
882   if (auto EC = visitDebugSubsection(SS, V, State))
883     return std::move(EC);
884 
885   return V.Subsection;
886 }
887 
888 std::unique_ptr<DebugStringTableSubsection>
889 llvm::CodeViewYAML::findStringTable(ArrayRef<YAMLDebugSubsection> Sections) {
890   for (const auto &SS : Sections) {
891     if (SS.Subsection->Kind != DebugSubsectionKind::StringTable)
892       continue;
893 
894     // String Table doesn't use the allocator.
895     BumpPtrAllocator Allocator;
896     auto Result =
897         SS.Subsection->toCodeViewSubsection(Allocator, nullptr, nullptr);
898     return llvm::cast<DebugStringTableSubsection>(std::move(Result));
899   }
900   return nullptr;
901 }
902