LLVM 24.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.getContainingFile().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 // The importing unit's DW_TAG_module skeleton can have a different
257 // DW_AT_LLVM_include_path than the unit built from the .pcm and the import
258 // must use the latter. The type pool already merges copies, so a reference
259 // with a type entry resolves correctly. Without one, the module's anchor is
260 // the only link between the two, and it is not known until the unit
261 // describing the module has been emitted.
262 if (RefDiePair->DieEntry->getTag() == dwarf::DW_TAG_module &&
263 AttrSpec.Attr == dwarf::DW_AT_import && !OutUnit.isTypeUnit() &&
264 !RefTypeName) {
265 SmallString<128> Path;
266 if (RefDiePair->CU->getModulePath(RefDiePair->DieEntry, Path)) {
267 ModuleAnchor *Anchor =
268 InUnit.getGlobalData().getModulePool().getOrCreate(Path);
269
270 DebugInfoOutputSection.notePatchWithOffsetUpdate(
272 AttrOutOffset, RefDiePair->CU,
273 RefDiePair->CU->getDIEIndex(RefDiePair->DieEntry), Anchor},
275 return Generator
276 .addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref_addr, 0xBADDEF)
277 .second;
278 }
279 }
280
281 if (OutUnit.isTypeUnit()) {
282 assert(RefTypeName && "Type name for referenced DIE is not set");
283 assert(InUnit.getDieTypeEntry(InputDIEIdx) &&
284 "Type name for DIE is not set");
285
287 AttrOutOffset, OutDIE, InUnit.getDieTypeEntry(InputDIEIdx),
288 RefTypeName});
289
290 return Generator
291 .addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref4, 0xBADDEF)
292 .second;
293 }
294
295 if (RefTypeName) {
296 DebugInfoOutputSection.notePatchWithOffsetUpdate(
298
299 return Generator
300 .addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref_addr, 0xBADDEF)
301 .second;
302 }
303
304 // Get output offset for referenced DIE.
305 uint64_t OutDieOffset = RefDiePair->CU->getDieOutOffset(RefDiePair->DieEntry);
306
307 // Examine whether referenced DIE is in current compile unit.
308 bool IsLocal = OutUnit->getUniqueID() == RefDiePair->CU->getUniqueID();
309
310 // Set attribute form basing on the kind of referenced DIE(local or not?).
311 dwarf::Form NewForm = IsLocal ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr;
312
313 // Check whether current attribute references already cloned DIE inside
314 // the same compilation unit. If true - write the already known offset value.
315 if (IsLocal && (OutDieOffset != 0))
316 return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, OutDieOffset)
317 .second;
318
319 // If offset value is not known at this point then create patch for the
320 // reference value and write dummy value into the attribute.
321 DebugInfoOutputSection.notePatchWithOffsetUpdate(
322 DebugDieRefPatch{AttrOutOffset, OutUnit.getAsCompileUnit(),
323 RefDiePair->CU,
324 RefDiePair->CU->getDIEIndex(RefDiePair->DieEntry)},
326 return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, 0xBADDEF).second;
327}
328
330 const DWARFFormValue &Val,
332
333 // Create patches for attribute referencing other non invariant section.
334 // Invariant section could not be updated here as this section and
335 // reference to it do not change value in case --update.
336 switch (AttrSpec.Attr) {
337 case dwarf::DW_AT_macro_info: {
338 if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {
339 const DWARFDebugMacro *Macro =
340 InUnit.getContainingFile().Dwarf->getDebugMacinfo();
341 if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset))
342 return 0;
343
344 DebugInfoOutputSection.notePatchWithOffsetUpdate(
346 &OutUnit->getOrCreateSectionDescriptor(
349 }
350 } break;
351 case dwarf::DW_AT_macros: {
352 if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {
353 const DWARFDebugMacro *Macro =
354 InUnit.getContainingFile().Dwarf->getDebugMacro();
355 if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset))
356 return 0;
357
358 DebugInfoOutputSection.notePatchWithOffsetUpdate(
360 &OutUnit->getOrCreateSectionDescriptor(
363 }
364 } break;
365 case dwarf::DW_AT_stmt_list: {
366 DebugInfoOutputSection.notePatchWithOffsetUpdate(
367 DebugOffsetPatch{AttrOutOffset, &OutUnit->getOrCreateSectionDescriptor(
370 } break;
371 case dwarf::DW_AT_str_offsets_base: {
372 DebugInfoOutputSection.notePatchWithOffsetUpdate(
374 &OutUnit->getOrCreateSectionDescriptor(
376 true},
378
379 // Use size of .debug_str_offsets header as attribute value. The offset
380 // to .debug_str_offsets would be added later while patching.
381 AttrInfo.HasStringOffsetBaseAttr = true;
382 return Generator
383 .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form,
384 OutUnit->getDebugStrOffsetsHeaderSize())
385 .second;
386 } break;
387 case dwarf::DW_AT_decl_file: {
388 // Value of DW_AT_decl_file may exceed original form. Longer
389 // form can affect offsets to the following attributes. To not
390 // update offsets of the following attributes we always remove
391 // original DW_AT_decl_file and attach it to the last position
392 // later.
393 if (OutUnit.isTypeUnit()) {
394 if (std::optional<std::pair<StringRef, StringRef>> DirAndFilename =
395 InUnit.getDirAndFilenameFromLineTable(Val))
397 OutDIE,
398 InUnit.getDieTypeEntry(InputDIEIdx),
399 OutUnit->getGlobalData()
400 .getStringPool()
401 .insert(DirAndFilename->first)
402 .first,
403 OutUnit->getGlobalData()
404 .getStringPool()
405 .insert(DirAndFilename->second)
406 .first,
407 });
408 return 0;
409 }
410 } break;
411 default: {
412 } break;
413 };
414
415 uint64_t Value;
416 if (AttrSpec.Attr == dwarf::DW_AT_const_value &&
417 (InputDieEntry->getTag() == dwarf::DW_TAG_variable ||
418 InputDieEntry->getTag() == dwarf::DW_TAG_constant))
419 AttrInfo.HasLiveAddress = true;
420
421 if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly) {
422 if (auto OptionalValue = Val.getAsUnsignedConstant())
423 Value = *OptionalValue;
424 else if (auto OptionalValue = Val.getAsSignedConstant())
425 Value = *OptionalValue;
426 else if (auto OptionalValue = Val.getAsSectionOffset())
427 Value = *OptionalValue;
428 else {
429 InUnit.warn("unsupported scalar attribute form. Dropping attribute.",
431 return 0;
432 }
433
434 if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
435 AttrInfo.IsDeclaration = true;
436
437 if (AttrSpec.Form == dwarf::DW_FORM_loclistx)
438 return Generator.addLocListAttribute(AttrSpec.Attr, AttrSpec.Form, Value)
439 .second;
440
441 return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Value)
442 .second;
443 }
444
445 dwarf::Form ResultingForm = AttrSpec.Form;
446 if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {
447 // DWARFLinker does not generate .debug_addr table. Thus we need to change
448 // all "addrx" related forms to "addr" version. Change DW_FORM_rnglistx
449 // to DW_FORM_sec_offset here.
450 std::optional<uint64_t> Index = Val.getAsSectionOffset();
451 if (!Index) {
452 InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
453 return 0;
454 }
455 std::optional<uint64_t> Offset =
456 InUnit.getOrigUnit().getRnglistOffset(*Index);
457 if (!Offset) {
458 InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
459 return 0;
460 }
461
462 Value = *Offset;
463 ResultingForm = dwarf::DW_FORM_sec_offset;
464 } else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {
465 // DWARFLinker does not generate .debug_addr table. Thus we need to change
466 // all "addrx" related forms to "addr" version. Change DW_FORM_loclistx
467 // to DW_FORM_sec_offset here.
468 std::optional<uint64_t> Index = Val.getAsSectionOffset();
469 if (!Index) {
470 InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
471 return 0;
472 }
473 std::optional<uint64_t> Offset =
474 InUnit.getOrigUnit().getLoclistOffset(*Index);
475 if (!Offset) {
476 InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
477 return 0;
478 }
479
480 Value = *Offset;
481 ResultingForm = dwarf::DW_FORM_sec_offset;
482 } else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
483 InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) {
484 if (!OutUnit.isCompileUnit())
485 return 0;
486
487 std::optional<uint64_t> LowPC = OutUnit.getAsCompileUnit()->getLowPc();
488 if (!LowPC)
489 return 0;
490 // Dwarf >= 4 high_pc is an size, not an address.
491 Value = OutUnit.getAsCompileUnit()->getHighPc() - *LowPC;
492 } else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
493 Value = *Val.getAsSectionOffset();
494 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
495 Value = *Val.getAsSignedConstant();
496 else if (auto OptionalValue = Val.getAsUnsignedConstant())
497 Value = *OptionalValue;
498 else {
499 InUnit.warn("unsupported scalar attribute form. Dropping attribute.",
501 return 0;
502 }
503
504 if (AttrSpec.Attr == dwarf::DW_AT_ranges ||
505 AttrSpec.Attr == dwarf::DW_AT_start_scope) {
506 // Create patch for the range offset value.
507 DebugInfoOutputSection.notePatchWithOffsetUpdate(
509 InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit},
511 AttrInfo.HasRanges = true;
512 } else if (DWARFAttribute::mayHaveLocationList(AttrSpec.Attr) &&
515 InUnit.getOrigUnit().getVersion())) {
516 int64_t AddrAdjustmentValue = 0;
518 AddrAdjustmentValue = *VarAddressAdjustment;
519 else if (FuncAddressAdjustment)
520 AddrAdjustmentValue = *FuncAddressAdjustment;
521
522 // Create patch for the location offset value.
523 DebugInfoOutputSection.notePatchWithOffsetUpdate(
524 DebugLocPatch{{AttrOutOffset}, AddrAdjustmentValue}, PatchesOffsets);
525 } else if (AttrSpec.Attr == dwarf::DW_AT_addr_base) {
526 DebugInfoOutputSection.notePatchWithOffsetUpdate(
529 &OutUnit->getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr),
530 true},
532
533 // Use size of .debug_addr header as attribute value. The offset to
534 // .debug_addr would be added later while patching.
535 return Generator
536 .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form,
537 OutUnit->getDebugAddrHeaderSize())
538 .second;
539 } else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
540 AttrInfo.IsDeclaration = true;
541
542 // DW_AT_LLVM_stmt_sequence refers to line info in this unit's
543 // .debug_line contribution, which only exists for compile units.
544 // DependencyTracker can route a module-scope subprogram to a type
545 // unit when ODR deduplication applies (see
546 // DependencyTracker.cpp: DW_TAG_subprogram case), so drop the
547 // attribute on that path — mirroring how cloneBlockAttr handles
548 // type-unit placement.
549 if (AttrSpec.Attr == dwarf::DW_AT_LLVM_stmt_sequence &&
550 !OutUnit.isCompileUnit())
551 return 0;
552
553 // A compile unit's high_pc comes from the unit's own linked range and spans
554 // every symbol in it.
555 if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
556 InputDieEntry->getTag() != dwarf::DW_TAG_compile_unit)
557 Value = constrainHighPC(Value, /*IsLength=*/true);
558
559 auto Result =
560 Generator.addScalarAttribute(AttrSpec.Attr, ResultingForm, Value);
561 // Record DW_AT_LLVM_stmt_sequence so the attribute value can be
562 // rewritten with the correct .debug_line offset after the line table
563 // for this CU has been emitted. We also register a DebugOffsetPatch so
564 // that the final-section offset of .debug_line gets added when the
565 // section is placed in the combined output.
566 if (AttrSpec.Attr == dwarf::DW_AT_LLVM_stmt_sequence) {
567 // Record the attribute's raw input stmt-sequence offset. Resolution
568 // to a first-row index — including the boundary-walk fallback for
569 // sequences the DWARF parser may not have registered — happens in
570 // a post-cloning pass (buildStmtSeqOffsetToFirstRowIndex), so that
571 // matches the classic linker's behaviour.
572 OutUnit.getAsCompileUnit()->noteStmtSeqListAttribute(&Result.first, Value);
573 DebugInfoOutputSection.notePatchWithOffsetUpdate(
576 &OutUnit->getOrCreateSectionDescriptor(DebugSectionKind::DebugLine),
577 /*AddLocalValue=*/true},
579 }
580 return Result.second;
581}
582
585
586 for (const DWARFExpression::Operation &Op : Expr) {
587 switch (Op.getCode()) {
588 case dwarf::DW_OP_addr:
589 case dwarf::DW_OP_addrx:
590 case dwarf::DW_OP_constx:
591 return true;
592 default:
593 break;
594 }
595
596 if (llvm::is_contained(Op.getDescription().Op, Encoding::BaseTypeRef))
597 return true;
598 }
599
600 return false;
601}
602
604 const DWARFFormValue &Val,
606
607 size_t NumberOfPatchesAtStart = PatchesOffsets.size();
608
609 // If the block is a DWARF Expression, clone it into the temporary
610 // buffer using cloneExpression(), otherwise copy the data directly.
612 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
616 DataExtractor Data(Bytes, InUnit.getOrigUnit().isLittleEndian());
617 DWARFExpression Expr(Data, InUnit.getOrigUnit().getAddressByteSize(),
618 InUnit.getFormParams().Format);
619
620 // A type unit is shared by every compile unit that references the type, so
621 // an expression resolving against one origin unit has no single correct
622 // value there.
623 if (OutUnit.isTypeUnit() && expressionDependsOnOriginUnit(Expr))
624 return 0;
625
626 InUnit.cloneDieAttrExpression(Expr, Buffer, DebugInfoOutputSection,
628 Bytes = Buffer;
629 }
630
631 // The expression location data might be updated and exceed the original size.
632 // Check whether the new data fits into the original form.
633 dwarf::Form ResultForm = AttrSpec.Form;
634 if ((ResultForm == dwarf::DW_FORM_block1 && Bytes.size() > UINT8_MAX) ||
635 (ResultForm == dwarf::DW_FORM_block2 && Bytes.size() > UINT16_MAX) ||
636 (ResultForm == dwarf::DW_FORM_block4 && Bytes.size() > UINT32_MAX))
637 ResultForm = dwarf::DW_FORM_block;
638
639 size_t FinalAttributeSize;
640 if (AttrSpec.Form == dwarf::DW_FORM_exprloc)
641 FinalAttributeSize =
642 Generator.addLocationAttribute(AttrSpec.Attr, ResultForm, Bytes).second;
643 else
644 FinalAttributeSize =
645 Generator.addBlockAttribute(AttrSpec.Attr, ResultForm, Bytes).second;
646
647 // Update patches offsets with the size of length field for Bytes.
648 for (size_t Idx = NumberOfPatchesAtStart; Idx < PatchesOffsets.size();
649 Idx++) {
650 assert(FinalAttributeSize > Bytes.size());
651 *PatchesOffsets[Idx] +=
652 (AttrOutOffset + (FinalAttributeSize - Bytes.size()));
653 }
654
656 AttrInfo.HasLiveAddress =
657 VarAddressAdjustment.has_value() ||
658 InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
659
660 return FinalAttributeSize;
661}
662
664 const DWARFFormValue &Val,
666 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
667 AttrInfo.HasLiveAddress = true;
668
669 if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
670 return Generator
671 .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Val.getRawUValue())
672 .second;
673
674 if (OutUnit.isTypeUnit())
675 return 0;
676
677 // Cloned Die may have address attributes relocated to a
678 // totally unrelated value. This can happen:
679 // - If high_pc is an address (Dwarf version == 2), then it might have been
680 // relocated to a totally unrelated value (because the end address in the
681 // object file might be start address of another function which got moved
682 // independently by the linker).
683 // - If address relocated in an inline_subprogram that happens at the
684 // beginning of its inlining function.
685 // To avoid above cases and to not apply relocation twice (in
686 // applyValidRelocs and here), read address attribute from InputDIE and apply
687 // Info.PCOffset here.
688
689 std::optional<DWARFFormValue> AddrAttribute =
690 InUnit.find(InputDieEntry, AttrSpec.Attr);
691 if (!AddrAttribute)
692 llvm_unreachable("Cann't find attribute");
693
694 std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();
695 if (!Addr) {
696 InUnit.warn("cann't read address attribute value.");
697 return 0;
698 }
699
700 if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
701 AttrSpec.Attr == dwarf::DW_AT_low_pc) {
702 if (std::optional<uint64_t> LowPC = OutUnit.getAsCompileUnit()->getLowPc())
703 Addr = *LowPC;
704 else
705 return 0;
706 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
707 AttrSpec.Attr == dwarf::DW_AT_high_pc) {
708 if (uint64_t HighPc = OutUnit.getAsCompileUnit()->getHighPc())
709 Addr = HighPc;
710 else
711 return 0;
712 } else {
713 if (AttrSpec.Attr == dwarf::DW_AT_high_pc)
714 Addr = constrainHighPC(*Addr, /*IsLength=*/false);
716 *Addr += *VarAddressAdjustment;
717 else if (FuncAddressAdjustment)
718 *Addr += *FuncAddressAdjustment;
719 }
720
721 if (AttrSpec.Form == dwarf::DW_FORM_addr) {
722 return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, *Addr)
723 .second;
724 }
725
726 return Generator
727 .addScalarAttribute(AttrSpec.Attr, dwarf::Form::DW_FORM_addrx,
728 OutUnit.getAsCompileUnit()->getDebugAddrIndex(*Addr))
729 .second;
730}
731
732uint64_t DIEAttributeCloner::constrainHighPC(uint64_t HighPC, bool IsLength) {
734 return HighPC;
735 std::optional<uint64_t> LowPC =
736 dwarf::toAddress(InUnit.find(InputDieEntry, dwarf::DW_AT_low_pc));
737 if (!LowPC)
738 return HighPC;
739 uint64_t Constrained =
740 InUnit.getContainingFile().Addresses->constrainCodeRangeHighPC(
741 *LowPC, IsLength ? *LowPC + HighPC : HighPC, *FuncAddressAdjustment);
742 return IsLength ? Constrained - *LowPC : Constrained;
743}
744
745unsigned DIEAttributeCloner::finalizeAbbreviations(bool HasChildrenToClone) {
746 // Add the size of the abbreviation number to the output offset.
748 Generator.finalizeAbbreviations(HasChildrenToClone, &PatchesOffsets);
749
750 return AttrOutOffset;
751}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool expressionDependsOnOriginUnit(const DWARFExpression &Expr)
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
A DWARFDataExtractor (typically for an in-memory copy of an object-file section) plus a relocation ma...
This class represents an Operation in the Expression.
Encoding
Size and signedness of expression operations' operands.
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.
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.
uint64_t constrainHighPC(uint64_t HighPC, bool IsLength)
Returns the input DIE's DW_AT_high_pc value HighPC, constrained so the code range it ends stays clear...
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< uint64_t > toAddress(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an address.
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:578
LLVM_ABI unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
Definition LEB128.cpp:19
DWARFExpression::Operation Op
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
static LLVM_ABI bool mayHaveLocationList(dwarf::Attribute Attr)
Identify DWARF attributes that may contain a pointer to a location list.
Definition DWARFDie.cpp:823
static LLVM_ABI bool mayHaveLocationExpr(dwarf::Attribute Attr)
Identifies DWARF attributes that may contain a reference to a DWARF expression.
Definition DWARFDie.cpp:840
This structure is used to update a DW_AT_import reference to a DW_TAG_module.
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.
Where the DW_TAG_module DIE describing a clang module ended up in the output.
Definition ModulePool.h:30