LCOV - code coverage report
Current view: top level - lib/ObjectYAML - CodeViewYAMLDebugSections.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 390 441 88.4 %
Date: 2017-09-14 15:23:50 Functions: 51 76 67.1 %
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             : LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, false)
      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         190 :   explicit YAMLSubsectionBase(DebugSubsectionKind Kind) : Kind(Kind) {}
      90             :   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          29 : struct YAMLChecksumsSubsection : public YAMLSubsectionBase {
     107             :   YAMLChecksumsSubsection()
     108          87 :       : 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          66 : struct YAMLLinesSubsection : public YAMLSubsectionBase {
     122          99 :   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           4 : struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase {
     137             :   YAMLInlineeLinesSubsection()
     138           6 :       : 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           8 : struct YAMLCrossModuleExportsSubsection : public YAMLSubsectionBase {
     153             :   YAMLCrossModuleExportsSubsection()
     154          12 :       : 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           6 :       : 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          86 : struct YAMLSymbolsSubsection : public YAMLSubsectionBase {
     182         258 :   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          64 : struct YAMLStringTableSubsection : public YAMLSubsectionBase {
     195             :   YAMLStringTableSubsection()
     196          96 :       : 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           4 : struct YAMLFrameDataSubsection : public YAMLSubsectionBase {
     209             :   YAMLFrameDataSubsection()
     210           6 :       : 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          33 : void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) {
     240          33 :   io.bitSetCase(Flags, "HasColumnInfo", LF_HaveColumns);
     241          33 :   io.enumFallback<Hex16>(Flags);
     242          33 : }
     243             : 
     244          35 : void ScalarEnumerationTraits<FileChecksumKind>::enumeration(
     245             :     IO &io, FileChecksumKind &Kind) {
     246          35 :   io.enumCase(Kind, "None", FileChecksumKind::None);
     247          35 :   io.enumCase(Kind, "MD5", FileChecksumKind::MD5);
     248          35 :   io.enumCase(Kind, "SHA1", FileChecksumKind::SHA1);
     249          35 :   io.enumCase(Kind, "SHA256", FileChecksumKind::SHA256);
     250          35 : }
     251             : 
     252           5 : void ScalarTraits<HexFormattedString>::output(const HexFormattedString &Value,
     253             :                                               void *ctx, raw_ostream &Out) {
     254          10 :   StringRef Bytes(reinterpret_cast<const char *>(Value.Bytes.data()),
     255          10 :                   Value.Bytes.size());
     256          15 :   Out << toHex(Bytes);
     257           5 : }
     258             : 
     259          30 : StringRef ScalarTraits<HexFormattedString>::input(StringRef Scalar, void *ctxt,
     260             :                                                   HexFormattedString &Value) {
     261          60 :   std::string H = fromHex(Scalar);
     262         120 :   Value.Bytes.assign(H.begin(), H.end());
     263          60 :   return StringRef();
     264             : }
     265             : 
     266          78 : void MappingTraits<SourceLineEntry>::mapping(IO &IO, SourceLineEntry &Obj) {
     267         156 :   IO.mapRequired("Offset", Obj.Offset);
     268         156 :   IO.mapRequired("LineStart", Obj.LineStart);
     269         156 :   IO.mapRequired("IsStatement", Obj.IsStatement);
     270         156 :   IO.mapRequired("EndDelta", Obj.EndDelta);
     271          78 : }
     272             : 
     273           1 : void MappingTraits<SourceColumnEntry>::mapping(IO &IO, SourceColumnEntry &Obj) {
     274           2 :   IO.mapRequired("StartColumn", Obj.StartColumn);
     275           2 :   IO.mapRequired("EndColumn", Obj.EndColumn);
     276           1 : }
     277             : 
     278          33 : void MappingTraits<SourceLineBlock>::mapping(IO &IO, SourceLineBlock &Obj) {
     279          66 :   IO.mapRequired("FileName", Obj.FileName);
     280          66 :   IO.mapRequired("Lines", Obj.Lines);
     281          66 :   IO.mapRequired("Columns", Obj.Columns);
     282          33 : }
     283             : 
     284           8 : void MappingTraits<CrossModuleExport>::mapping(IO &IO, CrossModuleExport &Obj) {
     285          16 :   IO.mapRequired("LocalId", Obj.Local);
     286          16 :   IO.mapRequired("GlobalId", Obj.Global);
     287           8 : }
     288             : 
     289           2 : void MappingTraits<YAMLCrossModuleImport>::mapping(IO &IO,
     290             :                                                    YAMLCrossModuleImport &Obj) {
     291           4 :   IO.mapRequired("Module", Obj.ModuleName);
     292           4 :   IO.mapRequired("Imports", Obj.ImportIds);
     293           2 : }
     294             : 
     295          35 : void MappingTraits<SourceFileChecksumEntry>::mapping(
     296             :     IO &IO, SourceFileChecksumEntry &Obj) {
     297          70 :   IO.mapRequired("FileName", Obj.FileName);
     298          70 :   IO.mapRequired("Kind", Obj.Kind);
     299          70 :   IO.mapRequired("Checksum", Obj.ChecksumBytes);
     300          35 : }
     301             : 
     302           2 : void MappingTraits<InlineeSite>::mapping(IO &IO, InlineeSite &Obj) {
     303           4 :   IO.mapRequired("FileName", Obj.FileName);
     304           4 :   IO.mapRequired("LineNum", Obj.SourceLineNum);
     305           4 :   IO.mapRequired("Inlinee", Obj.Inlinee);
     306           4 :   IO.mapOptional("ExtraFiles", Obj.ExtraFiles);
     307           2 : }
     308             : 
     309           2 : void MappingTraits<YAMLFrameData>::mapping(IO &IO, YAMLFrameData &Obj) {
     310           4 :   IO.mapRequired("CodeSize", Obj.CodeSize);
     311           4 :   IO.mapRequired("FrameFunc", Obj.FrameFunc);
     312           4 :   IO.mapRequired("LocalSize", Obj.LocalSize);
     313           4 :   IO.mapOptional("MaxStackSize", Obj.MaxStackSize);
     314           4 :   IO.mapOptional("ParamsSize", Obj.ParamsSize);
     315           4 :   IO.mapOptional("PrologSize", Obj.PrologSize);
     316           4 :   IO.mapOptional("RvaStart", Obj.RvaStart);
     317           4 :   IO.mapOptional("SavedRegsSize", Obj.SavedRegsSize);
     318           2 : }
     319             : 
     320          29 : void YAMLChecksumsSubsection::map(IO &IO) {
     321          58 :   IO.mapTag("!FileChecksums", true);
     322          58 :   IO.mapRequired("Checksums", Checksums);
     323          29 : }
     324             : 
     325          33 : void YAMLLinesSubsection::map(IO &IO) {
     326          66 :   IO.mapTag("!Lines", true);
     327          66 :   IO.mapRequired("CodeSize", Lines.CodeSize);
     328             : 
     329          66 :   IO.mapRequired("Flags", Lines.Flags);
     330          66 :   IO.mapRequired("RelocOffset", Lines.RelocOffset);
     331          66 :   IO.mapRequired("RelocSegment", Lines.RelocSegment);
     332          66 :   IO.mapRequired("Blocks", Lines.Blocks);
     333          33 : }
     334             : 
     335           2 : void YAMLInlineeLinesSubsection::map(IO &IO) {
     336           4 :   IO.mapTag("!InlineeLines", true);
     337           4 :   IO.mapRequired("HasExtraFiles", InlineeLines.HasExtraFiles);
     338           4 :   IO.mapRequired("Sites", InlineeLines.Sites);
     339           2 : }
     340             : 
     341           4 : void YAMLCrossModuleExportsSubsection::map(IO &IO) {
     342           8 :   IO.mapTag("!CrossModuleExports", true);
     343           8 :   IO.mapOptional("Exports", Exports);
     344           4 : }
     345             : 
     346           2 : void YAMLCrossModuleImportsSubsection::map(IO &IO) {
     347           4 :   IO.mapTag("!CrossModuleImports", true);
     348           4 :   IO.mapOptional("Imports", Imports);
     349           2 : }
     350             : 
     351          86 : void YAMLSymbolsSubsection::map(IO &IO) {
     352         172 :   IO.mapTag("!Symbols", true);
     353         172 :   IO.mapRequired("Records", Symbols);
     354          86 : }
     355             : 
     356          32 : void YAMLStringTableSubsection::map(IO &IO) {
     357          64 :   IO.mapTag("!StringTable", true);
     358          64 :   IO.mapRequired("Strings", Strings);
     359          32 : }
     360             : 
     361           2 : void YAMLFrameDataSubsection::map(IO &IO) {
     362           4 :   IO.mapTag("!FrameData", true);
     363           4 :   IO.mapRequired("Frames", Frames);
     364           2 : }
     365             : 
     366           0 : void YAMLCoffSymbolRVASubsection::map(IO &IO) {
     367           0 :   IO.mapTag("!COFFSymbolRVAs", true);
     368           0 :   IO.mapRequired("RVAs", RVAs);
     369           0 : }
     370             : 
     371         190 : void MappingTraits<YAMLDebugSubsection>::mapping(
     372             :     IO &IO, YAMLDebugSubsection &Subsection) {
     373         190 :   if (!IO.outputting()) {
     374         344 :     if (IO.mapTag("!FileChecksums")) {
     375          26 :       auto SS = std::make_shared<YAMLChecksumsSubsection>();
     376          52 :       Subsection.Subsection = SS;
     377         292 :     } else if (IO.mapTag("!Lines")) {
     378          87 :       Subsection.Subsection = std::make_shared<YAMLLinesSubsection>();
     379         234 :     } else if (IO.mapTag("!InlineeLines")) {
     380           3 :       Subsection.Subsection = std::make_shared<YAMLInlineeLinesSubsection>();
     381         232 :     } else if (IO.mapTag("!CrossModuleExports")) {
     382           2 :       Subsection.Subsection =
     383           4 :           std::make_shared<YAMLCrossModuleExportsSubsection>();
     384         228 :     } else if (IO.mapTag("!CrossModuleImports")) {
     385           1 :       Subsection.Subsection =
     386           2 :           std::make_shared<YAMLCrossModuleImportsSubsection>();
     387         226 :     } else if (IO.mapTag("!Symbols")) {
     388         246 :       Subsection.Subsection = std::make_shared<YAMLSymbolsSubsection>();
     389          62 :     } else if (IO.mapTag("!StringTable")) {
     390          90 :       Subsection.Subsection = std::make_shared<YAMLStringTableSubsection>();
     391           2 :     } else if (IO.mapTag("!FrameData")) {
     392           3 :       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         380 :   Subsection.Subsection->map(IO);
     400         190 : }
     401             : 
     402          50 : std::shared_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection(
     403             :     BumpPtrAllocator &Allocator,
     404             :     const codeview::StringsAndChecksums &SC) const {
     405             :   assert(SC.hasStrings());
     406         200 :   auto Result = std::make_shared<DebugChecksumsSubsection>(*SC.strings());
     407         258 :   for (const auto &CS : Checksums) {
     408         116 :     Result->addChecksum(CS.FileName, CS.Kind, CS.ChecksumBytes.Bytes);
     409             :   }
     410         100 :   return Result;
     411             : }
     412             : 
     413          29 : 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         145 :       std::make_shared<DebugLinesSubsection>(*SC.checksums(), *SC.strings());
     419          29 :   Result->setCodeSize(Lines.CodeSize);
     420          29 :   Result->setRelocationAddress(Lines.RelocSegment, Lines.RelocOffset);
     421          29 :   Result->setFlags(Lines.Flags);
     422         145 :   for (const auto &LC : Lines.Blocks) {
     423          29 :     Result->createBlock(LC.FileName);
     424          29 :     if (Result->hasColumnInfo()) {
     425           6 :       for (const auto &Item : zip(LC.Lines, LC.Columns)) {
     426           1 :         auto &L = std::get<0>(Item);
     427           1 :         auto &C = std::get<1>(Item);
     428           1 :         uint32_t LE = L.LineStart + L.EndDelta;
     429           4 :         Result->addLineAndColumnInfo(L.Offset,
     430           2 :                                      LineInfo(L.LineStart, LE, L.IsStatement),
     431           2 :                                      C.StartColumn, C.EndColumn);
     432             :       }
     433             :     } else {
     434         177 :       for (const auto &L : LC.Lines) {
     435          65 :         uint32_t LE = L.LineStart + L.EndDelta;
     436          65 :         Result->addLineInfo(L.Offset, LineInfo(L.LineStart, LE, L.IsStatement));
     437             :       }
     438             :     }
     439             :   }
     440          58 :   return Result;
     441             : }
     442             : 
     443             : std::shared_ptr<DebugSubsection>
     444           1 : YAMLInlineeLinesSubsection::toCodeViewSubsection(
     445             :     BumpPtrAllocator &Allocator,
     446             :     const codeview::StringsAndChecksums &SC) const {
     447             :   assert(SC.hasChecksums());
     448             :   auto Result = std::make_shared<DebugInlineeLinesSubsection>(
     449           4 :       *SC.checksums(), InlineeLines.HasExtraFiles);
     450             : 
     451           5 :   for (const auto &Site : InlineeLines.Sites) {
     452           3 :     Result->addInlineSite(TypeIndex(Site.Inlinee), Site.FileName,
     453           1 :                           Site.SourceLineNum);
     454           1 :     if (!InlineeLines.HasExtraFiles)
     455           1 :       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           2 :   auto Result = std::make_shared<DebugCrossModuleExportsSubsection>();
     469          12 :   for (const auto &M : Exports)
     470          12 :     Result->addMapping(M.Local, M.Global);
     471           4 :   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           4 :       std::make_shared<DebugCrossModuleImportsSubsection>(*SC.strings());
     482           5 :   for (const auto &M : Imports) {
     483           6 :     for (const auto Id : M.ImportIds)
     484           2 :       Result->addImport(M.ModuleName, Id);
     485             :   }
     486           2 :   return Result;
     487             : }
     488             : 
     489          80 : std::shared_ptr<DebugSubsection> YAMLSymbolsSubsection::toCodeViewSubsection(
     490             :     BumpPtrAllocator &Allocator,
     491             :     const codeview::StringsAndChecksums &SC) const {
     492          80 :   auto Result = std::make_shared<DebugSymbolsSubsection>();
     493         495 :   for (const auto &Sym : Symbols)
     494         350 :     Result->addSymbol(
     495         350 :         Sym.toCodeViewSymbol(Allocator, CodeViewContainer::ObjectFile));
     496         160 :   return Result;
     497             : }
     498             : 
     499             : std::shared_ptr<DebugSubsection>
     500          57 : YAMLStringTableSubsection::toCodeViewSubsection(
     501             :     BumpPtrAllocator &Allocator,
     502             :     const codeview::StringsAndChecksums &SC) const {
     503          57 :   auto Result = std::make_shared<DebugStringTableSubsection>();
     504         285 :   for (const auto &Str : this->Strings)
     505          57 :     Result->insert(Str);
     506         114 :   return Result;
     507             : }
     508             : 
     509           1 : std::shared_ptr<DebugSubsection> YAMLFrameDataSubsection::toCodeViewSubsection(
     510             :     BumpPtrAllocator &Allocator,
     511             :     const codeview::StringsAndChecksums &SC) const {
     512             :   assert(SC.hasStrings());
     513             : 
     514           1 :   auto Result = std::make_shared<DebugFrameDataSubsection>();
     515           5 :   for (const auto &YF : Frames) {
     516             :     codeview::FrameData F;
     517           2 :     F.CodeSize = YF.CodeSize;
     518           2 :     F.Flags = YF.Flags;
     519           2 :     F.LocalSize = YF.LocalSize;
     520           2 :     F.MaxStackSize = YF.MaxStackSize;
     521           2 :     F.ParamsSize = YF.ParamsSize;
     522           2 :     F.PrologSize = YF.PrologSize;
     523           2 :     F.RvaStart = YF.RvaStart;
     524           2 :     F.SavedRegsSize = YF.SavedRegsSize;
     525           3 :     F.FrameFunc = SC.strings()->insert(YF.FrameFunc);
     526           1 :     Result->addFrameData(F);
     527             :   }
     528           2 :   return Result;
     529             : }
     530             : 
     531             : std::shared_ptr<DebugSubsection>
     532           0 : YAMLCoffSymbolRVASubsection::toCodeViewSubsection(
     533             :     BumpPtrAllocator &Allocator,
     534             :     const codeview::StringsAndChecksums &SC) const {
     535           0 :   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           5 : convertOneChecksum(const DebugStringTableSubsectionRef &Strings,
     543             :                    const FileChecksumEntry &CS) {
     544          10 :   auto ExpectedString = Strings.getString(CS.FileNameOffset);
     545           5 :   if (!ExpectedString)
     546           0 :     return ExpectedString.takeError();
     547             : 
     548           5 :   SourceFileChecksumEntry Result;
     549          20 :   Result.ChecksumBytes.Bytes = CS.Checksum;
     550           5 :   Result.Kind = CS.Kind;
     551           5 :   Result.FileName = *ExpectedString;
     552           5 :   return Result;
     553             : }
     554             : 
     555             : static Expected<StringRef>
     556           5 : getFileName(const DebugStringTableSubsectionRef &Strings,
     557             :             const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) {
     558          15 :   auto Iter = Checksums.getArray().at(FileID);
     559          15 :   if (Iter == Checksums.getArray().end())
     560           0 :     return make_error<CodeViewError>(cv_error_code::no_records);
     561           5 :   uint32_t Offset = Iter->FileNameOffset;
     562           5 :   return Strings.getString(Offset);
     563             : }
     564             : 
     565             : Expected<std::shared_ptr<YAMLChecksumsSubsection>>
     566           3 : YAMLChecksumsSubsection::fromCodeViewSubsection(
     567             :     const DebugStringTableSubsectionRef &Strings,
     568             :     const DebugChecksumsSubsectionRef &FC) {
     569           3 :   auto Result = std::make_shared<YAMLChecksumsSubsection>();
     570             : 
     571          20 :   for (const auto &CS : FC) {
     572          10 :     auto ConvertedCS = convertOneChecksum(Strings, CS);
     573           5 :     if (!ConvertedCS)
     574           0 :       return ConvertedCS.takeError();
     575          10 :     Result->Checksums.push_back(*ConvertedCS);
     576             :   }
     577           3 :   return Result;
     578             : }
     579             : 
     580             : Expected<std::shared_ptr<YAMLLinesSubsection>>
     581           4 : YAMLLinesSubsection::fromCodeViewSubsection(
     582             :     const DebugStringTableSubsectionRef &Strings,
     583             :     const DebugChecksumsSubsectionRef &Checksums,
     584             :     const DebugLinesSubsectionRef &Lines) {
     585           4 :   auto Result = std::make_shared<YAMLLinesSubsection>();
     586          12 :   Result->Lines.CodeSize = Lines.header()->CodeSize;
     587          12 :   Result->Lines.RelocOffset = Lines.header()->RelocOffset;
     588          12 :   Result->Lines.RelocSegment = Lines.header()->RelocSegment;
     589          12 :   Result->Lines.Flags = static_cast<LineFlags>(uint16_t(Lines.header()->Flags));
     590          20 :   for (const auto &L : Lines) {
     591           8 :     SourceLineBlock Block;
     592          12 :     auto EF = getFileName(Strings, Checksums, L.NameIndex);
     593           4 :     if (!EF)
     594           0 :       return EF.takeError();
     595           4 :     Block.FileName = *EF;
     596           4 :     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          32 :     for (const auto &LN : L.LineNumbers) {
     605             :       SourceLineEntry SLE;
     606          36 :       LineInfo LI(LN.Flags);
     607          24 :       SLE.Offset = LN.Offset;
     608          12 :       SLE.LineStart = LI.getStartLine();
     609          12 :       SLE.EndDelta = LI.getLineDelta();
     610          12 :       SLE.IsStatement = LI.isStatement();
     611          12 :       Block.Lines.push_back(SLE);
     612             :     }
     613           4 :     Result->Lines.Blocks.push_back(Block);
     614             :   }
     615           4 :   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           2 :   auto Result = std::make_shared<YAMLInlineeLinesSubsection>();
     624             : 
     625           1 :   Result->InlineeLines.HasExtraFiles = Lines.hasExtraFiles();
     626           5 :   for (const auto &IL : Lines) {
     627           2 :     InlineeSite Site;
     628           3 :     auto ExpF = getFileName(Strings, Checksums, IL.Header->FileID);
     629           1 :     if (!ExpF)
     630           0 :       return ExpF.takeError();
     631           1 :     Site.FileName = *ExpF;
     632           2 :     Site.Inlinee = IL.Header->Inlinee.getIndex();
     633           2 :     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           0 :           return ExpF2.takeError();
     639           0 :         Site.ExtraFiles.push_back(*ExpF2);
     640             :       }
     641             :     }
     642           1 :     Result->InlineeLines.Sites.push_back(Site);
     643             :   }
     644           1 :   return Result;
     645             : }
     646             : 
     647             : Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>>
     648           2 : YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(
     649             :     const DebugCrossModuleExportsSubsectionRef &Exports) {
     650           4 :   auto Result = std::make_shared<YAMLCrossModuleExportsSubsection>();
     651          10 :   Result->Exports.assign(Exports.begin(), Exports.end());
     652           6 :   return Result;
     653             : }
     654             : 
     655             : Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>>
     656           1 : YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
     657             :     const DebugStringTableSubsectionRef &Strings,
     658             :     const DebugCrossModuleImportsSubsectionRef &Imports) {
     659           1 :   auto Result = std::make_shared<YAMLCrossModuleImportsSubsection>();
     660           5 :   for (const auto &CMI : Imports) {
     661           2 :     YAMLCrossModuleImport YCMI;
     662           3 :     auto ExpectedStr = Strings.getString(CMI.Header->ModuleNameOffset);
     663           1 :     if (!ExpectedStr)
     664           0 :       return ExpectedStr.takeError();
     665           1 :     YCMI.ModuleName = *ExpectedStr;
     666           5 :     YCMI.ImportIds.assign(CMI.Imports.begin(), CMI.Imports.end());
     667           1 :     Result->Imports.push_back(YCMI);
     668             :   }
     669           1 :   return Result;
     670             : }
     671             : 
     672             : Expected<std::shared_ptr<YAMLSymbolsSubsection>>
     673           4 : YAMLSymbolsSubsection::fromCodeViewSubsection(
     674             :     const DebugSymbolsSubsectionRef &Symbols) {
     675           4 :   auto Result = std::make_shared<YAMLSymbolsSubsection>();
     676          26 :   for (const auto &Sym : Symbols) {
     677          18 :     auto S = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(Sym);
     678           6 :     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          12 :     Result->Symbols.push_back(*S);
     686             :   }
     687           4 :   return Result;
     688             : }
     689             : 
     690             : Expected<std::shared_ptr<YAMLStringTableSubsection>>
     691           2 : YAMLStringTableSubsection::fromCodeViewSubsection(
     692             :     const DebugStringTableSubsectionRef &Strings) {
     693           4 :   auto Result = std::make_shared<YAMLStringTableSubsection>();
     694           6 :   BinaryStreamReader Reader(Strings.getBuffer());
     695           2 :   StringRef S;
     696             :   // First item is a single null string, skip it.
     697           6 :   if (auto EC = Reader.readCString(S))
     698           0 :     return std::move(EC);
     699             :   assert(S.empty());
     700          20 :   while (Reader.bytesRemaining() > 0) {
     701          27 :     if (auto EC = Reader.readCString(S))
     702           0 :       return std::move(EC);
     703           9 :     Result->Strings.push_back(S);
     704             :   }
     705           2 :   return Result;
     706             : }
     707             : 
     708             : Expected<std::shared_ptr<YAMLFrameDataSubsection>>
     709           1 : YAMLFrameDataSubsection::fromCodeViewSubsection(
     710             :     const DebugStringTableSubsectionRef &Strings,
     711             :     const DebugFrameDataSubsectionRef &Frames) {
     712           1 :   auto Result = std::make_shared<YAMLFrameDataSubsection>();
     713           6 :   for (const auto &F : Frames) {
     714           1 :     YAMLFrameData YF;
     715           2 :     YF.CodeSize = F.CodeSize;
     716           2 :     YF.Flags = F.Flags;
     717           2 :     YF.LocalSize = F.LocalSize;
     718           2 :     YF.MaxStackSize = F.MaxStackSize;
     719           2 :     YF.ParamsSize = F.ParamsSize;
     720           2 :     YF.PrologSize = F.PrologSize;
     721           2 :     YF.RvaStart = F.RvaStart;
     722           2 :     YF.SavedRegsSize = F.SavedRegsSize;
     723             : 
     724           3 :     auto ES = Strings.getString(F.FrameFunc);
     725           1 :     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           1 :     YF.FrameFunc = *ES;
     732           1 :     Result->Frames.push_back(YF);
     733             :   }
     734           1 :   return Result;
     735             : }
     736             : 
     737             : Expected<std::shared_ptr<YAMLCoffSymbolRVASubsection>>
     738           0 : YAMLCoffSymbolRVASubsection::fromCodeViewSubsection(
     739             :     const DebugSymbolRVASubsectionRef &Section) {
     740           0 :   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          44 : llvm::CodeViewYAML::toCodeViewSubsectionList(
     749             :     BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections,
     750             :     const codeview::StringsAndChecksums &SC) {
     751          88 :   std::vector<std::shared_ptr<DebugSubsection>> Result;
     752          44 :   if (Subsections.empty())
     753           9 :     return std::move(Result);
     754             : 
     755         238 :   for (const auto &SS : Subsections) {
     756         336 :     std::shared_ptr<DebugSubsection> CVS;
     757         672 :     CVS = SS.Subsection->toCodeViewSubsection(Allocator, SC);
     758             :     assert(CVS != nullptr);
     759         336 :     Result.push_back(std::move(CVS));
     760             :   }
     761          35 :   return std::move(Result);
     762             : }
     763             : 
     764             : namespace {
     765             : 
     766          36 : 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           4 : Error SubsectionConversionVisitor::visitLines(
     800             :     DebugLinesSubsectionRef &Lines, const StringsAndChecksumsRef &State) {
     801             :   auto Result = YAMLLinesSubsection::fromCodeViewSubsection(
     802           8 :       State.strings(), State.checksums(), Lines);
     803           4 :   if (!Result)
     804             :     return Result.takeError();
     805           8 :   Subsection.Subsection = *Result;
     806          12 :   return Error::success();
     807             : }
     808             : 
     809           3 : Error SubsectionConversionVisitor::visitFileChecksums(
     810             :     DebugChecksumsSubsectionRef &Checksums,
     811             :     const StringsAndChecksumsRef &State) {
     812             :   auto Result = YAMLChecksumsSubsection::fromCodeViewSubsection(State.strings(),
     813           6 :                                                                 Checksums);
     814           3 :   if (!Result)
     815             :     return Result.takeError();
     816           6 :   Subsection.Subsection = *Result;
     817           9 :   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           2 :   Subsection.Subsection = *Result;
     828           3 :   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           4 :   Subsection.Subsection = *Result;
     839           6 :   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           2 :   Subsection.Subsection = *Result;
     850           3 :   return Error::success();
     851             : }
     852             : 
     853           2 : Error SubsectionConversionVisitor::visitStringTable(
     854             :     DebugStringTableSubsectionRef &Strings,
     855             :     const StringsAndChecksumsRef &State) {
     856           4 :   auto Result = YAMLStringTableSubsection::fromCodeViewSubsection(Strings);
     857           2 :   if (!Result)
     858             :     return Result.takeError();
     859           4 :   Subsection.Subsection = *Result;
     860           6 :   return Error::success();
     861             : }
     862             : 
     863           4 : Error SubsectionConversionVisitor::visitSymbols(
     864             :     DebugSymbolsSubsectionRef &Symbols, const StringsAndChecksumsRef &State) {
     865           8 :   auto Result = YAMLSymbolsSubsection::fromCodeViewSubsection(Symbols);
     866           4 :   if (!Result)
     867             :     return Result.takeError();
     868           8 :   Subsection.Subsection = *Result;
     869          12 :   return Error::success();
     870             : }
     871             : 
     872           1 : Error SubsectionConversionVisitor::visitFrameData(
     873             :     DebugFrameDataSubsectionRef &Frames, const StringsAndChecksumsRef &State) {
     874             :   auto Result =
     875           2 :       YAMLFrameDataSubsection::fromCodeViewSubsection(State.strings(), Frames);
     876           1 :   if (!Result)
     877             :     return Result.takeError();
     878           2 :   Subsection.Subsection = *Result;
     879           3 :   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           0 :   Subsection.Subsection = *Result;
     888           0 :   return Error::success();
     889             : }
     890             : 
     891             : Expected<YAMLDebugSubsection>
     892          18 : YAMLDebugSubsection::fromCodeViewSubection(const StringsAndChecksumsRef &SC,
     893             :                                            const DebugSubsectionRecord &SS) {
     894          36 :   SubsectionConversionVisitor V;
     895          54 :   if (auto EC = visitDebugSubsection(SS, V, SC))
     896           0 :     return std::move(EC);
     897             : 
     898             :   return V.Subsection;
     899             : }
     900             : 
     901             : std::vector<YAMLDebugSubsection>
     902           2 : llvm::CodeViewYAML::fromDebugS(ArrayRef<uint8_t> Data,
     903             :                                const StringsAndChecksumsRef &SC) {
     904           4 :   BinaryStreamReader Reader(Data, support::little);
     905             :   uint32_t Magic;
     906             : 
     907          10 :   ExitOnError Err("Invalid .debug$S section!");
     908           4 :   Err(Reader.readInteger(Magic));
     909             :   assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$S section!");
     910             : 
     911           4 :   DebugSubsectionArray Subsections;
     912           4 :   Err(Reader.readArray(Subsections, Reader.bytesRemaining()));
     913             : 
     914           2 :   std::vector<YAMLDebugSubsection> Result;
     915             : 
     916          12 :   for (const auto &SS : Subsections) {
     917           8 :     auto YamlSS = Err(YAMLDebugSubsection::fromCodeViewSubection(SC, SS));
     918           4 :     Result.push_back(YamlSS);
     919             :   }
     920           2 :   return Result;
     921             : }
     922             : 
     923          41 : void llvm::CodeViewYAML::initializeStringsAndChecksums(
     924             :     ArrayRef<YAMLDebugSubsection> Sections, codeview::StringsAndChecksums &SC) {
     925             :   // String Table and Checksums subsections don't use the allocator.
     926          82 :   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          41 :   if (!SC.hasStrings()) {
     936         160 :     for (const auto &SS : Sections) {
     937         264 :       if (SS.Subsection->Kind != DebugSubsectionKind::StringTable)
     938         104 :         continue;
     939             : 
     940          84 :       auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC);
     941          28 :       SC.setStrings(
     942          56 :           std::static_pointer_cast<DebugStringTableSubsection>(Result));
     943             :       break;
     944             :     }
     945             :   }
     946             : 
     947          82 :   if (SC.hasStrings() && !SC.hasChecksums()) {
     948         172 :     for (const auto &SS : Sections) {
     949         230 :       if (SS.Subsection->Kind != DebugSubsectionKind::FileChecksums)
     950          90 :         continue;
     951             : 
     952          75 :       auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC);
     953          25 :       SC.setChecksums(
     954          50 :           std::static_pointer_cast<DebugChecksumsSubsection>(Result));
     955             :       break;
     956             :     }
     957             :   }
     958          41 : }

Generated by: LCOV version 1.13