brintos

brintos / llvm-project-archived public Read only

0
0
Text · 47.9 KiB · ec5e080 Raw
1297 lines · cpp
1//===- DWARFEmitter - Convert YAML to DWARF binary data -------------------===//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/// \file10/// The DWARF component of yaml2obj. Provided as library code for tests.11///12//===----------------------------------------------------------------------===//13 14#include "llvm/ObjectYAML/DWARFEmitter.h"15#include "llvm/ADT/ArrayRef.h"16#include "llvm/ADT/StringMap.h"17#include "llvm/ADT/StringRef.h"18#include "llvm/ADT/StringSwitch.h"19#include "llvm/BinaryFormat/Dwarf.h"20#include "llvm/ObjectYAML/DWARFYAML.h"21#include "llvm/Support/Errc.h"22#include "llvm/Support/Error.h"23#include "llvm/Support/LEB128.h"24#include "llvm/Support/MathExtras.h"25#include "llvm/Support/MemoryBuffer.h"26#include "llvm/Support/SourceMgr.h"27#include "llvm/Support/SwapByteOrder.h"28#include "llvm/Support/YAMLTraits.h"29#include "llvm/Support/raw_ostream.h"30#include "llvm/TargetParser/Host.h"31#include <cassert>32#include <cstddef>33#include <cstdint>34#include <memory>35#include <optional>36#include <string>37#include <vector>38 39using namespace llvm;40 41template <typename T>42static void writeInteger(T Integer, raw_ostream &OS, bool IsLittleEndian) {43  if (IsLittleEndian != sys::IsLittleEndianHost)44    sys::swapByteOrder(Integer);45  OS.write(reinterpret_cast<char *>(&Integer), sizeof(T));46}47 48static Error writeVariableSizedInteger(uint64_t Integer, size_t Size,49                                       raw_ostream &OS, bool IsLittleEndian) {50  if (8 == Size)51    writeInteger((uint64_t)Integer, OS, IsLittleEndian);52  else if (4 == Size)53    writeInteger((uint32_t)Integer, OS, IsLittleEndian);54  else if (2 == Size)55    writeInteger((uint16_t)Integer, OS, IsLittleEndian);56  else if (1 == Size)57    writeInteger((uint8_t)Integer, OS, IsLittleEndian);58  else59    return createStringError(errc::not_supported,60                             "invalid integer write size: %zu", Size);61 62  return Error::success();63}64 65static void ZeroFillBytes(raw_ostream &OS, size_t Size) {66  std::vector<uint8_t> FillData(Size, 0);67  OS.write(reinterpret_cast<char *>(FillData.data()), Size);68}69 70static void writeInitialLength(const dwarf::DwarfFormat Format,71                               const uint64_t Length, raw_ostream &OS,72                               bool IsLittleEndian) {73  bool IsDWARF64 = Format == dwarf::DWARF64;74  if (IsDWARF64)75    cantFail(writeVariableSizedInteger(dwarf::DW_LENGTH_DWARF64, 4, OS,76                                       IsLittleEndian));77  cantFail(78      writeVariableSizedInteger(Length, IsDWARF64 ? 8 : 4, OS, IsLittleEndian));79}80 81static void writeDWARFOffset(uint64_t Offset, dwarf::DwarfFormat Format,82                             raw_ostream &OS, bool IsLittleEndian) {83  cantFail(writeVariableSizedInteger(Offset, Format == dwarf::DWARF64 ? 8 : 4,84                                     OS, IsLittleEndian));85}86 87Error DWARFYAML::emitDebugStr(raw_ostream &OS, const DWARFYAML::Data &DI) {88  for (StringRef Str : *DI.DebugStrings) {89    OS.write(Str.data(), Str.size());90    OS.write('\0');91  }92 93  return Error::success();94}95 96StringRef DWARFYAML::Data::getAbbrevTableContentByIndex(uint64_t Index) const {97  assert(Index < DebugAbbrev.size() &&98         "Index should be less than the size of DebugAbbrev array");99  auto [It, Inserted] = AbbrevTableContents.try_emplace(Index);100  if (!Inserted)101    return It->second;102 103  raw_string_ostream OS(It->second);104 105  uint64_t AbbrevCode = 0;106  for (const DWARFYAML::Abbrev &AbbrevDecl : DebugAbbrev[Index].Table) {107    AbbrevCode = AbbrevDecl.Code ? (uint64_t)*AbbrevDecl.Code : AbbrevCode + 1;108    encodeULEB128(AbbrevCode, OS);109    encodeULEB128(AbbrevDecl.Tag, OS);110    OS.write(AbbrevDecl.Children);111    for (const auto &Attr : AbbrevDecl.Attributes) {112      encodeULEB128(Attr.Attribute, OS);113      encodeULEB128(Attr.Form, OS);114      if (Attr.Form == dwarf::DW_FORM_implicit_const)115        encodeSLEB128(Attr.Value, OS);116    }117    encodeULEB128(0, OS);118    encodeULEB128(0, OS);119  }120 121  // The abbreviations for a given compilation unit end with an entry122  // consisting of a 0 byte for the abbreviation code.123  OS.write_zeros(1);124 125  return It->second;126}127 128Error DWARFYAML::emitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) {129  for (uint64_t I = 0; I < DI.DebugAbbrev.size(); ++I) {130    StringRef AbbrevTableContent = DI.getAbbrevTableContentByIndex(I);131    OS.write(AbbrevTableContent.data(), AbbrevTableContent.size());132  }133 134  return Error::success();135}136 137Error DWARFYAML::emitDebugAranges(raw_ostream &OS, const DWARFYAML::Data &DI) {138  assert(DI.DebugAranges && "unexpected emitDebugAranges() call");139  for (const auto &Range : *DI.DebugAranges) {140    uint8_t AddrSize;141    if (Range.AddrSize)142      AddrSize = *Range.AddrSize;143    else144      AddrSize = DI.Is64BitAddrSize ? 8 : 4;145 146    uint64_t Length = 4; // sizeof(version) 2 + sizeof(address_size) 1 +147                         // sizeof(segment_selector_size) 1148    Length +=149        Range.Format == dwarf::DWARF64 ? 8 : 4; // sizeof(debug_info_offset)150 151    const uint64_t HeaderLength =152        Length + (Range.Format == dwarf::DWARF64153                      ? 12154                      : 4); // sizeof(unit_header) = 12 (DWARF64) or 4 (DWARF32)155    const uint64_t PaddedHeaderLength = alignTo(HeaderLength, AddrSize * 2);156 157    if (Range.Length) {158      Length = *Range.Length;159    } else {160      Length += PaddedHeaderLength - HeaderLength;161      Length += AddrSize * 2 * (Range.Descriptors.size() + 1);162    }163 164    writeInitialLength(Range.Format, Length, OS, DI.IsLittleEndian);165    writeInteger((uint16_t)Range.Version, OS, DI.IsLittleEndian);166    writeDWARFOffset(Range.CuOffset, Range.Format, OS, DI.IsLittleEndian);167    writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);168    writeInteger((uint8_t)Range.SegSize, OS, DI.IsLittleEndian);169    ZeroFillBytes(OS, PaddedHeaderLength - HeaderLength);170 171    for (const auto &Descriptor : Range.Descriptors) {172      if (Error Err = writeVariableSizedInteger(Descriptor.Address, AddrSize,173                                                OS, DI.IsLittleEndian))174        return createStringError(errc::not_supported,175                                 "unable to write debug_aranges address: %s",176                                 toString(std::move(Err)).c_str());177      cantFail(writeVariableSizedInteger(Descriptor.Length, AddrSize, OS,178                                         DI.IsLittleEndian));179    }180    ZeroFillBytes(OS, AddrSize * 2);181  }182 183  return Error::success();184}185 186Error DWARFYAML::emitDebugRanges(raw_ostream &OS, const DWARFYAML::Data &DI) {187  const size_t RangesOffset = OS.tell();188  uint64_t EntryIndex = 0;189  for (const auto &DebugRanges : *DI.DebugRanges) {190    const size_t CurrOffset = OS.tell() - RangesOffset;191    if (DebugRanges.Offset && (uint64_t)*DebugRanges.Offset < CurrOffset)192      return createStringError(errc::invalid_argument,193                               "'Offset' for 'debug_ranges' with index " +194                                   Twine(EntryIndex) +195                                   " must be greater than or equal to the "196                                   "number of bytes written already (0x" +197                                   Twine::utohexstr(CurrOffset) + ")");198    if (DebugRanges.Offset)199      ZeroFillBytes(OS, *DebugRanges.Offset - CurrOffset);200 201    uint8_t AddrSize;202    if (DebugRanges.AddrSize)203      AddrSize = *DebugRanges.AddrSize;204    else205      AddrSize = DI.Is64BitAddrSize ? 8 : 4;206    for (const auto &Entry : DebugRanges.Entries) {207      if (Error Err = writeVariableSizedInteger(Entry.LowOffset, AddrSize, OS,208                                                DI.IsLittleEndian))209        return createStringError(210            errc::not_supported,211            "unable to write debug_ranges address offset: %s",212            toString(std::move(Err)).c_str());213      cantFail(writeVariableSizedInteger(Entry.HighOffset, AddrSize, OS,214                                         DI.IsLittleEndian));215    }216    ZeroFillBytes(OS, AddrSize * 2);217    ++EntryIndex;218  }219 220  return Error::success();221}222 223static Error emitPubSection(raw_ostream &OS, const DWARFYAML::PubSection &Sect,224                            bool IsLittleEndian, bool IsGNUPubSec = false) {225  writeInitialLength(Sect.Format, Sect.Length, OS, IsLittleEndian);226  writeInteger((uint16_t)Sect.Version, OS, IsLittleEndian);227  writeInteger((uint32_t)Sect.UnitOffset, OS, IsLittleEndian);228  writeInteger((uint32_t)Sect.UnitSize, OS, IsLittleEndian);229  for (const auto &Entry : Sect.Entries) {230    writeInteger((uint32_t)Entry.DieOffset, OS, IsLittleEndian);231    if (IsGNUPubSec)232      writeInteger((uint8_t)Entry.Descriptor, OS, IsLittleEndian);233    OS.write(Entry.Name.data(), Entry.Name.size());234    OS.write('\0');235  }236  return Error::success();237}238 239Error DWARFYAML::emitDebugPubnames(raw_ostream &OS, const Data &DI) {240  assert(DI.PubNames && "unexpected emitDebugPubnames() call");241  return emitPubSection(OS, *DI.PubNames, DI.IsLittleEndian);242}243 244Error DWARFYAML::emitDebugPubtypes(raw_ostream &OS, const Data &DI) {245  assert(DI.PubTypes && "unexpected emitDebugPubtypes() call");246  return emitPubSection(OS, *DI.PubTypes, DI.IsLittleEndian);247}248 249Error DWARFYAML::emitDebugGNUPubnames(raw_ostream &OS, const Data &DI) {250  assert(DI.GNUPubNames && "unexpected emitDebugGNUPubnames() call");251  return emitPubSection(OS, *DI.GNUPubNames, DI.IsLittleEndian,252                        /*IsGNUStyle=*/true);253}254 255Error DWARFYAML::emitDebugGNUPubtypes(raw_ostream &OS, const Data &DI) {256  assert(DI.GNUPubTypes && "unexpected emitDebugGNUPubtypes() call");257  return emitPubSection(OS, *DI.GNUPubTypes, DI.IsLittleEndian,258                        /*IsGNUStyle=*/true);259}260 261static Expected<uint64_t> writeDIE(const DWARFYAML::Data &DI, uint64_t CUIndex,262                                   uint64_t AbbrevTableID,263                                   const dwarf::FormParams &Params,264                                   const DWARFYAML::Entry &Entry,265                                   raw_ostream &OS, bool IsLittleEndian) {266  uint64_t EntryBegin = OS.tell();267  encodeULEB128(Entry.AbbrCode, OS);268  uint32_t AbbrCode = Entry.AbbrCode;269  if (AbbrCode == 0 || Entry.Values.empty())270    return OS.tell() - EntryBegin;271 272  Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =273      DI.getAbbrevTableInfoByID(AbbrevTableID);274  if (!AbbrevTableInfoOrErr)275    return createStringError(errc::invalid_argument,276                             toString(AbbrevTableInfoOrErr.takeError()) +277                                 " for compilation unit with index " +278                                 utostr(CUIndex));279 280  ArrayRef<DWARFYAML::Abbrev> AbbrevDecls(281      DI.DebugAbbrev[AbbrevTableInfoOrErr->Index].Table);282 283  if (AbbrCode > AbbrevDecls.size())284    return createStringError(285        errc::invalid_argument,286        "abbrev code must be less than or equal to the number of "287        "entries in abbreviation table");288  const DWARFYAML::Abbrev &Abbrev = AbbrevDecls[AbbrCode - 1];289  auto FormVal = Entry.Values.begin();290  auto AbbrForm = Abbrev.Attributes.begin();291  for (; FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end();292       ++FormVal, ++AbbrForm) {293    dwarf::Form Form = AbbrForm->Form;294    bool Indirect;295    do {296      Indirect = false;297      switch (Form) {298      case dwarf::DW_FORM_addr:299        // TODO: Test this error.300        if (Error Err = writeVariableSizedInteger(301                FormVal->Value, Params.AddrSize, OS, IsLittleEndian))302          return std::move(Err);303        break;304      case dwarf::DW_FORM_ref_addr:305        // TODO: Test this error.306        if (Error Err = writeVariableSizedInteger(FormVal->Value,307                                                  Params.getRefAddrByteSize(),308                                                  OS, IsLittleEndian))309          return std::move(Err);310        break;311      case dwarf::DW_FORM_exprloc:312      case dwarf::DW_FORM_block:313        encodeULEB128(FormVal->BlockData.size(), OS);314        OS.write((const char *)FormVal->BlockData.data(),315                 FormVal->BlockData.size());316        break;317      case dwarf::DW_FORM_block1: {318        writeInteger((uint8_t)FormVal->BlockData.size(), OS, IsLittleEndian);319        OS.write((const char *)FormVal->BlockData.data(),320                 FormVal->BlockData.size());321        break;322      }323      case dwarf::DW_FORM_block2: {324        writeInteger((uint16_t)FormVal->BlockData.size(), OS, IsLittleEndian);325        OS.write((const char *)FormVal->BlockData.data(),326                 FormVal->BlockData.size());327        break;328      }329      case dwarf::DW_FORM_block4: {330        writeInteger((uint32_t)FormVal->BlockData.size(), OS, IsLittleEndian);331        OS.write((const char *)FormVal->BlockData.data(),332                 FormVal->BlockData.size());333        break;334      }335      case dwarf::DW_FORM_strx:336      case dwarf::DW_FORM_addrx:337      case dwarf::DW_FORM_rnglistx:338      case dwarf::DW_FORM_loclistx:339      case dwarf::DW_FORM_udata:340      case dwarf::DW_FORM_ref_udata:341      case dwarf::DW_FORM_GNU_addr_index:342      case dwarf::DW_FORM_GNU_str_index:343        encodeULEB128(FormVal->Value, OS);344        break;345      case dwarf::DW_FORM_data1:346      case dwarf::DW_FORM_ref1:347      case dwarf::DW_FORM_flag:348      case dwarf::DW_FORM_strx1:349      case dwarf::DW_FORM_addrx1:350        writeInteger((uint8_t)FormVal->Value, OS, IsLittleEndian);351        break;352      case dwarf::DW_FORM_data2:353      case dwarf::DW_FORM_ref2:354      case dwarf::DW_FORM_strx2:355      case dwarf::DW_FORM_addrx2:356        writeInteger((uint16_t)FormVal->Value, OS, IsLittleEndian);357        break;358      case dwarf::DW_FORM_data4:359      case dwarf::DW_FORM_ref4:360      case dwarf::DW_FORM_ref_sup4:361      case dwarf::DW_FORM_strx4:362      case dwarf::DW_FORM_addrx4:363        writeInteger((uint32_t)FormVal->Value, OS, IsLittleEndian);364        break;365      case dwarf::DW_FORM_data8:366      case dwarf::DW_FORM_ref8:367      case dwarf::DW_FORM_ref_sup8:368      case dwarf::DW_FORM_ref_sig8:369        writeInteger((uint64_t)FormVal->Value, OS, IsLittleEndian);370        break;371      case dwarf::DW_FORM_sdata:372        encodeSLEB128(FormVal->Value, OS);373        break;374      case dwarf::DW_FORM_string:375        OS.write(FormVal->CStr.data(), FormVal->CStr.size());376        OS.write('\0');377        break;378      case dwarf::DW_FORM_indirect:379        encodeULEB128(FormVal->Value, OS);380        Indirect = true;381        Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value);382        ++FormVal;383        break;384      case dwarf::DW_FORM_strp:385      case dwarf::DW_FORM_sec_offset:386      case dwarf::DW_FORM_GNU_ref_alt:387      case dwarf::DW_FORM_GNU_strp_alt:388      case dwarf::DW_FORM_line_strp:389      case dwarf::DW_FORM_strp_sup:390        cantFail(writeVariableSizedInteger(FormVal->Value,391                                           Params.getDwarfOffsetByteSize(), OS,392                                           IsLittleEndian));393        break;394      default:395        break;396      }397    } while (Indirect);398  }399 400  return OS.tell() - EntryBegin;401}402 403Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {404  for (uint64_t I = 0; I < DI.Units.size(); ++I) {405    const DWARFYAML::Unit &Unit = DI.Units[I];406    uint8_t AddrSize;407    if (Unit.AddrSize)408      AddrSize = *Unit.AddrSize;409    else410      AddrSize = DI.Is64BitAddrSize ? 8 : 4;411    dwarf::FormParams Params = {Unit.Version, AddrSize, Unit.Format};412    uint64_t Length = 3; // sizeof(version) + sizeof(address_size)413    Length += Params.getDwarfOffsetByteSize(); // sizeof(debug_abbrev_offset)414    if (Unit.Version >= 5) {415      ++Length; // sizeof(unit_type)416      switch (Unit.Type) {417      case dwarf::DW_UT_compile:418      case dwarf::DW_UT_partial:419      default:420        break;421      case dwarf::DW_UT_type:422      case dwarf::DW_UT_split_type:423        // sizeof(type_signature) + sizeof(type_offset)424        Length += 8 + Params.getDwarfOffsetByteSize();425        break;426      case dwarf::DW_UT_skeleton:427      case dwarf::DW_UT_split_compile:428        Length += 8; // sizeof(dwo_id)429      }430    }431 432    // Since the length of the current compilation unit is undetermined yet, we433    // firstly write the content of the compilation unit to a buffer to434    // calculate it and then serialize the buffer content to the actual output435    // stream.436    std::string EntryBuffer;437    raw_string_ostream EntryBufferOS(EntryBuffer);438 439    uint64_t AbbrevTableID = Unit.AbbrevTableID.value_or(I);440    for (const DWARFYAML::Entry &Entry : Unit.Entries) {441      if (Expected<uint64_t> EntryLength =442              writeDIE(DI, I, AbbrevTableID, Params, Entry, EntryBufferOS,443                       DI.IsLittleEndian))444        Length += *EntryLength;445      else446        return EntryLength.takeError();447    }448 449    // If the length is specified in the YAML description, we use it instead of450    // the actual length.451    if (Unit.Length)452      Length = *Unit.Length;453 454    writeInitialLength(Unit.Format, Length, OS, DI.IsLittleEndian);455    writeInteger((uint16_t)Unit.Version, OS, DI.IsLittleEndian);456 457    uint64_t AbbrevTableOffset = 0;458    if (Unit.AbbrOffset) {459      AbbrevTableOffset = *Unit.AbbrOffset;460    } else {461      if (Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =462              DI.getAbbrevTableInfoByID(AbbrevTableID)) {463        AbbrevTableOffset = AbbrevTableInfoOrErr->Offset;464      } else {465        // The current compilation unit may not have DIEs and it will not be466        // able to find the associated abbrev table. We consume the error and467        // assign 0 to the debug_abbrev_offset in such circumstances.468        consumeError(AbbrevTableInfoOrErr.takeError());469      }470    }471 472    if (Unit.Version >= 5) {473      writeInteger((uint8_t)Unit.Type, OS, DI.IsLittleEndian);474      writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);475      writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);476      switch (Unit.Type) {477      case dwarf::DW_UT_compile:478      case dwarf::DW_UT_partial:479      default:480        break;481      case dwarf::DW_UT_type:482      case dwarf::DW_UT_split_type:483        writeInteger(Unit.TypeSignatureOrDwoID, OS, DI.IsLittleEndian);484        writeDWARFOffset(Unit.TypeOffset, Unit.Format, OS, DI.IsLittleEndian);485        break;486      case dwarf::DW_UT_skeleton:487      case dwarf::DW_UT_split_compile:488        writeInteger(Unit.TypeSignatureOrDwoID, OS, DI.IsLittleEndian);489        break;490      }491    } else {492      writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);493      writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);494    }495 496    OS.write(EntryBuffer.data(), EntryBuffer.size());497  }498 499  return Error::success();500}501 502static void emitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) {503  OS.write(File.Name.data(), File.Name.size());504  OS.write('\0');505  encodeULEB128(File.DirIdx, OS);506  encodeULEB128(File.ModTime, OS);507  encodeULEB128(File.Length, OS);508}509 510static void writeExtendedOpcode(const DWARFYAML::LineTableOpcode &Op,511                                uint8_t AddrSize, bool IsLittleEndian,512                                raw_ostream &OS) {513  // The first byte of extended opcodes is a zero byte. The next bytes are an514  // ULEB128 integer giving the number of bytes in the instruction itself (does515  // not include the first zero byte or the size). We serialize the instruction516  // itself into the OpBuffer and then write the size of the buffer and the517  // buffer to the real output stream.518  std::string OpBuffer;519  raw_string_ostream OpBufferOS(OpBuffer);520  writeInteger((uint8_t)Op.SubOpcode, OpBufferOS, IsLittleEndian);521  switch (Op.SubOpcode) {522  case dwarf::DW_LNE_set_address:523    cantFail(writeVariableSizedInteger(Op.Data, AddrSize, OpBufferOS,524                                       IsLittleEndian));525    break;526  case dwarf::DW_LNE_define_file:527    emitFileEntry(OpBufferOS, Op.FileEntry);528    break;529  case dwarf::DW_LNE_set_discriminator:530    encodeULEB128(Op.Data, OpBufferOS);531    break;532  case dwarf::DW_LNE_end_sequence:533    break;534  default:535    for (auto OpByte : Op.UnknownOpcodeData)536      writeInteger((uint8_t)OpByte, OpBufferOS, IsLittleEndian);537  }538  uint64_t ExtLen = Op.ExtLen.value_or(OpBuffer.size());539  encodeULEB128(ExtLen, OS);540  OS.write(OpBuffer.data(), OpBuffer.size());541}542 543static void writeLineTableOpcode(const DWARFYAML::LineTableOpcode &Op,544                                 uint8_t OpcodeBase, uint8_t AddrSize,545                                 raw_ostream &OS, bool IsLittleEndian) {546  writeInteger((uint8_t)Op.Opcode, OS, IsLittleEndian);547  if (Op.Opcode == 0) {548    writeExtendedOpcode(Op, AddrSize, IsLittleEndian, OS);549  } else if (Op.Opcode < OpcodeBase) {550    switch (Op.Opcode) {551    case dwarf::DW_LNS_copy:552    case dwarf::DW_LNS_negate_stmt:553    case dwarf::DW_LNS_set_basic_block:554    case dwarf::DW_LNS_const_add_pc:555    case dwarf::DW_LNS_set_prologue_end:556    case dwarf::DW_LNS_set_epilogue_begin:557      break;558 559    case dwarf::DW_LNS_advance_pc:560    case dwarf::DW_LNS_set_file:561    case dwarf::DW_LNS_set_column:562    case dwarf::DW_LNS_set_isa:563      encodeULEB128(Op.Data, OS);564      break;565 566    case dwarf::DW_LNS_advance_line:567      encodeSLEB128(Op.SData, OS);568      break;569 570    case dwarf::DW_LNS_fixed_advance_pc:571      writeInteger((uint16_t)Op.Data, OS, IsLittleEndian);572      break;573 574    default:575      for (auto OpData : Op.StandardOpcodeData) {576        encodeULEB128(OpData, OS);577      }578    }579  }580}581 582static std::vector<uint8_t>583getStandardOpcodeLengths(uint16_t Version, std::optional<uint8_t> OpcodeBase) {584  // If the opcode_base field isn't specified, we returns the585  // standard_opcode_lengths array according to the version by default.586  std::vector<uint8_t> StandardOpcodeLengths{0, 1, 1, 1, 1, 0,587                                             0, 0, 1, 0, 0, 1};588  if (Version == 2) {589    // DWARF v2 uses the same first 9 standard opcodes as v3-5.590    StandardOpcodeLengths.resize(9);591  } else if (OpcodeBase) {592    StandardOpcodeLengths.resize(*OpcodeBase > 0 ? *OpcodeBase - 1 : 0, 0);593  }594  return StandardOpcodeLengths;595}596 597Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) {598  for (const DWARFYAML::LineTable &LineTable : DI.DebugLines) {599    // Buffer holds the bytes following the header_length (or prologue_length in600    // DWARFv2) field to the end of the line number program itself.601    std::string Buffer;602    raw_string_ostream BufferOS(Buffer);603 604    writeInteger(LineTable.MinInstLength, BufferOS, DI.IsLittleEndian);605    // TODO: Add support for emitting DWARFv5 line table.606    if (LineTable.Version >= 4)607      writeInteger(LineTable.MaxOpsPerInst, BufferOS, DI.IsLittleEndian);608    writeInteger(LineTable.DefaultIsStmt, BufferOS, DI.IsLittleEndian);609    writeInteger(LineTable.LineBase, BufferOS, DI.IsLittleEndian);610    writeInteger(LineTable.LineRange, BufferOS, DI.IsLittleEndian);611 612    std::vector<uint8_t> StandardOpcodeLengths =613        LineTable.StandardOpcodeLengths.value_or(614            getStandardOpcodeLengths(LineTable.Version, LineTable.OpcodeBase));615    uint8_t OpcodeBase = LineTable.OpcodeBase616                             ? *LineTable.OpcodeBase617                             : StandardOpcodeLengths.size() + 1;618    writeInteger(OpcodeBase, BufferOS, DI.IsLittleEndian);619    for (uint8_t OpcodeLength : StandardOpcodeLengths)620      writeInteger(OpcodeLength, BufferOS, DI.IsLittleEndian);621 622    for (StringRef IncludeDir : LineTable.IncludeDirs) {623      BufferOS.write(IncludeDir.data(), IncludeDir.size());624      BufferOS.write('\0');625    }626    BufferOS.write('\0');627 628    for (const DWARFYAML::File &File : LineTable.Files)629      emitFileEntry(BufferOS, File);630    BufferOS.write('\0');631 632    uint64_t HeaderLength =633        LineTable.PrologueLength ? *LineTable.PrologueLength : Buffer.size();634 635    for (const DWARFYAML::LineTableOpcode &Op : LineTable.Opcodes)636      writeLineTableOpcode(Op, OpcodeBase, DI.Is64BitAddrSize ? 8 : 4, BufferOS,637                           DI.IsLittleEndian);638 639    uint64_t Length;640    if (LineTable.Length) {641      Length = *LineTable.Length;642    } else {643      Length = 2; // sizeof(version)644      Length +=645          (LineTable.Format == dwarf::DWARF64 ? 8 : 4); // sizeof(header_length)646      Length += Buffer.size();647    }648 649    writeInitialLength(LineTable.Format, Length, OS, DI.IsLittleEndian);650    writeInteger(LineTable.Version, OS, DI.IsLittleEndian);651    writeDWARFOffset(HeaderLength, LineTable.Format, OS, DI.IsLittleEndian);652    OS.write(Buffer.data(), Buffer.size());653  }654 655  return Error::success();656}657 658Error DWARFYAML::emitDebugAddr(raw_ostream &OS, const Data &DI) {659  for (const AddrTableEntry &TableEntry : *DI.DebugAddr) {660    uint8_t AddrSize;661    if (TableEntry.AddrSize)662      AddrSize = *TableEntry.AddrSize;663    else664      AddrSize = DI.Is64BitAddrSize ? 8 : 4;665 666    uint64_t Length;667    if (TableEntry.Length)668      Length = (uint64_t)*TableEntry.Length;669    else670      // 2 (version) + 1 (address_size) + 1 (segment_selector_size) = 4671      Length = 4 + (AddrSize + TableEntry.SegSelectorSize) *672                       TableEntry.SegAddrPairs.size();673 674    writeInitialLength(TableEntry.Format, Length, OS, DI.IsLittleEndian);675    writeInteger((uint16_t)TableEntry.Version, OS, DI.IsLittleEndian);676    writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);677    writeInteger((uint8_t)TableEntry.SegSelectorSize, OS, DI.IsLittleEndian);678 679    for (const SegAddrPair &Pair : TableEntry.SegAddrPairs) {680      if (TableEntry.SegSelectorSize != yaml::Hex8{0})681        if (Error Err = writeVariableSizedInteger(Pair.Segment,682                                                  TableEntry.SegSelectorSize,683                                                  OS, DI.IsLittleEndian))684          return createStringError(errc::not_supported,685                                   "unable to write debug_addr segment: %s",686                                   toString(std::move(Err)).c_str());687      if (AddrSize != 0)688        if (Error Err = writeVariableSizedInteger(Pair.Address, AddrSize, OS,689                                                  DI.IsLittleEndian))690          return createStringError(errc::not_supported,691                                   "unable to write debug_addr address: %s",692                                   toString(std::move(Err)).c_str());693    }694  }695 696  return Error::success();697}698 699Error DWARFYAML::emitDebugStrOffsets(raw_ostream &OS, const Data &DI) {700  assert(DI.DebugStrOffsets && "unexpected emitDebugStrOffsets() call");701  for (const DWARFYAML::StringOffsetsTable &Table : *DI.DebugStrOffsets) {702    uint64_t Length;703    if (Table.Length)704      Length = *Table.Length;705    else706      // sizeof(version) + sizeof(padding) = 4707      Length =708          4 + Table.Offsets.size() * (Table.Format == dwarf::DWARF64 ? 8 : 4);709 710    writeInitialLength(Table.Format, Length, OS, DI.IsLittleEndian);711    writeInteger((uint16_t)Table.Version, OS, DI.IsLittleEndian);712    writeInteger((uint16_t)Table.Padding, OS, DI.IsLittleEndian);713 714    for (uint64_t Offset : Table.Offsets)715      writeDWARFOffset(Offset, Table.Format, OS, DI.IsLittleEndian);716  }717 718  return Error::success();719}720 721namespace {722/// Emits the header for a DebugNames section.723void emitDebugNamesHeader(raw_ostream &OS, bool IsLittleEndian,724                          uint32_t NameCount, uint32_t AbbrevSize,725                          uint32_t CombinedSizeOtherParts) {726  // Use the same AugmentationString as AsmPrinter.727  StringRef AugmentationString = "LLVM0700";728  size_t TotalSize = CombinedSizeOtherParts + 5 * sizeof(uint32_t) +729                     2 * sizeof(uint16_t) + sizeof(NameCount) +730                     sizeof(AbbrevSize) + AugmentationString.size();731  writeInteger(uint32_t(TotalSize), OS, IsLittleEndian); // Unit length732 733  // Everything below is included in total size.734  writeInteger(uint16_t(5), OS, IsLittleEndian); // Version735  writeInteger(uint16_t(0), OS, IsLittleEndian); // Padding736  writeInteger(uint32_t(1), OS, IsLittleEndian); // Compilation Unit count737  writeInteger(uint32_t(0), OS, IsLittleEndian); // Local Type Unit count738  writeInteger(uint32_t(0), OS, IsLittleEndian); // Foreign Type Unit count739  writeInteger(uint32_t(0), OS, IsLittleEndian); // Bucket count740  writeInteger(NameCount, OS, IsLittleEndian);741  writeInteger(AbbrevSize, OS, IsLittleEndian);742  writeInteger(uint32_t(AugmentationString.size()), OS, IsLittleEndian);743  OS.write(AugmentationString.data(), AugmentationString.size());744}745 746/// Emits the abbreviations for a DebugNames section.747std::string748emitDebugNamesAbbrev(ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {749  std::string Data;750  raw_string_ostream OS(Data);751  for (const DWARFYAML::DebugNameAbbreviation &Abbrev : Abbrevs) {752    encodeULEB128(Abbrev.Code, OS);753    encodeULEB128(Abbrev.Tag, OS);754    for (auto [Idx, Form] : Abbrev.Indices) {755      encodeULEB128(Idx, OS);756      encodeULEB128(Form, OS);757    }758    encodeULEB128(0, OS);759    encodeULEB128(0, OS);760  }761  encodeULEB128(0, OS);762  return Data;763}764 765/// Emits a simple CU offsets list for a DebugNames section containing a single766/// CU at offset 0.767std::string emitDebugNamesCUOffsets(bool IsLittleEndian) {768  std::string Data;769  raw_string_ostream OS(Data);770  writeInteger(uint32_t(0), OS, IsLittleEndian);771  return Data;772}773 774/// Emits the "NameTable" for a DebugNames section; according to the spec, it775/// consists of two arrays: an array of string offsets, followed immediately by776/// an array of entry offsets. The string offsets are emitted in the order777/// provided in `Entries`.778std::string emitDebugNamesNameTable(779    bool IsLittleEndian,780    const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> &Entries,781    ArrayRef<uint32_t> EntryPoolOffsets) {782  assert(Entries.size() == EntryPoolOffsets.size());783 784  std::string Data;785  raw_string_ostream OS(Data);786 787  for (uint32_t Strp : make_first_range(Entries))788    writeInteger(Strp, OS, IsLittleEndian);789  for (uint32_t PoolOffset : EntryPoolOffsets)790    writeInteger(PoolOffset, OS, IsLittleEndian);791  return Data;792}793 794/// Groups entries based on their name (strp) code and returns a map.795DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>>796groupEntries(ArrayRef<DWARFYAML::DebugNameEntry> Entries) {797  DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> StrpToEntries;798  for (const DWARFYAML::DebugNameEntry &Entry : Entries)799    StrpToEntries[Entry.NameStrp].push_back(Entry);800  return StrpToEntries;801}802 803/// Finds the abbreviation whose code is AbbrevCode and returns a list804/// containing the expected size of all non-zero-length forms.805Expected<SmallVector<uint8_t>>806getNonZeroDataSizesFor(uint32_t AbbrevCode,807                       ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {808  const auto *AbbrevIt = find_if(Abbrevs, [&](const auto &Abbrev) {809    return Abbrev.Code.value == AbbrevCode;810  });811  if (AbbrevIt == Abbrevs.end())812    return createStringError(inconvertibleErrorCode(),813                             "did not find an Abbreviation for this code");814 815  SmallVector<uint8_t> DataSizes;816  dwarf::FormParams Params{/*Version=*/5, /*AddrSize=*/4, dwarf::DWARF32};817  for (auto [Idx, Form] : AbbrevIt->Indices) {818    std::optional<uint8_t> FormSize = dwarf::getFixedFormByteSize(Form, Params);819    if (!FormSize)820      return createStringError(inconvertibleErrorCode(),821                               "unsupported Form for YAML debug_names emitter");822    if (FormSize == 0)823      continue;824    DataSizes.push_back(*FormSize);825  }826  return DataSizes;827}828 829struct PoolOffsetsAndData {830  std::string PoolData;831  std::vector<uint32_t> PoolOffsets;832};833 834/// Emits the entry pool and returns an array of offsets containing the start835/// offset for the entries of each unique name.836/// Verifies that the provided number of data values match those expected by837/// the abbreviation table.838Expected<PoolOffsetsAndData> emitDebugNamesEntryPool(839    bool IsLittleEndian,840    const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>>841        &StrpToEntries,842    ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {843  PoolOffsetsAndData Result;844  raw_string_ostream OS(Result.PoolData);845 846  for (ArrayRef<DWARFYAML::DebugNameEntry> EntriesWithSameName :847       make_second_range(StrpToEntries)) {848    Result.PoolOffsets.push_back(Result.PoolData.size());849 850    for (const DWARFYAML::DebugNameEntry &Entry : EntriesWithSameName) {851      encodeULEB128(Entry.Code, OS);852 853      Expected<SmallVector<uint8_t>> DataSizes =854          getNonZeroDataSizesFor(Entry.Code, Abbrevs);855      if (!DataSizes)856        return DataSizes.takeError();857      if (DataSizes->size() != Entry.Values.size())858        return createStringError(859            inconvertibleErrorCode(),860            "mismatch between provided and required number of values");861 862      for (auto [Value, ValueSize] : zip_equal(Entry.Values, *DataSizes))863        if (Error E =864                writeVariableSizedInteger(Value, ValueSize, OS, IsLittleEndian))865          return std::move(E);866    }867    encodeULEB128(0, OS);868  }869 870  return Result;871}872} // namespace873 874Error DWARFYAML::emitDebugNames(raw_ostream &OS, const Data &DI) {875  assert(DI.DebugNames && "unexpected emitDebugNames() call");876  const DebugNamesSection DebugNames = DI.DebugNames.value();877 878  DenseMap<uint32_t, std::vector<DebugNameEntry>> StrpToEntries =879      groupEntries(DebugNames.Entries);880 881  // Emit all sub-sections into individual strings so that we may compute882  // relative offsets and sizes.883  Expected<PoolOffsetsAndData> PoolInfo = emitDebugNamesEntryPool(884      DI.IsLittleEndian, StrpToEntries, DebugNames.Abbrevs);885  if (!PoolInfo)886    return PoolInfo.takeError();887  std::string NamesTableData = emitDebugNamesNameTable(888      DI.IsLittleEndian, StrpToEntries, PoolInfo->PoolOffsets);889 890  std::string AbbrevData = emitDebugNamesAbbrev(DebugNames.Abbrevs);891  std::string CUOffsetsData = emitDebugNamesCUOffsets(DI.IsLittleEndian);892 893  size_t TotalSize = PoolInfo->PoolData.size() + NamesTableData.size() +894                     AbbrevData.size() + CUOffsetsData.size();895 896  // Start real emission by combining all individual strings.897  emitDebugNamesHeader(OS, DI.IsLittleEndian, StrpToEntries.size(),898                       AbbrevData.size(), TotalSize);899  OS.write(CUOffsetsData.data(), CUOffsetsData.size());900  // No local TUs, no foreign TUs, no hash lookups table.901  OS.write(NamesTableData.data(), NamesTableData.size());902  OS.write(AbbrevData.data(), AbbrevData.size());903  OS.write(PoolInfo->PoolData.data(), PoolInfo->PoolData.size());904 905  return Error::success();906}907 908static Error checkOperandCount(StringRef EncodingString,909                               ArrayRef<yaml::Hex64> Values,910                               uint64_t ExpectedOperands) {911  if (Values.size() != ExpectedOperands)912    return createStringError(913        errc::invalid_argument,914        "invalid number (%zu) of operands for the operator: %s, %" PRIu64915        " expected",916        Values.size(), EncodingString.str().c_str(), ExpectedOperands);917 918  return Error::success();919}920 921static Error writeListEntryAddress(StringRef EncodingName, raw_ostream &OS,922                                   uint64_t Addr, uint8_t AddrSize,923                                   bool IsLittleEndian) {924  if (Error Err = writeVariableSizedInteger(Addr, AddrSize, OS, IsLittleEndian))925    return createStringError(errc::invalid_argument,926                             "unable to write address for the operator %s: %s",927                             EncodingName.str().c_str(),928                             toString(std::move(Err)).c_str());929 930  return Error::success();931}932 933static Expected<uint64_t>934writeDWARFExpression(raw_ostream &OS,935                     const DWARFYAML::DWARFOperation &Operation,936                     uint8_t AddrSize, bool IsLittleEndian) {937  auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {938    return checkOperandCount(dwarf::OperationEncodingString(Operation.Operator),939                             Operation.Values, ExpectedOperands);940  };941 942  uint64_t ExpressionBegin = OS.tell();943  writeInteger((uint8_t)Operation.Operator, OS, IsLittleEndian);944  switch (Operation.Operator) {945  case dwarf::DW_OP_consts:946    if (Error Err = CheckOperands(1))947      return std::move(Err);948    encodeSLEB128(Operation.Values[0], OS);949    break;950  case dwarf::DW_OP_stack_value:951    if (Error Err = CheckOperands(0))952      return std::move(Err);953    break;954  default:955    StringRef EncodingStr = dwarf::OperationEncodingString(Operation.Operator);956    return createStringError(errc::not_supported,957                             "DWARF expression: " +958                                 (EncodingStr.empty()959                                      ? "0x" + utohexstr(Operation.Operator)960                                      : EncodingStr) +961                                 " is not supported");962  }963  return OS.tell() - ExpressionBegin;964}965 966static Expected<uint64_t> writeListEntry(raw_ostream &OS,967                                         const DWARFYAML::RnglistEntry &Entry,968                                         uint8_t AddrSize,969                                         bool IsLittleEndian) {970  uint64_t BeginOffset = OS.tell();971  writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);972 973  StringRef EncodingName = dwarf::RangeListEncodingString(Entry.Operator);974 975  auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {976    return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);977  };978 979  auto WriteAddress = [&](uint64_t Addr) -> Error {980    return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,981                                 IsLittleEndian);982  };983 984  switch (Entry.Operator) {985  case dwarf::DW_RLE_end_of_list:986    if (Error Err = CheckOperands(0))987      return std::move(Err);988    break;989  case dwarf::DW_RLE_base_addressx:990    if (Error Err = CheckOperands(1))991      return std::move(Err);992    encodeULEB128(Entry.Values[0], OS);993    break;994  case dwarf::DW_RLE_startx_endx:995  case dwarf::DW_RLE_startx_length:996  case dwarf::DW_RLE_offset_pair:997    if (Error Err = CheckOperands(2))998      return std::move(Err);999    encodeULEB128(Entry.Values[0], OS);1000    encodeULEB128(Entry.Values[1], OS);1001    break;1002  case dwarf::DW_RLE_base_address:1003    if (Error Err = CheckOperands(1))1004      return std::move(Err);1005    if (Error Err = WriteAddress(Entry.Values[0]))1006      return std::move(Err);1007    break;1008  case dwarf::DW_RLE_start_end:1009    if (Error Err = CheckOperands(2))1010      return std::move(Err);1011    if (Error Err = WriteAddress(Entry.Values[0]))1012      return std::move(Err);1013    cantFail(WriteAddress(Entry.Values[1]));1014    break;1015  case dwarf::DW_RLE_start_length:1016    if (Error Err = CheckOperands(2))1017      return std::move(Err);1018    if (Error Err = WriteAddress(Entry.Values[0]))1019      return std::move(Err);1020    encodeULEB128(Entry.Values[1], OS);1021    break;1022  }1023 1024  return OS.tell() - BeginOffset;1025}1026 1027static Expected<uint64_t> writeListEntry(raw_ostream &OS,1028                                         const DWARFYAML::LoclistEntry &Entry,1029                                         uint8_t AddrSize,1030                                         bool IsLittleEndian) {1031  uint64_t BeginOffset = OS.tell();1032  writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);1033 1034  StringRef EncodingName = dwarf::LocListEncodingString(Entry.Operator);1035 1036  auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {1037    return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);1038  };1039 1040  auto WriteAddress = [&](uint64_t Addr) -> Error {1041    return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,1042                                 IsLittleEndian);1043  };1044 1045  auto WriteDWARFOperations = [&]() -> Error {1046    std::string OpBuffer;1047    raw_string_ostream OpBufferOS(OpBuffer);1048    uint64_t DescriptionsLength = 0;1049 1050    for (const DWARFYAML::DWARFOperation &Op : Entry.Descriptions) {1051      if (Expected<uint64_t> OpSize =1052              writeDWARFExpression(OpBufferOS, Op, AddrSize, IsLittleEndian))1053        DescriptionsLength += *OpSize;1054      else1055        return OpSize.takeError();1056    }1057 1058    if (Entry.DescriptionsLength)1059      DescriptionsLength = *Entry.DescriptionsLength;1060    else1061      DescriptionsLength = OpBuffer.size();1062 1063    encodeULEB128(DescriptionsLength, OS);1064    OS.write(OpBuffer.data(), OpBuffer.size());1065 1066    return Error::success();1067  };1068 1069  switch (Entry.Operator) {1070  case dwarf::DW_LLE_end_of_list:1071    if (Error Err = CheckOperands(0))1072      return std::move(Err);1073    break;1074  case dwarf::DW_LLE_base_addressx:1075    if (Error Err = CheckOperands(1))1076      return std::move(Err);1077    encodeULEB128(Entry.Values[0], OS);1078    break;1079  case dwarf::DW_LLE_startx_endx:1080  case dwarf::DW_LLE_startx_length:1081  case dwarf::DW_LLE_offset_pair:1082    if (Error Err = CheckOperands(2))1083      return std::move(Err);1084    encodeULEB128(Entry.Values[0], OS);1085    encodeULEB128(Entry.Values[1], OS);1086    if (Error Err = WriteDWARFOperations())1087      return std::move(Err);1088    break;1089  case dwarf::DW_LLE_default_location:1090    if (Error Err = CheckOperands(0))1091      return std::move(Err);1092    if (Error Err = WriteDWARFOperations())1093      return std::move(Err);1094    break;1095  case dwarf::DW_LLE_base_address:1096    if (Error Err = CheckOperands(1))1097      return std::move(Err);1098    if (Error Err = WriteAddress(Entry.Values[0]))1099      return std::move(Err);1100    break;1101  case dwarf::DW_LLE_start_end:1102    if (Error Err = CheckOperands(2))1103      return std::move(Err);1104    if (Error Err = WriteAddress(Entry.Values[0]))1105      return std::move(Err);1106    cantFail(WriteAddress(Entry.Values[1]));1107    if (Error Err = WriteDWARFOperations())1108      return std::move(Err);1109    break;1110  case dwarf::DW_LLE_start_length:1111    if (Error Err = CheckOperands(2))1112      return std::move(Err);1113    if (Error Err = WriteAddress(Entry.Values[0]))1114      return std::move(Err);1115    encodeULEB128(Entry.Values[1], OS);1116    if (Error Err = WriteDWARFOperations())1117      return std::move(Err);1118    break;1119  }1120 1121  return OS.tell() - BeginOffset;1122}1123 1124template <typename EntryType>1125static Error writeDWARFLists(raw_ostream &OS,1126                             ArrayRef<DWARFYAML::ListTable<EntryType>> Tables,1127                             bool IsLittleEndian, bool Is64BitAddrSize) {1128  for (const DWARFYAML::ListTable<EntryType> &Table : Tables) {1129    // sizeof(version) + sizeof(address_size) + sizeof(segment_selector_size) +1130    // sizeof(offset_entry_count) = 81131    uint64_t Length = 8;1132 1133    uint8_t AddrSize;1134    if (Table.AddrSize)1135      AddrSize = *Table.AddrSize;1136    else1137      AddrSize = Is64BitAddrSize ? 8 : 4;1138 1139    // Since the length of the current range/location lists entry is1140    // undetermined yet, we firstly write the content of the range/location1141    // lists to a buffer to calculate the length and then serialize the buffer1142    // content to the actual output stream.1143    std::string ListBuffer;1144    raw_string_ostream ListBufferOS(ListBuffer);1145 1146    // Offsets holds offsets for each range/location list. The i-th element is1147    // the offset from the beginning of the first range/location list to the1148    // location of the i-th range list.1149    std::vector<uint64_t> Offsets;1150 1151    for (const DWARFYAML::ListEntries<EntryType> &List : Table.Lists) {1152      Offsets.push_back(ListBufferOS.tell());1153      if (List.Content) {1154        List.Content->writeAsBinary(ListBufferOS, UINT64_MAX);1155        Length += List.Content->binary_size();1156      } else if (List.Entries) {1157        for (const EntryType &Entry : *List.Entries) {1158          Expected<uint64_t> EntrySize =1159              writeListEntry(ListBufferOS, Entry, AddrSize, IsLittleEndian);1160          if (!EntrySize)1161            return EntrySize.takeError();1162          Length += *EntrySize;1163        }1164      }1165    }1166 1167    // If the offset_entry_count field isn't specified, yaml2obj will infer it1168    // from the 'Offsets' field in the YAML description. If the 'Offsets' field1169    // isn't specified either, yaml2obj will infer it from the auto-generated1170    // offsets.1171    uint32_t OffsetEntryCount;1172    if (Table.OffsetEntryCount)1173      OffsetEntryCount = *Table.OffsetEntryCount;1174    else1175      OffsetEntryCount = Table.Offsets ? Table.Offsets->size() : Offsets.size();1176    uint64_t OffsetsSize =1177        OffsetEntryCount * (Table.Format == dwarf::DWARF64 ? 8 : 4);1178    Length += OffsetsSize;1179 1180    // If the length is specified in the YAML description, we use it instead of1181    // the actual length.1182    if (Table.Length)1183      Length = *Table.Length;1184 1185    writeInitialLength(Table.Format, Length, OS, IsLittleEndian);1186    writeInteger((uint16_t)Table.Version, OS, IsLittleEndian);1187    writeInteger((uint8_t)AddrSize, OS, IsLittleEndian);1188    writeInteger((uint8_t)Table.SegSelectorSize, OS, IsLittleEndian);1189    writeInteger((uint32_t)OffsetEntryCount, OS, IsLittleEndian);1190 1191    auto EmitOffsets = [&](ArrayRef<uint64_t> Offsets, uint64_t OffsetsSize) {1192      for (uint64_t Offset : Offsets)1193        writeDWARFOffset(OffsetsSize + Offset, Table.Format, OS,1194                         IsLittleEndian);1195    };1196 1197    if (Table.Offsets)1198      EmitOffsets(ArrayRef<uint64_t>((const uint64_t *)Table.Offsets->data(),1199                                     Table.Offsets->size()),1200                  0);1201    else if (OffsetEntryCount != 0)1202      EmitOffsets(Offsets, OffsetsSize);1203 1204    OS.write(ListBuffer.data(), ListBuffer.size());1205  }1206 1207  return Error::success();1208}1209 1210Error DWARFYAML::emitDebugRnglists(raw_ostream &OS, const Data &DI) {1211  assert(DI.DebugRnglists && "unexpected emitDebugRnglists() call");1212  return writeDWARFLists<DWARFYAML::RnglistEntry>(1213      OS, *DI.DebugRnglists, DI.IsLittleEndian, DI.Is64BitAddrSize);1214}1215 1216Error DWARFYAML::emitDebugLoclists(raw_ostream &OS, const Data &DI) {1217  assert(DI.DebugLoclists && "unexpected emitDebugRnglists() call");1218  return writeDWARFLists<DWARFYAML::LoclistEntry>(1219      OS, *DI.DebugLoclists, DI.IsLittleEndian, DI.Is64BitAddrSize);1220}1221 1222std::function<Error(raw_ostream &, const DWARFYAML::Data &)>1223DWARFYAML::getDWARFEmitterByName(StringRef SecName) {1224  auto EmitFunc =1225      StringSwitch<1226          std::function<Error(raw_ostream &, const DWARFYAML::Data &)>>(SecName)1227          .Case("debug_abbrev", DWARFYAML::emitDebugAbbrev)1228          .Case("debug_addr", DWARFYAML::emitDebugAddr)1229          .Case("debug_aranges", DWARFYAML::emitDebugAranges)1230          .Case("debug_gnu_pubnames", DWARFYAML::emitDebugGNUPubnames)1231          .Case("debug_gnu_pubtypes", DWARFYAML::emitDebugGNUPubtypes)1232          .Case("debug_info", DWARFYAML::emitDebugInfo)1233          .Case("debug_line", DWARFYAML::emitDebugLine)1234          .Case("debug_loclists", DWARFYAML::emitDebugLoclists)1235          .Case("debug_pubnames", DWARFYAML::emitDebugPubnames)1236          .Case("debug_pubtypes", DWARFYAML::emitDebugPubtypes)1237          .Case("debug_ranges", DWARFYAML::emitDebugRanges)1238          .Case("debug_rnglists", DWARFYAML::emitDebugRnglists)1239          .Case("debug_str", DWARFYAML::emitDebugStr)1240          .Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets)1241          .Case("debug_names", DWARFYAML::emitDebugNames)1242          .Default([&](raw_ostream &, const DWARFYAML::Data &) {1243            return createStringError(errc::not_supported,1244                                     SecName + " is not supported");1245          });1246 1247  return EmitFunc;1248}1249 1250static Error1251emitDebugSectionImpl(const DWARFYAML::Data &DI, StringRef Sec,1252                     StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) {1253  std::string Data;1254  raw_string_ostream DebugInfoStream(Data);1255 1256  auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Sec);1257 1258  if (Error Err = EmitFunc(DebugInfoStream, DI))1259    return Err;1260  DebugInfoStream.flush();1261  if (!Data.empty())1262    OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data);1263 1264  return Error::success();1265}1266 1267Expected<StringMap<std::unique_ptr<MemoryBuffer>>>1268DWARFYAML::emitDebugSections(StringRef YAMLString, bool IsLittleEndian,1269                             bool Is64BitAddrSize) {1270  auto CollectDiagnostic = [](const SMDiagnostic &Diag, void *DiagContext) {1271    *static_cast<SMDiagnostic *>(DiagContext) = Diag;1272  };1273 1274  SMDiagnostic GeneratedDiag;1275  yaml::Input YIn(YAMLString, /*Ctxt=*/nullptr, CollectDiagnostic,1276                  &GeneratedDiag);1277 1278  DWARFYAML::Data DI;1279  DI.IsLittleEndian = IsLittleEndian;1280  DI.Is64BitAddrSize = Is64BitAddrSize;1281 1282  YIn >> DI;1283  if (YIn.error())1284    return createStringError(YIn.error(), GeneratedDiag.getMessage());1285 1286  StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;1287  Error Err = Error::success();1288 1289  for (StringRef SecName : DI.getNonEmptySectionNames())1290    Err = joinErrors(std::move(Err),1291                     emitDebugSectionImpl(DI, SecName, DebugSections));1292 1293  if (Err)1294    return std::move(Err);1295  return std::move(DebugSections);1296}1297