Path: blob/main/contrib/llvm-project/llvm/lib/ObjectYAML/DWARFEmitter.cpp
35233 views
//===- DWARFEmitter - Convert YAML to DWARF binary data -------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// The DWARF component of yaml2obj. Provided as library code for tests.10///11//===----------------------------------------------------------------------===//1213#include "llvm/ObjectYAML/DWARFEmitter.h"14#include "llvm/ADT/ArrayRef.h"15#include "llvm/ADT/StringMap.h"16#include "llvm/ADT/StringRef.h"17#include "llvm/ADT/StringSwitch.h"18#include "llvm/BinaryFormat/Dwarf.h"19#include "llvm/ObjectYAML/DWARFYAML.h"20#include "llvm/Support/Errc.h"21#include "llvm/Support/Error.h"22#include "llvm/Support/LEB128.h"23#include "llvm/Support/MathExtras.h"24#include "llvm/Support/MemoryBuffer.h"25#include "llvm/Support/SourceMgr.h"26#include "llvm/Support/SwapByteOrder.h"27#include "llvm/Support/YAMLTraits.h"28#include "llvm/Support/raw_ostream.h"29#include "llvm/TargetParser/Host.h"30#include <algorithm>31#include <cassert>32#include <cstddef>33#include <cstdint>34#include <memory>35#include <optional>36#include <string>37#include <vector>3839using namespace llvm;4041template <typename T>42static void writeInteger(T Integer, raw_ostream &OS, bool IsLittleEndian) {43if (IsLittleEndian != sys::IsLittleEndianHost)44sys::swapByteOrder(Integer);45OS.write(reinterpret_cast<char *>(&Integer), sizeof(T));46}4748static Error writeVariableSizedInteger(uint64_t Integer, size_t Size,49raw_ostream &OS, bool IsLittleEndian) {50if (8 == Size)51writeInteger((uint64_t)Integer, OS, IsLittleEndian);52else if (4 == Size)53writeInteger((uint32_t)Integer, OS, IsLittleEndian);54else if (2 == Size)55writeInteger((uint16_t)Integer, OS, IsLittleEndian);56else if (1 == Size)57writeInteger((uint8_t)Integer, OS, IsLittleEndian);58else59return createStringError(errc::not_supported,60"invalid integer write size: %zu", Size);6162return Error::success();63}6465static void ZeroFillBytes(raw_ostream &OS, size_t Size) {66std::vector<uint8_t> FillData(Size, 0);67OS.write(reinterpret_cast<char *>(FillData.data()), Size);68}6970static void writeInitialLength(const dwarf::DwarfFormat Format,71const uint64_t Length, raw_ostream &OS,72bool IsLittleEndian) {73bool IsDWARF64 = Format == dwarf::DWARF64;74if (IsDWARF64)75cantFail(writeVariableSizedInteger(dwarf::DW_LENGTH_DWARF64, 4, OS,76IsLittleEndian));77cantFail(78writeVariableSizedInteger(Length, IsDWARF64 ? 8 : 4, OS, IsLittleEndian));79}8081static void writeDWARFOffset(uint64_t Offset, dwarf::DwarfFormat Format,82raw_ostream &OS, bool IsLittleEndian) {83cantFail(writeVariableSizedInteger(Offset, Format == dwarf::DWARF64 ? 8 : 4,84OS, IsLittleEndian));85}8687Error DWARFYAML::emitDebugStr(raw_ostream &OS, const DWARFYAML::Data &DI) {88for (StringRef Str : *DI.DebugStrings) {89OS.write(Str.data(), Str.size());90OS.write('\0');91}9293return Error::success();94}9596StringRef DWARFYAML::Data::getAbbrevTableContentByIndex(uint64_t Index) const {97assert(Index < DebugAbbrev.size() &&98"Index should be less than the size of DebugAbbrev array");99auto It = AbbrevTableContents.find(Index);100if (It != AbbrevTableContents.cend())101return It->second;102103std::string AbbrevTableBuffer;104raw_string_ostream OS(AbbrevTableBuffer);105106uint64_t AbbrevCode = 0;107for (const DWARFYAML::Abbrev &AbbrevDecl : DebugAbbrev[Index].Table) {108AbbrevCode = AbbrevDecl.Code ? (uint64_t)*AbbrevDecl.Code : AbbrevCode + 1;109encodeULEB128(AbbrevCode, OS);110encodeULEB128(AbbrevDecl.Tag, OS);111OS.write(AbbrevDecl.Children);112for (const auto &Attr : AbbrevDecl.Attributes) {113encodeULEB128(Attr.Attribute, OS);114encodeULEB128(Attr.Form, OS);115if (Attr.Form == dwarf::DW_FORM_implicit_const)116encodeSLEB128(Attr.Value, OS);117}118encodeULEB128(0, OS);119encodeULEB128(0, OS);120}121122// The abbreviations for a given compilation unit end with an entry123// consisting of a 0 byte for the abbreviation code.124OS.write_zeros(1);125126AbbrevTableContents.insert({Index, AbbrevTableBuffer});127128return AbbrevTableContents[Index];129}130131Error DWARFYAML::emitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) {132for (uint64_t I = 0; I < DI.DebugAbbrev.size(); ++I) {133StringRef AbbrevTableContent = DI.getAbbrevTableContentByIndex(I);134OS.write(AbbrevTableContent.data(), AbbrevTableContent.size());135}136137return Error::success();138}139140Error DWARFYAML::emitDebugAranges(raw_ostream &OS, const DWARFYAML::Data &DI) {141assert(DI.DebugAranges && "unexpected emitDebugAranges() call");142for (const auto &Range : *DI.DebugAranges) {143uint8_t AddrSize;144if (Range.AddrSize)145AddrSize = *Range.AddrSize;146else147AddrSize = DI.Is64BitAddrSize ? 8 : 4;148149uint64_t Length = 4; // sizeof(version) 2 + sizeof(address_size) 1 +150// sizeof(segment_selector_size) 1151Length +=152Range.Format == dwarf::DWARF64 ? 8 : 4; // sizeof(debug_info_offset)153154const uint64_t HeaderLength =155Length + (Range.Format == dwarf::DWARF64156? 12157: 4); // sizeof(unit_header) = 12 (DWARF64) or 4 (DWARF32)158const uint64_t PaddedHeaderLength = alignTo(HeaderLength, AddrSize * 2);159160if (Range.Length) {161Length = *Range.Length;162} else {163Length += PaddedHeaderLength - HeaderLength;164Length += AddrSize * 2 * (Range.Descriptors.size() + 1);165}166167writeInitialLength(Range.Format, Length, OS, DI.IsLittleEndian);168writeInteger((uint16_t)Range.Version, OS, DI.IsLittleEndian);169writeDWARFOffset(Range.CuOffset, Range.Format, OS, DI.IsLittleEndian);170writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);171writeInteger((uint8_t)Range.SegSize, OS, DI.IsLittleEndian);172ZeroFillBytes(OS, PaddedHeaderLength - HeaderLength);173174for (const auto &Descriptor : Range.Descriptors) {175if (Error Err = writeVariableSizedInteger(Descriptor.Address, AddrSize,176OS, DI.IsLittleEndian))177return createStringError(errc::not_supported,178"unable to write debug_aranges address: %s",179toString(std::move(Err)).c_str());180cantFail(writeVariableSizedInteger(Descriptor.Length, AddrSize, OS,181DI.IsLittleEndian));182}183ZeroFillBytes(OS, AddrSize * 2);184}185186return Error::success();187}188189Error DWARFYAML::emitDebugRanges(raw_ostream &OS, const DWARFYAML::Data &DI) {190const size_t RangesOffset = OS.tell();191uint64_t EntryIndex = 0;192for (const auto &DebugRanges : *DI.DebugRanges) {193const size_t CurrOffset = OS.tell() - RangesOffset;194if (DebugRanges.Offset && (uint64_t)*DebugRanges.Offset < CurrOffset)195return createStringError(errc::invalid_argument,196"'Offset' for 'debug_ranges' with index " +197Twine(EntryIndex) +198" must be greater than or equal to the "199"number of bytes written already (0x" +200Twine::utohexstr(CurrOffset) + ")");201if (DebugRanges.Offset)202ZeroFillBytes(OS, *DebugRanges.Offset - CurrOffset);203204uint8_t AddrSize;205if (DebugRanges.AddrSize)206AddrSize = *DebugRanges.AddrSize;207else208AddrSize = DI.Is64BitAddrSize ? 8 : 4;209for (const auto &Entry : DebugRanges.Entries) {210if (Error Err = writeVariableSizedInteger(Entry.LowOffset, AddrSize, OS,211DI.IsLittleEndian))212return createStringError(213errc::not_supported,214"unable to write debug_ranges address offset: %s",215toString(std::move(Err)).c_str());216cantFail(writeVariableSizedInteger(Entry.HighOffset, AddrSize, OS,217DI.IsLittleEndian));218}219ZeroFillBytes(OS, AddrSize * 2);220++EntryIndex;221}222223return Error::success();224}225226static Error emitPubSection(raw_ostream &OS, const DWARFYAML::PubSection &Sect,227bool IsLittleEndian, bool IsGNUPubSec = false) {228writeInitialLength(Sect.Format, Sect.Length, OS, IsLittleEndian);229writeInteger((uint16_t)Sect.Version, OS, IsLittleEndian);230writeInteger((uint32_t)Sect.UnitOffset, OS, IsLittleEndian);231writeInteger((uint32_t)Sect.UnitSize, OS, IsLittleEndian);232for (const auto &Entry : Sect.Entries) {233writeInteger((uint32_t)Entry.DieOffset, OS, IsLittleEndian);234if (IsGNUPubSec)235writeInteger((uint8_t)Entry.Descriptor, OS, IsLittleEndian);236OS.write(Entry.Name.data(), Entry.Name.size());237OS.write('\0');238}239return Error::success();240}241242Error DWARFYAML::emitDebugPubnames(raw_ostream &OS, const Data &DI) {243assert(DI.PubNames && "unexpected emitDebugPubnames() call");244return emitPubSection(OS, *DI.PubNames, DI.IsLittleEndian);245}246247Error DWARFYAML::emitDebugPubtypes(raw_ostream &OS, const Data &DI) {248assert(DI.PubTypes && "unexpected emitDebugPubtypes() call");249return emitPubSection(OS, *DI.PubTypes, DI.IsLittleEndian);250}251252Error DWARFYAML::emitDebugGNUPubnames(raw_ostream &OS, const Data &DI) {253assert(DI.GNUPubNames && "unexpected emitDebugGNUPubnames() call");254return emitPubSection(OS, *DI.GNUPubNames, DI.IsLittleEndian,255/*IsGNUStyle=*/true);256}257258Error DWARFYAML::emitDebugGNUPubtypes(raw_ostream &OS, const Data &DI) {259assert(DI.GNUPubTypes && "unexpected emitDebugGNUPubtypes() call");260return emitPubSection(OS, *DI.GNUPubTypes, DI.IsLittleEndian,261/*IsGNUStyle=*/true);262}263264static Expected<uint64_t> writeDIE(const DWARFYAML::Data &DI, uint64_t CUIndex,265uint64_t AbbrevTableID,266const dwarf::FormParams &Params,267const DWARFYAML::Entry &Entry,268raw_ostream &OS, bool IsLittleEndian) {269uint64_t EntryBegin = OS.tell();270encodeULEB128(Entry.AbbrCode, OS);271uint32_t AbbrCode = Entry.AbbrCode;272if (AbbrCode == 0 || Entry.Values.empty())273return OS.tell() - EntryBegin;274275Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =276DI.getAbbrevTableInfoByID(AbbrevTableID);277if (!AbbrevTableInfoOrErr)278return createStringError(errc::invalid_argument,279toString(AbbrevTableInfoOrErr.takeError()) +280" for compilation unit with index " +281utostr(CUIndex));282283ArrayRef<DWARFYAML::Abbrev> AbbrevDecls(284DI.DebugAbbrev[AbbrevTableInfoOrErr->Index].Table);285286if (AbbrCode > AbbrevDecls.size())287return createStringError(288errc::invalid_argument,289"abbrev code must be less than or equal to the number of "290"entries in abbreviation table");291const DWARFYAML::Abbrev &Abbrev = AbbrevDecls[AbbrCode - 1];292auto FormVal = Entry.Values.begin();293auto AbbrForm = Abbrev.Attributes.begin();294for (; FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end();295++FormVal, ++AbbrForm) {296dwarf::Form Form = AbbrForm->Form;297bool Indirect;298do {299Indirect = false;300switch (Form) {301case dwarf::DW_FORM_addr:302// TODO: Test this error.303if (Error Err = writeVariableSizedInteger(304FormVal->Value, Params.AddrSize, OS, IsLittleEndian))305return std::move(Err);306break;307case dwarf::DW_FORM_ref_addr:308// TODO: Test this error.309if (Error Err = writeVariableSizedInteger(FormVal->Value,310Params.getRefAddrByteSize(),311OS, IsLittleEndian))312return std::move(Err);313break;314case dwarf::DW_FORM_exprloc:315case dwarf::DW_FORM_block:316encodeULEB128(FormVal->BlockData.size(), OS);317OS.write((const char *)FormVal->BlockData.data(),318FormVal->BlockData.size());319break;320case dwarf::DW_FORM_block1: {321writeInteger((uint8_t)FormVal->BlockData.size(), OS, IsLittleEndian);322OS.write((const char *)FormVal->BlockData.data(),323FormVal->BlockData.size());324break;325}326case dwarf::DW_FORM_block2: {327writeInteger((uint16_t)FormVal->BlockData.size(), OS, IsLittleEndian);328OS.write((const char *)FormVal->BlockData.data(),329FormVal->BlockData.size());330break;331}332case dwarf::DW_FORM_block4: {333writeInteger((uint32_t)FormVal->BlockData.size(), OS, IsLittleEndian);334OS.write((const char *)FormVal->BlockData.data(),335FormVal->BlockData.size());336break;337}338case dwarf::DW_FORM_strx:339case dwarf::DW_FORM_addrx:340case dwarf::DW_FORM_rnglistx:341case dwarf::DW_FORM_loclistx:342case dwarf::DW_FORM_udata:343case dwarf::DW_FORM_ref_udata:344case dwarf::DW_FORM_GNU_addr_index:345case dwarf::DW_FORM_GNU_str_index:346encodeULEB128(FormVal->Value, OS);347break;348case dwarf::DW_FORM_data1:349case dwarf::DW_FORM_ref1:350case dwarf::DW_FORM_flag:351case dwarf::DW_FORM_strx1:352case dwarf::DW_FORM_addrx1:353writeInteger((uint8_t)FormVal->Value, OS, IsLittleEndian);354break;355case dwarf::DW_FORM_data2:356case dwarf::DW_FORM_ref2:357case dwarf::DW_FORM_strx2:358case dwarf::DW_FORM_addrx2:359writeInteger((uint16_t)FormVal->Value, OS, IsLittleEndian);360break;361case dwarf::DW_FORM_data4:362case dwarf::DW_FORM_ref4:363case dwarf::DW_FORM_ref_sup4:364case dwarf::DW_FORM_strx4:365case dwarf::DW_FORM_addrx4:366writeInteger((uint32_t)FormVal->Value, OS, IsLittleEndian);367break;368case dwarf::DW_FORM_data8:369case dwarf::DW_FORM_ref8:370case dwarf::DW_FORM_ref_sup8:371case dwarf::DW_FORM_ref_sig8:372writeInteger((uint64_t)FormVal->Value, OS, IsLittleEndian);373break;374case dwarf::DW_FORM_sdata:375encodeSLEB128(FormVal->Value, OS);376break;377case dwarf::DW_FORM_string:378OS.write(FormVal->CStr.data(), FormVal->CStr.size());379OS.write('\0');380break;381case dwarf::DW_FORM_indirect:382encodeULEB128(FormVal->Value, OS);383Indirect = true;384Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value);385++FormVal;386break;387case dwarf::DW_FORM_strp:388case dwarf::DW_FORM_sec_offset:389case dwarf::DW_FORM_GNU_ref_alt:390case dwarf::DW_FORM_GNU_strp_alt:391case dwarf::DW_FORM_line_strp:392case dwarf::DW_FORM_strp_sup:393cantFail(writeVariableSizedInteger(FormVal->Value,394Params.getDwarfOffsetByteSize(), OS,395IsLittleEndian));396break;397default:398break;399}400} while (Indirect);401}402403return OS.tell() - EntryBegin;404}405406Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {407for (uint64_t I = 0; I < DI.CompileUnits.size(); ++I) {408const DWARFYAML::Unit &Unit = DI.CompileUnits[I];409uint8_t AddrSize;410if (Unit.AddrSize)411AddrSize = *Unit.AddrSize;412else413AddrSize = DI.Is64BitAddrSize ? 8 : 4;414dwarf::FormParams Params = {Unit.Version, AddrSize, Unit.Format};415uint64_t Length = 3; // sizeof(version) + sizeof(address_size)416Length += Unit.Version >= 5 ? 1 : 0; // sizeof(unit_type)417Length += Params.getDwarfOffsetByteSize(); // sizeof(debug_abbrev_offset)418419// Since the length of the current compilation unit is undetermined yet, we420// firstly write the content of the compilation unit to a buffer to421// calculate it and then serialize the buffer content to the actual output422// stream.423std::string EntryBuffer;424raw_string_ostream EntryBufferOS(EntryBuffer);425426uint64_t AbbrevTableID = Unit.AbbrevTableID.value_or(I);427for (const DWARFYAML::Entry &Entry : Unit.Entries) {428if (Expected<uint64_t> EntryLength =429writeDIE(DI, I, AbbrevTableID, Params, Entry, EntryBufferOS,430DI.IsLittleEndian))431Length += *EntryLength;432else433return EntryLength.takeError();434}435436// If the length is specified in the YAML description, we use it instead of437// the actual length.438if (Unit.Length)439Length = *Unit.Length;440441writeInitialLength(Unit.Format, Length, OS, DI.IsLittleEndian);442writeInteger((uint16_t)Unit.Version, OS, DI.IsLittleEndian);443444uint64_t AbbrevTableOffset = 0;445if (Unit.AbbrOffset) {446AbbrevTableOffset = *Unit.AbbrOffset;447} else {448if (Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =449DI.getAbbrevTableInfoByID(AbbrevTableID)) {450AbbrevTableOffset = AbbrevTableInfoOrErr->Offset;451} else {452// The current compilation unit may not have DIEs and it will not be453// able to find the associated abbrev table. We consume the error and454// assign 0 to the debug_abbrev_offset in such circumstances.455consumeError(AbbrevTableInfoOrErr.takeError());456}457}458459if (Unit.Version >= 5) {460writeInteger((uint8_t)Unit.Type, OS, DI.IsLittleEndian);461writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);462writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);463} else {464writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);465writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);466}467468OS.write(EntryBuffer.data(), EntryBuffer.size());469}470471return Error::success();472}473474static void emitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) {475OS.write(File.Name.data(), File.Name.size());476OS.write('\0');477encodeULEB128(File.DirIdx, OS);478encodeULEB128(File.ModTime, OS);479encodeULEB128(File.Length, OS);480}481482static void writeExtendedOpcode(const DWARFYAML::LineTableOpcode &Op,483uint8_t AddrSize, bool IsLittleEndian,484raw_ostream &OS) {485// The first byte of extended opcodes is a zero byte. The next bytes are an486// ULEB128 integer giving the number of bytes in the instruction itself (does487// not include the first zero byte or the size). We serialize the instruction488// itself into the OpBuffer and then write the size of the buffer and the489// buffer to the real output stream.490std::string OpBuffer;491raw_string_ostream OpBufferOS(OpBuffer);492writeInteger((uint8_t)Op.SubOpcode, OpBufferOS, IsLittleEndian);493switch (Op.SubOpcode) {494case dwarf::DW_LNE_set_address:495cantFail(writeVariableSizedInteger(Op.Data, AddrSize, OpBufferOS,496IsLittleEndian));497break;498case dwarf::DW_LNE_define_file:499emitFileEntry(OpBufferOS, Op.FileEntry);500break;501case dwarf::DW_LNE_set_discriminator:502encodeULEB128(Op.Data, OpBufferOS);503break;504case dwarf::DW_LNE_end_sequence:505break;506default:507for (auto OpByte : Op.UnknownOpcodeData)508writeInteger((uint8_t)OpByte, OpBufferOS, IsLittleEndian);509}510uint64_t ExtLen = Op.ExtLen.value_or(OpBuffer.size());511encodeULEB128(ExtLen, OS);512OS.write(OpBuffer.data(), OpBuffer.size());513}514515static void writeLineTableOpcode(const DWARFYAML::LineTableOpcode &Op,516uint8_t OpcodeBase, uint8_t AddrSize,517raw_ostream &OS, bool IsLittleEndian) {518writeInteger((uint8_t)Op.Opcode, OS, IsLittleEndian);519if (Op.Opcode == 0) {520writeExtendedOpcode(Op, AddrSize, IsLittleEndian, OS);521} else if (Op.Opcode < OpcodeBase) {522switch (Op.Opcode) {523case dwarf::DW_LNS_copy:524case dwarf::DW_LNS_negate_stmt:525case dwarf::DW_LNS_set_basic_block:526case dwarf::DW_LNS_const_add_pc:527case dwarf::DW_LNS_set_prologue_end:528case dwarf::DW_LNS_set_epilogue_begin:529break;530531case dwarf::DW_LNS_advance_pc:532case dwarf::DW_LNS_set_file:533case dwarf::DW_LNS_set_column:534case dwarf::DW_LNS_set_isa:535encodeULEB128(Op.Data, OS);536break;537538case dwarf::DW_LNS_advance_line:539encodeSLEB128(Op.SData, OS);540break;541542case dwarf::DW_LNS_fixed_advance_pc:543writeInteger((uint16_t)Op.Data, OS, IsLittleEndian);544break;545546default:547for (auto OpData : Op.StandardOpcodeData) {548encodeULEB128(OpData, OS);549}550}551}552}553554static std::vector<uint8_t>555getStandardOpcodeLengths(uint16_t Version, std::optional<uint8_t> OpcodeBase) {556// If the opcode_base field isn't specified, we returns the557// standard_opcode_lengths array according to the version by default.558std::vector<uint8_t> StandardOpcodeLengths{0, 1, 1, 1, 1, 0,5590, 0, 1, 0, 0, 1};560if (Version == 2) {561// DWARF v2 uses the same first 9 standard opcodes as v3-5.562StandardOpcodeLengths.resize(9);563} else if (OpcodeBase) {564StandardOpcodeLengths.resize(*OpcodeBase > 0 ? *OpcodeBase - 1 : 0, 0);565}566return StandardOpcodeLengths;567}568569Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) {570for (const DWARFYAML::LineTable &LineTable : DI.DebugLines) {571// Buffer holds the bytes following the header_length (or prologue_length in572// DWARFv2) field to the end of the line number program itself.573std::string Buffer;574raw_string_ostream BufferOS(Buffer);575576writeInteger(LineTable.MinInstLength, BufferOS, DI.IsLittleEndian);577// TODO: Add support for emitting DWARFv5 line table.578if (LineTable.Version >= 4)579writeInteger(LineTable.MaxOpsPerInst, BufferOS, DI.IsLittleEndian);580writeInteger(LineTable.DefaultIsStmt, BufferOS, DI.IsLittleEndian);581writeInteger(LineTable.LineBase, BufferOS, DI.IsLittleEndian);582writeInteger(LineTable.LineRange, BufferOS, DI.IsLittleEndian);583584std::vector<uint8_t> StandardOpcodeLengths =585LineTable.StandardOpcodeLengths.value_or(586getStandardOpcodeLengths(LineTable.Version, LineTable.OpcodeBase));587uint8_t OpcodeBase = LineTable.OpcodeBase588? *LineTable.OpcodeBase589: StandardOpcodeLengths.size() + 1;590writeInteger(OpcodeBase, BufferOS, DI.IsLittleEndian);591for (uint8_t OpcodeLength : StandardOpcodeLengths)592writeInteger(OpcodeLength, BufferOS, DI.IsLittleEndian);593594for (StringRef IncludeDir : LineTable.IncludeDirs) {595BufferOS.write(IncludeDir.data(), IncludeDir.size());596BufferOS.write('\0');597}598BufferOS.write('\0');599600for (const DWARFYAML::File &File : LineTable.Files)601emitFileEntry(BufferOS, File);602BufferOS.write('\0');603604uint64_t HeaderLength =605LineTable.PrologueLength ? *LineTable.PrologueLength : Buffer.size();606607for (const DWARFYAML::LineTableOpcode &Op : LineTable.Opcodes)608writeLineTableOpcode(Op, OpcodeBase, DI.Is64BitAddrSize ? 8 : 4, BufferOS,609DI.IsLittleEndian);610611uint64_t Length;612if (LineTable.Length) {613Length = *LineTable.Length;614} else {615Length = 2; // sizeof(version)616Length +=617(LineTable.Format == dwarf::DWARF64 ? 8 : 4); // sizeof(header_length)618Length += Buffer.size();619}620621writeInitialLength(LineTable.Format, Length, OS, DI.IsLittleEndian);622writeInteger(LineTable.Version, OS, DI.IsLittleEndian);623writeDWARFOffset(HeaderLength, LineTable.Format, OS, DI.IsLittleEndian);624OS.write(Buffer.data(), Buffer.size());625}626627return Error::success();628}629630Error DWARFYAML::emitDebugAddr(raw_ostream &OS, const Data &DI) {631for (const AddrTableEntry &TableEntry : *DI.DebugAddr) {632uint8_t AddrSize;633if (TableEntry.AddrSize)634AddrSize = *TableEntry.AddrSize;635else636AddrSize = DI.Is64BitAddrSize ? 8 : 4;637638uint64_t Length;639if (TableEntry.Length)640Length = (uint64_t)*TableEntry.Length;641else642// 2 (version) + 1 (address_size) + 1 (segment_selector_size) = 4643Length = 4 + (AddrSize + TableEntry.SegSelectorSize) *644TableEntry.SegAddrPairs.size();645646writeInitialLength(TableEntry.Format, Length, OS, DI.IsLittleEndian);647writeInteger((uint16_t)TableEntry.Version, OS, DI.IsLittleEndian);648writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);649writeInteger((uint8_t)TableEntry.SegSelectorSize, OS, DI.IsLittleEndian);650651for (const SegAddrPair &Pair : TableEntry.SegAddrPairs) {652if (TableEntry.SegSelectorSize != yaml::Hex8{0})653if (Error Err = writeVariableSizedInteger(Pair.Segment,654TableEntry.SegSelectorSize,655OS, DI.IsLittleEndian))656return createStringError(errc::not_supported,657"unable to write debug_addr segment: %s",658toString(std::move(Err)).c_str());659if (AddrSize != 0)660if (Error Err = writeVariableSizedInteger(Pair.Address, AddrSize, OS,661DI.IsLittleEndian))662return createStringError(errc::not_supported,663"unable to write debug_addr address: %s",664toString(std::move(Err)).c_str());665}666}667668return Error::success();669}670671Error DWARFYAML::emitDebugStrOffsets(raw_ostream &OS, const Data &DI) {672assert(DI.DebugStrOffsets && "unexpected emitDebugStrOffsets() call");673for (const DWARFYAML::StringOffsetsTable &Table : *DI.DebugStrOffsets) {674uint64_t Length;675if (Table.Length)676Length = *Table.Length;677else678// sizeof(version) + sizeof(padding) = 4679Length =6804 + Table.Offsets.size() * (Table.Format == dwarf::DWARF64 ? 8 : 4);681682writeInitialLength(Table.Format, Length, OS, DI.IsLittleEndian);683writeInteger((uint16_t)Table.Version, OS, DI.IsLittleEndian);684writeInteger((uint16_t)Table.Padding, OS, DI.IsLittleEndian);685686for (uint64_t Offset : Table.Offsets)687writeDWARFOffset(Offset, Table.Format, OS, DI.IsLittleEndian);688}689690return Error::success();691}692693namespace {694/// Emits the header for a DebugNames section.695void emitDebugNamesHeader(raw_ostream &OS, bool IsLittleEndian,696uint32_t NameCount, uint32_t AbbrevSize,697uint32_t CombinedSizeOtherParts) {698// Use the same AugmentationString as AsmPrinter.699StringRef AugmentationString = "LLVM0700";700size_t TotalSize = CombinedSizeOtherParts + 5 * sizeof(uint32_t) +7012 * sizeof(uint16_t) + sizeof(NameCount) +702sizeof(AbbrevSize) + AugmentationString.size();703writeInteger(uint32_t(TotalSize), OS, IsLittleEndian); // Unit length704705// Everything below is included in total size.706writeInteger(uint16_t(5), OS, IsLittleEndian); // Version707writeInteger(uint16_t(0), OS, IsLittleEndian); // Padding708writeInteger(uint32_t(1), OS, IsLittleEndian); // Compilation Unit count709writeInteger(uint32_t(0), OS, IsLittleEndian); // Local Type Unit count710writeInteger(uint32_t(0), OS, IsLittleEndian); // Foreign Type Unit count711writeInteger(uint32_t(0), OS, IsLittleEndian); // Bucket count712writeInteger(NameCount, OS, IsLittleEndian);713writeInteger(AbbrevSize, OS, IsLittleEndian);714writeInteger(uint32_t(AugmentationString.size()), OS, IsLittleEndian);715OS.write(AugmentationString.data(), AugmentationString.size());716return;717}718719/// Emits the abbreviations for a DebugNames section.720std::string721emitDebugNamesAbbrev(ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {722std::string Data;723raw_string_ostream OS(Data);724for (const DWARFYAML::DebugNameAbbreviation &Abbrev : Abbrevs) {725encodeULEB128(Abbrev.Code, OS);726encodeULEB128(Abbrev.Tag, OS);727for (auto [Idx, Form] : Abbrev.Indices) {728encodeULEB128(Idx, OS);729encodeULEB128(Form, OS);730}731encodeULEB128(0, OS);732encodeULEB128(0, OS);733}734encodeULEB128(0, OS);735return Data;736}737738/// Emits a simple CU offsets list for a DebugNames section containing a single739/// CU at offset 0.740std::string emitDebugNamesCUOffsets(bool IsLittleEndian) {741std::string Data;742raw_string_ostream OS(Data);743writeInteger(uint32_t(0), OS, IsLittleEndian);744return Data;745}746747/// Emits the "NameTable" for a DebugNames section; according to the spec, it748/// consists of two arrays: an array of string offsets, followed immediately by749/// an array of entry offsets. The string offsets are emitted in the order750/// provided in `Entries`.751std::string emitDebugNamesNameTable(752bool IsLittleEndian,753const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> &Entries,754ArrayRef<uint32_t> EntryPoolOffsets) {755assert(Entries.size() == EntryPoolOffsets.size());756757std::string Data;758raw_string_ostream OS(Data);759760for (uint32_t Strp : make_first_range(Entries))761writeInteger(Strp, OS, IsLittleEndian);762for (uint32_t PoolOffset : EntryPoolOffsets)763writeInteger(PoolOffset, OS, IsLittleEndian);764return Data;765}766767/// Groups entries based on their name (strp) code and returns a map.768DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>>769groupEntries(ArrayRef<DWARFYAML::DebugNameEntry> Entries) {770DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> StrpToEntries;771for (const DWARFYAML::DebugNameEntry &Entry : Entries)772StrpToEntries[Entry.NameStrp].push_back(Entry);773return StrpToEntries;774}775776/// Finds the abbreviation whose code is AbbrevCode and returns a list777/// containing the expected size of all non-zero-length forms.778Expected<SmallVector<uint8_t>>779getNonZeroDataSizesFor(uint32_t AbbrevCode,780ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {781const auto *AbbrevIt = find_if(Abbrevs, [&](const auto &Abbrev) {782return Abbrev.Code.value == AbbrevCode;783});784if (AbbrevIt == Abbrevs.end())785return createStringError(inconvertibleErrorCode(),786"did not find an Abbreviation for this code");787788SmallVector<uint8_t> DataSizes;789dwarf::FormParams Params{/*Version=*/5, /*AddrSize=*/4, dwarf::DWARF32};790for (auto [Idx, Form] : AbbrevIt->Indices) {791std::optional<uint8_t> FormSize = dwarf::getFixedFormByteSize(Form, Params);792if (!FormSize)793return createStringError(inconvertibleErrorCode(),794"unsupported Form for YAML debug_names emitter");795if (FormSize == 0)796continue;797DataSizes.push_back(*FormSize);798}799return DataSizes;800}801802struct PoolOffsetsAndData {803std::string PoolData;804std::vector<uint32_t> PoolOffsets;805};806807/// Emits the entry pool and returns an array of offsets containing the start808/// offset for the entries of each unique name.809/// Verifies that the provided number of data values match those expected by810/// the abbreviation table.811Expected<PoolOffsetsAndData> emitDebugNamesEntryPool(812bool IsLittleEndian,813const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>>814&StrpToEntries,815ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {816PoolOffsetsAndData Result;817raw_string_ostream OS(Result.PoolData);818819for (ArrayRef<DWARFYAML::DebugNameEntry> EntriesWithSameName :820make_second_range(StrpToEntries)) {821Result.PoolOffsets.push_back(Result.PoolData.size());822823for (const DWARFYAML::DebugNameEntry &Entry : EntriesWithSameName) {824encodeULEB128(Entry.Code, OS);825826Expected<SmallVector<uint8_t>> DataSizes =827getNonZeroDataSizesFor(Entry.Code, Abbrevs);828if (!DataSizes)829return DataSizes.takeError();830if (DataSizes->size() != Entry.Values.size())831return createStringError(832inconvertibleErrorCode(),833"mismatch between provided and required number of values");834835for (auto [Value, ValueSize] : zip_equal(Entry.Values, *DataSizes))836if (Error E =837writeVariableSizedInteger(Value, ValueSize, OS, IsLittleEndian))838return std::move(E);839}840encodeULEB128(0, OS);841}842843return Result;844}845} // namespace846847Error DWARFYAML::emitDebugNames(raw_ostream &OS, const Data &DI) {848assert(DI.DebugNames && "unexpected emitDebugNames() call");849const DebugNamesSection DebugNames = DI.DebugNames.value();850851DenseMap<uint32_t, std::vector<DebugNameEntry>> StrpToEntries =852groupEntries(DebugNames.Entries);853854// Emit all sub-sections into individual strings so that we may compute855// relative offsets and sizes.856Expected<PoolOffsetsAndData> PoolInfo = emitDebugNamesEntryPool(857DI.IsLittleEndian, StrpToEntries, DebugNames.Abbrevs);858if (!PoolInfo)859return PoolInfo.takeError();860std::string NamesTableData = emitDebugNamesNameTable(861DI.IsLittleEndian, StrpToEntries, PoolInfo->PoolOffsets);862863std::string AbbrevData = emitDebugNamesAbbrev(DebugNames.Abbrevs);864std::string CUOffsetsData = emitDebugNamesCUOffsets(DI.IsLittleEndian);865866size_t TotalSize = PoolInfo->PoolData.size() + NamesTableData.size() +867AbbrevData.size() + CUOffsetsData.size();868869// Start real emission by combining all individual strings.870emitDebugNamesHeader(OS, DI.IsLittleEndian, StrpToEntries.size(),871AbbrevData.size(), TotalSize);872OS.write(CUOffsetsData.data(), CUOffsetsData.size());873// No local TUs, no foreign TUs, no hash lookups table.874OS.write(NamesTableData.data(), NamesTableData.size());875OS.write(AbbrevData.data(), AbbrevData.size());876OS.write(PoolInfo->PoolData.data(), PoolInfo->PoolData.size());877878return Error::success();879}880881static Error checkOperandCount(StringRef EncodingString,882ArrayRef<yaml::Hex64> Values,883uint64_t ExpectedOperands) {884if (Values.size() != ExpectedOperands)885return createStringError(886errc::invalid_argument,887"invalid number (%zu) of operands for the operator: %s, %" PRIu64888" expected",889Values.size(), EncodingString.str().c_str(), ExpectedOperands);890891return Error::success();892}893894static Error writeListEntryAddress(StringRef EncodingName, raw_ostream &OS,895uint64_t Addr, uint8_t AddrSize,896bool IsLittleEndian) {897if (Error Err = writeVariableSizedInteger(Addr, AddrSize, OS, IsLittleEndian))898return createStringError(errc::invalid_argument,899"unable to write address for the operator %s: %s",900EncodingName.str().c_str(),901toString(std::move(Err)).c_str());902903return Error::success();904}905906static Expected<uint64_t>907writeDWARFExpression(raw_ostream &OS,908const DWARFYAML::DWARFOperation &Operation,909uint8_t AddrSize, bool IsLittleEndian) {910auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {911return checkOperandCount(dwarf::OperationEncodingString(Operation.Operator),912Operation.Values, ExpectedOperands);913};914915uint64_t ExpressionBegin = OS.tell();916writeInteger((uint8_t)Operation.Operator, OS, IsLittleEndian);917switch (Operation.Operator) {918case dwarf::DW_OP_consts:919if (Error Err = CheckOperands(1))920return std::move(Err);921encodeSLEB128(Operation.Values[0], OS);922break;923case dwarf::DW_OP_stack_value:924if (Error Err = CheckOperands(0))925return std::move(Err);926break;927default:928StringRef EncodingStr = dwarf::OperationEncodingString(Operation.Operator);929return createStringError(errc::not_supported,930"DWARF expression: " +931(EncodingStr.empty()932? "0x" + utohexstr(Operation.Operator)933: EncodingStr) +934" is not supported");935}936return OS.tell() - ExpressionBegin;937}938939static Expected<uint64_t> writeListEntry(raw_ostream &OS,940const DWARFYAML::RnglistEntry &Entry,941uint8_t AddrSize,942bool IsLittleEndian) {943uint64_t BeginOffset = OS.tell();944writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);945946StringRef EncodingName = dwarf::RangeListEncodingString(Entry.Operator);947948auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {949return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);950};951952auto WriteAddress = [&](uint64_t Addr) -> Error {953return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,954IsLittleEndian);955};956957switch (Entry.Operator) {958case dwarf::DW_RLE_end_of_list:959if (Error Err = CheckOperands(0))960return std::move(Err);961break;962case dwarf::DW_RLE_base_addressx:963if (Error Err = CheckOperands(1))964return std::move(Err);965encodeULEB128(Entry.Values[0], OS);966break;967case dwarf::DW_RLE_startx_endx:968case dwarf::DW_RLE_startx_length:969case dwarf::DW_RLE_offset_pair:970if (Error Err = CheckOperands(2))971return std::move(Err);972encodeULEB128(Entry.Values[0], OS);973encodeULEB128(Entry.Values[1], OS);974break;975case dwarf::DW_RLE_base_address:976if (Error Err = CheckOperands(1))977return std::move(Err);978if (Error Err = WriteAddress(Entry.Values[0]))979return std::move(Err);980break;981case dwarf::DW_RLE_start_end:982if (Error Err = CheckOperands(2))983return std::move(Err);984if (Error Err = WriteAddress(Entry.Values[0]))985return std::move(Err);986cantFail(WriteAddress(Entry.Values[1]));987break;988case dwarf::DW_RLE_start_length:989if (Error Err = CheckOperands(2))990return std::move(Err);991if (Error Err = WriteAddress(Entry.Values[0]))992return std::move(Err);993encodeULEB128(Entry.Values[1], OS);994break;995}996997return OS.tell() - BeginOffset;998}9991000static Expected<uint64_t> writeListEntry(raw_ostream &OS,1001const DWARFYAML::LoclistEntry &Entry,1002uint8_t AddrSize,1003bool IsLittleEndian) {1004uint64_t BeginOffset = OS.tell();1005writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);10061007StringRef EncodingName = dwarf::LocListEncodingString(Entry.Operator);10081009auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {1010return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);1011};10121013auto WriteAddress = [&](uint64_t Addr) -> Error {1014return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,1015IsLittleEndian);1016};10171018auto WriteDWARFOperations = [&]() -> Error {1019std::string OpBuffer;1020raw_string_ostream OpBufferOS(OpBuffer);1021uint64_t DescriptionsLength = 0;10221023for (const DWARFYAML::DWARFOperation &Op : Entry.Descriptions) {1024if (Expected<uint64_t> OpSize =1025writeDWARFExpression(OpBufferOS, Op, AddrSize, IsLittleEndian))1026DescriptionsLength += *OpSize;1027else1028return OpSize.takeError();1029}10301031if (Entry.DescriptionsLength)1032DescriptionsLength = *Entry.DescriptionsLength;1033else1034DescriptionsLength = OpBuffer.size();10351036encodeULEB128(DescriptionsLength, OS);1037OS.write(OpBuffer.data(), OpBuffer.size());10381039return Error::success();1040};10411042switch (Entry.Operator) {1043case dwarf::DW_LLE_end_of_list:1044if (Error Err = CheckOperands(0))1045return std::move(Err);1046break;1047case dwarf::DW_LLE_base_addressx:1048if (Error Err = CheckOperands(1))1049return std::move(Err);1050encodeULEB128(Entry.Values[0], OS);1051break;1052case dwarf::DW_LLE_startx_endx:1053case dwarf::DW_LLE_startx_length:1054case dwarf::DW_LLE_offset_pair:1055if (Error Err = CheckOperands(2))1056return std::move(Err);1057encodeULEB128(Entry.Values[0], OS);1058encodeULEB128(Entry.Values[1], OS);1059if (Error Err = WriteDWARFOperations())1060return std::move(Err);1061break;1062case dwarf::DW_LLE_default_location:1063if (Error Err = CheckOperands(0))1064return std::move(Err);1065if (Error Err = WriteDWARFOperations())1066return std::move(Err);1067break;1068case dwarf::DW_LLE_base_address:1069if (Error Err = CheckOperands(1))1070return std::move(Err);1071if (Error Err = WriteAddress(Entry.Values[0]))1072return std::move(Err);1073break;1074case dwarf::DW_LLE_start_end:1075if (Error Err = CheckOperands(2))1076return std::move(Err);1077if (Error Err = WriteAddress(Entry.Values[0]))1078return std::move(Err);1079cantFail(WriteAddress(Entry.Values[1]));1080if (Error Err = WriteDWARFOperations())1081return std::move(Err);1082break;1083case dwarf::DW_LLE_start_length:1084if (Error Err = CheckOperands(2))1085return std::move(Err);1086if (Error Err = WriteAddress(Entry.Values[0]))1087return std::move(Err);1088encodeULEB128(Entry.Values[1], OS);1089if (Error Err = WriteDWARFOperations())1090return std::move(Err);1091break;1092}10931094return OS.tell() - BeginOffset;1095}10961097template <typename EntryType>1098static Error writeDWARFLists(raw_ostream &OS,1099ArrayRef<DWARFYAML::ListTable<EntryType>> Tables,1100bool IsLittleEndian, bool Is64BitAddrSize) {1101for (const DWARFYAML::ListTable<EntryType> &Table : Tables) {1102// sizeof(version) + sizeof(address_size) + sizeof(segment_selector_size) +1103// sizeof(offset_entry_count) = 81104uint64_t Length = 8;11051106uint8_t AddrSize;1107if (Table.AddrSize)1108AddrSize = *Table.AddrSize;1109else1110AddrSize = Is64BitAddrSize ? 8 : 4;11111112// Since the length of the current range/location lists entry is1113// undetermined yet, we firstly write the content of the range/location1114// lists to a buffer to calculate the length and then serialize the buffer1115// content to the actual output stream.1116std::string ListBuffer;1117raw_string_ostream ListBufferOS(ListBuffer);11181119// Offsets holds offsets for each range/location list. The i-th element is1120// the offset from the beginning of the first range/location list to the1121// location of the i-th range list.1122std::vector<uint64_t> Offsets;11231124for (const DWARFYAML::ListEntries<EntryType> &List : Table.Lists) {1125Offsets.push_back(ListBufferOS.tell());1126if (List.Content) {1127List.Content->writeAsBinary(ListBufferOS, UINT64_MAX);1128Length += List.Content->binary_size();1129} else if (List.Entries) {1130for (const EntryType &Entry : *List.Entries) {1131Expected<uint64_t> EntrySize =1132writeListEntry(ListBufferOS, Entry, AddrSize, IsLittleEndian);1133if (!EntrySize)1134return EntrySize.takeError();1135Length += *EntrySize;1136}1137}1138}11391140// If the offset_entry_count field isn't specified, yaml2obj will infer it1141// from the 'Offsets' field in the YAML description. If the 'Offsets' field1142// isn't specified either, yaml2obj will infer it from the auto-generated1143// offsets.1144uint32_t OffsetEntryCount;1145if (Table.OffsetEntryCount)1146OffsetEntryCount = *Table.OffsetEntryCount;1147else1148OffsetEntryCount = Table.Offsets ? Table.Offsets->size() : Offsets.size();1149uint64_t OffsetsSize =1150OffsetEntryCount * (Table.Format == dwarf::DWARF64 ? 8 : 4);1151Length += OffsetsSize;11521153// If the length is specified in the YAML description, we use it instead of1154// the actual length.1155if (Table.Length)1156Length = *Table.Length;11571158writeInitialLength(Table.Format, Length, OS, IsLittleEndian);1159writeInteger((uint16_t)Table.Version, OS, IsLittleEndian);1160writeInteger((uint8_t)AddrSize, OS, IsLittleEndian);1161writeInteger((uint8_t)Table.SegSelectorSize, OS, IsLittleEndian);1162writeInteger((uint32_t)OffsetEntryCount, OS, IsLittleEndian);11631164auto EmitOffsets = [&](ArrayRef<uint64_t> Offsets, uint64_t OffsetsSize) {1165for (uint64_t Offset : Offsets)1166writeDWARFOffset(OffsetsSize + Offset, Table.Format, OS,1167IsLittleEndian);1168};11691170if (Table.Offsets)1171EmitOffsets(ArrayRef<uint64_t>((const uint64_t *)Table.Offsets->data(),1172Table.Offsets->size()),11730);1174else if (OffsetEntryCount != 0)1175EmitOffsets(Offsets, OffsetsSize);11761177OS.write(ListBuffer.data(), ListBuffer.size());1178}11791180return Error::success();1181}11821183Error DWARFYAML::emitDebugRnglists(raw_ostream &OS, const Data &DI) {1184assert(DI.DebugRnglists && "unexpected emitDebugRnglists() call");1185return writeDWARFLists<DWARFYAML::RnglistEntry>(1186OS, *DI.DebugRnglists, DI.IsLittleEndian, DI.Is64BitAddrSize);1187}11881189Error DWARFYAML::emitDebugLoclists(raw_ostream &OS, const Data &DI) {1190assert(DI.DebugLoclists && "unexpected emitDebugRnglists() call");1191return writeDWARFLists<DWARFYAML::LoclistEntry>(1192OS, *DI.DebugLoclists, DI.IsLittleEndian, DI.Is64BitAddrSize);1193}11941195std::function<Error(raw_ostream &, const DWARFYAML::Data &)>1196DWARFYAML::getDWARFEmitterByName(StringRef SecName) {1197auto EmitFunc =1198StringSwitch<1199std::function<Error(raw_ostream &, const DWARFYAML::Data &)>>(SecName)1200.Case("debug_abbrev", DWARFYAML::emitDebugAbbrev)1201.Case("debug_addr", DWARFYAML::emitDebugAddr)1202.Case("debug_aranges", DWARFYAML::emitDebugAranges)1203.Case("debug_gnu_pubnames", DWARFYAML::emitDebugGNUPubnames)1204.Case("debug_gnu_pubtypes", DWARFYAML::emitDebugGNUPubtypes)1205.Case("debug_info", DWARFYAML::emitDebugInfo)1206.Case("debug_line", DWARFYAML::emitDebugLine)1207.Case("debug_loclists", DWARFYAML::emitDebugLoclists)1208.Case("debug_pubnames", DWARFYAML::emitDebugPubnames)1209.Case("debug_pubtypes", DWARFYAML::emitDebugPubtypes)1210.Case("debug_ranges", DWARFYAML::emitDebugRanges)1211.Case("debug_rnglists", DWARFYAML::emitDebugRnglists)1212.Case("debug_str", DWARFYAML::emitDebugStr)1213.Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets)1214.Case("debug_names", DWARFYAML::emitDebugNames)1215.Default([&](raw_ostream &, const DWARFYAML::Data &) {1216return createStringError(errc::not_supported,1217SecName + " is not supported");1218});12191220return EmitFunc;1221}12221223static Error1224emitDebugSectionImpl(const DWARFYAML::Data &DI, StringRef Sec,1225StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) {1226std::string Data;1227raw_string_ostream DebugInfoStream(Data);12281229auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Sec);12301231if (Error Err = EmitFunc(DebugInfoStream, DI))1232return Err;1233DebugInfoStream.flush();1234if (!Data.empty())1235OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data);12361237return Error::success();1238}12391240Expected<StringMap<std::unique_ptr<MemoryBuffer>>>1241DWARFYAML::emitDebugSections(StringRef YAMLString, bool IsLittleEndian,1242bool Is64BitAddrSize) {1243auto CollectDiagnostic = [](const SMDiagnostic &Diag, void *DiagContext) {1244*static_cast<SMDiagnostic *>(DiagContext) = Diag;1245};12461247SMDiagnostic GeneratedDiag;1248yaml::Input YIn(YAMLString, /*Ctxt=*/nullptr, CollectDiagnostic,1249&GeneratedDiag);12501251DWARFYAML::Data DI;1252DI.IsLittleEndian = IsLittleEndian;1253DI.Is64BitAddrSize = Is64BitAddrSize;12541255YIn >> DI;1256if (YIn.error())1257return createStringError(YIn.error(), GeneratedDiag.getMessage());12581259StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;1260Error Err = Error::success();12611262for (StringRef SecName : DI.getNonEmptySectionNames())1263Err = joinErrors(std::move(Err),1264emitDebugSectionImpl(DI, SecName, DebugSections));12651266if (Err)1267return std::move(Err);1268return std::move(DebugSections);1269}127012711272