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