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