1 //===--- unittests/DebugInfo/DWARF/DwarfGenerator.h -------------*- C++ -*-===//
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 //===----------------------------------------------------------------------===//
9 // A file that can generate DWARF debug info for unit tests.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_UNITTESTS_DEBUG_INFO_DWARF_DWARFGENERATOR_H
14 #define LLVM_UNITTESTS_DEBUG_INFO_DWARF_DWARFGENERATOR_H
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/CodeGen/DIE.h"
18 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
19 #include "llvm/Support/Error.h"
31 class DwarfStringPool
;
36 struct MCDwarfLineTableParams
;
40 class MCSubtargetInfo
;
42 class TargetLoweringObjectFile
;
51 /// A DWARF debug information entry class used to generate DWARF DIEs.
53 /// This class is used to quickly generate DWARF debug information by creating
54 /// child DIEs or adding attributes to the current DIE. Instances of this class
55 /// are created from the compile unit (dwarfgen::CompileUnit::getUnitDIE()) or
56 /// by calling dwarfgen::DIE::addChild(...) and using the returned DIE object.
58 dwarfgen::CompileUnit
*CU
;
62 friend class Generator
;
63 friend class CompileUnit
;
65 DIE(CompileUnit
*U
= nullptr, llvm::DIE
*D
= nullptr) : CU(U
), Die(D
) {}
67 /// Called with a compile/type unit relative offset prior to generating the
70 /// \param CUOffset the compile/type unit relative offset where the
71 /// abbreviation code for this DIE will be encoded.
72 unsigned computeSizeAndOffsets(unsigned CUOffset
);
75 /// Add an attribute value that has no value.
77 /// \param Attr a dwarf::Attribute enumeration value or any uint16_t that
78 /// represents a user defined DWARF attribute.
79 /// \param Form the dwarf::Form to use when encoding the attribute. This is
80 /// only used with the DW_FORM_flag_present form encoding.
81 void addAttribute(uint16_t Attr
, dwarf::Form Form
);
83 /// Add an attribute value to be encoded as a DIEInteger
85 /// \param Attr a dwarf::Attribute enumeration value or any uint16_t that
86 /// represents a user defined DWARF attribute.
87 /// \param Form the dwarf::Form to use when encoding the attribute.
88 /// \param U the unsigned integer to encode.
89 void addAttribute(uint16_t Attr
, dwarf::Form Form
, uint64_t U
);
91 /// Add an attribute value to be encoded as a DIEExpr
93 /// \param Attr a dwarf::Attribute enumeration value or any uint16_t that
94 /// represents a user defined DWARF attribute.
95 /// \param Form the dwarf::Form to use when encoding the attribute.
96 /// \param Expr the MC expression used to compute the value.
97 void addAttribute(uint16_t Attr
, dwarf::Form Form
, const MCExpr
&Expr
);
99 /// Add an attribute value to be encoded as a DIEString or DIEInlinedString.
101 /// \param Attr a dwarf::Attribute enumeration value or any uint16_t that
102 /// represents a user defined DWARF attribute.
103 /// \param Form the dwarf::Form to use when encoding the attribute. The form
104 /// must be one of DW_FORM_strp or DW_FORM_string.
105 /// \param String the string to encode.
106 void addAttribute(uint16_t Attr
, dwarf::Form Form
, StringRef String
);
108 /// Add an attribute value to be encoded as a DIEEntry.
110 /// DIEEntry attributes refer to other llvm::DIE objects that have been
113 /// \param Attr a dwarf::Attribute enumeration value or any uint16_t that
114 /// represents a user defined DWARF attribute.
115 /// \param Form the dwarf::Form to use when encoding the attribute. The form
116 /// must be one of DW_FORM_strp or DW_FORM_string.
117 /// \param RefDie the DIE that this attriute refers to.
118 void addAttribute(uint16_t Attr
, dwarf::Form Form
, dwarfgen::DIE
&RefDie
);
120 /// Add an attribute value to be encoded as a DIEBlock.
122 /// DIEBlock attributes refers to binary data that is stored as the
123 /// attribute's value.
125 /// \param Attr a dwarf::Attribute enumeration value or any uint16_t that
126 /// represents a user defined DWARF attribute.
127 /// \param Form the dwarf::Form to use when encoding the attribute. The form
128 /// must be one of DW_FORM_strp or DW_FORM_string.
129 /// \param P a pointer to the data to store as the attribute value.
130 /// \param S the size in bytes of the data pointed to by P .
131 void addAttribute(uint16_t Attr
, dwarf::Form Form
, const void *P
, size_t S
);
133 /// Add a DW_AT_str_offsets_base attribute to this DIE.
134 void addStrOffsetsBaseAttribute();
136 /// Add a new child to this DIE object.
138 /// \param Tag the dwarf::Tag to assing to the llvm::DIE object.
139 /// \returns the newly created DIE object that is now a child owned by this
141 dwarfgen::DIE
addChild(dwarf::Tag Tag
);
144 /// A DWARF compile unit used to generate DWARF compile/type units.
146 /// Instances of these classes are created by instances of the Generator
147 /// class. All information required to generate a DWARF compile unit is
148 /// contained inside this class.
154 CompileUnit(Generator
&D
, uint16_t V
, uint8_t A
)
155 : DG(D
), DU(V
, A
, dwarf::DW_TAG_compile_unit
) {}
157 Generator
&getGenerator() { return DG
; }
158 uint64_t getOffset() const { return DU
.getDebugSectionOffset(); }
159 uint64_t getLength() const { return DU
.getLength(); }
160 uint16_t getVersion() const { return DU
.getDwarfVersion(); }
161 uint16_t getAddressSize() const { return DU
.getAddressSize(); }
162 void setOffset(uint64_t Offset
) { DU
.setDebugSectionOffset(Offset
); }
163 void setLength(uint64_t Length
) { DU
.setLength(Length
); }
166 /// A DWARF line unit-like class used to generate DWARF line units.
168 /// Instances of this class are created by instances of the Generator class.
171 enum ValueLength
{ Byte
= 1, Half
= 2, Long
= 4, Quad
= 8, ULEB
, SLEB
};
173 struct ValueAndLength
{
178 LineTable(uint16_t Version
, dwarf::DwarfFormat Format
, uint8_t AddrSize
,
180 : Version(Version
), Format(Format
), AddrSize(AddrSize
), SegSize(SegSize
) {
181 assert(Version
>= 2 && Version
<= 5 && "unsupported version");
184 // Create a Prologue suitable to pass to setPrologue, with a single file and
185 // include directory entry.
186 DWARFDebugLine::Prologue
createBasicPrologue() const;
188 // Set or replace the current prologue with the specified prologue. If no
189 // prologue is set, a default one will be used when generating.
190 void setPrologue(DWARFDebugLine::Prologue NewPrologue
);
191 // Used to write an arbitrary payload instead of the standard prologue. This
192 // is useful if you wish to test handling of corrupt .debug_line sections.
193 void setCustomPrologue(ArrayRef
<ValueAndLength
> NewPrologue
);
195 // Add a byte to the program, with the given value. This can be used to
196 // specify a special opcode, or to add arbitrary contents to the section.
197 void addByte(uint8_t Value
);
198 // Add a standard opcode to the program. The opcode and operands do not have
200 void addStandardOpcode(uint8_t Opcode
, ArrayRef
<ValueAndLength
> Operands
);
201 // Add an extended opcode to the program with the specified length, opcode,
202 // and operands. These values do not have to be valid.
203 void addExtendedOpcode(uint64_t Length
, uint8_t Opcode
,
204 ArrayRef
<ValueAndLength
> Operands
);
206 // Write the contents of the LineUnit to the current section in the generator.
207 void generate(MCContext
&MC
, AsmPrinter
&Asm
) const;
210 void writeData(ArrayRef
<ValueAndLength
> Data
, AsmPrinter
&Asm
) const;
211 MCSymbol
*writeDefaultPrologue(AsmPrinter
&Asm
) const;
212 void writePrologue(AsmPrinter
&Asm
) const;
214 void writeProloguePayload(const DWARFDebugLine::Prologue
&Prologue
,
215 AsmPrinter
&Asm
) const;
217 llvm::Optional
<DWARFDebugLine::Prologue
> Prologue
;
218 std::vector
<ValueAndLength
> CustomPrologue
;
219 std::vector
<ValueAndLength
> Contents
;
221 // The Version field is used for determining how to write the Prologue, if a
222 // non-custom prologue is used. The version value actually written, will be
223 // that specified in the Prologue, if a custom prologue has been passed in.
224 // Otherwise, it will be this value.
227 dwarf::DwarfFormat Format
;
232 /// A DWARF generator.
234 /// Generate DWARF for unit tests by creating any instance of this class and
235 /// calling Generator::addCompileUnit(), and then getting the dwarfgen::DIE from
236 /// the returned compile unit and adding attributes and children to each DIE.
238 std::unique_ptr
<MCRegisterInfo
> MRI
;
239 std::unique_ptr
<MCAsmInfo
> MAI
;
240 std::unique_ptr
<MCContext
> MC
;
241 MCAsmBackend
*MAB
; // Owned by MCStreamer
242 std::unique_ptr
<MCInstrInfo
> MII
;
243 std::unique_ptr
<MCSubtargetInfo
> MSTI
;
244 MCCodeEmitter
*MCE
; // Owned by MCStreamer
245 MCStreamer
*MS
; // Owned by AsmPrinter
246 std::unique_ptr
<TargetMachine
> TM
;
247 TargetLoweringObjectFile
*TLOF
; // Owned by TargetMachine;
248 std::unique_ptr
<AsmPrinter
> Asm
;
249 BumpPtrAllocator Allocator
;
250 std::unique_ptr
<DwarfStringPool
> StringPool
; // Entries owned by Allocator.
251 std::vector
<std::unique_ptr
<CompileUnit
>> CompileUnits
;
252 std::vector
<std::unique_ptr
<LineTable
>> LineTables
;
253 DIEAbbrevSet Abbreviations
;
255 MCSymbol
*StringOffsetsStartSym
;
257 SmallString
<4096> FileBytes
;
258 /// The stream we use to generate the DWARF into as an ELF file.
259 std::unique_ptr
<raw_svector_ostream
> Stream
;
260 /// The DWARF version to generate.
263 /// Private constructor, call Generator::Create(...) to get a DWARF generator
267 /// Create the streamer and setup the output buffer.
268 llvm::Error
init(Triple TheTriple
, uint16_t DwarfVersion
);
271 /// Create a DWARF generator or get an appropriate error.
273 /// \param TheTriple the triple to use when creating any required support
274 /// classes needed to emit the DWARF.
275 /// \param DwarfVersion the version of DWARF to emit.
277 /// \returns a llvm::Expected that either contains a unique_ptr to a Generator
278 /// or a llvm::Error.
279 static llvm::Expected
<std::unique_ptr
<Generator
>>
280 create(Triple TheTriple
, uint16_t DwarfVersion
);
284 /// Generate all DWARF sections and return a memory buffer that
285 /// contains an ELF file that contains the DWARF.
286 StringRef
generate();
288 /// Add a compile unit to be generated.
290 /// \returns a dwarfgen::CompileUnit that can be used to retrieve the compile
291 /// unit dwarfgen::DIE that can be used to add attributes and add child DIE
293 dwarfgen::CompileUnit
&addCompileUnit();
295 /// Add a line table unit to be generated.
296 /// \param DwarfFormat the DWARF format to use (DWARF32 or DWARF64).
298 /// \returns a dwarfgen::LineTable that can be used to customise the contents
299 /// of the line table.
301 addLineTable(dwarf::DwarfFormat DwarfFormat
= dwarf::DwarfFormat::DWARF32
);
303 BumpPtrAllocator
&getAllocator() { return Allocator
; }
304 AsmPrinter
*getAsmPrinter() const { return Asm
.get(); }
305 MCContext
*getMCContext() const { return MC
.get(); }
306 DIEAbbrevSet
&getAbbrevSet() { return Abbreviations
; }
307 DwarfStringPool
&getStringPool() { return *StringPool
; }
308 MCSymbol
*getStringOffsetsStartSym() const { return StringOffsetsStartSym
; }
310 /// Save the generated DWARF file to disk.
312 /// \param Path the path to save the ELF file to.
313 bool saveFile(StringRef Path
);
316 } // end namespace dwarfgen
318 } // end namespace llvm
320 #endif // LLVM_UNITTESTS_DEBUG_INFO_DWARF_DWARFGENERATOR_H