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
599 OS << static_cast<char>(Count);
600 for (const auto [ContentType, Form] : Format) {
601 encodeULEB128(ContentType, OS);
602 encodeULEB128(Form, OS);
603 }
604}
605
607 for (const DWARFYAML::LineTable &LineTable : DI.DebugLines) {
608 // Buffer holds the bytes following the header_length (or prologue_length in
609 // DWARFv2) field to the end of the line number program itself.
610 std::string Buffer;
611 raw_string_ostream BufferOS(Buffer);
612
614 if (LineTable.Version >= 4)
619
620 std::vector<uint8_t> StandardOpcodeLengths =
623 uint8_t OpcodeBase = LineTable.OpcodeBase
625 : StandardOpcodeLengths.size() + 1;
626 writeInteger(OpcodeBase, BufferOS, DI.IsLittleEndian);
627 for (uint8_t OpcodeLength : StandardOpcodeLengths)
628 writeInteger(OpcodeLength, BufferOS, DI.IsLittleEndian);
629
630 if (LineTable.Version >= 5) {
633 // TODO: Support directories in DWARFv5
634 encodeULEB128(/*directories_count=*/0, BufferOS);
635
638 // TODO: Support file names in DWARFv5
639 encodeULEB128(/*file_names_count=*/0, BufferOS);
640 } else {
641 for (StringRef IncludeDir : LineTable.IncludeDirs) {
642 BufferOS.write(IncludeDir.data(), IncludeDir.size());
643 BufferOS.write('\0');
644 }
645 BufferOS.write('\0');
646
647 for (const DWARFYAML::File &File : LineTable.Files)
648 emitFileEntry(BufferOS, File);
649 BufferOS.write('\0');
650 }
651
652 uint64_t HeaderLength =
654
656 writeLineTableOpcode(Op, OpcodeBase, DI.Is64BitAddrSize ? 8 : 4, BufferOS,
657 DI.IsLittleEndian);
658
660 if (LineTable.Length) {
662 } else {
663 Length =
664 (LineTable.Format == dwarf::DWARF64 ? 8 : 4); // sizeof(unit_length)
665 Length += 2; // sizeof(version)
666 if (LineTable.Version >= 5)
667 Length += 2; // sizeof(address_size) + sizeof(segment_selector_size)
668 Length += Buffer.size();
669 }
670
673 if (LineTable.Version >= 5) {
676 }
677 writeDWARFOffset(HeaderLength, LineTable.Format, OS, DI.IsLittleEndian);
678 OS.write(Buffer.data(), Buffer.size());
679 }
680
681 return Error::success();
682}
683
685 for (const AddrTableEntry &TableEntry : *DI.DebugAddr) {
686 uint8_t AddrSize;
687 if (TableEntry.AddrSize)
688 AddrSize = *TableEntry.AddrSize;
689 else
690 AddrSize = DI.Is64BitAddrSize ? 8 : 4;
691
693 if (TableEntry.Length)
694 Length = (uint64_t)*TableEntry.Length;
695 else
696 // 2 (version) + 1 (address_size) + 1 (segment_selector_size) = 4
697 Length = 4 + (AddrSize + TableEntry.SegSelectorSize) *
698 TableEntry.SegAddrPairs.size();
699
700 writeInitialLength(TableEntry.Format, Length, OS, DI.IsLittleEndian);
701 writeInteger((uint16_t)TableEntry.Version, OS, DI.IsLittleEndian);
702 writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
703 writeInteger((uint8_t)TableEntry.SegSelectorSize, OS, DI.IsLittleEndian);
704
705 for (const SegAddrPair &Pair : TableEntry.SegAddrPairs) {
706 if (TableEntry.SegSelectorSize != yaml::Hex8{0})
708 TableEntry.SegSelectorSize,
709 OS, DI.IsLittleEndian))
711 "unable to write debug_addr segment: %s",
712 toString(std::move(Err)).c_str());
713 if (AddrSize != 0)
714 if (Error Err = writeVariableSizedInteger(Pair.Address, AddrSize, OS,
715 DI.IsLittleEndian))
717 "unable to write debug_addr address: %s",
718 toString(std::move(Err)).c_str());
719 }
720 }
721
722 return Error::success();
723}
724
726 assert(DI.DebugStrOffsets && "unexpected emitDebugStrOffsets() call");
727 for (const DWARFYAML::StringOffsetsTable &Table : *DI.DebugStrOffsets) {
729 if (Table.Length)
730 Length = *Table.Length;
731 else
732 // sizeof(version) + sizeof(padding) = 4
733 Length =
734 4 + Table.Offsets.size() * (Table.Format == dwarf::DWARF64 ? 8 : 4);
735
739
740 for (uint64_t Offset : Table.Offsets)
742 }
743
744 return Error::success();
745}
746
747namespace {
748/// Emits the header for a DebugNames section.
749void emitDebugNamesHeader(raw_ostream &OS, bool IsLittleEndian,
750 uint32_t NameCount, uint32_t AbbrevSize,
751 uint32_t CombinedSizeOtherParts) {
752 // Use the same AugmentationString as AsmPrinter.
753 StringRef AugmentationString = "LLVM0700";
754 size_t TotalSize = CombinedSizeOtherParts + 5 * sizeof(uint32_t) +
755 2 * sizeof(uint16_t) + sizeof(NameCount) +
756 sizeof(AbbrevSize) + AugmentationString.size();
757 writeInteger(uint32_t(TotalSize), OS, IsLittleEndian); // Unit length
758
759 // Everything below is included in total size.
760 writeInteger(uint16_t(5), OS, IsLittleEndian); // Version
761 writeInteger(uint16_t(0), OS, IsLittleEndian); // Padding
762 writeInteger(uint32_t(1), OS, IsLittleEndian); // Compilation Unit count
763 writeInteger(uint32_t(0), OS, IsLittleEndian); // Local Type Unit count
764 writeInteger(uint32_t(0), OS, IsLittleEndian); // Foreign Type Unit count
765 writeInteger(uint32_t(0), OS, IsLittleEndian); // Bucket count
766 writeInteger(NameCount, OS, IsLittleEndian);
767 writeInteger(AbbrevSize, OS, IsLittleEndian);
768 writeInteger(uint32_t(AugmentationString.size()), OS, IsLittleEndian);
769 OS.write(AugmentationString.data(), AugmentationString.size());
770}
771
772/// Emits the abbreviations for a DebugNames section.
773std::string
774emitDebugNamesAbbrev(ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {
775 std::string Data;
777 for (const DWARFYAML::DebugNameAbbreviation &Abbrev : Abbrevs) {
778 encodeULEB128(Abbrev.Code, OS);
779 encodeULEB128(Abbrev.Tag, OS);
780 for (auto [Idx, Form] : Abbrev.Indices) {
781 encodeULEB128(Idx, OS);
782 encodeULEB128(Form, OS);
783 }
784 encodeULEB128(0, OS);
785 encodeULEB128(0, OS);
786 }
787 encodeULEB128(0, OS);
788 return Data;
789}
790
791/// Emits a simple CU offsets list for a DebugNames section containing a single
792/// CU at offset 0.
793std::string emitDebugNamesCUOffsets(bool IsLittleEndian) {
794 std::string Data;
795 raw_string_ostream OS(Data);
796 writeInteger(uint32_t(0), OS, IsLittleEndian);
797 return Data;
798}
799
800/// Emits the "NameTable" for a DebugNames section; according to the spec, it
801/// consists of two arrays: an array of string offsets, followed immediately by
802/// an array of entry offsets. The string offsets are emitted in the order
803/// provided in `Entries`.
804std::string emitDebugNamesNameTable(
805 bool IsLittleEndian,
806 const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> &Entries,
807 ArrayRef<uint32_t> EntryPoolOffsets) {
808 assert(Entries.size() == EntryPoolOffsets.size());
809
810 std::string Data;
811 raw_string_ostream OS(Data);
812
813 for (uint32_t Strp : make_first_range(Entries))
814 writeInteger(Strp, OS, IsLittleEndian);
815 for (uint32_t PoolOffset : EntryPoolOffsets)
816 writeInteger(PoolOffset, OS, IsLittleEndian);
817 return Data;
818}
819
820/// Groups entries based on their name (strp) code and returns a map.
821DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>>
822groupEntries(ArrayRef<DWARFYAML::DebugNameEntry> Entries) {
823 DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> StrpToEntries;
824 for (const DWARFYAML::DebugNameEntry &Entry : Entries)
825 StrpToEntries[Entry.NameStrp].push_back(Entry);
826 return StrpToEntries;
827}
828
829/// Finds the abbreviation whose code is AbbrevCode and returns a list
830/// containing the expected size of all non-zero-length forms.
831Expected<SmallVector<uint8_t>>
832getNonZeroDataSizesFor(uint32_t AbbrevCode,
834 const auto *AbbrevIt = find_if(Abbrevs, [&](const auto &Abbrev) {
835 return Abbrev.Code.value == AbbrevCode;
836 });
837 if (AbbrevIt == Abbrevs.end())
839 "did not find an Abbreviation for this code");
840
841 SmallVector<uint8_t> DataSizes;
842 dwarf::FormParams Params{/*Version=*/5, /*AddrSize=*/4, dwarf::DWARF32};
843 for (auto [Idx, Form] : AbbrevIt->Indices) {
844 std::optional<uint8_t> FormSize = dwarf::getFixedFormByteSize(Form, Params);
845 if (!FormSize)
847 "unsupported Form for YAML debug_names emitter");
848 if (FormSize == 0)
849 continue;
850 DataSizes.push_back(*FormSize);
851 }
852 return DataSizes;
853}
854
855struct PoolOffsetsAndData {
856 std::string PoolData;
857 std::vector<uint32_t> PoolOffsets;
858};
859
860/// Emits the entry pool and returns an array of offsets containing the start
861/// offset for the entries of each unique name.
862/// Verifies that the provided number of data values match those expected by
863/// the abbreviation table.
864Expected<PoolOffsetsAndData> emitDebugNamesEntryPool(
865 bool IsLittleEndian,
866 const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>>
867 &StrpToEntries,
869 PoolOffsetsAndData Result;
870 raw_string_ostream OS(Result.PoolData);
871
872 for (ArrayRef<DWARFYAML::DebugNameEntry> EntriesWithSameName :
873 make_second_range(StrpToEntries)) {
874 Result.PoolOffsets.push_back(Result.PoolData.size());
875
876 for (const DWARFYAML::DebugNameEntry &Entry : EntriesWithSameName) {
877 encodeULEB128(Entry.Code, OS);
878
879 Expected<SmallVector<uint8_t>> DataSizes =
880 getNonZeroDataSizesFor(Entry.Code, Abbrevs);
881 if (!DataSizes)
882 return DataSizes.takeError();
883 if (DataSizes->size() != Entry.Values.size())
884 return createStringError(
886 "mismatch between provided and required number of values");
887
888 for (auto [Value, ValueSize] : zip_equal(Entry.Values, *DataSizes))
889 if (Error E =
890 writeVariableSizedInteger(Value, ValueSize, OS, IsLittleEndian))
891 return std::move(E);
892 }
893 encodeULEB128(0, OS);
894 }
895
896 return Result;
897}
898} // namespace
899
901 assert(DI.DebugNames && "unexpected emitDebugNames() call");
902 const DebugNamesSection DebugNames = DI.DebugNames.value();
903
905 groupEntries(DebugNames.Entries);
906
907 // Emit all sub-sections into individual strings so that we may compute
908 // relative offsets and sizes.
909 Expected<PoolOffsetsAndData> PoolInfo = emitDebugNamesEntryPool(
910 DI.IsLittleEndian, StrpToEntries, DebugNames.Abbrevs);
911 if (!PoolInfo)
912 return PoolInfo.takeError();
913 std::string NamesTableData = emitDebugNamesNameTable(
914 DI.IsLittleEndian, StrpToEntries, PoolInfo->PoolOffsets);
915
916 std::string AbbrevData = emitDebugNamesAbbrev(DebugNames.Abbrevs);
917 std::string CUOffsetsData = emitDebugNamesCUOffsets(DI.IsLittleEndian);
918
919 size_t TotalSize = PoolInfo->PoolData.size() + NamesTableData.size() +
920 AbbrevData.size() + CUOffsetsData.size();
921
922 // Start real emission by combining all individual strings.
923 emitDebugNamesHeader(OS, DI.IsLittleEndian, StrpToEntries.size(),
924 AbbrevData.size(), TotalSize);
925 OS.write(CUOffsetsData.data(), CUOffsetsData.size());
926 // No local TUs, no foreign TUs, no hash lookups table.
927 OS.write(NamesTableData.data(), NamesTableData.size());
928 OS.write(AbbrevData.data(), AbbrevData.size());
929 OS.write(PoolInfo->PoolData.data(), PoolInfo->PoolData.size());
930
931 return Error::success();
932}
933
934static Error checkOperandCount(StringRef EncodingString,
936 uint64_t ExpectedOperands) {
937 if (Values.size() != ExpectedOperands)
938 return createStringError(
940 "invalid number (%zu) of operands for the operator: %s, %" PRIu64
941 " expected",
942 Values.size(), EncodingString.str().c_str(), ExpectedOperands);
943
944 return Error::success();
945}
946
948 uint64_t Addr, uint8_t AddrSize,
949 bool IsLittleEndian) {
950 if (Error Err = writeVariableSizedInteger(Addr, AddrSize, OS, IsLittleEndian))
952 "unable to write address for the operator %s: %s",
953 EncodingName.str().c_str(),
954 toString(std::move(Err)).c_str());
955
956 return Error::success();
957}
958
959static Expected<uint64_t>
962 uint8_t AddrSize, bool IsLittleEndian) {
963 auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
965 Operation.Values, ExpectedOperands);
966 };
967
968 uint64_t ExpressionBegin = OS.tell();
969 writeInteger((uint8_t)Operation.Operator, OS, IsLittleEndian);
970 switch (Operation.Operator) {
971 case dwarf::DW_OP_consts:
972 if (Error Err = CheckOperands(1))
973 return std::move(Err);
974 encodeSLEB128(Operation.Values[0], OS);
975 break;
976 case dwarf::DW_OP_stack_value:
977 if (Error Err = CheckOperands(0))
978 return std::move(Err);
979 break;
980 default:
981 StringRef EncodingStr = dwarf::OperationEncodingString(Operation.Operator);
983 "DWARF expression: " +
984 (EncodingStr.empty()
985 ? "0x" + utohexstr(Operation.Operator)
986 : EncodingStr) +
987 " is not supported");
988 }
989 return OS.tell() - ExpressionBegin;
990}
991
993 const DWARFYAML::RnglistEntry &Entry,
994 uint8_t AddrSize,
995 bool IsLittleEndian) {
996 uint64_t BeginOffset = OS.tell();
997 writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);
998
999 StringRef EncodingName = dwarf::RangeListEncodingString(Entry.Operator);
1000
1001 auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
1002 return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
1003 };
1004
1005 auto WriteAddress = [&](uint64_t Addr) -> Error {
1006 return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
1007 IsLittleEndian);
1008 };
1009
1010 switch (Entry.Operator) {
1011 case dwarf::DW_RLE_end_of_list:
1012 if (Error Err = CheckOperands(0))
1013 return std::move(Err);
1014 break;
1015 case dwarf::DW_RLE_base_addressx:
1016 if (Error Err = CheckOperands(1))
1017 return std::move(Err);
1018 encodeULEB128(Entry.Values[0], OS);
1019 break;
1020 case dwarf::DW_RLE_startx_endx:
1021 case dwarf::DW_RLE_startx_length:
1022 case dwarf::DW_RLE_offset_pair:
1023 if (Error Err = CheckOperands(2))
1024 return std::move(Err);
1025 encodeULEB128(Entry.Values[0], OS);
1026 encodeULEB128(Entry.Values[1], OS);
1027 break;
1028 case dwarf::DW_RLE_base_address:
1029 if (Error Err = CheckOperands(1))
1030 return std::move(Err);
1031 if (Error Err = WriteAddress(Entry.Values[0]))
1032 return std::move(Err);
1033 break;
1034 case dwarf::DW_RLE_start_end:
1035 if (Error Err = CheckOperands(2))
1036 return std::move(Err);
1037 if (Error Err = WriteAddress(Entry.Values[0]))
1038 return std::move(Err);
1039 cantFail(WriteAddress(Entry.Values[1]));
1040 break;
1041 case dwarf::DW_RLE_start_length:
1042 if (Error Err = CheckOperands(2))
1043 return std::move(Err);
1044 if (Error Err = WriteAddress(Entry.Values[0]))
1045 return std::move(Err);
1046 encodeULEB128(Entry.Values[1], OS);
1047 break;
1048 }
1049
1050 return OS.tell() - BeginOffset;
1051}
1052
1054 const DWARFYAML::LoclistEntry &Entry,
1055 uint8_t AddrSize,
1056 bool IsLittleEndian) {
1057 uint64_t BeginOffset = OS.tell();
1058 writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);
1059
1060 StringRef EncodingName = dwarf::LocListEncodingString(Entry.Operator);
1061
1062 auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
1063 return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
1064 };
1065
1066 auto WriteAddress = [&](uint64_t Addr) -> Error {
1067 return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
1068 IsLittleEndian);
1069 };
1070
1071 auto WriteDWARFOperations = [&]() -> Error {
1072 std::string OpBuffer;
1073 raw_string_ostream OpBufferOS(OpBuffer);
1074 uint64_t DescriptionsLength = 0;
1075
1076 for (const DWARFYAML::DWARFOperation &Op : Entry.Descriptions) {
1077 if (Expected<uint64_t> OpSize =
1078 writeDWARFExpression(OpBufferOS, Op, AddrSize, IsLittleEndian))
1079 DescriptionsLength += *OpSize;
1080 else
1081 return OpSize.takeError();
1082 }
1083
1084 if (Entry.DescriptionsLength)
1085 DescriptionsLength = *Entry.DescriptionsLength;
1086 else
1087 DescriptionsLength = OpBuffer.size();
1088
1089 encodeULEB128(DescriptionsLength, OS);
1090 OS.write(OpBuffer.data(), OpBuffer.size());
1091
1092 return Error::success();
1093 };
1094
1095 switch (Entry.Operator) {
1096 case dwarf::DW_LLE_end_of_list:
1097 if (Error Err = CheckOperands(0))
1098 return std::move(Err);
1099 break;
1100 case dwarf::DW_LLE_base_addressx:
1101 if (Error Err = CheckOperands(1))
1102 return std::move(Err);
1103 encodeULEB128(Entry.Values[0], OS);
1104 break;
1105 case dwarf::DW_LLE_startx_endx:
1106 case dwarf::DW_LLE_startx_length:
1107 case dwarf::DW_LLE_offset_pair:
1108 if (Error Err = CheckOperands(2))
1109 return std::move(Err);
1110 encodeULEB128(Entry.Values[0], OS);
1111 encodeULEB128(Entry.Values[1], OS);
1112 if (Error Err = WriteDWARFOperations())
1113 return std::move(Err);
1114 break;
1115 case dwarf::DW_LLE_default_location:
1116 if (Error Err = CheckOperands(0))
1117 return std::move(Err);
1118 if (Error Err = WriteDWARFOperations())
1119 return std::move(Err);
1120 break;
1121 case dwarf::DW_LLE_base_address:
1122 if (Error Err = CheckOperands(1))
1123 return std::move(Err);
1124 if (Error Err = WriteAddress(Entry.Values[0]))
1125 return std::move(Err);
1126 break;
1127 case dwarf::DW_LLE_start_end:
1128 if (Error Err = CheckOperands(2))
1129 return std::move(Err);
1130 if (Error Err = WriteAddress(Entry.Values[0]))
1131 return std::move(Err);
1132 cantFail(WriteAddress(Entry.Values[1]));
1133 if (Error Err = WriteDWARFOperations())
1134 return std::move(Err);
1135 break;
1136 case dwarf::DW_LLE_start_length:
1137 if (Error Err = CheckOperands(2))
1138 return std::move(Err);
1139 if (Error Err = WriteAddress(Entry.Values[0]))
1140 return std::move(Err);
1141 encodeULEB128(Entry.Values[1], OS);
1142 if (Error Err = WriteDWARFOperations())
1143 return std::move(Err);
1144 break;
1145 }
1146
1147 return OS.tell() - BeginOffset;
1148}
1149
1150template <typename EntryType>
1153 bool IsLittleEndian, bool Is64BitAddrSize) {
1154 for (const DWARFYAML::ListTable<EntryType> &Table : Tables) {
1155 // sizeof(version) + sizeof(address_size) + sizeof(segment_selector_size) +
1156 // sizeof(offset_entry_count) = 8
1157 uint64_t Length = 8;
1158
1159 uint8_t AddrSize;
1160 if (Table.AddrSize)
1161 AddrSize = *Table.AddrSize;
1162 else
1163 AddrSize = Is64BitAddrSize ? 8 : 4;
1164
1165 // Since the length of the current range/location lists entry is
1166 // undetermined yet, we firstly write the content of the range/location
1167 // lists to a buffer to calculate the length and then serialize the buffer
1168 // content to the actual output stream.
1169 std::string ListBuffer;
1170 raw_string_ostream ListBufferOS(ListBuffer);
1171
1172 // Offsets holds offsets for each range/location list. The i-th element is
1173 // the offset from the beginning of the first range/location list to the
1174 // location of the i-th range list.
1175 std::vector<uint64_t> Offsets;
1176
1177 for (const DWARFYAML::ListEntries<EntryType> &List : Table.Lists) {
1178 Offsets.push_back(ListBufferOS.tell());
1179 if (List.Content) {
1180 List.Content->writeAsBinary(ListBufferOS, UINT64_MAX);
1181 Length += List.Content->binary_size();
1182 } else if (List.Entries) {
1183 for (const EntryType &Entry : *List.Entries) {
1184 Expected<uint64_t> EntrySize =
1185 writeListEntry(ListBufferOS, Entry, AddrSize, IsLittleEndian);
1186 if (!EntrySize)
1187 return EntrySize.takeError();
1188 Length += *EntrySize;
1189 }
1190 }
1191 }
1192
1193 // If the offset_entry_count field isn't specified, yaml2obj will infer it
1194 // from the 'Offsets' field in the YAML description. If the 'Offsets' field
1195 // isn't specified either, yaml2obj will infer it from the auto-generated
1196 // offsets.
1197 uint32_t OffsetEntryCount;
1198 if (Table.OffsetEntryCount)
1199 OffsetEntryCount = *Table.OffsetEntryCount;
1200 else
1201 OffsetEntryCount = Table.Offsets ? Table.Offsets->size() : Offsets.size();
1202 uint64_t OffsetsSize =
1203 OffsetEntryCount * (Table.Format == dwarf::DWARF64 ? 8 : 4);
1204 Length += OffsetsSize;
1205
1206 // If the length is specified in the YAML description, we use it instead of
1207 // the actual length.
1208 if (Table.Length)
1209 Length = *Table.Length;
1210
1211 writeInitialLength(Table.Format, Length, OS, IsLittleEndian);
1212 writeInteger((uint16_t)Table.Version, OS, IsLittleEndian);
1213 writeInteger((uint8_t)AddrSize, OS, IsLittleEndian);
1214 writeInteger((uint8_t)Table.SegSelectorSize, OS, IsLittleEndian);
1215 writeInteger((uint32_t)OffsetEntryCount, OS, IsLittleEndian);
1216
1217 auto EmitOffsets = [&](ArrayRef<uint64_t> Offsets, uint64_t OffsetsSize) {
1218 for (uint64_t Offset : Offsets)
1219 writeDWARFOffset(OffsetsSize + Offset, Table.Format, OS,
1220 IsLittleEndian);
1221 };
1222
1223 if (Table.Offsets)
1224 EmitOffsets(ArrayRef<uint64_t>((const uint64_t *)Table.Offsets->data(),
1225 Table.Offsets->size()),
1226 0);
1227 else if (OffsetEntryCount != 0)
1228 EmitOffsets(Offsets, OffsetsSize);
1229
1230 OS.write(ListBuffer.data(), ListBuffer.size());
1231 }
1232
1233 return Error::success();
1234}
1235
1237 assert(DI.DebugRnglists && "unexpected emitDebugRnglists() call");
1240}
1241
1243 assert(DI.DebugLoclists && "unexpected emitDebugRnglists() call");
1246}
1247
1248std::function<Error(raw_ostream &, const DWARFYAML::Data &)>
1250 auto EmitFunc =
1252 std::function<Error(raw_ostream &, const DWARFYAML::Data &)>>(SecName)
1253 .Case("debug_abbrev", DWARFYAML::emitDebugAbbrev)
1254 .Case("debug_addr", DWARFYAML::emitDebugAddr)
1255 .Case("debug_aranges", DWARFYAML::emitDebugAranges)
1256 .Case("debug_gnu_pubnames", DWARFYAML::emitDebugGNUPubnames)
1257 .Case("debug_gnu_pubtypes", DWARFYAML::emitDebugGNUPubtypes)
1258 .Case("debug_info", DWARFYAML::emitDebugInfo)
1259 .Case("debug_line", DWARFYAML::emitDebugLine)
1260 .Case("debug_loclists", DWARFYAML::emitDebugLoclists)
1261 .Case("debug_pubnames", DWARFYAML::emitDebugPubnames)
1262 .Case("debug_pubtypes", DWARFYAML::emitDebugPubtypes)
1263 .Case("debug_ranges", DWARFYAML::emitDebugRanges)
1264 .Case("debug_rnglists", DWARFYAML::emitDebugRnglists)
1265 .Case("debug_str", DWARFYAML::emitDebugStr)
1266 .Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets)
1267 .Case("debug_names", DWARFYAML::emitDebugNames)
1268 .Default([&](raw_ostream &, const DWARFYAML::Data &) {
1270 SecName + " is not supported");
1271 });
1272
1273 return EmitFunc;
1274}
1275
1276static Error
1278 StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) {
1279 std::string Data;
1280 raw_string_ostream DebugInfoStream(Data);
1281
1282 auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Sec);
1283
1284 if (Error Err = EmitFunc(DebugInfoStream, DI))
1285 return Err;
1286 if (!Data.empty())
1287 OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data);
1288
1289 return Error::success();
1290}
1291
1292Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
1293DWARFYAML::emitDebugSections(StringRef YAMLString, bool IsLittleEndian,
1294 bool Is64BitAddrSize) {
1295 auto CollectDiagnostic = [](const SMDiagnostic &Diag, void *DiagContext) {
1296 *static_cast<SMDiagnostic *>(DiagContext) = Diag;
1297 };
1298
1299 SMDiagnostic GeneratedDiag;
1300 yaml::Input YIn(YAMLString, /*Ctxt=*/nullptr, CollectDiagnostic,
1301 &GeneratedDiag);
1302
1303 DWARFYAML::Data DI;
1304 DI.IsLittleEndian = IsLittleEndian;
1305 DI.Is64BitAddrSize = Is64BitAddrSize;
1306
1307 YIn >> DI;
1308 if (YIn.error())
1309 return createStringError(YIn.error(), GeneratedDiag.getMessage());
1310
1312 Error Err = Error::success();
1313
1314 for (StringRef SecName : DI.getNonEmptySectionNames())
1315 Err = joinErrors(std::move(Err),
1316 emitDebugSectionImpl(DI, SecName, DebugSections));
1317
1318 if (Err)
1319 return std::move(Err);
1320 return std::move(DebugSections);
1321}
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 writeV5EntryFormat(raw_ostream &OS, uint8_t Count, ArrayRef< DWARFYAML::LnctForm > Format)
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:1321
@ 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
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
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:268
std::vector< LineTable > DebugLines
Definition DWARFYAML.h:270
std::optional< std::vector< AddrTableEntry > > DebugAddr
Definition DWARFYAML.h:261
std::optional< std::vector< Ranges > > DebugRanges
Definition DWARFYAML.h:260
std::optional< std::vector< ListTable< LoclistEntry > > > DebugLoclists
Definition DWARFYAML.h:272
std::vector< AbbrevTable > DebugAbbrev
Definition DWARFYAML.h:256
LLVM_ABI Expected< AbbrevTableInfo > getAbbrevTableInfoByID(uint64_t ID) const
Definition DWARFYAML.cpp:61
std::optional< PubSection > GNUPubNames
Definition DWARFYAML.h:265
std::optional< std::vector< ARange > > DebugAranges
Definition DWARFYAML.h:259
LLVM_ABI StringRef getAbbrevTableContentByIndex(uint64_t Index) const
std::optional< PubSection > GNUPubTypes
Definition DWARFYAML.h:266
LLVM_ABI SetVector< StringRef > getNonEmptySectionNames() const
Definition DWARFYAML.cpp:25
std::optional< std::vector< StringOffsetsTable > > DebugStrOffsets
Definition DWARFYAML.h:258
std::optional< std::vector< StringRef > > DebugStrings
Definition DWARFYAML.h:257
std::optional< std::vector< ListTable< RnglistEntry > > > DebugRnglists
Definition DWARFYAML.h:271
std::optional< PubSection > PubNames
Definition DWARFYAML.h:262
std::optional< DebugNamesSection > DebugNames
Definition DWARFYAML.h:273
std::optional< PubSection > PubTypes
Definition DWARFYAML.h:263
std::vector< FormValue > Values
Definition DWARFYAML.h:102
std::optional< uint64_t > Length
Definition DWARFYAML.h:172
std::optional< uint8_t > OpcodeBase
Definition DWARFYAML.h:182
std::vector< LineTableOpcode > Opcodes
Definition DWARFYAML.h:195
std::optional< uint64_t > PrologueLength
Definition DWARFYAML.h:176
dwarf::DwarfFormat Format
Definition DWARFYAML.h:171
std::vector< File > Files
Definition DWARFYAML.h:187
std::vector< StringRef > IncludeDirs
Definition DWARFYAML.h:186
std::vector< LnctForm > DirectoryEntryFormat
Definition DWARFYAML.h:191
std::vector< LnctForm > FileNameEntryFormat
Definition DWARFYAML.h:193
std::optional< std::vector< uint8_t > > StandardOpcodeLengths
Definition DWARFYAML.h:183
dwarf::DwarfFormat Format
Definition DWARFYAML.h:86
std::vector< PubEntry > Entries
Definition DWARFYAML.h:91
std::optional< yaml::Hex64 > Length
Definition DWARFYAML.h:214
std::vector< yaml::Hex64 > Offsets
Definition DWARFYAML.h:217
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