brintos

brintos / llvm-project-archived public Read only

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