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