10b57cec5SDimitry Andric //===- DWARFEmitter - Convert YAML to DWARF binary data -------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// The DWARF component of yaml2obj. Provided as library code for tests. 110b57cec5SDimitry Andric /// 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "llvm/ObjectYAML/DWARFEmitter.h" 15e8d8bef9SDimitry Andric #include "llvm/ADT/ArrayRef.h" 160b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h" 170b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 18e8d8bef9SDimitry Andric #include "llvm/ADT/StringSwitch.h" 195ffd83dbSDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 200b57cec5SDimitry Andric #include "llvm/ObjectYAML/DWARFYAML.h" 215ffd83dbSDimitry Andric #include "llvm/Support/Errc.h" 220b57cec5SDimitry Andric #include "llvm/Support/Error.h" 230b57cec5SDimitry Andric #include "llvm/Support/LEB128.h" 240b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 250b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 265ffd83dbSDimitry Andric #include "llvm/Support/SourceMgr.h" 270b57cec5SDimitry Andric #include "llvm/Support/SwapByteOrder.h" 280b57cec5SDimitry Andric #include "llvm/Support/YAMLTraits.h" 290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 3006c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h" 310b57cec5SDimitry Andric #include <algorithm> 320b57cec5SDimitry Andric #include <cassert> 330b57cec5SDimitry Andric #include <cstddef> 340b57cec5SDimitry Andric #include <cstdint> 350b57cec5SDimitry Andric #include <memory> 36bdd1243dSDimitry Andric #include <optional> 370b57cec5SDimitry Andric #include <string> 380b57cec5SDimitry Andric #include <vector> 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric using namespace llvm; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric template <typename T> 430b57cec5SDimitry Andric static void writeInteger(T Integer, raw_ostream &OS, bool IsLittleEndian) { 440b57cec5SDimitry Andric if (IsLittleEndian != sys::IsLittleEndianHost) 450b57cec5SDimitry Andric sys::swapByteOrder(Integer); 460b57cec5SDimitry Andric OS.write(reinterpret_cast<char *>(&Integer), sizeof(T)); 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric 495ffd83dbSDimitry Andric static Error writeVariableSizedInteger(uint64_t Integer, size_t Size, 500b57cec5SDimitry Andric raw_ostream &OS, bool IsLittleEndian) { 510b57cec5SDimitry Andric if (8 == Size) 520b57cec5SDimitry Andric writeInteger((uint64_t)Integer, OS, IsLittleEndian); 530b57cec5SDimitry Andric else if (4 == Size) 540b57cec5SDimitry Andric writeInteger((uint32_t)Integer, OS, IsLittleEndian); 550b57cec5SDimitry Andric else if (2 == Size) 560b57cec5SDimitry Andric writeInteger((uint16_t)Integer, OS, IsLittleEndian); 570b57cec5SDimitry Andric else if (1 == Size) 580b57cec5SDimitry Andric writeInteger((uint8_t)Integer, OS, IsLittleEndian); 590b57cec5SDimitry Andric else 605ffd83dbSDimitry Andric return createStringError(errc::not_supported, 615ffd83dbSDimitry Andric "invalid integer write size: %zu", Size); 625ffd83dbSDimitry Andric 635ffd83dbSDimitry Andric return Error::success(); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric static void ZeroFillBytes(raw_ostream &OS, size_t Size) { 67e8d8bef9SDimitry Andric std::vector<uint8_t> FillData(Size, 0); 680b57cec5SDimitry Andric OS.write(reinterpret_cast<char *>(FillData.data()), Size); 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 715ffd83dbSDimitry Andric static void writeInitialLength(const dwarf::DwarfFormat Format, 725ffd83dbSDimitry Andric const uint64_t Length, raw_ostream &OS, 735ffd83dbSDimitry Andric bool IsLittleEndian) { 745ffd83dbSDimitry Andric bool IsDWARF64 = Format == dwarf::DWARF64; 755ffd83dbSDimitry Andric if (IsDWARF64) 765ffd83dbSDimitry Andric cantFail(writeVariableSizedInteger(dwarf::DW_LENGTH_DWARF64, 4, OS, 775ffd83dbSDimitry Andric IsLittleEndian)); 785ffd83dbSDimitry Andric cantFail( 795ffd83dbSDimitry Andric writeVariableSizedInteger(Length, IsDWARF64 ? 8 : 4, OS, IsLittleEndian)); 805ffd83dbSDimitry Andric } 815ffd83dbSDimitry Andric 82e8d8bef9SDimitry Andric static void writeDWARFOffset(uint64_t Offset, dwarf::DwarfFormat Format, 83e8d8bef9SDimitry Andric raw_ostream &OS, bool IsLittleEndian) { 84e8d8bef9SDimitry Andric cantFail(writeVariableSizedInteger(Offset, Format == dwarf::DWARF64 ? 8 : 4, 85e8d8bef9SDimitry Andric OS, IsLittleEndian)); 86e8d8bef9SDimitry Andric } 87e8d8bef9SDimitry Andric 885ffd83dbSDimitry Andric Error DWARFYAML::emitDebugStr(raw_ostream &OS, const DWARFYAML::Data &DI) { 89e8d8bef9SDimitry Andric for (StringRef Str : *DI.DebugStrings) { 900b57cec5SDimitry Andric OS.write(Str.data(), Str.size()); 910b57cec5SDimitry Andric OS.write('\0'); 920b57cec5SDimitry Andric } 935ffd83dbSDimitry Andric 945ffd83dbSDimitry Andric return Error::success(); 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 97e8d8bef9SDimitry Andric StringRef DWARFYAML::Data::getAbbrevTableContentByIndex(uint64_t Index) const { 98e8d8bef9SDimitry Andric assert(Index < DebugAbbrev.size() && 99e8d8bef9SDimitry Andric "Index should be less than the size of DebugAbbrev array"); 100e8d8bef9SDimitry Andric auto It = AbbrevTableContents.find(Index); 101e8d8bef9SDimitry Andric if (It != AbbrevTableContents.cend()) 102e8d8bef9SDimitry Andric return It->second; 103e8d8bef9SDimitry Andric 104e8d8bef9SDimitry Andric std::string AbbrevTableBuffer; 105e8d8bef9SDimitry Andric raw_string_ostream OS(AbbrevTableBuffer); 106e8d8bef9SDimitry Andric 1075ffd83dbSDimitry Andric uint64_t AbbrevCode = 0; 108e8d8bef9SDimitry Andric for (const DWARFYAML::Abbrev &AbbrevDecl : DebugAbbrev[Index].Table) { 1095ffd83dbSDimitry Andric AbbrevCode = AbbrevDecl.Code ? (uint64_t)*AbbrevDecl.Code : AbbrevCode + 1; 1105ffd83dbSDimitry Andric encodeULEB128(AbbrevCode, OS); 1110b57cec5SDimitry Andric encodeULEB128(AbbrevDecl.Tag, OS); 1120b57cec5SDimitry Andric OS.write(AbbrevDecl.Children); 113e8d8bef9SDimitry Andric for (const auto &Attr : AbbrevDecl.Attributes) { 1140b57cec5SDimitry Andric encodeULEB128(Attr.Attribute, OS); 1150b57cec5SDimitry Andric encodeULEB128(Attr.Form, OS); 1160b57cec5SDimitry Andric if (Attr.Form == dwarf::DW_FORM_implicit_const) 1170b57cec5SDimitry Andric encodeSLEB128(Attr.Value, OS); 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric encodeULEB128(0, OS); 1200b57cec5SDimitry Andric encodeULEB128(0, OS); 1210b57cec5SDimitry Andric } 1225ffd83dbSDimitry Andric 123e8d8bef9SDimitry Andric // The abbreviations for a given compilation unit end with an entry 124e8d8bef9SDimitry Andric // consisting of a 0 byte for the abbreviation code. 1255ffd83dbSDimitry Andric OS.write_zeros(1); 1265ffd83dbSDimitry Andric 127e8d8bef9SDimitry Andric AbbrevTableContents.insert({Index, AbbrevTableBuffer}); 128e8d8bef9SDimitry Andric 129e8d8bef9SDimitry Andric return AbbrevTableContents[Index]; 130e8d8bef9SDimitry Andric } 131e8d8bef9SDimitry Andric 132e8d8bef9SDimitry Andric Error DWARFYAML::emitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) { 133e8d8bef9SDimitry Andric for (uint64_t I = 0; I < DI.DebugAbbrev.size(); ++I) { 134e8d8bef9SDimitry Andric StringRef AbbrevTableContent = DI.getAbbrevTableContentByIndex(I); 135e8d8bef9SDimitry Andric OS.write(AbbrevTableContent.data(), AbbrevTableContent.size()); 136e8d8bef9SDimitry Andric } 137e8d8bef9SDimitry Andric 1385ffd83dbSDimitry Andric return Error::success(); 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1415ffd83dbSDimitry Andric Error DWARFYAML::emitDebugAranges(raw_ostream &OS, const DWARFYAML::Data &DI) { 142e8d8bef9SDimitry Andric assert(DI.DebugAranges && "unexpected emitDebugAranges() call"); 143e8d8bef9SDimitry Andric for (const auto &Range : *DI.DebugAranges) { 144e8d8bef9SDimitry Andric uint8_t AddrSize; 145e8d8bef9SDimitry Andric if (Range.AddrSize) 146e8d8bef9SDimitry Andric AddrSize = *Range.AddrSize; 1475ffd83dbSDimitry Andric else 148e8d8bef9SDimitry Andric AddrSize = DI.Is64BitAddrSize ? 8 : 4; 149e8d8bef9SDimitry Andric 150e8d8bef9SDimitry Andric uint64_t Length = 4; // sizeof(version) 2 + sizeof(address_size) 1 + 151e8d8bef9SDimitry Andric // sizeof(segment_selector_size) 1 152e8d8bef9SDimitry Andric Length += 153e8d8bef9SDimitry Andric Range.Format == dwarf::DWARF64 ? 8 : 4; // sizeof(debug_info_offset) 154e8d8bef9SDimitry Andric 155e8d8bef9SDimitry Andric const uint64_t HeaderLength = 156e8d8bef9SDimitry Andric Length + (Range.Format == dwarf::DWARF64 157e8d8bef9SDimitry Andric ? 12 158e8d8bef9SDimitry Andric : 4); // sizeof(unit_header) = 12 (DWARF64) or 4 (DWARF32) 159e8d8bef9SDimitry Andric const uint64_t PaddedHeaderLength = alignTo(HeaderLength, AddrSize * 2); 160e8d8bef9SDimitry Andric 161e8d8bef9SDimitry Andric if (Range.Length) { 162e8d8bef9SDimitry Andric Length = *Range.Length; 163e8d8bef9SDimitry Andric } else { 164e8d8bef9SDimitry Andric Length += PaddedHeaderLength - HeaderLength; 165e8d8bef9SDimitry Andric Length += AddrSize * 2 * (Range.Descriptors.size() + 1); 166e8d8bef9SDimitry Andric } 167e8d8bef9SDimitry Andric 168e8d8bef9SDimitry Andric writeInitialLength(Range.Format, Length, OS, DI.IsLittleEndian); 169e8d8bef9SDimitry Andric writeInteger((uint16_t)Range.Version, OS, DI.IsLittleEndian); 170e8d8bef9SDimitry Andric writeDWARFOffset(Range.CuOffset, Range.Format, OS, DI.IsLittleEndian); 171e8d8bef9SDimitry Andric writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian); 1720b57cec5SDimitry Andric writeInteger((uint8_t)Range.SegSize, OS, DI.IsLittleEndian); 173e8d8bef9SDimitry Andric ZeroFillBytes(OS, PaddedHeaderLength - HeaderLength); 1740b57cec5SDimitry Andric 175e8d8bef9SDimitry Andric for (const auto &Descriptor : Range.Descriptors) { 176e8d8bef9SDimitry Andric if (Error Err = writeVariableSizedInteger(Descriptor.Address, AddrSize, 177e8d8bef9SDimitry Andric OS, DI.IsLittleEndian)) 1785ffd83dbSDimitry Andric return createStringError(errc::not_supported, 1795ffd83dbSDimitry Andric "unable to write debug_aranges address: %s", 1805ffd83dbSDimitry Andric toString(std::move(Err)).c_str()); 181e8d8bef9SDimitry Andric cantFail(writeVariableSizedInteger(Descriptor.Length, AddrSize, OS, 1825ffd83dbSDimitry Andric DI.IsLittleEndian)); 1830b57cec5SDimitry Andric } 184e8d8bef9SDimitry Andric ZeroFillBytes(OS, AddrSize * 2); 1850b57cec5SDimitry Andric } 1865ffd83dbSDimitry Andric 1875ffd83dbSDimitry Andric return Error::success(); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1905ffd83dbSDimitry Andric Error DWARFYAML::emitDebugRanges(raw_ostream &OS, const DWARFYAML::Data &DI) { 1915ffd83dbSDimitry Andric const size_t RangesOffset = OS.tell(); 1925ffd83dbSDimitry Andric uint64_t EntryIndex = 0; 193e8d8bef9SDimitry Andric for (const auto &DebugRanges : *DI.DebugRanges) { 1945ffd83dbSDimitry Andric const size_t CurrOffset = OS.tell() - RangesOffset; 1955ffd83dbSDimitry Andric if (DebugRanges.Offset && (uint64_t)*DebugRanges.Offset < CurrOffset) 1965ffd83dbSDimitry Andric return createStringError(errc::invalid_argument, 1975ffd83dbSDimitry Andric "'Offset' for 'debug_ranges' with index " + 1985ffd83dbSDimitry Andric Twine(EntryIndex) + 1995ffd83dbSDimitry Andric " must be greater than or equal to the " 2005ffd83dbSDimitry Andric "number of bytes written already (0x" + 2015ffd83dbSDimitry Andric Twine::utohexstr(CurrOffset) + ")"); 2025ffd83dbSDimitry Andric if (DebugRanges.Offset) 2035ffd83dbSDimitry Andric ZeroFillBytes(OS, *DebugRanges.Offset - CurrOffset); 2045ffd83dbSDimitry Andric 2055ffd83dbSDimitry Andric uint8_t AddrSize; 2065ffd83dbSDimitry Andric if (DebugRanges.AddrSize) 2075ffd83dbSDimitry Andric AddrSize = *DebugRanges.AddrSize; 2085ffd83dbSDimitry Andric else 2095ffd83dbSDimitry Andric AddrSize = DI.Is64BitAddrSize ? 8 : 4; 210e8d8bef9SDimitry Andric for (const auto &Entry : DebugRanges.Entries) { 2115ffd83dbSDimitry Andric if (Error Err = writeVariableSizedInteger(Entry.LowOffset, AddrSize, OS, 2125ffd83dbSDimitry Andric DI.IsLittleEndian)) 2135ffd83dbSDimitry Andric return createStringError( 2145ffd83dbSDimitry Andric errc::not_supported, 2155ffd83dbSDimitry Andric "unable to write debug_ranges address offset: %s", 2165ffd83dbSDimitry Andric toString(std::move(Err)).c_str()); 2175ffd83dbSDimitry Andric cantFail(writeVariableSizedInteger(Entry.HighOffset, AddrSize, OS, 2185ffd83dbSDimitry Andric DI.IsLittleEndian)); 2195ffd83dbSDimitry Andric } 2205ffd83dbSDimitry Andric ZeroFillBytes(OS, AddrSize * 2); 2215ffd83dbSDimitry Andric ++EntryIndex; 2225ffd83dbSDimitry Andric } 2235ffd83dbSDimitry Andric 2245ffd83dbSDimitry Andric return Error::success(); 2255ffd83dbSDimitry Andric } 2265ffd83dbSDimitry Andric 227e8d8bef9SDimitry Andric static Error emitPubSection(raw_ostream &OS, const DWARFYAML::PubSection &Sect, 228e8d8bef9SDimitry Andric bool IsLittleEndian, bool IsGNUPubSec = false) { 229e8d8bef9SDimitry Andric writeInitialLength(Sect.Format, Sect.Length, OS, IsLittleEndian); 2300b57cec5SDimitry Andric writeInteger((uint16_t)Sect.Version, OS, IsLittleEndian); 2310b57cec5SDimitry Andric writeInteger((uint32_t)Sect.UnitOffset, OS, IsLittleEndian); 2320b57cec5SDimitry Andric writeInteger((uint32_t)Sect.UnitSize, OS, IsLittleEndian); 233e8d8bef9SDimitry Andric for (const auto &Entry : Sect.Entries) { 2340b57cec5SDimitry Andric writeInteger((uint32_t)Entry.DieOffset, OS, IsLittleEndian); 2355ffd83dbSDimitry Andric if (IsGNUPubSec) 2365ffd83dbSDimitry Andric writeInteger((uint8_t)Entry.Descriptor, OS, IsLittleEndian); 2370b57cec5SDimitry Andric OS.write(Entry.Name.data(), Entry.Name.size()); 2380b57cec5SDimitry Andric OS.write('\0'); 2390b57cec5SDimitry Andric } 2405ffd83dbSDimitry Andric return Error::success(); 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 243e8d8bef9SDimitry Andric Error DWARFYAML::emitDebugPubnames(raw_ostream &OS, const Data &DI) { 244e8d8bef9SDimitry Andric assert(DI.PubNames && "unexpected emitDebugPubnames() call"); 245e8d8bef9SDimitry Andric return emitPubSection(OS, *DI.PubNames, DI.IsLittleEndian); 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric 248e8d8bef9SDimitry Andric Error DWARFYAML::emitDebugPubtypes(raw_ostream &OS, const Data &DI) { 249e8d8bef9SDimitry Andric assert(DI.PubTypes && "unexpected emitDebugPubtypes() call"); 250e8d8bef9SDimitry Andric return emitPubSection(OS, *DI.PubTypes, DI.IsLittleEndian); 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric 253e8d8bef9SDimitry Andric Error DWARFYAML::emitDebugGNUPubnames(raw_ostream &OS, const Data &DI) { 254e8d8bef9SDimitry Andric assert(DI.GNUPubNames && "unexpected emitDebugGNUPubnames() call"); 255e8d8bef9SDimitry Andric return emitPubSection(OS, *DI.GNUPubNames, DI.IsLittleEndian, 256e8d8bef9SDimitry Andric /*IsGNUStyle=*/true); 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric 259e8d8bef9SDimitry Andric Error DWARFYAML::emitDebugGNUPubtypes(raw_ostream &OS, const Data &DI) { 260e8d8bef9SDimitry Andric assert(DI.GNUPubTypes && "unexpected emitDebugGNUPubtypes() call"); 261e8d8bef9SDimitry Andric return emitPubSection(OS, *DI.GNUPubTypes, DI.IsLittleEndian, 262e8d8bef9SDimitry Andric /*IsGNUStyle=*/true); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 265e8d8bef9SDimitry Andric static Expected<uint64_t> writeDIE(const DWARFYAML::Data &DI, uint64_t CUIndex, 266e8d8bef9SDimitry Andric uint64_t AbbrevTableID, 267e8d8bef9SDimitry Andric const dwarf::FormParams &Params, 268e8d8bef9SDimitry Andric const DWARFYAML::Entry &Entry, 269e8d8bef9SDimitry Andric raw_ostream &OS, bool IsLittleEndian) { 270e8d8bef9SDimitry Andric uint64_t EntryBegin = OS.tell(); 271e8d8bef9SDimitry Andric encodeULEB128(Entry.AbbrCode, OS); 272e8d8bef9SDimitry Andric uint32_t AbbrCode = Entry.AbbrCode; 273e8d8bef9SDimitry Andric if (AbbrCode == 0 || Entry.Values.empty()) 274e8d8bef9SDimitry Andric return OS.tell() - EntryBegin; 2750b57cec5SDimitry Andric 276e8d8bef9SDimitry Andric Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr = 277e8d8bef9SDimitry Andric DI.getAbbrevTableInfoByID(AbbrevTableID); 278e8d8bef9SDimitry Andric if (!AbbrevTableInfoOrErr) 279e8d8bef9SDimitry Andric return createStringError(errc::invalid_argument, 280e8d8bef9SDimitry Andric toString(AbbrevTableInfoOrErr.takeError()) + 281e8d8bef9SDimitry Andric " for compilation unit with index " + 282e8d8bef9SDimitry Andric utostr(CUIndex)); 2830b57cec5SDimitry Andric 284e8d8bef9SDimitry Andric ArrayRef<DWARFYAML::Abbrev> AbbrevDecls( 285e8d8bef9SDimitry Andric DI.DebugAbbrev[AbbrevTableInfoOrErr->Index].Table); 2860b57cec5SDimitry Andric 287e8d8bef9SDimitry Andric if (AbbrCode > AbbrevDecls.size()) 288e8d8bef9SDimitry Andric return createStringError( 289e8d8bef9SDimitry Andric errc::invalid_argument, 290e8d8bef9SDimitry Andric "abbrev code must be less than or equal to the number of " 291e8d8bef9SDimitry Andric "entries in abbreviation table"); 292e8d8bef9SDimitry Andric const DWARFYAML::Abbrev &Abbrev = AbbrevDecls[AbbrCode - 1]; 293e8d8bef9SDimitry Andric auto FormVal = Entry.Values.begin(); 294e8d8bef9SDimitry Andric auto AbbrForm = Abbrev.Attributes.begin(); 295e8d8bef9SDimitry Andric for (; FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end(); 296e8d8bef9SDimitry Andric ++FormVal, ++AbbrForm) { 297e8d8bef9SDimitry Andric dwarf::Form Form = AbbrForm->Form; 298e8d8bef9SDimitry Andric bool Indirect; 299e8d8bef9SDimitry Andric do { 300e8d8bef9SDimitry Andric Indirect = false; 301e8d8bef9SDimitry Andric switch (Form) { 302e8d8bef9SDimitry Andric case dwarf::DW_FORM_addr: 303e8d8bef9SDimitry Andric // TODO: Test this error. 304e8d8bef9SDimitry Andric if (Error Err = writeVariableSizedInteger( 305e8d8bef9SDimitry Andric FormVal->Value, Params.AddrSize, OS, IsLittleEndian)) 306e8d8bef9SDimitry Andric return std::move(Err); 307e8d8bef9SDimitry Andric break; 308e8d8bef9SDimitry Andric case dwarf::DW_FORM_ref_addr: 309e8d8bef9SDimitry Andric // TODO: Test this error. 310e8d8bef9SDimitry Andric if (Error Err = writeVariableSizedInteger(FormVal->Value, 311e8d8bef9SDimitry Andric Params.getRefAddrByteSize(), 312e8d8bef9SDimitry Andric OS, IsLittleEndian)) 313e8d8bef9SDimitry Andric return std::move(Err); 314e8d8bef9SDimitry Andric break; 315e8d8bef9SDimitry Andric case dwarf::DW_FORM_exprloc: 316e8d8bef9SDimitry Andric case dwarf::DW_FORM_block: 317e8d8bef9SDimitry Andric encodeULEB128(FormVal->BlockData.size(), OS); 318e8d8bef9SDimitry Andric OS.write((const char *)FormVal->BlockData.data(), 319e8d8bef9SDimitry Andric FormVal->BlockData.size()); 320e8d8bef9SDimitry Andric break; 321e8d8bef9SDimitry Andric case dwarf::DW_FORM_block1: { 322e8d8bef9SDimitry Andric writeInteger((uint8_t)FormVal->BlockData.size(), OS, IsLittleEndian); 323e8d8bef9SDimitry Andric OS.write((const char *)FormVal->BlockData.data(), 324e8d8bef9SDimitry Andric FormVal->BlockData.size()); 325e8d8bef9SDimitry Andric break; 326e8d8bef9SDimitry Andric } 327e8d8bef9SDimitry Andric case dwarf::DW_FORM_block2: { 328e8d8bef9SDimitry Andric writeInteger((uint16_t)FormVal->BlockData.size(), OS, IsLittleEndian); 329e8d8bef9SDimitry Andric OS.write((const char *)FormVal->BlockData.data(), 330e8d8bef9SDimitry Andric FormVal->BlockData.size()); 331e8d8bef9SDimitry Andric break; 332e8d8bef9SDimitry Andric } 333e8d8bef9SDimitry Andric case dwarf::DW_FORM_block4: { 334e8d8bef9SDimitry Andric writeInteger((uint32_t)FormVal->BlockData.size(), OS, IsLittleEndian); 335e8d8bef9SDimitry Andric OS.write((const char *)FormVal->BlockData.data(), 336e8d8bef9SDimitry Andric FormVal->BlockData.size()); 337e8d8bef9SDimitry Andric break; 338e8d8bef9SDimitry Andric } 339e8d8bef9SDimitry Andric case dwarf::DW_FORM_strx: 340e8d8bef9SDimitry Andric case dwarf::DW_FORM_addrx: 341e8d8bef9SDimitry Andric case dwarf::DW_FORM_rnglistx: 342e8d8bef9SDimitry Andric case dwarf::DW_FORM_loclistx: 343e8d8bef9SDimitry Andric case dwarf::DW_FORM_udata: 344e8d8bef9SDimitry Andric case dwarf::DW_FORM_ref_udata: 345e8d8bef9SDimitry Andric case dwarf::DW_FORM_GNU_addr_index: 346e8d8bef9SDimitry Andric case dwarf::DW_FORM_GNU_str_index: 347e8d8bef9SDimitry Andric encodeULEB128(FormVal->Value, OS); 348e8d8bef9SDimitry Andric break; 349e8d8bef9SDimitry Andric case dwarf::DW_FORM_data1: 350e8d8bef9SDimitry Andric case dwarf::DW_FORM_ref1: 351e8d8bef9SDimitry Andric case dwarf::DW_FORM_flag: 352e8d8bef9SDimitry Andric case dwarf::DW_FORM_strx1: 353e8d8bef9SDimitry Andric case dwarf::DW_FORM_addrx1: 354e8d8bef9SDimitry Andric writeInteger((uint8_t)FormVal->Value, OS, IsLittleEndian); 355e8d8bef9SDimitry Andric break; 356e8d8bef9SDimitry Andric case dwarf::DW_FORM_data2: 357e8d8bef9SDimitry Andric case dwarf::DW_FORM_ref2: 358e8d8bef9SDimitry Andric case dwarf::DW_FORM_strx2: 359e8d8bef9SDimitry Andric case dwarf::DW_FORM_addrx2: 360e8d8bef9SDimitry Andric writeInteger((uint16_t)FormVal->Value, OS, IsLittleEndian); 361e8d8bef9SDimitry Andric break; 362e8d8bef9SDimitry Andric case dwarf::DW_FORM_data4: 363e8d8bef9SDimitry Andric case dwarf::DW_FORM_ref4: 364e8d8bef9SDimitry Andric case dwarf::DW_FORM_ref_sup4: 365e8d8bef9SDimitry Andric case dwarf::DW_FORM_strx4: 366e8d8bef9SDimitry Andric case dwarf::DW_FORM_addrx4: 367e8d8bef9SDimitry Andric writeInteger((uint32_t)FormVal->Value, OS, IsLittleEndian); 368e8d8bef9SDimitry Andric break; 369e8d8bef9SDimitry Andric case dwarf::DW_FORM_data8: 370e8d8bef9SDimitry Andric case dwarf::DW_FORM_ref8: 371e8d8bef9SDimitry Andric case dwarf::DW_FORM_ref_sup8: 372e8d8bef9SDimitry Andric case dwarf::DW_FORM_ref_sig8: 373e8d8bef9SDimitry Andric writeInteger((uint64_t)FormVal->Value, OS, IsLittleEndian); 374e8d8bef9SDimitry Andric break; 375e8d8bef9SDimitry Andric case dwarf::DW_FORM_sdata: 376e8d8bef9SDimitry Andric encodeSLEB128(FormVal->Value, OS); 377e8d8bef9SDimitry Andric break; 378e8d8bef9SDimitry Andric case dwarf::DW_FORM_string: 379e8d8bef9SDimitry Andric OS.write(FormVal->CStr.data(), FormVal->CStr.size()); 3800b57cec5SDimitry Andric OS.write('\0'); 381e8d8bef9SDimitry Andric break; 382e8d8bef9SDimitry Andric case dwarf::DW_FORM_indirect: 383e8d8bef9SDimitry Andric encodeULEB128(FormVal->Value, OS); 384e8d8bef9SDimitry Andric Indirect = true; 385e8d8bef9SDimitry Andric Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value); 386e8d8bef9SDimitry Andric ++FormVal; 387e8d8bef9SDimitry Andric break; 388e8d8bef9SDimitry Andric case dwarf::DW_FORM_strp: 389e8d8bef9SDimitry Andric case dwarf::DW_FORM_sec_offset: 390e8d8bef9SDimitry Andric case dwarf::DW_FORM_GNU_ref_alt: 391e8d8bef9SDimitry Andric case dwarf::DW_FORM_GNU_strp_alt: 392e8d8bef9SDimitry Andric case dwarf::DW_FORM_line_strp: 393e8d8bef9SDimitry Andric case dwarf::DW_FORM_strp_sup: 394e8d8bef9SDimitry Andric cantFail(writeVariableSizedInteger(FormVal->Value, 395e8d8bef9SDimitry Andric Params.getDwarfOffsetByteSize(), OS, 396e8d8bef9SDimitry Andric IsLittleEndian)); 397e8d8bef9SDimitry Andric break; 398e8d8bef9SDimitry Andric default: 399e8d8bef9SDimitry Andric break; 400e8d8bef9SDimitry Andric } 401e8d8bef9SDimitry Andric } while (Indirect); 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric 404e8d8bef9SDimitry Andric return OS.tell() - EntryBegin; 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric 4075ffd83dbSDimitry Andric Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) { 408e8d8bef9SDimitry Andric for (uint64_t I = 0; I < DI.CompileUnits.size(); ++I) { 409e8d8bef9SDimitry Andric const DWARFYAML::Unit &Unit = DI.CompileUnits[I]; 410e8d8bef9SDimitry Andric uint8_t AddrSize; 411e8d8bef9SDimitry Andric if (Unit.AddrSize) 412e8d8bef9SDimitry Andric AddrSize = *Unit.AddrSize; 413e8d8bef9SDimitry Andric else 414e8d8bef9SDimitry Andric AddrSize = DI.Is64BitAddrSize ? 8 : 4; 415e8d8bef9SDimitry Andric dwarf::FormParams Params = {Unit.Version, AddrSize, Unit.Format}; 416e8d8bef9SDimitry Andric uint64_t Length = 3; // sizeof(version) + sizeof(address_size) 417e8d8bef9SDimitry Andric Length += Unit.Version >= 5 ? 1 : 0; // sizeof(unit_type) 418e8d8bef9SDimitry Andric Length += Params.getDwarfOffsetByteSize(); // sizeof(debug_abbrev_offset) 419e8d8bef9SDimitry Andric 420e8d8bef9SDimitry Andric // Since the length of the current compilation unit is undetermined yet, we 421e8d8bef9SDimitry Andric // firstly write the content of the compilation unit to a buffer to 422e8d8bef9SDimitry Andric // calculate it and then serialize the buffer content to the actual output 423e8d8bef9SDimitry Andric // stream. 424e8d8bef9SDimitry Andric std::string EntryBuffer; 425e8d8bef9SDimitry Andric raw_string_ostream EntryBufferOS(EntryBuffer); 426e8d8bef9SDimitry Andric 42781ad6265SDimitry Andric uint64_t AbbrevTableID = Unit.AbbrevTableID.value_or(I); 428e8d8bef9SDimitry Andric for (const DWARFYAML::Entry &Entry : Unit.Entries) { 429e8d8bef9SDimitry Andric if (Expected<uint64_t> EntryLength = 430e8d8bef9SDimitry Andric writeDIE(DI, I, AbbrevTableID, Params, Entry, EntryBufferOS, 431e8d8bef9SDimitry Andric DI.IsLittleEndian)) 432e8d8bef9SDimitry Andric Length += *EntryLength; 433e8d8bef9SDimitry Andric else 434e8d8bef9SDimitry Andric return EntryLength.takeError(); 435e8d8bef9SDimitry Andric } 436e8d8bef9SDimitry Andric 437e8d8bef9SDimitry Andric // If the length is specified in the YAML description, we use it instead of 438e8d8bef9SDimitry Andric // the actual length. 439e8d8bef9SDimitry Andric if (Unit.Length) 440e8d8bef9SDimitry Andric Length = *Unit.Length; 441e8d8bef9SDimitry Andric 442e8d8bef9SDimitry Andric writeInitialLength(Unit.Format, Length, OS, DI.IsLittleEndian); 443e8d8bef9SDimitry Andric writeInteger((uint16_t)Unit.Version, OS, DI.IsLittleEndian); 444e8d8bef9SDimitry Andric 445e8d8bef9SDimitry Andric uint64_t AbbrevTableOffset = 0; 446e8d8bef9SDimitry Andric if (Unit.AbbrOffset) { 447e8d8bef9SDimitry Andric AbbrevTableOffset = *Unit.AbbrOffset; 448e8d8bef9SDimitry Andric } else { 449e8d8bef9SDimitry Andric if (Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr = 450e8d8bef9SDimitry Andric DI.getAbbrevTableInfoByID(AbbrevTableID)) { 451e8d8bef9SDimitry Andric AbbrevTableOffset = AbbrevTableInfoOrErr->Offset; 452e8d8bef9SDimitry Andric } else { 453e8d8bef9SDimitry Andric // The current compilation unit may not have DIEs and it will not be 454e8d8bef9SDimitry Andric // able to find the associated abbrev table. We consume the error and 455e8d8bef9SDimitry Andric // assign 0 to the debug_abbrev_offset in such circumstances. 456e8d8bef9SDimitry Andric consumeError(AbbrevTableInfoOrErr.takeError()); 457e8d8bef9SDimitry Andric } 458e8d8bef9SDimitry Andric } 459e8d8bef9SDimitry Andric 460e8d8bef9SDimitry Andric if (Unit.Version >= 5) { 461e8d8bef9SDimitry Andric writeInteger((uint8_t)Unit.Type, OS, DI.IsLittleEndian); 462e8d8bef9SDimitry Andric writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian); 463e8d8bef9SDimitry Andric writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian); 464e8d8bef9SDimitry Andric } else { 465e8d8bef9SDimitry Andric writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian); 466e8d8bef9SDimitry Andric writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian); 467e8d8bef9SDimitry Andric } 468e8d8bef9SDimitry Andric 469e8d8bef9SDimitry Andric OS.write(EntryBuffer.data(), EntryBuffer.size()); 470e8d8bef9SDimitry Andric } 471e8d8bef9SDimitry Andric 472e8d8bef9SDimitry Andric return Error::success(); 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric 4755ffd83dbSDimitry Andric static void emitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) { 4760b57cec5SDimitry Andric OS.write(File.Name.data(), File.Name.size()); 4770b57cec5SDimitry Andric OS.write('\0'); 4780b57cec5SDimitry Andric encodeULEB128(File.DirIdx, OS); 4790b57cec5SDimitry Andric encodeULEB128(File.ModTime, OS); 4800b57cec5SDimitry Andric encodeULEB128(File.Length, OS); 4810b57cec5SDimitry Andric } 4820b57cec5SDimitry Andric 483e8d8bef9SDimitry Andric static void writeExtendedOpcode(const DWARFYAML::LineTableOpcode &Op, 484e8d8bef9SDimitry Andric uint8_t AddrSize, bool IsLittleEndian, 485e8d8bef9SDimitry Andric raw_ostream &OS) { 486e8d8bef9SDimitry Andric // The first byte of extended opcodes is a zero byte. The next bytes are an 487e8d8bef9SDimitry Andric // ULEB128 integer giving the number of bytes in the instruction itself (does 488e8d8bef9SDimitry Andric // not include the first zero byte or the size). We serialize the instruction 489e8d8bef9SDimitry Andric // itself into the OpBuffer and then write the size of the buffer and the 490e8d8bef9SDimitry Andric // buffer to the real output stream. 491e8d8bef9SDimitry Andric std::string OpBuffer; 492e8d8bef9SDimitry Andric raw_string_ostream OpBufferOS(OpBuffer); 493e8d8bef9SDimitry Andric writeInteger((uint8_t)Op.SubOpcode, OpBufferOS, IsLittleEndian); 4940b57cec5SDimitry Andric switch (Op.SubOpcode) { 4950b57cec5SDimitry Andric case dwarf::DW_LNE_set_address: 496e8d8bef9SDimitry Andric cantFail(writeVariableSizedInteger(Op.Data, AddrSize, OpBufferOS, 497e8d8bef9SDimitry Andric IsLittleEndian)); 4980b57cec5SDimitry Andric break; 4990b57cec5SDimitry Andric case dwarf::DW_LNE_define_file: 500e8d8bef9SDimitry Andric emitFileEntry(OpBufferOS, Op.FileEntry); 501e8d8bef9SDimitry Andric break; 502e8d8bef9SDimitry Andric case dwarf::DW_LNE_set_discriminator: 503e8d8bef9SDimitry Andric encodeULEB128(Op.Data, OpBufferOS); 5040b57cec5SDimitry Andric break; 5050b57cec5SDimitry Andric case dwarf::DW_LNE_end_sequence: 5060b57cec5SDimitry Andric break; 5070b57cec5SDimitry Andric default: 5080b57cec5SDimitry Andric for (auto OpByte : Op.UnknownOpcodeData) 509e8d8bef9SDimitry Andric writeInteger((uint8_t)OpByte, OpBufferOS, IsLittleEndian); 5100b57cec5SDimitry Andric } 51181ad6265SDimitry Andric uint64_t ExtLen = Op.ExtLen.value_or(OpBuffer.size()); 512e8d8bef9SDimitry Andric encodeULEB128(ExtLen, OS); 513e8d8bef9SDimitry Andric OS.write(OpBuffer.data(), OpBuffer.size()); 514e8d8bef9SDimitry Andric } 515e8d8bef9SDimitry Andric 516e8d8bef9SDimitry Andric static void writeLineTableOpcode(const DWARFYAML::LineTableOpcode &Op, 517e8d8bef9SDimitry Andric uint8_t OpcodeBase, uint8_t AddrSize, 518e8d8bef9SDimitry Andric raw_ostream &OS, bool IsLittleEndian) { 519e8d8bef9SDimitry Andric writeInteger((uint8_t)Op.Opcode, OS, IsLittleEndian); 520e8d8bef9SDimitry Andric if (Op.Opcode == 0) { 521e8d8bef9SDimitry Andric writeExtendedOpcode(Op, AddrSize, IsLittleEndian, OS); 522e8d8bef9SDimitry Andric } else if (Op.Opcode < OpcodeBase) { 5230b57cec5SDimitry Andric switch (Op.Opcode) { 5240b57cec5SDimitry Andric case dwarf::DW_LNS_copy: 5250b57cec5SDimitry Andric case dwarf::DW_LNS_negate_stmt: 5260b57cec5SDimitry Andric case dwarf::DW_LNS_set_basic_block: 5270b57cec5SDimitry Andric case dwarf::DW_LNS_const_add_pc: 5280b57cec5SDimitry Andric case dwarf::DW_LNS_set_prologue_end: 5290b57cec5SDimitry Andric case dwarf::DW_LNS_set_epilogue_begin: 5300b57cec5SDimitry Andric break; 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric case dwarf::DW_LNS_advance_pc: 5330b57cec5SDimitry Andric case dwarf::DW_LNS_set_file: 5340b57cec5SDimitry Andric case dwarf::DW_LNS_set_column: 5350b57cec5SDimitry Andric case dwarf::DW_LNS_set_isa: 5360b57cec5SDimitry Andric encodeULEB128(Op.Data, OS); 5370b57cec5SDimitry Andric break; 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric case dwarf::DW_LNS_advance_line: 5400b57cec5SDimitry Andric encodeSLEB128(Op.SData, OS); 5410b57cec5SDimitry Andric break; 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andric case dwarf::DW_LNS_fixed_advance_pc: 544e8d8bef9SDimitry Andric writeInteger((uint16_t)Op.Data, OS, IsLittleEndian); 5450b57cec5SDimitry Andric break; 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric default: 5480b57cec5SDimitry Andric for (auto OpData : Op.StandardOpcodeData) { 5490b57cec5SDimitry Andric encodeULEB128(OpData, OS); 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric } 5520b57cec5SDimitry Andric } 5530b57cec5SDimitry Andric } 554e8d8bef9SDimitry Andric 555e8d8bef9SDimitry Andric static std::vector<uint8_t> 556bdd1243dSDimitry Andric getStandardOpcodeLengths(uint16_t Version, std::optional<uint8_t> OpcodeBase) { 557e8d8bef9SDimitry Andric // If the opcode_base field isn't specified, we returns the 558e8d8bef9SDimitry Andric // standard_opcode_lengths array according to the version by default. 559e8d8bef9SDimitry Andric std::vector<uint8_t> StandardOpcodeLengths{0, 1, 1, 1, 1, 0, 560e8d8bef9SDimitry Andric 0, 0, 1, 0, 0, 1}; 561e8d8bef9SDimitry Andric if (Version == 2) { 562e8d8bef9SDimitry Andric // DWARF v2 uses the same first 9 standard opcodes as v3-5. 563e8d8bef9SDimitry Andric StandardOpcodeLengths.resize(9); 564e8d8bef9SDimitry Andric } else if (OpcodeBase) { 565e8d8bef9SDimitry Andric StandardOpcodeLengths.resize(*OpcodeBase > 0 ? *OpcodeBase - 1 : 0, 0); 566e8d8bef9SDimitry Andric } 567e8d8bef9SDimitry Andric return StandardOpcodeLengths; 568e8d8bef9SDimitry Andric } 569e8d8bef9SDimitry Andric 570e8d8bef9SDimitry Andric Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) { 571e8d8bef9SDimitry Andric for (const DWARFYAML::LineTable &LineTable : DI.DebugLines) { 572e8d8bef9SDimitry Andric // Buffer holds the bytes following the header_length (or prologue_length in 573e8d8bef9SDimitry Andric // DWARFv2) field to the end of the line number program itself. 574e8d8bef9SDimitry Andric std::string Buffer; 575e8d8bef9SDimitry Andric raw_string_ostream BufferOS(Buffer); 576e8d8bef9SDimitry Andric 577e8d8bef9SDimitry Andric writeInteger(LineTable.MinInstLength, BufferOS, DI.IsLittleEndian); 578e8d8bef9SDimitry Andric // TODO: Add support for emitting DWARFv5 line table. 579e8d8bef9SDimitry Andric if (LineTable.Version >= 4) 580e8d8bef9SDimitry Andric writeInteger(LineTable.MaxOpsPerInst, BufferOS, DI.IsLittleEndian); 581e8d8bef9SDimitry Andric writeInteger(LineTable.DefaultIsStmt, BufferOS, DI.IsLittleEndian); 582e8d8bef9SDimitry Andric writeInteger(LineTable.LineBase, BufferOS, DI.IsLittleEndian); 583e8d8bef9SDimitry Andric writeInteger(LineTable.LineRange, BufferOS, DI.IsLittleEndian); 584e8d8bef9SDimitry Andric 585e8d8bef9SDimitry Andric std::vector<uint8_t> StandardOpcodeLengths = 58681ad6265SDimitry Andric LineTable.StandardOpcodeLengths.value_or( 587e8d8bef9SDimitry Andric getStandardOpcodeLengths(LineTable.Version, LineTable.OpcodeBase)); 588e8d8bef9SDimitry Andric uint8_t OpcodeBase = LineTable.OpcodeBase 589e8d8bef9SDimitry Andric ? *LineTable.OpcodeBase 590e8d8bef9SDimitry Andric : StandardOpcodeLengths.size() + 1; 591e8d8bef9SDimitry Andric writeInteger(OpcodeBase, BufferOS, DI.IsLittleEndian); 592e8d8bef9SDimitry Andric for (uint8_t OpcodeLength : StandardOpcodeLengths) 593e8d8bef9SDimitry Andric writeInteger(OpcodeLength, BufferOS, DI.IsLittleEndian); 594e8d8bef9SDimitry Andric 595e8d8bef9SDimitry Andric for (StringRef IncludeDir : LineTable.IncludeDirs) { 596e8d8bef9SDimitry Andric BufferOS.write(IncludeDir.data(), IncludeDir.size()); 597e8d8bef9SDimitry Andric BufferOS.write('\0'); 598e8d8bef9SDimitry Andric } 599e8d8bef9SDimitry Andric BufferOS.write('\0'); 600e8d8bef9SDimitry Andric 601e8d8bef9SDimitry Andric for (const DWARFYAML::File &File : LineTable.Files) 602e8d8bef9SDimitry Andric emitFileEntry(BufferOS, File); 603e8d8bef9SDimitry Andric BufferOS.write('\0'); 604e8d8bef9SDimitry Andric 605e8d8bef9SDimitry Andric uint64_t HeaderLength = 606e8d8bef9SDimitry Andric LineTable.PrologueLength ? *LineTable.PrologueLength : Buffer.size(); 607e8d8bef9SDimitry Andric 608e8d8bef9SDimitry Andric for (const DWARFYAML::LineTableOpcode &Op : LineTable.Opcodes) 609e8d8bef9SDimitry Andric writeLineTableOpcode(Op, OpcodeBase, DI.Is64BitAddrSize ? 8 : 4, BufferOS, 610e8d8bef9SDimitry Andric DI.IsLittleEndian); 611e8d8bef9SDimitry Andric 612e8d8bef9SDimitry Andric uint64_t Length; 613e8d8bef9SDimitry Andric if (LineTable.Length) { 614e8d8bef9SDimitry Andric Length = *LineTable.Length; 615e8d8bef9SDimitry Andric } else { 616e8d8bef9SDimitry Andric Length = 2; // sizeof(version) 617e8d8bef9SDimitry Andric Length += 618e8d8bef9SDimitry Andric (LineTable.Format == dwarf::DWARF64 ? 8 : 4); // sizeof(header_length) 619e8d8bef9SDimitry Andric Length += Buffer.size(); 620e8d8bef9SDimitry Andric } 621e8d8bef9SDimitry Andric 622e8d8bef9SDimitry Andric writeInitialLength(LineTable.Format, Length, OS, DI.IsLittleEndian); 623e8d8bef9SDimitry Andric writeInteger(LineTable.Version, OS, DI.IsLittleEndian); 624e8d8bef9SDimitry Andric writeDWARFOffset(HeaderLength, LineTable.Format, OS, DI.IsLittleEndian); 625e8d8bef9SDimitry Andric OS.write(Buffer.data(), Buffer.size()); 6260b57cec5SDimitry Andric } 6275ffd83dbSDimitry Andric 6285ffd83dbSDimitry Andric return Error::success(); 6290b57cec5SDimitry Andric } 6300b57cec5SDimitry Andric 6315ffd83dbSDimitry Andric Error DWARFYAML::emitDebugAddr(raw_ostream &OS, const Data &DI) { 632e8d8bef9SDimitry Andric for (const AddrTableEntry &TableEntry : *DI.DebugAddr) { 6335ffd83dbSDimitry Andric uint8_t AddrSize; 6345ffd83dbSDimitry Andric if (TableEntry.AddrSize) 6355ffd83dbSDimitry Andric AddrSize = *TableEntry.AddrSize; 6365ffd83dbSDimitry Andric else 6375ffd83dbSDimitry Andric AddrSize = DI.Is64BitAddrSize ? 8 : 4; 6380b57cec5SDimitry Andric 6395ffd83dbSDimitry Andric uint64_t Length; 6405ffd83dbSDimitry Andric if (TableEntry.Length) 6415ffd83dbSDimitry Andric Length = (uint64_t)*TableEntry.Length; 6425ffd83dbSDimitry Andric else 6435ffd83dbSDimitry Andric // 2 (version) + 1 (address_size) + 1 (segment_selector_size) = 4 6445ffd83dbSDimitry Andric Length = 4 + (AddrSize + TableEntry.SegSelectorSize) * 6455ffd83dbSDimitry Andric TableEntry.SegAddrPairs.size(); 6465ffd83dbSDimitry Andric 6475ffd83dbSDimitry Andric writeInitialLength(TableEntry.Format, Length, OS, DI.IsLittleEndian); 6485ffd83dbSDimitry Andric writeInteger((uint16_t)TableEntry.Version, OS, DI.IsLittleEndian); 6495ffd83dbSDimitry Andric writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian); 6505ffd83dbSDimitry Andric writeInteger((uint8_t)TableEntry.SegSelectorSize, OS, DI.IsLittleEndian); 6515ffd83dbSDimitry Andric 6525ffd83dbSDimitry Andric for (const SegAddrPair &Pair : TableEntry.SegAddrPairs) { 653e8d8bef9SDimitry Andric if (TableEntry.SegSelectorSize != yaml::Hex8{0}) 6545ffd83dbSDimitry Andric if (Error Err = writeVariableSizedInteger(Pair.Segment, 6555ffd83dbSDimitry Andric TableEntry.SegSelectorSize, 6565ffd83dbSDimitry Andric OS, DI.IsLittleEndian)) 6575ffd83dbSDimitry Andric return createStringError(errc::not_supported, 6585ffd83dbSDimitry Andric "unable to write debug_addr segment: %s", 6595ffd83dbSDimitry Andric toString(std::move(Err)).c_str()); 6605ffd83dbSDimitry Andric if (AddrSize != 0) 6615ffd83dbSDimitry Andric if (Error Err = writeVariableSizedInteger(Pair.Address, AddrSize, OS, 6625ffd83dbSDimitry Andric DI.IsLittleEndian)) 6635ffd83dbSDimitry Andric return createStringError(errc::not_supported, 6645ffd83dbSDimitry Andric "unable to write debug_addr address: %s", 6655ffd83dbSDimitry Andric toString(std::move(Err)).c_str()); 6665ffd83dbSDimitry Andric } 6675ffd83dbSDimitry Andric } 6685ffd83dbSDimitry Andric 6695ffd83dbSDimitry Andric return Error::success(); 6705ffd83dbSDimitry Andric } 6715ffd83dbSDimitry Andric 672e8d8bef9SDimitry Andric Error DWARFYAML::emitDebugStrOffsets(raw_ostream &OS, const Data &DI) { 673e8d8bef9SDimitry Andric assert(DI.DebugStrOffsets && "unexpected emitDebugStrOffsets() call"); 674e8d8bef9SDimitry Andric for (const DWARFYAML::StringOffsetsTable &Table : *DI.DebugStrOffsets) { 675e8d8bef9SDimitry Andric uint64_t Length; 676e8d8bef9SDimitry Andric if (Table.Length) 677e8d8bef9SDimitry Andric Length = *Table.Length; 678e8d8bef9SDimitry Andric else 679e8d8bef9SDimitry Andric // sizeof(version) + sizeof(padding) = 4 680e8d8bef9SDimitry Andric Length = 681e8d8bef9SDimitry Andric 4 + Table.Offsets.size() * (Table.Format == dwarf::DWARF64 ? 8 : 4); 682e8d8bef9SDimitry Andric 683e8d8bef9SDimitry Andric writeInitialLength(Table.Format, Length, OS, DI.IsLittleEndian); 684e8d8bef9SDimitry Andric writeInteger((uint16_t)Table.Version, OS, DI.IsLittleEndian); 685e8d8bef9SDimitry Andric writeInteger((uint16_t)Table.Padding, OS, DI.IsLittleEndian); 686e8d8bef9SDimitry Andric 687e8d8bef9SDimitry Andric for (uint64_t Offset : Table.Offsets) 688e8d8bef9SDimitry Andric writeDWARFOffset(Offset, Table.Format, OS, DI.IsLittleEndian); 689e8d8bef9SDimitry Andric } 690e8d8bef9SDimitry Andric 691e8d8bef9SDimitry Andric return Error::success(); 692e8d8bef9SDimitry Andric } 693e8d8bef9SDimitry Andric 694*0fca6ea1SDimitry Andric namespace { 695*0fca6ea1SDimitry Andric /// Emits the header for a DebugNames section. 696*0fca6ea1SDimitry Andric void emitDebugNamesHeader(raw_ostream &OS, bool IsLittleEndian, 697*0fca6ea1SDimitry Andric uint32_t NameCount, uint32_t AbbrevSize, 698*0fca6ea1SDimitry Andric uint32_t CombinedSizeOtherParts) { 699*0fca6ea1SDimitry Andric // Use the same AugmentationString as AsmPrinter. 700*0fca6ea1SDimitry Andric StringRef AugmentationString = "LLVM0700"; 701*0fca6ea1SDimitry Andric size_t TotalSize = CombinedSizeOtherParts + 5 * sizeof(uint32_t) + 702*0fca6ea1SDimitry Andric 2 * sizeof(uint16_t) + sizeof(NameCount) + 703*0fca6ea1SDimitry Andric sizeof(AbbrevSize) + AugmentationString.size(); 704*0fca6ea1SDimitry Andric writeInteger(uint32_t(TotalSize), OS, IsLittleEndian); // Unit length 705*0fca6ea1SDimitry Andric 706*0fca6ea1SDimitry Andric // Everything below is included in total size. 707*0fca6ea1SDimitry Andric writeInteger(uint16_t(5), OS, IsLittleEndian); // Version 708*0fca6ea1SDimitry Andric writeInteger(uint16_t(0), OS, IsLittleEndian); // Padding 709*0fca6ea1SDimitry Andric writeInteger(uint32_t(1), OS, IsLittleEndian); // Compilation Unit count 710*0fca6ea1SDimitry Andric writeInteger(uint32_t(0), OS, IsLittleEndian); // Local Type Unit count 711*0fca6ea1SDimitry Andric writeInteger(uint32_t(0), OS, IsLittleEndian); // Foreign Type Unit count 712*0fca6ea1SDimitry Andric writeInteger(uint32_t(0), OS, IsLittleEndian); // Bucket count 713*0fca6ea1SDimitry Andric writeInteger(NameCount, OS, IsLittleEndian); 714*0fca6ea1SDimitry Andric writeInteger(AbbrevSize, OS, IsLittleEndian); 715*0fca6ea1SDimitry Andric writeInteger(uint32_t(AugmentationString.size()), OS, IsLittleEndian); 716*0fca6ea1SDimitry Andric OS.write(AugmentationString.data(), AugmentationString.size()); 717*0fca6ea1SDimitry Andric return; 718*0fca6ea1SDimitry Andric } 719*0fca6ea1SDimitry Andric 720*0fca6ea1SDimitry Andric /// Emits the abbreviations for a DebugNames section. 721*0fca6ea1SDimitry Andric std::string 722*0fca6ea1SDimitry Andric emitDebugNamesAbbrev(ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) { 723*0fca6ea1SDimitry Andric std::string Data; 724*0fca6ea1SDimitry Andric raw_string_ostream OS(Data); 725*0fca6ea1SDimitry Andric for (const DWARFYAML::DebugNameAbbreviation &Abbrev : Abbrevs) { 726*0fca6ea1SDimitry Andric encodeULEB128(Abbrev.Code, OS); 727*0fca6ea1SDimitry Andric encodeULEB128(Abbrev.Tag, OS); 728*0fca6ea1SDimitry Andric for (auto [Idx, Form] : Abbrev.Indices) { 729*0fca6ea1SDimitry Andric encodeULEB128(Idx, OS); 730*0fca6ea1SDimitry Andric encodeULEB128(Form, OS); 731*0fca6ea1SDimitry Andric } 732*0fca6ea1SDimitry Andric encodeULEB128(0, OS); 733*0fca6ea1SDimitry Andric encodeULEB128(0, OS); 734*0fca6ea1SDimitry Andric } 735*0fca6ea1SDimitry Andric encodeULEB128(0, OS); 736*0fca6ea1SDimitry Andric return Data; 737*0fca6ea1SDimitry Andric } 738*0fca6ea1SDimitry Andric 739*0fca6ea1SDimitry Andric /// Emits a simple CU offsets list for a DebugNames section containing a single 740*0fca6ea1SDimitry Andric /// CU at offset 0. 741*0fca6ea1SDimitry Andric std::string emitDebugNamesCUOffsets(bool IsLittleEndian) { 742*0fca6ea1SDimitry Andric std::string Data; 743*0fca6ea1SDimitry Andric raw_string_ostream OS(Data); 744*0fca6ea1SDimitry Andric writeInteger(uint32_t(0), OS, IsLittleEndian); 745*0fca6ea1SDimitry Andric return Data; 746*0fca6ea1SDimitry Andric } 747*0fca6ea1SDimitry Andric 748*0fca6ea1SDimitry Andric /// Emits the "NameTable" for a DebugNames section; according to the spec, it 749*0fca6ea1SDimitry Andric /// consists of two arrays: an array of string offsets, followed immediately by 750*0fca6ea1SDimitry Andric /// an array of entry offsets. The string offsets are emitted in the order 751*0fca6ea1SDimitry Andric /// provided in `Entries`. 752*0fca6ea1SDimitry Andric std::string emitDebugNamesNameTable( 753*0fca6ea1SDimitry Andric bool IsLittleEndian, 754*0fca6ea1SDimitry Andric const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> &Entries, 755*0fca6ea1SDimitry Andric ArrayRef<uint32_t> EntryPoolOffsets) { 756*0fca6ea1SDimitry Andric assert(Entries.size() == EntryPoolOffsets.size()); 757*0fca6ea1SDimitry Andric 758*0fca6ea1SDimitry Andric std::string Data; 759*0fca6ea1SDimitry Andric raw_string_ostream OS(Data); 760*0fca6ea1SDimitry Andric 761*0fca6ea1SDimitry Andric for (uint32_t Strp : make_first_range(Entries)) 762*0fca6ea1SDimitry Andric writeInteger(Strp, OS, IsLittleEndian); 763*0fca6ea1SDimitry Andric for (uint32_t PoolOffset : EntryPoolOffsets) 764*0fca6ea1SDimitry Andric writeInteger(PoolOffset, OS, IsLittleEndian); 765*0fca6ea1SDimitry Andric return Data; 766*0fca6ea1SDimitry Andric } 767*0fca6ea1SDimitry Andric 768*0fca6ea1SDimitry Andric /// Groups entries based on their name (strp) code and returns a map. 769*0fca6ea1SDimitry Andric DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> 770*0fca6ea1SDimitry Andric groupEntries(ArrayRef<DWARFYAML::DebugNameEntry> Entries) { 771*0fca6ea1SDimitry Andric DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> StrpToEntries; 772*0fca6ea1SDimitry Andric for (const DWARFYAML::DebugNameEntry &Entry : Entries) 773*0fca6ea1SDimitry Andric StrpToEntries[Entry.NameStrp].push_back(Entry); 774*0fca6ea1SDimitry Andric return StrpToEntries; 775*0fca6ea1SDimitry Andric } 776*0fca6ea1SDimitry Andric 777*0fca6ea1SDimitry Andric /// Finds the abbreviation whose code is AbbrevCode and returns a list 778*0fca6ea1SDimitry Andric /// containing the expected size of all non-zero-length forms. 779*0fca6ea1SDimitry Andric Expected<SmallVector<uint8_t>> 780*0fca6ea1SDimitry Andric getNonZeroDataSizesFor(uint32_t AbbrevCode, 781*0fca6ea1SDimitry Andric ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) { 782*0fca6ea1SDimitry Andric const auto *AbbrevIt = find_if(Abbrevs, [&](const auto &Abbrev) { 783*0fca6ea1SDimitry Andric return Abbrev.Code.value == AbbrevCode; 784*0fca6ea1SDimitry Andric }); 785*0fca6ea1SDimitry Andric if (AbbrevIt == Abbrevs.end()) 786*0fca6ea1SDimitry Andric return createStringError(inconvertibleErrorCode(), 787*0fca6ea1SDimitry Andric "did not find an Abbreviation for this code"); 788*0fca6ea1SDimitry Andric 789*0fca6ea1SDimitry Andric SmallVector<uint8_t> DataSizes; 790*0fca6ea1SDimitry Andric dwarf::FormParams Params{/*Version=*/5, /*AddrSize=*/4, dwarf::DWARF32}; 791*0fca6ea1SDimitry Andric for (auto [Idx, Form] : AbbrevIt->Indices) { 792*0fca6ea1SDimitry Andric std::optional<uint8_t> FormSize = dwarf::getFixedFormByteSize(Form, Params); 793*0fca6ea1SDimitry Andric if (!FormSize) 794*0fca6ea1SDimitry Andric return createStringError(inconvertibleErrorCode(), 795*0fca6ea1SDimitry Andric "unsupported Form for YAML debug_names emitter"); 796*0fca6ea1SDimitry Andric if (FormSize == 0) 797*0fca6ea1SDimitry Andric continue; 798*0fca6ea1SDimitry Andric DataSizes.push_back(*FormSize); 799*0fca6ea1SDimitry Andric } 800*0fca6ea1SDimitry Andric return DataSizes; 801*0fca6ea1SDimitry Andric } 802*0fca6ea1SDimitry Andric 803*0fca6ea1SDimitry Andric struct PoolOffsetsAndData { 804*0fca6ea1SDimitry Andric std::string PoolData; 805*0fca6ea1SDimitry Andric std::vector<uint32_t> PoolOffsets; 806*0fca6ea1SDimitry Andric }; 807*0fca6ea1SDimitry Andric 808*0fca6ea1SDimitry Andric /// Emits the entry pool and returns an array of offsets containing the start 809*0fca6ea1SDimitry Andric /// offset for the entries of each unique name. 810*0fca6ea1SDimitry Andric /// Verifies that the provided number of data values match those expected by 811*0fca6ea1SDimitry Andric /// the abbreviation table. 812*0fca6ea1SDimitry Andric Expected<PoolOffsetsAndData> emitDebugNamesEntryPool( 813*0fca6ea1SDimitry Andric bool IsLittleEndian, 814*0fca6ea1SDimitry Andric const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> 815*0fca6ea1SDimitry Andric &StrpToEntries, 816*0fca6ea1SDimitry Andric ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) { 817*0fca6ea1SDimitry Andric PoolOffsetsAndData Result; 818*0fca6ea1SDimitry Andric raw_string_ostream OS(Result.PoolData); 819*0fca6ea1SDimitry Andric 820*0fca6ea1SDimitry Andric for (ArrayRef<DWARFYAML::DebugNameEntry> EntriesWithSameName : 821*0fca6ea1SDimitry Andric make_second_range(StrpToEntries)) { 822*0fca6ea1SDimitry Andric Result.PoolOffsets.push_back(Result.PoolData.size()); 823*0fca6ea1SDimitry Andric 824*0fca6ea1SDimitry Andric for (const DWARFYAML::DebugNameEntry &Entry : EntriesWithSameName) { 825*0fca6ea1SDimitry Andric encodeULEB128(Entry.Code, OS); 826*0fca6ea1SDimitry Andric 827*0fca6ea1SDimitry Andric Expected<SmallVector<uint8_t>> DataSizes = 828*0fca6ea1SDimitry Andric getNonZeroDataSizesFor(Entry.Code, Abbrevs); 829*0fca6ea1SDimitry Andric if (!DataSizes) 830*0fca6ea1SDimitry Andric return DataSizes.takeError(); 831*0fca6ea1SDimitry Andric if (DataSizes->size() != Entry.Values.size()) 832*0fca6ea1SDimitry Andric return createStringError( 833*0fca6ea1SDimitry Andric inconvertibleErrorCode(), 834*0fca6ea1SDimitry Andric "mismatch between provided and required number of values"); 835*0fca6ea1SDimitry Andric 836*0fca6ea1SDimitry Andric for (auto [Value, ValueSize] : zip_equal(Entry.Values, *DataSizes)) 837*0fca6ea1SDimitry Andric if (Error E = 838*0fca6ea1SDimitry Andric writeVariableSizedInteger(Value, ValueSize, OS, IsLittleEndian)) 839*0fca6ea1SDimitry Andric return std::move(E); 840*0fca6ea1SDimitry Andric } 841*0fca6ea1SDimitry Andric encodeULEB128(0, OS); 842*0fca6ea1SDimitry Andric } 843*0fca6ea1SDimitry Andric 844*0fca6ea1SDimitry Andric return Result; 845*0fca6ea1SDimitry Andric } 846*0fca6ea1SDimitry Andric } // namespace 847*0fca6ea1SDimitry Andric 848*0fca6ea1SDimitry Andric Error DWARFYAML::emitDebugNames(raw_ostream &OS, const Data &DI) { 849*0fca6ea1SDimitry Andric assert(DI.DebugNames && "unexpected emitDebugNames() call"); 850*0fca6ea1SDimitry Andric const DebugNamesSection DebugNames = DI.DebugNames.value(); 851*0fca6ea1SDimitry Andric 852*0fca6ea1SDimitry Andric DenseMap<uint32_t, std::vector<DebugNameEntry>> StrpToEntries = 853*0fca6ea1SDimitry Andric groupEntries(DebugNames.Entries); 854*0fca6ea1SDimitry Andric 855*0fca6ea1SDimitry Andric // Emit all sub-sections into individual strings so that we may compute 856*0fca6ea1SDimitry Andric // relative offsets and sizes. 857*0fca6ea1SDimitry Andric Expected<PoolOffsetsAndData> PoolInfo = emitDebugNamesEntryPool( 858*0fca6ea1SDimitry Andric DI.IsLittleEndian, StrpToEntries, DebugNames.Abbrevs); 859*0fca6ea1SDimitry Andric if (!PoolInfo) 860*0fca6ea1SDimitry Andric return PoolInfo.takeError(); 861*0fca6ea1SDimitry Andric std::string NamesTableData = emitDebugNamesNameTable( 862*0fca6ea1SDimitry Andric DI.IsLittleEndian, StrpToEntries, PoolInfo->PoolOffsets); 863*0fca6ea1SDimitry Andric 864*0fca6ea1SDimitry Andric std::string AbbrevData = emitDebugNamesAbbrev(DebugNames.Abbrevs); 865*0fca6ea1SDimitry Andric std::string CUOffsetsData = emitDebugNamesCUOffsets(DI.IsLittleEndian); 866*0fca6ea1SDimitry Andric 867*0fca6ea1SDimitry Andric size_t TotalSize = PoolInfo->PoolData.size() + NamesTableData.size() + 868*0fca6ea1SDimitry Andric AbbrevData.size() + CUOffsetsData.size(); 869*0fca6ea1SDimitry Andric 870*0fca6ea1SDimitry Andric // Start real emission by combining all individual strings. 871*0fca6ea1SDimitry Andric emitDebugNamesHeader(OS, DI.IsLittleEndian, StrpToEntries.size(), 872*0fca6ea1SDimitry Andric AbbrevData.size(), TotalSize); 873*0fca6ea1SDimitry Andric OS.write(CUOffsetsData.data(), CUOffsetsData.size()); 874*0fca6ea1SDimitry Andric // No local TUs, no foreign TUs, no hash lookups table. 875*0fca6ea1SDimitry Andric OS.write(NamesTableData.data(), NamesTableData.size()); 876*0fca6ea1SDimitry Andric OS.write(AbbrevData.data(), AbbrevData.size()); 877*0fca6ea1SDimitry Andric OS.write(PoolInfo->PoolData.data(), PoolInfo->PoolData.size()); 878*0fca6ea1SDimitry Andric 879*0fca6ea1SDimitry Andric return Error::success(); 880*0fca6ea1SDimitry Andric } 881*0fca6ea1SDimitry Andric 882e8d8bef9SDimitry Andric static Error checkOperandCount(StringRef EncodingString, 883e8d8bef9SDimitry Andric ArrayRef<yaml::Hex64> Values, 884e8d8bef9SDimitry Andric uint64_t ExpectedOperands) { 885e8d8bef9SDimitry Andric if (Values.size() != ExpectedOperands) 886e8d8bef9SDimitry Andric return createStringError( 887e8d8bef9SDimitry Andric errc::invalid_argument, 888e8d8bef9SDimitry Andric "invalid number (%zu) of operands for the operator: %s, %" PRIu64 889e8d8bef9SDimitry Andric " expected", 890e8d8bef9SDimitry Andric Values.size(), EncodingString.str().c_str(), ExpectedOperands); 891e8d8bef9SDimitry Andric 892e8d8bef9SDimitry Andric return Error::success(); 893e8d8bef9SDimitry Andric } 894e8d8bef9SDimitry Andric 895e8d8bef9SDimitry Andric static Error writeListEntryAddress(StringRef EncodingName, raw_ostream &OS, 896e8d8bef9SDimitry Andric uint64_t Addr, uint8_t AddrSize, 897e8d8bef9SDimitry Andric bool IsLittleEndian) { 898e8d8bef9SDimitry Andric if (Error Err = writeVariableSizedInteger(Addr, AddrSize, OS, IsLittleEndian)) 899e8d8bef9SDimitry Andric return createStringError(errc::invalid_argument, 900e8d8bef9SDimitry Andric "unable to write address for the operator %s: %s", 901e8d8bef9SDimitry Andric EncodingName.str().c_str(), 902e8d8bef9SDimitry Andric toString(std::move(Err)).c_str()); 903e8d8bef9SDimitry Andric 904e8d8bef9SDimitry Andric return Error::success(); 905e8d8bef9SDimitry Andric } 906e8d8bef9SDimitry Andric 907e8d8bef9SDimitry Andric static Expected<uint64_t> 908e8d8bef9SDimitry Andric writeDWARFExpression(raw_ostream &OS, 909e8d8bef9SDimitry Andric const DWARFYAML::DWARFOperation &Operation, 910e8d8bef9SDimitry Andric uint8_t AddrSize, bool IsLittleEndian) { 911e8d8bef9SDimitry Andric auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error { 912e8d8bef9SDimitry Andric return checkOperandCount(dwarf::OperationEncodingString(Operation.Operator), 913e8d8bef9SDimitry Andric Operation.Values, ExpectedOperands); 914e8d8bef9SDimitry Andric }; 915e8d8bef9SDimitry Andric 916e8d8bef9SDimitry Andric uint64_t ExpressionBegin = OS.tell(); 917e8d8bef9SDimitry Andric writeInteger((uint8_t)Operation.Operator, OS, IsLittleEndian); 918e8d8bef9SDimitry Andric switch (Operation.Operator) { 919e8d8bef9SDimitry Andric case dwarf::DW_OP_consts: 920e8d8bef9SDimitry Andric if (Error Err = CheckOperands(1)) 921e8d8bef9SDimitry Andric return std::move(Err); 922e8d8bef9SDimitry Andric encodeSLEB128(Operation.Values[0], OS); 923e8d8bef9SDimitry Andric break; 924e8d8bef9SDimitry Andric case dwarf::DW_OP_stack_value: 925e8d8bef9SDimitry Andric if (Error Err = CheckOperands(0)) 926e8d8bef9SDimitry Andric return std::move(Err); 927e8d8bef9SDimitry Andric break; 928e8d8bef9SDimitry Andric default: 929e8d8bef9SDimitry Andric StringRef EncodingStr = dwarf::OperationEncodingString(Operation.Operator); 930e8d8bef9SDimitry Andric return createStringError(errc::not_supported, 931e8d8bef9SDimitry Andric "DWARF expression: " + 932e8d8bef9SDimitry Andric (EncodingStr.empty() 933e8d8bef9SDimitry Andric ? "0x" + utohexstr(Operation.Operator) 934e8d8bef9SDimitry Andric : EncodingStr) + 935e8d8bef9SDimitry Andric " is not supported"); 936e8d8bef9SDimitry Andric } 937e8d8bef9SDimitry Andric return OS.tell() - ExpressionBegin; 938e8d8bef9SDimitry Andric } 939e8d8bef9SDimitry Andric 940e8d8bef9SDimitry Andric static Expected<uint64_t> writeListEntry(raw_ostream &OS, 941e8d8bef9SDimitry Andric const DWARFYAML::RnglistEntry &Entry, 942e8d8bef9SDimitry Andric uint8_t AddrSize, 943e8d8bef9SDimitry Andric bool IsLittleEndian) { 944e8d8bef9SDimitry Andric uint64_t BeginOffset = OS.tell(); 945e8d8bef9SDimitry Andric writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian); 946e8d8bef9SDimitry Andric 947e8d8bef9SDimitry Andric StringRef EncodingName = dwarf::RangeListEncodingString(Entry.Operator); 948e8d8bef9SDimitry Andric 949e8d8bef9SDimitry Andric auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error { 950e8d8bef9SDimitry Andric return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands); 951e8d8bef9SDimitry Andric }; 952e8d8bef9SDimitry Andric 953e8d8bef9SDimitry Andric auto WriteAddress = [&](uint64_t Addr) -> Error { 954e8d8bef9SDimitry Andric return writeListEntryAddress(EncodingName, OS, Addr, AddrSize, 955e8d8bef9SDimitry Andric IsLittleEndian); 956e8d8bef9SDimitry Andric }; 957e8d8bef9SDimitry Andric 958e8d8bef9SDimitry Andric switch (Entry.Operator) { 959e8d8bef9SDimitry Andric case dwarf::DW_RLE_end_of_list: 960e8d8bef9SDimitry Andric if (Error Err = CheckOperands(0)) 961e8d8bef9SDimitry Andric return std::move(Err); 962e8d8bef9SDimitry Andric break; 963e8d8bef9SDimitry Andric case dwarf::DW_RLE_base_addressx: 964e8d8bef9SDimitry Andric if (Error Err = CheckOperands(1)) 965e8d8bef9SDimitry Andric return std::move(Err); 966e8d8bef9SDimitry Andric encodeULEB128(Entry.Values[0], OS); 967e8d8bef9SDimitry Andric break; 968e8d8bef9SDimitry Andric case dwarf::DW_RLE_startx_endx: 969e8d8bef9SDimitry Andric case dwarf::DW_RLE_startx_length: 970e8d8bef9SDimitry Andric case dwarf::DW_RLE_offset_pair: 971e8d8bef9SDimitry Andric if (Error Err = CheckOperands(2)) 972e8d8bef9SDimitry Andric return std::move(Err); 973e8d8bef9SDimitry Andric encodeULEB128(Entry.Values[0], OS); 974e8d8bef9SDimitry Andric encodeULEB128(Entry.Values[1], OS); 975e8d8bef9SDimitry Andric break; 976e8d8bef9SDimitry Andric case dwarf::DW_RLE_base_address: 977e8d8bef9SDimitry Andric if (Error Err = CheckOperands(1)) 978e8d8bef9SDimitry Andric return std::move(Err); 979e8d8bef9SDimitry Andric if (Error Err = WriteAddress(Entry.Values[0])) 980e8d8bef9SDimitry Andric return std::move(Err); 981e8d8bef9SDimitry Andric break; 982e8d8bef9SDimitry Andric case dwarf::DW_RLE_start_end: 983e8d8bef9SDimitry Andric if (Error Err = CheckOperands(2)) 984e8d8bef9SDimitry Andric return std::move(Err); 985e8d8bef9SDimitry Andric if (Error Err = WriteAddress(Entry.Values[0])) 986e8d8bef9SDimitry Andric return std::move(Err); 987e8d8bef9SDimitry Andric cantFail(WriteAddress(Entry.Values[1])); 988e8d8bef9SDimitry Andric break; 989e8d8bef9SDimitry Andric case dwarf::DW_RLE_start_length: 990e8d8bef9SDimitry Andric if (Error Err = CheckOperands(2)) 991e8d8bef9SDimitry Andric return std::move(Err); 992e8d8bef9SDimitry Andric if (Error Err = WriteAddress(Entry.Values[0])) 993e8d8bef9SDimitry Andric return std::move(Err); 994e8d8bef9SDimitry Andric encodeULEB128(Entry.Values[1], OS); 995e8d8bef9SDimitry Andric break; 996e8d8bef9SDimitry Andric } 997e8d8bef9SDimitry Andric 998e8d8bef9SDimitry Andric return OS.tell() - BeginOffset; 999e8d8bef9SDimitry Andric } 1000e8d8bef9SDimitry Andric 1001e8d8bef9SDimitry Andric static Expected<uint64_t> writeListEntry(raw_ostream &OS, 1002e8d8bef9SDimitry Andric const DWARFYAML::LoclistEntry &Entry, 1003e8d8bef9SDimitry Andric uint8_t AddrSize, 1004e8d8bef9SDimitry Andric bool IsLittleEndian) { 1005e8d8bef9SDimitry Andric uint64_t BeginOffset = OS.tell(); 1006e8d8bef9SDimitry Andric writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian); 1007e8d8bef9SDimitry Andric 1008e8d8bef9SDimitry Andric StringRef EncodingName = dwarf::LocListEncodingString(Entry.Operator); 1009e8d8bef9SDimitry Andric 1010e8d8bef9SDimitry Andric auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error { 1011e8d8bef9SDimitry Andric return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands); 1012e8d8bef9SDimitry Andric }; 1013e8d8bef9SDimitry Andric 1014e8d8bef9SDimitry Andric auto WriteAddress = [&](uint64_t Addr) -> Error { 1015e8d8bef9SDimitry Andric return writeListEntryAddress(EncodingName, OS, Addr, AddrSize, 1016e8d8bef9SDimitry Andric IsLittleEndian); 1017e8d8bef9SDimitry Andric }; 1018e8d8bef9SDimitry Andric 1019e8d8bef9SDimitry Andric auto WriteDWARFOperations = [&]() -> Error { 1020e8d8bef9SDimitry Andric std::string OpBuffer; 1021e8d8bef9SDimitry Andric raw_string_ostream OpBufferOS(OpBuffer); 1022e8d8bef9SDimitry Andric uint64_t DescriptionsLength = 0; 1023e8d8bef9SDimitry Andric 1024e8d8bef9SDimitry Andric for (const DWARFYAML::DWARFOperation &Op : Entry.Descriptions) { 1025e8d8bef9SDimitry Andric if (Expected<uint64_t> OpSize = 1026e8d8bef9SDimitry Andric writeDWARFExpression(OpBufferOS, Op, AddrSize, IsLittleEndian)) 1027e8d8bef9SDimitry Andric DescriptionsLength += *OpSize; 1028e8d8bef9SDimitry Andric else 1029e8d8bef9SDimitry Andric return OpSize.takeError(); 1030e8d8bef9SDimitry Andric } 1031e8d8bef9SDimitry Andric 1032e8d8bef9SDimitry Andric if (Entry.DescriptionsLength) 1033e8d8bef9SDimitry Andric DescriptionsLength = *Entry.DescriptionsLength; 1034e8d8bef9SDimitry Andric else 1035e8d8bef9SDimitry Andric DescriptionsLength = OpBuffer.size(); 1036e8d8bef9SDimitry Andric 1037e8d8bef9SDimitry Andric encodeULEB128(DescriptionsLength, OS); 1038e8d8bef9SDimitry Andric OS.write(OpBuffer.data(), OpBuffer.size()); 1039e8d8bef9SDimitry Andric 1040e8d8bef9SDimitry Andric return Error::success(); 1041e8d8bef9SDimitry Andric }; 1042e8d8bef9SDimitry Andric 1043e8d8bef9SDimitry Andric switch (Entry.Operator) { 1044e8d8bef9SDimitry Andric case dwarf::DW_LLE_end_of_list: 1045e8d8bef9SDimitry Andric if (Error Err = CheckOperands(0)) 1046e8d8bef9SDimitry Andric return std::move(Err); 1047e8d8bef9SDimitry Andric break; 1048e8d8bef9SDimitry Andric case dwarf::DW_LLE_base_addressx: 1049e8d8bef9SDimitry Andric if (Error Err = CheckOperands(1)) 1050e8d8bef9SDimitry Andric return std::move(Err); 1051e8d8bef9SDimitry Andric encodeULEB128(Entry.Values[0], OS); 1052e8d8bef9SDimitry Andric break; 1053e8d8bef9SDimitry Andric case dwarf::DW_LLE_startx_endx: 1054e8d8bef9SDimitry Andric case dwarf::DW_LLE_startx_length: 1055e8d8bef9SDimitry Andric case dwarf::DW_LLE_offset_pair: 1056e8d8bef9SDimitry Andric if (Error Err = CheckOperands(2)) 1057e8d8bef9SDimitry Andric return std::move(Err); 1058e8d8bef9SDimitry Andric encodeULEB128(Entry.Values[0], OS); 1059e8d8bef9SDimitry Andric encodeULEB128(Entry.Values[1], OS); 1060e8d8bef9SDimitry Andric if (Error Err = WriteDWARFOperations()) 1061e8d8bef9SDimitry Andric return std::move(Err); 1062e8d8bef9SDimitry Andric break; 1063e8d8bef9SDimitry Andric case dwarf::DW_LLE_default_location: 1064e8d8bef9SDimitry Andric if (Error Err = CheckOperands(0)) 1065e8d8bef9SDimitry Andric return std::move(Err); 1066e8d8bef9SDimitry Andric if (Error Err = WriteDWARFOperations()) 1067e8d8bef9SDimitry Andric return std::move(Err); 1068e8d8bef9SDimitry Andric break; 1069e8d8bef9SDimitry Andric case dwarf::DW_LLE_base_address: 1070e8d8bef9SDimitry Andric if (Error Err = CheckOperands(1)) 1071e8d8bef9SDimitry Andric return std::move(Err); 1072e8d8bef9SDimitry Andric if (Error Err = WriteAddress(Entry.Values[0])) 1073e8d8bef9SDimitry Andric return std::move(Err); 1074e8d8bef9SDimitry Andric break; 1075e8d8bef9SDimitry Andric case dwarf::DW_LLE_start_end: 1076e8d8bef9SDimitry Andric if (Error Err = CheckOperands(2)) 1077e8d8bef9SDimitry Andric return std::move(Err); 1078e8d8bef9SDimitry Andric if (Error Err = WriteAddress(Entry.Values[0])) 1079e8d8bef9SDimitry Andric return std::move(Err); 1080e8d8bef9SDimitry Andric cantFail(WriteAddress(Entry.Values[1])); 1081e8d8bef9SDimitry Andric if (Error Err = WriteDWARFOperations()) 1082e8d8bef9SDimitry Andric return std::move(Err); 1083e8d8bef9SDimitry Andric break; 1084e8d8bef9SDimitry Andric case dwarf::DW_LLE_start_length: 1085e8d8bef9SDimitry Andric if (Error Err = CheckOperands(2)) 1086e8d8bef9SDimitry Andric return std::move(Err); 1087e8d8bef9SDimitry Andric if (Error Err = WriteAddress(Entry.Values[0])) 1088e8d8bef9SDimitry Andric return std::move(Err); 1089e8d8bef9SDimitry Andric encodeULEB128(Entry.Values[1], OS); 1090e8d8bef9SDimitry Andric if (Error Err = WriteDWARFOperations()) 1091e8d8bef9SDimitry Andric return std::move(Err); 1092e8d8bef9SDimitry Andric break; 1093e8d8bef9SDimitry Andric } 1094e8d8bef9SDimitry Andric 1095e8d8bef9SDimitry Andric return OS.tell() - BeginOffset; 1096e8d8bef9SDimitry Andric } 1097e8d8bef9SDimitry Andric 1098e8d8bef9SDimitry Andric template <typename EntryType> 1099e8d8bef9SDimitry Andric static Error writeDWARFLists(raw_ostream &OS, 1100e8d8bef9SDimitry Andric ArrayRef<DWARFYAML::ListTable<EntryType>> Tables, 1101e8d8bef9SDimitry Andric bool IsLittleEndian, bool Is64BitAddrSize) { 1102e8d8bef9SDimitry Andric for (const DWARFYAML::ListTable<EntryType> &Table : Tables) { 1103e8d8bef9SDimitry Andric // sizeof(version) + sizeof(address_size) + sizeof(segment_selector_size) + 1104e8d8bef9SDimitry Andric // sizeof(offset_entry_count) = 8 1105e8d8bef9SDimitry Andric uint64_t Length = 8; 1106e8d8bef9SDimitry Andric 1107e8d8bef9SDimitry Andric uint8_t AddrSize; 1108e8d8bef9SDimitry Andric if (Table.AddrSize) 1109e8d8bef9SDimitry Andric AddrSize = *Table.AddrSize; 1110e8d8bef9SDimitry Andric else 1111e8d8bef9SDimitry Andric AddrSize = Is64BitAddrSize ? 8 : 4; 1112e8d8bef9SDimitry Andric 1113e8d8bef9SDimitry Andric // Since the length of the current range/location lists entry is 1114e8d8bef9SDimitry Andric // undetermined yet, we firstly write the content of the range/location 1115e8d8bef9SDimitry Andric // lists to a buffer to calculate the length and then serialize the buffer 1116e8d8bef9SDimitry Andric // content to the actual output stream. 1117e8d8bef9SDimitry Andric std::string ListBuffer; 1118e8d8bef9SDimitry Andric raw_string_ostream ListBufferOS(ListBuffer); 1119e8d8bef9SDimitry Andric 1120e8d8bef9SDimitry Andric // Offsets holds offsets for each range/location list. The i-th element is 1121e8d8bef9SDimitry Andric // the offset from the beginning of the first range/location list to the 1122e8d8bef9SDimitry Andric // location of the i-th range list. 1123e8d8bef9SDimitry Andric std::vector<uint64_t> Offsets; 1124e8d8bef9SDimitry Andric 1125e8d8bef9SDimitry Andric for (const DWARFYAML::ListEntries<EntryType> &List : Table.Lists) { 1126e8d8bef9SDimitry Andric Offsets.push_back(ListBufferOS.tell()); 1127e8d8bef9SDimitry Andric if (List.Content) { 1128e8d8bef9SDimitry Andric List.Content->writeAsBinary(ListBufferOS, UINT64_MAX); 1129e8d8bef9SDimitry Andric Length += List.Content->binary_size(); 1130e8d8bef9SDimitry Andric } else if (List.Entries) { 1131e8d8bef9SDimitry Andric for (const EntryType &Entry : *List.Entries) { 1132e8d8bef9SDimitry Andric Expected<uint64_t> EntrySize = 1133e8d8bef9SDimitry Andric writeListEntry(ListBufferOS, Entry, AddrSize, IsLittleEndian); 1134e8d8bef9SDimitry Andric if (!EntrySize) 1135e8d8bef9SDimitry Andric return EntrySize.takeError(); 1136e8d8bef9SDimitry Andric Length += *EntrySize; 1137e8d8bef9SDimitry Andric } 1138e8d8bef9SDimitry Andric } 1139e8d8bef9SDimitry Andric } 1140e8d8bef9SDimitry Andric 1141e8d8bef9SDimitry Andric // If the offset_entry_count field isn't specified, yaml2obj will infer it 1142e8d8bef9SDimitry Andric // from the 'Offsets' field in the YAML description. If the 'Offsets' field 1143e8d8bef9SDimitry Andric // isn't specified either, yaml2obj will infer it from the auto-generated 1144e8d8bef9SDimitry Andric // offsets. 1145e8d8bef9SDimitry Andric uint32_t OffsetEntryCount; 1146e8d8bef9SDimitry Andric if (Table.OffsetEntryCount) 1147e8d8bef9SDimitry Andric OffsetEntryCount = *Table.OffsetEntryCount; 1148e8d8bef9SDimitry Andric else 1149e8d8bef9SDimitry Andric OffsetEntryCount = Table.Offsets ? Table.Offsets->size() : Offsets.size(); 1150e8d8bef9SDimitry Andric uint64_t OffsetsSize = 1151e8d8bef9SDimitry Andric OffsetEntryCount * (Table.Format == dwarf::DWARF64 ? 8 : 4); 1152e8d8bef9SDimitry Andric Length += OffsetsSize; 1153e8d8bef9SDimitry Andric 1154e8d8bef9SDimitry Andric // If the length is specified in the YAML description, we use it instead of 1155e8d8bef9SDimitry Andric // the actual length. 1156e8d8bef9SDimitry Andric if (Table.Length) 1157e8d8bef9SDimitry Andric Length = *Table.Length; 1158e8d8bef9SDimitry Andric 1159e8d8bef9SDimitry Andric writeInitialLength(Table.Format, Length, OS, IsLittleEndian); 1160e8d8bef9SDimitry Andric writeInteger((uint16_t)Table.Version, OS, IsLittleEndian); 1161e8d8bef9SDimitry Andric writeInteger((uint8_t)AddrSize, OS, IsLittleEndian); 1162e8d8bef9SDimitry Andric writeInteger((uint8_t)Table.SegSelectorSize, OS, IsLittleEndian); 1163e8d8bef9SDimitry Andric writeInteger((uint32_t)OffsetEntryCount, OS, IsLittleEndian); 1164e8d8bef9SDimitry Andric 1165e8d8bef9SDimitry Andric auto EmitOffsets = [&](ArrayRef<uint64_t> Offsets, uint64_t OffsetsSize) { 1166e8d8bef9SDimitry Andric for (uint64_t Offset : Offsets) 1167e8d8bef9SDimitry Andric writeDWARFOffset(OffsetsSize + Offset, Table.Format, OS, 1168e8d8bef9SDimitry Andric IsLittleEndian); 1169e8d8bef9SDimitry Andric }; 1170e8d8bef9SDimitry Andric 1171e8d8bef9SDimitry Andric if (Table.Offsets) 1172e8d8bef9SDimitry Andric EmitOffsets(ArrayRef<uint64_t>((const uint64_t *)Table.Offsets->data(), 1173e8d8bef9SDimitry Andric Table.Offsets->size()), 1174e8d8bef9SDimitry Andric 0); 1175e8d8bef9SDimitry Andric else if (OffsetEntryCount != 0) 1176e8d8bef9SDimitry Andric EmitOffsets(Offsets, OffsetsSize); 1177e8d8bef9SDimitry Andric 1178e8d8bef9SDimitry Andric OS.write(ListBuffer.data(), ListBuffer.size()); 1179e8d8bef9SDimitry Andric } 1180e8d8bef9SDimitry Andric 1181e8d8bef9SDimitry Andric return Error::success(); 1182e8d8bef9SDimitry Andric } 1183e8d8bef9SDimitry Andric 1184e8d8bef9SDimitry Andric Error DWARFYAML::emitDebugRnglists(raw_ostream &OS, const Data &DI) { 1185e8d8bef9SDimitry Andric assert(DI.DebugRnglists && "unexpected emitDebugRnglists() call"); 1186e8d8bef9SDimitry Andric return writeDWARFLists<DWARFYAML::RnglistEntry>( 1187e8d8bef9SDimitry Andric OS, *DI.DebugRnglists, DI.IsLittleEndian, DI.Is64BitAddrSize); 1188e8d8bef9SDimitry Andric } 1189e8d8bef9SDimitry Andric 1190e8d8bef9SDimitry Andric Error DWARFYAML::emitDebugLoclists(raw_ostream &OS, const Data &DI) { 1191e8d8bef9SDimitry Andric assert(DI.DebugLoclists && "unexpected emitDebugRnglists() call"); 1192e8d8bef9SDimitry Andric return writeDWARFLists<DWARFYAML::LoclistEntry>( 1193e8d8bef9SDimitry Andric OS, *DI.DebugLoclists, DI.IsLittleEndian, DI.Is64BitAddrSize); 1194e8d8bef9SDimitry Andric } 1195e8d8bef9SDimitry Andric 1196e8d8bef9SDimitry Andric std::function<Error(raw_ostream &, const DWARFYAML::Data &)> 1197e8d8bef9SDimitry Andric DWARFYAML::getDWARFEmitterByName(StringRef SecName) { 1198e8d8bef9SDimitry Andric auto EmitFunc = 1199e8d8bef9SDimitry Andric StringSwitch< 1200e8d8bef9SDimitry Andric std::function<Error(raw_ostream &, const DWARFYAML::Data &)>>(SecName) 1201e8d8bef9SDimitry Andric .Case("debug_abbrev", DWARFYAML::emitDebugAbbrev) 1202e8d8bef9SDimitry Andric .Case("debug_addr", DWARFYAML::emitDebugAddr) 1203e8d8bef9SDimitry Andric .Case("debug_aranges", DWARFYAML::emitDebugAranges) 1204e8d8bef9SDimitry Andric .Case("debug_gnu_pubnames", DWARFYAML::emitDebugGNUPubnames) 1205e8d8bef9SDimitry Andric .Case("debug_gnu_pubtypes", DWARFYAML::emitDebugGNUPubtypes) 1206e8d8bef9SDimitry Andric .Case("debug_info", DWARFYAML::emitDebugInfo) 1207e8d8bef9SDimitry Andric .Case("debug_line", DWARFYAML::emitDebugLine) 1208e8d8bef9SDimitry Andric .Case("debug_loclists", DWARFYAML::emitDebugLoclists) 1209e8d8bef9SDimitry Andric .Case("debug_pubnames", DWARFYAML::emitDebugPubnames) 1210e8d8bef9SDimitry Andric .Case("debug_pubtypes", DWARFYAML::emitDebugPubtypes) 1211e8d8bef9SDimitry Andric .Case("debug_ranges", DWARFYAML::emitDebugRanges) 1212e8d8bef9SDimitry Andric .Case("debug_rnglists", DWARFYAML::emitDebugRnglists) 1213e8d8bef9SDimitry Andric .Case("debug_str", DWARFYAML::emitDebugStr) 1214e8d8bef9SDimitry Andric .Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets) 1215*0fca6ea1SDimitry Andric .Case("debug_names", DWARFYAML::emitDebugNames) 1216e8d8bef9SDimitry Andric .Default([&](raw_ostream &, const DWARFYAML::Data &) { 1217e8d8bef9SDimitry Andric return createStringError(errc::not_supported, 1218e8d8bef9SDimitry Andric SecName + " is not supported"); 1219e8d8bef9SDimitry Andric }); 1220e8d8bef9SDimitry Andric 1221e8d8bef9SDimitry Andric return EmitFunc; 1222e8d8bef9SDimitry Andric } 12235ffd83dbSDimitry Andric 12245ffd83dbSDimitry Andric static Error 1225e8d8bef9SDimitry Andric emitDebugSectionImpl(const DWARFYAML::Data &DI, StringRef Sec, 12260b57cec5SDimitry Andric StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) { 12270b57cec5SDimitry Andric std::string Data; 12280b57cec5SDimitry Andric raw_string_ostream DebugInfoStream(Data); 1229e8d8bef9SDimitry Andric 1230e8d8bef9SDimitry Andric auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Sec); 1231e8d8bef9SDimitry Andric 12325ffd83dbSDimitry Andric if (Error Err = EmitFunc(DebugInfoStream, DI)) 12335ffd83dbSDimitry Andric return Err; 12340b57cec5SDimitry Andric DebugInfoStream.flush(); 12350b57cec5SDimitry Andric if (!Data.empty()) 12360b57cec5SDimitry Andric OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data); 12375ffd83dbSDimitry Andric 12385ffd83dbSDimitry Andric return Error::success(); 12390b57cec5SDimitry Andric } 12400b57cec5SDimitry Andric 12410b57cec5SDimitry Andric Expected<StringMap<std::unique_ptr<MemoryBuffer>>> 1242e8d8bef9SDimitry Andric DWARFYAML::emitDebugSections(StringRef YAMLString, bool IsLittleEndian, 1243e8d8bef9SDimitry Andric bool Is64BitAddrSize) { 12445ffd83dbSDimitry Andric auto CollectDiagnostic = [](const SMDiagnostic &Diag, void *DiagContext) { 12455ffd83dbSDimitry Andric *static_cast<SMDiagnostic *>(DiagContext) = Diag; 12465ffd83dbSDimitry Andric }; 12475ffd83dbSDimitry Andric 12485ffd83dbSDimitry Andric SMDiagnostic GeneratedDiag; 12495ffd83dbSDimitry Andric yaml::Input YIn(YAMLString, /*Ctxt=*/nullptr, CollectDiagnostic, 12505ffd83dbSDimitry Andric &GeneratedDiag); 12510b57cec5SDimitry Andric 12520b57cec5SDimitry Andric DWARFYAML::Data DI; 12530b57cec5SDimitry Andric DI.IsLittleEndian = IsLittleEndian; 1254e8d8bef9SDimitry Andric DI.Is64BitAddrSize = Is64BitAddrSize; 1255e8d8bef9SDimitry Andric 12560b57cec5SDimitry Andric YIn >> DI; 12570b57cec5SDimitry Andric if (YIn.error()) 12585ffd83dbSDimitry Andric return createStringError(YIn.error(), GeneratedDiag.getMessage()); 12590b57cec5SDimitry Andric 12600b57cec5SDimitry Andric StringMap<std::unique_ptr<MemoryBuffer>> DebugSections; 1261e8d8bef9SDimitry Andric Error Err = Error::success(); 1262e8d8bef9SDimitry Andric 1263e8d8bef9SDimitry Andric for (StringRef SecName : DI.getNonEmptySectionNames()) 12645ffd83dbSDimitry Andric Err = joinErrors(std::move(Err), 1265e8d8bef9SDimitry Andric emitDebugSectionImpl(DI, SecName, DebugSections)); 12665ffd83dbSDimitry Andric 12675ffd83dbSDimitry Andric if (Err) 12685ffd83dbSDimitry Andric return std::move(Err); 12690b57cec5SDimitry Andric return std::move(DebugSections); 12700b57cec5SDimitry Andric } 1271