LLVM 23.0.0git
DIEAttributeCloner.cpp
Go to the documentation of this file.
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
11
12using namespace llvm;
13using namespace dwarf_linker;
14using namespace dwarf_linker::parallel;
15
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.",
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(
124 &OutUnit->getOrCreateSectionDescriptor(
126 true},
128
131 .addScalarAttribute(dwarf::DW_AT_str_offsets_base,
132 dwarf::DW_FORM_sec_offset,
133 OutUnit->getDebugStrOffsetsHeaderSize())
134 .second;
135 }
136}
137
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.
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
183 const DWARFFormValue &Val,
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()) {
204 AttrOutOffset, OutDIE, InUnit.getDieTypeEntry(InputDIEIdx),
205 StringInPool});
206 } else {
207 DebugInfoOutputSection.notePatchWithOffsetUpdate(
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(
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
237 const DWARFFormValue &Val,
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("could not 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
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(
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)},
301 return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, 0xBADDEF).second;
302}
303
305 const DWARFFormValue &Val,
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(
321 &OutUnit->getOrCreateSectionDescriptor(
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(
335 &OutUnit->getOrCreateSectionDescriptor(
338 }
339 } break;
340 case dwarf::DW_AT_stmt_list: {
341 DebugInfoOutputSection.notePatchWithOffsetUpdate(
342 DebugOffsetPatch{AttrOutOffset, &OutUnit->getOrCreateSectionDescriptor(
345 } break;
346 case dwarf::DW_AT_str_offsets_base: {
347 DebugInfoOutputSection.notePatchWithOffsetUpdate(
349 &OutUnit->getOrCreateSectionDescriptor(
351 true},
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))
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
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.",
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.",
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(
484 InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit},
486 AttrInfo.HasRanges = true;
487 } else if (DWARFAttribute::mayHaveLocationList(AttrSpec.Attr) &&
490 InUnit.getOrigUnit().getVersion())) {
491 int64_t AddrAdjustmentValue = 0;
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(
504 &OutUnit->getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr),
505 true},
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 // DW_AT_LLVM_stmt_sequence refers to line info in this unit's
518 // .debug_line contribution, which only exists for compile units.
519 // DependencyTracker can route a module-scope subprogram to a type
520 // unit when ODR deduplication applies (see
521 // DependencyTracker.cpp: DW_TAG_subprogram case), so drop the
522 // attribute on that path — mirroring how cloneBlockAttr handles
523 // type-unit placement.
524 if (AttrSpec.Attr == dwarf::DW_AT_LLVM_stmt_sequence &&
525 !OutUnit.isCompileUnit())
526 return 0;
527
528 auto Result =
529 Generator.addScalarAttribute(AttrSpec.Attr, ResultingForm, Value);
530 // Record DW_AT_LLVM_stmt_sequence so the attribute value can be
531 // rewritten with the correct .debug_line offset after the line table
532 // for this CU has been emitted. We also register a DebugOffsetPatch so
533 // that the final-section offset of .debug_line gets added when the
534 // section is placed in the combined output.
535 if (AttrSpec.Attr == dwarf::DW_AT_LLVM_stmt_sequence) {
536 // Record the attribute's raw input stmt-sequence offset. Resolution
537 // to a first-row index — including the boundary-walk fallback for
538 // sequences the DWARF parser may not have registered — happens in
539 // a post-cloning pass (buildStmtSeqOffsetToFirstRowIndex), so that
540 // matches the classic linker's behaviour.
541 OutUnit.getAsCompileUnit()->noteStmtSeqListAttribute(&Result.first, Value);
542 DebugInfoOutputSection.notePatchWithOffsetUpdate(
545 &OutUnit->getOrCreateSectionDescriptor(DebugSectionKind::DebugLine),
546 /*AddLocalValue=*/true},
548 }
549 return Result.second;
550}
551
553 const DWARFFormValue &Val,
555
556 if (OutUnit.isTypeUnit())
557 return 0;
558
559 size_t NumberOfPatchesAtStart = PatchesOffsets.size();
560
561 // If the block is a DWARF Expression, clone it into the temporary
562 // buffer using cloneExpression(), otherwise copy the data directly.
564 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
568 DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()),
569 InUnit.getOrigUnit().isLittleEndian(),
570 InUnit.getOrigUnit().getAddressByteSize());
571 DWARFExpression Expr(Data, InUnit.getOrigUnit().getAddressByteSize(),
572 InUnit.getFormParams().Format);
573
574 InUnit.cloneDieAttrExpression(Expr, Buffer, DebugInfoOutputSection,
576 Bytes = Buffer;
577 }
578
579 // The expression location data might be updated and exceed the original size.
580 // Check whether the new data fits into the original form.
581 dwarf::Form ResultForm = AttrSpec.Form;
582 if ((ResultForm == dwarf::DW_FORM_block1 && Bytes.size() > UINT8_MAX) ||
583 (ResultForm == dwarf::DW_FORM_block2 && Bytes.size() > UINT16_MAX) ||
584 (ResultForm == dwarf::DW_FORM_block4 && Bytes.size() > UINT32_MAX))
585 ResultForm = dwarf::DW_FORM_block;
586
587 size_t FinalAttributeSize;
588 if (AttrSpec.Form == dwarf::DW_FORM_exprloc)
589 FinalAttributeSize =
590 Generator.addLocationAttribute(AttrSpec.Attr, ResultForm, Bytes).second;
591 else
592 FinalAttributeSize =
593 Generator.addBlockAttribute(AttrSpec.Attr, ResultForm, Bytes).second;
594
595 // Update patches offsets with the size of length field for Bytes.
596 for (size_t Idx = NumberOfPatchesAtStart; Idx < PatchesOffsets.size();
597 Idx++) {
598 assert(FinalAttributeSize > Bytes.size());
599 *PatchesOffsets[Idx] +=
600 (AttrOutOffset + (FinalAttributeSize - Bytes.size()));
601 }
602
604 AttrInfo.HasLiveAddress =
605 VarAddressAdjustment.has_value() ||
606 InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
607
608 return FinalAttributeSize;
609}
610
612 const DWARFFormValue &Val,
614 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
615 AttrInfo.HasLiveAddress = true;
616
617 if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
618 return Generator
619 .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Val.getRawUValue())
620 .second;
621
622 if (OutUnit.isTypeUnit())
623 return 0;
624
625 // Cloned Die may have address attributes relocated to a
626 // totally unrelated value. This can happen:
627 // - If high_pc is an address (Dwarf version == 2), then it might have been
628 // relocated to a totally unrelated value (because the end address in the
629 // object file might be start address of another function which got moved
630 // independently by the linker).
631 // - If address relocated in an inline_subprogram that happens at the
632 // beginning of its inlining function.
633 // To avoid above cases and to not apply relocation twice (in
634 // applyValidRelocs and here), read address attribute from InputDIE and apply
635 // Info.PCOffset here.
636
637 std::optional<DWARFFormValue> AddrAttribute =
638 InUnit.find(InputDieEntry, AttrSpec.Attr);
639 if (!AddrAttribute)
640 llvm_unreachable("Cann't find attribute");
641
642 std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();
643 if (!Addr) {
644 InUnit.warn("cann't read address attribute value.");
645 return 0;
646 }
647
648 if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
649 AttrSpec.Attr == dwarf::DW_AT_low_pc) {
650 if (std::optional<uint64_t> LowPC = OutUnit.getAsCompileUnit()->getLowPc())
651 Addr = *LowPC;
652 else
653 return 0;
654 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
655 AttrSpec.Attr == dwarf::DW_AT_high_pc) {
656 if (uint64_t HighPc = OutUnit.getAsCompileUnit()->getHighPc())
657 Addr = HighPc;
658 else
659 return 0;
660 } else {
662 *Addr += *VarAddressAdjustment;
663 else if (FuncAddressAdjustment)
664 *Addr += *FuncAddressAdjustment;
665 }
666
667 if (AttrSpec.Form == dwarf::DW_FORM_addr) {
668 return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, *Addr)
669 .second;
670 }
671
672 return Generator
673 .addScalarAttribute(AttrSpec.Attr, dwarf::Form::DW_FORM_addrx,
674 OutUnit.getAsCompileUnit()->getDebugAddrIndex(*Addr))
675 .second;
676}
677
678unsigned DIEAttributeCloner::finalizeAbbreviations(bool HasChildrenToClone) {
679 // Add the size of the abbreviation number to the output offset.
681 Generator.finalizeAbbreviations(HasChildrenToClone, &PatchesOffsets);
682
683 return AttrOutOffset;
684}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
const T * data() const
Definition ArrayRef.h:138
A DWARFDataExtractor (typically for an in-memory copy of an object-file section) plus a relocation ma...
LLVM_ABI std::optional< ArrayRef< uint8_t > > getAsBlock() const
LLVM_ABI std::optional< uint64_t > getAsSectionOffset() const
LLVM_ABI bool isFormClass(FormClass FC) const
LLVM_ABI std::optional< int64_t > getAsSignedConstant() const
LLVM_ABI bool extractValue(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, dwarf::FormParams FormParams, const DWARFContext *Context=nullptr, const DWARFUnit *Unit=nullptr)
Extracts a value in Data at offset *OffsetPtr.
LLVM_ABI std::optional< uint64_t > getAsUnsignedConstant() const
bool skipValue(DataExtractor DebugInfoData, uint64_t *OffsetPtr, const dwarf::FormParams Params) const
Skip a form's value in DebugInfoData at the offset specified by OffsetPtr.
uint64_t getRawUValue() const
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
LLVM Value Representation.
Definition Value.h:75
size_t cloneBlockAttr(const DWARFFormValue &Val, const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec)
Clone block or exprloc attribute.
AttributesInfo AttrInfo
Cannot be used concurrently.
CompileUnit & InUnit
Input compilation unit.
bool HasLocationExpressionAddress
Indicates whether InputDieEntry has an location attribute containg address expression.
SectionDescriptor & DebugInfoOutputSection
.debug_info section descriptor.
unsigned finalizeAbbreviations(bool HasChildrenToClone)
Create abbreviations for the output DIE after all attributes are cloned.
unsigned AttrOutOffset
Output offset after all attributes.
DIEGenerator & Generator
Output DIE generator.
size_t cloneScalarAttr(const DWARFFormValue &Val, const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec)
Clone scalar attribute.
OffsetsPtrVector PatchesOffsets
Patches for the cloned attributes.
size_t cloneDieRefAttr(const DWARFFormValue &Val, const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec)
Clone attribute referencing another DIE.
bool shouldSkipAttribute(DWARFAbbreviationDeclaration::AttributeSpec AttrSpec)
Returns true if attribute should be skipped.
size_t cloneStringAttr(const DWARFFormValue &Val, const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec)
Clone string attribute.
const DWARFDebugInfoEntry * InputDieEntry
Input DIE entry.
std::optional< int64_t > FuncAddressAdjustment
Relocation adjustment for the function address ranges.
CompileUnit::OutputUnitVariantPtr OutUnit
Output unit(either "plain" compilation unit, either artificial type unit).
size_t cloneAddressAttr(const DWARFFormValue &Val, const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec)
Clone address attribute.
std::optional< int64_t > VarAddressAdjustment
Relocation adjustment for the variable locations.
bool Use_DW_FORM_strp
This flag forces using DW_FORM_strp for string attributes.
LLVM_ABI StringRef FormEncodingString(unsigned Encoding)
Definition Dwarf.cpp:105
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
Definition TypePool.h:28
StringMapEntry< EmptyStringSetTag > StringEntry
StringEntry keeps data of the string: the length, external offset and a string body which is placed r...
Definition StringPool.h:23
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
LLVM_ABI bool doesFormBelongToClass(dwarf::Form Form, DWARFFormValue::FormClass FC, uint16_t DwarfVersion)
Check whether specified Form belongs to the FC class.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:557
LLVM_ABI unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
Definition LEB128.cpp:19
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:221
static LLVM_ABI bool mayHaveLocationList(dwarf::Attribute Attr)
Identify DWARF attributes that may contain a pointer to a location list.
Definition DWARFDie.cpp:806
static LLVM_ABI bool mayHaveLocationExpr(dwarf::Attribute Attr)
Identifies DWARF attributes that may contain a reference to a DWARF expression.
Definition DWARFDie.cpp:823
This structure is used to update reference to the DIE.
This structure is used to update reference to the type DIE.
This structure is used to update strings offsets into .debug_line_str.
This structure is used to update location list offset into .debug_loc/.debug_loclists.
This structure is used to update range list offset into .debug_ranges/.debug_rnglists.
This structure is used to update strings offsets into .debug_str.
This structure is used to update reference to the type DIE.