11b88f4f3SZachary Turner //===- CodeViewYAMLDebugSections.cpp - CodeView YAMLIO debug sections -----===//
21b88f4f3SZachary Turner //
31b88f4f3SZachary Turner //                     The LLVM Compiler Infrastructure
41b88f4f3SZachary Turner //
51b88f4f3SZachary Turner // This file is distributed under the University of Illinois Open Source
61b88f4f3SZachary Turner // License. See LICENSE.TXT for details.
71b88f4f3SZachary Turner //
81b88f4f3SZachary Turner //===----------------------------------------------------------------------===//
91b88f4f3SZachary Turner //
101b88f4f3SZachary Turner // This file defines classes for handling the YAML representation of CodeView
111b88f4f3SZachary Turner // Debug Info.
121b88f4f3SZachary Turner //
131b88f4f3SZachary Turner //===----------------------------------------------------------------------===//
141b88f4f3SZachary Turner 
151b88f4f3SZachary Turner #include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h"
161b88f4f3SZachary Turner 
171b88f4f3SZachary Turner #include "llvm/ADT/StringExtras.h"
181b88f4f3SZachary Turner #include "llvm/ADT/StringSwitch.h"
191b88f4f3SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewError.h"
2092dcdda6SZachary Turner #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
2192dcdda6SZachary Turner #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
2292dcdda6SZachary Turner #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
2392dcdda6SZachary Turner #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
2492dcdda6SZachary Turner #include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
251b88f4f3SZachary Turner #include "llvm/DebugInfo/CodeView/EnumTables.h"
261b88f4f3SZachary Turner #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
271b88f4f3SZachary Turner 
281b88f4f3SZachary Turner using namespace llvm;
291b88f4f3SZachary Turner using namespace llvm::codeview;
301b88f4f3SZachary Turner using namespace llvm::CodeViewYAML;
311b88f4f3SZachary Turner using namespace llvm::CodeViewYAML::detail;
321b88f4f3SZachary Turner using namespace llvm::yaml;
331b88f4f3SZachary Turner 
341b88f4f3SZachary Turner LLVM_YAML_IS_SEQUENCE_VECTOR(SourceFileChecksumEntry)
351b88f4f3SZachary Turner LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineEntry)
361b88f4f3SZachary Turner LLVM_YAML_IS_SEQUENCE_VECTOR(SourceColumnEntry)
371b88f4f3SZachary Turner LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineBlock)
381b88f4f3SZachary Turner LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineInfo)
391b88f4f3SZachary Turner LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeSite)
401b88f4f3SZachary Turner LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeInfo)
411b88f4f3SZachary Turner LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
421b88f4f3SZachary Turner 
431b88f4f3SZachary Turner LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, false)
4492dcdda6SZachary Turner LLVM_YAML_DECLARE_ENUM_TRAITS(DebugSubsectionKind)
451b88f4f3SZachary Turner LLVM_YAML_DECLARE_ENUM_TRAITS(FileChecksumKind)
461b88f4f3SZachary Turner LLVM_YAML_DECLARE_BITSET_TRAITS(LineFlags)
471b88f4f3SZachary Turner 
4892dcdda6SZachary Turner LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineEntry)
4992dcdda6SZachary Turner LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceColumnEntry)
5092dcdda6SZachary Turner LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceFileChecksumEntry)
5192dcdda6SZachary Turner LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineBlock)
5292dcdda6SZachary Turner LLVM_YAML_DECLARE_MAPPING_TRAITS(InlineeSite)
5392dcdda6SZachary Turner 
5492dcdda6SZachary Turner namespace llvm {
5592dcdda6SZachary Turner namespace CodeViewYAML {
5692dcdda6SZachary Turner namespace detail {
5792dcdda6SZachary Turner struct YAMLSubsectionBase {
5892dcdda6SZachary Turner   explicit YAMLSubsectionBase(DebugSubsectionKind Kind) : Kind(Kind) {}
5992dcdda6SZachary Turner   DebugSubsectionKind Kind;
6092dcdda6SZachary Turner   virtual ~YAMLSubsectionBase() {}
6192dcdda6SZachary Turner 
6292dcdda6SZachary Turner   virtual void map(IO &IO) = 0;
6392dcdda6SZachary Turner   virtual std::unique_ptr<DebugSubsection>
6492dcdda6SZachary Turner   toCodeViewSubsection(DebugStringTableSubsection *UseStrings,
6592dcdda6SZachary Turner                        DebugChecksumsSubsection *UseChecksums) const = 0;
6692dcdda6SZachary Turner };
6792dcdda6SZachary Turner }
6892dcdda6SZachary Turner }
6992dcdda6SZachary Turner }
7092dcdda6SZachary Turner 
7192dcdda6SZachary Turner namespace {
7292dcdda6SZachary Turner struct YAMLChecksumsSubsection : public YAMLSubsectionBase {
7392dcdda6SZachary Turner   YAMLChecksumsSubsection()
7492dcdda6SZachary Turner       : YAMLSubsectionBase(DebugSubsectionKind::FileChecksums) {}
7592dcdda6SZachary Turner 
7692dcdda6SZachary Turner   void map(IO &IO) override;
7792dcdda6SZachary Turner   std::unique_ptr<DebugSubsection>
7892dcdda6SZachary Turner   toCodeViewSubsection(DebugStringTableSubsection *Strings,
7992dcdda6SZachary Turner                        DebugChecksumsSubsection *Checksums) const override;
8092dcdda6SZachary Turner   static Expected<std::shared_ptr<YAMLChecksumsSubsection>>
8192dcdda6SZachary Turner   fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
8292dcdda6SZachary Turner                          const DebugChecksumsSubsectionRef &FC);
8392dcdda6SZachary Turner 
8492dcdda6SZachary Turner   std::vector<SourceFileChecksumEntry> Checksums;
8592dcdda6SZachary Turner };
8692dcdda6SZachary Turner 
8792dcdda6SZachary Turner struct YAMLLinesSubsection : public YAMLSubsectionBase {
8892dcdda6SZachary Turner   YAMLLinesSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Lines) {}
8992dcdda6SZachary Turner 
9092dcdda6SZachary Turner   void map(IO &IO) override;
9192dcdda6SZachary Turner   std::unique_ptr<DebugSubsection>
9292dcdda6SZachary Turner   toCodeViewSubsection(DebugStringTableSubsection *Strings,
9392dcdda6SZachary Turner                        DebugChecksumsSubsection *Checksums) const override;
9492dcdda6SZachary Turner   static Expected<std::shared_ptr<YAMLLinesSubsection>>
9592dcdda6SZachary Turner   fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
9692dcdda6SZachary Turner                          const DebugChecksumsSubsectionRef &Checksums,
9792dcdda6SZachary Turner                          const DebugLinesSubsectionRef &Lines);
9892dcdda6SZachary Turner 
9992dcdda6SZachary Turner   SourceLineInfo Lines;
10092dcdda6SZachary Turner };
10192dcdda6SZachary Turner 
10292dcdda6SZachary Turner struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase {
10392dcdda6SZachary Turner   YAMLInlineeLinesSubsection()
10492dcdda6SZachary Turner       : YAMLSubsectionBase(DebugSubsectionKind::InlineeLines) {}
10592dcdda6SZachary Turner 
10692dcdda6SZachary Turner   void map(IO &IO) override;
10792dcdda6SZachary Turner   std::unique_ptr<DebugSubsection>
10892dcdda6SZachary Turner   toCodeViewSubsection(DebugStringTableSubsection *Strings,
10992dcdda6SZachary Turner                        DebugChecksumsSubsection *Checksums) const override;
11092dcdda6SZachary Turner   static Expected<std::shared_ptr<YAMLInlineeLinesSubsection>>
11192dcdda6SZachary Turner   fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
11292dcdda6SZachary Turner                          const DebugChecksumsSubsectionRef &Checksums,
11392dcdda6SZachary Turner                          const DebugInlineeLinesSubsectionRef &Lines);
11492dcdda6SZachary Turner 
11592dcdda6SZachary Turner   InlineeInfo InlineeLines;
11692dcdda6SZachary Turner };
11792dcdda6SZachary Turner }
1181b88f4f3SZachary Turner 
1191b88f4f3SZachary Turner void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) {
1201b88f4f3SZachary Turner   io.bitSetCase(Flags, "HasColumnInfo", LF_HaveColumns);
1211b88f4f3SZachary Turner   io.enumFallback<Hex16>(Flags);
1221b88f4f3SZachary Turner }
1231b88f4f3SZachary Turner 
1241b88f4f3SZachary Turner void ScalarEnumerationTraits<FileChecksumKind>::enumeration(
1251b88f4f3SZachary Turner     IO &io, FileChecksumKind &Kind) {
1261b88f4f3SZachary Turner   io.enumCase(Kind, "None", FileChecksumKind::None);
1271b88f4f3SZachary Turner   io.enumCase(Kind, "MD5", FileChecksumKind::MD5);
1281b88f4f3SZachary Turner   io.enumCase(Kind, "SHA1", FileChecksumKind::SHA1);
1291b88f4f3SZachary Turner   io.enumCase(Kind, "SHA256", FileChecksumKind::SHA256);
1301b88f4f3SZachary Turner }
1311b88f4f3SZachary Turner 
1321b88f4f3SZachary Turner void ScalarTraits<HexFormattedString>::output(const HexFormattedString &Value,
1331b88f4f3SZachary Turner                                               void *ctx, raw_ostream &Out) {
1341b88f4f3SZachary Turner   StringRef Bytes(reinterpret_cast<const char *>(Value.Bytes.data()),
1351b88f4f3SZachary Turner                   Value.Bytes.size());
1361b88f4f3SZachary Turner   Out << toHex(Bytes);
1371b88f4f3SZachary Turner }
1381b88f4f3SZachary Turner 
1391b88f4f3SZachary Turner StringRef ScalarTraits<HexFormattedString>::input(StringRef Scalar, void *ctxt,
1401b88f4f3SZachary Turner                                                   HexFormattedString &Value) {
1411b88f4f3SZachary Turner   std::string H = fromHex(Scalar);
1421b88f4f3SZachary Turner   Value.Bytes.assign(H.begin(), H.end());
1431b88f4f3SZachary Turner   return StringRef();
1441b88f4f3SZachary Turner }
1451b88f4f3SZachary Turner 
1461b88f4f3SZachary Turner void MappingTraits<SourceLineEntry>::mapping(IO &IO, SourceLineEntry &Obj) {
1471b88f4f3SZachary Turner   IO.mapRequired("Offset", Obj.Offset);
1481b88f4f3SZachary Turner   IO.mapRequired("LineStart", Obj.LineStart);
1491b88f4f3SZachary Turner   IO.mapRequired("IsStatement", Obj.IsStatement);
1501b88f4f3SZachary Turner   IO.mapRequired("EndDelta", Obj.EndDelta);
1511b88f4f3SZachary Turner }
1521b88f4f3SZachary Turner 
1531b88f4f3SZachary Turner void MappingTraits<SourceColumnEntry>::mapping(IO &IO, SourceColumnEntry &Obj) {
1541b88f4f3SZachary Turner   IO.mapRequired("StartColumn", Obj.StartColumn);
1551b88f4f3SZachary Turner   IO.mapRequired("EndColumn", Obj.EndColumn);
1561b88f4f3SZachary Turner }
1571b88f4f3SZachary Turner 
1581b88f4f3SZachary Turner void MappingTraits<SourceLineBlock>::mapping(IO &IO, SourceLineBlock &Obj) {
1591b88f4f3SZachary Turner   IO.mapRequired("FileName", Obj.FileName);
1601b88f4f3SZachary Turner   IO.mapRequired("Lines", Obj.Lines);
1611b88f4f3SZachary Turner   IO.mapRequired("Columns", Obj.Columns);
1621b88f4f3SZachary Turner }
1631b88f4f3SZachary Turner 
1641b88f4f3SZachary Turner void MappingTraits<SourceFileChecksumEntry>::mapping(
1651b88f4f3SZachary Turner     IO &IO, SourceFileChecksumEntry &Obj) {
1661b88f4f3SZachary Turner   IO.mapRequired("FileName", Obj.FileName);
1671b88f4f3SZachary Turner   IO.mapRequired("Kind", Obj.Kind);
1681b88f4f3SZachary Turner   IO.mapRequired("Checksum", Obj.ChecksumBytes);
1691b88f4f3SZachary Turner }
1701b88f4f3SZachary Turner 
1711b88f4f3SZachary Turner void MappingTraits<InlineeSite>::mapping(IO &IO, InlineeSite &Obj) {
1721b88f4f3SZachary Turner   IO.mapRequired("FileName", Obj.FileName);
1731b88f4f3SZachary Turner   IO.mapRequired("LineNum", Obj.SourceLineNum);
1741b88f4f3SZachary Turner   IO.mapRequired("Inlinee", Obj.Inlinee);
1751b88f4f3SZachary Turner   IO.mapOptional("ExtraFiles", Obj.ExtraFiles);
1761b88f4f3SZachary Turner }
1771b88f4f3SZachary Turner 
17892dcdda6SZachary Turner void YAMLChecksumsSubsection::map(IO &IO) {
17992dcdda6SZachary Turner   IO.mapTag("!FileChecksums", true);
18092dcdda6SZachary Turner   IO.mapRequired("Checksums", Checksums);
18192dcdda6SZachary Turner }
18292dcdda6SZachary Turner 
18392dcdda6SZachary Turner void YAMLLinesSubsection::map(IO &IO) {
18492dcdda6SZachary Turner   IO.mapTag("!Lines", true);
18592dcdda6SZachary Turner   IO.mapRequired("CodeSize", Lines.CodeSize);
18692dcdda6SZachary Turner 
18792dcdda6SZachary Turner   IO.mapRequired("Flags", Lines.Flags);
18892dcdda6SZachary Turner   IO.mapRequired("RelocOffset", Lines.RelocOffset);
18992dcdda6SZachary Turner   IO.mapRequired("RelocSegment", Lines.RelocSegment);
19092dcdda6SZachary Turner   IO.mapRequired("Blocks", Lines.Blocks);
19192dcdda6SZachary Turner }
19292dcdda6SZachary Turner 
19392dcdda6SZachary Turner void YAMLInlineeLinesSubsection::map(IO &IO) {
19492dcdda6SZachary Turner   IO.mapTag("!InlineeLines", true);
19592dcdda6SZachary Turner   IO.mapRequired("HasExtraFiles", InlineeLines.HasExtraFiles);
19692dcdda6SZachary Turner   IO.mapRequired("Sites", InlineeLines.Sites);
19792dcdda6SZachary Turner }
19892dcdda6SZachary Turner 
19992dcdda6SZachary Turner void MappingTraits<YAMLDebugSubsection>::mapping(
20092dcdda6SZachary Turner     IO &IO, YAMLDebugSubsection &Subsection) {
20192dcdda6SZachary Turner   if (!IO.outputting()) {
20292dcdda6SZachary Turner     if (IO.mapTag("!FileChecksums")) {
20392dcdda6SZachary Turner       auto SS = std::make_shared<YAMLChecksumsSubsection>();
20492dcdda6SZachary Turner       Subsection.Subsection = SS;
20592dcdda6SZachary Turner     } else if (IO.mapTag("!Lines")) {
20692dcdda6SZachary Turner       Subsection.Subsection = std::make_shared<YAMLLinesSubsection>();
20792dcdda6SZachary Turner     } else if (IO.mapTag("!InlineeLines")) {
20892dcdda6SZachary Turner       Subsection.Subsection = std::make_shared<YAMLInlineeLinesSubsection>();
20992dcdda6SZachary Turner     } else {
21092dcdda6SZachary Turner       llvm_unreachable("Unexpected subsection tag!");
21192dcdda6SZachary Turner     }
21292dcdda6SZachary Turner   }
21392dcdda6SZachary Turner   Subsection.Subsection->map(IO);
21492dcdda6SZachary Turner }
21592dcdda6SZachary Turner 
21692dcdda6SZachary Turner static Expected<const YAMLChecksumsSubsection &>
21792dcdda6SZachary Turner findChecksums(ArrayRef<YAMLDebugSubsection> Subsections) {
21892dcdda6SZachary Turner   for (const auto &SS : Subsections) {
21992dcdda6SZachary Turner     if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) {
22092dcdda6SZachary Turner       return static_cast<const YAMLChecksumsSubsection &>(*SS.Subsection);
22192dcdda6SZachary Turner     }
22292dcdda6SZachary Turner   }
22392dcdda6SZachary Turner   return make_error<CodeViewError>(cv_error_code::no_records);
22492dcdda6SZachary Turner }
22592dcdda6SZachary Turner 
22692dcdda6SZachary Turner std::unique_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection(
22792dcdda6SZachary Turner     DebugStringTableSubsection *UseStrings,
22892dcdda6SZachary Turner     DebugChecksumsSubsection *UseChecksums) const {
22992dcdda6SZachary Turner   assert(UseStrings && !UseChecksums);
23092dcdda6SZachary Turner   auto Result = llvm::make_unique<DebugChecksumsSubsection>(*UseStrings);
23192dcdda6SZachary Turner   for (const auto &CS : Checksums) {
23292dcdda6SZachary Turner     Result->addChecksum(CS.FileName, CS.Kind, CS.ChecksumBytes.Bytes);
23392dcdda6SZachary Turner   }
23492dcdda6SZachary Turner   return std::move(Result);
23592dcdda6SZachary Turner }
23692dcdda6SZachary Turner 
23792dcdda6SZachary Turner std::unique_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection(
23892dcdda6SZachary Turner     DebugStringTableSubsection *UseStrings,
23992dcdda6SZachary Turner     DebugChecksumsSubsection *UseChecksums) const {
24092dcdda6SZachary Turner   assert(UseStrings && UseChecksums);
24192dcdda6SZachary Turner   auto Result =
24292dcdda6SZachary Turner       llvm::make_unique<DebugLinesSubsection>(*UseChecksums, *UseStrings);
24392dcdda6SZachary Turner   Result->setCodeSize(Lines.CodeSize);
24492dcdda6SZachary Turner   Result->setRelocationAddress(Lines.RelocSegment, Lines.RelocOffset);
24592dcdda6SZachary Turner   Result->setFlags(Lines.Flags);
24692dcdda6SZachary Turner   for (const auto &LC : Lines.Blocks) {
24792dcdda6SZachary Turner     Result->createBlock(LC.FileName);
24892dcdda6SZachary Turner     if (Result->hasColumnInfo()) {
24992dcdda6SZachary Turner       for (const auto &Item : zip(LC.Lines, LC.Columns)) {
25092dcdda6SZachary Turner         auto &L = std::get<0>(Item);
25192dcdda6SZachary Turner         auto &C = std::get<1>(Item);
25292dcdda6SZachary Turner         uint32_t LE = L.LineStart + L.EndDelta;
25392dcdda6SZachary Turner         Result->addLineAndColumnInfo(L.Offset,
25492dcdda6SZachary Turner                                      LineInfo(L.LineStart, LE, L.IsStatement),
25592dcdda6SZachary Turner                                      C.StartColumn, C.EndColumn);
25692dcdda6SZachary Turner       }
25792dcdda6SZachary Turner     } else {
25892dcdda6SZachary Turner       for (const auto &L : LC.Lines) {
25992dcdda6SZachary Turner         uint32_t LE = L.LineStart + L.EndDelta;
26092dcdda6SZachary Turner         Result->addLineInfo(L.Offset, LineInfo(L.LineStart, LE, L.IsStatement));
26192dcdda6SZachary Turner       }
26292dcdda6SZachary Turner     }
26392dcdda6SZachary Turner   }
264*4bedb5fdSZachary Turner   return llvm::cast<DebugSubsection>(std::move(Result));
26592dcdda6SZachary Turner }
26692dcdda6SZachary Turner 
26792dcdda6SZachary Turner std::unique_ptr<DebugSubsection>
26892dcdda6SZachary Turner YAMLInlineeLinesSubsection::toCodeViewSubsection(
26992dcdda6SZachary Turner     DebugStringTableSubsection *UseStrings,
27092dcdda6SZachary Turner     DebugChecksumsSubsection *UseChecksums) const {
27192dcdda6SZachary Turner   assert(UseChecksums);
27292dcdda6SZachary Turner   auto Result = llvm::make_unique<DebugInlineeLinesSubsection>(
27392dcdda6SZachary Turner       *UseChecksums, InlineeLines.HasExtraFiles);
27492dcdda6SZachary Turner 
27592dcdda6SZachary Turner   for (const auto &Site : InlineeLines.Sites) {
27692dcdda6SZachary Turner     Result->addInlineSite(TypeIndex(Site.Inlinee), Site.FileName,
27792dcdda6SZachary Turner                           Site.SourceLineNum);
27892dcdda6SZachary Turner     if (!InlineeLines.HasExtraFiles)
27992dcdda6SZachary Turner       continue;
28092dcdda6SZachary Turner 
28192dcdda6SZachary Turner     for (auto EF : Site.ExtraFiles) {
28292dcdda6SZachary Turner       Result->addExtraFile(EF);
28392dcdda6SZachary Turner     }
28492dcdda6SZachary Turner   }
285*4bedb5fdSZachary Turner   return llvm::cast<DebugSubsection>(std::move(Result));
28692dcdda6SZachary Turner }
28792dcdda6SZachary Turner 
28892dcdda6SZachary Turner static Expected<SourceFileChecksumEntry>
28992dcdda6SZachary Turner convertOneChecksum(const DebugStringTableSubsectionRef &Strings,
29092dcdda6SZachary Turner                    const FileChecksumEntry &CS) {
29192dcdda6SZachary Turner   auto ExpectedString = Strings.getString(CS.FileNameOffset);
29292dcdda6SZachary Turner   if (!ExpectedString)
29392dcdda6SZachary Turner     return ExpectedString.takeError();
29492dcdda6SZachary Turner 
29592dcdda6SZachary Turner   SourceFileChecksumEntry Result;
29692dcdda6SZachary Turner   Result.ChecksumBytes.Bytes = CS.Checksum;
29792dcdda6SZachary Turner   Result.Kind = CS.Kind;
29892dcdda6SZachary Turner   Result.FileName = *ExpectedString;
29992dcdda6SZachary Turner   return Result;
30092dcdda6SZachary Turner }
30192dcdda6SZachary Turner 
30292dcdda6SZachary Turner static Expected<StringRef>
30392dcdda6SZachary Turner getFileName(const DebugStringTableSubsectionRef &Strings,
30492dcdda6SZachary Turner             const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) {
30592dcdda6SZachary Turner   auto Iter = Checksums.getArray().at(FileID);
30692dcdda6SZachary Turner   if (Iter == Checksums.getArray().end())
30792dcdda6SZachary Turner     return make_error<CodeViewError>(cv_error_code::no_records);
30892dcdda6SZachary Turner   uint32_t Offset = Iter->FileNameOffset;
30992dcdda6SZachary Turner   return Strings.getString(Offset);
31092dcdda6SZachary Turner }
31192dcdda6SZachary Turner 
31292dcdda6SZachary Turner Expected<std::shared_ptr<YAMLChecksumsSubsection>>
31392dcdda6SZachary Turner YAMLChecksumsSubsection::fromCodeViewSubsection(
31492dcdda6SZachary Turner     const DebugStringTableSubsectionRef &Strings,
31592dcdda6SZachary Turner     const DebugChecksumsSubsectionRef &FC) {
31692dcdda6SZachary Turner   auto Result = std::make_shared<YAMLChecksumsSubsection>();
31792dcdda6SZachary Turner 
31892dcdda6SZachary Turner   for (const auto &CS : FC) {
31992dcdda6SZachary Turner     auto ConvertedCS = convertOneChecksum(Strings, CS);
32092dcdda6SZachary Turner     if (!ConvertedCS)
32192dcdda6SZachary Turner       return ConvertedCS.takeError();
32292dcdda6SZachary Turner     Result->Checksums.push_back(*ConvertedCS);
32392dcdda6SZachary Turner   }
32492dcdda6SZachary Turner   return Result;
32592dcdda6SZachary Turner }
32692dcdda6SZachary Turner 
32792dcdda6SZachary Turner Expected<std::shared_ptr<YAMLLinesSubsection>>
32892dcdda6SZachary Turner YAMLLinesSubsection::fromCodeViewSubsection(
32992dcdda6SZachary Turner     const DebugStringTableSubsectionRef &Strings,
33092dcdda6SZachary Turner     const DebugChecksumsSubsectionRef &Checksums,
33192dcdda6SZachary Turner     const DebugLinesSubsectionRef &Lines) {
33292dcdda6SZachary Turner   auto Result = std::make_shared<YAMLLinesSubsection>();
33392dcdda6SZachary Turner   Result->Lines.CodeSize = Lines.header()->CodeSize;
33492dcdda6SZachary Turner   Result->Lines.RelocOffset = Lines.header()->RelocOffset;
33592dcdda6SZachary Turner   Result->Lines.RelocSegment = Lines.header()->RelocSegment;
33692dcdda6SZachary Turner   Result->Lines.Flags = static_cast<LineFlags>(uint16_t(Lines.header()->Flags));
33792dcdda6SZachary Turner   for (const auto &L : Lines) {
33892dcdda6SZachary Turner     SourceLineBlock Block;
33992dcdda6SZachary Turner     auto EF = getFileName(Strings, Checksums, L.NameIndex);
34092dcdda6SZachary Turner     if (!EF)
34192dcdda6SZachary Turner       return EF.takeError();
34292dcdda6SZachary Turner     Block.FileName = *EF;
34392dcdda6SZachary Turner     if (Lines.hasColumnInfo()) {
34492dcdda6SZachary Turner       for (const auto &C : L.Columns) {
34592dcdda6SZachary Turner         SourceColumnEntry SCE;
34692dcdda6SZachary Turner         SCE.EndColumn = C.EndColumn;
34792dcdda6SZachary Turner         SCE.StartColumn = C.StartColumn;
34892dcdda6SZachary Turner         Block.Columns.push_back(SCE);
34992dcdda6SZachary Turner       }
35092dcdda6SZachary Turner     }
35192dcdda6SZachary Turner     for (const auto &LN : L.LineNumbers) {
35292dcdda6SZachary Turner       SourceLineEntry SLE;
35392dcdda6SZachary Turner       LineInfo LI(LN.Flags);
35492dcdda6SZachary Turner       SLE.Offset = LN.Offset;
35592dcdda6SZachary Turner       SLE.LineStart = LI.getStartLine();
35692dcdda6SZachary Turner       SLE.EndDelta = LI.getLineDelta();
35792dcdda6SZachary Turner       SLE.IsStatement = LI.isStatement();
35892dcdda6SZachary Turner       Block.Lines.push_back(SLE);
35992dcdda6SZachary Turner     }
36092dcdda6SZachary Turner     Result->Lines.Blocks.push_back(Block);
36192dcdda6SZachary Turner   }
36292dcdda6SZachary Turner   return Result;
36392dcdda6SZachary Turner }
36492dcdda6SZachary Turner 
36592dcdda6SZachary Turner Expected<std::shared_ptr<YAMLInlineeLinesSubsection>>
36692dcdda6SZachary Turner YAMLInlineeLinesSubsection::fromCodeViewSubsection(
36792dcdda6SZachary Turner     const DebugStringTableSubsectionRef &Strings,
36892dcdda6SZachary Turner     const DebugChecksumsSubsectionRef &Checksums,
36992dcdda6SZachary Turner     const DebugInlineeLinesSubsectionRef &Lines) {
37092dcdda6SZachary Turner   auto Result = std::make_shared<YAMLInlineeLinesSubsection>();
37192dcdda6SZachary Turner 
37292dcdda6SZachary Turner   Result->InlineeLines.HasExtraFiles = Lines.hasExtraFiles();
37392dcdda6SZachary Turner   for (const auto &IL : Lines) {
37492dcdda6SZachary Turner     InlineeSite Site;
37592dcdda6SZachary Turner     auto ExpF = getFileName(Strings, Checksums, IL.Header->FileID);
37692dcdda6SZachary Turner     if (!ExpF)
37792dcdda6SZachary Turner       return ExpF.takeError();
37892dcdda6SZachary Turner     Site.FileName = *ExpF;
37992dcdda6SZachary Turner     Site.Inlinee = IL.Header->Inlinee.getIndex();
38092dcdda6SZachary Turner     Site.SourceLineNum = IL.Header->SourceLineNum;
38192dcdda6SZachary Turner     if (Lines.hasExtraFiles()) {
38292dcdda6SZachary Turner       for (const auto EF : IL.ExtraFiles) {
38392dcdda6SZachary Turner         auto ExpF2 = getFileName(Strings, Checksums, EF);
38492dcdda6SZachary Turner         if (!ExpF2)
38592dcdda6SZachary Turner           return ExpF2.takeError();
38692dcdda6SZachary Turner         Site.ExtraFiles.push_back(*ExpF2);
38792dcdda6SZachary Turner       }
38892dcdda6SZachary Turner     }
38992dcdda6SZachary Turner     Result->InlineeLines.Sites.push_back(Site);
39092dcdda6SZachary Turner   }
39192dcdda6SZachary Turner   return Result;
39292dcdda6SZachary Turner }
39392dcdda6SZachary Turner 
39492dcdda6SZachary Turner Expected<std::vector<std::unique_ptr<DebugSubsection>>>
39592dcdda6SZachary Turner llvm::CodeViewYAML::convertSubsectionList(
39692dcdda6SZachary Turner     ArrayRef<YAMLDebugSubsection> Subsections,
39792dcdda6SZachary Turner     DebugStringTableSubsection &Strings) {
39892dcdda6SZachary Turner   std::vector<std::unique_ptr<DebugSubsection>> Result;
39992dcdda6SZachary Turner   if (Subsections.empty())
40092dcdda6SZachary Turner     return Result;
40192dcdda6SZachary Turner 
40292dcdda6SZachary Turner   auto Checksums = findChecksums(Subsections);
40392dcdda6SZachary Turner   if (!Checksums)
40492dcdda6SZachary Turner     return Checksums.takeError();
40592dcdda6SZachary Turner   auto ChecksumsBase = Checksums->toCodeViewSubsection(&Strings, nullptr);
40692dcdda6SZachary Turner   DebugChecksumsSubsection &CS =
40792dcdda6SZachary Turner       llvm::cast<DebugChecksumsSubsection>(*ChecksumsBase);
40892dcdda6SZachary Turner   for (const auto &SS : Subsections) {
40992dcdda6SZachary Turner     // We've already converted the checksums subsection, don't do it
41092dcdda6SZachary Turner     // twice.
41192dcdda6SZachary Turner     std::unique_ptr<DebugSubsection> CVS;
41292dcdda6SZachary Turner     if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums)
41392dcdda6SZachary Turner       CVS = std::move(ChecksumsBase);
41492dcdda6SZachary Turner     else
41592dcdda6SZachary Turner       CVS = SS.Subsection->toCodeViewSubsection(&Strings, &CS);
41692dcdda6SZachary Turner     Result.push_back(std::move(CVS));
41792dcdda6SZachary Turner   }
41892dcdda6SZachary Turner   return std::move(Result);
41992dcdda6SZachary Turner }
42092dcdda6SZachary Turner 
42192dcdda6SZachary Turner namespace {
42292dcdda6SZachary Turner struct SubsectionConversionVisitor : public DebugSubsectionVisitor {
42392dcdda6SZachary Turner   explicit SubsectionConversionVisitor(
42492dcdda6SZachary Turner       const DebugStringTableSubsectionRef &Strings,
42592dcdda6SZachary Turner       const DebugChecksumsSubsectionRef &Checksums)
42692dcdda6SZachary Turner       : Strings(Strings), Checksums(Checksums) {}
42792dcdda6SZachary Turner 
42892dcdda6SZachary Turner   Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override;
42992dcdda6SZachary Turner   Error visitLines(DebugLinesSubsectionRef &Lines) override;
43092dcdda6SZachary Turner   Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums) override;
43192dcdda6SZachary Turner   Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees) override;
43292dcdda6SZachary Turner 
43392dcdda6SZachary Turner   YAMLDebugSubsection Subsection;
43492dcdda6SZachary Turner 
43592dcdda6SZachary Turner private:
43692dcdda6SZachary Turner   const DebugStringTableSubsectionRef &Strings;
43792dcdda6SZachary Turner   const DebugChecksumsSubsectionRef &Checksums;
43892dcdda6SZachary Turner };
43992dcdda6SZachary Turner 
44092dcdda6SZachary Turner Error SubsectionConversionVisitor::visitUnknown(
44192dcdda6SZachary Turner     DebugUnknownSubsectionRef &Unknown) {
44292dcdda6SZachary Turner   return make_error<CodeViewError>(cv_error_code::operation_unsupported);
44392dcdda6SZachary Turner }
44492dcdda6SZachary Turner 
44592dcdda6SZachary Turner Error SubsectionConversionVisitor::visitLines(DebugLinesSubsectionRef &Lines) {
44692dcdda6SZachary Turner   auto Result =
44792dcdda6SZachary Turner       YAMLLinesSubsection::fromCodeViewSubsection(Strings, Checksums, Lines);
44892dcdda6SZachary Turner   if (!Result)
44992dcdda6SZachary Turner     return Result.takeError();
45092dcdda6SZachary Turner   Subsection.Subsection = *Result;
45192dcdda6SZachary Turner   return Error::success();
45292dcdda6SZachary Turner }
45392dcdda6SZachary Turner 
45492dcdda6SZachary Turner Error SubsectionConversionVisitor::visitFileChecksums(
45592dcdda6SZachary Turner     DebugChecksumsSubsectionRef &Checksums) {
45692dcdda6SZachary Turner   auto Result =
45792dcdda6SZachary Turner       YAMLChecksumsSubsection::fromCodeViewSubsection(Strings, Checksums);
45892dcdda6SZachary Turner   if (!Result)
45992dcdda6SZachary Turner     return Result.takeError();
46092dcdda6SZachary Turner   Subsection.Subsection = *Result;
46192dcdda6SZachary Turner   return Error::success();
46292dcdda6SZachary Turner }
46392dcdda6SZachary Turner 
46492dcdda6SZachary Turner Error SubsectionConversionVisitor::visitInlineeLines(
46592dcdda6SZachary Turner     DebugInlineeLinesSubsectionRef &Inlinees) {
46692dcdda6SZachary Turner   auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection(
46792dcdda6SZachary Turner       Strings, Checksums, Inlinees);
46892dcdda6SZachary Turner   if (!Result)
46992dcdda6SZachary Turner     return Result.takeError();
47092dcdda6SZachary Turner   Subsection.Subsection = *Result;
47192dcdda6SZachary Turner   return Error::success();
47292dcdda6SZachary Turner }
47392dcdda6SZachary Turner }
47492dcdda6SZachary Turner 
47592dcdda6SZachary Turner Expected<YAMLDebugSubsection> YAMLDebugSubsection::fromCodeViewSubection(
47692dcdda6SZachary Turner     const DebugStringTableSubsectionRef &Strings,
47792dcdda6SZachary Turner     const DebugChecksumsSubsectionRef &Checksums,
47892dcdda6SZachary Turner     const DebugSubsectionRecord &SS) {
47992dcdda6SZachary Turner   SubsectionConversionVisitor V(Strings, Checksums);
48092dcdda6SZachary Turner   if (auto EC = visitDebugSubsection(SS, V))
48192dcdda6SZachary Turner     return std::move(EC);
48292dcdda6SZachary Turner 
48392dcdda6SZachary Turner   return V.Subsection;
4841b88f4f3SZachary Turner }
485