1 //===- DWARFEmitter - Convert YAML to DWARF binary data -------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// The DWARF component of yaml2obj. Provided as library code for tests.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/ObjectYAML/DWARFEmitter.h"
16 #include "DWARFVisitor.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ObjectYAML/DWARFYAML.h"
20 #include "llvm/Support/Error.h"
21 #include "llvm/Support/Host.h"
22 #include "llvm/Support/LEB128.h"
23 #include "llvm/Support/MathExtras.h"
24 #include "llvm/Support/MemoryBuffer.h"
25 #include "llvm/Support/SwapByteOrder.h"
26 #include "llvm/Support/YAMLTraits.h"
27 #include "llvm/Support/raw_ostream.h"
39 static void writeInteger(T Integer
, raw_ostream
&OS
, bool IsLittleEndian
) {
40 if (IsLittleEndian
!= sys::IsLittleEndianHost
)
41 sys::swapByteOrder(Integer
);
42 OS
.write(reinterpret_cast<char *>(&Integer
), sizeof(T
));
45 static void writeVariableSizedInteger(uint64_t Integer
, size_t Size
,
46 raw_ostream
&OS
, bool IsLittleEndian
) {
48 writeInteger((uint64_t)Integer
, OS
, IsLittleEndian
);
50 writeInteger((uint32_t)Integer
, OS
, IsLittleEndian
);
52 writeInteger((uint16_t)Integer
, OS
, IsLittleEndian
);
54 writeInteger((uint8_t)Integer
, OS
, IsLittleEndian
);
56 assert(false && "Invalid integer write size.");
59 static void ZeroFillBytes(raw_ostream
&OS
, size_t Size
) {
60 std::vector
<uint8_t> FillData
;
61 FillData
.insert(FillData
.begin(), Size
, 0);
62 OS
.write(reinterpret_cast<char *>(FillData
.data()), Size
);
65 static void writeInitialLength(const DWARFYAML::InitialLength
&Length
,
66 raw_ostream
&OS
, bool IsLittleEndian
) {
67 writeInteger((uint32_t)Length
.TotalLength
, OS
, IsLittleEndian
);
68 if (Length
.isDWARF64())
69 writeInteger((uint64_t)Length
.TotalLength64
, OS
, IsLittleEndian
);
72 void DWARFYAML::EmitDebugStr(raw_ostream
&OS
, const DWARFYAML::Data
&DI
) {
73 for (auto Str
: DI
.DebugStrings
) {
74 OS
.write(Str
.data(), Str
.size());
79 void DWARFYAML::EmitDebugAbbrev(raw_ostream
&OS
, const DWARFYAML::Data
&DI
) {
80 for (auto AbbrevDecl
: DI
.AbbrevDecls
) {
81 encodeULEB128(AbbrevDecl
.Code
, OS
);
82 encodeULEB128(AbbrevDecl
.Tag
, OS
);
83 OS
.write(AbbrevDecl
.Children
);
84 for (auto Attr
: AbbrevDecl
.Attributes
) {
85 encodeULEB128(Attr
.Attribute
, OS
);
86 encodeULEB128(Attr
.Form
, OS
);
87 if (Attr
.Form
== dwarf::DW_FORM_implicit_const
)
88 encodeSLEB128(Attr
.Value
, OS
);
95 void DWARFYAML::EmitDebugAranges(raw_ostream
&OS
, const DWARFYAML::Data
&DI
) {
96 for (auto Range
: DI
.ARanges
) {
97 auto HeaderStart
= OS
.tell();
98 writeInitialLength(Range
.Length
, OS
, DI
.IsLittleEndian
);
99 writeInteger((uint16_t)Range
.Version
, OS
, DI
.IsLittleEndian
);
100 writeInteger((uint32_t)Range
.CuOffset
, OS
, DI
.IsLittleEndian
);
101 writeInteger((uint8_t)Range
.AddrSize
, OS
, DI
.IsLittleEndian
);
102 writeInteger((uint8_t)Range
.SegSize
, OS
, DI
.IsLittleEndian
);
104 auto HeaderSize
= OS
.tell() - HeaderStart
;
105 auto FirstDescriptor
= alignTo(HeaderSize
, Range
.AddrSize
* 2);
106 ZeroFillBytes(OS
, FirstDescriptor
- HeaderSize
);
108 for (auto Descriptor
: Range
.Descriptors
) {
109 writeVariableSizedInteger(Descriptor
.Address
, Range
.AddrSize
, OS
,
111 writeVariableSizedInteger(Descriptor
.Length
, Range
.AddrSize
, OS
,
114 ZeroFillBytes(OS
, Range
.AddrSize
* 2);
118 void DWARFYAML::EmitPubSection(raw_ostream
&OS
,
119 const DWARFYAML::PubSection
&Sect
,
120 bool IsLittleEndian
) {
121 writeInitialLength(Sect
.Length
, OS
, IsLittleEndian
);
122 writeInteger((uint16_t)Sect
.Version
, OS
, IsLittleEndian
);
123 writeInteger((uint32_t)Sect
.UnitOffset
, OS
, IsLittleEndian
);
124 writeInteger((uint32_t)Sect
.UnitSize
, OS
, IsLittleEndian
);
125 for (auto Entry
: Sect
.Entries
) {
126 writeInteger((uint32_t)Entry
.DieOffset
, OS
, IsLittleEndian
);
128 writeInteger((uint32_t)Entry
.Descriptor
, OS
, IsLittleEndian
);
129 OS
.write(Entry
.Name
.data(), Entry
.Name
.size());
135 /// An extension of the DWARFYAML::ConstVisitor which writes compile
136 /// units and DIEs to a stream.
137 class DumpVisitor
: public DWARFYAML::ConstVisitor
{
141 void onStartCompileUnit(const DWARFYAML::Unit
&CU
) override
{
142 writeInitialLength(CU
.Length
, OS
, DebugInfo
.IsLittleEndian
);
143 writeInteger((uint16_t)CU
.Version
, OS
, DebugInfo
.IsLittleEndian
);
144 if(CU
.Version
>= 5) {
145 writeInteger((uint8_t)CU
.Type
, OS
, DebugInfo
.IsLittleEndian
);
146 writeInteger((uint8_t)CU
.AddrSize
, OS
, DebugInfo
.IsLittleEndian
);
147 writeInteger((uint32_t)CU
.AbbrOffset
, OS
, DebugInfo
.IsLittleEndian
);
149 writeInteger((uint32_t)CU
.AbbrOffset
, OS
, DebugInfo
.IsLittleEndian
);
150 writeInteger((uint8_t)CU
.AddrSize
, OS
, DebugInfo
.IsLittleEndian
);
154 void onStartDIE(const DWARFYAML::Unit
&CU
,
155 const DWARFYAML::Entry
&DIE
) override
{
156 encodeULEB128(DIE
.AbbrCode
, OS
);
159 void onValue(const uint8_t U
) override
{
160 writeInteger(U
, OS
, DebugInfo
.IsLittleEndian
);
163 void onValue(const uint16_t U
) override
{
164 writeInteger(U
, OS
, DebugInfo
.IsLittleEndian
);
167 void onValue(const uint32_t U
) override
{
168 writeInteger(U
, OS
, DebugInfo
.IsLittleEndian
);
171 void onValue(const uint64_t U
, const bool LEB
= false) override
{
173 encodeULEB128(U
, OS
);
175 writeInteger(U
, OS
, DebugInfo
.IsLittleEndian
);
178 void onValue(const int64_t S
, const bool LEB
= false) override
{
180 encodeSLEB128(S
, OS
);
182 writeInteger(S
, OS
, DebugInfo
.IsLittleEndian
);
185 void onValue(const StringRef String
) override
{
186 OS
.write(String
.data(), String
.size());
190 void onValue(const MemoryBufferRef MBR
) override
{
191 OS
.write(MBR
.getBufferStart(), MBR
.getBufferSize());
195 DumpVisitor(const DWARFYAML::Data
&DI
, raw_ostream
&Out
)
196 : DWARFYAML::ConstVisitor(DI
), OS(Out
) {}
200 void DWARFYAML::EmitDebugInfo(raw_ostream
&OS
, const DWARFYAML::Data
&DI
) {
201 DumpVisitor
Visitor(DI
, OS
);
202 Visitor
.traverseDebugInfo();
205 static void EmitFileEntry(raw_ostream
&OS
, const DWARFYAML::File
&File
) {
206 OS
.write(File
.Name
.data(), File
.Name
.size());
208 encodeULEB128(File
.DirIdx
, OS
);
209 encodeULEB128(File
.ModTime
, OS
);
210 encodeULEB128(File
.Length
, OS
);
213 void DWARFYAML::EmitDebugLine(raw_ostream
&OS
, const DWARFYAML::Data
&DI
) {
214 for (const auto &LineTable
: DI
.DebugLines
) {
215 writeInitialLength(LineTable
.Length
, OS
, DI
.IsLittleEndian
);
216 uint64_t SizeOfPrologueLength
= LineTable
.Length
.isDWARF64() ? 8 : 4;
217 writeInteger((uint16_t)LineTable
.Version
, OS
, DI
.IsLittleEndian
);
218 writeVariableSizedInteger(LineTable
.PrologueLength
, SizeOfPrologueLength
,
219 OS
, DI
.IsLittleEndian
);
220 writeInteger((uint8_t)LineTable
.MinInstLength
, OS
, DI
.IsLittleEndian
);
221 if (LineTable
.Version
>= 4)
222 writeInteger((uint8_t)LineTable
.MaxOpsPerInst
, OS
, DI
.IsLittleEndian
);
223 writeInteger((uint8_t)LineTable
.DefaultIsStmt
, OS
, DI
.IsLittleEndian
);
224 writeInteger((uint8_t)LineTable
.LineBase
, OS
, DI
.IsLittleEndian
);
225 writeInteger((uint8_t)LineTable
.LineRange
, OS
, DI
.IsLittleEndian
);
226 writeInteger((uint8_t)LineTable
.OpcodeBase
, OS
, DI
.IsLittleEndian
);
228 for (auto OpcodeLength
: LineTable
.StandardOpcodeLengths
)
229 writeInteger((uint8_t)OpcodeLength
, OS
, DI
.IsLittleEndian
);
231 for (auto IncludeDir
: LineTable
.IncludeDirs
) {
232 OS
.write(IncludeDir
.data(), IncludeDir
.size());
237 for (auto File
: LineTable
.Files
)
238 EmitFileEntry(OS
, File
);
241 for (auto Op
: LineTable
.Opcodes
) {
242 writeInteger((uint8_t)Op
.Opcode
, OS
, DI
.IsLittleEndian
);
243 if (Op
.Opcode
== 0) {
244 encodeULEB128(Op
.ExtLen
, OS
);
245 writeInteger((uint8_t)Op
.SubOpcode
, OS
, DI
.IsLittleEndian
);
246 switch (Op
.SubOpcode
) {
247 case dwarf::DW_LNE_set_address
:
248 case dwarf::DW_LNE_set_discriminator
:
249 writeVariableSizedInteger(Op
.Data
, DI
.CompileUnits
[0].AddrSize
, OS
,
252 case dwarf::DW_LNE_define_file
:
253 EmitFileEntry(OS
, Op
.FileEntry
);
255 case dwarf::DW_LNE_end_sequence
:
258 for (auto OpByte
: Op
.UnknownOpcodeData
)
259 writeInteger((uint8_t)OpByte
, OS
, DI
.IsLittleEndian
);
261 } else if (Op
.Opcode
< LineTable
.OpcodeBase
) {
263 case dwarf::DW_LNS_copy
:
264 case dwarf::DW_LNS_negate_stmt
:
265 case dwarf::DW_LNS_set_basic_block
:
266 case dwarf::DW_LNS_const_add_pc
:
267 case dwarf::DW_LNS_set_prologue_end
:
268 case dwarf::DW_LNS_set_epilogue_begin
:
271 case dwarf::DW_LNS_advance_pc
:
272 case dwarf::DW_LNS_set_file
:
273 case dwarf::DW_LNS_set_column
:
274 case dwarf::DW_LNS_set_isa
:
275 encodeULEB128(Op
.Data
, OS
);
278 case dwarf::DW_LNS_advance_line
:
279 encodeSLEB128(Op
.SData
, OS
);
282 case dwarf::DW_LNS_fixed_advance_pc
:
283 writeInteger((uint16_t)Op
.Data
, OS
, DI
.IsLittleEndian
);
287 for (auto OpData
: Op
.StandardOpcodeData
) {
288 encodeULEB128(OpData
, OS
);
296 using EmitFuncType
= void (*)(raw_ostream
&, const DWARFYAML::Data
&);
299 EmitDebugSectionImpl(const DWARFYAML::Data
&DI
, EmitFuncType EmitFunc
,
301 StringMap
<std::unique_ptr
<MemoryBuffer
>> &OutputBuffers
) {
303 raw_string_ostream
DebugInfoStream(Data
);
304 EmitFunc(DebugInfoStream
, DI
);
305 DebugInfoStream
.flush();
307 OutputBuffers
[Sec
] = MemoryBuffer::getMemBufferCopy(Data
);
311 class DIEFixupVisitor
: public DWARFYAML::Visitor
{
315 DIEFixupVisitor(DWARFYAML::Data
&DI
) : DWARFYAML::Visitor(DI
){};
318 virtual void onStartCompileUnit(DWARFYAML::Unit
&CU
) { Length
= 7; }
320 virtual void onEndCompileUnit(DWARFYAML::Unit
&CU
) {
321 CU
.Length
.setLength(Length
);
324 virtual void onStartDIE(DWARFYAML::Unit
&CU
, DWARFYAML::Entry
&DIE
) {
325 Length
+= getULEB128Size(DIE
.AbbrCode
);
328 virtual void onValue(const uint8_t U
) { Length
+= 1; }
329 virtual void onValue(const uint16_t U
) { Length
+= 2; }
330 virtual void onValue(const uint32_t U
) { Length
+= 4; }
331 virtual void onValue(const uint64_t U
, const bool LEB
= false) {
333 Length
+= getULEB128Size(U
);
337 virtual void onValue(const int64_t S
, const bool LEB
= false) {
339 Length
+= getSLEB128Size(S
);
343 virtual void onValue(const StringRef String
) { Length
+= String
.size() + 1; }
345 virtual void onValue(const MemoryBufferRef MBR
) {
346 Length
+= MBR
.getBufferSize();
351 Expected
<StringMap
<std::unique_ptr
<MemoryBuffer
>>>
352 DWARFYAML::EmitDebugSections(StringRef YAMLString
, bool ApplyFixups
,
353 bool IsLittleEndian
) {
354 yaml::Input
YIn(YAMLString
);
357 DI
.IsLittleEndian
= IsLittleEndian
;
360 return errorCodeToError(YIn
.error());
363 DIEFixupVisitor
DIFixer(DI
);
364 DIFixer
.traverseDebugInfo();
367 StringMap
<std::unique_ptr
<MemoryBuffer
>> DebugSections
;
368 EmitDebugSectionImpl(DI
, &DWARFYAML::EmitDebugInfo
, "debug_info",
370 EmitDebugSectionImpl(DI
, &DWARFYAML::EmitDebugLine
, "debug_line",
372 EmitDebugSectionImpl(DI
, &DWARFYAML::EmitDebugStr
, "debug_str",
374 EmitDebugSectionImpl(DI
, &DWARFYAML::EmitDebugAbbrev
, "debug_abbrev",
376 EmitDebugSectionImpl(DI
, &DWARFYAML::EmitDebugAranges
, "debug_aranges",
378 return std::move(DebugSections
);