Home | History | Annotate | Line # | Download | only in ObjectYAML
      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-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 ///
      9 /// \file
     10 /// 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/Host.h"
     24 #include "llvm/Support/LEB128.h"
     25 #include "llvm/Support/MathExtras.h"
     26 #include "llvm/Support/MemoryBuffer.h"
     27 #include "llvm/Support/SourceMgr.h"
     28 #include "llvm/Support/SwapByteOrder.h"
     29 #include "llvm/Support/YAMLTraits.h"
     30 #include "llvm/Support/raw_ostream.h"
     31 #include <algorithm>
     32 #include <cassert>
     33 #include <cstddef>
     34 #include <cstdint>
     35 #include <memory>
     36 #include <string>
     37 #include <vector>
     38 
     39 using namespace llvm;
     40 
     41 template <typename T>
     42 static 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 
     48 static 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   else
     59     return createStringError(errc::not_supported,
     60                              "invalid integer write size: %zu", Size);
     61 
     62   return Error::success();
     63 }
     64 
     65 static 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 
     70 static 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 
     81 static 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 
     87 Error 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 
     96 StringRef 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 = AbbrevTableContents.find(Index);
    100   if (It != AbbrevTableContents.cend())
    101     return It->second;
    102 
    103   std::string AbbrevTableBuffer;
    104   raw_string_ostream OS(AbbrevTableBuffer);
    105 
    106   uint64_t AbbrevCode = 0;
    107   for (const DWARFYAML::Abbrev &AbbrevDecl : DebugAbbrev[Index].Table) {
    108     AbbrevCode = AbbrevDecl.Code ? (uint64_t)*AbbrevDecl.Code : AbbrevCode + 1;
    109     encodeULEB128(AbbrevCode, OS);
    110     encodeULEB128(AbbrevDecl.Tag, OS);
    111     OS.write(AbbrevDecl.Children);
    112     for (const auto &Attr : AbbrevDecl.Attributes) {
    113       encodeULEB128(Attr.Attribute, OS);
    114       encodeULEB128(Attr.Form, OS);
    115       if (Attr.Form == dwarf::DW_FORM_implicit_const)
    116         encodeSLEB128(Attr.Value, OS);
    117     }
    118     encodeULEB128(0, OS);
    119     encodeULEB128(0, OS);
    120   }
    121 
    122   // The abbreviations for a given compilation unit end with an entry
    123   // consisting of a 0 byte for the abbreviation code.
    124   OS.write_zeros(1);
    125 
    126   AbbrevTableContents.insert({Index, AbbrevTableBuffer});
    127 
    128   return AbbrevTableContents[Index];
    129 }
    130 
    131 Error DWARFYAML::emitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) {
    132   for (uint64_t I = 0; I < DI.DebugAbbrev.size(); ++I) {
    133     StringRef AbbrevTableContent = DI.getAbbrevTableContentByIndex(I);
    134     OS.write(AbbrevTableContent.data(), AbbrevTableContent.size());
    135   }
    136 
    137   return Error::success();
    138 }
    139 
    140 Error DWARFYAML::emitDebugAranges(raw_ostream &OS, const DWARFYAML::Data &DI) {
    141   assert(DI.DebugAranges && "unexpected emitDebugAranges() call");
    142   for (const auto &Range : *DI.DebugAranges) {
    143     uint8_t AddrSize;
    144     if (Range.AddrSize)
    145       AddrSize = *Range.AddrSize;
    146     else
    147       AddrSize = DI.Is64BitAddrSize ? 8 : 4;
    148 
    149     uint64_t Length = 4; // sizeof(version) 2 + sizeof(address_size) 1 +
    150                          // sizeof(segment_selector_size) 1
    151     Length +=
    152         Range.Format == dwarf::DWARF64 ? 8 : 4; // sizeof(debug_info_offset)
    153 
    154     const uint64_t HeaderLength =
    155         Length + (Range.Format == dwarf::DWARF64
    156                       ? 12
    157                       : 4); // sizeof(unit_header) = 12 (DWARF64) or 4 (DWARF32)
    158     const uint64_t PaddedHeaderLength = alignTo(HeaderLength, AddrSize * 2);
    159 
    160     if (Range.Length) {
    161       Length = *Range.Length;
    162     } else {
    163       Length += PaddedHeaderLength - HeaderLength;
    164       Length += AddrSize * 2 * (Range.Descriptors.size() + 1);
    165     }
    166 
    167     writeInitialLength(Range.Format, Length, OS, DI.IsLittleEndian);
    168     writeInteger((uint16_t)Range.Version, OS, DI.IsLittleEndian);
    169     writeDWARFOffset(Range.CuOffset, Range.Format, OS, DI.IsLittleEndian);
    170     writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
    171     writeInteger((uint8_t)Range.SegSize, OS, DI.IsLittleEndian);
    172     ZeroFillBytes(OS, PaddedHeaderLength - HeaderLength);
    173 
    174     for (const auto &Descriptor : Range.Descriptors) {
    175       if (Error Err = writeVariableSizedInteger(Descriptor.Address, AddrSize,
    176                                                 OS, DI.IsLittleEndian))
    177         return createStringError(errc::not_supported,
    178                                  "unable to write debug_aranges address: %s",
    179                                  toString(std::move(Err)).c_str());
    180       cantFail(writeVariableSizedInteger(Descriptor.Length, AddrSize, OS,
    181                                          DI.IsLittleEndian));
    182     }
    183     ZeroFillBytes(OS, AddrSize * 2);
    184   }
    185 
    186   return Error::success();
    187 }
    188 
    189 Error DWARFYAML::emitDebugRanges(raw_ostream &OS, const DWARFYAML::Data &DI) {
    190   const size_t RangesOffset = OS.tell();
    191   uint64_t EntryIndex = 0;
    192   for (const auto &DebugRanges : *DI.DebugRanges) {
    193     const size_t CurrOffset = OS.tell() - RangesOffset;
    194     if (DebugRanges.Offset && (uint64_t)*DebugRanges.Offset < CurrOffset)
    195       return createStringError(errc::invalid_argument,
    196                                "'Offset' for 'debug_ranges' with index " +
    197                                    Twine(EntryIndex) +
    198                                    " must be greater than or equal to the "
    199                                    "number of bytes written already (0x" +
    200                                    Twine::utohexstr(CurrOffset) + ")");
    201     if (DebugRanges.Offset)
    202       ZeroFillBytes(OS, *DebugRanges.Offset - CurrOffset);
    203 
    204     uint8_t AddrSize;
    205     if (DebugRanges.AddrSize)
    206       AddrSize = *DebugRanges.AddrSize;
    207     else
    208       AddrSize = DI.Is64BitAddrSize ? 8 : 4;
    209     for (const auto &Entry : DebugRanges.Entries) {
    210       if (Error Err = writeVariableSizedInteger(Entry.LowOffset, AddrSize, OS,
    211                                                 DI.IsLittleEndian))
    212         return createStringError(
    213             errc::not_supported,
    214             "unable to write debug_ranges address offset: %s",
    215             toString(std::move(Err)).c_str());
    216       cantFail(writeVariableSizedInteger(Entry.HighOffset, AddrSize, OS,
    217                                          DI.IsLittleEndian));
    218     }
    219     ZeroFillBytes(OS, AddrSize * 2);
    220     ++EntryIndex;
    221   }
    222 
    223   return Error::success();
    224 }
    225 
    226 static Error emitPubSection(raw_ostream &OS, const DWARFYAML::PubSection &Sect,
    227                             bool IsLittleEndian, bool IsGNUPubSec = false) {
    228   writeInitialLength(Sect.Format, Sect.Length, OS, IsLittleEndian);
    229   writeInteger((uint16_t)Sect.Version, OS, IsLittleEndian);
    230   writeInteger((uint32_t)Sect.UnitOffset, OS, IsLittleEndian);
    231   writeInteger((uint32_t)Sect.UnitSize, OS, IsLittleEndian);
    232   for (const auto &Entry : Sect.Entries) {
    233     writeInteger((uint32_t)Entry.DieOffset, OS, IsLittleEndian);
    234     if (IsGNUPubSec)
    235       writeInteger((uint8_t)Entry.Descriptor, OS, IsLittleEndian);
    236     OS.write(Entry.Name.data(), Entry.Name.size());
    237     OS.write('\0');
    238   }
    239   return Error::success();
    240 }
    241 
    242 Error DWARFYAML::emitDebugPubnames(raw_ostream &OS, const Data &DI) {
    243   assert(DI.PubNames && "unexpected emitDebugPubnames() call");
    244   return emitPubSection(OS, *DI.PubNames, DI.IsLittleEndian);
    245 }
    246 
    247 Error DWARFYAML::emitDebugPubtypes(raw_ostream &OS, const Data &DI) {
    248   assert(DI.PubTypes && "unexpected emitDebugPubtypes() call");
    249   return emitPubSection(OS, *DI.PubTypes, DI.IsLittleEndian);
    250 }
    251 
    252 Error DWARFYAML::emitDebugGNUPubnames(raw_ostream &OS, const Data &DI) {
    253   assert(DI.GNUPubNames && "unexpected emitDebugGNUPubnames() call");
    254   return emitPubSection(OS, *DI.GNUPubNames, DI.IsLittleEndian,
    255                         /*IsGNUStyle=*/true);
    256 }
    257 
    258 Error DWARFYAML::emitDebugGNUPubtypes(raw_ostream &OS, const Data &DI) {
    259   assert(DI.GNUPubTypes && "unexpected emitDebugGNUPubtypes() call");
    260   return emitPubSection(OS, *DI.GNUPubTypes, DI.IsLittleEndian,
    261                         /*IsGNUStyle=*/true);
    262 }
    263 
    264 static Expected<uint64_t> writeDIE(const DWARFYAML::Data &DI, uint64_t CUIndex,
    265                                    uint64_t AbbrevTableID,
    266                                    const dwarf::FormParams &Params,
    267                                    const DWARFYAML::Entry &Entry,
    268                                    raw_ostream &OS, bool IsLittleEndian) {
    269   uint64_t EntryBegin = OS.tell();
    270   encodeULEB128(Entry.AbbrCode, OS);
    271   uint32_t AbbrCode = Entry.AbbrCode;
    272   if (AbbrCode == 0 || Entry.Values.empty())
    273     return OS.tell() - EntryBegin;
    274 
    275   Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =
    276       DI.getAbbrevTableInfoByID(AbbrevTableID);
    277   if (!AbbrevTableInfoOrErr)
    278     return createStringError(errc::invalid_argument,
    279                              toString(AbbrevTableInfoOrErr.takeError()) +
    280                                  " for compilation unit with index " +
    281                                  utostr(CUIndex));
    282 
    283   ArrayRef<DWARFYAML::Abbrev> AbbrevDecls(
    284       DI.DebugAbbrev[AbbrevTableInfoOrErr->Index].Table);
    285 
    286   if (AbbrCode > AbbrevDecls.size())
    287     return createStringError(
    288         errc::invalid_argument,
    289         "abbrev code must be less than or equal to the number of "
    290         "entries in abbreviation table");
    291   const DWARFYAML::Abbrev &Abbrev = AbbrevDecls[AbbrCode - 1];
    292   auto FormVal = Entry.Values.begin();
    293   auto AbbrForm = Abbrev.Attributes.begin();
    294   for (; FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end();
    295        ++FormVal, ++AbbrForm) {
    296     dwarf::Form Form = AbbrForm->Form;
    297     bool Indirect;
    298     do {
    299       Indirect = false;
    300       switch (Form) {
    301       case dwarf::DW_FORM_addr:
    302         // TODO: Test this error.
    303         if (Error Err = writeVariableSizedInteger(
    304                 FormVal->Value, Params.AddrSize, OS, IsLittleEndian))
    305           return std::move(Err);
    306         break;
    307       case dwarf::DW_FORM_ref_addr:
    308         // TODO: Test this error.
    309         if (Error Err = writeVariableSizedInteger(FormVal->Value,
    310                                                   Params.getRefAddrByteSize(),
    311                                                   OS, IsLittleEndian))
    312           return std::move(Err);
    313         break;
    314       case dwarf::DW_FORM_exprloc:
    315       case dwarf::DW_FORM_block:
    316         encodeULEB128(FormVal->BlockData.size(), OS);
    317         OS.write((const char *)FormVal->BlockData.data(),
    318                  FormVal->BlockData.size());
    319         break;
    320       case dwarf::DW_FORM_block1: {
    321         writeInteger((uint8_t)FormVal->BlockData.size(), OS, IsLittleEndian);
    322         OS.write((const char *)FormVal->BlockData.data(),
    323                  FormVal->BlockData.size());
    324         break;
    325       }
    326       case dwarf::DW_FORM_block2: {
    327         writeInteger((uint16_t)FormVal->BlockData.size(), OS, IsLittleEndian);
    328         OS.write((const char *)FormVal->BlockData.data(),
    329                  FormVal->BlockData.size());
    330         break;
    331       }
    332       case dwarf::DW_FORM_block4: {
    333         writeInteger((uint32_t)FormVal->BlockData.size(), OS, IsLittleEndian);
    334         OS.write((const char *)FormVal->BlockData.data(),
    335                  FormVal->BlockData.size());
    336         break;
    337       }
    338       case dwarf::DW_FORM_strx:
    339       case dwarf::DW_FORM_addrx:
    340       case dwarf::DW_FORM_rnglistx:
    341       case dwarf::DW_FORM_loclistx:
    342       case dwarf::DW_FORM_udata:
    343       case dwarf::DW_FORM_ref_udata:
    344       case dwarf::DW_FORM_GNU_addr_index:
    345       case dwarf::DW_FORM_GNU_str_index:
    346         encodeULEB128(FormVal->Value, OS);
    347         break;
    348       case dwarf::DW_FORM_data1:
    349       case dwarf::DW_FORM_ref1:
    350       case dwarf::DW_FORM_flag:
    351       case dwarf::DW_FORM_strx1:
    352       case dwarf::DW_FORM_addrx1:
    353         writeInteger((uint8_t)FormVal->Value, OS, IsLittleEndian);
    354         break;
    355       case dwarf::DW_FORM_data2:
    356       case dwarf::DW_FORM_ref2:
    357       case dwarf::DW_FORM_strx2:
    358       case dwarf::DW_FORM_addrx2:
    359         writeInteger((uint16_t)FormVal->Value, OS, IsLittleEndian);
    360         break;
    361       case dwarf::DW_FORM_data4:
    362       case dwarf::DW_FORM_ref4:
    363       case dwarf::DW_FORM_ref_sup4:
    364       case dwarf::DW_FORM_strx4:
    365       case dwarf::DW_FORM_addrx4:
    366         writeInteger((uint32_t)FormVal->Value, OS, IsLittleEndian);
    367         break;
    368       case dwarf::DW_FORM_data8:
    369       case dwarf::DW_FORM_ref8:
    370       case dwarf::DW_FORM_ref_sup8:
    371       case dwarf::DW_FORM_ref_sig8:
    372         writeInteger((uint64_t)FormVal->Value, OS, IsLittleEndian);
    373         break;
    374       case dwarf::DW_FORM_sdata:
    375         encodeSLEB128(FormVal->Value, OS);
    376         break;
    377       case dwarf::DW_FORM_string:
    378         OS.write(FormVal->CStr.data(), FormVal->CStr.size());
    379         OS.write('\0');
    380         break;
    381       case dwarf::DW_FORM_indirect:
    382         encodeULEB128(FormVal->Value, OS);
    383         Indirect = true;
    384         Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value);
    385         ++FormVal;
    386         break;
    387       case dwarf::DW_FORM_strp:
    388       case dwarf::DW_FORM_sec_offset:
    389       case dwarf::DW_FORM_GNU_ref_alt:
    390       case dwarf::DW_FORM_GNU_strp_alt:
    391       case dwarf::DW_FORM_line_strp:
    392       case dwarf::DW_FORM_strp_sup:
    393         cantFail(writeVariableSizedInteger(FormVal->Value,
    394                                            Params.getDwarfOffsetByteSize(), OS,
    395                                            IsLittleEndian));
    396         break;
    397       default:
    398         break;
    399       }
    400     } while (Indirect);
    401   }
    402 
    403   return OS.tell() - EntryBegin;
    404 }
    405 
    406 Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {
    407   for (uint64_t I = 0; I < DI.CompileUnits.size(); ++I) {
    408     const DWARFYAML::Unit &Unit = DI.CompileUnits[I];
    409     uint8_t AddrSize;
    410     if (Unit.AddrSize)
    411       AddrSize = *Unit.AddrSize;
    412     else
    413       AddrSize = DI.Is64BitAddrSize ? 8 : 4;
    414     dwarf::FormParams Params = {Unit.Version, AddrSize, Unit.Format};
    415     uint64_t Length = 3; // sizeof(version) + sizeof(address_size)
    416     Length += Unit.Version >= 5 ? 1 : 0;       // sizeof(unit_type)
    417     Length += Params.getDwarfOffsetByteSize(); // sizeof(debug_abbrev_offset)
    418 
    419     // Since the length of the current compilation unit is undetermined yet, we
    420     // firstly write the content of the compilation unit to a buffer to
    421     // calculate it and then serialize the buffer content to the actual output
    422     // stream.
    423     std::string EntryBuffer;
    424     raw_string_ostream EntryBufferOS(EntryBuffer);
    425 
    426     uint64_t AbbrevTableID = Unit.AbbrevTableID.getValueOr(I);
    427     for (const DWARFYAML::Entry &Entry : Unit.Entries) {
    428       if (Expected<uint64_t> EntryLength =
    429               writeDIE(DI, I, AbbrevTableID, Params, Entry, EntryBufferOS,
    430                        DI.IsLittleEndian))
    431         Length += *EntryLength;
    432       else
    433         return EntryLength.takeError();
    434     }
    435 
    436     // If the length is specified in the YAML description, we use it instead of
    437     // the actual length.
    438     if (Unit.Length)
    439       Length = *Unit.Length;
    440 
    441     writeInitialLength(Unit.Format, Length, OS, DI.IsLittleEndian);
    442     writeInteger((uint16_t)Unit.Version, OS, DI.IsLittleEndian);
    443 
    444     uint64_t AbbrevTableOffset = 0;
    445     if (Unit.AbbrOffset) {
    446       AbbrevTableOffset = *Unit.AbbrOffset;
    447     } else {
    448       if (Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =
    449               DI.getAbbrevTableInfoByID(AbbrevTableID)) {
    450         AbbrevTableOffset = AbbrevTableInfoOrErr->Offset;
    451       } else {
    452         // The current compilation unit may not have DIEs and it will not be
    453         // able to find the associated abbrev table. We consume the error and
    454         // assign 0 to the debug_abbrev_offset in such circumstances.
    455         consumeError(AbbrevTableInfoOrErr.takeError());
    456       }
    457     }
    458 
    459     if (Unit.Version >= 5) {
    460       writeInteger((uint8_t)Unit.Type, OS, DI.IsLittleEndian);
    461       writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
    462       writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);
    463     } else {
    464       writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);
    465       writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
    466     }
    467 
    468     OS.write(EntryBuffer.data(), EntryBuffer.size());
    469   }
    470 
    471   return Error::success();
    472 }
    473 
    474 static void emitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) {
    475   OS.write(File.Name.data(), File.Name.size());
    476   OS.write('\0');
    477   encodeULEB128(File.DirIdx, OS);
    478   encodeULEB128(File.ModTime, OS);
    479   encodeULEB128(File.Length, OS);
    480 }
    481 
    482 static void writeExtendedOpcode(const DWARFYAML::LineTableOpcode &Op,
    483                                 uint8_t AddrSize, bool IsLittleEndian,
    484                                 raw_ostream &OS) {
    485   // The first byte of extended opcodes is a zero byte. The next bytes are an
    486   // ULEB128 integer giving the number of bytes in the instruction itself (does
    487   // not include the first zero byte or the size). We serialize the instruction
    488   // itself into the OpBuffer and then write the size of the buffer and the
    489   // buffer to the real output stream.
    490   std::string OpBuffer;
    491   raw_string_ostream OpBufferOS(OpBuffer);
    492   writeInteger((uint8_t)Op.SubOpcode, OpBufferOS, IsLittleEndian);
    493   switch (Op.SubOpcode) {
    494   case dwarf::DW_LNE_set_address:
    495     cantFail(writeVariableSizedInteger(Op.Data, AddrSize, OpBufferOS,
    496                                        IsLittleEndian));
    497     break;
    498   case dwarf::DW_LNE_define_file:
    499     emitFileEntry(OpBufferOS, Op.FileEntry);
    500     break;
    501   case dwarf::DW_LNE_set_discriminator:
    502     encodeULEB128(Op.Data, OpBufferOS);
    503     break;
    504   case dwarf::DW_LNE_end_sequence:
    505     break;
    506   default:
    507     for (auto OpByte : Op.UnknownOpcodeData)
    508       writeInteger((uint8_t)OpByte, OpBufferOS, IsLittleEndian);
    509   }
    510   uint64_t ExtLen = Op.ExtLen.getValueOr(OpBuffer.size());
    511   encodeULEB128(ExtLen, OS);
    512   OS.write(OpBuffer.data(), OpBuffer.size());
    513 }
    514 
    515 static void writeLineTableOpcode(const DWARFYAML::LineTableOpcode &Op,
    516                                  uint8_t OpcodeBase, uint8_t AddrSize,
    517                                  raw_ostream &OS, bool IsLittleEndian) {
    518   writeInteger((uint8_t)Op.Opcode, OS, IsLittleEndian);
    519   if (Op.Opcode == 0) {
    520     writeExtendedOpcode(Op, AddrSize, IsLittleEndian, OS);
    521   } else if (Op.Opcode < OpcodeBase) {
    522     switch (Op.Opcode) {
    523     case dwarf::DW_LNS_copy:
    524     case dwarf::DW_LNS_negate_stmt:
    525     case dwarf::DW_LNS_set_basic_block:
    526     case dwarf::DW_LNS_const_add_pc:
    527     case dwarf::DW_LNS_set_prologue_end:
    528     case dwarf::DW_LNS_set_epilogue_begin:
    529       break;
    530 
    531     case dwarf::DW_LNS_advance_pc:
    532     case dwarf::DW_LNS_set_file:
    533     case dwarf::DW_LNS_set_column:
    534     case dwarf::DW_LNS_set_isa:
    535       encodeULEB128(Op.Data, OS);
    536       break;
    537 
    538     case dwarf::DW_LNS_advance_line:
    539       encodeSLEB128(Op.SData, OS);
    540       break;
    541 
    542     case dwarf::DW_LNS_fixed_advance_pc:
    543       writeInteger((uint16_t)Op.Data, OS, IsLittleEndian);
    544       break;
    545 
    546     default:
    547       for (auto OpData : Op.StandardOpcodeData) {
    548         encodeULEB128(OpData, OS);
    549       }
    550     }
    551   }
    552 }
    553 
    554 static std::vector<uint8_t>
    555 getStandardOpcodeLengths(uint16_t Version, Optional<uint8_t> OpcodeBase) {
    556   // If the opcode_base field isn't specified, we returns the
    557   // standard_opcode_lengths array according to the version by default.
    558   std::vector<uint8_t> StandardOpcodeLengths{0, 1, 1, 1, 1, 0,
    559                                              0, 0, 1, 0, 0, 1};
    560   if (Version == 2) {
    561     // DWARF v2 uses the same first 9 standard opcodes as v3-5.
    562     StandardOpcodeLengths.resize(9);
    563   } else if (OpcodeBase) {
    564     StandardOpcodeLengths.resize(*OpcodeBase > 0 ? *OpcodeBase - 1 : 0, 0);
    565   }
    566   return StandardOpcodeLengths;
    567 }
    568 
    569 Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) {
    570   for (const DWARFYAML::LineTable &LineTable : DI.DebugLines) {
    571     // Buffer holds the bytes following the header_length (or prologue_length in
    572     // DWARFv2) field to the end of the line number program itself.
    573     std::string Buffer;
    574     raw_string_ostream BufferOS(Buffer);
    575 
    576     writeInteger(LineTable.MinInstLength, BufferOS, DI.IsLittleEndian);
    577     // TODO: Add support for emitting DWARFv5 line table.
    578     if (LineTable.Version >= 4)
    579       writeInteger(LineTable.MaxOpsPerInst, BufferOS, DI.IsLittleEndian);
    580     writeInteger(LineTable.DefaultIsStmt, BufferOS, DI.IsLittleEndian);
    581     writeInteger(LineTable.LineBase, BufferOS, DI.IsLittleEndian);
    582     writeInteger(LineTable.LineRange, BufferOS, DI.IsLittleEndian);
    583 
    584     std::vector<uint8_t> StandardOpcodeLengths =
    585         LineTable.StandardOpcodeLengths.getValueOr(
    586             getStandardOpcodeLengths(LineTable.Version, LineTable.OpcodeBase));
    587     uint8_t OpcodeBase = LineTable.OpcodeBase
    588                              ? *LineTable.OpcodeBase
    589                              : StandardOpcodeLengths.size() + 1;
    590     writeInteger(OpcodeBase, BufferOS, DI.IsLittleEndian);
    591     for (uint8_t OpcodeLength : StandardOpcodeLengths)
    592       writeInteger(OpcodeLength, BufferOS, DI.IsLittleEndian);
    593 
    594     for (StringRef IncludeDir : LineTable.IncludeDirs) {
    595       BufferOS.write(IncludeDir.data(), IncludeDir.size());
    596       BufferOS.write('\0');
    597     }
    598     BufferOS.write('\0');
    599 
    600     for (const DWARFYAML::File &File : LineTable.Files)
    601       emitFileEntry(BufferOS, File);
    602     BufferOS.write('\0');
    603 
    604     uint64_t HeaderLength =
    605         LineTable.PrologueLength ? *LineTable.PrologueLength : Buffer.size();
    606 
    607     for (const DWARFYAML::LineTableOpcode &Op : LineTable.Opcodes)
    608       writeLineTableOpcode(Op, OpcodeBase, DI.Is64BitAddrSize ? 8 : 4, BufferOS,
    609                            DI.IsLittleEndian);
    610 
    611     uint64_t Length;
    612     if (LineTable.Length) {
    613       Length = *LineTable.Length;
    614     } else {
    615       Length = 2; // sizeof(version)
    616       Length +=
    617           (LineTable.Format == dwarf::DWARF64 ? 8 : 4); // sizeof(header_length)
    618       Length += Buffer.size();
    619     }
    620 
    621     writeInitialLength(LineTable.Format, Length, OS, DI.IsLittleEndian);
    622     writeInteger(LineTable.Version, OS, DI.IsLittleEndian);
    623     writeDWARFOffset(HeaderLength, LineTable.Format, OS, DI.IsLittleEndian);
    624     OS.write(Buffer.data(), Buffer.size());
    625   }
    626 
    627   return Error::success();
    628 }
    629 
    630 Error DWARFYAML::emitDebugAddr(raw_ostream &OS, const Data &DI) {
    631   for (const AddrTableEntry &TableEntry : *DI.DebugAddr) {
    632     uint8_t AddrSize;
    633     if (TableEntry.AddrSize)
    634       AddrSize = *TableEntry.AddrSize;
    635     else
    636       AddrSize = DI.Is64BitAddrSize ? 8 : 4;
    637 
    638     uint64_t Length;
    639     if (TableEntry.Length)
    640       Length = (uint64_t)*TableEntry.Length;
    641     else
    642       // 2 (version) + 1 (address_size) + 1 (segment_selector_size) = 4
    643       Length = 4 + (AddrSize + TableEntry.SegSelectorSize) *
    644                        TableEntry.SegAddrPairs.size();
    645 
    646     writeInitialLength(TableEntry.Format, Length, OS, DI.IsLittleEndian);
    647     writeInteger((uint16_t)TableEntry.Version, OS, DI.IsLittleEndian);
    648     writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
    649     writeInteger((uint8_t)TableEntry.SegSelectorSize, OS, DI.IsLittleEndian);
    650 
    651     for (const SegAddrPair &Pair : TableEntry.SegAddrPairs) {
    652       if (TableEntry.SegSelectorSize != yaml::Hex8{0})
    653         if (Error Err = writeVariableSizedInteger(Pair.Segment,
    654                                                   TableEntry.SegSelectorSize,
    655                                                   OS, DI.IsLittleEndian))
    656           return createStringError(errc::not_supported,
    657                                    "unable to write debug_addr segment: %s",
    658                                    toString(std::move(Err)).c_str());
    659       if (AddrSize != 0)
    660         if (Error Err = writeVariableSizedInteger(Pair.Address, AddrSize, OS,
    661                                                   DI.IsLittleEndian))
    662           return createStringError(errc::not_supported,
    663                                    "unable to write debug_addr address: %s",
    664                                    toString(std::move(Err)).c_str());
    665     }
    666   }
    667 
    668   return Error::success();
    669 }
    670 
    671 Error DWARFYAML::emitDebugStrOffsets(raw_ostream &OS, const Data &DI) {
    672   assert(DI.DebugStrOffsets && "unexpected emitDebugStrOffsets() call");
    673   for (const DWARFYAML::StringOffsetsTable &Table : *DI.DebugStrOffsets) {
    674     uint64_t Length;
    675     if (Table.Length)
    676       Length = *Table.Length;
    677     else
    678       // sizeof(version) + sizeof(padding) = 4
    679       Length =
    680           4 + Table.Offsets.size() * (Table.Format == dwarf::DWARF64 ? 8 : 4);
    681 
    682     writeInitialLength(Table.Format, Length, OS, DI.IsLittleEndian);
    683     writeInteger((uint16_t)Table.Version, OS, DI.IsLittleEndian);
    684     writeInteger((uint16_t)Table.Padding, OS, DI.IsLittleEndian);
    685 
    686     for (uint64_t Offset : Table.Offsets)
    687       writeDWARFOffset(Offset, Table.Format, OS, DI.IsLittleEndian);
    688   }
    689 
    690   return Error::success();
    691 }
    692 
    693 static Error checkOperandCount(StringRef EncodingString,
    694                                ArrayRef<yaml::Hex64> Values,
    695                                uint64_t ExpectedOperands) {
    696   if (Values.size() != ExpectedOperands)
    697     return createStringError(
    698         errc::invalid_argument,
    699         "invalid number (%zu) of operands for the operator: %s, %" PRIu64
    700         " expected",
    701         Values.size(), EncodingString.str().c_str(), ExpectedOperands);
    702 
    703   return Error::success();
    704 }
    705 
    706 static Error writeListEntryAddress(StringRef EncodingName, raw_ostream &OS,
    707                                    uint64_t Addr, uint8_t AddrSize,
    708                                    bool IsLittleEndian) {
    709   if (Error Err = writeVariableSizedInteger(Addr, AddrSize, OS, IsLittleEndian))
    710     return createStringError(errc::invalid_argument,
    711                              "unable to write address for the operator %s: %s",
    712                              EncodingName.str().c_str(),
    713                              toString(std::move(Err)).c_str());
    714 
    715   return Error::success();
    716 }
    717 
    718 static Expected<uint64_t>
    719 writeDWARFExpression(raw_ostream &OS,
    720                      const DWARFYAML::DWARFOperation &Operation,
    721                      uint8_t AddrSize, bool IsLittleEndian) {
    722   auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
    723     return checkOperandCount(dwarf::OperationEncodingString(Operation.Operator),
    724                              Operation.Values, ExpectedOperands);
    725   };
    726 
    727   uint64_t ExpressionBegin = OS.tell();
    728   writeInteger((uint8_t)Operation.Operator, OS, IsLittleEndian);
    729   switch (Operation.Operator) {
    730   case dwarf::DW_OP_consts:
    731     if (Error Err = CheckOperands(1))
    732       return std::move(Err);
    733     encodeSLEB128(Operation.Values[0], OS);
    734     break;
    735   case dwarf::DW_OP_stack_value:
    736     if (Error Err = CheckOperands(0))
    737       return std::move(Err);
    738     break;
    739   default:
    740     StringRef EncodingStr = dwarf::OperationEncodingString(Operation.Operator);
    741     return createStringError(errc::not_supported,
    742                              "DWARF expression: " +
    743                                  (EncodingStr.empty()
    744                                       ? "0x" + utohexstr(Operation.Operator)
    745                                       : EncodingStr) +
    746                                  " is not supported");
    747   }
    748   return OS.tell() - ExpressionBegin;
    749 }
    750 
    751 static Expected<uint64_t> writeListEntry(raw_ostream &OS,
    752                                          const DWARFYAML::RnglistEntry &Entry,
    753                                          uint8_t AddrSize,
    754                                          bool IsLittleEndian) {
    755   uint64_t BeginOffset = OS.tell();
    756   writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);
    757 
    758   StringRef EncodingName = dwarf::RangeListEncodingString(Entry.Operator);
    759 
    760   auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
    761     return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
    762   };
    763 
    764   auto WriteAddress = [&](uint64_t Addr) -> Error {
    765     return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
    766                                  IsLittleEndian);
    767   };
    768 
    769   switch (Entry.Operator) {
    770   case dwarf::DW_RLE_end_of_list:
    771     if (Error Err = CheckOperands(0))
    772       return std::move(Err);
    773     break;
    774   case dwarf::DW_RLE_base_addressx:
    775     if (Error Err = CheckOperands(1))
    776       return std::move(Err);
    777     encodeULEB128(Entry.Values[0], OS);
    778     break;
    779   case dwarf::DW_RLE_startx_endx:
    780   case dwarf::DW_RLE_startx_length:
    781   case dwarf::DW_RLE_offset_pair:
    782     if (Error Err = CheckOperands(2))
    783       return std::move(Err);
    784     encodeULEB128(Entry.Values[0], OS);
    785     encodeULEB128(Entry.Values[1], OS);
    786     break;
    787   case dwarf::DW_RLE_base_address:
    788     if (Error Err = CheckOperands(1))
    789       return std::move(Err);
    790     if (Error Err = WriteAddress(Entry.Values[0]))
    791       return std::move(Err);
    792     break;
    793   case dwarf::DW_RLE_start_end:
    794     if (Error Err = CheckOperands(2))
    795       return std::move(Err);
    796     if (Error Err = WriteAddress(Entry.Values[0]))
    797       return std::move(Err);
    798     cantFail(WriteAddress(Entry.Values[1]));
    799     break;
    800   case dwarf::DW_RLE_start_length:
    801     if (Error Err = CheckOperands(2))
    802       return std::move(Err);
    803     if (Error Err = WriteAddress(Entry.Values[0]))
    804       return std::move(Err);
    805     encodeULEB128(Entry.Values[1], OS);
    806     break;
    807   }
    808 
    809   return OS.tell() - BeginOffset;
    810 }
    811 
    812 static Expected<uint64_t> writeListEntry(raw_ostream &OS,
    813                                          const DWARFYAML::LoclistEntry &Entry,
    814                                          uint8_t AddrSize,
    815                                          bool IsLittleEndian) {
    816   uint64_t BeginOffset = OS.tell();
    817   writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);
    818 
    819   StringRef EncodingName = dwarf::LocListEncodingString(Entry.Operator);
    820 
    821   auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
    822     return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
    823   };
    824 
    825   auto WriteAddress = [&](uint64_t Addr) -> Error {
    826     return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
    827                                  IsLittleEndian);
    828   };
    829 
    830   auto WriteDWARFOperations = [&]() -> Error {
    831     std::string OpBuffer;
    832     raw_string_ostream OpBufferOS(OpBuffer);
    833     uint64_t DescriptionsLength = 0;
    834 
    835     for (const DWARFYAML::DWARFOperation &Op : Entry.Descriptions) {
    836       if (Expected<uint64_t> OpSize =
    837               writeDWARFExpression(OpBufferOS, Op, AddrSize, IsLittleEndian))
    838         DescriptionsLength += *OpSize;
    839       else
    840         return OpSize.takeError();
    841     }
    842 
    843     if (Entry.DescriptionsLength)
    844       DescriptionsLength = *Entry.DescriptionsLength;
    845     else
    846       DescriptionsLength = OpBuffer.size();
    847 
    848     encodeULEB128(DescriptionsLength, OS);
    849     OS.write(OpBuffer.data(), OpBuffer.size());
    850 
    851     return Error::success();
    852   };
    853 
    854   switch (Entry.Operator) {
    855   case dwarf::DW_LLE_end_of_list:
    856     if (Error Err = CheckOperands(0))
    857       return std::move(Err);
    858     break;
    859   case dwarf::DW_LLE_base_addressx:
    860     if (Error Err = CheckOperands(1))
    861       return std::move(Err);
    862     encodeULEB128(Entry.Values[0], OS);
    863     break;
    864   case dwarf::DW_LLE_startx_endx:
    865   case dwarf::DW_LLE_startx_length:
    866   case dwarf::DW_LLE_offset_pair:
    867     if (Error Err = CheckOperands(2))
    868       return std::move(Err);
    869     encodeULEB128(Entry.Values[0], OS);
    870     encodeULEB128(Entry.Values[1], OS);
    871     if (Error Err = WriteDWARFOperations())
    872       return std::move(Err);
    873     break;
    874   case dwarf::DW_LLE_default_location:
    875     if (Error Err = CheckOperands(0))
    876       return std::move(Err);
    877     if (Error Err = WriteDWARFOperations())
    878       return std::move(Err);
    879     break;
    880   case dwarf::DW_LLE_base_address:
    881     if (Error Err = CheckOperands(1))
    882       return std::move(Err);
    883     if (Error Err = WriteAddress(Entry.Values[0]))
    884       return std::move(Err);
    885     break;
    886   case dwarf::DW_LLE_start_end:
    887     if (Error Err = CheckOperands(2))
    888       return std::move(Err);
    889     if (Error Err = WriteAddress(Entry.Values[0]))
    890       return std::move(Err);
    891     cantFail(WriteAddress(Entry.Values[1]));
    892     if (Error Err = WriteDWARFOperations())
    893       return std::move(Err);
    894     break;
    895   case dwarf::DW_LLE_start_length:
    896     if (Error Err = CheckOperands(2))
    897       return std::move(Err);
    898     if (Error Err = WriteAddress(Entry.Values[0]))
    899       return std::move(Err);
    900     encodeULEB128(Entry.Values[1], OS);
    901     if (Error Err = WriteDWARFOperations())
    902       return std::move(Err);
    903     break;
    904   }
    905 
    906   return OS.tell() - BeginOffset;
    907 }
    908 
    909 template <typename EntryType>
    910 static Error writeDWARFLists(raw_ostream &OS,
    911                              ArrayRef<DWARFYAML::ListTable<EntryType>> Tables,
    912                              bool IsLittleEndian, bool Is64BitAddrSize) {
    913   for (const DWARFYAML::ListTable<EntryType> &Table : Tables) {
    914     // sizeof(version) + sizeof(address_size) + sizeof(segment_selector_size) +
    915     // sizeof(offset_entry_count) = 8
    916     uint64_t Length = 8;
    917 
    918     uint8_t AddrSize;
    919     if (Table.AddrSize)
    920       AddrSize = *Table.AddrSize;
    921     else
    922       AddrSize = Is64BitAddrSize ? 8 : 4;
    923 
    924     // Since the length of the current range/location lists entry is
    925     // undetermined yet, we firstly write the content of the range/location
    926     // lists to a buffer to calculate the length and then serialize the buffer
    927     // content to the actual output stream.
    928     std::string ListBuffer;
    929     raw_string_ostream ListBufferOS(ListBuffer);
    930 
    931     // Offsets holds offsets for each range/location list. The i-th element is
    932     // the offset from the beginning of the first range/location list to the
    933     // location of the i-th range list.
    934     std::vector<uint64_t> Offsets;
    935 
    936     for (const DWARFYAML::ListEntries<EntryType> &List : Table.Lists) {
    937       Offsets.push_back(ListBufferOS.tell());
    938       if (List.Content) {
    939         List.Content->writeAsBinary(ListBufferOS, UINT64_MAX);
    940         Length += List.Content->binary_size();
    941       } else if (List.Entries) {
    942         for (const EntryType &Entry : *List.Entries) {
    943           Expected<uint64_t> EntrySize =
    944               writeListEntry(ListBufferOS, Entry, AddrSize, IsLittleEndian);
    945           if (!EntrySize)
    946             return EntrySize.takeError();
    947           Length += *EntrySize;
    948         }
    949       }
    950     }
    951 
    952     // If the offset_entry_count field isn't specified, yaml2obj will infer it
    953     // from the 'Offsets' field in the YAML description. If the 'Offsets' field
    954     // isn't specified either, yaml2obj will infer it from the auto-generated
    955     // offsets.
    956     uint32_t OffsetEntryCount;
    957     if (Table.OffsetEntryCount)
    958       OffsetEntryCount = *Table.OffsetEntryCount;
    959     else
    960       OffsetEntryCount = Table.Offsets ? Table.Offsets->size() : Offsets.size();
    961     uint64_t OffsetsSize =
    962         OffsetEntryCount * (Table.Format == dwarf::DWARF64 ? 8 : 4);
    963     Length += OffsetsSize;
    964 
    965     // If the length is specified in the YAML description, we use it instead of
    966     // the actual length.
    967     if (Table.Length)
    968       Length = *Table.Length;
    969 
    970     writeInitialLength(Table.Format, Length, OS, IsLittleEndian);
    971     writeInteger((uint16_t)Table.Version, OS, IsLittleEndian);
    972     writeInteger((uint8_t)AddrSize, OS, IsLittleEndian);
    973     writeInteger((uint8_t)Table.SegSelectorSize, OS, IsLittleEndian);
    974     writeInteger((uint32_t)OffsetEntryCount, OS, IsLittleEndian);
    975 
    976     auto EmitOffsets = [&](ArrayRef<uint64_t> Offsets, uint64_t OffsetsSize) {
    977       for (uint64_t Offset : Offsets)
    978         writeDWARFOffset(OffsetsSize + Offset, Table.Format, OS,
    979                          IsLittleEndian);
    980     };
    981 
    982     if (Table.Offsets)
    983       EmitOffsets(ArrayRef<uint64_t>((const uint64_t *)Table.Offsets->data(),
    984                                      Table.Offsets->size()),
    985                   0);
    986     else if (OffsetEntryCount != 0)
    987       EmitOffsets(Offsets, OffsetsSize);
    988 
    989     OS.write(ListBuffer.data(), ListBuffer.size());
    990   }
    991 
    992   return Error::success();
    993 }
    994 
    995 Error DWARFYAML::emitDebugRnglists(raw_ostream &OS, const Data &DI) {
    996   assert(DI.DebugRnglists && "unexpected emitDebugRnglists() call");
    997   return writeDWARFLists<DWARFYAML::RnglistEntry>(
    998       OS, *DI.DebugRnglists, DI.IsLittleEndian, DI.Is64BitAddrSize);
    999 }
   1000 
   1001 Error DWARFYAML::emitDebugLoclists(raw_ostream &OS, const Data &DI) {
   1002   assert(DI.DebugLoclists && "unexpected emitDebugRnglists() call");
   1003   return writeDWARFLists<DWARFYAML::LoclistEntry>(
   1004       OS, *DI.DebugLoclists, DI.IsLittleEndian, DI.Is64BitAddrSize);
   1005 }
   1006 
   1007 std::function<Error(raw_ostream &, const DWARFYAML::Data &)>
   1008 DWARFYAML::getDWARFEmitterByName(StringRef SecName) {
   1009   auto EmitFunc =
   1010       StringSwitch<
   1011           std::function<Error(raw_ostream &, const DWARFYAML::Data &)>>(SecName)
   1012           .Case("debug_abbrev", DWARFYAML::emitDebugAbbrev)
   1013           .Case("debug_addr", DWARFYAML::emitDebugAddr)
   1014           .Case("debug_aranges", DWARFYAML::emitDebugAranges)
   1015           .Case("debug_gnu_pubnames", DWARFYAML::emitDebugGNUPubnames)
   1016           .Case("debug_gnu_pubtypes", DWARFYAML::emitDebugGNUPubtypes)
   1017           .Case("debug_info", DWARFYAML::emitDebugInfo)
   1018           .Case("debug_line", DWARFYAML::emitDebugLine)
   1019           .Case("debug_loclists", DWARFYAML::emitDebugLoclists)
   1020           .Case("debug_pubnames", DWARFYAML::emitDebugPubnames)
   1021           .Case("debug_pubtypes", DWARFYAML::emitDebugPubtypes)
   1022           .Case("debug_ranges", DWARFYAML::emitDebugRanges)
   1023           .Case("debug_rnglists", DWARFYAML::emitDebugRnglists)
   1024           .Case("debug_str", DWARFYAML::emitDebugStr)
   1025           .Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets)
   1026           .Default([&](raw_ostream &, const DWARFYAML::Data &) {
   1027             return createStringError(errc::not_supported,
   1028                                      SecName + " is not supported");
   1029           });
   1030 
   1031   return EmitFunc;
   1032 }
   1033 
   1034 static Error
   1035 emitDebugSectionImpl(const DWARFYAML::Data &DI, StringRef Sec,
   1036                      StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) {
   1037   std::string Data;
   1038   raw_string_ostream DebugInfoStream(Data);
   1039 
   1040   auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Sec);
   1041 
   1042   if (Error Err = EmitFunc(DebugInfoStream, DI))
   1043     return Err;
   1044   DebugInfoStream.flush();
   1045   if (!Data.empty())
   1046     OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data);
   1047 
   1048   return Error::success();
   1049 }
   1050 
   1051 Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
   1052 DWARFYAML::emitDebugSections(StringRef YAMLString, bool IsLittleEndian,
   1053                              bool Is64BitAddrSize) {
   1054   auto CollectDiagnostic = [](const SMDiagnostic &Diag, void *DiagContext) {
   1055     *static_cast<SMDiagnostic *>(DiagContext) = Diag;
   1056   };
   1057 
   1058   SMDiagnostic GeneratedDiag;
   1059   yaml::Input YIn(YAMLString, /*Ctxt=*/nullptr, CollectDiagnostic,
   1060                   &GeneratedDiag);
   1061 
   1062   DWARFYAML::Data DI;
   1063   DI.IsLittleEndian = IsLittleEndian;
   1064   DI.Is64BitAddrSize = Is64BitAddrSize;
   1065 
   1066   YIn >> DI;
   1067   if (YIn.error())
   1068     return createStringError(YIn.error(), GeneratedDiag.getMessage());
   1069 
   1070   StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;
   1071   Error Err = Error::success();
   1072 
   1073   for (StringRef SecName : DI.getNonEmptySectionNames())
   1074     Err = joinErrors(std::move(Err),
   1075                      emitDebugSectionImpl(DI, SecName, DebugSections));
   1076 
   1077   if (Err)
   1078     return std::move(Err);
   1079   return std::move(DebugSections);
   1080 }
   1081