LCOV - code coverage report
Current view: top level - lib/ObjectYAML - CodeViewYAMLDebugSections.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 322 370 87.0 %
Date: 2018-10-20 13:21:21 Functions: 51 59 86.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13