1 //===- DebugLineSectionEmitter.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 #ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H
10 #define LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H
12 #include "DWARFEmitterImpl.h"
13 #include "llvm/DWARFLinker/AddressesMap.h"
14 #include "llvm/DWARFLinker/Parallel/DWARFLinker.h"
15 #include "llvm/DebugInfo/DWARF/DWARFObject.h"
16 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
17 #include "llvm/MC/TargetRegistry.h"
20 namespace dwarf_linker
{
23 /// This class emits specified line table into the .debug_line section.
24 class DebugLineSectionEmitter
{
26 DebugLineSectionEmitter(const Triple
&TheTriple
, DwarfUnit
&U
)
27 : TheTriple(TheTriple
), U(U
) {}
29 Error
emit(const DWARFDebugLine::LineTable
&LineTable
) {
30 // FIXME: remove dependence on MCDwarfLineAddr::encode.
31 // As we reuse MCDwarfLineAddr::encode, we need to create/initialize
33 if (Error Err
= init(TheTriple
))
36 // Get descriptor for output .debug_line section.
37 SectionDescriptor
&OutSection
=
38 U
.getOrCreateSectionDescriptor(DebugSectionKind::DebugLine
);
41 OutSection
.emitUnitLength(0xBADDEF);
42 uint64_t OffsetAfterUnitLength
= OutSection
.OS
.tell();
45 emitLineTablePrologue(LineTable
.Prologue
, OutSection
);
48 emitLineTableRows(LineTable
, OutSection
);
49 uint64_t OffsetAfterEnd
= OutSection
.OS
.tell();
51 // Update unit length field with actual length value.
52 assert(OffsetAfterUnitLength
-
53 OutSection
.getFormParams().getDwarfOffsetByteSize() <
54 OffsetAfterUnitLength
);
55 OutSection
.apply(OffsetAfterUnitLength
-
56 OutSection
.getFormParams().getDwarfOffsetByteSize(),
57 dwarf::DW_FORM_sec_offset
,
58 OffsetAfterEnd
- OffsetAfterUnitLength
);
60 return Error::success();
64 Error
init(Triple TheTriple
) {
66 std::string TripleName
;
69 const Target
*TheTarget
=
70 TargetRegistry::lookupTarget(TripleName
, TheTriple
, ErrorStr
);
72 return createStringError(std::errc::invalid_argument
, ErrorStr
.c_str());
73 TripleName
= TheTriple
.getTriple();
75 // Create all the MC Objects.
76 MRI
.reset(TheTarget
->createMCRegInfo(TripleName
));
78 return createStringError(std::errc::invalid_argument
,
79 "no register info for target %s",
82 MCTargetOptions MCOptions
= mc::InitMCTargetOptionsFromFlags();
83 MAI
.reset(TheTarget
->createMCAsmInfo(*MRI
, TripleName
, MCOptions
));
85 return createStringError(std::errc::invalid_argument
,
86 "no asm info for target %s", TripleName
.c_str());
88 MSTI
.reset(TheTarget
->createMCSubtargetInfo(TripleName
, "", ""));
90 return createStringError(std::errc::invalid_argument
,
91 "no subtarget info for target %s",
94 MC
.reset(new MCContext(TheTriple
, MAI
.get(), MRI
.get(), MSTI
.get(), nullptr,
95 nullptr, true, "__DWARF"));
97 return Error::success();
100 void emitLineTablePrologue(const DWARFDebugLine::Prologue
&P
,
101 SectionDescriptor
&Section
) {
103 Section
.emitIntVal(P
.getVersion(), 2);
104 if (P
.getVersion() == 5) {
105 // address_size (ubyte).
106 Section
.emitIntVal(P
.getAddressSize(), 1);
108 // segment_selector_size (ubyte).
109 Section
.emitIntVal(P
.SegSelectorSize
, 1);
113 Section
.emitOffset(0xBADDEF);
115 uint64_t OffsetAfterPrologueLength
= Section
.OS
.tell();
116 emitLineTableProloguePayload(P
, Section
);
117 uint64_t OffsetAfterPrologueEnd
= Section
.OS
.tell();
119 // Update prologue length field with actual length value.
120 Section
.apply(OffsetAfterPrologueLength
-
121 Section
.getFormParams().getDwarfOffsetByteSize(),
122 dwarf::DW_FORM_sec_offset
,
123 OffsetAfterPrologueEnd
- OffsetAfterPrologueLength
);
127 emitLineTablePrologueV2IncludeAndFileTable(const DWARFDebugLine::Prologue
&P
,
128 SectionDescriptor
&Section
) {
129 // include_directories (sequence of path names).
130 for (const DWARFFormValue
&Include
: P
.IncludeDirectories
) {
131 std::optional
<const char *> IncludeStr
= dwarf::toString(Include
);
133 U
.warn("cann't read string from line table.");
137 Section
.emitString(Include
.getForm(), *IncludeStr
);
139 // The last entry is followed by a single null byte.
140 Section
.emitIntVal(0, 1);
142 // file_names (sequence of file entries).
143 for (const DWARFDebugLine::FileNameEntry
&File
: P
.FileNames
) {
144 std::optional
<const char *> FileNameStr
= dwarf::toString(File
.Name
);
146 U
.warn("cann't read string from line table.");
150 // A null-terminated string containing the full or relative path name of a
152 Section
.emitString(File
.Name
.getForm(), *FileNameStr
);
154 // An unsigned LEB128 number representing the directory index of a
155 // directory in the include_directories section.
156 encodeULEB128(File
.DirIdx
, Section
.OS
);
157 // An unsigned LEB128 number representing the (implementation-defined)
158 // time of last modification for the file, or 0 if not available.
159 encodeULEB128(File
.ModTime
, Section
.OS
);
160 // An unsigned LEB128 number representing the length in bytes of the file,
161 // or 0 if not available.
162 encodeULEB128(File
.Length
, Section
.OS
);
164 // The last entry is followed by a single null byte.
165 Section
.emitIntVal(0, 1);
169 emitLineTablePrologueV5IncludeAndFileTable(const DWARFDebugLine::Prologue
&P
,
170 SectionDescriptor
&Section
) {
171 if (P
.IncludeDirectories
.empty()) {
172 // directory_entry_format_count(ubyte).
173 Section
.emitIntVal(0, 1);
175 // directory_entry_format_count(ubyte).
176 Section
.emitIntVal(1, 1);
178 // directory_entry_format (sequence of ULEB128 pairs).
179 encodeULEB128(dwarf::DW_LNCT_path
, Section
.OS
);
180 encodeULEB128(P
.IncludeDirectories
[0].getForm(), Section
.OS
);
183 // directories_count (ULEB128).
184 encodeULEB128(P
.IncludeDirectories
.size(), Section
.OS
);
185 // directories (sequence of directory names).
186 for (auto Include
: P
.IncludeDirectories
) {
187 std::optional
<const char *> IncludeStr
= dwarf::toString(Include
);
189 U
.warn("cann't read string from line table.");
193 Section
.emitString(Include
.getForm(), *IncludeStr
);
196 bool HasChecksums
= P
.ContentTypes
.HasMD5
;
197 bool HasInlineSources
= P
.ContentTypes
.HasSource
;
199 dwarf::Form FileNameForm
= dwarf::DW_FORM_string
;
200 dwarf::Form LLVMSourceForm
= dwarf::DW_FORM_string
;
202 if (P
.FileNames
.empty()) {
203 // file_name_entry_format_count (ubyte).
204 Section
.emitIntVal(0, 1);
206 FileNameForm
= P
.FileNames
[0].Name
.getForm();
207 LLVMSourceForm
= P
.FileNames
[0].Source
.getForm();
209 // file_name_entry_format_count (ubyte).
211 2 + (HasChecksums
? 1 : 0) + (HasInlineSources
? 1 : 0), 1);
213 // file_name_entry_format (sequence of ULEB128 pairs).
214 encodeULEB128(dwarf::DW_LNCT_path
, Section
.OS
);
215 encodeULEB128(FileNameForm
, Section
.OS
);
217 encodeULEB128(dwarf::DW_LNCT_directory_index
, Section
.OS
);
218 encodeULEB128(dwarf::DW_FORM_data1
, Section
.OS
);
221 encodeULEB128(dwarf::DW_LNCT_MD5
, Section
.OS
);
222 encodeULEB128(dwarf::DW_FORM_data16
, Section
.OS
);
225 if (HasInlineSources
) {
226 encodeULEB128(dwarf::DW_LNCT_LLVM_source
, Section
.OS
);
227 encodeULEB128(LLVMSourceForm
, Section
.OS
);
231 // file_names_count (ULEB128).
232 encodeULEB128(P
.FileNames
.size(), Section
.OS
);
234 // file_names (sequence of file name entries).
235 for (auto File
: P
.FileNames
) {
236 std::optional
<const char *> FileNameStr
= dwarf::toString(File
.Name
);
238 U
.warn("cann't read string from line table.");
242 // A null-terminated string containing the full or relative path name of a
244 Section
.emitString(FileNameForm
, *FileNameStr
);
245 Section
.emitIntVal(File
.DirIdx
, 1);
248 assert((File
.Checksum
.size() == 16) &&
249 "checksum size is not equal to 16 bytes.");
250 Section
.emitBinaryData(
251 StringRef(reinterpret_cast<const char *>(File
.Checksum
.data()),
252 File
.Checksum
.size()));
255 if (HasInlineSources
) {
256 std::optional
<const char *> FileSourceStr
=
257 dwarf::toString(File
.Source
);
258 if (!FileSourceStr
) {
259 U
.warn("cann't read string from line table.");
263 Section
.emitString(LLVMSourceForm
, *FileSourceStr
);
268 void emitLineTableProloguePayload(const DWARFDebugLine::Prologue
&P
,
269 SectionDescriptor
&Section
) {
270 // minimum_instruction_length (ubyte).
271 Section
.emitIntVal(P
.MinInstLength
, 1);
272 if (P
.FormParams
.Version
>= 4) {
273 // maximum_operations_per_instruction (ubyte).
274 Section
.emitIntVal(P
.MaxOpsPerInst
, 1);
276 // default_is_stmt (ubyte).
277 Section
.emitIntVal(P
.DefaultIsStmt
, 1);
278 // line_base (sbyte).
279 Section
.emitIntVal(P
.LineBase
, 1);
280 // line_range (ubyte).
281 Section
.emitIntVal(P
.LineRange
, 1);
282 // opcode_base (ubyte).
283 Section
.emitIntVal(P
.OpcodeBase
, 1);
285 // standard_opcode_lengths (array of ubyte).
286 for (auto Length
: P
.StandardOpcodeLengths
)
287 Section
.emitIntVal(Length
, 1);
289 if (P
.FormParams
.Version
< 5)
290 emitLineTablePrologueV2IncludeAndFileTable(P
, Section
);
292 emitLineTablePrologueV5IncludeAndFileTable(P
, Section
);
295 void emitLineTableRows(const DWARFDebugLine::LineTable
&LineTable
,
296 SectionDescriptor
&Section
) {
298 MCDwarfLineTableParams Params
;
299 Params
.DWARF2LineOpcodeBase
= LineTable
.Prologue
.OpcodeBase
;
300 Params
.DWARF2LineBase
= LineTable
.Prologue
.LineBase
;
301 Params
.DWARF2LineRange
= LineTable
.Prologue
.LineRange
;
303 SmallString
<128> EncodingBuffer
;
305 if (LineTable
.Rows
.empty()) {
306 // We only have the dummy entry, dsymutil emits an entry with a 0
307 // address in that case.
308 MCDwarfLineAddr::encode(*MC
, Params
, std::numeric_limits
<int64_t>::max(),
310 Section
.OS
.write(EncodingBuffer
.c_str(), EncodingBuffer
.size());
314 // Line table state machine fields
315 unsigned FileNum
= 1;
316 unsigned LastLine
= 1;
318 unsigned Discriminator
= 0;
319 unsigned IsStatement
= 1;
321 uint64_t Address
= -1ULL;
323 unsigned RowsSinceLastSequence
= 0;
325 for (const DWARFDebugLine::Row
&Row
: LineTable
.Rows
) {
326 int64_t AddressDelta
;
327 if (Address
== -1ULL) {
328 Section
.emitIntVal(dwarf::DW_LNS_extended_op
, 1);
329 encodeULEB128(Section
.getFormParams().AddrSize
+ 1, Section
.OS
);
330 Section
.emitIntVal(dwarf::DW_LNE_set_address
, 1);
331 Section
.emitIntVal(Row
.Address
.Address
,
332 Section
.getFormParams().AddrSize
);
336 (Row
.Address
.Address
- Address
) / LineTable
.Prologue
.MinInstLength
;
339 // FIXME: code copied and transformed from
340 // MCDwarf.cpp::EmitDwarfLineTable. We should find a way to share this
341 // code, but the current compatibility requirement with classic dsymutil
342 // makes it hard. Revisit that once this requirement is dropped.
344 if (FileNum
!= Row
.File
) {
346 Section
.emitIntVal(dwarf::DW_LNS_set_file
, 1);
347 encodeULEB128(FileNum
, Section
.OS
);
349 if (Column
!= Row
.Column
) {
351 Section
.emitIntVal(dwarf::DW_LNS_set_column
, 1);
352 encodeULEB128(Column
, Section
.OS
);
354 if (Discriminator
!= Row
.Discriminator
&& MC
->getDwarfVersion() >= 4) {
355 Discriminator
= Row
.Discriminator
;
356 unsigned Size
= getULEB128Size(Discriminator
);
357 Section
.emitIntVal(dwarf::DW_LNS_extended_op
, 1);
358 encodeULEB128(Size
+ 1, Section
.OS
);
359 Section
.emitIntVal(dwarf::DW_LNE_set_discriminator
, 1);
360 encodeULEB128(Discriminator
, Section
.OS
);
364 if (Isa
!= Row
.Isa
) {
366 Section
.emitIntVal(dwarf::DW_LNS_set_isa
, 1);
367 encodeULEB128(Isa
, Section
.OS
);
369 if (IsStatement
!= Row
.IsStmt
) {
370 IsStatement
= Row
.IsStmt
;
371 Section
.emitIntVal(dwarf::DW_LNS_negate_stmt
, 1);
374 Section
.emitIntVal(dwarf::DW_LNS_set_basic_block
, 1);
377 Section
.emitIntVal(dwarf::DW_LNS_set_prologue_end
, 1);
379 if (Row
.EpilogueBegin
)
380 Section
.emitIntVal(dwarf::DW_LNS_set_epilogue_begin
, 1);
382 int64_t LineDelta
= int64_t(Row
.Line
) - LastLine
;
383 if (!Row
.EndSequence
) {
384 MCDwarfLineAddr::encode(*MC
, Params
, LineDelta
, AddressDelta
,
386 Section
.OS
.write(EncodingBuffer
.c_str(), EncodingBuffer
.size());
387 EncodingBuffer
.resize(0);
388 Address
= Row
.Address
.Address
;
390 RowsSinceLastSequence
++;
393 Section
.emitIntVal(dwarf::DW_LNS_advance_line
, 1);
394 encodeSLEB128(LineDelta
, Section
.OS
);
397 Section
.emitIntVal(dwarf::DW_LNS_advance_pc
, 1);
398 encodeULEB128(AddressDelta
, Section
.OS
);
400 MCDwarfLineAddr::encode(*MC
, Params
,
401 std::numeric_limits
<int64_t>::max(), 0,
403 Section
.OS
.write(EncodingBuffer
.c_str(), EncodingBuffer
.size());
404 EncodingBuffer
.resize(0);
406 LastLine
= FileNum
= IsStatement
= 1;
407 RowsSinceLastSequence
= Column
= Discriminator
= Isa
= 0;
411 if (RowsSinceLastSequence
) {
412 MCDwarfLineAddr::encode(*MC
, Params
, std::numeric_limits
<int64_t>::max(),
414 Section
.OS
.write(EncodingBuffer
.c_str(), EncodingBuffer
.size());
415 EncodingBuffer
.resize(0);
422 std::unique_ptr
<MCRegisterInfo
> MRI
;
423 std::unique_ptr
<MCAsmInfo
> MAI
;
424 std::unique_ptr
<MCContext
> MC
;
425 std::unique_ptr
<MCSubtargetInfo
> MSTI
;
428 } // end of namespace parallel
429 } // end of namespace dwarf_linker
430 } // end of namespace llvm
432 #endif // LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H