xref: /freebsd/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DIEAttributeCloner.cpp (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
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