Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DebugLineSectionEmitter.h
35292 views
1
//===- DebugLineSectionEmitter.h --------------------------------*- C++ -*-===//
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
#ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H
10
#define LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H
11
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"
18
19
namespace llvm {
20
namespace dwarf_linker {
21
namespace parallel {
22
23
/// This class emits specified line table into the .debug_line section.
24
class DebugLineSectionEmitter {
25
public:
26
DebugLineSectionEmitter(const Triple &TheTriple, DwarfUnit &U)
27
: TheTriple(TheTriple), U(U) {}
28
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
32
// some MC* classes.
33
if (Error Err = init(TheTriple))
34
return Err;
35
36
// Get descriptor for output .debug_line section.
37
SectionDescriptor &OutSection =
38
U.getOrCreateSectionDescriptor(DebugSectionKind::DebugLine);
39
40
// unit_length.
41
OutSection.emitUnitLength(0xBADDEF);
42
uint64_t OffsetAfterUnitLength = OutSection.OS.tell();
43
44
// Emit prologue.
45
emitLineTablePrologue(LineTable.Prologue, OutSection);
46
47
// Emit rows.
48
emitLineTableRows(LineTable, OutSection);
49
uint64_t OffsetAfterEnd = OutSection.OS.tell();
50
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);
59
60
return Error::success();
61
}
62
63
private:
64
Error init(Triple TheTriple) {
65
std::string ErrorStr;
66
std::string TripleName;
67
68
// Get the target.
69
const Target *TheTarget =
70
TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
71
if (!TheTarget)
72
return createStringError(std::errc::invalid_argument, ErrorStr.c_str());
73
TripleName = TheTriple.getTriple();
74
75
// Create all the MC Objects.
76
MRI.reset(TheTarget->createMCRegInfo(TripleName));
77
if (!MRI)
78
return createStringError(std::errc::invalid_argument,
79
"no register info for target %s",
80
TripleName.c_str());
81
82
MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
83
MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
84
if (!MAI)
85
return createStringError(std::errc::invalid_argument,
86
"no asm info for target %s", TripleName.c_str());
87
88
MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
89
if (!MSTI)
90
return createStringError(std::errc::invalid_argument,
91
"no subtarget info for target %s",
92
TripleName.c_str());
93
94
MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,
95
nullptr, true, "__DWARF"));
96
97
return Error::success();
98
}
99
100
void emitLineTablePrologue(const DWARFDebugLine::Prologue &P,
101
SectionDescriptor &Section) {
102
// version (uhalf).
103
Section.emitIntVal(P.getVersion(), 2);
104
if (P.getVersion() == 5) {
105
// address_size (ubyte).
106
Section.emitIntVal(P.getAddressSize(), 1);
107
108
// segment_selector_size (ubyte).
109
Section.emitIntVal(P.SegSelectorSize, 1);
110
}
111
112
// header_length.
113
Section.emitOffset(0xBADDEF);
114
115
uint64_t OffsetAfterPrologueLength = Section.OS.tell();
116
emitLineTableProloguePayload(P, Section);
117
uint64_t OffsetAfterPrologueEnd = Section.OS.tell();
118
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);
124
}
125
126
void
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);
132
if (!IncludeStr) {
133
U.warn("cann't read string from line table.");
134
return;
135
}
136
137
Section.emitString(Include.getForm(), *IncludeStr);
138
}
139
// The last entry is followed by a single null byte.
140
Section.emitIntVal(0, 1);
141
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);
145
if (!FileNameStr) {
146
U.warn("cann't read string from line table.");
147
return;
148
}
149
150
// A null-terminated string containing the full or relative path name of a
151
// source file.
152
Section.emitString(File.Name.getForm(), *FileNameStr);
153
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);
163
}
164
// The last entry is followed by a single null byte.
165
Section.emitIntVal(0, 1);
166
}
167
168
void
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);
174
} else {
175
// directory_entry_format_count(ubyte).
176
Section.emitIntVal(1, 1);
177
178
// directory_entry_format (sequence of ULEB128 pairs).
179
encodeULEB128(dwarf::DW_LNCT_path, Section.OS);
180
encodeULEB128(P.IncludeDirectories[0].getForm(), Section.OS);
181
}
182
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);
188
if (!IncludeStr) {
189
U.warn("cann't read string from line table.");
190
return;
191
}
192
193
Section.emitString(Include.getForm(), *IncludeStr);
194
}
195
196
bool HasChecksums = P.ContentTypes.HasMD5;
197
bool HasInlineSources = P.ContentTypes.HasSource;
198
199
dwarf::Form FileNameForm = dwarf::DW_FORM_string;
200
dwarf::Form LLVMSourceForm = dwarf::DW_FORM_string;
201
202
if (P.FileNames.empty()) {
203
// file_name_entry_format_count (ubyte).
204
Section.emitIntVal(0, 1);
205
} else {
206
FileNameForm = P.FileNames[0].Name.getForm();
207
LLVMSourceForm = P.FileNames[0].Source.getForm();
208
209
// file_name_entry_format_count (ubyte).
210
Section.emitIntVal(
211
2 + (HasChecksums ? 1 : 0) + (HasInlineSources ? 1 : 0), 1);
212
213
// file_name_entry_format (sequence of ULEB128 pairs).
214
encodeULEB128(dwarf::DW_LNCT_path, Section.OS);
215
encodeULEB128(FileNameForm, Section.OS);
216
217
encodeULEB128(dwarf::DW_LNCT_directory_index, Section.OS);
218
encodeULEB128(dwarf::DW_FORM_data1, Section.OS);
219
220
if (HasChecksums) {
221
encodeULEB128(dwarf::DW_LNCT_MD5, Section.OS);
222
encodeULEB128(dwarf::DW_FORM_data16, Section.OS);
223
}
224
225
if (HasInlineSources) {
226
encodeULEB128(dwarf::DW_LNCT_LLVM_source, Section.OS);
227
encodeULEB128(LLVMSourceForm, Section.OS);
228
}
229
}
230
231
// file_names_count (ULEB128).
232
encodeULEB128(P.FileNames.size(), Section.OS);
233
234
// file_names (sequence of file name entries).
235
for (auto File : P.FileNames) {
236
std::optional<const char *> FileNameStr = dwarf::toString(File.Name);
237
if (!FileNameStr) {
238
U.warn("cann't read string from line table.");
239
return;
240
}
241
242
// A null-terminated string containing the full or relative path name of a
243
// source file.
244
Section.emitString(FileNameForm, *FileNameStr);
245
Section.emitIntVal(File.DirIdx, 1);
246
247
if (HasChecksums) {
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()));
253
}
254
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.");
260
return;
261
}
262
263
Section.emitString(LLVMSourceForm, *FileSourceStr);
264
}
265
}
266
}
267
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);
275
}
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);
284
285
// standard_opcode_lengths (array of ubyte).
286
for (auto Length : P.StandardOpcodeLengths)
287
Section.emitIntVal(Length, 1);
288
289
if (P.FormParams.Version < 5)
290
emitLineTablePrologueV2IncludeAndFileTable(P, Section);
291
else
292
emitLineTablePrologueV5IncludeAndFileTable(P, Section);
293
}
294
295
void emitLineTableRows(const DWARFDebugLine::LineTable &LineTable,
296
SectionDescriptor &Section) {
297
298
MCDwarfLineTableParams Params;
299
Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase;
300
Params.DWARF2LineBase = LineTable.Prologue.LineBase;
301
Params.DWARF2LineRange = LineTable.Prologue.LineRange;
302
303
SmallString<128> EncodingBuffer;
304
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(),
309
0, EncodingBuffer);
310
Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size());
311
return;
312
}
313
314
// Line table state machine fields
315
unsigned FileNum = 1;
316
unsigned LastLine = 1;
317
unsigned Column = 0;
318
unsigned Discriminator = 0;
319
unsigned IsStatement = 1;
320
unsigned Isa = 0;
321
uint64_t Address = -1ULL;
322
323
unsigned RowsSinceLastSequence = 0;
324
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);
333
AddressDelta = 0;
334
} else {
335
AddressDelta =
336
(Row.Address.Address - Address) / LineTable.Prologue.MinInstLength;
337
}
338
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.
343
344
if (FileNum != Row.File) {
345
FileNum = Row.File;
346
Section.emitIntVal(dwarf::DW_LNS_set_file, 1);
347
encodeULEB128(FileNum, Section.OS);
348
}
349
if (Column != Row.Column) {
350
Column = Row.Column;
351
Section.emitIntVal(dwarf::DW_LNS_set_column, 1);
352
encodeULEB128(Column, Section.OS);
353
}
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);
361
}
362
Discriminator = 0;
363
364
if (Isa != Row.Isa) {
365
Isa = Row.Isa;
366
Section.emitIntVal(dwarf::DW_LNS_set_isa, 1);
367
encodeULEB128(Isa, Section.OS);
368
}
369
if (IsStatement != Row.IsStmt) {
370
IsStatement = Row.IsStmt;
371
Section.emitIntVal(dwarf::DW_LNS_negate_stmt, 1);
372
}
373
if (Row.BasicBlock)
374
Section.emitIntVal(dwarf::DW_LNS_set_basic_block, 1);
375
376
if (Row.PrologueEnd)
377
Section.emitIntVal(dwarf::DW_LNS_set_prologue_end, 1);
378
379
if (Row.EpilogueBegin)
380
Section.emitIntVal(dwarf::DW_LNS_set_epilogue_begin, 1);
381
382
int64_t LineDelta = int64_t(Row.Line) - LastLine;
383
if (!Row.EndSequence) {
384
MCDwarfLineAddr::encode(*MC, Params, LineDelta, AddressDelta,
385
EncodingBuffer);
386
Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size());
387
EncodingBuffer.resize(0);
388
Address = Row.Address.Address;
389
LastLine = Row.Line;
390
RowsSinceLastSequence++;
391
} else {
392
if (LineDelta) {
393
Section.emitIntVal(dwarf::DW_LNS_advance_line, 1);
394
encodeSLEB128(LineDelta, Section.OS);
395
}
396
if (AddressDelta) {
397
Section.emitIntVal(dwarf::DW_LNS_advance_pc, 1);
398
encodeULEB128(AddressDelta, Section.OS);
399
}
400
MCDwarfLineAddr::encode(*MC, Params,
401
std::numeric_limits<int64_t>::max(), 0,
402
EncodingBuffer);
403
Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size());
404
EncodingBuffer.resize(0);
405
Address = -1ULL;
406
LastLine = FileNum = IsStatement = 1;
407
RowsSinceLastSequence = Column = Discriminator = Isa = 0;
408
}
409
}
410
411
if (RowsSinceLastSequence) {
412
MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(),
413
0, EncodingBuffer);
414
Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size());
415
EncodingBuffer.resize(0);
416
}
417
}
418
419
Triple TheTriple;
420
DwarfUnit &U;
421
422
std::unique_ptr<MCRegisterInfo> MRI;
423
std::unique_ptr<MCAsmInfo> MAI;
424
std::unique_ptr<MCContext> MC;
425
std::unique_ptr<MCSubtargetInfo> MSTI;
426
};
427
428
} // end of namespace parallel
429
} // end of namespace dwarf_linker
430
} // end of namespace llvm
431
432
#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H
433
434