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