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
261template <typename FormTy>
262static Error writeFormValues(raw_ostream &OS, const FormTy &Forms,
264 const dwarf::FormParams &Params,
265 bool IsLittleEndian) {
266 auto FormIt = Forms.begin();
267 const DWARFYAML::FormValue *FormVal = Values.begin();
268 for (; FormIt != Forms.end() && FormVal != Values.end();
269 ++FormIt, ++FormVal) {
270 dwarf::Form Form = *FormIt;
271 bool Indirect;
272 do {
273 Indirect = false;
274 switch (Form) {
275 case dwarf::DW_FORM_addr:
276 // TODO: Test this error.
278 FormVal->Value, Params.AddrSize, OS, IsLittleEndian))
279 return Err;
280 break;
281 case dwarf::DW_FORM_ref_addr:
282 // TODO: Test this error.
283 if (Error Err = writeVariableSizedInteger(FormVal->Value,
284 Params.getRefAddrByteSize(),
285 OS, IsLittleEndian))
286 return Err;
287 break;
288 case dwarf::DW_FORM_exprloc:
289 case dwarf::DW_FORM_block:
290 encodeULEB128(FormVal->BlockData.size(), OS);
291 OS.write((const char *)FormVal->BlockData.data(),
292 FormVal->BlockData.size());
293 break;
294 case dwarf::DW_FORM_block1: {
295 writeInteger((uint8_t)FormVal->BlockData.size(), OS, IsLittleEndian);
296 OS.write((const char *)FormVal->BlockData.data(),
297 FormVal->BlockData.size());
298 break;
299 }
300 case dwarf::DW_FORM_block2: {
301 writeInteger((uint16_t)FormVal->BlockData.size(), OS, IsLittleEndian);
302 OS.write((const char *)FormVal->BlockData.data(),
303 FormVal->BlockData.size());
304 break;
305 }
306 case dwarf::DW_FORM_block4: {
307 writeInteger((uint32_t)FormVal->BlockData.size(), OS, IsLittleEndian);
308 OS.write((const char *)FormVal->BlockData.data(),
309 FormVal->BlockData.size());
310 break;
311 }
312 case dwarf::DW_FORM_strx:
313 case dwarf::DW_FORM_addrx:
314 case dwarf::DW_FORM_rnglistx:
315 case dwarf::DW_FORM_loclistx:
316 case dwarf::DW_FORM_udata:
317 case dwarf::DW_FORM_ref_udata:
318 case dwarf::DW_FORM_GNU_addr_index:
319 case dwarf::DW_FORM_GNU_str_index:
320 encodeULEB128(FormVal->Value, OS);
321 break;
322 case dwarf::DW_FORM_data1:
323 case dwarf::DW_FORM_ref1:
324 case dwarf::DW_FORM_flag:
325 case dwarf::DW_FORM_strx1:
326 case dwarf::DW_FORM_addrx1:
327 writeInteger((uint8_t)FormVal->Value, OS, IsLittleEndian);
328 break;
329 case dwarf::DW_FORM_data2:
330 case dwarf::DW_FORM_ref2:
331 case dwarf::DW_FORM_strx2:
332 case dwarf::DW_FORM_addrx2:
333 writeInteger((uint16_t)FormVal->Value, OS, IsLittleEndian);
334 break;
335 case dwarf::DW_FORM_data4:
336 case dwarf::DW_FORM_ref4:
337 case dwarf::DW_FORM_ref_sup4:
338 case dwarf::DW_FORM_strx4:
339 case dwarf::DW_FORM_addrx4:
340 writeInteger((uint32_t)FormVal->Value, OS, IsLittleEndian);
341 break;
342 case dwarf::DW_FORM_data8:
343 case dwarf::DW_FORM_ref8:
344 case dwarf::DW_FORM_ref_sup8:
345 case dwarf::DW_FORM_ref_sig8:
346 writeInteger((uint64_t)FormVal->Value, OS, IsLittleEndian);
347 break;
348 case dwarf::DW_FORM_sdata:
349 encodeSLEB128(FormVal->Value, OS);
350 break;
351 case dwarf::DW_FORM_string:
352 OS.write(FormVal->CStr.data(), FormVal->CStr.size());
353 OS.write('\0');
354 break;
355 case dwarf::DW_FORM_indirect:
356 encodeULEB128(FormVal->Value, OS);
357 Indirect = true;
358 Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value);
359 ++FormVal;
360 break;
361 case dwarf::DW_FORM_strp:
362 case dwarf::DW_FORM_sec_offset:
363 case dwarf::DW_FORM_GNU_ref_alt:
364 case dwarf::DW_FORM_GNU_strp_alt:
365 case dwarf::DW_FORM_line_strp:
366 case dwarf::DW_FORM_strp_sup:
368 Params.getDwarfOffsetByteSize(), OS,
369 IsLittleEndian));
370 break;
371 default:
372 break;
373 }
374 } while (Indirect);
375 }
376 return Error::success();
377}
378
380 uint64_t AbbrevTableID,
381 const dwarf::FormParams &Params,
382 const DWARFYAML::Entry &Entry,
383 raw_ostream &OS, bool IsLittleEndian) {
384 uint64_t EntryBegin = OS.tell();
385 encodeULEB128(Entry.AbbrCode, OS);
386 uint32_t AbbrCode = Entry.AbbrCode;
387 if (AbbrCode == 0 || Entry.Values.empty())
388 return OS.tell() - EntryBegin;
389
390 Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =
391 DI.getAbbrevTableInfoByID(AbbrevTableID);
392 if (!AbbrevTableInfoOrErr)
394 toString(AbbrevTableInfoOrErr.takeError()) +
395 " for compilation unit with index " +
396 utostr(CUIndex));
397
398 ArrayRef<DWARFYAML::Abbrev> AbbrevDecls(
399 DI.DebugAbbrev[AbbrevTableInfoOrErr->Index].Table);
400
401 if (AbbrCode > AbbrevDecls.size())
402 return createStringError(
404 "abbrev code must be less than or equal to the number of "
405 "entries in abbreviation table");
406 const DWARFYAML::Abbrev &Abbrev = AbbrevDecls[AbbrCode - 1];
407 if (Error Err =
409 map_range(Abbrev.Attributes,
410 [](const DWARFYAML::AttributeAbbrev &Abbr) {
411 return Abbr.Form;
412 }),
413 Entry.Values, Params, IsLittleEndian))
414 return Err;
415
416 return OS.tell() - EntryBegin;
417}
418
420 for (uint64_t I = 0; I < DI.Units.size(); ++I) {
421 const DWARFYAML::Unit &Unit = DI.Units[I];
422 uint8_t AddrSize;
423 if (Unit.AddrSize)
424 AddrSize = *Unit.AddrSize;
425 else
426 AddrSize = DI.Is64BitAddrSize ? 8 : 4;
427 dwarf::FormParams Params = {Unit.Version, AddrSize, Unit.Format};
428 uint64_t Length = 3; // sizeof(version) + sizeof(address_size)
429 Length += Params.getDwarfOffsetByteSize(); // sizeof(debug_abbrev_offset)
430 if (Unit.Version >= 5) {
431 ++Length; // sizeof(unit_type)
432 switch (Unit.Type) {
433 case dwarf::DW_UT_compile:
434 case dwarf::DW_UT_partial:
435 default:
436 break;
437 case dwarf::DW_UT_type:
438 case dwarf::DW_UT_split_type:
439 // sizeof(type_signature) + sizeof(type_offset)
440 Length += 8 + Params.getDwarfOffsetByteSize();
441 break;
442 case dwarf::DW_UT_skeleton:
443 case dwarf::DW_UT_split_compile:
444 Length += 8; // sizeof(dwo_id)
445 }
446 }
447
448 // Since the length of the current compilation unit is undetermined yet, we
449 // firstly write the content of the compilation unit to a buffer to
450 // calculate it and then serialize the buffer content to the actual output
451 // stream.
452 std::string EntryBuffer;
453 raw_string_ostream EntryBufferOS(EntryBuffer);
454
455 uint64_t AbbrevTableID = Unit.AbbrevTableID.value_or(I);
456 for (const DWARFYAML::Entry &Entry : Unit.Entries) {
457 if (Expected<uint64_t> EntryLength =
458 writeDIE(DI, I, AbbrevTableID, Params, Entry, EntryBufferOS,
459 DI.IsLittleEndian))
460 Length += *EntryLength;
461 else
462 return EntryLength.takeError();
463 }
464
465 // If the length is specified in the YAML description, we use it instead of
466 // the actual length.
467 if (Unit.Length)
468 Length = *Unit.Length;
469
472
473 uint64_t AbbrevTableOffset = 0;
474 if (Unit.AbbrOffset) {
475 AbbrevTableOffset = *Unit.AbbrOffset;
476 } else {
477 if (Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =
478 DI.getAbbrevTableInfoByID(AbbrevTableID)) {
479 AbbrevTableOffset = AbbrevTableInfoOrErr->Offset;
480 } else {
481 // The current compilation unit may not have DIEs and it will not be
482 // able to find the associated abbrev table. We consume the error and
483 // assign 0 to the debug_abbrev_offset in such circumstances.
484 consumeError(AbbrevTableInfoOrErr.takeError());
485 }
486 }
487
488 if (Unit.Version >= 5) {
490 writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
491 writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);
492 switch (Unit.Type) {
493 case dwarf::DW_UT_compile:
494 case dwarf::DW_UT_partial:
495 default:
496 break;
497 case dwarf::DW_UT_type:
498 case dwarf::DW_UT_split_type:
501 break;
502 case dwarf::DW_UT_skeleton:
503 case dwarf::DW_UT_split_compile:
505 break;
506 }
507 } else {
508 writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);
509 writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
510 }
511
512 OS.write(EntryBuffer.data(), EntryBuffer.size());
513 }
514
515 return Error::success();
516}
517
518static void emitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) {
519 OS.write(File.Name.data(), File.Name.size());
520 OS.write('\0');
521 encodeULEB128(File.DirIdx, OS);
522 encodeULEB128(File.ModTime, OS);
523 encodeULEB128(File.Length, OS);
524}
525
527 uint8_t AddrSize, bool IsLittleEndian,
528 raw_ostream &OS) {
529 // The first byte of extended opcodes is a zero byte. The next bytes are an
530 // ULEB128 integer giving the number of bytes in the instruction itself (does
531 // not include the first zero byte or the size). We serialize the instruction
532 // itself into the OpBuffer and then write the size of the buffer and the
533 // buffer to the real output stream.
534 std::string OpBuffer;
535 raw_string_ostream OpBufferOS(OpBuffer);
536 writeInteger((uint8_t)Op.SubOpcode, OpBufferOS, IsLittleEndian);
537 switch (Op.SubOpcode) {
538 case dwarf::DW_LNE_set_address:
539 cantFail(writeVariableSizedInteger(Op.Data, AddrSize, OpBufferOS,
540 IsLittleEndian));
541 break;
542 case dwarf::DW_LNE_define_file:
543 emitFileEntry(OpBufferOS, Op.FileEntry);
544 break;
545 case dwarf::DW_LNE_set_discriminator:
546 encodeULEB128(Op.Data, OpBufferOS);
547 break;
548 case dwarf::DW_LNE_end_sequence:
549 break;
550 default:
551 for (auto OpByte : Op.UnknownOpcodeData)
552 writeInteger((uint8_t)OpByte, OpBufferOS, IsLittleEndian);
553 }
554 uint64_t ExtLen = Op.ExtLen.value_or(OpBuffer.size());
555 encodeULEB128(ExtLen, OS);
556 OS.write(OpBuffer.data(), OpBuffer.size());
557}
558
560 uint8_t OpcodeBase, uint8_t AddrSize,
561 raw_ostream &OS, bool IsLittleEndian) {
562 writeInteger((uint8_t)Op.Opcode, OS, IsLittleEndian);
563 if (Op.Opcode == 0) {
564 writeExtendedOpcode(Op, AddrSize, IsLittleEndian, OS);
565 } else if (Op.Opcode < OpcodeBase) {
566 switch (Op.Opcode) {
567 case dwarf::DW_LNS_copy:
568 case dwarf::DW_LNS_negate_stmt:
569 case dwarf::DW_LNS_set_basic_block:
570 case dwarf::DW_LNS_const_add_pc:
571 case dwarf::DW_LNS_set_prologue_end:
572 case dwarf::DW_LNS_set_epilogue_begin:
573 break;
574
575 case dwarf::DW_LNS_advance_pc:
576 case dwarf::DW_LNS_set_file:
577 case dwarf::DW_LNS_set_column:
578 case dwarf::DW_LNS_set_isa:
579 encodeULEB128(Op.Data, OS);
580 break;
581
582 case dwarf::DW_LNS_advance_line:
583 encodeSLEB128(Op.SData, OS);
584 break;
585
586 case dwarf::DW_LNS_fixed_advance_pc:
587 writeInteger((uint16_t)Op.Data, OS, IsLittleEndian);
588 break;
589
590 default:
591 for (auto OpData : Op.StandardOpcodeData) {
592 encodeULEB128(OpData, OS);
593 }
594 }
595 }
596}
597
598static std::vector<uint8_t>
599getStandardOpcodeLengths(uint16_t Version, std::optional<uint8_t> OpcodeBase) {
600 // If the opcode_base field isn't specified, we returns the
601 // standard_opcode_lengths array according to the version by default.
602 std::vector<uint8_t> StandardOpcodeLengths{0, 1, 1, 1, 1, 0,
603 0, 0, 1, 0, 0, 1};
604 if (Version == 2) {
605 // DWARF v2 uses the same first 9 standard opcodes as v3-5.
606 StandardOpcodeLengths.resize(9);
607 } else if (OpcodeBase) {
608 StandardOpcodeLengths.resize(*OpcodeBase > 0 ? *OpcodeBase - 1 : 0, 0);
609 }
610 return StandardOpcodeLengths;
611}
612
615 OS << static_cast<char>(Count);
616 for (const auto [ContentType, Form] : Format) {
617 encodeULEB128(ContentType, OS);
618 encodeULEB128(Form, OS);
619 }
620}
621
624 ArrayRef<std::vector<DWARFYAML::FormValue>> EntryList,
625 const dwarf::FormParams &Params,
626 bool IsLittleEndian) {
627 encodeULEB128(Count, OS);
628 for (ArrayRef<DWARFYAML::FormValue> Entry : EntryList) {
629 if (Error Err = writeFormValues(
630 OS,
631 map_range(Format,
632 [](const DWARFYAML::LnctForm &F) { return F.Form; }),
633 Entry, Params, IsLittleEndian))
634 return Err;
635 }
636 return Error::success();
637}
638
640 for (const DWARFYAML::LineTable &LineTable : DI.DebugLines) {
641 // Buffer holds the bytes following the header_length (or prologue_length in
642 // DWARFv2) field to the end of the line number program itself.
643 std::string Buffer;
644 raw_string_ostream BufferOS(Buffer);
645
647 if (LineTable.Version >= 4)
652
653 std::vector<uint8_t> StandardOpcodeLengths =
656 uint8_t OpcodeBase = LineTable.OpcodeBase
658 : StandardOpcodeLengths.size() + 1;
659 writeInteger(OpcodeBase, BufferOS, DI.IsLittleEndian);
660 for (uint8_t OpcodeLength : StandardOpcodeLengths)
661 writeInteger(OpcodeLength, BufferOS, DI.IsLittleEndian);
662
663 if (LineTable.Version >= 5) {
666
669 if (Error Err =
673 return Err;
674
677 if (Error Err = writeV5Entry(
680 return Err;
681 } else {
682 for (StringRef IncludeDir : LineTable.IncludeDirs) {
683 BufferOS.write(IncludeDir.data(), IncludeDir.size());
684 BufferOS.write('\0');
685 }
686 BufferOS.write('\0');
687
688 for (const DWARFYAML::File &File : LineTable.Files)
689 emitFileEntry(BufferOS, File);
690 BufferOS.write('\0');
691 }
692
693 uint64_t HeaderLength =
695
697 writeLineTableOpcode(Op, OpcodeBase, DI.Is64BitAddrSize ? 8 : 4, BufferOS,
698 DI.IsLittleEndian);
699
701 if (LineTable.Length) {
703 } else {
704 Length =
705 (LineTable.Format == dwarf::DWARF64 ? 8 : 4); // sizeof(unit_length)
706 Length += 2; // sizeof(version)
707 if (LineTable.Version >= 5)
708 Length += 2; // sizeof(address_size) + sizeof(segment_selector_size)
709 Length += Buffer.size();
710 }
711
714 if (LineTable.Version >= 5) {
717 }
718 writeDWARFOffset(HeaderLength, LineTable.Format, OS, DI.IsLittleEndian);
719 OS.write(Buffer.data(), Buffer.size());
720 }
721
722 return Error::success();
723}
724
726 for (const AddrTableEntry &TableEntry : *DI.DebugAddr) {
727 uint8_t AddrSize;
728 if (TableEntry.AddrSize)
729 AddrSize = *TableEntry.AddrSize;
730 else
731 AddrSize = DI.Is64BitAddrSize ? 8 : 4;
732
734 if (TableEntry.Length)
735 Length = (uint64_t)*TableEntry.Length;
736 else
737 // 2 (version) + 1 (address_size) + 1 (segment_selector_size) = 4
738 Length = 4 + (AddrSize + TableEntry.SegSelectorSize) *
739 TableEntry.SegAddrPairs.size();
740
741 writeInitialLength(TableEntry.Format, Length, OS, DI.IsLittleEndian);
742 writeInteger((uint16_t)TableEntry.Version, OS, DI.IsLittleEndian);
743 writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
744 writeInteger((uint8_t)TableEntry.SegSelectorSize, OS, DI.IsLittleEndian);
745
746 for (const SegAddrPair &Pair : TableEntry.SegAddrPairs) {
747 if (TableEntry.SegSelectorSize != yaml::Hex8{0})
749 TableEntry.SegSelectorSize,
750 OS, DI.IsLittleEndian))
752 "unable to write debug_addr segment: %s",
753 toString(std::move(Err)).c_str());
754 if (AddrSize != 0)
755 if (Error Err = writeVariableSizedInteger(Pair.Address, AddrSize, OS,
756 DI.IsLittleEndian))
758 "unable to write debug_addr address: %s",
759 toString(std::move(Err)).c_str());
760 }
761 }
762
763 return Error::success();
764}
765
767 assert(DI.DebugStrOffsets && "unexpected emitDebugStrOffsets() call");
768 for (const DWARFYAML::StringOffsetsTable &Table : *DI.DebugStrOffsets) {
770 if (Table.Length)
771 Length = *Table.Length;
772 else
773 // sizeof(version) + sizeof(padding) = 4
774 Length =
775 4 + Table.Offsets.size() * (Table.Format == dwarf::DWARF64 ? 8 : 4);
776
780
781 for (uint64_t Offset : Table.Offsets)
783 }
784
785 return Error::success();
786}
787
788namespace {
789/// Emits the header for a DebugNames section.
790void emitDebugNamesHeader(raw_ostream &OS, bool IsLittleEndian,
791 uint32_t NameCount, uint32_t AbbrevSize,
792 uint32_t CombinedSizeOtherParts) {
793 // Use the same AugmentationString as AsmPrinter.
794 StringRef AugmentationString = "LLVM0700";
795 size_t TotalSize = CombinedSizeOtherParts + 5 * sizeof(uint32_t) +
796 2 * sizeof(uint16_t) + sizeof(NameCount) +
797 sizeof(AbbrevSize) + AugmentationString.size();
798 writeInteger(uint32_t(TotalSize), OS, IsLittleEndian); // Unit length
799
800 // Everything below is included in total size.
801 writeInteger(uint16_t(5), OS, IsLittleEndian); // Version
802 writeInteger(uint16_t(0), OS, IsLittleEndian); // Padding
803 writeInteger(uint32_t(1), OS, IsLittleEndian); // Compilation Unit count
804 writeInteger(uint32_t(0), OS, IsLittleEndian); // Local Type Unit count
805 writeInteger(uint32_t(0), OS, IsLittleEndian); // Foreign Type Unit count
806 writeInteger(uint32_t(0), OS, IsLittleEndian); // Bucket count
807 writeInteger(NameCount, OS, IsLittleEndian);
808 writeInteger(AbbrevSize, OS, IsLittleEndian);
809 writeInteger(uint32_t(AugmentationString.size()), OS, IsLittleEndian);
810 OS.write(AugmentationString.data(), AugmentationString.size());
811}
812
813/// Emits the abbreviations for a DebugNames section.
814std::string
815emitDebugNamesAbbrev(ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {
816 std::string Data;
818 for (const DWARFYAML::DebugNameAbbreviation &Abbrev : Abbrevs) {
819 encodeULEB128(Abbrev.Code, OS);
820 encodeULEB128(Abbrev.Tag, OS);
821 for (auto [Idx, Form] : Abbrev.Indices) {
822 encodeULEB128(Idx, OS);
823 encodeULEB128(Form, OS);
824 }
825 encodeULEB128(0, OS);
826 encodeULEB128(0, OS);
827 }
828 encodeULEB128(0, OS);
829 return Data;
830}
831
832/// Emits a simple CU offsets list for a DebugNames section containing a single
833/// CU at offset 0.
834std::string emitDebugNamesCUOffsets(bool IsLittleEndian) {
835 std::string Data;
836 raw_string_ostream OS(Data);
837 writeInteger(uint32_t(0), OS, IsLittleEndian);
838 return Data;
839}
840
841/// Emits the "NameTable" for a DebugNames section; according to the spec, it
842/// consists of two arrays: an array of string offsets, followed immediately by
843/// an array of entry offsets. The string offsets are emitted in the order
844/// provided in `Entries`.
845std::string emitDebugNamesNameTable(
846 bool IsLittleEndian,
847 const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> &Entries,
848 ArrayRef<uint32_t> EntryPoolOffsets) {
849 assert(Entries.size() == EntryPoolOffsets.size());
850
851 std::string Data;
852 raw_string_ostream OS(Data);
853
854 for (uint32_t Strp : make_first_range(Entries))
855 writeInteger(Strp, OS, IsLittleEndian);
856 for (uint32_t PoolOffset : EntryPoolOffsets)
857 writeInteger(PoolOffset, OS, IsLittleEndian);
858 return Data;
859}
860
861/// Groups entries based on their name (strp) code and returns a map.
862DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>>
863groupEntries(ArrayRef<DWARFYAML::DebugNameEntry> Entries) {
864 DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> StrpToEntries;
865 for (const DWARFYAML::DebugNameEntry &Entry : Entries)
866 StrpToEntries[Entry.NameStrp].push_back(Entry);
867 return StrpToEntries;
868}
869
870/// Finds the abbreviation whose code is AbbrevCode and returns a list
871/// containing the expected size of all non-zero-length forms.
872Expected<SmallVector<uint8_t>>
873getNonZeroDataSizesFor(uint32_t AbbrevCode,
875 const auto *AbbrevIt = find_if(Abbrevs, [&](const auto &Abbrev) {
876 return Abbrev.Code.value == AbbrevCode;
877 });
878 if (AbbrevIt == Abbrevs.end())
880 "did not find an Abbreviation for this code");
881
882 SmallVector<uint8_t> DataSizes;
883 dwarf::FormParams Params{/*Version=*/5, /*AddrSize=*/4, dwarf::DWARF32};
884 for (auto [Idx, Form] : AbbrevIt->Indices) {
885 std::optional<uint8_t> FormSize = dwarf::getFixedFormByteSize(Form, Params);
886 if (!FormSize)
888 "unsupported Form for YAML debug_names emitter");
889 if (FormSize == 0)
890 continue;
891 DataSizes.push_back(*FormSize);
892 }
893 return DataSizes;
894}
895
896struct PoolOffsetsAndData {
897 std::string PoolData;
898 std::vector<uint32_t> PoolOffsets;
899};
900
901/// Emits the entry pool and returns an array of offsets containing the start
902/// offset for the entries of each unique name.
903/// Verifies that the provided number of data values match those expected by
904/// the abbreviation table.
905Expected<PoolOffsetsAndData> emitDebugNamesEntryPool(
906 bool IsLittleEndian,
907 const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>>
908 &StrpToEntries,
910 PoolOffsetsAndData Result;
911 raw_string_ostream OS(Result.PoolData);
912
913 for (ArrayRef<DWARFYAML::DebugNameEntry> EntriesWithSameName :
914 make_second_range(StrpToEntries)) {
915 Result.PoolOffsets.push_back(Result.PoolData.size());
916
917 for (const DWARFYAML::DebugNameEntry &Entry : EntriesWithSameName) {
918 encodeULEB128(Entry.Code, OS);
919
920 Expected<SmallVector<uint8_t>> DataSizes =
921 getNonZeroDataSizesFor(Entry.Code, Abbrevs);
922 if (!DataSizes)
923 return DataSizes.takeError();
924 if (DataSizes->size() != Entry.Values.size())
925 return createStringError(
927 "mismatch between provided and required number of values");
928
929 for (auto [Value, ValueSize] : zip_equal(Entry.Values, *DataSizes))
930 if (Error E =
931 writeVariableSizedInteger(Value, ValueSize, OS, IsLittleEndian))
932 return std::move(E);
933 }
934 encodeULEB128(0, OS);
935 }
936
937 return Result;
938}
939} // namespace
940
942 assert(DI.DebugNames && "unexpected emitDebugNames() call");
943 const DebugNamesSection DebugNames = DI.DebugNames.value();
944
946 groupEntries(DebugNames.Entries);
947
948 // Emit all sub-sections into individual strings so that we may compute
949 // relative offsets and sizes.
950 Expected<PoolOffsetsAndData> PoolInfo = emitDebugNamesEntryPool(
951 DI.IsLittleEndian, StrpToEntries, DebugNames.Abbrevs);
952 if (!PoolInfo)
953 return PoolInfo.takeError();
954 std::string NamesTableData = emitDebugNamesNameTable(
955 DI.IsLittleEndian, StrpToEntries, PoolInfo->PoolOffsets);
956
957 std::string AbbrevData = emitDebugNamesAbbrev(DebugNames.Abbrevs);
958 std::string CUOffsetsData = emitDebugNamesCUOffsets(DI.IsLittleEndian);
959
960 size_t TotalSize = PoolInfo->PoolData.size() + NamesTableData.size() +
961 AbbrevData.size() + CUOffsetsData.size();
962
963 // Start real emission by combining all individual strings.
964 emitDebugNamesHeader(OS, DI.IsLittleEndian, StrpToEntries.size(),
965 AbbrevData.size(), TotalSize);
966 OS.write(CUOffsetsData.data(), CUOffsetsData.size());
967 // No local TUs, no foreign TUs, no hash lookups table.
968 OS.write(NamesTableData.data(), NamesTableData.size());
969 OS.write(AbbrevData.data(), AbbrevData.size());
970 OS.write(PoolInfo->PoolData.data(), PoolInfo->PoolData.size());
971
972 return Error::success();
973}
974
975static Error checkOperandCount(StringRef EncodingString,
977 uint64_t ExpectedOperands) {
978 if (Values.size() != ExpectedOperands)
979 return createStringError(
981 "invalid number (%zu) of operands for the operator: %s, %" PRIu64
982 " expected",
983 Values.size(), EncodingString.str().c_str(), ExpectedOperands);
984
985 return Error::success();
986}
987
989 uint64_t Addr, uint8_t AddrSize,
990 bool IsLittleEndian) {
991 if (Error Err = writeVariableSizedInteger(Addr, AddrSize, OS, IsLittleEndian))
993 "unable to write address for the operator %s: %s",
994 EncodingName.str().c_str(),
995 toString(std::move(Err)).c_str());
996
997 return Error::success();
998}
999
1000static Expected<uint64_t>
1003 uint8_t AddrSize, bool IsLittleEndian) {
1004 auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
1006 Operation.Values, ExpectedOperands);
1007 };
1008
1009 uint64_t ExpressionBegin = OS.tell();
1010 writeInteger((uint8_t)Operation.Operator, OS, IsLittleEndian);
1011 switch (Operation.Operator) {
1012 case dwarf::DW_OP_consts:
1013 if (Error Err = CheckOperands(1))
1014 return std::move(Err);
1015 encodeSLEB128(Operation.Values[0], OS);
1016 break;
1017 case dwarf::DW_OP_stack_value:
1018 if (Error Err = CheckOperands(0))
1019 return std::move(Err);
1020 break;
1021 default:
1022 StringRef EncodingStr = dwarf::OperationEncodingString(Operation.Operator);
1024 "DWARF expression: " +
1025 (EncodingStr.empty()
1026 ? "0x" + utohexstr(Operation.Operator)
1027 : EncodingStr) +
1028 " is not supported");
1029 }
1030 return OS.tell() - ExpressionBegin;
1031}
1032
1034 const DWARFYAML::RnglistEntry &Entry,
1035 uint8_t AddrSize,
1036 bool IsLittleEndian) {
1037 uint64_t BeginOffset = OS.tell();
1038 writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);
1039
1040 StringRef EncodingName = dwarf::RangeListEncodingString(Entry.Operator);
1041
1042 auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
1043 return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
1044 };
1045
1046 auto WriteAddress = [&](uint64_t Addr) -> Error {
1047 return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
1048 IsLittleEndian);
1049 };
1050
1051 switch (Entry.Operator) {
1052 case dwarf::DW_RLE_end_of_list:
1053 if (Error Err = CheckOperands(0))
1054 return std::move(Err);
1055 break;
1056 case dwarf::DW_RLE_base_addressx:
1057 if (Error Err = CheckOperands(1))
1058 return std::move(Err);
1059 encodeULEB128(Entry.Values[0], OS);
1060 break;
1061 case dwarf::DW_RLE_startx_endx:
1062 case dwarf::DW_RLE_startx_length:
1063 case dwarf::DW_RLE_offset_pair:
1064 if (Error Err = CheckOperands(2))
1065 return std::move(Err);
1066 encodeULEB128(Entry.Values[0], OS);
1067 encodeULEB128(Entry.Values[1], OS);
1068 break;
1069 case dwarf::DW_RLE_base_address:
1070 if (Error Err = CheckOperands(1))
1071 return std::move(Err);
1072 if (Error Err = WriteAddress(Entry.Values[0]))
1073 return std::move(Err);
1074 break;
1075 case dwarf::DW_RLE_start_end:
1076 if (Error Err = CheckOperands(2))
1077 return std::move(Err);
1078 if (Error Err = WriteAddress(Entry.Values[0]))
1079 return std::move(Err);
1080 cantFail(WriteAddress(Entry.Values[1]));
1081 break;
1082 case dwarf::DW_RLE_start_length:
1083 if (Error Err = CheckOperands(2))
1084 return std::move(Err);
1085 if (Error Err = WriteAddress(Entry.Values[0]))
1086 return std::move(Err);
1087 encodeULEB128(Entry.Values[1], OS);
1088 break;
1089 }
1090
1091 return OS.tell() - BeginOffset;
1092}
1093
1095 const DWARFYAML::LoclistEntry &Entry,
1096 uint8_t AddrSize,
1097 bool IsLittleEndian) {
1098 uint64_t BeginOffset = OS.tell();
1099 writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);
1100
1101 StringRef EncodingName = dwarf::LocListEncodingString(Entry.Operator);
1102
1103 auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
1104 return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
1105 };
1106
1107 auto WriteAddress = [&](uint64_t Addr) -> Error {
1108 return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
1109 IsLittleEndian);
1110 };
1111
1112 auto WriteDWARFOperations = [&]() -> Error {
1113 std::string OpBuffer;
1114 raw_string_ostream OpBufferOS(OpBuffer);
1115 uint64_t DescriptionsLength = 0;
1116
1117 for (const DWARFYAML::DWARFOperation &Op : Entry.Descriptions) {
1118 if (Expected<uint64_t> OpSize =
1119 writeDWARFExpression(OpBufferOS, Op, AddrSize, IsLittleEndian))
1120 DescriptionsLength += *OpSize;
1121 else
1122 return OpSize.takeError();
1123 }
1124
1125 if (Entry.DescriptionsLength)
1126 DescriptionsLength = *Entry.DescriptionsLength;
1127 else
1128 DescriptionsLength = OpBuffer.size();
1129
1130 encodeULEB128(DescriptionsLength, OS);
1131 OS.write(OpBuffer.data(), OpBuffer.size());
1132
1133 return Error::success();
1134 };
1135
1136 switch (Entry.Operator) {
1137 case dwarf::DW_LLE_end_of_list:
1138 if (Error Err = CheckOperands(0))
1139 return std::move(Err);
1140 break;
1141 case dwarf::DW_LLE_base_addressx:
1142 if (Error Err = CheckOperands(1))
1143 return std::move(Err);
1144 encodeULEB128(Entry.Values[0], OS);
1145 break;
1146 case dwarf::DW_LLE_startx_endx:
1147 case dwarf::DW_LLE_startx_length:
1148 case dwarf::DW_LLE_offset_pair:
1149 if (Error Err = CheckOperands(2))
1150 return std::move(Err);
1151 encodeULEB128(Entry.Values[0], OS);
1152 encodeULEB128(Entry.Values[1], OS);
1153 if (Error Err = WriteDWARFOperations())
1154 return std::move(Err);
1155 break;
1156 case dwarf::DW_LLE_default_location:
1157 if (Error Err = CheckOperands(0))
1158 return std::move(Err);
1159 if (Error Err = WriteDWARFOperations())
1160 return std::move(Err);
1161 break;
1162 case dwarf::DW_LLE_base_address:
1163 if (Error Err = CheckOperands(1))
1164 return std::move(Err);
1165 if (Error Err = WriteAddress(Entry.Values[0]))
1166 return std::move(Err);
1167 break;
1168 case dwarf::DW_LLE_start_end:
1169 if (Error Err = CheckOperands(2))
1170 return std::move(Err);
1171 if (Error Err = WriteAddress(Entry.Values[0]))
1172 return std::move(Err);
1173 cantFail(WriteAddress(Entry.Values[1]));
1174 if (Error Err = WriteDWARFOperations())
1175 return std::move(Err);
1176 break;
1177 case dwarf::DW_LLE_start_length:
1178 if (Error Err = CheckOperands(2))
1179 return std::move(Err);
1180 if (Error Err = WriteAddress(Entry.Values[0]))
1181 return std::move(Err);
1182 encodeULEB128(Entry.Values[1], OS);
1183 if (Error Err = WriteDWARFOperations())
1184 return std::move(Err);
1185 break;
1186 }
1187
1188 return OS.tell() - BeginOffset;
1189}
1190
1191template <typename EntryType>
1194 bool IsLittleEndian, bool Is64BitAddrSize) {
1195 for (const DWARFYAML::ListTable<EntryType> &Table : Tables) {
1196 // sizeof(version) + sizeof(address_size) + sizeof(segment_selector_size) +
1197 // sizeof(offset_entry_count) = 8
1198 uint64_t Length = 8;
1199
1200 uint8_t AddrSize;
1201 if (Table.AddrSize)
1202 AddrSize = *Table.AddrSize;
1203 else
1204 AddrSize = Is64BitAddrSize ? 8 : 4;
1205
1206 // Since the length of the current range/location lists entry is
1207 // undetermined yet, we firstly write the content of the range/location
1208 // lists to a buffer to calculate the length and then serialize the buffer
1209 // content to the actual output stream.
1210 std::string ListBuffer;
1211 raw_string_ostream ListBufferOS(ListBuffer);
1212
1213 // Offsets holds offsets for each range/location list. The i-th element is
1214 // the offset from the beginning of the first range/location list to the
1215 // location of the i-th range list.
1216 std::vector<uint64_t> Offsets;
1217
1218 for (const DWARFYAML::ListEntries<EntryType> &List : Table.Lists) {
1219 Offsets.push_back(ListBufferOS.tell());
1220 if (List.Content) {
1221 List.Content->writeAsBinary(ListBufferOS, UINT64_MAX);
1222 Length += List.Content->binary_size();
1223 } else if (List.Entries) {
1224 for (const EntryType &Entry : *List.Entries) {
1225 Expected<uint64_t> EntrySize =
1226 writeListEntry(ListBufferOS, Entry, AddrSize, IsLittleEndian);
1227 if (!EntrySize)
1228 return EntrySize.takeError();
1229 Length += *EntrySize;
1230 }
1231 }
1232 }
1233
1234 // If the offset_entry_count field isn't specified, yaml2obj will infer it
1235 // from the 'Offsets' field in the YAML description. If the 'Offsets' field
1236 // isn't specified either, yaml2obj will infer it from the auto-generated
1237 // offsets.
1238 uint32_t OffsetEntryCount;
1239 if (Table.OffsetEntryCount)
1240 OffsetEntryCount = *Table.OffsetEntryCount;
1241 else
1242 OffsetEntryCount = Table.Offsets ? Table.Offsets->size() : Offsets.size();
1243 uint64_t OffsetsSize =
1244 OffsetEntryCount * (Table.Format == dwarf::DWARF64 ? 8 : 4);
1245 Length += OffsetsSize;
1246
1247 // If the length is specified in the YAML description, we use it instead of
1248 // the actual length.
1249 if (Table.Length)
1250 Length = *Table.Length;
1251
1252 writeInitialLength(Table.Format, Length, OS, IsLittleEndian);
1253 writeInteger((uint16_t)Table.Version, OS, IsLittleEndian);
1254 writeInteger((uint8_t)AddrSize, OS, IsLittleEndian);
1255 writeInteger((uint8_t)Table.SegSelectorSize, OS, IsLittleEndian);
1256 writeInteger((uint32_t)OffsetEntryCount, OS, IsLittleEndian);
1257
1258 auto EmitOffsets = [&](ArrayRef<uint64_t> Offsets, uint64_t OffsetsSize) {
1259 for (uint64_t Offset : Offsets)
1260 writeDWARFOffset(OffsetsSize + Offset, Table.Format, OS,
1261 IsLittleEndian);
1262 };
1263
1264 if (Table.Offsets)
1265 EmitOffsets(ArrayRef<uint64_t>((const uint64_t *)Table.Offsets->data(),
1266 Table.Offsets->size()),
1267 0);
1268 else if (OffsetEntryCount != 0)
1269 EmitOffsets(Offsets, OffsetsSize);
1270
1271 OS.write(ListBuffer.data(), ListBuffer.size());
1272 }
1273
1274 return Error::success();
1275}
1276
1278 assert(DI.DebugRnglists && "unexpected emitDebugRnglists() call");
1281}
1282
1284 assert(DI.DebugLoclists && "unexpected emitDebugRnglists() call");
1287}
1288
1289std::function<Error(raw_ostream &, const DWARFYAML::Data &)>
1291 auto EmitFunc =
1293 std::function<Error(raw_ostream &, const DWARFYAML::Data &)>>(SecName)
1294 .Case("debug_abbrev", DWARFYAML::emitDebugAbbrev)
1295 .Case("debug_addr", DWARFYAML::emitDebugAddr)
1296 .Case("debug_aranges", DWARFYAML::emitDebugAranges)
1297 .Case("debug_gnu_pubnames", DWARFYAML::emitDebugGNUPubnames)
1298 .Case("debug_gnu_pubtypes", DWARFYAML::emitDebugGNUPubtypes)
1299 .Case("debug_info", DWARFYAML::emitDebugInfo)
1300 .Case("debug_line", DWARFYAML::emitDebugLine)
1301 .Case("debug_loclists", DWARFYAML::emitDebugLoclists)
1302 .Case("debug_pubnames", DWARFYAML::emitDebugPubnames)
1303 .Case("debug_pubtypes", DWARFYAML::emitDebugPubtypes)
1304 .Case("debug_ranges", DWARFYAML::emitDebugRanges)
1305 .Case("debug_rnglists", DWARFYAML::emitDebugRnglists)
1306 .Case("debug_str", DWARFYAML::emitDebugStr)
1307 .Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets)
1308 .Case("debug_names", DWARFYAML::emitDebugNames)
1309 .Default([&](raw_ostream &, const DWARFYAML::Data &) {
1311 SecName + " is not supported");
1312 });
1313
1314 return EmitFunc;
1315}
1316
1317static Error
1319 StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) {
1320 std::string Data;
1321 raw_string_ostream DebugInfoStream(Data);
1322
1323 auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Sec);
1324
1325 if (Error Err = EmitFunc(DebugInfoStream, DI))
1326 return Err;
1327 if (!Data.empty())
1328 OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data);
1329
1330 return Error::success();
1331}
1332
1333Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
1334DWARFYAML::emitDebugSections(StringRef YAMLString, bool IsLittleEndian,
1335 bool Is64BitAddrSize) {
1336 auto CollectDiagnostic = [](const SMDiagnostic &Diag, void *DiagContext) {
1337 *static_cast<SMDiagnostic *>(DiagContext) = Diag;
1338 };
1339
1340 SMDiagnostic GeneratedDiag;
1341 yaml::Input YIn(YAMLString, /*Ctxt=*/nullptr, CollectDiagnostic,
1342 &GeneratedDiag);
1343
1344 DWARFYAML::Data DI;
1345 DI.IsLittleEndian = IsLittleEndian;
1346 DI.Is64BitAddrSize = Is64BitAddrSize;
1347
1348 YIn >> DI;
1349 if (YIn.error())
1350 return createStringError(YIn.error(), GeneratedDiag.getMessage());
1351
1353 Error Err = Error::success();
1354
1355 for (StringRef SecName : DI.getNonEmptySectionNames())
1356 Err = joinErrors(std::move(Err),
1357 emitDebugSectionImpl(DI, SecName, DebugSections));
1358
1359 if (Err)
1360 return std::move(Err);
1361 return std::move(DebugSections);
1362}
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 writeFormValues(raw_ostream &OS, const FormTy &Forms, ArrayRef< DWARFYAML::FormValue > Values, const dwarf::FormParams &Params, 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 Error writeV5Entry(raw_ostream &OS, uint64_t Count, ArrayRef< DWARFYAML::LnctForm > Format, ArrayRef< std::vector< DWARFYAML::FormValue > > EntryList, const dwarf::FormParams &Params, bool IsLittleEndian)
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 F(x, y, z)
Definition MD5.cpp:54
#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
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
Definition STLExtras.h:366
@ 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:272
std::vector< LineTable > DebugLines
Definition DWARFYAML.h:274
std::optional< std::vector< AddrTableEntry > > DebugAddr
Definition DWARFYAML.h:265
std::optional< std::vector< Ranges > > DebugRanges
Definition DWARFYAML.h:264
std::optional< std::vector< ListTable< LoclistEntry > > > DebugLoclists
Definition DWARFYAML.h:276
std::vector< AbbrevTable > DebugAbbrev
Definition DWARFYAML.h:260
LLVM_ABI Expected< AbbrevTableInfo > getAbbrevTableInfoByID(uint64_t ID) const
Definition DWARFYAML.cpp:61
std::optional< PubSection > GNUPubNames
Definition DWARFYAML.h:269
std::optional< std::vector< ARange > > DebugAranges
Definition DWARFYAML.h:263
LLVM_ABI StringRef getAbbrevTableContentByIndex(uint64_t Index) const
std::optional< PubSection > GNUPubTypes
Definition DWARFYAML.h:270
LLVM_ABI SetVector< StringRef > getNonEmptySectionNames() const
Definition DWARFYAML.cpp:25
std::optional< std::vector< StringOffsetsTable > > DebugStrOffsets
Definition DWARFYAML.h:262
std::optional< std::vector< StringRef > > DebugStrings
Definition DWARFYAML.h:261
std::optional< std::vector< ListTable< RnglistEntry > > > DebugRnglists
Definition DWARFYAML.h:275
std::optional< PubSection > PubNames
Definition DWARFYAML.h:266
std::optional< DebugNamesSection > DebugNames
Definition DWARFYAML.h:277
std::optional< PubSection > PubTypes
Definition DWARFYAML.h:267
std::vector< FormValue > Values
Definition DWARFYAML.h:102
std::vector< llvm::yaml::Hex8 > BlockData
Definition DWARFYAML.h:97
llvm::yaml::Hex64 Value
Definition DWARFYAML.h:95
std::vector< std::vector< FormValue > > FileNames
Definition DWARFYAML.h:197
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:199
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:195
std::optional< std::vector< uint8_t > > StandardOpcodeLengths
Definition DWARFYAML.h:183
std::vector< std::vector< FormValue > > Directories
Definition DWARFYAML.h:193
dwarf::DwarfFormat Format
Definition DWARFYAML.h:86
std::vector< PubEntry > Entries
Definition DWARFYAML.h:91
std::optional< yaml::Hex64 > Length
Definition DWARFYAML.h:218
std::vector< yaml::Hex64 > Offsets
Definition DWARFYAML.h:221
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