Revert " [LoongArch][ISel] Check the number of sign bits in `PatGprGpr_32` (#107432)"
[llvm-project.git] / llvm / lib / DWARFLinker / Parallel / DIEAttributeCloner.cpp
blob07ebd55e2c46fe60224f3e9b4da9f1eeeca1684d
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 //===----------------------------------------------------------------------===//
9 #include "DIEAttributeCloner.h"
10 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
12 using namespace llvm;
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));
32 Data =
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
40 // the data.
41 Offset = 0;
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());
53 continue;
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);
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);
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);
129 AttrOutOffset +=
130 Generator
131 .addScalarAttribute(dwarf::DW_AT_str_offsets_base,
132 dwarf::DW_FORM_sec_offset,
133 OutUnit->getDebugStrOffsetsHeaderSize())
134 .second;
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;
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;
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);
186 if (!String) {
187 InUnit.warn("cann't read string attribute.");
188 return 0;
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),
205 StringInPool});
206 } else {
207 DebugInfoOutputSection.notePatchWithOffsetUpdate(
208 DebugLineStrPatch{{AttrOutOffset}, StringInPool}, PatchesOffsets);
210 return Generator
211 .addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_line_strp)
212 .second;
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);
225 return Generator
226 .addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_strp)
227 .second;
230 return Generator
231 .addIndexedStringAttribute(AttrSpec.Attr, dwarf::DW_FORM_strx,
232 OutUnit->getDebugStrIndex(StringInPool))
233 .second;
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;
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;
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),
263 RefTypeName});
265 return Generator
266 .addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref4, 0xBADDEF)
267 .second;
270 if (RefTypeName) {
271 DebugInfoOutputSection.notePatchWithOffsetUpdate(
272 DebugDieTypeRefPatch{AttrOutOffset, RefTypeName}, PatchesOffsets);
274 return Generator
275 .addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref_addr, 0xBADDEF)
276 .second;
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)
292 .second;
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;
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))
317 return 0;
319 DebugInfoOutputSection.notePatchWithOffsetUpdate(
320 DebugOffsetPatch{AttrOutOffset,
321 &OutUnit->getOrCreateSectionDescriptor(
322 DebugSectionKind::DebugMacinfo)},
323 PatchesOffsets);
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;
333 DebugInfoOutputSection.notePatchWithOffsetUpdate(
334 DebugOffsetPatch{AttrOutOffset,
335 &OutUnit->getOrCreateSectionDescriptor(
336 DebugSectionKind::DebugMacro)},
337 PatchesOffsets);
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);
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,
383 return 0;
385 } break;
386 default: {
387 } break;
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;
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;
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)
414 .second;
416 return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Value)
417 .second;
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;
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;
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;
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;
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;
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;
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;
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);
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;
517 return Generator.addScalarAttribute(AttrSpec.Attr, ResultingForm, Value)
518 .second;
521 size_t DIEAttributeCloner::cloneBlockAttr(
522 const DWARFFormValue &Val,
523 const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {
525 if (OutUnit.isTypeUnit())
526 return 0;
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);
545 Bytes = Buffer;
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)
558 FinalAttributeSize =
559 Generator.addLocationAttribute(AttrSpec.Attr, ResultForm, Bytes).second;
560 else
561 FinalAttributeSize =
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();
566 Idx++) {
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)
587 return Generator
588 .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Val.getRawUValue())
589 .second;
591 if (OutUnit.isTypeUnit())
592 return 0;
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);
608 if (!AddrAttribute)
609 llvm_unreachable("Cann't find attribute");
611 std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();
612 if (!Addr) {
613 InUnit.warn("cann't read address attribute value.");
614 return 0;
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;
636 if (AttrSpec.Form == dwarf::DW_FORM_addr) {
637 return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, *Addr)
638 .second;
641 return Generator
642 .addScalarAttribute(AttrSpec.Attr, dwarf::Form::DW_FORM_addrx,
643 OutUnit.getAsCompileUnit()->getDebugAddrIndex(*Addr))
644 .second;
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);
652 return AttrOutOffset;