brintos

brintos / llvm-project-archived public Read only

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