1 //===- DWARFEmitter - Convert YAML to DWARF binary data -------------------===//
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
7 //===----------------------------------------------------------------------===//
10 /// The DWARF component of yaml2obj. Provided as library code for tests.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/ObjectYAML/DWARFEmitter.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/StringMap.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/ADT/StringSwitch.h"
19 #include "llvm/BinaryFormat/Dwarf.h"
20 #include "llvm/ObjectYAML/DWARFYAML.h"
21 #include "llvm/Support/Errc.h"
22 #include "llvm/Support/Error.h"
23 #include "llvm/Support/LEB128.h"
24 #include "llvm/Support/MathExtras.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/SourceMgr.h"
27 #include "llvm/Support/SwapByteOrder.h"
28 #include "llvm/Support/YAMLTraits.h"
29 #include "llvm/Support/raw_ostream.h"
30 #include "llvm/TargetParser/Host.h"
43 static void writeInteger(T Integer
, raw_ostream
&OS
, bool IsLittleEndian
) {
44 if (IsLittleEndian
!= sys::IsLittleEndianHost
)
45 sys::swapByteOrder(Integer
);
46 OS
.write(reinterpret_cast<char *>(&Integer
), sizeof(T
));
49 static Error
writeVariableSizedInteger(uint64_t Integer
, size_t Size
,
50 raw_ostream
&OS
, bool IsLittleEndian
) {
52 writeInteger((uint64_t)Integer
, OS
, IsLittleEndian
);
54 writeInteger((uint32_t)Integer
, OS
, IsLittleEndian
);
56 writeInteger((uint16_t)Integer
, OS
, IsLittleEndian
);
58 writeInteger((uint8_t)Integer
, OS
, IsLittleEndian
);
60 return createStringError(errc::not_supported
,
61 "invalid integer write size: %zu", Size
);
63 return Error::success();
66 static void ZeroFillBytes(raw_ostream
&OS
, size_t Size
) {
67 std::vector
<uint8_t> FillData(Size
, 0);
68 OS
.write(reinterpret_cast<char *>(FillData
.data()), Size
);
71 static void writeInitialLength(const dwarf::DwarfFormat Format
,
72 const uint64_t Length
, raw_ostream
&OS
,
73 bool IsLittleEndian
) {
74 bool IsDWARF64
= Format
== dwarf::DWARF64
;
76 cantFail(writeVariableSizedInteger(dwarf::DW_LENGTH_DWARF64
, 4, OS
,
79 writeVariableSizedInteger(Length
, IsDWARF64
? 8 : 4, OS
, IsLittleEndian
));
82 static void writeDWARFOffset(uint64_t Offset
, dwarf::DwarfFormat Format
,
83 raw_ostream
&OS
, bool IsLittleEndian
) {
84 cantFail(writeVariableSizedInteger(Offset
, Format
== dwarf::DWARF64
? 8 : 4,
88 Error
DWARFYAML::emitDebugStr(raw_ostream
&OS
, const DWARFYAML::Data
&DI
) {
89 for (StringRef Str
: *DI
.DebugStrings
) {
90 OS
.write(Str
.data(), Str
.size());
94 return Error::success();
97 StringRef
DWARFYAML::Data::getAbbrevTableContentByIndex(uint64_t Index
) const {
98 assert(Index
< DebugAbbrev
.size() &&
99 "Index should be less than the size of DebugAbbrev array");
100 auto It
= AbbrevTableContents
.find(Index
);
101 if (It
!= AbbrevTableContents
.cend())
104 std::string AbbrevTableBuffer
;
105 raw_string_ostream
OS(AbbrevTableBuffer
);
107 uint64_t AbbrevCode
= 0;
108 for (const DWARFYAML::Abbrev
&AbbrevDecl
: DebugAbbrev
[Index
].Table
) {
109 AbbrevCode
= AbbrevDecl
.Code
? (uint64_t)*AbbrevDecl
.Code
: AbbrevCode
+ 1;
110 encodeULEB128(AbbrevCode
, OS
);
111 encodeULEB128(AbbrevDecl
.Tag
, OS
);
112 OS
.write(AbbrevDecl
.Children
);
113 for (const auto &Attr
: AbbrevDecl
.Attributes
) {
114 encodeULEB128(Attr
.Attribute
, OS
);
115 encodeULEB128(Attr
.Form
, OS
);
116 if (Attr
.Form
== dwarf::DW_FORM_implicit_const
)
117 encodeSLEB128(Attr
.Value
, OS
);
119 encodeULEB128(0, OS
);
120 encodeULEB128(0, OS
);
123 // The abbreviations for a given compilation unit end with an entry
124 // consisting of a 0 byte for the abbreviation code.
127 AbbrevTableContents
.insert({Index
, AbbrevTableBuffer
});
129 return AbbrevTableContents
[Index
];
132 Error
DWARFYAML::emitDebugAbbrev(raw_ostream
&OS
, const DWARFYAML::Data
&DI
) {
133 for (uint64_t I
= 0; I
< DI
.DebugAbbrev
.size(); ++I
) {
134 StringRef AbbrevTableContent
= DI
.getAbbrevTableContentByIndex(I
);
135 OS
.write(AbbrevTableContent
.data(), AbbrevTableContent
.size());
138 return Error::success();
141 Error
DWARFYAML::emitDebugAranges(raw_ostream
&OS
, const DWARFYAML::Data
&DI
) {
142 assert(DI
.DebugAranges
&& "unexpected emitDebugAranges() call");
143 for (const auto &Range
: *DI
.DebugAranges
) {
146 AddrSize
= *Range
.AddrSize
;
148 AddrSize
= DI
.Is64BitAddrSize
? 8 : 4;
150 uint64_t Length
= 4; // sizeof(version) 2 + sizeof(address_size) 1 +
151 // sizeof(segment_selector_size) 1
153 Range
.Format
== dwarf::DWARF64
? 8 : 4; // sizeof(debug_info_offset)
155 const uint64_t HeaderLength
=
156 Length
+ (Range
.Format
== dwarf::DWARF64
158 : 4); // sizeof(unit_header) = 12 (DWARF64) or 4 (DWARF32)
159 const uint64_t PaddedHeaderLength
= alignTo(HeaderLength
, AddrSize
* 2);
162 Length
= *Range
.Length
;
164 Length
+= PaddedHeaderLength
- HeaderLength
;
165 Length
+= AddrSize
* 2 * (Range
.Descriptors
.size() + 1);
168 writeInitialLength(Range
.Format
, Length
, OS
, DI
.IsLittleEndian
);
169 writeInteger((uint16_t)Range
.Version
, OS
, DI
.IsLittleEndian
);
170 writeDWARFOffset(Range
.CuOffset
, Range
.Format
, OS
, DI
.IsLittleEndian
);
171 writeInteger((uint8_t)AddrSize
, OS
, DI
.IsLittleEndian
);
172 writeInteger((uint8_t)Range
.SegSize
, OS
, DI
.IsLittleEndian
);
173 ZeroFillBytes(OS
, PaddedHeaderLength
- HeaderLength
);
175 for (const auto &Descriptor
: Range
.Descriptors
) {
176 if (Error Err
= writeVariableSizedInteger(Descriptor
.Address
, AddrSize
,
177 OS
, DI
.IsLittleEndian
))
178 return createStringError(errc::not_supported
,
179 "unable to write debug_aranges address: %s",
180 toString(std::move(Err
)).c_str());
181 cantFail(writeVariableSizedInteger(Descriptor
.Length
, AddrSize
, OS
,
184 ZeroFillBytes(OS
, AddrSize
* 2);
187 return Error::success();
190 Error
DWARFYAML::emitDebugRanges(raw_ostream
&OS
, const DWARFYAML::Data
&DI
) {
191 const size_t RangesOffset
= OS
.tell();
192 uint64_t EntryIndex
= 0;
193 for (const auto &DebugRanges
: *DI
.DebugRanges
) {
194 const size_t CurrOffset
= OS
.tell() - RangesOffset
;
195 if (DebugRanges
.Offset
&& (uint64_t)*DebugRanges
.Offset
< CurrOffset
)
196 return createStringError(errc::invalid_argument
,
197 "'Offset' for 'debug_ranges' with index " +
199 " must be greater than or equal to the "
200 "number of bytes written already (0x" +
201 Twine::utohexstr(CurrOffset
) + ")");
202 if (DebugRanges
.Offset
)
203 ZeroFillBytes(OS
, *DebugRanges
.Offset
- CurrOffset
);
206 if (DebugRanges
.AddrSize
)
207 AddrSize
= *DebugRanges
.AddrSize
;
209 AddrSize
= DI
.Is64BitAddrSize
? 8 : 4;
210 for (const auto &Entry
: DebugRanges
.Entries
) {
211 if (Error Err
= writeVariableSizedInteger(Entry
.LowOffset
, AddrSize
, OS
,
213 return createStringError(
215 "unable to write debug_ranges address offset: %s",
216 toString(std::move(Err
)).c_str());
217 cantFail(writeVariableSizedInteger(Entry
.HighOffset
, AddrSize
, OS
,
220 ZeroFillBytes(OS
, AddrSize
* 2);
224 return Error::success();
227 static Error
emitPubSection(raw_ostream
&OS
, const DWARFYAML::PubSection
&Sect
,
228 bool IsLittleEndian
, bool IsGNUPubSec
= false) {
229 writeInitialLength(Sect
.Format
, Sect
.Length
, OS
, IsLittleEndian
);
230 writeInteger((uint16_t)Sect
.Version
, OS
, IsLittleEndian
);
231 writeInteger((uint32_t)Sect
.UnitOffset
, OS
, IsLittleEndian
);
232 writeInteger((uint32_t)Sect
.UnitSize
, OS
, IsLittleEndian
);
233 for (const auto &Entry
: Sect
.Entries
) {
234 writeInteger((uint32_t)Entry
.DieOffset
, OS
, IsLittleEndian
);
236 writeInteger((uint8_t)Entry
.Descriptor
, OS
, IsLittleEndian
);
237 OS
.write(Entry
.Name
.data(), Entry
.Name
.size());
240 return Error::success();
243 Error
DWARFYAML::emitDebugPubnames(raw_ostream
&OS
, const Data
&DI
) {
244 assert(DI
.PubNames
&& "unexpected emitDebugPubnames() call");
245 return emitPubSection(OS
, *DI
.PubNames
, DI
.IsLittleEndian
);
248 Error
DWARFYAML::emitDebugPubtypes(raw_ostream
&OS
, const Data
&DI
) {
249 assert(DI
.PubTypes
&& "unexpected emitDebugPubtypes() call");
250 return emitPubSection(OS
, *DI
.PubTypes
, DI
.IsLittleEndian
);
253 Error
DWARFYAML::emitDebugGNUPubnames(raw_ostream
&OS
, const Data
&DI
) {
254 assert(DI
.GNUPubNames
&& "unexpected emitDebugGNUPubnames() call");
255 return emitPubSection(OS
, *DI
.GNUPubNames
, DI
.IsLittleEndian
,
256 /*IsGNUStyle=*/true);
259 Error
DWARFYAML::emitDebugGNUPubtypes(raw_ostream
&OS
, const Data
&DI
) {
260 assert(DI
.GNUPubTypes
&& "unexpected emitDebugGNUPubtypes() call");
261 return emitPubSection(OS
, *DI
.GNUPubTypes
, DI
.IsLittleEndian
,
262 /*IsGNUStyle=*/true);
265 static Expected
<uint64_t> writeDIE(const DWARFYAML::Data
&DI
, uint64_t CUIndex
,
266 uint64_t AbbrevTableID
,
267 const dwarf::FormParams
&Params
,
268 const DWARFYAML::Entry
&Entry
,
269 raw_ostream
&OS
, bool IsLittleEndian
) {
270 uint64_t EntryBegin
= OS
.tell();
271 encodeULEB128(Entry
.AbbrCode
, OS
);
272 uint32_t AbbrCode
= Entry
.AbbrCode
;
273 if (AbbrCode
== 0 || Entry
.Values
.empty())
274 return OS
.tell() - EntryBegin
;
276 Expected
<DWARFYAML::Data::AbbrevTableInfo
> AbbrevTableInfoOrErr
=
277 DI
.getAbbrevTableInfoByID(AbbrevTableID
);
278 if (!AbbrevTableInfoOrErr
)
279 return createStringError(errc::invalid_argument
,
280 toString(AbbrevTableInfoOrErr
.takeError()) +
281 " for compilation unit with index " +
284 ArrayRef
<DWARFYAML::Abbrev
> AbbrevDecls(
285 DI
.DebugAbbrev
[AbbrevTableInfoOrErr
->Index
].Table
);
287 if (AbbrCode
> AbbrevDecls
.size())
288 return createStringError(
289 errc::invalid_argument
,
290 "abbrev code must be less than or equal to the number of "
291 "entries in abbreviation table");
292 const DWARFYAML::Abbrev
&Abbrev
= AbbrevDecls
[AbbrCode
- 1];
293 auto FormVal
= Entry
.Values
.begin();
294 auto AbbrForm
= Abbrev
.Attributes
.begin();
295 for (; FormVal
!= Entry
.Values
.end() && AbbrForm
!= Abbrev
.Attributes
.end();
296 ++FormVal
, ++AbbrForm
) {
297 dwarf::Form Form
= AbbrForm
->Form
;
302 case dwarf::DW_FORM_addr
:
303 // TODO: Test this error.
304 if (Error Err
= writeVariableSizedInteger(
305 FormVal
->Value
, Params
.AddrSize
, OS
, IsLittleEndian
))
306 return std::move(Err
);
308 case dwarf::DW_FORM_ref_addr
:
309 // TODO: Test this error.
310 if (Error Err
= writeVariableSizedInteger(FormVal
->Value
,
311 Params
.getRefAddrByteSize(),
313 return std::move(Err
);
315 case dwarf::DW_FORM_exprloc
:
316 case dwarf::DW_FORM_block
:
317 encodeULEB128(FormVal
->BlockData
.size(), OS
);
318 OS
.write((const char *)FormVal
->BlockData
.data(),
319 FormVal
->BlockData
.size());
321 case dwarf::DW_FORM_block1
: {
322 writeInteger((uint8_t)FormVal
->BlockData
.size(), OS
, IsLittleEndian
);
323 OS
.write((const char *)FormVal
->BlockData
.data(),
324 FormVal
->BlockData
.size());
327 case dwarf::DW_FORM_block2
: {
328 writeInteger((uint16_t)FormVal
->BlockData
.size(), OS
, IsLittleEndian
);
329 OS
.write((const char *)FormVal
->BlockData
.data(),
330 FormVal
->BlockData
.size());
333 case dwarf::DW_FORM_block4
: {
334 writeInteger((uint32_t)FormVal
->BlockData
.size(), OS
, IsLittleEndian
);
335 OS
.write((const char *)FormVal
->BlockData
.data(),
336 FormVal
->BlockData
.size());
339 case dwarf::DW_FORM_strx
:
340 case dwarf::DW_FORM_addrx
:
341 case dwarf::DW_FORM_rnglistx
:
342 case dwarf::DW_FORM_loclistx
:
343 case dwarf::DW_FORM_udata
:
344 case dwarf::DW_FORM_ref_udata
:
345 case dwarf::DW_FORM_GNU_addr_index
:
346 case dwarf::DW_FORM_GNU_str_index
:
347 encodeULEB128(FormVal
->Value
, OS
);
349 case dwarf::DW_FORM_data1
:
350 case dwarf::DW_FORM_ref1
:
351 case dwarf::DW_FORM_flag
:
352 case dwarf::DW_FORM_strx1
:
353 case dwarf::DW_FORM_addrx1
:
354 writeInteger((uint8_t)FormVal
->Value
, OS
, IsLittleEndian
);
356 case dwarf::DW_FORM_data2
:
357 case dwarf::DW_FORM_ref2
:
358 case dwarf::DW_FORM_strx2
:
359 case dwarf::DW_FORM_addrx2
:
360 writeInteger((uint16_t)FormVal
->Value
, OS
, IsLittleEndian
);
362 case dwarf::DW_FORM_data4
:
363 case dwarf::DW_FORM_ref4
:
364 case dwarf::DW_FORM_ref_sup4
:
365 case dwarf::DW_FORM_strx4
:
366 case dwarf::DW_FORM_addrx4
:
367 writeInteger((uint32_t)FormVal
->Value
, OS
, IsLittleEndian
);
369 case dwarf::DW_FORM_data8
:
370 case dwarf::DW_FORM_ref8
:
371 case dwarf::DW_FORM_ref_sup8
:
372 case dwarf::DW_FORM_ref_sig8
:
373 writeInteger((uint64_t)FormVal
->Value
, OS
, IsLittleEndian
);
375 case dwarf::DW_FORM_sdata
:
376 encodeSLEB128(FormVal
->Value
, OS
);
378 case dwarf::DW_FORM_string
:
379 OS
.write(FormVal
->CStr
.data(), FormVal
->CStr
.size());
382 case dwarf::DW_FORM_indirect
:
383 encodeULEB128(FormVal
->Value
, OS
);
385 Form
= static_cast<dwarf::Form
>((uint64_t)FormVal
->Value
);
388 case dwarf::DW_FORM_strp
:
389 case dwarf::DW_FORM_sec_offset
:
390 case dwarf::DW_FORM_GNU_ref_alt
:
391 case dwarf::DW_FORM_GNU_strp_alt
:
392 case dwarf::DW_FORM_line_strp
:
393 case dwarf::DW_FORM_strp_sup
:
394 cantFail(writeVariableSizedInteger(FormVal
->Value
,
395 Params
.getDwarfOffsetByteSize(), OS
,
404 return OS
.tell() - EntryBegin
;
407 Error
DWARFYAML::emitDebugInfo(raw_ostream
&OS
, const DWARFYAML::Data
&DI
) {
408 for (uint64_t I
= 0; I
< DI
.CompileUnits
.size(); ++I
) {
409 const DWARFYAML::Unit
&Unit
= DI
.CompileUnits
[I
];
412 AddrSize
= *Unit
.AddrSize
;
414 AddrSize
= DI
.Is64BitAddrSize
? 8 : 4;
415 dwarf::FormParams Params
= {Unit
.Version
, AddrSize
, Unit
.Format
};
416 uint64_t Length
= 3; // sizeof(version) + sizeof(address_size)
417 Length
+= Unit
.Version
>= 5 ? 1 : 0; // sizeof(unit_type)
418 Length
+= Params
.getDwarfOffsetByteSize(); // sizeof(debug_abbrev_offset)
420 // Since the length of the current compilation unit is undetermined yet, we
421 // firstly write the content of the compilation unit to a buffer to
422 // calculate it and then serialize the buffer content to the actual output
424 std::string EntryBuffer
;
425 raw_string_ostream
EntryBufferOS(EntryBuffer
);
427 uint64_t AbbrevTableID
= Unit
.AbbrevTableID
.value_or(I
);
428 for (const DWARFYAML::Entry
&Entry
: Unit
.Entries
) {
429 if (Expected
<uint64_t> EntryLength
=
430 writeDIE(DI
, I
, AbbrevTableID
, Params
, Entry
, EntryBufferOS
,
432 Length
+= *EntryLength
;
434 return EntryLength
.takeError();
437 // If the length is specified in the YAML description, we use it instead of
438 // the actual length.
440 Length
= *Unit
.Length
;
442 writeInitialLength(Unit
.Format
, Length
, OS
, DI
.IsLittleEndian
);
443 writeInteger((uint16_t)Unit
.Version
, OS
, DI
.IsLittleEndian
);
445 uint64_t AbbrevTableOffset
= 0;
446 if (Unit
.AbbrOffset
) {
447 AbbrevTableOffset
= *Unit
.AbbrOffset
;
449 if (Expected
<DWARFYAML::Data::AbbrevTableInfo
> AbbrevTableInfoOrErr
=
450 DI
.getAbbrevTableInfoByID(AbbrevTableID
)) {
451 AbbrevTableOffset
= AbbrevTableInfoOrErr
->Offset
;
453 // The current compilation unit may not have DIEs and it will not be
454 // able to find the associated abbrev table. We consume the error and
455 // assign 0 to the debug_abbrev_offset in such circumstances.
456 consumeError(AbbrevTableInfoOrErr
.takeError());
460 if (Unit
.Version
>= 5) {
461 writeInteger((uint8_t)Unit
.Type
, OS
, DI
.IsLittleEndian
);
462 writeInteger((uint8_t)AddrSize
, OS
, DI
.IsLittleEndian
);
463 writeDWARFOffset(AbbrevTableOffset
, Unit
.Format
, OS
, DI
.IsLittleEndian
);
465 writeDWARFOffset(AbbrevTableOffset
, Unit
.Format
, OS
, DI
.IsLittleEndian
);
466 writeInteger((uint8_t)AddrSize
, OS
, DI
.IsLittleEndian
);
469 OS
.write(EntryBuffer
.data(), EntryBuffer
.size());
472 return Error::success();
475 static void emitFileEntry(raw_ostream
&OS
, const DWARFYAML::File
&File
) {
476 OS
.write(File
.Name
.data(), File
.Name
.size());
478 encodeULEB128(File
.DirIdx
, OS
);
479 encodeULEB128(File
.ModTime
, OS
);
480 encodeULEB128(File
.Length
, OS
);
483 static void writeExtendedOpcode(const DWARFYAML::LineTableOpcode
&Op
,
484 uint8_t AddrSize
, bool IsLittleEndian
,
486 // The first byte of extended opcodes is a zero byte. The next bytes are an
487 // ULEB128 integer giving the number of bytes in the instruction itself (does
488 // not include the first zero byte or the size). We serialize the instruction
489 // itself into the OpBuffer and then write the size of the buffer and the
490 // buffer to the real output stream.
491 std::string OpBuffer
;
492 raw_string_ostream
OpBufferOS(OpBuffer
);
493 writeInteger((uint8_t)Op
.SubOpcode
, OpBufferOS
, IsLittleEndian
);
494 switch (Op
.SubOpcode
) {
495 case dwarf::DW_LNE_set_address
:
496 cantFail(writeVariableSizedInteger(Op
.Data
, AddrSize
, OpBufferOS
,
499 case dwarf::DW_LNE_define_file
:
500 emitFileEntry(OpBufferOS
, Op
.FileEntry
);
502 case dwarf::DW_LNE_set_discriminator
:
503 encodeULEB128(Op
.Data
, OpBufferOS
);
505 case dwarf::DW_LNE_end_sequence
:
508 for (auto OpByte
: Op
.UnknownOpcodeData
)
509 writeInteger((uint8_t)OpByte
, OpBufferOS
, IsLittleEndian
);
511 uint64_t ExtLen
= Op
.ExtLen
.value_or(OpBuffer
.size());
512 encodeULEB128(ExtLen
, OS
);
513 OS
.write(OpBuffer
.data(), OpBuffer
.size());
516 static void writeLineTableOpcode(const DWARFYAML::LineTableOpcode
&Op
,
517 uint8_t OpcodeBase
, uint8_t AddrSize
,
518 raw_ostream
&OS
, bool IsLittleEndian
) {
519 writeInteger((uint8_t)Op
.Opcode
, OS
, IsLittleEndian
);
520 if (Op
.Opcode
== 0) {
521 writeExtendedOpcode(Op
, AddrSize
, IsLittleEndian
, OS
);
522 } else if (Op
.Opcode
< OpcodeBase
) {
524 case dwarf::DW_LNS_copy
:
525 case dwarf::DW_LNS_negate_stmt
:
526 case dwarf::DW_LNS_set_basic_block
:
527 case dwarf::DW_LNS_const_add_pc
:
528 case dwarf::DW_LNS_set_prologue_end
:
529 case dwarf::DW_LNS_set_epilogue_begin
:
532 case dwarf::DW_LNS_advance_pc
:
533 case dwarf::DW_LNS_set_file
:
534 case dwarf::DW_LNS_set_column
:
535 case dwarf::DW_LNS_set_isa
:
536 encodeULEB128(Op
.Data
, OS
);
539 case dwarf::DW_LNS_advance_line
:
540 encodeSLEB128(Op
.SData
, OS
);
543 case dwarf::DW_LNS_fixed_advance_pc
:
544 writeInteger((uint16_t)Op
.Data
, OS
, IsLittleEndian
);
548 for (auto OpData
: Op
.StandardOpcodeData
) {
549 encodeULEB128(OpData
, OS
);
555 static std::vector
<uint8_t>
556 getStandardOpcodeLengths(uint16_t Version
, std::optional
<uint8_t> OpcodeBase
) {
557 // If the opcode_base field isn't specified, we returns the
558 // standard_opcode_lengths array according to the version by default.
559 std::vector
<uint8_t> StandardOpcodeLengths
{0, 1, 1, 1, 1, 0,
562 // DWARF v2 uses the same first 9 standard opcodes as v3-5.
563 StandardOpcodeLengths
.resize(9);
564 } else if (OpcodeBase
) {
565 StandardOpcodeLengths
.resize(*OpcodeBase
> 0 ? *OpcodeBase
- 1 : 0, 0);
567 return StandardOpcodeLengths
;
570 Error
DWARFYAML::emitDebugLine(raw_ostream
&OS
, const DWARFYAML::Data
&DI
) {
571 for (const DWARFYAML::LineTable
&LineTable
: DI
.DebugLines
) {
572 // Buffer holds the bytes following the header_length (or prologue_length in
573 // DWARFv2) field to the end of the line number program itself.
575 raw_string_ostream
BufferOS(Buffer
);
577 writeInteger(LineTable
.MinInstLength
, BufferOS
, DI
.IsLittleEndian
);
578 // TODO: Add support for emitting DWARFv5 line table.
579 if (LineTable
.Version
>= 4)
580 writeInteger(LineTable
.MaxOpsPerInst
, BufferOS
, DI
.IsLittleEndian
);
581 writeInteger(LineTable
.DefaultIsStmt
, BufferOS
, DI
.IsLittleEndian
);
582 writeInteger(LineTable
.LineBase
, BufferOS
, DI
.IsLittleEndian
);
583 writeInteger(LineTable
.LineRange
, BufferOS
, DI
.IsLittleEndian
);
585 std::vector
<uint8_t> StandardOpcodeLengths
=
586 LineTable
.StandardOpcodeLengths
.value_or(
587 getStandardOpcodeLengths(LineTable
.Version
, LineTable
.OpcodeBase
));
588 uint8_t OpcodeBase
= LineTable
.OpcodeBase
589 ? *LineTable
.OpcodeBase
590 : StandardOpcodeLengths
.size() + 1;
591 writeInteger(OpcodeBase
, BufferOS
, DI
.IsLittleEndian
);
592 for (uint8_t OpcodeLength
: StandardOpcodeLengths
)
593 writeInteger(OpcodeLength
, BufferOS
, DI
.IsLittleEndian
);
595 for (StringRef IncludeDir
: LineTable
.IncludeDirs
) {
596 BufferOS
.write(IncludeDir
.data(), IncludeDir
.size());
597 BufferOS
.write('\0');
599 BufferOS
.write('\0');
601 for (const DWARFYAML::File
&File
: LineTable
.Files
)
602 emitFileEntry(BufferOS
, File
);
603 BufferOS
.write('\0');
605 uint64_t HeaderLength
=
606 LineTable
.PrologueLength
? *LineTable
.PrologueLength
: Buffer
.size();
608 for (const DWARFYAML::LineTableOpcode
&Op
: LineTable
.Opcodes
)
609 writeLineTableOpcode(Op
, OpcodeBase
, DI
.Is64BitAddrSize
? 8 : 4, BufferOS
,
613 if (LineTable
.Length
) {
614 Length
= *LineTable
.Length
;
616 Length
= 2; // sizeof(version)
618 (LineTable
.Format
== dwarf::DWARF64
? 8 : 4); // sizeof(header_length)
619 Length
+= Buffer
.size();
622 writeInitialLength(LineTable
.Format
, Length
, OS
, DI
.IsLittleEndian
);
623 writeInteger(LineTable
.Version
, OS
, DI
.IsLittleEndian
);
624 writeDWARFOffset(HeaderLength
, LineTable
.Format
, OS
, DI
.IsLittleEndian
);
625 OS
.write(Buffer
.data(), Buffer
.size());
628 return Error::success();
631 Error
DWARFYAML::emitDebugAddr(raw_ostream
&OS
, const Data
&DI
) {
632 for (const AddrTableEntry
&TableEntry
: *DI
.DebugAddr
) {
634 if (TableEntry
.AddrSize
)
635 AddrSize
= *TableEntry
.AddrSize
;
637 AddrSize
= DI
.Is64BitAddrSize
? 8 : 4;
640 if (TableEntry
.Length
)
641 Length
= (uint64_t)*TableEntry
.Length
;
643 // 2 (version) + 1 (address_size) + 1 (segment_selector_size) = 4
644 Length
= 4 + (AddrSize
+ TableEntry
.SegSelectorSize
) *
645 TableEntry
.SegAddrPairs
.size();
647 writeInitialLength(TableEntry
.Format
, Length
, OS
, DI
.IsLittleEndian
);
648 writeInteger((uint16_t)TableEntry
.Version
, OS
, DI
.IsLittleEndian
);
649 writeInteger((uint8_t)AddrSize
, OS
, DI
.IsLittleEndian
);
650 writeInteger((uint8_t)TableEntry
.SegSelectorSize
, OS
, DI
.IsLittleEndian
);
652 for (const SegAddrPair
&Pair
: TableEntry
.SegAddrPairs
) {
653 if (TableEntry
.SegSelectorSize
!= yaml::Hex8
{0})
654 if (Error Err
= writeVariableSizedInteger(Pair
.Segment
,
655 TableEntry
.SegSelectorSize
,
656 OS
, DI
.IsLittleEndian
))
657 return createStringError(errc::not_supported
,
658 "unable to write debug_addr segment: %s",
659 toString(std::move(Err
)).c_str());
661 if (Error Err
= writeVariableSizedInteger(Pair
.Address
, AddrSize
, OS
,
663 return createStringError(errc::not_supported
,
664 "unable to write debug_addr address: %s",
665 toString(std::move(Err
)).c_str());
669 return Error::success();
672 Error
DWARFYAML::emitDebugStrOffsets(raw_ostream
&OS
, const Data
&DI
) {
673 assert(DI
.DebugStrOffsets
&& "unexpected emitDebugStrOffsets() call");
674 for (const DWARFYAML::StringOffsetsTable
&Table
: *DI
.DebugStrOffsets
) {
677 Length
= *Table
.Length
;
679 // sizeof(version) + sizeof(padding) = 4
681 4 + Table
.Offsets
.size() * (Table
.Format
== dwarf::DWARF64
? 8 : 4);
683 writeInitialLength(Table
.Format
, Length
, OS
, DI
.IsLittleEndian
);
684 writeInteger((uint16_t)Table
.Version
, OS
, DI
.IsLittleEndian
);
685 writeInteger((uint16_t)Table
.Padding
, OS
, DI
.IsLittleEndian
);
687 for (uint64_t Offset
: Table
.Offsets
)
688 writeDWARFOffset(Offset
, Table
.Format
, OS
, DI
.IsLittleEndian
);
691 return Error::success();
694 static Error
checkOperandCount(StringRef EncodingString
,
695 ArrayRef
<yaml::Hex64
> Values
,
696 uint64_t ExpectedOperands
) {
697 if (Values
.size() != ExpectedOperands
)
698 return createStringError(
699 errc::invalid_argument
,
700 "invalid number (%zu) of operands for the operator: %s, %" PRIu64
702 Values
.size(), EncodingString
.str().c_str(), ExpectedOperands
);
704 return Error::success();
707 static Error
writeListEntryAddress(StringRef EncodingName
, raw_ostream
&OS
,
708 uint64_t Addr
, uint8_t AddrSize
,
709 bool IsLittleEndian
) {
710 if (Error Err
= writeVariableSizedInteger(Addr
, AddrSize
, OS
, IsLittleEndian
))
711 return createStringError(errc::invalid_argument
,
712 "unable to write address for the operator %s: %s",
713 EncodingName
.str().c_str(),
714 toString(std::move(Err
)).c_str());
716 return Error::success();
719 static Expected
<uint64_t>
720 writeDWARFExpression(raw_ostream
&OS
,
721 const DWARFYAML::DWARFOperation
&Operation
,
722 uint8_t AddrSize
, bool IsLittleEndian
) {
723 auto CheckOperands
= [&](uint64_t ExpectedOperands
) -> Error
{
724 return checkOperandCount(dwarf::OperationEncodingString(Operation
.Operator
),
725 Operation
.Values
, ExpectedOperands
);
728 uint64_t ExpressionBegin
= OS
.tell();
729 writeInteger((uint8_t)Operation
.Operator
, OS
, IsLittleEndian
);
730 switch (Operation
.Operator
) {
731 case dwarf::DW_OP_consts
:
732 if (Error Err
= CheckOperands(1))
733 return std::move(Err
);
734 encodeSLEB128(Operation
.Values
[0], OS
);
736 case dwarf::DW_OP_stack_value
:
737 if (Error Err
= CheckOperands(0))
738 return std::move(Err
);
741 StringRef EncodingStr
= dwarf::OperationEncodingString(Operation
.Operator
);
742 return createStringError(errc::not_supported
,
743 "DWARF expression: " +
745 ? "0x" + utohexstr(Operation
.Operator
)
747 " is not supported");
749 return OS
.tell() - ExpressionBegin
;
752 static Expected
<uint64_t> writeListEntry(raw_ostream
&OS
,
753 const DWARFYAML::RnglistEntry
&Entry
,
755 bool IsLittleEndian
) {
756 uint64_t BeginOffset
= OS
.tell();
757 writeInteger((uint8_t)Entry
.Operator
, OS
, IsLittleEndian
);
759 StringRef EncodingName
= dwarf::RangeListEncodingString(Entry
.Operator
);
761 auto CheckOperands
= [&](uint64_t ExpectedOperands
) -> Error
{
762 return checkOperandCount(EncodingName
, Entry
.Values
, ExpectedOperands
);
765 auto WriteAddress
= [&](uint64_t Addr
) -> Error
{
766 return writeListEntryAddress(EncodingName
, OS
, Addr
, AddrSize
,
770 switch (Entry
.Operator
) {
771 case dwarf::DW_RLE_end_of_list
:
772 if (Error Err
= CheckOperands(0))
773 return std::move(Err
);
775 case dwarf::DW_RLE_base_addressx
:
776 if (Error Err
= CheckOperands(1))
777 return std::move(Err
);
778 encodeULEB128(Entry
.Values
[0], OS
);
780 case dwarf::DW_RLE_startx_endx
:
781 case dwarf::DW_RLE_startx_length
:
782 case dwarf::DW_RLE_offset_pair
:
783 if (Error Err
= CheckOperands(2))
784 return std::move(Err
);
785 encodeULEB128(Entry
.Values
[0], OS
);
786 encodeULEB128(Entry
.Values
[1], OS
);
788 case dwarf::DW_RLE_base_address
:
789 if (Error Err
= CheckOperands(1))
790 return std::move(Err
);
791 if (Error Err
= WriteAddress(Entry
.Values
[0]))
792 return std::move(Err
);
794 case dwarf::DW_RLE_start_end
:
795 if (Error Err
= CheckOperands(2))
796 return std::move(Err
);
797 if (Error Err
= WriteAddress(Entry
.Values
[0]))
798 return std::move(Err
);
799 cantFail(WriteAddress(Entry
.Values
[1]));
801 case dwarf::DW_RLE_start_length
:
802 if (Error Err
= CheckOperands(2))
803 return std::move(Err
);
804 if (Error Err
= WriteAddress(Entry
.Values
[0]))
805 return std::move(Err
);
806 encodeULEB128(Entry
.Values
[1], OS
);
810 return OS
.tell() - BeginOffset
;
813 static Expected
<uint64_t> writeListEntry(raw_ostream
&OS
,
814 const DWARFYAML::LoclistEntry
&Entry
,
816 bool IsLittleEndian
) {
817 uint64_t BeginOffset
= OS
.tell();
818 writeInteger((uint8_t)Entry
.Operator
, OS
, IsLittleEndian
);
820 StringRef EncodingName
= dwarf::LocListEncodingString(Entry
.Operator
);
822 auto CheckOperands
= [&](uint64_t ExpectedOperands
) -> Error
{
823 return checkOperandCount(EncodingName
, Entry
.Values
, ExpectedOperands
);
826 auto WriteAddress
= [&](uint64_t Addr
) -> Error
{
827 return writeListEntryAddress(EncodingName
, OS
, Addr
, AddrSize
,
831 auto WriteDWARFOperations
= [&]() -> Error
{
832 std::string OpBuffer
;
833 raw_string_ostream
OpBufferOS(OpBuffer
);
834 uint64_t DescriptionsLength
= 0;
836 for (const DWARFYAML::DWARFOperation
&Op
: Entry
.Descriptions
) {
837 if (Expected
<uint64_t> OpSize
=
838 writeDWARFExpression(OpBufferOS
, Op
, AddrSize
, IsLittleEndian
))
839 DescriptionsLength
+= *OpSize
;
841 return OpSize
.takeError();
844 if (Entry
.DescriptionsLength
)
845 DescriptionsLength
= *Entry
.DescriptionsLength
;
847 DescriptionsLength
= OpBuffer
.size();
849 encodeULEB128(DescriptionsLength
, OS
);
850 OS
.write(OpBuffer
.data(), OpBuffer
.size());
852 return Error::success();
855 switch (Entry
.Operator
) {
856 case dwarf::DW_LLE_end_of_list
:
857 if (Error Err
= CheckOperands(0))
858 return std::move(Err
);
860 case dwarf::DW_LLE_base_addressx
:
861 if (Error Err
= CheckOperands(1))
862 return std::move(Err
);
863 encodeULEB128(Entry
.Values
[0], OS
);
865 case dwarf::DW_LLE_startx_endx
:
866 case dwarf::DW_LLE_startx_length
:
867 case dwarf::DW_LLE_offset_pair
:
868 if (Error Err
= CheckOperands(2))
869 return std::move(Err
);
870 encodeULEB128(Entry
.Values
[0], OS
);
871 encodeULEB128(Entry
.Values
[1], OS
);
872 if (Error Err
= WriteDWARFOperations())
873 return std::move(Err
);
875 case dwarf::DW_LLE_default_location
:
876 if (Error Err
= CheckOperands(0))
877 return std::move(Err
);
878 if (Error Err
= WriteDWARFOperations())
879 return std::move(Err
);
881 case dwarf::DW_LLE_base_address
:
882 if (Error Err
= CheckOperands(1))
883 return std::move(Err
);
884 if (Error Err
= WriteAddress(Entry
.Values
[0]))
885 return std::move(Err
);
887 case dwarf::DW_LLE_start_end
:
888 if (Error Err
= CheckOperands(2))
889 return std::move(Err
);
890 if (Error Err
= WriteAddress(Entry
.Values
[0]))
891 return std::move(Err
);
892 cantFail(WriteAddress(Entry
.Values
[1]));
893 if (Error Err
= WriteDWARFOperations())
894 return std::move(Err
);
896 case dwarf::DW_LLE_start_length
:
897 if (Error Err
= CheckOperands(2))
898 return std::move(Err
);
899 if (Error Err
= WriteAddress(Entry
.Values
[0]))
900 return std::move(Err
);
901 encodeULEB128(Entry
.Values
[1], OS
);
902 if (Error Err
= WriteDWARFOperations())
903 return std::move(Err
);
907 return OS
.tell() - BeginOffset
;
910 template <typename EntryType
>
911 static Error
writeDWARFLists(raw_ostream
&OS
,
912 ArrayRef
<DWARFYAML::ListTable
<EntryType
>> Tables
,
913 bool IsLittleEndian
, bool Is64BitAddrSize
) {
914 for (const DWARFYAML::ListTable
<EntryType
> &Table
: Tables
) {
915 // sizeof(version) + sizeof(address_size) + sizeof(segment_selector_size) +
916 // sizeof(offset_entry_count) = 8
921 AddrSize
= *Table
.AddrSize
;
923 AddrSize
= Is64BitAddrSize
? 8 : 4;
925 // Since the length of the current range/location lists entry is
926 // undetermined yet, we firstly write the content of the range/location
927 // lists to a buffer to calculate the length and then serialize the buffer
928 // content to the actual output stream.
929 std::string ListBuffer
;
930 raw_string_ostream
ListBufferOS(ListBuffer
);
932 // Offsets holds offsets for each range/location list. The i-th element is
933 // the offset from the beginning of the first range/location list to the
934 // location of the i-th range list.
935 std::vector
<uint64_t> Offsets
;
937 for (const DWARFYAML::ListEntries
<EntryType
> &List
: Table
.Lists
) {
938 Offsets
.push_back(ListBufferOS
.tell());
940 List
.Content
->writeAsBinary(ListBufferOS
, UINT64_MAX
);
941 Length
+= List
.Content
->binary_size();
942 } else if (List
.Entries
) {
943 for (const EntryType
&Entry
: *List
.Entries
) {
944 Expected
<uint64_t> EntrySize
=
945 writeListEntry(ListBufferOS
, Entry
, AddrSize
, IsLittleEndian
);
947 return EntrySize
.takeError();
948 Length
+= *EntrySize
;
953 // If the offset_entry_count field isn't specified, yaml2obj will infer it
954 // from the 'Offsets' field in the YAML description. If the 'Offsets' field
955 // isn't specified either, yaml2obj will infer it from the auto-generated
957 uint32_t OffsetEntryCount
;
958 if (Table
.OffsetEntryCount
)
959 OffsetEntryCount
= *Table
.OffsetEntryCount
;
961 OffsetEntryCount
= Table
.Offsets
? Table
.Offsets
->size() : Offsets
.size();
962 uint64_t OffsetsSize
=
963 OffsetEntryCount
* (Table
.Format
== dwarf::DWARF64
? 8 : 4);
964 Length
+= OffsetsSize
;
966 // If the length is specified in the YAML description, we use it instead of
967 // the actual length.
969 Length
= *Table
.Length
;
971 writeInitialLength(Table
.Format
, Length
, OS
, IsLittleEndian
);
972 writeInteger((uint16_t)Table
.Version
, OS
, IsLittleEndian
);
973 writeInteger((uint8_t)AddrSize
, OS
, IsLittleEndian
);
974 writeInteger((uint8_t)Table
.SegSelectorSize
, OS
, IsLittleEndian
);
975 writeInteger((uint32_t)OffsetEntryCount
, OS
, IsLittleEndian
);
977 auto EmitOffsets
= [&](ArrayRef
<uint64_t> Offsets
, uint64_t OffsetsSize
) {
978 for (uint64_t Offset
: Offsets
)
979 writeDWARFOffset(OffsetsSize
+ Offset
, Table
.Format
, OS
,
984 EmitOffsets(ArrayRef
<uint64_t>((const uint64_t *)Table
.Offsets
->data(),
985 Table
.Offsets
->size()),
987 else if (OffsetEntryCount
!= 0)
988 EmitOffsets(Offsets
, OffsetsSize
);
990 OS
.write(ListBuffer
.data(), ListBuffer
.size());
993 return Error::success();
996 Error
DWARFYAML::emitDebugRnglists(raw_ostream
&OS
, const Data
&DI
) {
997 assert(DI
.DebugRnglists
&& "unexpected emitDebugRnglists() call");
998 return writeDWARFLists
<DWARFYAML::RnglistEntry
>(
999 OS
, *DI
.DebugRnglists
, DI
.IsLittleEndian
, DI
.Is64BitAddrSize
);
1002 Error
DWARFYAML::emitDebugLoclists(raw_ostream
&OS
, const Data
&DI
) {
1003 assert(DI
.DebugLoclists
&& "unexpected emitDebugRnglists() call");
1004 return writeDWARFLists
<DWARFYAML::LoclistEntry
>(
1005 OS
, *DI
.DebugLoclists
, DI
.IsLittleEndian
, DI
.Is64BitAddrSize
);
1008 std::function
<Error(raw_ostream
&, const DWARFYAML::Data
&)>
1009 DWARFYAML::getDWARFEmitterByName(StringRef SecName
) {
1012 std::function
<Error(raw_ostream
&, const DWARFYAML::Data
&)>>(SecName
)
1013 .Case("debug_abbrev", DWARFYAML::emitDebugAbbrev
)
1014 .Case("debug_addr", DWARFYAML::emitDebugAddr
)
1015 .Case("debug_aranges", DWARFYAML::emitDebugAranges
)
1016 .Case("debug_gnu_pubnames", DWARFYAML::emitDebugGNUPubnames
)
1017 .Case("debug_gnu_pubtypes", DWARFYAML::emitDebugGNUPubtypes
)
1018 .Case("debug_info", DWARFYAML::emitDebugInfo
)
1019 .Case("debug_line", DWARFYAML::emitDebugLine
)
1020 .Case("debug_loclists", DWARFYAML::emitDebugLoclists
)
1021 .Case("debug_pubnames", DWARFYAML::emitDebugPubnames
)
1022 .Case("debug_pubtypes", DWARFYAML::emitDebugPubtypes
)
1023 .Case("debug_ranges", DWARFYAML::emitDebugRanges
)
1024 .Case("debug_rnglists", DWARFYAML::emitDebugRnglists
)
1025 .Case("debug_str", DWARFYAML::emitDebugStr
)
1026 .Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets
)
1027 .Default([&](raw_ostream
&, const DWARFYAML::Data
&) {
1028 return createStringError(errc::not_supported
,
1029 SecName
+ " is not supported");
1036 emitDebugSectionImpl(const DWARFYAML::Data
&DI
, StringRef Sec
,
1037 StringMap
<std::unique_ptr
<MemoryBuffer
>> &OutputBuffers
) {
1039 raw_string_ostream
DebugInfoStream(Data
);
1041 auto EmitFunc
= DWARFYAML::getDWARFEmitterByName(Sec
);
1043 if (Error Err
= EmitFunc(DebugInfoStream
, DI
))
1045 DebugInfoStream
.flush();
1047 OutputBuffers
[Sec
] = MemoryBuffer::getMemBufferCopy(Data
);
1049 return Error::success();
1052 Expected
<StringMap
<std::unique_ptr
<MemoryBuffer
>>>
1053 DWARFYAML::emitDebugSections(StringRef YAMLString
, bool IsLittleEndian
,
1054 bool Is64BitAddrSize
) {
1055 auto CollectDiagnostic
= [](const SMDiagnostic
&Diag
, void *DiagContext
) {
1056 *static_cast<SMDiagnostic
*>(DiagContext
) = Diag
;
1059 SMDiagnostic GeneratedDiag
;
1060 yaml::Input
YIn(YAMLString
, /*Ctxt=*/nullptr, CollectDiagnostic
,
1064 DI
.IsLittleEndian
= IsLittleEndian
;
1065 DI
.Is64BitAddrSize
= Is64BitAddrSize
;
1069 return createStringError(YIn
.error(), GeneratedDiag
.getMessage());
1071 StringMap
<std::unique_ptr
<MemoryBuffer
>> DebugSections
;
1072 Error Err
= Error::success();
1074 for (StringRef SecName
: DI
.getNonEmptySectionNames())
1075 Err
= joinErrors(std::move(Err
),
1076 emitDebugSectionImpl(DI
, SecName
, DebugSections
));
1079 return std::move(Err
);
1080 return std::move(DebugSections
);