1 //=== DIEAttributeCloner.cpp ----------------------------------------------===//
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 #include "DIEAttributeCloner.h"
10 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
13 using namespace dwarf_linker
;
14 using namespace dwarf_linker::parallel
;
16 void DIEAttributeCloner::clone() {
17 // Extract and clone every attribute.
18 DWARFDataExtractor Data
= InUnit
.getOrigUnit().getDebugInfoExtractor();
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();
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
));
33 DWARFDataExtractor(DIECopy
, Data
.isLittleEndian(), Data
.getAddressSize());
35 // Modify the copy with relocated addresses.
36 InUnit
.getContaingFile().Addresses
->applyValidRelocs(DIECopy
, Offset
,
37 Data
.isLittleEndian());
39 // Reset the Offset to 0 as we will be working on the local copy of
43 const auto *Abbrev
= InputDieEntry
->getAbbreviationDeclarationPtr();
44 Offset
+= getULEB128Size(Abbrev
->getCode());
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());
56 DWARFFormValue Val
= AttrSpec
.getFormValue();
57 Val
.extractValue(Data
, &Offset
, InUnit
.getFormParams(),
58 &InUnit
.getOrigUnit());
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
);
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
);
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
);
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
);
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
);
110 InUnit
.warn("unsupported attribute form " +
111 dwarf::FormEncodingString(AttrSpec
.Form
) +
112 " in DieAttributeCloner::clone(). Dropping.",
117 // We convert source strings into the indexed form for DWARFv5.
118 // Check if original compile unit already has DW_AT_str_offsets_base
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
),
131 .addScalarAttribute(dwarf::DW_AT_str_offsets_base
,
132 dwarf::DW_FORM_sec_offset
,
133 OutUnit
->getDebugStrOffsetsHeaderSize())
138 bool DIEAttributeCloner::shouldSkipAttribute(
139 DWARFAbbreviationDeclaration::AttributeSpec AttrSpec
) {
140 switch (AttrSpec
.Attr
) {
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
)
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
)
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();
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();
182 size_t DIEAttributeCloner::cloneStringAttr(
183 const DWARFFormValue
&Val
,
184 const DWARFAbbreviationDeclaration::AttributeSpec
&AttrSpec
) {
185 std::optional
<const char *> String
= dwarf::toString(Val
);
187 InUnit
.warn("cann't read string attribute.");
191 StringEntry
*StringInPool
=
192 InUnit
.getGlobalData().getStringPool().insert(*String
).first
;
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
;
201 if (AttrSpec
.Form
== dwarf::DW_FORM_line_strp
) {
202 if (OutUnit
.isTypeUnit()) {
203 DebugInfoOutputSection
.notePatch(DebugTypeLineStrPatch
{
204 AttrOutOffset
, OutDIE
, InUnit
.getDieTypeEntry(InputDIEIdx
),
207 DebugInfoOutputSection
.notePatchWithOffsetUpdate(
208 DebugLineStrPatch
{{AttrOutOffset
}, StringInPool
}, PatchesOffsets
);
211 .addStringPlaceholderAttribute(AttrSpec
.Attr
, dwarf::DW_FORM_line_strp
)
215 if (Use_DW_FORM_strp
) {
216 if (OutUnit
.isTypeUnit()) {
217 DebugInfoOutputSection
.notePatch(
218 DebugTypeStrPatch
{AttrOutOffset
, OutDIE
,
219 InUnit
.getDieTypeEntry(InputDIEIdx
), StringInPool
});
221 DebugInfoOutputSection
.notePatchWithOffsetUpdate(
222 DebugStrPatch
{{AttrOutOffset
}, StringInPool
}, PatchesOffsets
);
226 .addStringPlaceholderAttribute(AttrSpec
.Attr
, dwarf::DW_FORM_strp
)
231 .addIndexedStringAttribute(AttrSpec
.Attr
, dwarf::DW_FORM_strx
,
232 OutUnit
->getDebugStrIndex(StringInPool
))
236 size_t DIEAttributeCloner::cloneDieRefAttr(
237 const DWARFFormValue
&Val
,
238 const DWARFAbbreviationDeclaration::AttributeSpec
&AttrSpec
) {
239 if (AttrSpec
.Attr
== dwarf::DW_AT_sibling
)
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
);
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
);
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");
261 DebugInfoOutputSection
.notePatch(DebugType2TypeDieRefPatch
{
262 AttrOutOffset
, OutDIE
, InUnit
.getDieTypeEntry(InputDIEIdx
),
266 .addScalarAttribute(AttrSpec
.Attr
, dwarf::DW_FORM_ref4
, 0xBADDEF)
271 DebugInfoOutputSection
.notePatchWithOffsetUpdate(
272 DebugDieTypeRefPatch
{AttrOutOffset
, RefTypeName
}, PatchesOffsets
);
275 .addScalarAttribute(AttrSpec
.Attr
, dwarf::DW_FORM_ref_addr
, 0xBADDEF)
279 // Get output offset for referenced DIE.
280 uint64_t OutDieOffset
= RefDiePair
->CU
->getDieOutOffset(RefDiePair
->DieEntry
);
282 // Examine whether referenced DIE is in current compile unit.
283 bool IsLocal
= OutUnit
->getUniqueID() == RefDiePair
->CU
->getUniqueID();
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
;
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
)
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(),
299 RefDiePair
->CU
->getDIEIndex(RefDiePair
->DieEntry
)},
301 return Generator
.addScalarAttribute(AttrSpec
.Attr
, NewForm
, 0xBADDEF).second
;
304 size_t DIEAttributeCloner::cloneScalarAttr(
305 const DWARFFormValue
&Val
,
306 const DWARFAbbreviationDeclaration::AttributeSpec
&AttrSpec
) {
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
))
319 DebugInfoOutputSection
.notePatchWithOffsetUpdate(
320 DebugOffsetPatch
{AttrOutOffset
,
321 &OutUnit
->getOrCreateSectionDescriptor(
322 DebugSectionKind::DebugMacinfo
)},
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
))
333 DebugInfoOutputSection
.notePatchWithOffsetUpdate(
334 DebugOffsetPatch
{AttrOutOffset
,
335 &OutUnit
->getOrCreateSectionDescriptor(
336 DebugSectionKind::DebugMacro
)},
340 case dwarf::DW_AT_stmt_list
: {
341 DebugInfoOutputSection
.notePatchWithOffsetUpdate(
342 DebugOffsetPatch
{AttrOutOffset
, &OutUnit
->getOrCreateSectionDescriptor(
343 DebugSectionKind::DebugLine
)},
346 case dwarf::DW_AT_str_offsets_base
: {
347 DebugInfoOutputSection
.notePatchWithOffsetUpdate(
348 DebugOffsetPatch
{AttrOutOffset
,
349 &OutUnit
->getOrCreateSectionDescriptor(
350 DebugSectionKind::DebugStrOffsets
),
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;
358 .addScalarAttribute(AttrSpec
.Attr
, AttrSpec
.Form
,
359 OutUnit
->getDebugStrOffsetsHeaderSize())
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
368 if (OutUnit
.isTypeUnit()) {
369 if (std::optional
<std::pair
<StringRef
, StringRef
>> DirAndFilename
=
370 InUnit
.getDirAndFilenameFromLineTable(Val
))
371 DebugInfoOutputSection
.notePatch(DebugTypeDeclFilePatch
{
373 InUnit
.getDieTypeEntry(InputDIEIdx
),
374 OutUnit
->getGlobalData()
376 .insert(DirAndFilename
->first
)
378 OutUnit
->getGlobalData()
380 .insert(DirAndFilename
->second
)
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;
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
;
404 InUnit
.warn("unsupported scalar attribute form. Dropping attribute.",
409 if (AttrSpec
.Attr
== dwarf::DW_AT_declaration
&& Value
)
410 AttrInfo
.IsDeclaration
= true;
412 if (AttrSpec
.Form
== dwarf::DW_FORM_loclistx
)
413 return Generator
.addLocListAttribute(AttrSpec
.Attr
, AttrSpec
.Form
, Value
)
416 return Generator
.addScalarAttribute(AttrSpec
.Attr
, AttrSpec
.Form
, Value
)
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();
427 InUnit
.warn("cann't read the attribute. Dropping.", InputDieEntry
);
430 std::optional
<uint64_t> Offset
=
431 InUnit
.getOrigUnit().getRnglistOffset(*Index
);
433 InUnit
.warn("cann't read the attribute. Dropping.", InputDieEntry
);
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();
445 InUnit
.warn("cann't read the attribute. Dropping.", InputDieEntry
);
448 std::optional
<uint64_t> Offset
=
449 InUnit
.getOrigUnit().getLoclistOffset(*Index
);
451 InUnit
.warn("cann't read the attribute. Dropping.", InputDieEntry
);
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())
462 std::optional
<uint64_t> LowPC
= OutUnit
.getAsCompileUnit()->getLowPc();
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
;
474 InUnit
.warn("unsupported scalar attribute form. Dropping attribute.",
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
},
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
;
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(
504 &OutUnit
->getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr
),
508 // Use size of .debug_addr header as attribute value. The offset to
509 // .debug_addr would be added later while patching.
511 .addScalarAttribute(AttrSpec
.Attr
, AttrSpec
.Form
,
512 OutUnit
->getDebugAddrHeaderSize())
514 } else if (AttrSpec
.Attr
== dwarf::DW_AT_declaration
&& Value
)
515 AttrInfo
.IsDeclaration
= true;
517 return Generator
.addScalarAttribute(AttrSpec
.Attr
, ResultingForm
, Value
)
521 size_t DIEAttributeCloner::cloneBlockAttr(
522 const DWARFFormValue
&Val
,
523 const DWARFAbbreviationDeclaration::AttributeSpec
&AttrSpec
) {
525 if (OutUnit
.isTypeUnit())
528 size_t NumberOfPatchesAtStart
= PatchesOffsets
.size();
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
);
543 InUnit
.cloneDieAttrExpression(Expr
, Buffer
, DebugInfoOutputSection
,
544 VarAddressAdjustment
, PatchesOffsets
);
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
;
556 size_t FinalAttributeSize
;
557 if (AttrSpec
.Form
== dwarf::DW_FORM_exprloc
)
559 Generator
.addLocationAttribute(AttrSpec
.Attr
, ResultForm
, Bytes
).second
;
562 Generator
.addBlockAttribute(AttrSpec
.Attr
, ResultForm
, Bytes
).second
;
564 // Update patches offsets with the size of length field for Bytes.
565 for (size_t Idx
= NumberOfPatchesAtStart
; Idx
< PatchesOffsets
.size();
567 assert(FinalAttributeSize
> Bytes
.size());
568 *PatchesOffsets
[Idx
] +=
569 (AttrOutOffset
+ (FinalAttributeSize
- Bytes
.size()));
572 if (HasLocationExpressionAddress
)
573 AttrInfo
.HasLiveAddress
=
574 VarAddressAdjustment
.has_value() ||
575 InUnit
.getGlobalData().getOptions().UpdateIndexTablesOnly
;
577 return FinalAttributeSize
;
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;
586 if (InUnit
.getGlobalData().getOptions().UpdateIndexTablesOnly
)
588 .addScalarAttribute(AttrSpec
.Attr
, AttrSpec
.Form
, Val
.getRawUValue())
591 if (OutUnit
.isTypeUnit())
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.
606 std::optional
<DWARFFormValue
> AddrAttribute
=
607 InUnit
.find(InputDieEntry
, AttrSpec
.Attr
);
609 llvm_unreachable("Cann't find attribute");
611 std::optional
<uint64_t> Addr
= AddrAttribute
->getAsAddress();
613 InUnit
.warn("cann't read address attribute value.");
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())
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())
630 if (VarAddressAdjustment
)
631 *Addr
+= *VarAddressAdjustment
;
632 else if (FuncAddressAdjustment
)
633 *Addr
+= *FuncAddressAdjustment
;
636 if (AttrSpec
.Form
== dwarf::DW_FORM_addr
) {
637 return Generator
.addScalarAttribute(AttrSpec
.Attr
, AttrSpec
.Form
, *Addr
)
642 .addScalarAttribute(AttrSpec
.Attr
, dwarf::Form::DW_FORM_addrx
,
643 OutUnit
.getAsCompileUnit()->getDebugAddrIndex(*Addr
))
647 unsigned DIEAttributeCloner::finalizeAbbreviations(bool HasChildrenToClone
) {
648 // Add the size of the abbreviation number to the output offset.
650 Generator
.finalizeAbbreviations(HasChildrenToClone
, &PatchesOffsets
);
652 return AttrOutOffset
;