xref: /llvm-project/llvm/lib/ObjectYAML/DWARFEmitter.cpp (revision 5b7102d1f37eab7a8f17b7bf4124ca76fbdbd66d)
1 //===- DWARFEmitter - Convert YAML to DWARF binary data -------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// The DWARF component of yaml2obj. Provided as library code for tests.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/ObjectYAML/DWARFEmitter.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/StringMap.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/ADT/StringSwitch.h"
19 #include "llvm/BinaryFormat/Dwarf.h"
20 #include "llvm/ObjectYAML/DWARFYAML.h"
21 #include "llvm/Support/Errc.h"
22 #include "llvm/Support/Error.h"
23 #include "llvm/Support/LEB128.h"
24 #include "llvm/Support/MathExtras.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/SourceMgr.h"
27 #include "llvm/Support/SwapByteOrder.h"
28 #include "llvm/Support/YAMLTraits.h"
29 #include "llvm/Support/raw_ostream.h"
30 #include "llvm/TargetParser/Host.h"
31 #include <cassert>
32 #include <cstddef>
33 #include <cstdint>
34 #include <memory>
35 #include <optional>
36 #include <string>
37 #include <vector>
38 
39 using namespace llvm;
40 
41 template <typename T>
42 static void writeInteger(T Integer, raw_ostream &OS, bool IsLittleEndian) {
43   if (IsLittleEndian != sys::IsLittleEndianHost)
44     sys::swapByteOrder(Integer);
45   OS.write(reinterpret_cast<char *>(&Integer), sizeof(T));
46 }
47 
48 static Error writeVariableSizedInteger(uint64_t Integer, size_t Size,
49                                        raw_ostream &OS, bool IsLittleEndian) {
50   if (8 == Size)
51     writeInteger((uint64_t)Integer, OS, IsLittleEndian);
52   else if (4 == Size)
53     writeInteger((uint32_t)Integer, OS, IsLittleEndian);
54   else if (2 == Size)
55     writeInteger((uint16_t)Integer, OS, IsLittleEndian);
56   else if (1 == Size)
57     writeInteger((uint8_t)Integer, OS, IsLittleEndian);
58   else
59     return createStringError(errc::not_supported,
60                              "invalid integer write size: %zu", Size);
61 
62   return Error::success();
63 }
64 
65 static void ZeroFillBytes(raw_ostream &OS, size_t Size) {
66   std::vector<uint8_t> FillData(Size, 0);
67   OS.write(reinterpret_cast<char *>(FillData.data()), Size);
68 }
69 
70 static void writeInitialLength(const dwarf::DwarfFormat Format,
71                                const uint64_t Length, raw_ostream &OS,
72                                bool IsLittleEndian) {
73   bool IsDWARF64 = Format == dwarf::DWARF64;
74   if (IsDWARF64)
75     cantFail(writeVariableSizedInteger(dwarf::DW_LENGTH_DWARF64, 4, OS,
76                                        IsLittleEndian));
77   cantFail(
78       writeVariableSizedInteger(Length, IsDWARF64 ? 8 : 4, OS, IsLittleEndian));
79 }
80 
81 static void writeDWARFOffset(uint64_t Offset, dwarf::DwarfFormat Format,
82                              raw_ostream &OS, bool IsLittleEndian) {
83   cantFail(writeVariableSizedInteger(Offset, Format == dwarf::DWARF64 ? 8 : 4,
84                                      OS, IsLittleEndian));
85 }
86 
87 Error DWARFYAML::emitDebugStr(raw_ostream &OS, const DWARFYAML::Data &DI) {
88   for (StringRef Str : *DI.DebugStrings) {
89     OS.write(Str.data(), Str.size());
90     OS.write('\0');
91   }
92 
93   return Error::success();
94 }
95 
96 StringRef DWARFYAML::Data::getAbbrevTableContentByIndex(uint64_t Index) const {
97   assert(Index < DebugAbbrev.size() &&
98          "Index should be less than the size of DebugAbbrev array");
99   auto It = AbbrevTableContents.find(Index);
100   if (It != AbbrevTableContents.cend())
101     return It->second;
102 
103   std::string AbbrevTableBuffer;
104   raw_string_ostream OS(AbbrevTableBuffer);
105 
106   uint64_t AbbrevCode = 0;
107   for (const DWARFYAML::Abbrev &AbbrevDecl : DebugAbbrev[Index].Table) {
108     AbbrevCode = AbbrevDecl.Code ? (uint64_t)*AbbrevDecl.Code : AbbrevCode + 1;
109     encodeULEB128(AbbrevCode, OS);
110     encodeULEB128(AbbrevDecl.Tag, OS);
111     OS.write(AbbrevDecl.Children);
112     for (const auto &Attr : AbbrevDecl.Attributes) {
113       encodeULEB128(Attr.Attribute, OS);
114       encodeULEB128(Attr.Form, OS);
115       if (Attr.Form == dwarf::DW_FORM_implicit_const)
116         encodeSLEB128(Attr.Value, OS);
117     }
118     encodeULEB128(0, OS);
119     encodeULEB128(0, OS);
120   }
121 
122   // The abbreviations for a given compilation unit end with an entry
123   // consisting of a 0 byte for the abbreviation code.
124   OS.write_zeros(1);
125 
126   AbbrevTableContents.insert({Index, AbbrevTableBuffer});
127 
128   return AbbrevTableContents[Index];
129 }
130 
131 Error DWARFYAML::emitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) {
132   for (uint64_t I = 0; I < DI.DebugAbbrev.size(); ++I) {
133     StringRef AbbrevTableContent = DI.getAbbrevTableContentByIndex(I);
134     OS.write(AbbrevTableContent.data(), AbbrevTableContent.size());
135   }
136 
137   return Error::success();
138 }
139 
140 Error DWARFYAML::emitDebugAranges(raw_ostream &OS, const DWARFYAML::Data &DI) {
141   assert(DI.DebugAranges && "unexpected emitDebugAranges() call");
142   for (const auto &Range : *DI.DebugAranges) {
143     uint8_t AddrSize;
144     if (Range.AddrSize)
145       AddrSize = *Range.AddrSize;
146     else
147       AddrSize = DI.Is64BitAddrSize ? 8 : 4;
148 
149     uint64_t Length = 4; // sizeof(version) 2 + sizeof(address_size) 1 +
150                          // sizeof(segment_selector_size) 1
151     Length +=
152         Range.Format == dwarf::DWARF64 ? 8 : 4; // sizeof(debug_info_offset)
153 
154     const uint64_t HeaderLength =
155         Length + (Range.Format == dwarf::DWARF64
156                       ? 12
157                       : 4); // sizeof(unit_header) = 12 (DWARF64) or 4 (DWARF32)
158     const uint64_t PaddedHeaderLength = alignTo(HeaderLength, AddrSize * 2);
159 
160     if (Range.Length) {
161       Length = *Range.Length;
162     } else {
163       Length += PaddedHeaderLength - HeaderLength;
164       Length += AddrSize * 2 * (Range.Descriptors.size() + 1);
165     }
166 
167     writeInitialLength(Range.Format, Length, OS, DI.IsLittleEndian);
168     writeInteger((uint16_t)Range.Version, OS, DI.IsLittleEndian);
169     writeDWARFOffset(Range.CuOffset, Range.Format, OS, DI.IsLittleEndian);
170     writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
171     writeInteger((uint8_t)Range.SegSize, OS, DI.IsLittleEndian);
172     ZeroFillBytes(OS, PaddedHeaderLength - HeaderLength);
173 
174     for (const auto &Descriptor : Range.Descriptors) {
175       if (Error Err = writeVariableSizedInteger(Descriptor.Address, AddrSize,
176                                                 OS, DI.IsLittleEndian))
177         return createStringError(errc::not_supported,
178                                  "unable to write debug_aranges address: %s",
179                                  toString(std::move(Err)).c_str());
180       cantFail(writeVariableSizedInteger(Descriptor.Length, AddrSize, OS,
181                                          DI.IsLittleEndian));
182     }
183     ZeroFillBytes(OS, AddrSize * 2);
184   }
185 
186   return Error::success();
187 }
188 
189 Error DWARFYAML::emitDebugRanges(raw_ostream &OS, const DWARFYAML::Data &DI) {
190   const size_t RangesOffset = OS.tell();
191   uint64_t EntryIndex = 0;
192   for (const auto &DebugRanges : *DI.DebugRanges) {
193     const size_t CurrOffset = OS.tell() - RangesOffset;
194     if (DebugRanges.Offset && (uint64_t)*DebugRanges.Offset < CurrOffset)
195       return createStringError(errc::invalid_argument,
196                                "'Offset' for 'debug_ranges' with index " +
197                                    Twine(EntryIndex) +
198                                    " must be greater than or equal to the "
199                                    "number of bytes written already (0x" +
200                                    Twine::utohexstr(CurrOffset) + ")");
201     if (DebugRanges.Offset)
202       ZeroFillBytes(OS, *DebugRanges.Offset - CurrOffset);
203 
204     uint8_t AddrSize;
205     if (DebugRanges.AddrSize)
206       AddrSize = *DebugRanges.AddrSize;
207     else
208       AddrSize = DI.Is64BitAddrSize ? 8 : 4;
209     for (const auto &Entry : DebugRanges.Entries) {
210       if (Error Err = writeVariableSizedInteger(Entry.LowOffset, AddrSize, OS,
211                                                 DI.IsLittleEndian))
212         return createStringError(
213             errc::not_supported,
214             "unable to write debug_ranges address offset: %s",
215             toString(std::move(Err)).c_str());
216       cantFail(writeVariableSizedInteger(Entry.HighOffset, AddrSize, OS,
217                                          DI.IsLittleEndian));
218     }
219     ZeroFillBytes(OS, AddrSize * 2);
220     ++EntryIndex;
221   }
222 
223   return Error::success();
224 }
225 
226 static Error emitPubSection(raw_ostream &OS, const DWARFYAML::PubSection &Sect,
227                             bool IsLittleEndian, bool IsGNUPubSec = false) {
228   writeInitialLength(Sect.Format, Sect.Length, OS, IsLittleEndian);
229   writeInteger((uint16_t)Sect.Version, OS, IsLittleEndian);
230   writeInteger((uint32_t)Sect.UnitOffset, OS, IsLittleEndian);
231   writeInteger((uint32_t)Sect.UnitSize, OS, IsLittleEndian);
232   for (const auto &Entry : Sect.Entries) {
233     writeInteger((uint32_t)Entry.DieOffset, OS, IsLittleEndian);
234     if (IsGNUPubSec)
235       writeInteger((uint8_t)Entry.Descriptor, OS, IsLittleEndian);
236     OS.write(Entry.Name.data(), Entry.Name.size());
237     OS.write('\0');
238   }
239   return Error::success();
240 }
241 
242 Error DWARFYAML::emitDebugPubnames(raw_ostream &OS, const Data &DI) {
243   assert(DI.PubNames && "unexpected emitDebugPubnames() call");
244   return emitPubSection(OS, *DI.PubNames, DI.IsLittleEndian);
245 }
246 
247 Error DWARFYAML::emitDebugPubtypes(raw_ostream &OS, const Data &DI) {
248   assert(DI.PubTypes && "unexpected emitDebugPubtypes() call");
249   return emitPubSection(OS, *DI.PubTypes, DI.IsLittleEndian);
250 }
251 
252 Error DWARFYAML::emitDebugGNUPubnames(raw_ostream &OS, const Data &DI) {
253   assert(DI.GNUPubNames && "unexpected emitDebugGNUPubnames() call");
254   return emitPubSection(OS, *DI.GNUPubNames, DI.IsLittleEndian,
255                         /*IsGNUStyle=*/true);
256 }
257 
258 Error DWARFYAML::emitDebugGNUPubtypes(raw_ostream &OS, const Data &DI) {
259   assert(DI.GNUPubTypes && "unexpected emitDebugGNUPubtypes() call");
260   return emitPubSection(OS, *DI.GNUPubTypes, DI.IsLittleEndian,
261                         /*IsGNUStyle=*/true);
262 }
263 
264 static Expected<uint64_t> writeDIE(const DWARFYAML::Data &DI, uint64_t CUIndex,
265                                    uint64_t AbbrevTableID,
266                                    const dwarf::FormParams &Params,
267                                    const DWARFYAML::Entry &Entry,
268                                    raw_ostream &OS, bool IsLittleEndian) {
269   uint64_t EntryBegin = OS.tell();
270   encodeULEB128(Entry.AbbrCode, OS);
271   uint32_t AbbrCode = Entry.AbbrCode;
272   if (AbbrCode == 0 || Entry.Values.empty())
273     return OS.tell() - EntryBegin;
274 
275   Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =
276       DI.getAbbrevTableInfoByID(AbbrevTableID);
277   if (!AbbrevTableInfoOrErr)
278     return createStringError(errc::invalid_argument,
279                              toString(AbbrevTableInfoOrErr.takeError()) +
280                                  " for compilation unit with index " +
281                                  utostr(CUIndex));
282 
283   ArrayRef<DWARFYAML::Abbrev> AbbrevDecls(
284       DI.DebugAbbrev[AbbrevTableInfoOrErr->Index].Table);
285 
286   if (AbbrCode > AbbrevDecls.size())
287     return createStringError(
288         errc::invalid_argument,
289         "abbrev code must be less than or equal to the number of "
290         "entries in abbreviation table");
291   const DWARFYAML::Abbrev &Abbrev = AbbrevDecls[AbbrCode - 1];
292   auto FormVal = Entry.Values.begin();
293   auto AbbrForm = Abbrev.Attributes.begin();
294   for (; FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end();
295        ++FormVal, ++AbbrForm) {
296     dwarf::Form Form = AbbrForm->Form;
297     bool Indirect;
298     do {
299       Indirect = false;
300       switch (Form) {
301       case dwarf::DW_FORM_addr:
302         // TODO: Test this error.
303         if (Error Err = writeVariableSizedInteger(
304                 FormVal->Value, Params.AddrSize, OS, IsLittleEndian))
305           return std::move(Err);
306         break;
307       case dwarf::DW_FORM_ref_addr:
308         // TODO: Test this error.
309         if (Error Err = writeVariableSizedInteger(FormVal->Value,
310                                                   Params.getRefAddrByteSize(),
311                                                   OS, IsLittleEndian))
312           return std::move(Err);
313         break;
314       case dwarf::DW_FORM_exprloc:
315       case dwarf::DW_FORM_block:
316         encodeULEB128(FormVal->BlockData.size(), OS);
317         OS.write((const char *)FormVal->BlockData.data(),
318                  FormVal->BlockData.size());
319         break;
320       case dwarf::DW_FORM_block1: {
321         writeInteger((uint8_t)FormVal->BlockData.size(), OS, IsLittleEndian);
322         OS.write((const char *)FormVal->BlockData.data(),
323                  FormVal->BlockData.size());
324         break;
325       }
326       case dwarf::DW_FORM_block2: {
327         writeInteger((uint16_t)FormVal->BlockData.size(), OS, IsLittleEndian);
328         OS.write((const char *)FormVal->BlockData.data(),
329                  FormVal->BlockData.size());
330         break;
331       }
332       case dwarf::DW_FORM_block4: {
333         writeInteger((uint32_t)FormVal->BlockData.size(), OS, IsLittleEndian);
334         OS.write((const char *)FormVal->BlockData.data(),
335                  FormVal->BlockData.size());
336         break;
337       }
338       case dwarf::DW_FORM_strx:
339       case dwarf::DW_FORM_addrx:
340       case dwarf::DW_FORM_rnglistx:
341       case dwarf::DW_FORM_loclistx:
342       case dwarf::DW_FORM_udata:
343       case dwarf::DW_FORM_ref_udata:
344       case dwarf::DW_FORM_GNU_addr_index:
345       case dwarf::DW_FORM_GNU_str_index:
346         encodeULEB128(FormVal->Value, OS);
347         break;
348       case dwarf::DW_FORM_data1:
349       case dwarf::DW_FORM_ref1:
350       case dwarf::DW_FORM_flag:
351       case dwarf::DW_FORM_strx1:
352       case dwarf::DW_FORM_addrx1:
353         writeInteger((uint8_t)FormVal->Value, OS, IsLittleEndian);
354         break;
355       case dwarf::DW_FORM_data2:
356       case dwarf::DW_FORM_ref2:
357       case dwarf::DW_FORM_strx2:
358       case dwarf::DW_FORM_addrx2:
359         writeInteger((uint16_t)FormVal->Value, OS, IsLittleEndian);
360         break;
361       case dwarf::DW_FORM_data4:
362       case dwarf::DW_FORM_ref4:
363       case dwarf::DW_FORM_ref_sup4:
364       case dwarf::DW_FORM_strx4:
365       case dwarf::DW_FORM_addrx4:
366         writeInteger((uint32_t)FormVal->Value, OS, IsLittleEndian);
367         break;
368       case dwarf::DW_FORM_data8:
369       case dwarf::DW_FORM_ref8:
370       case dwarf::DW_FORM_ref_sup8:
371       case dwarf::DW_FORM_ref_sig8:
372         writeInteger((uint64_t)FormVal->Value, OS, IsLittleEndian);
373         break;
374       case dwarf::DW_FORM_sdata:
375         encodeSLEB128(FormVal->Value, OS);
376         break;
377       case dwarf::DW_FORM_string:
378         OS.write(FormVal->CStr.data(), FormVal->CStr.size());
379         OS.write('\0');
380         break;
381       case dwarf::DW_FORM_indirect:
382         encodeULEB128(FormVal->Value, OS);
383         Indirect = true;
384         Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value);
385         ++FormVal;
386         break;
387       case dwarf::DW_FORM_strp:
388       case dwarf::DW_FORM_sec_offset:
389       case dwarf::DW_FORM_GNU_ref_alt:
390       case dwarf::DW_FORM_GNU_strp_alt:
391       case dwarf::DW_FORM_line_strp:
392       case dwarf::DW_FORM_strp_sup:
393         cantFail(writeVariableSizedInteger(FormVal->Value,
394                                            Params.getDwarfOffsetByteSize(), OS,
395                                            IsLittleEndian));
396         break;
397       default:
398         break;
399       }
400     } while (Indirect);
401   }
402 
403   return OS.tell() - EntryBegin;
404 }
405 
406 Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {
407   for (uint64_t I = 0; I < DI.Units.size(); ++I) {
408     const DWARFYAML::Unit &Unit = DI.Units[I];
409     uint8_t AddrSize;
410     if (Unit.AddrSize)
411       AddrSize = *Unit.AddrSize;
412     else
413       AddrSize = DI.Is64BitAddrSize ? 8 : 4;
414     dwarf::FormParams Params = {Unit.Version, AddrSize, Unit.Format};
415     uint64_t Length = 3; // sizeof(version) + sizeof(address_size)
416     Length += Params.getDwarfOffsetByteSize(); // sizeof(debug_abbrev_offset)
417     if (Unit.Version >= 5) {
418       ++Length; // sizeof(unit_type)
419       switch (Unit.Type) {
420       case dwarf::DW_UT_compile:
421       case dwarf::DW_UT_partial:
422       default:
423         break;
424       case dwarf::DW_UT_type:
425       case dwarf::DW_UT_split_type:
426         // sizeof(type_signature) + sizeof(type_offset)
427         Length += 8 + Params.getDwarfOffsetByteSize();
428         break;
429       case dwarf::DW_UT_skeleton:
430       case dwarf::DW_UT_split_compile:
431         Length += 8; // sizeof(dwo_id)
432       }
433     }
434 
435     // Since the length of the current compilation unit is undetermined yet, we
436     // firstly write the content of the compilation unit to a buffer to
437     // calculate it and then serialize the buffer content to the actual output
438     // stream.
439     std::string EntryBuffer;
440     raw_string_ostream EntryBufferOS(EntryBuffer);
441 
442     uint64_t AbbrevTableID = Unit.AbbrevTableID.value_or(I);
443     for (const DWARFYAML::Entry &Entry : Unit.Entries) {
444       if (Expected<uint64_t> EntryLength =
445               writeDIE(DI, I, AbbrevTableID, Params, Entry, EntryBufferOS,
446                        DI.IsLittleEndian))
447         Length += *EntryLength;
448       else
449         return EntryLength.takeError();
450     }
451 
452     // If the length is specified in the YAML description, we use it instead of
453     // the actual length.
454     if (Unit.Length)
455       Length = *Unit.Length;
456 
457     writeInitialLength(Unit.Format, Length, OS, DI.IsLittleEndian);
458     writeInteger((uint16_t)Unit.Version, OS, DI.IsLittleEndian);
459 
460     uint64_t AbbrevTableOffset = 0;
461     if (Unit.AbbrOffset) {
462       AbbrevTableOffset = *Unit.AbbrOffset;
463     } else {
464       if (Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =
465               DI.getAbbrevTableInfoByID(AbbrevTableID)) {
466         AbbrevTableOffset = AbbrevTableInfoOrErr->Offset;
467       } else {
468         // The current compilation unit may not have DIEs and it will not be
469         // able to find the associated abbrev table. We consume the error and
470         // assign 0 to the debug_abbrev_offset in such circumstances.
471         consumeError(AbbrevTableInfoOrErr.takeError());
472       }
473     }
474 
475     if (Unit.Version >= 5) {
476       writeInteger((uint8_t)Unit.Type, OS, DI.IsLittleEndian);
477       writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
478       writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);
479       switch (Unit.Type) {
480       case dwarf::DW_UT_compile:
481       case dwarf::DW_UT_partial:
482       default:
483         break;
484       case dwarf::DW_UT_type:
485       case dwarf::DW_UT_split_type:
486         writeInteger(Unit.TypeSignatureOrDwoID, OS, DI.IsLittleEndian);
487         writeDWARFOffset(Unit.TypeOffset, Unit.Format, OS, DI.IsLittleEndian);
488         break;
489       case dwarf::DW_UT_skeleton:
490       case dwarf::DW_UT_split_compile:
491         writeInteger(Unit.TypeSignatureOrDwoID, OS, DI.IsLittleEndian);
492         break;
493       }
494     } else {
495       writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);
496       writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
497     }
498 
499     OS.write(EntryBuffer.data(), EntryBuffer.size());
500   }
501 
502   return Error::success();
503 }
504 
505 static void emitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) {
506   OS.write(File.Name.data(), File.Name.size());
507   OS.write('\0');
508   encodeULEB128(File.DirIdx, OS);
509   encodeULEB128(File.ModTime, OS);
510   encodeULEB128(File.Length, OS);
511 }
512 
513 static void writeExtendedOpcode(const DWARFYAML::LineTableOpcode &Op,
514                                 uint8_t AddrSize, bool IsLittleEndian,
515                                 raw_ostream &OS) {
516   // The first byte of extended opcodes is a zero byte. The next bytes are an
517   // ULEB128 integer giving the number of bytes in the instruction itself (does
518   // not include the first zero byte or the size). We serialize the instruction
519   // itself into the OpBuffer and then write the size of the buffer and the
520   // buffer to the real output stream.
521   std::string OpBuffer;
522   raw_string_ostream OpBufferOS(OpBuffer);
523   writeInteger((uint8_t)Op.SubOpcode, OpBufferOS, IsLittleEndian);
524   switch (Op.SubOpcode) {
525   case dwarf::DW_LNE_set_address:
526     cantFail(writeVariableSizedInteger(Op.Data, AddrSize, OpBufferOS,
527                                        IsLittleEndian));
528     break;
529   case dwarf::DW_LNE_define_file:
530     emitFileEntry(OpBufferOS, Op.FileEntry);
531     break;
532   case dwarf::DW_LNE_set_discriminator:
533     encodeULEB128(Op.Data, OpBufferOS);
534     break;
535   case dwarf::DW_LNE_end_sequence:
536     break;
537   default:
538     for (auto OpByte : Op.UnknownOpcodeData)
539       writeInteger((uint8_t)OpByte, OpBufferOS, IsLittleEndian);
540   }
541   uint64_t ExtLen = Op.ExtLen.value_or(OpBuffer.size());
542   encodeULEB128(ExtLen, OS);
543   OS.write(OpBuffer.data(), OpBuffer.size());
544 }
545 
546 static void writeLineTableOpcode(const DWARFYAML::LineTableOpcode &Op,
547                                  uint8_t OpcodeBase, uint8_t AddrSize,
548                                  raw_ostream &OS, bool IsLittleEndian) {
549   writeInteger((uint8_t)Op.Opcode, OS, IsLittleEndian);
550   if (Op.Opcode == 0) {
551     writeExtendedOpcode(Op, AddrSize, IsLittleEndian, OS);
552   } else if (Op.Opcode < OpcodeBase) {
553     switch (Op.Opcode) {
554     case dwarf::DW_LNS_copy:
555     case dwarf::DW_LNS_negate_stmt:
556     case dwarf::DW_LNS_set_basic_block:
557     case dwarf::DW_LNS_const_add_pc:
558     case dwarf::DW_LNS_set_prologue_end:
559     case dwarf::DW_LNS_set_epilogue_begin:
560       break;
561 
562     case dwarf::DW_LNS_advance_pc:
563     case dwarf::DW_LNS_set_file:
564     case dwarf::DW_LNS_set_column:
565     case dwarf::DW_LNS_set_isa:
566       encodeULEB128(Op.Data, OS);
567       break;
568 
569     case dwarf::DW_LNS_advance_line:
570       encodeSLEB128(Op.SData, OS);
571       break;
572 
573     case dwarf::DW_LNS_fixed_advance_pc:
574       writeInteger((uint16_t)Op.Data, OS, IsLittleEndian);
575       break;
576 
577     default:
578       for (auto OpData : Op.StandardOpcodeData) {
579         encodeULEB128(OpData, OS);
580       }
581     }
582   }
583 }
584 
585 static std::vector<uint8_t>
586 getStandardOpcodeLengths(uint16_t Version, std::optional<uint8_t> OpcodeBase) {
587   // If the opcode_base field isn't specified, we returns the
588   // standard_opcode_lengths array according to the version by default.
589   std::vector<uint8_t> StandardOpcodeLengths{0, 1, 1, 1, 1, 0,
590                                              0, 0, 1, 0, 0, 1};
591   if (Version == 2) {
592     // DWARF v2 uses the same first 9 standard opcodes as v3-5.
593     StandardOpcodeLengths.resize(9);
594   } else if (OpcodeBase) {
595     StandardOpcodeLengths.resize(*OpcodeBase > 0 ? *OpcodeBase - 1 : 0, 0);
596   }
597   return StandardOpcodeLengths;
598 }
599 
600 Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) {
601   for (const DWARFYAML::LineTable &LineTable : DI.DebugLines) {
602     // Buffer holds the bytes following the header_length (or prologue_length in
603     // DWARFv2) field to the end of the line number program itself.
604     std::string Buffer;
605     raw_string_ostream BufferOS(Buffer);
606 
607     writeInteger(LineTable.MinInstLength, BufferOS, DI.IsLittleEndian);
608     // TODO: Add support for emitting DWARFv5 line table.
609     if (LineTable.Version >= 4)
610       writeInteger(LineTable.MaxOpsPerInst, BufferOS, DI.IsLittleEndian);
611     writeInteger(LineTable.DefaultIsStmt, BufferOS, DI.IsLittleEndian);
612     writeInteger(LineTable.LineBase, BufferOS, DI.IsLittleEndian);
613     writeInteger(LineTable.LineRange, BufferOS, DI.IsLittleEndian);
614 
615     std::vector<uint8_t> StandardOpcodeLengths =
616         LineTable.StandardOpcodeLengths.value_or(
617             getStandardOpcodeLengths(LineTable.Version, LineTable.OpcodeBase));
618     uint8_t OpcodeBase = LineTable.OpcodeBase
619                              ? *LineTable.OpcodeBase
620                              : StandardOpcodeLengths.size() + 1;
621     writeInteger(OpcodeBase, BufferOS, DI.IsLittleEndian);
622     for (uint8_t OpcodeLength : StandardOpcodeLengths)
623       writeInteger(OpcodeLength, BufferOS, DI.IsLittleEndian);
624 
625     for (StringRef IncludeDir : LineTable.IncludeDirs) {
626       BufferOS.write(IncludeDir.data(), IncludeDir.size());
627       BufferOS.write('\0');
628     }
629     BufferOS.write('\0');
630 
631     for (const DWARFYAML::File &File : LineTable.Files)
632       emitFileEntry(BufferOS, File);
633     BufferOS.write('\0');
634 
635     uint64_t HeaderLength =
636         LineTable.PrologueLength ? *LineTable.PrologueLength : Buffer.size();
637 
638     for (const DWARFYAML::LineTableOpcode &Op : LineTable.Opcodes)
639       writeLineTableOpcode(Op, OpcodeBase, DI.Is64BitAddrSize ? 8 : 4, BufferOS,
640                            DI.IsLittleEndian);
641 
642     uint64_t Length;
643     if (LineTable.Length) {
644       Length = *LineTable.Length;
645     } else {
646       Length = 2; // sizeof(version)
647       Length +=
648           (LineTable.Format == dwarf::DWARF64 ? 8 : 4); // sizeof(header_length)
649       Length += Buffer.size();
650     }
651 
652     writeInitialLength(LineTable.Format, Length, OS, DI.IsLittleEndian);
653     writeInteger(LineTable.Version, OS, DI.IsLittleEndian);
654     writeDWARFOffset(HeaderLength, LineTable.Format, OS, DI.IsLittleEndian);
655     OS.write(Buffer.data(), Buffer.size());
656   }
657 
658   return Error::success();
659 }
660 
661 Error DWARFYAML::emitDebugAddr(raw_ostream &OS, const Data &DI) {
662   for (const AddrTableEntry &TableEntry : *DI.DebugAddr) {
663     uint8_t AddrSize;
664     if (TableEntry.AddrSize)
665       AddrSize = *TableEntry.AddrSize;
666     else
667       AddrSize = DI.Is64BitAddrSize ? 8 : 4;
668 
669     uint64_t Length;
670     if (TableEntry.Length)
671       Length = (uint64_t)*TableEntry.Length;
672     else
673       // 2 (version) + 1 (address_size) + 1 (segment_selector_size) = 4
674       Length = 4 + (AddrSize + TableEntry.SegSelectorSize) *
675                        TableEntry.SegAddrPairs.size();
676 
677     writeInitialLength(TableEntry.Format, Length, OS, DI.IsLittleEndian);
678     writeInteger((uint16_t)TableEntry.Version, OS, DI.IsLittleEndian);
679     writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
680     writeInteger((uint8_t)TableEntry.SegSelectorSize, OS, DI.IsLittleEndian);
681 
682     for (const SegAddrPair &Pair : TableEntry.SegAddrPairs) {
683       if (TableEntry.SegSelectorSize != yaml::Hex8{0})
684         if (Error Err = writeVariableSizedInteger(Pair.Segment,
685                                                   TableEntry.SegSelectorSize,
686                                                   OS, DI.IsLittleEndian))
687           return createStringError(errc::not_supported,
688                                    "unable to write debug_addr segment: %s",
689                                    toString(std::move(Err)).c_str());
690       if (AddrSize != 0)
691         if (Error Err = writeVariableSizedInteger(Pair.Address, AddrSize, OS,
692                                                   DI.IsLittleEndian))
693           return createStringError(errc::not_supported,
694                                    "unable to write debug_addr address: %s",
695                                    toString(std::move(Err)).c_str());
696     }
697   }
698 
699   return Error::success();
700 }
701 
702 Error DWARFYAML::emitDebugStrOffsets(raw_ostream &OS, const Data &DI) {
703   assert(DI.DebugStrOffsets && "unexpected emitDebugStrOffsets() call");
704   for (const DWARFYAML::StringOffsetsTable &Table : *DI.DebugStrOffsets) {
705     uint64_t Length;
706     if (Table.Length)
707       Length = *Table.Length;
708     else
709       // sizeof(version) + sizeof(padding) = 4
710       Length =
711           4 + Table.Offsets.size() * (Table.Format == dwarf::DWARF64 ? 8 : 4);
712 
713     writeInitialLength(Table.Format, Length, OS, DI.IsLittleEndian);
714     writeInteger((uint16_t)Table.Version, OS, DI.IsLittleEndian);
715     writeInteger((uint16_t)Table.Padding, OS, DI.IsLittleEndian);
716 
717     for (uint64_t Offset : Table.Offsets)
718       writeDWARFOffset(Offset, Table.Format, OS, DI.IsLittleEndian);
719   }
720 
721   return Error::success();
722 }
723 
724 namespace {
725 /// Emits the header for a DebugNames section.
726 void emitDebugNamesHeader(raw_ostream &OS, bool IsLittleEndian,
727                           uint32_t NameCount, uint32_t AbbrevSize,
728                           uint32_t CombinedSizeOtherParts) {
729   // Use the same AugmentationString as AsmPrinter.
730   StringRef AugmentationString = "LLVM0700";
731   size_t TotalSize = CombinedSizeOtherParts + 5 * sizeof(uint32_t) +
732                      2 * sizeof(uint16_t) + sizeof(NameCount) +
733                      sizeof(AbbrevSize) + AugmentationString.size();
734   writeInteger(uint32_t(TotalSize), OS, IsLittleEndian); // Unit length
735 
736   // Everything below is included in total size.
737   writeInteger(uint16_t(5), OS, IsLittleEndian); // Version
738   writeInteger(uint16_t(0), OS, IsLittleEndian); // Padding
739   writeInteger(uint32_t(1), OS, IsLittleEndian); // Compilation Unit count
740   writeInteger(uint32_t(0), OS, IsLittleEndian); // Local Type Unit count
741   writeInteger(uint32_t(0), OS, IsLittleEndian); // Foreign Type Unit count
742   writeInteger(uint32_t(0), OS, IsLittleEndian); // Bucket count
743   writeInteger(NameCount, OS, IsLittleEndian);
744   writeInteger(AbbrevSize, OS, IsLittleEndian);
745   writeInteger(uint32_t(AugmentationString.size()), OS, IsLittleEndian);
746   OS.write(AugmentationString.data(), AugmentationString.size());
747 }
748 
749 /// Emits the abbreviations for a DebugNames section.
750 std::string
751 emitDebugNamesAbbrev(ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {
752   std::string Data;
753   raw_string_ostream OS(Data);
754   for (const DWARFYAML::DebugNameAbbreviation &Abbrev : Abbrevs) {
755     encodeULEB128(Abbrev.Code, OS);
756     encodeULEB128(Abbrev.Tag, OS);
757     for (auto [Idx, Form] : Abbrev.Indices) {
758       encodeULEB128(Idx, OS);
759       encodeULEB128(Form, OS);
760     }
761     encodeULEB128(0, OS);
762     encodeULEB128(0, OS);
763   }
764   encodeULEB128(0, OS);
765   return Data;
766 }
767 
768 /// Emits a simple CU offsets list for a DebugNames section containing a single
769 /// CU at offset 0.
770 std::string emitDebugNamesCUOffsets(bool IsLittleEndian) {
771   std::string Data;
772   raw_string_ostream OS(Data);
773   writeInteger(uint32_t(0), OS, IsLittleEndian);
774   return Data;
775 }
776 
777 /// Emits the "NameTable" for a DebugNames section; according to the spec, it
778 /// consists of two arrays: an array of string offsets, followed immediately by
779 /// an array of entry offsets. The string offsets are emitted in the order
780 /// provided in `Entries`.
781 std::string emitDebugNamesNameTable(
782     bool IsLittleEndian,
783     const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> &Entries,
784     ArrayRef<uint32_t> EntryPoolOffsets) {
785   assert(Entries.size() == EntryPoolOffsets.size());
786 
787   std::string Data;
788   raw_string_ostream OS(Data);
789 
790   for (uint32_t Strp : make_first_range(Entries))
791     writeInteger(Strp, OS, IsLittleEndian);
792   for (uint32_t PoolOffset : EntryPoolOffsets)
793     writeInteger(PoolOffset, OS, IsLittleEndian);
794   return Data;
795 }
796 
797 /// Groups entries based on their name (strp) code and returns a map.
798 DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>>
799 groupEntries(ArrayRef<DWARFYAML::DebugNameEntry> Entries) {
800   DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> StrpToEntries;
801   for (const DWARFYAML::DebugNameEntry &Entry : Entries)
802     StrpToEntries[Entry.NameStrp].push_back(Entry);
803   return StrpToEntries;
804 }
805 
806 /// Finds the abbreviation whose code is AbbrevCode and returns a list
807 /// containing the expected size of all non-zero-length forms.
808 Expected<SmallVector<uint8_t>>
809 getNonZeroDataSizesFor(uint32_t AbbrevCode,
810                        ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {
811   const auto *AbbrevIt = find_if(Abbrevs, [&](const auto &Abbrev) {
812     return Abbrev.Code.value == AbbrevCode;
813   });
814   if (AbbrevIt == Abbrevs.end())
815     return createStringError(inconvertibleErrorCode(),
816                              "did not find an Abbreviation for this code");
817 
818   SmallVector<uint8_t> DataSizes;
819   dwarf::FormParams Params{/*Version=*/5, /*AddrSize=*/4, dwarf::DWARF32};
820   for (auto [Idx, Form] : AbbrevIt->Indices) {
821     std::optional<uint8_t> FormSize = dwarf::getFixedFormByteSize(Form, Params);
822     if (!FormSize)
823       return createStringError(inconvertibleErrorCode(),
824                                "unsupported Form for YAML debug_names emitter");
825     if (FormSize == 0)
826       continue;
827     DataSizes.push_back(*FormSize);
828   }
829   return DataSizes;
830 }
831 
832 struct PoolOffsetsAndData {
833   std::string PoolData;
834   std::vector<uint32_t> PoolOffsets;
835 };
836 
837 /// Emits the entry pool and returns an array of offsets containing the start
838 /// offset for the entries of each unique name.
839 /// Verifies that the provided number of data values match those expected by
840 /// the abbreviation table.
841 Expected<PoolOffsetsAndData> emitDebugNamesEntryPool(
842     bool IsLittleEndian,
843     const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>>
844         &StrpToEntries,
845     ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {
846   PoolOffsetsAndData Result;
847   raw_string_ostream OS(Result.PoolData);
848 
849   for (ArrayRef<DWARFYAML::DebugNameEntry> EntriesWithSameName :
850        make_second_range(StrpToEntries)) {
851     Result.PoolOffsets.push_back(Result.PoolData.size());
852 
853     for (const DWARFYAML::DebugNameEntry &Entry : EntriesWithSameName) {
854       encodeULEB128(Entry.Code, OS);
855 
856       Expected<SmallVector<uint8_t>> DataSizes =
857           getNonZeroDataSizesFor(Entry.Code, Abbrevs);
858       if (!DataSizes)
859         return DataSizes.takeError();
860       if (DataSizes->size() != Entry.Values.size())
861         return createStringError(
862             inconvertibleErrorCode(),
863             "mismatch between provided and required number of values");
864 
865       for (auto [Value, ValueSize] : zip_equal(Entry.Values, *DataSizes))
866         if (Error E =
867                 writeVariableSizedInteger(Value, ValueSize, OS, IsLittleEndian))
868           return std::move(E);
869     }
870     encodeULEB128(0, OS);
871   }
872 
873   return Result;
874 }
875 } // namespace
876 
877 Error DWARFYAML::emitDebugNames(raw_ostream &OS, const Data &DI) {
878   assert(DI.DebugNames && "unexpected emitDebugNames() call");
879   const DebugNamesSection DebugNames = DI.DebugNames.value();
880 
881   DenseMap<uint32_t, std::vector<DebugNameEntry>> StrpToEntries =
882       groupEntries(DebugNames.Entries);
883 
884   // Emit all sub-sections into individual strings so that we may compute
885   // relative offsets and sizes.
886   Expected<PoolOffsetsAndData> PoolInfo = emitDebugNamesEntryPool(
887       DI.IsLittleEndian, StrpToEntries, DebugNames.Abbrevs);
888   if (!PoolInfo)
889     return PoolInfo.takeError();
890   std::string NamesTableData = emitDebugNamesNameTable(
891       DI.IsLittleEndian, StrpToEntries, PoolInfo->PoolOffsets);
892 
893   std::string AbbrevData = emitDebugNamesAbbrev(DebugNames.Abbrevs);
894   std::string CUOffsetsData = emitDebugNamesCUOffsets(DI.IsLittleEndian);
895 
896   size_t TotalSize = PoolInfo->PoolData.size() + NamesTableData.size() +
897                      AbbrevData.size() + CUOffsetsData.size();
898 
899   // Start real emission by combining all individual strings.
900   emitDebugNamesHeader(OS, DI.IsLittleEndian, StrpToEntries.size(),
901                        AbbrevData.size(), TotalSize);
902   OS.write(CUOffsetsData.data(), CUOffsetsData.size());
903   // No local TUs, no foreign TUs, no hash lookups table.
904   OS.write(NamesTableData.data(), NamesTableData.size());
905   OS.write(AbbrevData.data(), AbbrevData.size());
906   OS.write(PoolInfo->PoolData.data(), PoolInfo->PoolData.size());
907 
908   return Error::success();
909 }
910 
911 static Error checkOperandCount(StringRef EncodingString,
912                                ArrayRef<yaml::Hex64> Values,
913                                uint64_t ExpectedOperands) {
914   if (Values.size() != ExpectedOperands)
915     return createStringError(
916         errc::invalid_argument,
917         "invalid number (%zu) of operands for the operator: %s, %" PRIu64
918         " expected",
919         Values.size(), EncodingString.str().c_str(), ExpectedOperands);
920 
921   return Error::success();
922 }
923 
924 static Error writeListEntryAddress(StringRef EncodingName, raw_ostream &OS,
925                                    uint64_t Addr, uint8_t AddrSize,
926                                    bool IsLittleEndian) {
927   if (Error Err = writeVariableSizedInteger(Addr, AddrSize, OS, IsLittleEndian))
928     return createStringError(errc::invalid_argument,
929                              "unable to write address for the operator %s: %s",
930                              EncodingName.str().c_str(),
931                              toString(std::move(Err)).c_str());
932 
933   return Error::success();
934 }
935 
936 static Expected<uint64_t>
937 writeDWARFExpression(raw_ostream &OS,
938                      const DWARFYAML::DWARFOperation &Operation,
939                      uint8_t AddrSize, bool IsLittleEndian) {
940   auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
941     return checkOperandCount(dwarf::OperationEncodingString(Operation.Operator),
942                              Operation.Values, ExpectedOperands);
943   };
944 
945   uint64_t ExpressionBegin = OS.tell();
946   writeInteger((uint8_t)Operation.Operator, OS, IsLittleEndian);
947   switch (Operation.Operator) {
948   case dwarf::DW_OP_consts:
949     if (Error Err = CheckOperands(1))
950       return std::move(Err);
951     encodeSLEB128(Operation.Values[0], OS);
952     break;
953   case dwarf::DW_OP_stack_value:
954     if (Error Err = CheckOperands(0))
955       return std::move(Err);
956     break;
957   default:
958     StringRef EncodingStr = dwarf::OperationEncodingString(Operation.Operator);
959     return createStringError(errc::not_supported,
960                              "DWARF expression: " +
961                                  (EncodingStr.empty()
962                                       ? "0x" + utohexstr(Operation.Operator)
963                                       : EncodingStr) +
964                                  " is not supported");
965   }
966   return OS.tell() - ExpressionBegin;
967 }
968 
969 static Expected<uint64_t> writeListEntry(raw_ostream &OS,
970                                          const DWARFYAML::RnglistEntry &Entry,
971                                          uint8_t AddrSize,
972                                          bool IsLittleEndian) {
973   uint64_t BeginOffset = OS.tell();
974   writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);
975 
976   StringRef EncodingName = dwarf::RangeListEncodingString(Entry.Operator);
977 
978   auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
979     return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
980   };
981 
982   auto WriteAddress = [&](uint64_t Addr) -> Error {
983     return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
984                                  IsLittleEndian);
985   };
986 
987   switch (Entry.Operator) {
988   case dwarf::DW_RLE_end_of_list:
989     if (Error Err = CheckOperands(0))
990       return std::move(Err);
991     break;
992   case dwarf::DW_RLE_base_addressx:
993     if (Error Err = CheckOperands(1))
994       return std::move(Err);
995     encodeULEB128(Entry.Values[0], OS);
996     break;
997   case dwarf::DW_RLE_startx_endx:
998   case dwarf::DW_RLE_startx_length:
999   case dwarf::DW_RLE_offset_pair:
1000     if (Error Err = CheckOperands(2))
1001       return std::move(Err);
1002     encodeULEB128(Entry.Values[0], OS);
1003     encodeULEB128(Entry.Values[1], OS);
1004     break;
1005   case dwarf::DW_RLE_base_address:
1006     if (Error Err = CheckOperands(1))
1007       return std::move(Err);
1008     if (Error Err = WriteAddress(Entry.Values[0]))
1009       return std::move(Err);
1010     break;
1011   case dwarf::DW_RLE_start_end:
1012     if (Error Err = CheckOperands(2))
1013       return std::move(Err);
1014     if (Error Err = WriteAddress(Entry.Values[0]))
1015       return std::move(Err);
1016     cantFail(WriteAddress(Entry.Values[1]));
1017     break;
1018   case dwarf::DW_RLE_start_length:
1019     if (Error Err = CheckOperands(2))
1020       return std::move(Err);
1021     if (Error Err = WriteAddress(Entry.Values[0]))
1022       return std::move(Err);
1023     encodeULEB128(Entry.Values[1], OS);
1024     break;
1025   }
1026 
1027   return OS.tell() - BeginOffset;
1028 }
1029 
1030 static Expected<uint64_t> writeListEntry(raw_ostream &OS,
1031                                          const DWARFYAML::LoclistEntry &Entry,
1032                                          uint8_t AddrSize,
1033                                          bool IsLittleEndian) {
1034   uint64_t BeginOffset = OS.tell();
1035   writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);
1036 
1037   StringRef EncodingName = dwarf::LocListEncodingString(Entry.Operator);
1038 
1039   auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
1040     return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
1041   };
1042 
1043   auto WriteAddress = [&](uint64_t Addr) -> Error {
1044     return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
1045                                  IsLittleEndian);
1046   };
1047 
1048   auto WriteDWARFOperations = [&]() -> Error {
1049     std::string OpBuffer;
1050     raw_string_ostream OpBufferOS(OpBuffer);
1051     uint64_t DescriptionsLength = 0;
1052 
1053     for (const DWARFYAML::DWARFOperation &Op : Entry.Descriptions) {
1054       if (Expected<uint64_t> OpSize =
1055               writeDWARFExpression(OpBufferOS, Op, AddrSize, IsLittleEndian))
1056         DescriptionsLength += *OpSize;
1057       else
1058         return OpSize.takeError();
1059     }
1060 
1061     if (Entry.DescriptionsLength)
1062       DescriptionsLength = *Entry.DescriptionsLength;
1063     else
1064       DescriptionsLength = OpBuffer.size();
1065 
1066     encodeULEB128(DescriptionsLength, OS);
1067     OS.write(OpBuffer.data(), OpBuffer.size());
1068 
1069     return Error::success();
1070   };
1071 
1072   switch (Entry.Operator) {
1073   case dwarf::DW_LLE_end_of_list:
1074     if (Error Err = CheckOperands(0))
1075       return std::move(Err);
1076     break;
1077   case dwarf::DW_LLE_base_addressx:
1078     if (Error Err = CheckOperands(1))
1079       return std::move(Err);
1080     encodeULEB128(Entry.Values[0], OS);
1081     break;
1082   case dwarf::DW_LLE_startx_endx:
1083   case dwarf::DW_LLE_startx_length:
1084   case dwarf::DW_LLE_offset_pair:
1085     if (Error Err = CheckOperands(2))
1086       return std::move(Err);
1087     encodeULEB128(Entry.Values[0], OS);
1088     encodeULEB128(Entry.Values[1], OS);
1089     if (Error Err = WriteDWARFOperations())
1090       return std::move(Err);
1091     break;
1092   case dwarf::DW_LLE_default_location:
1093     if (Error Err = CheckOperands(0))
1094       return std::move(Err);
1095     if (Error Err = WriteDWARFOperations())
1096       return std::move(Err);
1097     break;
1098   case dwarf::DW_LLE_base_address:
1099     if (Error Err = CheckOperands(1))
1100       return std::move(Err);
1101     if (Error Err = WriteAddress(Entry.Values[0]))
1102       return std::move(Err);
1103     break;
1104   case dwarf::DW_LLE_start_end:
1105     if (Error Err = CheckOperands(2))
1106       return std::move(Err);
1107     if (Error Err = WriteAddress(Entry.Values[0]))
1108       return std::move(Err);
1109     cantFail(WriteAddress(Entry.Values[1]));
1110     if (Error Err = WriteDWARFOperations())
1111       return std::move(Err);
1112     break;
1113   case dwarf::DW_LLE_start_length:
1114     if (Error Err = CheckOperands(2))
1115       return std::move(Err);
1116     if (Error Err = WriteAddress(Entry.Values[0]))
1117       return std::move(Err);
1118     encodeULEB128(Entry.Values[1], OS);
1119     if (Error Err = WriteDWARFOperations())
1120       return std::move(Err);
1121     break;
1122   }
1123 
1124   return OS.tell() - BeginOffset;
1125 }
1126 
1127 template <typename EntryType>
1128 static Error writeDWARFLists(raw_ostream &OS,
1129                              ArrayRef<DWARFYAML::ListTable<EntryType>> Tables,
1130                              bool IsLittleEndian, bool Is64BitAddrSize) {
1131   for (const DWARFYAML::ListTable<EntryType> &Table : Tables) {
1132     // sizeof(version) + sizeof(address_size) + sizeof(segment_selector_size) +
1133     // sizeof(offset_entry_count) = 8
1134     uint64_t Length = 8;
1135 
1136     uint8_t AddrSize;
1137     if (Table.AddrSize)
1138       AddrSize = *Table.AddrSize;
1139     else
1140       AddrSize = Is64BitAddrSize ? 8 : 4;
1141 
1142     // Since the length of the current range/location lists entry is
1143     // undetermined yet, we firstly write the content of the range/location
1144     // lists to a buffer to calculate the length and then serialize the buffer
1145     // content to the actual output stream.
1146     std::string ListBuffer;
1147     raw_string_ostream ListBufferOS(ListBuffer);
1148 
1149     // Offsets holds offsets for each range/location list. The i-th element is
1150     // the offset from the beginning of the first range/location list to the
1151     // location of the i-th range list.
1152     std::vector<uint64_t> Offsets;
1153 
1154     for (const DWARFYAML::ListEntries<EntryType> &List : Table.Lists) {
1155       Offsets.push_back(ListBufferOS.tell());
1156       if (List.Content) {
1157         List.Content->writeAsBinary(ListBufferOS, UINT64_MAX);
1158         Length += List.Content->binary_size();
1159       } else if (List.Entries) {
1160         for (const EntryType &Entry : *List.Entries) {
1161           Expected<uint64_t> EntrySize =
1162               writeListEntry(ListBufferOS, Entry, AddrSize, IsLittleEndian);
1163           if (!EntrySize)
1164             return EntrySize.takeError();
1165           Length += *EntrySize;
1166         }
1167       }
1168     }
1169 
1170     // If the offset_entry_count field isn't specified, yaml2obj will infer it
1171     // from the 'Offsets' field in the YAML description. If the 'Offsets' field
1172     // isn't specified either, yaml2obj will infer it from the auto-generated
1173     // offsets.
1174     uint32_t OffsetEntryCount;
1175     if (Table.OffsetEntryCount)
1176       OffsetEntryCount = *Table.OffsetEntryCount;
1177     else
1178       OffsetEntryCount = Table.Offsets ? Table.Offsets->size() : Offsets.size();
1179     uint64_t OffsetsSize =
1180         OffsetEntryCount * (Table.Format == dwarf::DWARF64 ? 8 : 4);
1181     Length += OffsetsSize;
1182 
1183     // If the length is specified in the YAML description, we use it instead of
1184     // the actual length.
1185     if (Table.Length)
1186       Length = *Table.Length;
1187 
1188     writeInitialLength(Table.Format, Length, OS, IsLittleEndian);
1189     writeInteger((uint16_t)Table.Version, OS, IsLittleEndian);
1190     writeInteger((uint8_t)AddrSize, OS, IsLittleEndian);
1191     writeInteger((uint8_t)Table.SegSelectorSize, OS, IsLittleEndian);
1192     writeInteger((uint32_t)OffsetEntryCount, OS, IsLittleEndian);
1193 
1194     auto EmitOffsets = [&](ArrayRef<uint64_t> Offsets, uint64_t OffsetsSize) {
1195       for (uint64_t Offset : Offsets)
1196         writeDWARFOffset(OffsetsSize + Offset, Table.Format, OS,
1197                          IsLittleEndian);
1198     };
1199 
1200     if (Table.Offsets)
1201       EmitOffsets(ArrayRef<uint64_t>((const uint64_t *)Table.Offsets->data(),
1202                                      Table.Offsets->size()),
1203                   0);
1204     else if (OffsetEntryCount != 0)
1205       EmitOffsets(Offsets, OffsetsSize);
1206 
1207     OS.write(ListBuffer.data(), ListBuffer.size());
1208   }
1209 
1210   return Error::success();
1211 }
1212 
1213 Error DWARFYAML::emitDebugRnglists(raw_ostream &OS, const Data &DI) {
1214   assert(DI.DebugRnglists && "unexpected emitDebugRnglists() call");
1215   return writeDWARFLists<DWARFYAML::RnglistEntry>(
1216       OS, *DI.DebugRnglists, DI.IsLittleEndian, DI.Is64BitAddrSize);
1217 }
1218 
1219 Error DWARFYAML::emitDebugLoclists(raw_ostream &OS, const Data &DI) {
1220   assert(DI.DebugLoclists && "unexpected emitDebugRnglists() call");
1221   return writeDWARFLists<DWARFYAML::LoclistEntry>(
1222       OS, *DI.DebugLoclists, DI.IsLittleEndian, DI.Is64BitAddrSize);
1223 }
1224 
1225 std::function<Error(raw_ostream &, const DWARFYAML::Data &)>
1226 DWARFYAML::getDWARFEmitterByName(StringRef SecName) {
1227   auto EmitFunc =
1228       StringSwitch<
1229           std::function<Error(raw_ostream &, const DWARFYAML::Data &)>>(SecName)
1230           .Case("debug_abbrev", DWARFYAML::emitDebugAbbrev)
1231           .Case("debug_addr", DWARFYAML::emitDebugAddr)
1232           .Case("debug_aranges", DWARFYAML::emitDebugAranges)
1233           .Case("debug_gnu_pubnames", DWARFYAML::emitDebugGNUPubnames)
1234           .Case("debug_gnu_pubtypes", DWARFYAML::emitDebugGNUPubtypes)
1235           .Case("debug_info", DWARFYAML::emitDebugInfo)
1236           .Case("debug_line", DWARFYAML::emitDebugLine)
1237           .Case("debug_loclists", DWARFYAML::emitDebugLoclists)
1238           .Case("debug_pubnames", DWARFYAML::emitDebugPubnames)
1239           .Case("debug_pubtypes", DWARFYAML::emitDebugPubtypes)
1240           .Case("debug_ranges", DWARFYAML::emitDebugRanges)
1241           .Case("debug_rnglists", DWARFYAML::emitDebugRnglists)
1242           .Case("debug_str", DWARFYAML::emitDebugStr)
1243           .Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets)
1244           .Case("debug_names", DWARFYAML::emitDebugNames)
1245           .Default([&](raw_ostream &, const DWARFYAML::Data &) {
1246             return createStringError(errc::not_supported,
1247                                      SecName + " is not supported");
1248           });
1249 
1250   return EmitFunc;
1251 }
1252 
1253 static Error
1254 emitDebugSectionImpl(const DWARFYAML::Data &DI, StringRef Sec,
1255                      StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) {
1256   std::string Data;
1257   raw_string_ostream DebugInfoStream(Data);
1258 
1259   auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Sec);
1260 
1261   if (Error Err = EmitFunc(DebugInfoStream, DI))
1262     return Err;
1263   DebugInfoStream.flush();
1264   if (!Data.empty())
1265     OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data);
1266 
1267   return Error::success();
1268 }
1269 
1270 Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
1271 DWARFYAML::emitDebugSections(StringRef YAMLString, bool IsLittleEndian,
1272                              bool Is64BitAddrSize) {
1273   auto CollectDiagnostic = [](const SMDiagnostic &Diag, void *DiagContext) {
1274     *static_cast<SMDiagnostic *>(DiagContext) = Diag;
1275   };
1276 
1277   SMDiagnostic GeneratedDiag;
1278   yaml::Input YIn(YAMLString, /*Ctxt=*/nullptr, CollectDiagnostic,
1279                   &GeneratedDiag);
1280 
1281   DWARFYAML::Data DI;
1282   DI.IsLittleEndian = IsLittleEndian;
1283   DI.Is64BitAddrSize = Is64BitAddrSize;
1284 
1285   YIn >> DI;
1286   if (YIn.error())
1287     return createStringError(YIn.error(), GeneratedDiag.getMessage());
1288 
1289   StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;
1290   Error Err = Error::success();
1291 
1292   for (StringRef SecName : DI.getNonEmptySectionNames())
1293     Err = joinErrors(std::move(Err),
1294                      emitDebugSectionImpl(DI, SecName, DebugSections));
1295 
1296   if (Err)
1297     return std::move(Err);
1298   return std::move(DebugSections);
1299 }
1300