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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "DIEAttributeCloner.h" 10 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" 11 12 using namespace llvm; 13 using namespace dwarf_linker; 14 using namespace dwarf_linker::parallel; 15 16 void 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 NULL 22 // entry after the current one). If this is a lone 23 // 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. After 29 // testing, it seems there is no performance downside to doing the copy 30 // 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 of 40 // 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_base 119 // 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 Generator 131 .addScalarAttribute(dwarf::DW_AT_str_offsets_base, 132 dwarf::DW_FORM_sec_offset, 133 OutUnit->getDebugStrOffsetsHeaderSize()) 134 .second; 135 } 136 } 137 138 bool 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 not 150 // 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 the 157 // 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 the 163 // 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 attribute 171 // 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 not 176 // reference live address. 177 return InUnit.getDIEInfo(InputDIEIdx).getIsInFunctionScope() && 178 !FuncAddressAdjustment.has_value(); 179 } 180 } 181 182 size_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 Generator 211 .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 Generator 226 .addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_strp) 227 .second; 228 } 229 230 return Generator 231 .addIndexedStringAttribute(AttrSpec.Attr, dwarf::DW_FORM_strx, 232 OutUnit->getDebugStrIndex(StringInPool)) 233 .second; 234 } 235 236 size_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 Generator 266 .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 Generator 275 .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 inside 289 // 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 the 295 // 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 304 size_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 and 310 // 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 offset 355 // to .debug_str_offsets would be added later while patching. 356 AttrInfo.HasStringOffsetBaseAttr = true; 357 return Generator 358 .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. Longer 364 // form can affect offsets to the following attributes. To not 365 // update offsets of the following attributes we always remove 366 // original DW_AT_decl_file and attach it to the last position 367 // 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 change 423 // all "addrx" related forms to "addr" version. Change DW_FORM_rnglistx 424 // 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 change 441 // all "addrx" related forms to "addr" version. Change DW_FORM_loclistx 442 // 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 to 509 // .debug_addr would be added later while patching. 510 return Generator 511 .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 521 size_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 temporary 531 // 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 else 561 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 580 size_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 Generator 588 .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 a 595 // totally unrelated value. This can happen: 596 // - If high_pc is an address (Dwarf version == 2), then it might have been 597 // relocated to a totally unrelated value (because the end address in the 598 // object file might be start address of another function which got moved 599 // independently by the linker). 600 // - If address relocated in an inline_subprogram that happens at the 601 // beginning of its inlining function. 602 // To avoid above cases and to not apply relocation twice (in 603 // applyValidRelocs and here), read address attribute from InputDIE and apply 604 // 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 else 622 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 else 628 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 Generator 642 .addScalarAttribute(AttrSpec.Attr, dwarf::Form::DW_FORM_addrx, 643 OutUnit.getAsCompileUnit()->getDebugAddrIndex(*Addr)) 644 .second; 645 } 646 647 unsigned 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