Path: blob/main/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DIEAttributeCloner.cpp
35292 views
//=== DIEAttributeCloner.cpp ----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "DIEAttributeCloner.h"9#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"1011using namespace llvm;12using namespace dwarf_linker;13using namespace dwarf_linker::parallel;1415void DIEAttributeCloner::clone() {16// Extract and clone every attribute.17DWARFDataExtractor Data = InUnit.getOrigUnit().getDebugInfoExtractor();1819uint64_t Offset = InputDieEntry->getOffset();20// Point to the next DIE (generally there is always at least a NULL21// entry after the current one). If this is a lone22// DW_TAG_compile_unit without any children, point to the next unit.23uint64_t NextOffset = (InputDIEIdx + 1 < InUnit.getOrigUnit().getNumDIEs())24? InUnit.getDIEAtIndex(InputDIEIdx + 1).getOffset()25: InUnit.getOrigUnit().getNextUnitOffset();2627// We could copy the data only if we need to apply a relocation to it. After28// testing, it seems there is no performance downside to doing the copy29// unconditionally, and it makes the code simpler.30SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset));31Data =32DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize());3334// Modify the copy with relocated addresses.35InUnit.getContaingFile().Addresses->applyValidRelocs(DIECopy, Offset,36Data.isLittleEndian());3738// Reset the Offset to 0 as we will be working on the local copy of39// the data.40Offset = 0;4142const auto *Abbrev = InputDieEntry->getAbbreviationDeclarationPtr();43Offset += getULEB128Size(Abbrev->getCode());4445// Set current output offset.46AttrOutOffset = OutUnit.isCompileUnit() ? OutDIE->getOffset() : 0;47for (const auto &AttrSpec : Abbrev->attributes()) {48// Check whether current attribute should be skipped.49if (shouldSkipAttribute(AttrSpec)) {50DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,51InUnit.getFormParams());52continue;53}5455DWARFFormValue Val = AttrSpec.getFormValue();56Val.extractValue(Data, &Offset, InUnit.getFormParams(),57&InUnit.getOrigUnit());5859// Clone current attribute.60switch (AttrSpec.Form) {61case dwarf::DW_FORM_strp:62case dwarf::DW_FORM_line_strp:63case dwarf::DW_FORM_string:64case dwarf::DW_FORM_strx:65case dwarf::DW_FORM_strx1:66case dwarf::DW_FORM_strx2:67case dwarf::DW_FORM_strx3:68case dwarf::DW_FORM_strx4:69AttrOutOffset += cloneStringAttr(Val, AttrSpec);70break;71case dwarf::DW_FORM_ref_addr:72case dwarf::DW_FORM_ref1:73case dwarf::DW_FORM_ref2:74case dwarf::DW_FORM_ref4:75case dwarf::DW_FORM_ref8:76case dwarf::DW_FORM_ref_udata:77AttrOutOffset += cloneDieRefAttr(Val, AttrSpec);78break;79case dwarf::DW_FORM_data1:80case dwarf::DW_FORM_data2:81case dwarf::DW_FORM_data4:82case dwarf::DW_FORM_data8:83case dwarf::DW_FORM_udata:84case dwarf::DW_FORM_sdata:85case dwarf::DW_FORM_sec_offset:86case dwarf::DW_FORM_flag:87case dwarf::DW_FORM_flag_present:88case dwarf::DW_FORM_rnglistx:89case dwarf::DW_FORM_loclistx:90case dwarf::DW_FORM_implicit_const:91AttrOutOffset += cloneScalarAttr(Val, AttrSpec);92break;93case dwarf::DW_FORM_block:94case dwarf::DW_FORM_block1:95case dwarf::DW_FORM_block2:96case dwarf::DW_FORM_block4:97case dwarf::DW_FORM_exprloc:98AttrOutOffset += cloneBlockAttr(Val, AttrSpec);99break;100case dwarf::DW_FORM_addr:101case dwarf::DW_FORM_addrx:102case dwarf::DW_FORM_addrx1:103case dwarf::DW_FORM_addrx2:104case dwarf::DW_FORM_addrx3:105case dwarf::DW_FORM_addrx4:106AttrOutOffset += cloneAddressAttr(Val, AttrSpec);107break;108default:109InUnit.warn("unsupported attribute form " +110dwarf::FormEncodingString(AttrSpec.Form) +111" in DieAttributeCloner::clone(). Dropping.",112InputDieEntry);113}114}115116// We convert source strings into the indexed form for DWARFv5.117// Check if original compile unit already has DW_AT_str_offsets_base118// attribute.119if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&120InUnit.getVersion() >= 5 && !AttrInfo.HasStringOffsetBaseAttr) {121DebugInfoOutputSection.notePatchWithOffsetUpdate(122DebugOffsetPatch{AttrOutOffset,123&OutUnit->getOrCreateSectionDescriptor(124DebugSectionKind::DebugStrOffsets),125true},126PatchesOffsets);127128AttrOutOffset +=129Generator130.addScalarAttribute(dwarf::DW_AT_str_offsets_base,131dwarf::DW_FORM_sec_offset,132OutUnit->getDebugStrOffsetsHeaderSize())133.second;134}135}136137bool DIEAttributeCloner::shouldSkipAttribute(138DWARFAbbreviationDeclaration::AttributeSpec AttrSpec) {139switch (AttrSpec.Attr) {140default:141return false;142case dwarf::DW_AT_low_pc:143case dwarf::DW_AT_high_pc:144case dwarf::DW_AT_ranges:145if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)146return false;147148// Skip address attribute if we are in function scope and function does not149// reference live address.150return InUnit.getDIEInfo(InputDIEIdx).getIsInFunctionScope() &&151!FuncAddressAdjustment.has_value();152case dwarf::DW_AT_rnglists_base:153// In case !Update the .debug_addr table is not generated/preserved.154// Thus instead of DW_FORM_rnglistx the DW_FORM_sec_offset is used.155// Since DW_AT_rnglists_base is used for only DW_FORM_rnglistx the156// DW_AT_rnglists_base is removed.157return !InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;158case dwarf::DW_AT_loclists_base:159// In case !Update the .debug_addr table is not generated/preserved.160// Thus instead of DW_FORM_loclistx the DW_FORM_sec_offset is used.161// Since DW_AT_loclists_base is used for only DW_FORM_loclistx the162// DW_AT_loclists_base is removed.163return !InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;164case dwarf::DW_AT_location:165case dwarf::DW_AT_frame_base:166if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)167return false;168169// When location expression contains an address: skip this attribute170// if it does not reference live address.171if (HasLocationExpressionAddress)172return !VarAddressAdjustment.has_value();173174// Skip location attribute if we are in function scope and function does not175// reference live address.176return InUnit.getDIEInfo(InputDIEIdx).getIsInFunctionScope() &&177!FuncAddressAdjustment.has_value();178}179}180181size_t DIEAttributeCloner::cloneStringAttr(182const DWARFFormValue &Val,183const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {184std::optional<const char *> String = dwarf::toString(Val);185if (!String) {186InUnit.warn("cann't read string attribute.");187return 0;188}189190StringEntry *StringInPool =191InUnit.getGlobalData().getStringPool().insert(*String).first;192193// Update attributes info.194if (AttrSpec.Attr == dwarf::DW_AT_name)195AttrInfo.Name = StringInPool;196else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||197AttrSpec.Attr == dwarf::DW_AT_linkage_name)198AttrInfo.MangledName = StringInPool;199200if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {201if (OutUnit.isTypeUnit()) {202DebugInfoOutputSection.notePatch(DebugTypeLineStrPatch{203AttrOutOffset, OutDIE, InUnit.getDieTypeEntry(InputDIEIdx),204StringInPool});205} else {206DebugInfoOutputSection.notePatchWithOffsetUpdate(207DebugLineStrPatch{{AttrOutOffset}, StringInPool}, PatchesOffsets);208}209return Generator210.addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_line_strp)211.second;212}213214if (Use_DW_FORM_strp) {215if (OutUnit.isTypeUnit()) {216DebugInfoOutputSection.notePatch(217DebugTypeStrPatch{AttrOutOffset, OutDIE,218InUnit.getDieTypeEntry(InputDIEIdx), StringInPool});219} else {220DebugInfoOutputSection.notePatchWithOffsetUpdate(221DebugStrPatch{{AttrOutOffset}, StringInPool}, PatchesOffsets);222}223224return Generator225.addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_strp)226.second;227}228229return Generator230.addIndexedStringAttribute(AttrSpec.Attr, dwarf::DW_FORM_strx,231OutUnit->getDebugStrIndex(StringInPool))232.second;233}234235size_t DIEAttributeCloner::cloneDieRefAttr(236const DWARFFormValue &Val,237const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {238if (AttrSpec.Attr == dwarf::DW_AT_sibling)239return 0;240241std::optional<UnitEntryPairTy> RefDiePair =242InUnit.resolveDIEReference(Val, ResolveInterCUReferencesMode::Resolve);243if (!RefDiePair || !RefDiePair->DieEntry) {244// If the referenced DIE is not found, drop the attribute.245InUnit.warn("cann't find referenced DIE.", InputDieEntry);246return 0;247}248249TypeEntry *RefTypeName = nullptr;250const CompileUnit::DIEInfo &RefDIEInfo =251RefDiePair->CU->getDIEInfo(RefDiePair->DieEntry);252if (RefDIEInfo.needToPlaceInTypeTable())253RefTypeName = RefDiePair->CU->getDieTypeEntry(RefDiePair->DieEntry);254255if (OutUnit.isTypeUnit()) {256assert(RefTypeName && "Type name for referenced DIE is not set");257assert(InUnit.getDieTypeEntry(InputDIEIdx) &&258"Type name for DIE is not set");259260DebugInfoOutputSection.notePatch(DebugType2TypeDieRefPatch{261AttrOutOffset, OutDIE, InUnit.getDieTypeEntry(InputDIEIdx),262RefTypeName});263264return Generator265.addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref4, 0xBADDEF)266.second;267}268269if (RefTypeName) {270DebugInfoOutputSection.notePatchWithOffsetUpdate(271DebugDieTypeRefPatch{AttrOutOffset, RefTypeName}, PatchesOffsets);272273return Generator274.addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref_addr, 0xBADDEF)275.second;276}277278// Get output offset for referenced DIE.279uint64_t OutDieOffset = RefDiePair->CU->getDieOutOffset(RefDiePair->DieEntry);280281// Examine whether referenced DIE is in current compile unit.282bool IsLocal = OutUnit->getUniqueID() == RefDiePair->CU->getUniqueID();283284// Set attribute form basing on the kind of referenced DIE(local or not?).285dwarf::Form NewForm = IsLocal ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr;286287// Check whether current attribute references already cloned DIE inside288// the same compilation unit. If true - write the already known offset value.289if (IsLocal && (OutDieOffset != 0))290return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, OutDieOffset)291.second;292293// If offset value is not known at this point then create patch for the294// reference value and write dummy value into the attribute.295DebugInfoOutputSection.notePatchWithOffsetUpdate(296DebugDieRefPatch{AttrOutOffset, OutUnit.getAsCompileUnit(),297RefDiePair->CU,298RefDiePair->CU->getDIEIndex(RefDiePair->DieEntry)},299PatchesOffsets);300return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, 0xBADDEF).second;301}302303size_t DIEAttributeCloner::cloneScalarAttr(304const DWARFFormValue &Val,305const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {306307// Create patches for attribute referencing other non invariant section.308// Invariant section could not be updated here as this section and309// reference to it do not change value in case --update.310switch (AttrSpec.Attr) {311case dwarf::DW_AT_macro_info: {312if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {313const DWARFDebugMacro *Macro =314InUnit.getContaingFile().Dwarf->getDebugMacinfo();315if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset))316return 0;317318DebugInfoOutputSection.notePatchWithOffsetUpdate(319DebugOffsetPatch{AttrOutOffset,320&OutUnit->getOrCreateSectionDescriptor(321DebugSectionKind::DebugMacinfo)},322PatchesOffsets);323}324} break;325case dwarf::DW_AT_macros: {326if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {327const DWARFDebugMacro *Macro =328InUnit.getContaingFile().Dwarf->getDebugMacro();329if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset))330return 0;331332DebugInfoOutputSection.notePatchWithOffsetUpdate(333DebugOffsetPatch{AttrOutOffset,334&OutUnit->getOrCreateSectionDescriptor(335DebugSectionKind::DebugMacro)},336PatchesOffsets);337}338} break;339case dwarf::DW_AT_stmt_list: {340DebugInfoOutputSection.notePatchWithOffsetUpdate(341DebugOffsetPatch{AttrOutOffset, &OutUnit->getOrCreateSectionDescriptor(342DebugSectionKind::DebugLine)},343PatchesOffsets);344} break;345case dwarf::DW_AT_str_offsets_base: {346DebugInfoOutputSection.notePatchWithOffsetUpdate(347DebugOffsetPatch{AttrOutOffset,348&OutUnit->getOrCreateSectionDescriptor(349DebugSectionKind::DebugStrOffsets),350true},351PatchesOffsets);352353// Use size of .debug_str_offsets header as attribute value. The offset354// to .debug_str_offsets would be added later while patching.355AttrInfo.HasStringOffsetBaseAttr = true;356return Generator357.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form,358OutUnit->getDebugStrOffsetsHeaderSize())359.second;360} break;361case dwarf::DW_AT_decl_file: {362// Value of DW_AT_decl_file may exceed original form. Longer363// form can affect offsets to the following attributes. To not364// update offsets of the following attributes we always remove365// original DW_AT_decl_file and attach it to the last position366// later.367if (OutUnit.isTypeUnit()) {368if (std::optional<std::pair<StringRef, StringRef>> DirAndFilename =369InUnit.getDirAndFilenameFromLineTable(Val))370DebugInfoOutputSection.notePatch(DebugTypeDeclFilePatch{371OutDIE,372InUnit.getDieTypeEntry(InputDIEIdx),373OutUnit->getGlobalData()374.getStringPool()375.insert(DirAndFilename->first)376.first,377OutUnit->getGlobalData()378.getStringPool()379.insert(DirAndFilename->second)380.first,381});382return 0;383}384} break;385default: {386} break;387};388389uint64_t Value;390if (AttrSpec.Attr == dwarf::DW_AT_const_value &&391(InputDieEntry->getTag() == dwarf::DW_TAG_variable ||392InputDieEntry->getTag() == dwarf::DW_TAG_constant))393AttrInfo.HasLiveAddress = true;394395if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly) {396if (auto OptionalValue = Val.getAsUnsignedConstant())397Value = *OptionalValue;398else if (auto OptionalValue = Val.getAsSignedConstant())399Value = *OptionalValue;400else if (auto OptionalValue = Val.getAsSectionOffset())401Value = *OptionalValue;402else {403InUnit.warn("unsupported scalar attribute form. Dropping attribute.",404InputDieEntry);405return 0;406}407408if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)409AttrInfo.IsDeclaration = true;410411if (AttrSpec.Form == dwarf::DW_FORM_loclistx)412return Generator.addLocListAttribute(AttrSpec.Attr, AttrSpec.Form, Value)413.second;414415return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Value)416.second;417}418419dwarf::Form ResultingForm = AttrSpec.Form;420if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {421// DWARFLinker does not generate .debug_addr table. Thus we need to change422// all "addrx" related forms to "addr" version. Change DW_FORM_rnglistx423// to DW_FORM_sec_offset here.424std::optional<uint64_t> Index = Val.getAsSectionOffset();425if (!Index) {426InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);427return 0;428}429std::optional<uint64_t> Offset =430InUnit.getOrigUnit().getRnglistOffset(*Index);431if (!Offset) {432InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);433return 0;434}435436Value = *Offset;437ResultingForm = dwarf::DW_FORM_sec_offset;438} else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {439// DWARFLinker does not generate .debug_addr table. Thus we need to change440// all "addrx" related forms to "addr" version. Change DW_FORM_loclistx441// to DW_FORM_sec_offset here.442std::optional<uint64_t> Index = Val.getAsSectionOffset();443if (!Index) {444InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);445return 0;446}447std::optional<uint64_t> Offset =448InUnit.getOrigUnit().getLoclistOffset(*Index);449if (!Offset) {450InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);451return 0;452}453454Value = *Offset;455ResultingForm = dwarf::DW_FORM_sec_offset;456} else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&457InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) {458if (!OutUnit.isCompileUnit())459return 0;460461std::optional<uint64_t> LowPC = OutUnit.getAsCompileUnit()->getLowPc();462if (!LowPC)463return 0;464// Dwarf >= 4 high_pc is an size, not an address.465Value = OutUnit.getAsCompileUnit()->getHighPc() - *LowPC;466} else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)467Value = *Val.getAsSectionOffset();468else if (AttrSpec.Form == dwarf::DW_FORM_sdata)469Value = *Val.getAsSignedConstant();470else if (auto OptionalValue = Val.getAsUnsignedConstant())471Value = *OptionalValue;472else {473InUnit.warn("unsupported scalar attribute form. Dropping attribute.",474InputDieEntry);475return 0;476}477478if (AttrSpec.Attr == dwarf::DW_AT_ranges ||479AttrSpec.Attr == dwarf::DW_AT_start_scope) {480// Create patch for the range offset value.481DebugInfoOutputSection.notePatchWithOffsetUpdate(482DebugRangePatch{{AttrOutOffset},483InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit},484PatchesOffsets);485AttrInfo.HasRanges = true;486} else if (DWARFAttribute::mayHaveLocationList(AttrSpec.Attr) &&487dwarf::doesFormBelongToClass(AttrSpec.Form,488DWARFFormValue::FC_SectionOffset,489InUnit.getOrigUnit().getVersion())) {490int64_t AddrAdjustmentValue = 0;491if (VarAddressAdjustment)492AddrAdjustmentValue = *VarAddressAdjustment;493else if (FuncAddressAdjustment)494AddrAdjustmentValue = *FuncAddressAdjustment;495496// Create patch for the location offset value.497DebugInfoOutputSection.notePatchWithOffsetUpdate(498DebugLocPatch{{AttrOutOffset}, AddrAdjustmentValue}, PatchesOffsets);499} else if (AttrSpec.Attr == dwarf::DW_AT_addr_base) {500DebugInfoOutputSection.notePatchWithOffsetUpdate(501DebugOffsetPatch{502AttrOutOffset,503&OutUnit->getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr),504true},505PatchesOffsets);506507// Use size of .debug_addr header as attribute value. The offset to508// .debug_addr would be added later while patching.509return Generator510.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form,511OutUnit->getDebugAddrHeaderSize())512.second;513} else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)514AttrInfo.IsDeclaration = true;515516return Generator.addScalarAttribute(AttrSpec.Attr, ResultingForm, Value)517.second;518}519520size_t DIEAttributeCloner::cloneBlockAttr(521const DWARFFormValue &Val,522const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {523524if (OutUnit.isTypeUnit())525return 0;526527size_t NumberOfPatchesAtStart = PatchesOffsets.size();528529// If the block is a DWARF Expression, clone it into the temporary530// buffer using cloneExpression(), otherwise copy the data directly.531SmallVector<uint8_t, 32> Buffer;532ArrayRef<uint8_t> Bytes = *Val.getAsBlock();533if (DWARFAttribute::mayHaveLocationExpr(AttrSpec.Attr) &&534(Val.isFormClass(DWARFFormValue::FC_Block) ||535Val.isFormClass(DWARFFormValue::FC_Exprloc))) {536DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()),537InUnit.getOrigUnit().isLittleEndian(),538InUnit.getOrigUnit().getAddressByteSize());539DWARFExpression Expr(Data, InUnit.getOrigUnit().getAddressByteSize(),540InUnit.getFormParams().Format);541542InUnit.cloneDieAttrExpression(Expr, Buffer, DebugInfoOutputSection,543VarAddressAdjustment, PatchesOffsets);544Bytes = Buffer;545}546547// The expression location data might be updated and exceed the original size.548// Check whether the new data fits into the original form.549dwarf::Form ResultForm = AttrSpec.Form;550if ((ResultForm == dwarf::DW_FORM_block1 && Bytes.size() > UINT8_MAX) ||551(ResultForm == dwarf::DW_FORM_block2 && Bytes.size() > UINT16_MAX) ||552(ResultForm == dwarf::DW_FORM_block4 && Bytes.size() > UINT32_MAX))553ResultForm = dwarf::DW_FORM_block;554555size_t FinalAttributeSize;556if (AttrSpec.Form == dwarf::DW_FORM_exprloc)557FinalAttributeSize =558Generator.addLocationAttribute(AttrSpec.Attr, ResultForm, Bytes).second;559else560FinalAttributeSize =561Generator.addBlockAttribute(AttrSpec.Attr, ResultForm, Bytes).second;562563// Update patches offsets with the size of length field for Bytes.564for (size_t Idx = NumberOfPatchesAtStart; Idx < PatchesOffsets.size();565Idx++) {566assert(FinalAttributeSize > Bytes.size());567*PatchesOffsets[Idx] +=568(AttrOutOffset + (FinalAttributeSize - Bytes.size()));569}570571if (HasLocationExpressionAddress)572AttrInfo.HasLiveAddress =573VarAddressAdjustment.has_value() ||574InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;575576return FinalAttributeSize;577}578579size_t DIEAttributeCloner::cloneAddressAttr(580const DWARFFormValue &Val,581const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {582if (AttrSpec.Attr == dwarf::DW_AT_low_pc)583AttrInfo.HasLiveAddress = true;584585if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)586return Generator587.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Val.getRawUValue())588.second;589590if (OutUnit.isTypeUnit())591return 0;592593// Cloned Die may have address attributes relocated to a594// totally unrelated value. This can happen:595// - If high_pc is an address (Dwarf version == 2), then it might have been596// relocated to a totally unrelated value (because the end address in the597// object file might be start address of another function which got moved598// independently by the linker).599// - If address relocated in an inline_subprogram that happens at the600// beginning of its inlining function.601// To avoid above cases and to not apply relocation twice (in602// applyValidRelocs and here), read address attribute from InputDIE and apply603// Info.PCOffset here.604605std::optional<DWARFFormValue> AddrAttribute =606InUnit.find(InputDieEntry, AttrSpec.Attr);607if (!AddrAttribute)608llvm_unreachable("Cann't find attribute");609610std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();611if (!Addr) {612InUnit.warn("cann't read address attribute value.");613return 0;614}615616if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&617AttrSpec.Attr == dwarf::DW_AT_low_pc) {618if (std::optional<uint64_t> LowPC = OutUnit.getAsCompileUnit()->getLowPc())619Addr = *LowPC;620else621return 0;622} else if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&623AttrSpec.Attr == dwarf::DW_AT_high_pc) {624if (uint64_t HighPc = OutUnit.getAsCompileUnit()->getHighPc())625Addr = HighPc;626else627return 0;628} else {629if (VarAddressAdjustment)630*Addr += *VarAddressAdjustment;631else if (FuncAddressAdjustment)632*Addr += *FuncAddressAdjustment;633}634635if (AttrSpec.Form == dwarf::DW_FORM_addr) {636return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, *Addr)637.second;638}639640return Generator641.addScalarAttribute(AttrSpec.Attr, dwarf::Form::DW_FORM_addrx,642OutUnit.getAsCompileUnit()->getDebugAddrIndex(*Addr))643.second;644}645646unsigned DIEAttributeCloner::finalizeAbbreviations(bool HasChildrenToClone) {647// Add the size of the abbreviation number to the output offset.648AttrOutOffset +=649Generator.finalizeAbbreviations(HasChildrenToClone, &PatchesOffsets);650651return AttrOutOffset;652}653654655