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 
checkOperandCount(StringRef EncodingString,ArrayRef<yaml::Hex64> Values,uint64_t ExpectedOperands)694e8d8bef9SDimitry Andric static Error checkOperandCount(StringRef EncodingString,
695e8d8bef9SDimitry Andric                                ArrayRef<yaml::Hex64> Values,
696e8d8bef9SDimitry Andric                                uint64_t ExpectedOperands) {
697e8d8bef9SDimitry Andric   if (Values.size() != ExpectedOperands)
698e8d8bef9SDimitry Andric     return createStringError(
699e8d8bef9SDimitry Andric         errc::invalid_argument,
700e8d8bef9SDimitry Andric         "invalid number (%zu) of operands for the operator: %s, %" PRIu64
701e8d8bef9SDimitry Andric         " expected",
702e8d8bef9SDimitry Andric         Values.size(), EncodingString.str().c_str(), ExpectedOperands);
703e8d8bef9SDimitry Andric 
704e8d8bef9SDimitry Andric   return Error::success();
705e8d8bef9SDimitry Andric }
706e8d8bef9SDimitry Andric 
writeListEntryAddress(StringRef EncodingName,raw_ostream & OS,uint64_t Addr,uint8_t AddrSize,bool IsLittleEndian)707e8d8bef9SDimitry Andric static Error writeListEntryAddress(StringRef EncodingName, raw_ostream &OS,
708e8d8bef9SDimitry Andric                                    uint64_t Addr, uint8_t AddrSize,
709e8d8bef9SDimitry Andric                                    bool IsLittleEndian) {
710e8d8bef9SDimitry Andric   if (Error Err = writeVariableSizedInteger(Addr, AddrSize, OS, IsLittleEndian))
711e8d8bef9SDimitry Andric     return createStringError(errc::invalid_argument,
712e8d8bef9SDimitry Andric                              "unable to write address for the operator %s: %s",
713e8d8bef9SDimitry Andric                              EncodingName.str().c_str(),
714e8d8bef9SDimitry Andric                              toString(std::move(Err)).c_str());
715e8d8bef9SDimitry Andric 
716e8d8bef9SDimitry Andric   return Error::success();
717e8d8bef9SDimitry Andric }
718e8d8bef9SDimitry Andric 
719e8d8bef9SDimitry Andric static Expected<uint64_t>
writeDWARFExpression(raw_ostream & OS,const DWARFYAML::DWARFOperation & Operation,uint8_t AddrSize,bool IsLittleEndian)720e8d8bef9SDimitry Andric writeDWARFExpression(raw_ostream &OS,
721e8d8bef9SDimitry Andric                      const DWARFYAML::DWARFOperation &Operation,
722e8d8bef9SDimitry Andric                      uint8_t AddrSize, bool IsLittleEndian) {
723e8d8bef9SDimitry Andric   auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
724e8d8bef9SDimitry Andric     return checkOperandCount(dwarf::OperationEncodingString(Operation.Operator),
725e8d8bef9SDimitry Andric                              Operation.Values, ExpectedOperands);
726e8d8bef9SDimitry Andric   };
727e8d8bef9SDimitry Andric 
728e8d8bef9SDimitry Andric   uint64_t ExpressionBegin = OS.tell();
729e8d8bef9SDimitry Andric   writeInteger((uint8_t)Operation.Operator, OS, IsLittleEndian);
730e8d8bef9SDimitry Andric   switch (Operation.Operator) {
731e8d8bef9SDimitry Andric   case dwarf::DW_OP_consts:
732e8d8bef9SDimitry Andric     if (Error Err = CheckOperands(1))
733e8d8bef9SDimitry Andric       return std::move(Err);
734e8d8bef9SDimitry Andric     encodeSLEB128(Operation.Values[0], OS);
735e8d8bef9SDimitry Andric     break;
736e8d8bef9SDimitry Andric   case dwarf::DW_OP_stack_value:
737e8d8bef9SDimitry Andric     if (Error Err = CheckOperands(0))
738e8d8bef9SDimitry Andric       return std::move(Err);
739e8d8bef9SDimitry Andric     break;
740e8d8bef9SDimitry Andric   default:
741e8d8bef9SDimitry Andric     StringRef EncodingStr = dwarf::OperationEncodingString(Operation.Operator);
742e8d8bef9SDimitry Andric     return createStringError(errc::not_supported,
743e8d8bef9SDimitry Andric                              "DWARF expression: " +
744e8d8bef9SDimitry Andric                                  (EncodingStr.empty()
745e8d8bef9SDimitry Andric                                       ? "0x" + utohexstr(Operation.Operator)
746e8d8bef9SDimitry Andric                                       : EncodingStr) +
747e8d8bef9SDimitry Andric                                  " is not supported");
748e8d8bef9SDimitry Andric   }
749e8d8bef9SDimitry Andric   return OS.tell() - ExpressionBegin;
750e8d8bef9SDimitry Andric }
751e8d8bef9SDimitry Andric 
writeListEntry(raw_ostream & OS,const DWARFYAML::RnglistEntry & Entry,uint8_t AddrSize,bool IsLittleEndian)752e8d8bef9SDimitry Andric static Expected<uint64_t> writeListEntry(raw_ostream &OS,
753e8d8bef9SDimitry Andric                                          const DWARFYAML::RnglistEntry &Entry,
754e8d8bef9SDimitry Andric                                          uint8_t AddrSize,
755e8d8bef9SDimitry Andric                                          bool IsLittleEndian) {
756e8d8bef9SDimitry Andric   uint64_t BeginOffset = OS.tell();
757e8d8bef9SDimitry Andric   writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);
758e8d8bef9SDimitry Andric 
759e8d8bef9SDimitry Andric   StringRef EncodingName = dwarf::RangeListEncodingString(Entry.Operator);
760e8d8bef9SDimitry Andric 
761e8d8bef9SDimitry Andric   auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
762e8d8bef9SDimitry Andric     return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
763e8d8bef9SDimitry Andric   };
764e8d8bef9SDimitry Andric 
765e8d8bef9SDimitry Andric   auto WriteAddress = [&](uint64_t Addr) -> Error {
766e8d8bef9SDimitry Andric     return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
767e8d8bef9SDimitry Andric                                  IsLittleEndian);
768e8d8bef9SDimitry Andric   };
769e8d8bef9SDimitry Andric 
770e8d8bef9SDimitry Andric   switch (Entry.Operator) {
771e8d8bef9SDimitry Andric   case dwarf::DW_RLE_end_of_list:
772e8d8bef9SDimitry Andric     if (Error Err = CheckOperands(0))
773e8d8bef9SDimitry Andric       return std::move(Err);
774e8d8bef9SDimitry Andric     break;
775e8d8bef9SDimitry Andric   case dwarf::DW_RLE_base_addressx:
776e8d8bef9SDimitry Andric     if (Error Err = CheckOperands(1))
777e8d8bef9SDimitry Andric       return std::move(Err);
778e8d8bef9SDimitry Andric     encodeULEB128(Entry.Values[0], OS);
779e8d8bef9SDimitry Andric     break;
780e8d8bef9SDimitry Andric   case dwarf::DW_RLE_startx_endx:
781e8d8bef9SDimitry Andric   case dwarf::DW_RLE_startx_length:
782e8d8bef9SDimitry Andric   case dwarf::DW_RLE_offset_pair:
783e8d8bef9SDimitry Andric     if (Error Err = CheckOperands(2))
784e8d8bef9SDimitry Andric       return std::move(Err);
785e8d8bef9SDimitry Andric     encodeULEB128(Entry.Values[0], OS);
786e8d8bef9SDimitry Andric     encodeULEB128(Entry.Values[1], OS);
787e8d8bef9SDimitry Andric     break;
788e8d8bef9SDimitry Andric   case dwarf::DW_RLE_base_address:
789e8d8bef9SDimitry Andric     if (Error Err = CheckOperands(1))
790e8d8bef9SDimitry Andric       return std::move(Err);
791e8d8bef9SDimitry Andric     if (Error Err = WriteAddress(Entry.Values[0]))
792e8d8bef9SDimitry Andric       return std::move(Err);
793e8d8bef9SDimitry Andric     break;
794e8d8bef9SDimitry Andric   case dwarf::DW_RLE_start_end:
795e8d8bef9SDimitry Andric     if (Error Err = CheckOperands(2))
796e8d8bef9SDimitry Andric       return std::move(Err);
797e8d8bef9SDimitry Andric     if (Error Err = WriteAddress(Entry.Values[0]))
798e8d8bef9SDimitry Andric       return std::move(Err);
799e8d8bef9SDimitry Andric     cantFail(WriteAddress(Entry.Values[1]));
800e8d8bef9SDimitry Andric     break;
801e8d8bef9SDimitry Andric   case dwarf::DW_RLE_start_length:
802e8d8bef9SDimitry Andric     if (Error Err = CheckOperands(2))
803e8d8bef9SDimitry Andric       return std::move(Err);
804e8d8bef9SDimitry Andric     if (Error Err = WriteAddress(Entry.Values[0]))
805e8d8bef9SDimitry Andric       return std::move(Err);
806e8d8bef9SDimitry Andric     encodeULEB128(Entry.Values[1], OS);
807e8d8bef9SDimitry Andric     break;
808e8d8bef9SDimitry Andric   }
809e8d8bef9SDimitry Andric 
810e8d8bef9SDimitry Andric   return OS.tell() - BeginOffset;
811e8d8bef9SDimitry Andric }
812e8d8bef9SDimitry Andric 
writeListEntry(raw_ostream & OS,const DWARFYAML::LoclistEntry & Entry,uint8_t AddrSize,bool IsLittleEndian)813e8d8bef9SDimitry Andric static Expected<uint64_t> writeListEntry(raw_ostream &OS,
814e8d8bef9SDimitry Andric                                          const DWARFYAML::LoclistEntry &Entry,
815e8d8bef9SDimitry Andric                                          uint8_t AddrSize,
816e8d8bef9SDimitry Andric                                          bool IsLittleEndian) {
817e8d8bef9SDimitry Andric   uint64_t BeginOffset = OS.tell();
818e8d8bef9SDimitry Andric   writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);
819e8d8bef9SDimitry Andric 
820e8d8bef9SDimitry Andric   StringRef EncodingName = dwarf::LocListEncodingString(Entry.Operator);
821e8d8bef9SDimitry Andric 
822e8d8bef9SDimitry Andric   auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
823e8d8bef9SDimitry Andric     return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
824e8d8bef9SDimitry Andric   };
825e8d8bef9SDimitry Andric 
826e8d8bef9SDimitry Andric   auto WriteAddress = [&](uint64_t Addr) -> Error {
827e8d8bef9SDimitry Andric     return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
828e8d8bef9SDimitry Andric                                  IsLittleEndian);
829e8d8bef9SDimitry Andric   };
830e8d8bef9SDimitry Andric 
831e8d8bef9SDimitry Andric   auto WriteDWARFOperations = [&]() -> Error {
832e8d8bef9SDimitry Andric     std::string OpBuffer;
833e8d8bef9SDimitry Andric     raw_string_ostream OpBufferOS(OpBuffer);
834e8d8bef9SDimitry Andric     uint64_t DescriptionsLength = 0;
835e8d8bef9SDimitry Andric 
836e8d8bef9SDimitry Andric     for (const DWARFYAML::DWARFOperation &Op : Entry.Descriptions) {
837e8d8bef9SDimitry Andric       if (Expected<uint64_t> OpSize =
838e8d8bef9SDimitry Andric               writeDWARFExpression(OpBufferOS, Op, AddrSize, IsLittleEndian))
839e8d8bef9SDimitry Andric         DescriptionsLength += *OpSize;
840e8d8bef9SDimitry Andric       else
841e8d8bef9SDimitry Andric         return OpSize.takeError();
842e8d8bef9SDimitry Andric     }
843e8d8bef9SDimitry Andric 
844e8d8bef9SDimitry Andric     if (Entry.DescriptionsLength)
845e8d8bef9SDimitry Andric       DescriptionsLength = *Entry.DescriptionsLength;
846e8d8bef9SDimitry Andric     else
847e8d8bef9SDimitry Andric       DescriptionsLength = OpBuffer.size();
848e8d8bef9SDimitry Andric 
849e8d8bef9SDimitry Andric     encodeULEB128(DescriptionsLength, OS);
850e8d8bef9SDimitry Andric     OS.write(OpBuffer.data(), OpBuffer.size());
851e8d8bef9SDimitry Andric 
852e8d8bef9SDimitry Andric     return Error::success();
853e8d8bef9SDimitry Andric   };
854e8d8bef9SDimitry Andric 
855e8d8bef9SDimitry Andric   switch (Entry.Operator) {
856e8d8bef9SDimitry Andric   case dwarf::DW_LLE_end_of_list:
857e8d8bef9SDimitry Andric     if (Error Err = CheckOperands(0))
858e8d8bef9SDimitry Andric       return std::move(Err);
859e8d8bef9SDimitry Andric     break;
860e8d8bef9SDimitry Andric   case dwarf::DW_LLE_base_addressx:
861e8d8bef9SDimitry Andric     if (Error Err = CheckOperands(1))
862e8d8bef9SDimitry Andric       return std::move(Err);
863e8d8bef9SDimitry Andric     encodeULEB128(Entry.Values[0], OS);
864e8d8bef9SDimitry Andric     break;
865e8d8bef9SDimitry Andric   case dwarf::DW_LLE_startx_endx:
866e8d8bef9SDimitry Andric   case dwarf::DW_LLE_startx_length:
867e8d8bef9SDimitry Andric   case dwarf::DW_LLE_offset_pair:
868e8d8bef9SDimitry Andric     if (Error Err = CheckOperands(2))
869e8d8bef9SDimitry Andric       return std::move(Err);
870e8d8bef9SDimitry Andric     encodeULEB128(Entry.Values[0], OS);
871e8d8bef9SDimitry Andric     encodeULEB128(Entry.Values[1], OS);
872e8d8bef9SDimitry Andric     if (Error Err = WriteDWARFOperations())
873e8d8bef9SDimitry Andric       return std::move(Err);
874e8d8bef9SDimitry Andric     break;
875e8d8bef9SDimitry Andric   case dwarf::DW_LLE_default_location:
876e8d8bef9SDimitry Andric     if (Error Err = CheckOperands(0))
877e8d8bef9SDimitry Andric       return std::move(Err);
878e8d8bef9SDimitry Andric     if (Error Err = WriteDWARFOperations())
879e8d8bef9SDimitry Andric       return std::move(Err);
880e8d8bef9SDimitry Andric     break;
881e8d8bef9SDimitry Andric   case dwarf::DW_LLE_base_address:
882e8d8bef9SDimitry Andric     if (Error Err = CheckOperands(1))
883e8d8bef9SDimitry Andric       return std::move(Err);
884e8d8bef9SDimitry Andric     if (Error Err = WriteAddress(Entry.Values[0]))
885e8d8bef9SDimitry Andric       return std::move(Err);
886e8d8bef9SDimitry Andric     break;
887e8d8bef9SDimitry Andric   case dwarf::DW_LLE_start_end:
888e8d8bef9SDimitry Andric     if (Error Err = CheckOperands(2))
889e8d8bef9SDimitry Andric       return std::move(Err);
890e8d8bef9SDimitry Andric     if (Error Err = WriteAddress(Entry.Values[0]))
891e8d8bef9SDimitry Andric       return std::move(Err);
892e8d8bef9SDimitry Andric     cantFail(WriteAddress(Entry.Values[1]));
893e8d8bef9SDimitry Andric     if (Error Err = WriteDWARFOperations())
894e8d8bef9SDimitry Andric       return std::move(Err);
895e8d8bef9SDimitry Andric     break;
896e8d8bef9SDimitry Andric   case dwarf::DW_LLE_start_length:
897e8d8bef9SDimitry Andric     if (Error Err = CheckOperands(2))
898e8d8bef9SDimitry Andric       return std::move(Err);
899e8d8bef9SDimitry Andric     if (Error Err = WriteAddress(Entry.Values[0]))
900e8d8bef9SDimitry Andric       return std::move(Err);
901e8d8bef9SDimitry Andric     encodeULEB128(Entry.Values[1], OS);
902e8d8bef9SDimitry Andric     if (Error Err = WriteDWARFOperations())
903e8d8bef9SDimitry Andric       return std::move(Err);
904e8d8bef9SDimitry Andric     break;
905e8d8bef9SDimitry Andric   }
906e8d8bef9SDimitry Andric 
907e8d8bef9SDimitry Andric   return OS.tell() - BeginOffset;
908e8d8bef9SDimitry Andric }
909e8d8bef9SDimitry Andric 
910e8d8bef9SDimitry Andric template <typename EntryType>
writeDWARFLists(raw_ostream & OS,ArrayRef<DWARFYAML::ListTable<EntryType>> Tables,bool IsLittleEndian,bool Is64BitAddrSize)911e8d8bef9SDimitry Andric static Error writeDWARFLists(raw_ostream &OS,
912e8d8bef9SDimitry Andric                              ArrayRef<DWARFYAML::ListTable<EntryType>> Tables,
913e8d8bef9SDimitry Andric                              bool IsLittleEndian, bool Is64BitAddrSize) {
914e8d8bef9SDimitry Andric   for (const DWARFYAML::ListTable<EntryType> &Table : Tables) {
915e8d8bef9SDimitry Andric     // sizeof(version) + sizeof(address_size) + sizeof(segment_selector_size) +
916e8d8bef9SDimitry Andric     // sizeof(offset_entry_count) = 8
917e8d8bef9SDimitry Andric     uint64_t Length = 8;
918e8d8bef9SDimitry Andric 
919e8d8bef9SDimitry Andric     uint8_t AddrSize;
920e8d8bef9SDimitry Andric     if (Table.AddrSize)
921e8d8bef9SDimitry Andric       AddrSize = *Table.AddrSize;
922e8d8bef9SDimitry Andric     else
923e8d8bef9SDimitry Andric       AddrSize = Is64BitAddrSize ? 8 : 4;
924e8d8bef9SDimitry Andric 
925e8d8bef9SDimitry Andric     // Since the length of the current range/location lists entry is
926e8d8bef9SDimitry Andric     // undetermined yet, we firstly write the content of the range/location
927e8d8bef9SDimitry Andric     // lists to a buffer to calculate the length and then serialize the buffer
928e8d8bef9SDimitry Andric     // content to the actual output stream.
929e8d8bef9SDimitry Andric     std::string ListBuffer;
930e8d8bef9SDimitry Andric     raw_string_ostream ListBufferOS(ListBuffer);
931e8d8bef9SDimitry Andric 
932e8d8bef9SDimitry Andric     // Offsets holds offsets for each range/location list. The i-th element is
933e8d8bef9SDimitry Andric     // the offset from the beginning of the first range/location list to the
934e8d8bef9SDimitry Andric     // location of the i-th range list.
935e8d8bef9SDimitry Andric     std::vector<uint64_t> Offsets;
936e8d8bef9SDimitry Andric 
937e8d8bef9SDimitry Andric     for (const DWARFYAML::ListEntries<EntryType> &List : Table.Lists) {
938e8d8bef9SDimitry Andric       Offsets.push_back(ListBufferOS.tell());
939e8d8bef9SDimitry Andric       if (List.Content) {
940e8d8bef9SDimitry Andric         List.Content->writeAsBinary(ListBufferOS, UINT64_MAX);
941e8d8bef9SDimitry Andric         Length += List.Content->binary_size();
942e8d8bef9SDimitry Andric       } else if (List.Entries) {
943e8d8bef9SDimitry Andric         for (const EntryType &Entry : *List.Entries) {
944e8d8bef9SDimitry Andric           Expected<uint64_t> EntrySize =
945e8d8bef9SDimitry Andric               writeListEntry(ListBufferOS, Entry, AddrSize, IsLittleEndian);
946e8d8bef9SDimitry Andric           if (!EntrySize)
947e8d8bef9SDimitry Andric             return EntrySize.takeError();
948e8d8bef9SDimitry Andric           Length += *EntrySize;
949e8d8bef9SDimitry Andric         }
950e8d8bef9SDimitry Andric       }
951e8d8bef9SDimitry Andric     }
952e8d8bef9SDimitry Andric 
953e8d8bef9SDimitry Andric     // If the offset_entry_count field isn't specified, yaml2obj will infer it
954e8d8bef9SDimitry Andric     // from the 'Offsets' field in the YAML description. If the 'Offsets' field
955e8d8bef9SDimitry Andric     // isn't specified either, yaml2obj will infer it from the auto-generated
956e8d8bef9SDimitry Andric     // offsets.
957e8d8bef9SDimitry Andric     uint32_t OffsetEntryCount;
958e8d8bef9SDimitry Andric     if (Table.OffsetEntryCount)
959e8d8bef9SDimitry Andric       OffsetEntryCount = *Table.OffsetEntryCount;
960e8d8bef9SDimitry Andric     else
961e8d8bef9SDimitry Andric       OffsetEntryCount = Table.Offsets ? Table.Offsets->size() : Offsets.size();
962e8d8bef9SDimitry Andric     uint64_t OffsetsSize =
963e8d8bef9SDimitry Andric         OffsetEntryCount * (Table.Format == dwarf::DWARF64 ? 8 : 4);
964e8d8bef9SDimitry Andric     Length += OffsetsSize;
965e8d8bef9SDimitry Andric 
966e8d8bef9SDimitry Andric     // If the length is specified in the YAML description, we use it instead of
967e8d8bef9SDimitry Andric     // the actual length.
968e8d8bef9SDimitry Andric     if (Table.Length)
969e8d8bef9SDimitry Andric       Length = *Table.Length;
970e8d8bef9SDimitry Andric 
971e8d8bef9SDimitry Andric     writeInitialLength(Table.Format, Length, OS, IsLittleEndian);
972e8d8bef9SDimitry Andric     writeInteger((uint16_t)Table.Version, OS, IsLittleEndian);
973e8d8bef9SDimitry Andric     writeInteger((uint8_t)AddrSize, OS, IsLittleEndian);
974e8d8bef9SDimitry Andric     writeInteger((uint8_t)Table.SegSelectorSize, OS, IsLittleEndian);
975e8d8bef9SDimitry Andric     writeInteger((uint32_t)OffsetEntryCount, OS, IsLittleEndian);
976e8d8bef9SDimitry Andric 
977e8d8bef9SDimitry Andric     auto EmitOffsets = [&](ArrayRef<uint64_t> Offsets, uint64_t OffsetsSize) {
978e8d8bef9SDimitry Andric       for (uint64_t Offset : Offsets)
979e8d8bef9SDimitry Andric         writeDWARFOffset(OffsetsSize + Offset, Table.Format, OS,
980e8d8bef9SDimitry Andric                          IsLittleEndian);
981e8d8bef9SDimitry Andric     };
982e8d8bef9SDimitry Andric 
983e8d8bef9SDimitry Andric     if (Table.Offsets)
984e8d8bef9SDimitry Andric       EmitOffsets(ArrayRef<uint64_t>((const uint64_t *)Table.Offsets->data(),
985e8d8bef9SDimitry Andric                                      Table.Offsets->size()),
986e8d8bef9SDimitry Andric                   0);
987e8d8bef9SDimitry Andric     else if (OffsetEntryCount != 0)
988e8d8bef9SDimitry Andric       EmitOffsets(Offsets, OffsetsSize);
989e8d8bef9SDimitry Andric 
990e8d8bef9SDimitry Andric     OS.write(ListBuffer.data(), ListBuffer.size());
991e8d8bef9SDimitry Andric   }
992e8d8bef9SDimitry Andric 
993e8d8bef9SDimitry Andric   return Error::success();
994e8d8bef9SDimitry Andric }
995e8d8bef9SDimitry Andric 
emitDebugRnglists(raw_ostream & OS,const Data & DI)996e8d8bef9SDimitry Andric Error DWARFYAML::emitDebugRnglists(raw_ostream &OS, const Data &DI) {
997e8d8bef9SDimitry Andric   assert(DI.DebugRnglists && "unexpected emitDebugRnglists() call");
998e8d8bef9SDimitry Andric   return writeDWARFLists<DWARFYAML::RnglistEntry>(
999e8d8bef9SDimitry Andric       OS, *DI.DebugRnglists, DI.IsLittleEndian, DI.Is64BitAddrSize);
1000e8d8bef9SDimitry Andric }
1001e8d8bef9SDimitry Andric 
emitDebugLoclists(raw_ostream & OS,const Data & DI)1002e8d8bef9SDimitry Andric Error DWARFYAML::emitDebugLoclists(raw_ostream &OS, const Data &DI) {
1003e8d8bef9SDimitry Andric   assert(DI.DebugLoclists && "unexpected emitDebugRnglists() call");
1004e8d8bef9SDimitry Andric   return writeDWARFLists<DWARFYAML::LoclistEntry>(
1005e8d8bef9SDimitry Andric       OS, *DI.DebugLoclists, DI.IsLittleEndian, DI.Is64BitAddrSize);
1006e8d8bef9SDimitry Andric }
1007e8d8bef9SDimitry Andric 
1008e8d8bef9SDimitry Andric std::function<Error(raw_ostream &, const DWARFYAML::Data &)>
getDWARFEmitterByName(StringRef SecName)1009e8d8bef9SDimitry Andric DWARFYAML::getDWARFEmitterByName(StringRef SecName) {
1010e8d8bef9SDimitry Andric   auto EmitFunc =
1011e8d8bef9SDimitry Andric       StringSwitch<
1012e8d8bef9SDimitry Andric           std::function<Error(raw_ostream &, const DWARFYAML::Data &)>>(SecName)
1013e8d8bef9SDimitry Andric           .Case("debug_abbrev", DWARFYAML::emitDebugAbbrev)
1014e8d8bef9SDimitry Andric           .Case("debug_addr", DWARFYAML::emitDebugAddr)
1015e8d8bef9SDimitry Andric           .Case("debug_aranges", DWARFYAML::emitDebugAranges)
1016e8d8bef9SDimitry Andric           .Case("debug_gnu_pubnames", DWARFYAML::emitDebugGNUPubnames)
1017e8d8bef9SDimitry Andric           .Case("debug_gnu_pubtypes", DWARFYAML::emitDebugGNUPubtypes)
1018e8d8bef9SDimitry Andric           .Case("debug_info", DWARFYAML::emitDebugInfo)
1019e8d8bef9SDimitry Andric           .Case("debug_line", DWARFYAML::emitDebugLine)
1020e8d8bef9SDimitry Andric           .Case("debug_loclists", DWARFYAML::emitDebugLoclists)
1021e8d8bef9SDimitry Andric           .Case("debug_pubnames", DWARFYAML::emitDebugPubnames)
1022e8d8bef9SDimitry Andric           .Case("debug_pubtypes", DWARFYAML::emitDebugPubtypes)
1023e8d8bef9SDimitry Andric           .Case("debug_ranges", DWARFYAML::emitDebugRanges)
1024e8d8bef9SDimitry Andric           .Case("debug_rnglists", DWARFYAML::emitDebugRnglists)
1025e8d8bef9SDimitry Andric           .Case("debug_str", DWARFYAML::emitDebugStr)
1026e8d8bef9SDimitry Andric           .Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets)
1027e8d8bef9SDimitry Andric           .Default([&](raw_ostream &, const DWARFYAML::Data &) {
1028e8d8bef9SDimitry Andric             return createStringError(errc::not_supported,
1029e8d8bef9SDimitry Andric                                      SecName + " is not supported");
1030e8d8bef9SDimitry Andric           });
1031e8d8bef9SDimitry Andric 
1032e8d8bef9SDimitry Andric   return EmitFunc;
1033e8d8bef9SDimitry Andric }
10345ffd83dbSDimitry Andric 
10355ffd83dbSDimitry Andric static Error
emitDebugSectionImpl(const DWARFYAML::Data & DI,StringRef Sec,StringMap<std::unique_ptr<MemoryBuffer>> & OutputBuffers)1036e8d8bef9SDimitry Andric emitDebugSectionImpl(const DWARFYAML::Data &DI, StringRef Sec,
10370b57cec5SDimitry Andric                      StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) {
10380b57cec5SDimitry Andric   std::string Data;
10390b57cec5SDimitry Andric   raw_string_ostream DebugInfoStream(Data);
1040e8d8bef9SDimitry Andric 
1041e8d8bef9SDimitry Andric   auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Sec);
1042e8d8bef9SDimitry Andric 
10435ffd83dbSDimitry Andric   if (Error Err = EmitFunc(DebugInfoStream, DI))
10445ffd83dbSDimitry Andric     return Err;
10450b57cec5SDimitry Andric   DebugInfoStream.flush();
10460b57cec5SDimitry Andric   if (!Data.empty())
10470b57cec5SDimitry Andric     OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data);
10485ffd83dbSDimitry Andric 
10495ffd83dbSDimitry Andric   return Error::success();
10500b57cec5SDimitry Andric }
10510b57cec5SDimitry Andric 
10520b57cec5SDimitry Andric Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
emitDebugSections(StringRef YAMLString,bool IsLittleEndian,bool Is64BitAddrSize)1053e8d8bef9SDimitry Andric DWARFYAML::emitDebugSections(StringRef YAMLString, bool IsLittleEndian,
1054e8d8bef9SDimitry Andric                              bool Is64BitAddrSize) {
10555ffd83dbSDimitry Andric   auto CollectDiagnostic = [](const SMDiagnostic &Diag, void *DiagContext) {
10565ffd83dbSDimitry Andric     *static_cast<SMDiagnostic *>(DiagContext) = Diag;
10575ffd83dbSDimitry Andric   };
10585ffd83dbSDimitry Andric 
10595ffd83dbSDimitry Andric   SMDiagnostic GeneratedDiag;
10605ffd83dbSDimitry Andric   yaml::Input YIn(YAMLString, /*Ctxt=*/nullptr, CollectDiagnostic,
10615ffd83dbSDimitry Andric                   &GeneratedDiag);
10620b57cec5SDimitry Andric 
10630b57cec5SDimitry Andric   DWARFYAML::Data DI;
10640b57cec5SDimitry Andric   DI.IsLittleEndian = IsLittleEndian;
1065e8d8bef9SDimitry Andric   DI.Is64BitAddrSize = Is64BitAddrSize;
1066e8d8bef9SDimitry Andric 
10670b57cec5SDimitry Andric   YIn >> DI;
10680b57cec5SDimitry Andric   if (YIn.error())
10695ffd83dbSDimitry Andric     return createStringError(YIn.error(), GeneratedDiag.getMessage());
10700b57cec5SDimitry Andric 
10710b57cec5SDimitry Andric   StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;
1072e8d8bef9SDimitry Andric   Error Err = Error::success();
1073e8d8bef9SDimitry Andric 
1074e8d8bef9SDimitry Andric   for (StringRef SecName : DI.getNonEmptySectionNames())
10755ffd83dbSDimitry Andric     Err = joinErrors(std::move(Err),
1076e8d8bef9SDimitry Andric                      emitDebugSectionImpl(DI, SecName, DebugSections));
10775ffd83dbSDimitry Andric 
10785ffd83dbSDimitry Andric   if (Err)
10795ffd83dbSDimitry Andric     return std::move(Err);
10800b57cec5SDimitry Andric   return std::move(DebugSections);
10810b57cec5SDimitry Andric }
1082