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/DIEAttributeCloner.cpp
35292 views
1
//=== DIEAttributeCloner.cpp ----------------------------------------------===//
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
#include "DIEAttributeCloner.h"
10
#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
11
12
using namespace llvm;
13
using namespace dwarf_linker;
14
using namespace dwarf_linker::parallel;
15
16
void DIEAttributeCloner::clone() {
17
// Extract and clone every attribute.
18
DWARFDataExtractor Data = InUnit.getOrigUnit().getDebugInfoExtractor();
19
20
uint64_t Offset = InputDieEntry->getOffset();
21
// Point to the next DIE (generally there is always at least a NULL
22
// entry after the current one). If this is a lone
23
// DW_TAG_compile_unit without any children, point to the next unit.
24
uint64_t NextOffset = (InputDIEIdx + 1 < InUnit.getOrigUnit().getNumDIEs())
25
? InUnit.getDIEAtIndex(InputDIEIdx + 1).getOffset()
26
: InUnit.getOrigUnit().getNextUnitOffset();
27
28
// We could copy the data only if we need to apply a relocation to it. After
29
// testing, it seems there is no performance downside to doing the copy
30
// unconditionally, and it makes the code simpler.
31
SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset));
32
Data =
33
DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize());
34
35
// Modify the copy with relocated addresses.
36
InUnit.getContaingFile().Addresses->applyValidRelocs(DIECopy, Offset,
37
Data.isLittleEndian());
38
39
// Reset the Offset to 0 as we will be working on the local copy of
40
// the data.
41
Offset = 0;
42
43
const auto *Abbrev = InputDieEntry->getAbbreviationDeclarationPtr();
44
Offset += getULEB128Size(Abbrev->getCode());
45
46
// Set current output offset.
47
AttrOutOffset = OutUnit.isCompileUnit() ? OutDIE->getOffset() : 0;
48
for (const auto &AttrSpec : Abbrev->attributes()) {
49
// Check whether current attribute should be skipped.
50
if (shouldSkipAttribute(AttrSpec)) {
51
DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
52
InUnit.getFormParams());
53
continue;
54
}
55
56
DWARFFormValue Val = AttrSpec.getFormValue();
57
Val.extractValue(Data, &Offset, InUnit.getFormParams(),
58
&InUnit.getOrigUnit());
59
60
// Clone current attribute.
61
switch (AttrSpec.Form) {
62
case dwarf::DW_FORM_strp:
63
case dwarf::DW_FORM_line_strp:
64
case dwarf::DW_FORM_string:
65
case dwarf::DW_FORM_strx:
66
case dwarf::DW_FORM_strx1:
67
case dwarf::DW_FORM_strx2:
68
case dwarf::DW_FORM_strx3:
69
case dwarf::DW_FORM_strx4:
70
AttrOutOffset += cloneStringAttr(Val, AttrSpec);
71
break;
72
case dwarf::DW_FORM_ref_addr:
73
case dwarf::DW_FORM_ref1:
74
case dwarf::DW_FORM_ref2:
75
case dwarf::DW_FORM_ref4:
76
case dwarf::DW_FORM_ref8:
77
case dwarf::DW_FORM_ref_udata:
78
AttrOutOffset += cloneDieRefAttr(Val, AttrSpec);
79
break;
80
case dwarf::DW_FORM_data1:
81
case dwarf::DW_FORM_data2:
82
case dwarf::DW_FORM_data4:
83
case dwarf::DW_FORM_data8:
84
case dwarf::DW_FORM_udata:
85
case dwarf::DW_FORM_sdata:
86
case dwarf::DW_FORM_sec_offset:
87
case dwarf::DW_FORM_flag:
88
case dwarf::DW_FORM_flag_present:
89
case dwarf::DW_FORM_rnglistx:
90
case dwarf::DW_FORM_loclistx:
91
case dwarf::DW_FORM_implicit_const:
92
AttrOutOffset += cloneScalarAttr(Val, AttrSpec);
93
break;
94
case dwarf::DW_FORM_block:
95
case dwarf::DW_FORM_block1:
96
case dwarf::DW_FORM_block2:
97
case dwarf::DW_FORM_block4:
98
case dwarf::DW_FORM_exprloc:
99
AttrOutOffset += cloneBlockAttr(Val, AttrSpec);
100
break;
101
case dwarf::DW_FORM_addr:
102
case dwarf::DW_FORM_addrx:
103
case dwarf::DW_FORM_addrx1:
104
case dwarf::DW_FORM_addrx2:
105
case dwarf::DW_FORM_addrx3:
106
case dwarf::DW_FORM_addrx4:
107
AttrOutOffset += cloneAddressAttr(Val, AttrSpec);
108
break;
109
default:
110
InUnit.warn("unsupported attribute form " +
111
dwarf::FormEncodingString(AttrSpec.Form) +
112
" in DieAttributeCloner::clone(). Dropping.",
113
InputDieEntry);
114
}
115
}
116
117
// We convert source strings into the indexed form for DWARFv5.
118
// Check if original compile unit already has DW_AT_str_offsets_base
119
// attribute.
120
if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
121
InUnit.getVersion() >= 5 && !AttrInfo.HasStringOffsetBaseAttr) {
122
DebugInfoOutputSection.notePatchWithOffsetUpdate(
123
DebugOffsetPatch{AttrOutOffset,
124
&OutUnit->getOrCreateSectionDescriptor(
125
DebugSectionKind::DebugStrOffsets),
126
true},
127
PatchesOffsets);
128
129
AttrOutOffset +=
130
Generator
131
.addScalarAttribute(dwarf::DW_AT_str_offsets_base,
132
dwarf::DW_FORM_sec_offset,
133
OutUnit->getDebugStrOffsetsHeaderSize())
134
.second;
135
}
136
}
137
138
bool DIEAttributeCloner::shouldSkipAttribute(
139
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec) {
140
switch (AttrSpec.Attr) {
141
default:
142
return false;
143
case dwarf::DW_AT_low_pc:
144
case dwarf::DW_AT_high_pc:
145
case dwarf::DW_AT_ranges:
146
if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
147
return false;
148
149
// Skip address attribute if we are in function scope and function does not
150
// reference live address.
151
return InUnit.getDIEInfo(InputDIEIdx).getIsInFunctionScope() &&
152
!FuncAddressAdjustment.has_value();
153
case dwarf::DW_AT_rnglists_base:
154
// In case !Update the .debug_addr table is not generated/preserved.
155
// Thus instead of DW_FORM_rnglistx the DW_FORM_sec_offset is used.
156
// Since DW_AT_rnglists_base is used for only DW_FORM_rnglistx the
157
// DW_AT_rnglists_base is removed.
158
return !InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
159
case dwarf::DW_AT_loclists_base:
160
// In case !Update the .debug_addr table is not generated/preserved.
161
// Thus instead of DW_FORM_loclistx the DW_FORM_sec_offset is used.
162
// Since DW_AT_loclists_base is used for only DW_FORM_loclistx the
163
// DW_AT_loclists_base is removed.
164
return !InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
165
case dwarf::DW_AT_location:
166
case dwarf::DW_AT_frame_base:
167
if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
168
return false;
169
170
// When location expression contains an address: skip this attribute
171
// if it does not reference live address.
172
if (HasLocationExpressionAddress)
173
return !VarAddressAdjustment.has_value();
174
175
// Skip location attribute if we are in function scope and function does not
176
// reference live address.
177
return InUnit.getDIEInfo(InputDIEIdx).getIsInFunctionScope() &&
178
!FuncAddressAdjustment.has_value();
179
}
180
}
181
182
size_t DIEAttributeCloner::cloneStringAttr(
183
const DWARFFormValue &Val,
184
const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {
185
std::optional<const char *> String = dwarf::toString(Val);
186
if (!String) {
187
InUnit.warn("cann't read string attribute.");
188
return 0;
189
}
190
191
StringEntry *StringInPool =
192
InUnit.getGlobalData().getStringPool().insert(*String).first;
193
194
// Update attributes info.
195
if (AttrSpec.Attr == dwarf::DW_AT_name)
196
AttrInfo.Name = StringInPool;
197
else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||
198
AttrSpec.Attr == dwarf::DW_AT_linkage_name)
199
AttrInfo.MangledName = StringInPool;
200
201
if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {
202
if (OutUnit.isTypeUnit()) {
203
DebugInfoOutputSection.notePatch(DebugTypeLineStrPatch{
204
AttrOutOffset, OutDIE, InUnit.getDieTypeEntry(InputDIEIdx),
205
StringInPool});
206
} else {
207
DebugInfoOutputSection.notePatchWithOffsetUpdate(
208
DebugLineStrPatch{{AttrOutOffset}, StringInPool}, PatchesOffsets);
209
}
210
return Generator
211
.addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_line_strp)
212
.second;
213
}
214
215
if (Use_DW_FORM_strp) {
216
if (OutUnit.isTypeUnit()) {
217
DebugInfoOutputSection.notePatch(
218
DebugTypeStrPatch{AttrOutOffset, OutDIE,
219
InUnit.getDieTypeEntry(InputDIEIdx), StringInPool});
220
} else {
221
DebugInfoOutputSection.notePatchWithOffsetUpdate(
222
DebugStrPatch{{AttrOutOffset}, StringInPool}, PatchesOffsets);
223
}
224
225
return Generator
226
.addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_strp)
227
.second;
228
}
229
230
return Generator
231
.addIndexedStringAttribute(AttrSpec.Attr, dwarf::DW_FORM_strx,
232
OutUnit->getDebugStrIndex(StringInPool))
233
.second;
234
}
235
236
size_t DIEAttributeCloner::cloneDieRefAttr(
237
const DWARFFormValue &Val,
238
const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {
239
if (AttrSpec.Attr == dwarf::DW_AT_sibling)
240
return 0;
241
242
std::optional<UnitEntryPairTy> RefDiePair =
243
InUnit.resolveDIEReference(Val, ResolveInterCUReferencesMode::Resolve);
244
if (!RefDiePair || !RefDiePair->DieEntry) {
245
// If the referenced DIE is not found, drop the attribute.
246
InUnit.warn("cann't find referenced DIE.", InputDieEntry);
247
return 0;
248
}
249
250
TypeEntry *RefTypeName = nullptr;
251
const CompileUnit::DIEInfo &RefDIEInfo =
252
RefDiePair->CU->getDIEInfo(RefDiePair->DieEntry);
253
if (RefDIEInfo.needToPlaceInTypeTable())
254
RefTypeName = RefDiePair->CU->getDieTypeEntry(RefDiePair->DieEntry);
255
256
if (OutUnit.isTypeUnit()) {
257
assert(RefTypeName && "Type name for referenced DIE is not set");
258
assert(InUnit.getDieTypeEntry(InputDIEIdx) &&
259
"Type name for DIE is not set");
260
261
DebugInfoOutputSection.notePatch(DebugType2TypeDieRefPatch{
262
AttrOutOffset, OutDIE, InUnit.getDieTypeEntry(InputDIEIdx),
263
RefTypeName});
264
265
return Generator
266
.addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref4, 0xBADDEF)
267
.second;
268
}
269
270
if (RefTypeName) {
271
DebugInfoOutputSection.notePatchWithOffsetUpdate(
272
DebugDieTypeRefPatch{AttrOutOffset, RefTypeName}, PatchesOffsets);
273
274
return Generator
275
.addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref_addr, 0xBADDEF)
276
.second;
277
}
278
279
// Get output offset for referenced DIE.
280
uint64_t OutDieOffset = RefDiePair->CU->getDieOutOffset(RefDiePair->DieEntry);
281
282
// Examine whether referenced DIE is in current compile unit.
283
bool IsLocal = OutUnit->getUniqueID() == RefDiePair->CU->getUniqueID();
284
285
// Set attribute form basing on the kind of referenced DIE(local or not?).
286
dwarf::Form NewForm = IsLocal ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr;
287
288
// Check whether current attribute references already cloned DIE inside
289
// the same compilation unit. If true - write the already known offset value.
290
if (IsLocal && (OutDieOffset != 0))
291
return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, OutDieOffset)
292
.second;
293
294
// If offset value is not known at this point then create patch for the
295
// reference value and write dummy value into the attribute.
296
DebugInfoOutputSection.notePatchWithOffsetUpdate(
297
DebugDieRefPatch{AttrOutOffset, OutUnit.getAsCompileUnit(),
298
RefDiePair->CU,
299
RefDiePair->CU->getDIEIndex(RefDiePair->DieEntry)},
300
PatchesOffsets);
301
return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, 0xBADDEF).second;
302
}
303
304
size_t DIEAttributeCloner::cloneScalarAttr(
305
const DWARFFormValue &Val,
306
const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {
307
308
// Create patches for attribute referencing other non invariant section.
309
// Invariant section could not be updated here as this section and
310
// reference to it do not change value in case --update.
311
switch (AttrSpec.Attr) {
312
case dwarf::DW_AT_macro_info: {
313
if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {
314
const DWARFDebugMacro *Macro =
315
InUnit.getContaingFile().Dwarf->getDebugMacinfo();
316
if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset))
317
return 0;
318
319
DebugInfoOutputSection.notePatchWithOffsetUpdate(
320
DebugOffsetPatch{AttrOutOffset,
321
&OutUnit->getOrCreateSectionDescriptor(
322
DebugSectionKind::DebugMacinfo)},
323
PatchesOffsets);
324
}
325
} break;
326
case dwarf::DW_AT_macros: {
327
if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {
328
const DWARFDebugMacro *Macro =
329
InUnit.getContaingFile().Dwarf->getDebugMacro();
330
if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset))
331
return 0;
332
333
DebugInfoOutputSection.notePatchWithOffsetUpdate(
334
DebugOffsetPatch{AttrOutOffset,
335
&OutUnit->getOrCreateSectionDescriptor(
336
DebugSectionKind::DebugMacro)},
337
PatchesOffsets);
338
}
339
} break;
340
case dwarf::DW_AT_stmt_list: {
341
DebugInfoOutputSection.notePatchWithOffsetUpdate(
342
DebugOffsetPatch{AttrOutOffset, &OutUnit->getOrCreateSectionDescriptor(
343
DebugSectionKind::DebugLine)},
344
PatchesOffsets);
345
} break;
346
case dwarf::DW_AT_str_offsets_base: {
347
DebugInfoOutputSection.notePatchWithOffsetUpdate(
348
DebugOffsetPatch{AttrOutOffset,
349
&OutUnit->getOrCreateSectionDescriptor(
350
DebugSectionKind::DebugStrOffsets),
351
true},
352
PatchesOffsets);
353
354
// Use size of .debug_str_offsets header as attribute value. The offset
355
// to .debug_str_offsets would be added later while patching.
356
AttrInfo.HasStringOffsetBaseAttr = true;
357
return Generator
358
.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form,
359
OutUnit->getDebugStrOffsetsHeaderSize())
360
.second;
361
} break;
362
case dwarf::DW_AT_decl_file: {
363
// Value of DW_AT_decl_file may exceed original form. Longer
364
// form can affect offsets to the following attributes. To not
365
// update offsets of the following attributes we always remove
366
// original DW_AT_decl_file and attach it to the last position
367
// later.
368
if (OutUnit.isTypeUnit()) {
369
if (std::optional<std::pair<StringRef, StringRef>> DirAndFilename =
370
InUnit.getDirAndFilenameFromLineTable(Val))
371
DebugInfoOutputSection.notePatch(DebugTypeDeclFilePatch{
372
OutDIE,
373
InUnit.getDieTypeEntry(InputDIEIdx),
374
OutUnit->getGlobalData()
375
.getStringPool()
376
.insert(DirAndFilename->first)
377
.first,
378
OutUnit->getGlobalData()
379
.getStringPool()
380
.insert(DirAndFilename->second)
381
.first,
382
});
383
return 0;
384
}
385
} break;
386
default: {
387
} break;
388
};
389
390
uint64_t Value;
391
if (AttrSpec.Attr == dwarf::DW_AT_const_value &&
392
(InputDieEntry->getTag() == dwarf::DW_TAG_variable ||
393
InputDieEntry->getTag() == dwarf::DW_TAG_constant))
394
AttrInfo.HasLiveAddress = true;
395
396
if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly) {
397
if (auto OptionalValue = Val.getAsUnsignedConstant())
398
Value = *OptionalValue;
399
else if (auto OptionalValue = Val.getAsSignedConstant())
400
Value = *OptionalValue;
401
else if (auto OptionalValue = Val.getAsSectionOffset())
402
Value = *OptionalValue;
403
else {
404
InUnit.warn("unsupported scalar attribute form. Dropping attribute.",
405
InputDieEntry);
406
return 0;
407
}
408
409
if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
410
AttrInfo.IsDeclaration = true;
411
412
if (AttrSpec.Form == dwarf::DW_FORM_loclistx)
413
return Generator.addLocListAttribute(AttrSpec.Attr, AttrSpec.Form, Value)
414
.second;
415
416
return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Value)
417
.second;
418
}
419
420
dwarf::Form ResultingForm = AttrSpec.Form;
421
if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {
422
// DWARFLinker does not generate .debug_addr table. Thus we need to change
423
// all "addrx" related forms to "addr" version. Change DW_FORM_rnglistx
424
// to DW_FORM_sec_offset here.
425
std::optional<uint64_t> Index = Val.getAsSectionOffset();
426
if (!Index) {
427
InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
428
return 0;
429
}
430
std::optional<uint64_t> Offset =
431
InUnit.getOrigUnit().getRnglistOffset(*Index);
432
if (!Offset) {
433
InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
434
return 0;
435
}
436
437
Value = *Offset;
438
ResultingForm = dwarf::DW_FORM_sec_offset;
439
} else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {
440
// DWARFLinker does not generate .debug_addr table. Thus we need to change
441
// all "addrx" related forms to "addr" version. Change DW_FORM_loclistx
442
// to DW_FORM_sec_offset here.
443
std::optional<uint64_t> Index = Val.getAsSectionOffset();
444
if (!Index) {
445
InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
446
return 0;
447
}
448
std::optional<uint64_t> Offset =
449
InUnit.getOrigUnit().getLoclistOffset(*Index);
450
if (!Offset) {
451
InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
452
return 0;
453
}
454
455
Value = *Offset;
456
ResultingForm = dwarf::DW_FORM_sec_offset;
457
} else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
458
InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) {
459
if (!OutUnit.isCompileUnit())
460
return 0;
461
462
std::optional<uint64_t> LowPC = OutUnit.getAsCompileUnit()->getLowPc();
463
if (!LowPC)
464
return 0;
465
// Dwarf >= 4 high_pc is an size, not an address.
466
Value = OutUnit.getAsCompileUnit()->getHighPc() - *LowPC;
467
} else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
468
Value = *Val.getAsSectionOffset();
469
else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
470
Value = *Val.getAsSignedConstant();
471
else if (auto OptionalValue = Val.getAsUnsignedConstant())
472
Value = *OptionalValue;
473
else {
474
InUnit.warn("unsupported scalar attribute form. Dropping attribute.",
475
InputDieEntry);
476
return 0;
477
}
478
479
if (AttrSpec.Attr == dwarf::DW_AT_ranges ||
480
AttrSpec.Attr == dwarf::DW_AT_start_scope) {
481
// Create patch for the range offset value.
482
DebugInfoOutputSection.notePatchWithOffsetUpdate(
483
DebugRangePatch{{AttrOutOffset},
484
InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit},
485
PatchesOffsets);
486
AttrInfo.HasRanges = true;
487
} else if (DWARFAttribute::mayHaveLocationList(AttrSpec.Attr) &&
488
dwarf::doesFormBelongToClass(AttrSpec.Form,
489
DWARFFormValue::FC_SectionOffset,
490
InUnit.getOrigUnit().getVersion())) {
491
int64_t AddrAdjustmentValue = 0;
492
if (VarAddressAdjustment)
493
AddrAdjustmentValue = *VarAddressAdjustment;
494
else if (FuncAddressAdjustment)
495
AddrAdjustmentValue = *FuncAddressAdjustment;
496
497
// Create patch for the location offset value.
498
DebugInfoOutputSection.notePatchWithOffsetUpdate(
499
DebugLocPatch{{AttrOutOffset}, AddrAdjustmentValue}, PatchesOffsets);
500
} else if (AttrSpec.Attr == dwarf::DW_AT_addr_base) {
501
DebugInfoOutputSection.notePatchWithOffsetUpdate(
502
DebugOffsetPatch{
503
AttrOutOffset,
504
&OutUnit->getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr),
505
true},
506
PatchesOffsets);
507
508
// Use size of .debug_addr header as attribute value. The offset to
509
// .debug_addr would be added later while patching.
510
return Generator
511
.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form,
512
OutUnit->getDebugAddrHeaderSize())
513
.second;
514
} else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
515
AttrInfo.IsDeclaration = true;
516
517
return Generator.addScalarAttribute(AttrSpec.Attr, ResultingForm, Value)
518
.second;
519
}
520
521
size_t DIEAttributeCloner::cloneBlockAttr(
522
const DWARFFormValue &Val,
523
const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {
524
525
if (OutUnit.isTypeUnit())
526
return 0;
527
528
size_t NumberOfPatchesAtStart = PatchesOffsets.size();
529
530
// If the block is a DWARF Expression, clone it into the temporary
531
// buffer using cloneExpression(), otherwise copy the data directly.
532
SmallVector<uint8_t, 32> Buffer;
533
ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
534
if (DWARFAttribute::mayHaveLocationExpr(AttrSpec.Attr) &&
535
(Val.isFormClass(DWARFFormValue::FC_Block) ||
536
Val.isFormClass(DWARFFormValue::FC_Exprloc))) {
537
DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()),
538
InUnit.getOrigUnit().isLittleEndian(),
539
InUnit.getOrigUnit().getAddressByteSize());
540
DWARFExpression Expr(Data, InUnit.getOrigUnit().getAddressByteSize(),
541
InUnit.getFormParams().Format);
542
543
InUnit.cloneDieAttrExpression(Expr, Buffer, DebugInfoOutputSection,
544
VarAddressAdjustment, PatchesOffsets);
545
Bytes = Buffer;
546
}
547
548
// The expression location data might be updated and exceed the original size.
549
// Check whether the new data fits into the original form.
550
dwarf::Form ResultForm = AttrSpec.Form;
551
if ((ResultForm == dwarf::DW_FORM_block1 && Bytes.size() > UINT8_MAX) ||
552
(ResultForm == dwarf::DW_FORM_block2 && Bytes.size() > UINT16_MAX) ||
553
(ResultForm == dwarf::DW_FORM_block4 && Bytes.size() > UINT32_MAX))
554
ResultForm = dwarf::DW_FORM_block;
555
556
size_t FinalAttributeSize;
557
if (AttrSpec.Form == dwarf::DW_FORM_exprloc)
558
FinalAttributeSize =
559
Generator.addLocationAttribute(AttrSpec.Attr, ResultForm, Bytes).second;
560
else
561
FinalAttributeSize =
562
Generator.addBlockAttribute(AttrSpec.Attr, ResultForm, Bytes).second;
563
564
// Update patches offsets with the size of length field for Bytes.
565
for (size_t Idx = NumberOfPatchesAtStart; Idx < PatchesOffsets.size();
566
Idx++) {
567
assert(FinalAttributeSize > Bytes.size());
568
*PatchesOffsets[Idx] +=
569
(AttrOutOffset + (FinalAttributeSize - Bytes.size()));
570
}
571
572
if (HasLocationExpressionAddress)
573
AttrInfo.HasLiveAddress =
574
VarAddressAdjustment.has_value() ||
575
InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
576
577
return FinalAttributeSize;
578
}
579
580
size_t DIEAttributeCloner::cloneAddressAttr(
581
const DWARFFormValue &Val,
582
const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {
583
if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
584
AttrInfo.HasLiveAddress = true;
585
586
if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
587
return Generator
588
.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Val.getRawUValue())
589
.second;
590
591
if (OutUnit.isTypeUnit())
592
return 0;
593
594
// Cloned Die may have address attributes relocated to a
595
// totally unrelated value. This can happen:
596
// - If high_pc is an address (Dwarf version == 2), then it might have been
597
// relocated to a totally unrelated value (because the end address in the
598
// object file might be start address of another function which got moved
599
// independently by the linker).
600
// - If address relocated in an inline_subprogram that happens at the
601
// beginning of its inlining function.
602
// To avoid above cases and to not apply relocation twice (in
603
// applyValidRelocs and here), read address attribute from InputDIE and apply
604
// Info.PCOffset here.
605
606
std::optional<DWARFFormValue> AddrAttribute =
607
InUnit.find(InputDieEntry, AttrSpec.Attr);
608
if (!AddrAttribute)
609
llvm_unreachable("Cann't find attribute");
610
611
std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();
612
if (!Addr) {
613
InUnit.warn("cann't read address attribute value.");
614
return 0;
615
}
616
617
if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
618
AttrSpec.Attr == dwarf::DW_AT_low_pc) {
619
if (std::optional<uint64_t> LowPC = OutUnit.getAsCompileUnit()->getLowPc())
620
Addr = *LowPC;
621
else
622
return 0;
623
} else if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
624
AttrSpec.Attr == dwarf::DW_AT_high_pc) {
625
if (uint64_t HighPc = OutUnit.getAsCompileUnit()->getHighPc())
626
Addr = HighPc;
627
else
628
return 0;
629
} else {
630
if (VarAddressAdjustment)
631
*Addr += *VarAddressAdjustment;
632
else if (FuncAddressAdjustment)
633
*Addr += *FuncAddressAdjustment;
634
}
635
636
if (AttrSpec.Form == dwarf::DW_FORM_addr) {
637
return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, *Addr)
638
.second;
639
}
640
641
return Generator
642
.addScalarAttribute(AttrSpec.Attr, dwarf::Form::DW_FORM_addrx,
643
OutUnit.getAsCompileUnit()->getDebugAddrIndex(*Addr))
644
.second;
645
}
646
647
unsigned DIEAttributeCloner::finalizeAbbreviations(bool HasChildrenToClone) {
648
// Add the size of the abbreviation number to the output offset.
649
AttrOutOffset +=
650
Generator.finalizeAbbreviations(HasChildrenToClone, &PatchesOffsets);
651
652
return AttrOutOffset;
653
}
654
655