xref: /freebsd/contrib/llvm-project/llvm/lib/ObjectYAML/DWARFEmitter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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>
writeInteger(T Integer,raw_ostream & OS,bool IsLittleEndian)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 
writeVariableSizedInteger(uint64_t Integer,size_t Size,raw_ostream & OS,bool IsLittleEndian)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 
ZeroFillBytes(raw_ostream & OS,size_t Size)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 
writeInitialLength(const dwarf::DwarfFormat Format,const uint64_t Length,raw_ostream & OS,bool IsLittleEndian)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 
writeDWARFOffset(uint64_t Offset,dwarf::DwarfFormat Format,raw_ostream & OS,bool IsLittleEndian)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 
emitDebugStr(raw_ostream & OS,const DWARFYAML::Data & DI)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 
getAbbrevTableContentByIndex(uint64_t Index) const97e8d8bef9SDimitry 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 
emitDebugAbbrev(raw_ostream & OS,const DWARFYAML::Data & DI)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 
emitDebugAranges(raw_ostream & OS,const DWARFYAML::Data & DI)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 
emitDebugRanges(raw_ostream & OS,const DWARFYAML::Data & DI)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 
emitPubSection(raw_ostream & OS,const DWARFYAML::PubSection & Sect,bool IsLittleEndian,bool IsGNUPubSec=false)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 
emitDebugPubnames(raw_ostream & OS,const Data & DI)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 
emitDebugPubtypes(raw_ostream & OS,const Data & DI)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 
emitDebugGNUPubnames(raw_ostream & OS,const Data & DI)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 
emitDebugGNUPubtypes(raw_ostream & OS,const Data & DI)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 
writeDIE(const DWARFYAML::Data & DI,uint64_t CUIndex,uint64_t AbbrevTableID,const dwarf::FormParams & Params,const DWARFYAML::Entry & Entry,raw_ostream & OS,bool IsLittleEndian)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 
emitDebugInfo(raw_ostream & OS,const DWARFYAML::Data & DI)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 
emitFileEntry(raw_ostream & OS,const DWARFYAML::File & File)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 
writeExtendedOpcode(const DWARFYAML::LineTableOpcode & Op,uint8_t AddrSize,bool IsLittleEndian,raw_ostream & OS)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 
writeLineTableOpcode(const DWARFYAML::LineTableOpcode & Op,uint8_t OpcodeBase,uint8_t AddrSize,raw_ostream & OS,bool IsLittleEndian)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>
getStandardOpcodeLengths(uint16_t Version,std::optional<uint8_t> OpcodeBase)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 
emitDebugLine(raw_ostream & OS,const DWARFYAML::Data & DI)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 
emitDebugAddr(raw_ostream & OS,const Data & DI)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 
emitDebugStrOffsets(raw_ostream & OS,const Data & DI)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.
emitDebugNamesHeader(raw_ostream & OS,bool IsLittleEndian,uint32_t NameCount,uint32_t AbbrevSize,uint32_t CombinedSizeOtherParts)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
emitDebugNamesAbbrev(ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs)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.
emitDebugNamesCUOffsets(bool IsLittleEndian)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`.
emitDebugNamesNameTable(bool IsLittleEndian,const DenseMap<uint32_t,std::vector<DWARFYAML::DebugNameEntry>> & Entries,ArrayRef<uint32_t> EntryPoolOffsets)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>>
groupEntries(ArrayRef<DWARFYAML::DebugNameEntry> Entries)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>>
getNonZeroDataSizesFor(uint32_t AbbrevCode,ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs)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.
emitDebugNamesEntryPool(bool IsLittleEndian,const DenseMap<uint32_t,std::vector<DWARFYAML::DebugNameEntry>> & StrpToEntries,ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs)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 
emitDebugNames(raw_ostream & OS,const Data & DI)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 
checkOperandCount(StringRef EncodingString,ArrayRef<yaml::Hex64> Values,uint64_t ExpectedOperands)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 
writeListEntryAddress(StringRef EncodingName,raw_ostream & OS,uint64_t Addr,uint8_t AddrSize,bool IsLittleEndian)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>
writeDWARFExpression(raw_ostream & OS,const DWARFYAML::DWARFOperation & Operation,uint8_t AddrSize,bool IsLittleEndian)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 
writeListEntry(raw_ostream & OS,const DWARFYAML::RnglistEntry & Entry,uint8_t AddrSize,bool IsLittleEndian)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 
writeListEntry(raw_ostream & OS,const DWARFYAML::LoclistEntry & Entry,uint8_t AddrSize,bool IsLittleEndian)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>
writeDWARFLists(raw_ostream & OS,ArrayRef<DWARFYAML::ListTable<EntryType>> Tables,bool IsLittleEndian,bool Is64BitAddrSize)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 
emitDebugRnglists(raw_ostream & OS,const Data & DI)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 
emitDebugLoclists(raw_ostream & OS,const Data & DI)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 &)>
getDWARFEmitterByName(StringRef SecName)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
emitDebugSectionImpl(const DWARFYAML::Data & DI,StringRef Sec,StringMap<std::unique_ptr<MemoryBuffer>> & OutputBuffers)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>>>
emitDebugSections(StringRef YAMLString,bool IsLittleEndian,bool Is64BitAddrSize)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