LLVM 22.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 // TODO: Add support for emitting DWARFv5 line table.
606 if (LineTable.Version >= 4)
611
612 std::vector<uint8_t> StandardOpcodeLengths =
615 uint8_t OpcodeBase = LineTable.OpcodeBase
617 : StandardOpcodeLengths.size() + 1;
618 writeInteger(OpcodeBase, BufferOS, DI.IsLittleEndian);
619 for (uint8_t OpcodeLength : StandardOpcodeLengths)
620 writeInteger(OpcodeLength, BufferOS, DI.IsLittleEndian);
621
622 for (StringRef IncludeDir : LineTable.IncludeDirs) {
623 BufferOS.write(IncludeDir.data(), IncludeDir.size());
624 BufferOS.write('\0');
625 }
626 BufferOS.write('\0');
627
628 for (const DWARFYAML::File &File : LineTable.Files)
629 emitFileEntry(BufferOS, File);
630 BufferOS.write('\0');
631
632 uint64_t HeaderLength =
634
636 writeLineTableOpcode(Op, OpcodeBase, DI.Is64BitAddrSize ? 8 : 4, BufferOS,
637 DI.IsLittleEndian);
638
640 if (LineTable.Length) {
642 } else {
643 Length = 2; // sizeof(version)
644 Length +=
645 (LineTable.Format == dwarf::DWARF64 ? 8 : 4); // sizeof(header_length)
646 Length += Buffer.size();
647 }
648
651 writeDWARFOffset(HeaderLength, LineTable.Format, OS, DI.IsLittleEndian);
652 OS.write(Buffer.data(), Buffer.size());
653 }
654
655 return Error::success();
656}
657
659 for (const AddrTableEntry &TableEntry : *DI.DebugAddr) {
660 uint8_t AddrSize;
661 if (TableEntry.AddrSize)
662 AddrSize = *TableEntry.AddrSize;
663 else
664 AddrSize = DI.Is64BitAddrSize ? 8 : 4;
665
667 if (TableEntry.Length)
668 Length = (uint64_t)*TableEntry.Length;
669 else
670 // 2 (version) + 1 (address_size) + 1 (segment_selector_size) = 4
671 Length = 4 + (AddrSize + TableEntry.SegSelectorSize) *
672 TableEntry.SegAddrPairs.size();
673
674 writeInitialLength(TableEntry.Format, Length, OS, DI.IsLittleEndian);
675 writeInteger((uint16_t)TableEntry.Version, OS, DI.IsLittleEndian);
676 writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
677 writeInteger((uint8_t)TableEntry.SegSelectorSize, OS, DI.IsLittleEndian);
678
679 for (const SegAddrPair &Pair : TableEntry.SegAddrPairs) {
680 if (TableEntry.SegSelectorSize != yaml::Hex8{0})
682 TableEntry.SegSelectorSize,
683 OS, DI.IsLittleEndian))
685 "unable to write debug_addr segment: %s",
686 toString(std::move(Err)).c_str());
687 if (AddrSize != 0)
688 if (Error Err = writeVariableSizedInteger(Pair.Address, AddrSize, OS,
689 DI.IsLittleEndian))
691 "unable to write debug_addr address: %s",
692 toString(std::move(Err)).c_str());
693 }
694 }
695
696 return Error::success();
697}
698
700 assert(DI.DebugStrOffsets && "unexpected emitDebugStrOffsets() call");
701 for (const DWARFYAML::StringOffsetsTable &Table : *DI.DebugStrOffsets) {
703 if (Table.Length)
704 Length = *Table.Length;
705 else
706 // sizeof(version) + sizeof(padding) = 4
707 Length =
708 4 + Table.Offsets.size() * (Table.Format == dwarf::DWARF64 ? 8 : 4);
709
713
714 for (uint64_t Offset : Table.Offsets)
716 }
717
718 return Error::success();
719}
720
721namespace {
722/// Emits the header for a DebugNames section.
723void emitDebugNamesHeader(raw_ostream &OS, bool IsLittleEndian,
724 uint32_t NameCount, uint32_t AbbrevSize,
725 uint32_t CombinedSizeOtherParts) {
726 // Use the same AugmentationString as AsmPrinter.
727 StringRef AugmentationString = "LLVM0700";
728 size_t TotalSize = CombinedSizeOtherParts + 5 * sizeof(uint32_t) +
729 2 * sizeof(uint16_t) + sizeof(NameCount) +
730 sizeof(AbbrevSize) + AugmentationString.size();
731 writeInteger(uint32_t(TotalSize), OS, IsLittleEndian); // Unit length
732
733 // Everything below is included in total size.
734 writeInteger(uint16_t(5), OS, IsLittleEndian); // Version
735 writeInteger(uint16_t(0), OS, IsLittleEndian); // Padding
736 writeInteger(uint32_t(1), OS, IsLittleEndian); // Compilation Unit count
737 writeInteger(uint32_t(0), OS, IsLittleEndian); // Local Type Unit count
738 writeInteger(uint32_t(0), OS, IsLittleEndian); // Foreign Type Unit count
739 writeInteger(uint32_t(0), OS, IsLittleEndian); // Bucket count
740 writeInteger(NameCount, OS, IsLittleEndian);
741 writeInteger(AbbrevSize, OS, IsLittleEndian);
742 writeInteger(uint32_t(AugmentationString.size()), OS, IsLittleEndian);
743 OS.write(AugmentationString.data(), AugmentationString.size());
744}
745
746/// Emits the abbreviations for a DebugNames section.
747std::string
748emitDebugNamesAbbrev(ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {
749 std::string Data;
751 for (const DWARFYAML::DebugNameAbbreviation &Abbrev : Abbrevs) {
752 encodeULEB128(Abbrev.Code, OS);
753 encodeULEB128(Abbrev.Tag, OS);
754 for (auto [Idx, Form] : Abbrev.Indices) {
755 encodeULEB128(Idx, OS);
756 encodeULEB128(Form, OS);
757 }
758 encodeULEB128(0, OS);
759 encodeULEB128(0, OS);
760 }
761 encodeULEB128(0, OS);
762 return Data;
763}
764
765/// Emits a simple CU offsets list for a DebugNames section containing a single
766/// CU at offset 0.
767std::string emitDebugNamesCUOffsets(bool IsLittleEndian) {
768 std::string Data;
769 raw_string_ostream OS(Data);
770 writeInteger(uint32_t(0), OS, IsLittleEndian);
771 return Data;
772}
773
774/// Emits the "NameTable" for a DebugNames section; according to the spec, it
775/// consists of two arrays: an array of string offsets, followed immediately by
776/// an array of entry offsets. The string offsets are emitted in the order
777/// provided in `Entries`.
778std::string emitDebugNamesNameTable(
779 bool IsLittleEndian,
780 const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> &Entries,
781 ArrayRef<uint32_t> EntryPoolOffsets) {
782 assert(Entries.size() == EntryPoolOffsets.size());
783
784 std::string Data;
785 raw_string_ostream OS(Data);
786
787 for (uint32_t Strp : make_first_range(Entries))
788 writeInteger(Strp, OS, IsLittleEndian);
789 for (uint32_t PoolOffset : EntryPoolOffsets)
790 writeInteger(PoolOffset, OS, IsLittleEndian);
791 return Data;
792}
793
794/// Groups entries based on their name (strp) code and returns a map.
795DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>>
796groupEntries(ArrayRef<DWARFYAML::DebugNameEntry> Entries) {
797 DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> StrpToEntries;
798 for (const DWARFYAML::DebugNameEntry &Entry : Entries)
799 StrpToEntries[Entry.NameStrp].push_back(Entry);
800 return StrpToEntries;
801}
802
803/// Finds the abbreviation whose code is AbbrevCode and returns a list
804/// containing the expected size of all non-zero-length forms.
805Expected<SmallVector<uint8_t>>
806getNonZeroDataSizesFor(uint32_t AbbrevCode,
808 const auto *AbbrevIt = find_if(Abbrevs, [&](const auto &Abbrev) {
809 return Abbrev.Code.value == AbbrevCode;
810 });
811 if (AbbrevIt == Abbrevs.end())
813 "did not find an Abbreviation for this code");
814
815 SmallVector<uint8_t> DataSizes;
816 dwarf::FormParams Params{/*Version=*/5, /*AddrSize=*/4, dwarf::DWARF32};
817 for (auto [Idx, Form] : AbbrevIt->Indices) {
818 std::optional<uint8_t> FormSize = dwarf::getFixedFormByteSize(Form, Params);
819 if (!FormSize)
821 "unsupported Form for YAML debug_names emitter");
822 if (FormSize == 0)
823 continue;
824 DataSizes.push_back(*FormSize);
825 }
826 return DataSizes;
827}
828
829struct PoolOffsetsAndData {
830 std::string PoolData;
831 std::vector<uint32_t> PoolOffsets;
832};
833
834/// Emits the entry pool and returns an array of offsets containing the start
835/// offset for the entries of each unique name.
836/// Verifies that the provided number of data values match those expected by
837/// the abbreviation table.
838Expected<PoolOffsetsAndData> emitDebugNamesEntryPool(
839 bool IsLittleEndian,
840 const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>>
841 &StrpToEntries,
843 PoolOffsetsAndData Result;
844 raw_string_ostream OS(Result.PoolData);
845
846 for (ArrayRef<DWARFYAML::DebugNameEntry> EntriesWithSameName :
847 make_second_range(StrpToEntries)) {
848 Result.PoolOffsets.push_back(Result.PoolData.size());
849
850 for (const DWARFYAML::DebugNameEntry &Entry : EntriesWithSameName) {
851 encodeULEB128(Entry.Code, OS);
852
853 Expected<SmallVector<uint8_t>> DataSizes =
854 getNonZeroDataSizesFor(Entry.Code, Abbrevs);
855 if (!DataSizes)
856 return DataSizes.takeError();
857 if (DataSizes->size() != Entry.Values.size())
858 return createStringError(
860 "mismatch between provided and required number of values");
861
862 for (auto [Value, ValueSize] : zip_equal(Entry.Values, *DataSizes))
863 if (Error E =
864 writeVariableSizedInteger(Value, ValueSize, OS, IsLittleEndian))
865 return std::move(E);
866 }
867 encodeULEB128(0, OS);
868 }
869
870 return Result;
871}
872} // namespace
873
875 assert(DI.DebugNames && "unexpected emitDebugNames() call");
876 const DebugNamesSection DebugNames = DI.DebugNames.value();
877
879 groupEntries(DebugNames.Entries);
880
881 // Emit all sub-sections into individual strings so that we may compute
882 // relative offsets and sizes.
883 Expected<PoolOffsetsAndData> PoolInfo = emitDebugNamesEntryPool(
884 DI.IsLittleEndian, StrpToEntries, DebugNames.Abbrevs);
885 if (!PoolInfo)
886 return PoolInfo.takeError();
887 std::string NamesTableData = emitDebugNamesNameTable(
888 DI.IsLittleEndian, StrpToEntries, PoolInfo->PoolOffsets);
889
890 std::string AbbrevData = emitDebugNamesAbbrev(DebugNames.Abbrevs);
891 std::string CUOffsetsData = emitDebugNamesCUOffsets(DI.IsLittleEndian);
892
893 size_t TotalSize = PoolInfo->PoolData.size() + NamesTableData.size() +
894 AbbrevData.size() + CUOffsetsData.size();
895
896 // Start real emission by combining all individual strings.
897 emitDebugNamesHeader(OS, DI.IsLittleEndian, StrpToEntries.size(),
898 AbbrevData.size(), TotalSize);
899 OS.write(CUOffsetsData.data(), CUOffsetsData.size());
900 // No local TUs, no foreign TUs, no hash lookups table.
901 OS.write(NamesTableData.data(), NamesTableData.size());
902 OS.write(AbbrevData.data(), AbbrevData.size());
903 OS.write(PoolInfo->PoolData.data(), PoolInfo->PoolData.size());
904
905 return Error::success();
906}
907
908static Error checkOperandCount(StringRef EncodingString,
910 uint64_t ExpectedOperands) {
911 if (Values.size() != ExpectedOperands)
912 return createStringError(
914 "invalid number (%zu) of operands for the operator: %s, %" PRIu64
915 " expected",
916 Values.size(), EncodingString.str().c_str(), ExpectedOperands);
917
918 return Error::success();
919}
920
922 uint64_t Addr, uint8_t AddrSize,
923 bool IsLittleEndian) {
924 if (Error Err = writeVariableSizedInteger(Addr, AddrSize, OS, IsLittleEndian))
926 "unable to write address for the operator %s: %s",
927 EncodingName.str().c_str(),
928 toString(std::move(Err)).c_str());
929
930 return Error::success();
931}
932
933static Expected<uint64_t>
936 uint8_t AddrSize, bool IsLittleEndian) {
937 auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
939 Operation.Values, ExpectedOperands);
940 };
941
942 uint64_t ExpressionBegin = OS.tell();
943 writeInteger((uint8_t)Operation.Operator, OS, IsLittleEndian);
944 switch (Operation.Operator) {
945 case dwarf::DW_OP_consts:
946 if (Error Err = CheckOperands(1))
947 return std::move(Err);
948 encodeSLEB128(Operation.Values[0], OS);
949 break;
950 case dwarf::DW_OP_stack_value:
951 if (Error Err = CheckOperands(0))
952 return std::move(Err);
953 break;
954 default:
955 StringRef EncodingStr = dwarf::OperationEncodingString(Operation.Operator);
957 "DWARF expression: " +
958 (EncodingStr.empty()
959 ? "0x" + utohexstr(Operation.Operator)
960 : EncodingStr) +
961 " is not supported");
962 }
963 return OS.tell() - ExpressionBegin;
964}
965
967 const DWARFYAML::RnglistEntry &Entry,
968 uint8_t AddrSize,
969 bool IsLittleEndian) {
970 uint64_t BeginOffset = OS.tell();
971 writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);
972
973 StringRef EncodingName = dwarf::RangeListEncodingString(Entry.Operator);
974
975 auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
976 return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
977 };
978
979 auto WriteAddress = [&](uint64_t Addr) -> Error {
980 return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
981 IsLittleEndian);
982 };
983
984 switch (Entry.Operator) {
985 case dwarf::DW_RLE_end_of_list:
986 if (Error Err = CheckOperands(0))
987 return std::move(Err);
988 break;
989 case dwarf::DW_RLE_base_addressx:
990 if (Error Err = CheckOperands(1))
991 return std::move(Err);
992 encodeULEB128(Entry.Values[0], OS);
993 break;
994 case dwarf::DW_RLE_startx_endx:
995 case dwarf::DW_RLE_startx_length:
996 case dwarf::DW_RLE_offset_pair:
997 if (Error Err = CheckOperands(2))
998 return std::move(Err);
999 encodeULEB128(Entry.Values[0], OS);
1000 encodeULEB128(Entry.Values[1], OS);
1001 break;
1002 case dwarf::DW_RLE_base_address:
1003 if (Error Err = CheckOperands(1))
1004 return std::move(Err);
1005 if (Error Err = WriteAddress(Entry.Values[0]))
1006 return std::move(Err);
1007 break;
1008 case dwarf::DW_RLE_start_end:
1009 if (Error Err = CheckOperands(2))
1010 return std::move(Err);
1011 if (Error Err = WriteAddress(Entry.Values[0]))
1012 return std::move(Err);
1013 cantFail(WriteAddress(Entry.Values[1]));
1014 break;
1015 case dwarf::DW_RLE_start_length:
1016 if (Error Err = CheckOperands(2))
1017 return std::move(Err);
1018 if (Error Err = WriteAddress(Entry.Values[0]))
1019 return std::move(Err);
1020 encodeULEB128(Entry.Values[1], OS);
1021 break;
1022 }
1023
1024 return OS.tell() - BeginOffset;
1025}
1026
1028 const DWARFYAML::LoclistEntry &Entry,
1029 uint8_t AddrSize,
1030 bool IsLittleEndian) {
1031 uint64_t BeginOffset = OS.tell();
1032 writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);
1033
1034 StringRef EncodingName = dwarf::LocListEncodingString(Entry.Operator);
1035
1036 auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
1037 return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
1038 };
1039
1040 auto WriteAddress = [&](uint64_t Addr) -> Error {
1041 return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
1042 IsLittleEndian);
1043 };
1044
1045 auto WriteDWARFOperations = [&]() -> Error {
1046 std::string OpBuffer;
1047 raw_string_ostream OpBufferOS(OpBuffer);
1048 uint64_t DescriptionsLength = 0;
1049
1050 for (const DWARFYAML::DWARFOperation &Op : Entry.Descriptions) {
1051 if (Expected<uint64_t> OpSize =
1052 writeDWARFExpression(OpBufferOS, Op, AddrSize, IsLittleEndian))
1053 DescriptionsLength += *OpSize;
1054 else
1055 return OpSize.takeError();
1056 }
1057
1058 if (Entry.DescriptionsLength)
1059 DescriptionsLength = *Entry.DescriptionsLength;
1060 else
1061 DescriptionsLength = OpBuffer.size();
1062
1063 encodeULEB128(DescriptionsLength, OS);
1064 OS.write(OpBuffer.data(), OpBuffer.size());
1065
1066 return Error::success();
1067 };
1068
1069 switch (Entry.Operator) {
1070 case dwarf::DW_LLE_end_of_list:
1071 if (Error Err = CheckOperands(0))
1072 return std::move(Err);
1073 break;
1074 case dwarf::DW_LLE_base_addressx:
1075 if (Error Err = CheckOperands(1))
1076 return std::move(Err);
1077 encodeULEB128(Entry.Values[0], OS);
1078 break;
1079 case dwarf::DW_LLE_startx_endx:
1080 case dwarf::DW_LLE_startx_length:
1081 case dwarf::DW_LLE_offset_pair:
1082 if (Error Err = CheckOperands(2))
1083 return std::move(Err);
1084 encodeULEB128(Entry.Values[0], OS);
1085 encodeULEB128(Entry.Values[1], OS);
1086 if (Error Err = WriteDWARFOperations())
1087 return std::move(Err);
1088 break;
1089 case dwarf::DW_LLE_default_location:
1090 if (Error Err = CheckOperands(0))
1091 return std::move(Err);
1092 if (Error Err = WriteDWARFOperations())
1093 return std::move(Err);
1094 break;
1095 case dwarf::DW_LLE_base_address:
1096 if (Error Err = CheckOperands(1))
1097 return std::move(Err);
1098 if (Error Err = WriteAddress(Entry.Values[0]))
1099 return std::move(Err);
1100 break;
1101 case dwarf::DW_LLE_start_end:
1102 if (Error Err = CheckOperands(2))
1103 return std::move(Err);
1104 if (Error Err = WriteAddress(Entry.Values[0]))
1105 return std::move(Err);
1106 cantFail(WriteAddress(Entry.Values[1]));
1107 if (Error Err = WriteDWARFOperations())
1108 return std::move(Err);
1109 break;
1110 case dwarf::DW_LLE_start_length:
1111 if (Error Err = CheckOperands(2))
1112 return std::move(Err);
1113 if (Error Err = WriteAddress(Entry.Values[0]))
1114 return std::move(Err);
1115 encodeULEB128(Entry.Values[1], OS);
1116 if (Error Err = WriteDWARFOperations())
1117 return std::move(Err);
1118 break;
1119 }
1120
1121 return OS.tell() - BeginOffset;
1122}
1123
1124template <typename EntryType>
1127 bool IsLittleEndian, bool Is64BitAddrSize) {
1128 for (const DWARFYAML::ListTable<EntryType> &Table : Tables) {
1129 // sizeof(version) + sizeof(address_size) + sizeof(segment_selector_size) +
1130 // sizeof(offset_entry_count) = 8
1131 uint64_t Length = 8;
1132
1133 uint8_t AddrSize;
1134 if (Table.AddrSize)
1135 AddrSize = *Table.AddrSize;
1136 else
1137 AddrSize = Is64BitAddrSize ? 8 : 4;
1138
1139 // Since the length of the current range/location lists entry is
1140 // undetermined yet, we firstly write the content of the range/location
1141 // lists to a buffer to calculate the length and then serialize the buffer
1142 // content to the actual output stream.
1143 std::string ListBuffer;
1144 raw_string_ostream ListBufferOS(ListBuffer);
1145
1146 // Offsets holds offsets for each range/location list. The i-th element is
1147 // the offset from the beginning of the first range/location list to the
1148 // location of the i-th range list.
1149 std::vector<uint64_t> Offsets;
1150
1151 for (const DWARFYAML::ListEntries<EntryType> &List : Table.Lists) {
1152 Offsets.push_back(ListBufferOS.tell());
1153 if (List.Content) {
1154 List.Content->writeAsBinary(ListBufferOS, UINT64_MAX);
1155 Length += List.Content->binary_size();
1156 } else if (List.Entries) {
1157 for (const EntryType &Entry : *List.Entries) {
1158 Expected<uint64_t> EntrySize =
1159 writeListEntry(ListBufferOS, Entry, AddrSize, IsLittleEndian);
1160 if (!EntrySize)
1161 return EntrySize.takeError();
1162 Length += *EntrySize;
1163 }
1164 }
1165 }
1166
1167 // If the offset_entry_count field isn't specified, yaml2obj will infer it
1168 // from the 'Offsets' field in the YAML description. If the 'Offsets' field
1169 // isn't specified either, yaml2obj will infer it from the auto-generated
1170 // offsets.
1171 uint32_t OffsetEntryCount;
1172 if (Table.OffsetEntryCount)
1173 OffsetEntryCount = *Table.OffsetEntryCount;
1174 else
1175 OffsetEntryCount = Table.Offsets ? Table.Offsets->size() : Offsets.size();
1176 uint64_t OffsetsSize =
1177 OffsetEntryCount * (Table.Format == dwarf::DWARF64 ? 8 : 4);
1178 Length += OffsetsSize;
1179
1180 // If the length is specified in the YAML description, we use it instead of
1181 // the actual length.
1182 if (Table.Length)
1183 Length = *Table.Length;
1184
1185 writeInitialLength(Table.Format, Length, OS, IsLittleEndian);
1186 writeInteger((uint16_t)Table.Version, OS, IsLittleEndian);
1187 writeInteger((uint8_t)AddrSize, OS, IsLittleEndian);
1188 writeInteger((uint8_t)Table.SegSelectorSize, OS, IsLittleEndian);
1189 writeInteger((uint32_t)OffsetEntryCount, OS, IsLittleEndian);
1190
1191 auto EmitOffsets = [&](ArrayRef<uint64_t> Offsets, uint64_t OffsetsSize) {
1192 for (uint64_t Offset : Offsets)
1193 writeDWARFOffset(OffsetsSize + Offset, Table.Format, OS,
1194 IsLittleEndian);
1195 };
1196
1197 if (Table.Offsets)
1198 EmitOffsets(ArrayRef<uint64_t>((const uint64_t *)Table.Offsets->data(),
1199 Table.Offsets->size()),
1200 0);
1201 else if (OffsetEntryCount != 0)
1202 EmitOffsets(Offsets, OffsetsSize);
1203
1204 OS.write(ListBuffer.data(), ListBuffer.size());
1205 }
1206
1207 return Error::success();
1208}
1209
1211 assert(DI.DebugRnglists && "unexpected emitDebugRnglists() call");
1214}
1215
1217 assert(DI.DebugLoclists && "unexpected emitDebugRnglists() call");
1220}
1221
1222std::function<Error(raw_ostream &, const DWARFYAML::Data &)>
1224 auto EmitFunc =
1226 std::function<Error(raw_ostream &, const DWARFYAML::Data &)>>(SecName)
1227 .Case("debug_abbrev", DWARFYAML::emitDebugAbbrev)
1228 .Case("debug_addr", DWARFYAML::emitDebugAddr)
1229 .Case("debug_aranges", DWARFYAML::emitDebugAranges)
1230 .Case("debug_gnu_pubnames", DWARFYAML::emitDebugGNUPubnames)
1231 .Case("debug_gnu_pubtypes", DWARFYAML::emitDebugGNUPubtypes)
1232 .Case("debug_info", DWARFYAML::emitDebugInfo)
1233 .Case("debug_line", DWARFYAML::emitDebugLine)
1234 .Case("debug_loclists", DWARFYAML::emitDebugLoclists)
1235 .Case("debug_pubnames", DWARFYAML::emitDebugPubnames)
1236 .Case("debug_pubtypes", DWARFYAML::emitDebugPubtypes)
1237 .Case("debug_ranges", DWARFYAML::emitDebugRanges)
1238 .Case("debug_rnglists", DWARFYAML::emitDebugRnglists)
1239 .Case("debug_str", DWARFYAML::emitDebugStr)
1240 .Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets)
1241 .Case("debug_names", DWARFYAML::emitDebugNames)
1242 .Default([&](raw_ostream &, const DWARFYAML::Data &) {
1244 SecName + " is not supported");
1245 });
1246
1247 return EmitFunc;
1248}
1249
1250static Error
1252 StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) {
1253 std::string Data;
1254 raw_string_ostream DebugInfoStream(Data);
1255
1256 auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Sec);
1257
1258 if (Error Err = EmitFunc(DebugInfoStream, DI))
1259 return Err;
1260 DebugInfoStream.flush();
1261 if (!Data.empty())
1262 OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data);
1263
1264 return Error::success();
1265}
1266
1267Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
1268DWARFYAML::emitDebugSections(StringRef YAMLString, bool IsLittleEndian,
1269 bool Is64BitAddrSize) {
1270 auto CollectDiagnostic = [](const SMDiagnostic &Diag, void *DiagContext) {
1271 *static_cast<SMDiagnostic *>(DiagContext) = Diag;
1272 };
1273
1274 SMDiagnostic GeneratedDiag;
1275 yaml::Input YIn(YAMLString, /*Ctxt=*/nullptr, CollectDiagnostic,
1276 &GeneratedDiag);
1277
1278 DWARFYAML::Data DI;
1279 DI.IsLittleEndian = IsLittleEndian;
1280 DI.Is64BitAddrSize = Is64BitAddrSize;
1281
1282 YIn >> DI;
1283 if (YIn.error())
1284 return createStringError(YIn.error(), GeneratedDiag.getMessage());
1285
1287 Error Err = Error::success();
1288
1289 for (StringRef SecName : DI.getNonEmptySectionNames())
1290 Err = joinErrors(std::move(Err),
1291 emitDebugSectionImpl(DI, SecName, DebugSections));
1292
1293 if (Err)
1294 return std::move(Err);
1295 return std::move(DebugSections);
1296}
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:58
#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:41
iterator end() const
Definition ArrayRef.h:136
size_t size() const
size - Get the array size.
Definition ArrayRef.h:147
iterator begin() const
Definition ArrayRef.h:135
unsigned size() const
Definition DenseMap.h:108
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:282
StringRef getMessage() const
Definition SourceMgr.h:313
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:233
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:151
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:154
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:148
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(const uint64_t &Val)
Definition Twine.h:392
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:610
LLVM_ABI StringRef LocListEncodingString(unsigned Encoding)
Definition Dwarf.cpp:621
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:92
@ DWARF64
Definition Dwarf.h:92
@ DWARF32
Definition Dwarf.h:92
LLVM_ABI std::optional< uint8_t > getFixedFormByteSize(dwarf::Form Form, FormParams Params)
Get the fixed byte size for a given form.
Definition Dwarf.cpp:792
@ DW_LENGTH_DWARF64
Indicator of 64-bit DWARF format.
Definition Dwarf.h:56
constexpr bool IsLittleEndianHost
void swapByteOrder(T &Value)
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
@ Length
Definition DWP.cpp:477
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:853
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:98
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:1305
@ 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:1427
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:189
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:155
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:1437
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:1760
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:81
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1083
std::vector< AttributeAbbrev > Attributes
Definition DWARFYAML.h:42
std::optional< yaml::Hex64 > Code
Definition DWARFYAML.h:39
std::vector< Unit > Units
Definition DWARFYAML.h:252
std::vector< LineTable > DebugLines
Definition DWARFYAML.h:254
std::optional< std::vector< AddrTableEntry > > DebugAddr
Definition DWARFYAML.h:245
std::optional< std::vector< Ranges > > DebugRanges
Definition DWARFYAML.h:244
std::optional< std::vector< ListTable< LoclistEntry > > > DebugLoclists
Definition DWARFYAML.h:256
std::vector< AbbrevTable > DebugAbbrev
Definition DWARFYAML.h:240
LLVM_ABI Expected< AbbrevTableInfo > getAbbrevTableInfoByID(uint64_t ID) const
Definition DWARFYAML.cpp:61
std::optional< PubSection > GNUPubNames
Definition DWARFYAML.h:249
std::optional< std::vector< ARange > > DebugAranges
Definition DWARFYAML.h:243
LLVM_ABI StringRef getAbbrevTableContentByIndex(uint64_t Index) const
std::optional< PubSection > GNUPubTypes
Definition DWARFYAML.h:250
LLVM_ABI SetVector< StringRef > getNonEmptySectionNames() const
Definition DWARFYAML.cpp:25
std::optional< std::vector< StringOffsetsTable > > DebugStrOffsets
Definition DWARFYAML.h:242
std::optional< std::vector< StringRef > > DebugStrings
Definition DWARFYAML.h:241
std::optional< std::vector< ListTable< RnglistEntry > > > DebugRnglists
Definition DWARFYAML.h:255
std::optional< PubSection > PubNames
Definition DWARFYAML.h:246
std::optional< DebugNamesSection > DebugNames
Definition DWARFYAML.h:257
std::optional< PubSection > PubTypes
Definition DWARFYAML.h:247
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:175
std::vector< LineTableOpcode > Opcodes
Definition DWARFYAML.h:179
std::optional< uint64_t > PrologueLength
Definition DWARFYAML.h:169
dwarf::DwarfFormat Format
Definition DWARFYAML.h:166
std::vector< File > Files
Definition DWARFYAML.h:178
std::vector< StringRef > IncludeDirs
Definition DWARFYAML.h:177
std::optional< std::vector< uint8_t > > StandardOpcodeLengths
Definition DWARFYAML.h:176
dwarf::DwarfFormat Format
Definition DWARFYAML.h:86
std::vector< PubEntry > Entries
Definition DWARFYAML.h:91
std::optional< yaml::Hex64 > Length
Definition DWARFYAML.h:198
std::vector< yaml::Hex64 > Offsets
Definition DWARFYAML.h:201
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:1093
uint8_t getDwarfOffsetByteSize() const
The size of a reference is determined by the DWARF 32/64-bit format.
Definition Dwarf.h:1111
uint8_t getRefAddrByteSize() const
The definition of the size of form DW_FORM_ref_addr depends on the version.
Definition Dwarf.h:1104