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