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 unit already has DW_AT_str_offsets_base
119 // attribute.
120 if (InputDIEIdx == 0 && InUnit.getVersion() >= 5 &&
121 !AttrInfo.HasStringOffsetBaseAttr && OutUnit.isCompileUnit()) {
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 // No DW_AT_addr_base: add one for the addrx-indexed entries. Except in
138 // update mode, where HasAddrBaseAttr is never set.
139 if (InputDIEIdx == 0 && InUnit.getVersion() >= 5 &&
140 !AttrInfo.HasAddrBaseAttr &&
141 !InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly) {
142 DebugInfoOutputSection.notePatchWithOffsetUpdate(
145 &OutUnit->getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr),
146 true},
148
150 .addScalarAttribute(dwarf::DW_AT_addr_base,
151 dwarf::DW_FORM_sec_offset,
152 OutUnit->getDebugAddrHeaderSize())
153 .second;
154 }
155}
156
159 switch (AttrSpec.Attr) {
160 default:
161 return false;
162 case dwarf::DW_AT_low_pc:
163 case dwarf::DW_AT_high_pc:
164 case dwarf::DW_AT_ranges:
165 if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
166 return false;
167
168 // Skip address attribute if we are in function scope and function does not
169 // reference live address.
170 return InUnit.getDIEInfo(InputDIEIdx).getIsInFunctionScope() &&
171 !FuncAddressAdjustment.has_value();
172 case dwarf::DW_AT_rnglists_base:
173 // In case !Update the .debug_addr table is not generated/preserved.
174 // Thus instead of DW_FORM_rnglistx the DW_FORM_sec_offset is used.
175 // Since DW_AT_rnglists_base is used for only DW_FORM_rnglistx the
176 // DW_AT_rnglists_base is removed.
177 return !InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
178 case dwarf::DW_AT_loclists_base:
179 // In case !Update the .debug_addr table is not generated/preserved.
180 // Thus instead of DW_FORM_loclistx the DW_FORM_sec_offset is used.
181 // Since DW_AT_loclists_base is used for only DW_FORM_loclistx the
182 // DW_AT_loclists_base is removed.
183 return !InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
184 case dwarf::DW_AT_location:
185 case dwarf::DW_AT_frame_base:
186 if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
187 return false;
188
189 // When location expression contains an address: skip this attribute
190 // if it does not reference live address.
192 return !VarAddressAdjustment.has_value();
193
194 // Skip location attribute if we are in function scope and function does not
195 // reference live address.
196 return InUnit.getDIEInfo(InputDIEIdx).getIsInFunctionScope() &&
197 !FuncAddressAdjustment.has_value();
198 }
199}
200
202 const DWARFFormValue &Val,
204 std::optional<const char *> String = dwarf::toString(Val);
205 if (!String) {
206 InUnit.warn("cann't read string attribute.");
207 return 0;
208 }
209
210 StringEntry *StringInPool =
211 InUnit.getGlobalData().getStringPool().insert(*String).first;
212
213 // Update attributes info.
214 if (AttrSpec.Attr == dwarf::DW_AT_name)
215 AttrInfo.Name = StringInPool;
216 else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||
217 AttrSpec.Attr == dwarf::DW_AT_linkage_name)
218 AttrInfo.MangledName = StringInPool;
219
220 if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {
221 if (OutUnit.isTypeUnit()) {
223 AttrOutOffset, OutDIE, InUnit.getDieTypeEntry(InputDIEIdx),
224 StringInPool});
225 } else {
226 DebugInfoOutputSection.notePatchWithOffsetUpdate(
228 }
229 return Generator
230 .addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_line_strp)
231 .second;
232 }
233
234 if (Use_DW_FORM_strp) {
235 if (OutUnit.isTypeUnit()) {
236 DebugInfoOutputSection.notePatch(
238 InUnit.getDieTypeEntry(InputDIEIdx), StringInPool});
239 } else {
240 DebugInfoOutputSection.notePatchWithOffsetUpdate(
241 DebugStrPatch{{AttrOutOffset}, StringInPool}, PatchesOffsets);
242 }
243
244 return Generator
245 .addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_strp)
246 .second;
247 }
248
249 return Generator
250 .addIndexedStringAttribute(AttrSpec.Attr, dwarf::DW_FORM_strx,
251 OutUnit->getDebugStrIndex(StringInPool))
252 .second;
253}
254
256 const DWARFFormValue &Val,
258 if (AttrSpec.Attr == dwarf::DW_AT_sibling)
259 return 0;
260
261 std::optional<UnitEntryPairTy> RefDiePair =
262 InUnit.resolveDIEReference(Val, ResolveInterCUReferencesMode::Resolve);
263 if (!RefDiePair || !RefDiePair->DieEntry) {
264 // If the referenced DIE is not found, drop the attribute.
265 InUnit.warn("could not find referenced DIE", InputDieEntry);
266 return 0;
267 }
268
269 TypeEntry *RefTypeName = nullptr;
270 const CompileUnit::DIEInfo &RefDIEInfo =
271 RefDiePair->CU->getDIEInfo(RefDiePair->DieEntry);
272 if (RefDIEInfo.needToPlaceInTypeTable())
273 RefTypeName = RefDiePair->CU->getDieTypeEntry(RefDiePair->DieEntry);
274
275 // The importing unit's DW_TAG_module skeleton can have a different
276 // DW_AT_LLVM_include_path than the unit built from the .pcm and the import
277 // must use the latter. The type pool already merges copies, so a reference
278 // with a type entry resolves correctly. Without one, the module's anchor is
279 // the only link between the two, and it is not known until the unit
280 // describing the module has been emitted.
281 if (RefDiePair->DieEntry->getTag() == dwarf::DW_TAG_module &&
282 AttrSpec.Attr == dwarf::DW_AT_import && !OutUnit.isTypeUnit() &&
283 !RefTypeName) {
284 SmallString<128> Path;
285 if (RefDiePair->CU->getModulePath(RefDiePair->DieEntry, Path)) {
286 ModuleAnchor *Anchor =
287 InUnit.getGlobalData().getModulePool().getOrCreate(Path);
288
289 DebugInfoOutputSection.notePatchWithOffsetUpdate(
291 AttrOutOffset, RefDiePair->CU,
292 RefDiePair->CU->getDIEIndex(RefDiePair->DieEntry), Anchor},
294 return Generator
295 .addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref_addr, 0xBADDEF)
296 .second;
297 }
298 }
299
300 if (OutUnit.isTypeUnit()) {
301 assert(RefTypeName && "Type name for referenced DIE is not set");
302 assert(InUnit.getDieTypeEntry(InputDIEIdx) &&
303 "Type name for DIE is not set");
304
306 AttrOutOffset, OutDIE, InUnit.getDieTypeEntry(InputDIEIdx),
307 RefTypeName});
308
309 return Generator
310 .addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref4, 0xBADDEF)
311 .second;
312 }
313
314 if (RefTypeName) {
315 DebugInfoOutputSection.notePatchWithOffsetUpdate(
317
318 return Generator
319 .addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref_addr, 0xBADDEF)
320 .second;
321 }
322
323 // Get output offset for referenced DIE.
324 uint64_t OutDieOffset = RefDiePair->CU->getDieOutOffset(RefDiePair->DieEntry);
325
326 // Examine whether referenced DIE is in current compile unit.
327 bool IsLocal = OutUnit->getUniqueID() == RefDiePair->CU->getUniqueID();
328
329 // Set attribute form basing on the kind of referenced DIE(local or not?).
330 dwarf::Form NewForm = IsLocal ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr;
331
332 // Check whether current attribute references already cloned DIE inside
333 // the same compilation unit. If true - write the already known offset value.
334 if (IsLocal && (OutDieOffset != 0))
335 return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, OutDieOffset)
336 .second;
337
338 // If offset value is not known at this point then create patch for the
339 // reference value and write dummy value into the attribute.
340 DebugInfoOutputSection.notePatchWithOffsetUpdate(
341 DebugDieRefPatch{AttrOutOffset, OutUnit.getAsCompileUnit(),
342 RefDiePair->CU,
343 RefDiePair->CU->getDIEIndex(RefDiePair->DieEntry)},
345 return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, 0xBADDEF).second;
346}
347
349 const DWARFFormValue &Val,
351
352 // Create patches for attribute referencing other non invariant section.
353 // Invariant section could not be updated here as this section and
354 // reference to it do not change value in case --update.
355 switch (AttrSpec.Attr) {
356 case dwarf::DW_AT_macro_info: {
357 if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {
358 const DWARFDebugMacro *Macro =
359 InUnit.getContainingFile().Dwarf->getDebugMacinfo();
360 if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset))
361 return 0;
362
363 DebugInfoOutputSection.notePatchWithOffsetUpdate(
365 &OutUnit->getOrCreateSectionDescriptor(
368 }
369 } break;
370 case dwarf::DW_AT_macros: {
371 if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {
372 const DWARFDebugMacro *Macro =
373 InUnit.getContainingFile().Dwarf->getDebugMacro();
374 if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset))
375 return 0;
376
377 DebugInfoOutputSection.notePatchWithOffsetUpdate(
379 &OutUnit->getOrCreateSectionDescriptor(
382 }
383 } break;
384 case dwarf::DW_AT_stmt_list: {
385 DebugInfoOutputSection.notePatchWithOffsetUpdate(
386 DebugOffsetPatch{AttrOutOffset, &OutUnit->getOrCreateSectionDescriptor(
389 } break;
390 case dwarf::DW_AT_str_offsets_base: {
391 DebugInfoOutputSection.notePatchWithOffsetUpdate(
393 &OutUnit->getOrCreateSectionDescriptor(
395 true},
397
398 // Use size of .debug_str_offsets header as attribute value. The offset
399 // to .debug_str_offsets would be added later while patching.
400 AttrInfo.HasStringOffsetBaseAttr = true;
401 return Generator
402 .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form,
403 OutUnit->getDebugStrOffsetsHeaderSize())
404 .second;
405 } break;
406 case dwarf::DW_AT_decl_file: {
407 // Value of DW_AT_decl_file may exceed original form. Longer
408 // form can affect offsets to the following attributes. To not
409 // update offsets of the following attributes we always remove
410 // original DW_AT_decl_file and attach it to the last position
411 // later.
412 if (OutUnit.isTypeUnit()) {
413 if (std::optional<std::pair<StringRef, StringRef>> DirAndFilename =
414 InUnit.getDirAndFilenameFromLineTable(Val))
416 OutDIE,
417 InUnit.getDieTypeEntry(InputDIEIdx),
418 OutUnit->getGlobalData()
419 .getStringPool()
420 .insert(DirAndFilename->first)
421 .first,
422 OutUnit->getGlobalData()
423 .getStringPool()
424 .insert(DirAndFilename->second)
425 .first,
426 });
427 return 0;
428 }
429 } break;
430 default: {
431 } break;
432 };
433
434 uint64_t Value;
435 if (AttrSpec.Attr == dwarf::DW_AT_const_value &&
436 (InputDieEntry->getTag() == dwarf::DW_TAG_variable ||
437 InputDieEntry->getTag() == dwarf::DW_TAG_constant))
438 AttrInfo.HasLiveAddress = true;
439
440 if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly) {
441 if (auto OptionalValue = Val.getAsUnsignedConstant())
442 Value = *OptionalValue;
443 else if (auto OptionalValue = Val.getAsSignedConstant())
444 Value = *OptionalValue;
445 else if (auto OptionalValue = Val.getAsSectionOffset())
446 Value = *OptionalValue;
447 else {
448 InUnit.warn("unsupported scalar attribute form. Dropping attribute.",
450 return 0;
451 }
452
453 if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
454 AttrInfo.IsDeclaration = true;
455
456 if (AttrSpec.Form == dwarf::DW_FORM_loclistx)
457 return Generator.addLocListAttribute(AttrSpec.Attr, AttrSpec.Form, Value)
458 .second;
459
460 return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Value)
461 .second;
462 }
463
464 dwarf::Form ResultingForm = AttrSpec.Form;
465 if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {
466 // DWARFLinker does not generate .debug_addr table. Thus we need to change
467 // all "addrx" related forms to "addr" version. Change DW_FORM_rnglistx
468 // to DW_FORM_sec_offset here.
469 std::optional<uint64_t> Index = Val.getAsSectionOffset();
470 if (!Index) {
471 InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
472 return 0;
473 }
474 std::optional<uint64_t> Offset =
475 InUnit.getOrigUnit().getRnglistOffset(*Index);
476 if (!Offset) {
477 InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
478 return 0;
479 }
480
481 Value = *Offset;
482 ResultingForm = dwarf::DW_FORM_sec_offset;
483 } else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {
484 // DWARFLinker does not generate .debug_addr table. Thus we need to change
485 // all "addrx" related forms to "addr" version. Change DW_FORM_loclistx
486 // to DW_FORM_sec_offset here.
487 std::optional<uint64_t> Index = Val.getAsSectionOffset();
488 if (!Index) {
489 InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
490 return 0;
491 }
492 std::optional<uint64_t> Offset =
493 InUnit.getOrigUnit().getLoclistOffset(*Index);
494 if (!Offset) {
495 InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
496 return 0;
497 }
498
499 Value = *Offset;
500 ResultingForm = dwarf::DW_FORM_sec_offset;
501 } else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
502 InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) {
503 if (!OutUnit.isCompileUnit())
504 return 0;
505
506 std::optional<uint64_t> LowPC = OutUnit.getAsCompileUnit()->getLowPc();
507 if (!LowPC)
508 return 0;
509 // Dwarf >= 4 high_pc is an size, not an address.
510 Value = OutUnit.getAsCompileUnit()->getHighPc() - *LowPC;
511 } else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
512 Value = *Val.getAsSectionOffset();
513 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
514 Value = *Val.getAsSignedConstant();
515 else if (auto OptionalValue = Val.getAsUnsignedConstant())
516 Value = *OptionalValue;
517 else {
518 InUnit.warn("unsupported scalar attribute form. Dropping attribute.",
520 return 0;
521 }
522
523 if (AttrSpec.Attr == dwarf::DW_AT_ranges ||
524 AttrSpec.Attr == dwarf::DW_AT_start_scope) {
525 // Create patch for the range offset value.
526 DebugInfoOutputSection.notePatchWithOffsetUpdate(
528 InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit},
530 AttrInfo.HasRanges = true;
531 } else if (DWARFAttribute::mayHaveLocationList(AttrSpec.Attr) &&
534 InUnit.getOrigUnit().getVersion())) {
535 int64_t AddrAdjustmentValue = 0;
537 AddrAdjustmentValue = *VarAddressAdjustment;
538 else if (FuncAddressAdjustment)
539 AddrAdjustmentValue = *FuncAddressAdjustment;
540
541 // Create patch for the location offset value.
542 DebugInfoOutputSection.notePatchWithOffsetUpdate(
543 DebugLocPatch{{AttrOutOffset}, AddrAdjustmentValue}, PatchesOffsets);
544 } else if (AttrSpec.Attr == dwarf::DW_AT_addr_base) {
545 DebugInfoOutputSection.notePatchWithOffsetUpdate(
548 &OutUnit->getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr),
549 true},
551
552 // Use size of .debug_addr header as attribute value. The offset to
553 // .debug_addr would be added later while patching.
554 AttrInfo.HasAddrBaseAttr = true;
555 return Generator
556 .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form,
557 OutUnit->getDebugAddrHeaderSize())
558 .second;
559 } else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
560 AttrInfo.IsDeclaration = true;
561
562 // DW_AT_LLVM_stmt_sequence refers to line info in this unit's
563 // .debug_line contribution, which only exists for compile units.
564 // DependencyTracker can route a module-scope subprogram to a type
565 // unit when ODR deduplication applies (see
566 // DependencyTracker.cpp: DW_TAG_subprogram case), so drop the
567 // attribute on that path — mirroring how cloneBlockAttr handles
568 // type-unit placement.
569 if (AttrSpec.Attr == dwarf::DW_AT_LLVM_stmt_sequence &&
570 !OutUnit.isCompileUnit())
571 return 0;
572
573 // A compile unit's high_pc comes from the unit's own linked range and spans
574 // every symbol in it.
575 if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
576 InputDieEntry->getTag() != dwarf::DW_TAG_compile_unit)
577 Value = constrainHighPC(Value, /*IsLength=*/true);
578
579 auto Result =
580 Generator.addScalarAttribute(AttrSpec.Attr, ResultingForm, Value);
581 // Record DW_AT_LLVM_stmt_sequence so the attribute value can be
582 // rewritten with the correct .debug_line offset after the line table
583 // for this CU has been emitted. We also register a DebugOffsetPatch so
584 // that the final-section offset of .debug_line gets added when the
585 // section is placed in the combined output.
586 if (AttrSpec.Attr == dwarf::DW_AT_LLVM_stmt_sequence) {
587 // Record the attribute's raw input stmt-sequence offset. Resolution
588 // to a first-row index — including the boundary-walk fallback for
589 // sequences the DWARF parser may not have registered — happens in
590 // a post-cloning pass (buildStmtSeqOffsetToFirstRowIndex), so that
591 // matches the classic linker's behaviour.
592 OutUnit.getAsCompileUnit()->noteStmtSeqListAttribute(&Result.first, Value);
593 DebugInfoOutputSection.notePatchWithOffsetUpdate(
596 &OutUnit->getOrCreateSectionDescriptor(DebugSectionKind::DebugLine),
597 /*AddLocalValue=*/true},
599 }
600 return Result.second;
601}
602
605
606 for (const DWARFExpression::Operation &Op : Expr) {
607 switch (Op.getCode()) {
608 case dwarf::DW_OP_addr:
609 case dwarf::DW_OP_addrx:
610 case dwarf::DW_OP_constx:
611 return true;
612 default:
613 break;
614 }
615
616 if (llvm::is_contained(Op.getDescription().Op, Encoding::BaseTypeRef))
617 return true;
618 }
619
620 return false;
621}
622
624 const DWARFFormValue &Val,
626
627 size_t NumberOfPatchesAtStart = PatchesOffsets.size();
628
629 // If the block is a DWARF Expression, clone it into the temporary
630 // buffer using cloneExpression(), otherwise copy the data directly.
632 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
636 DataExtractor Data(Bytes, InUnit.getOrigUnit().isLittleEndian());
637 DWARFExpression Expr(Data, InUnit.getOrigUnit().getAddressByteSize(),
638 InUnit.getFormParams().Format);
639
640 // A type unit is shared by every compile unit that references the type, so
641 // an expression resolving against one origin unit has no single correct
642 // value there.
643 if (OutUnit.isTypeUnit() && expressionDependsOnOriginUnit(Expr))
644 return 0;
645
646 InUnit.cloneDieAttrExpression(Expr, Buffer, DebugInfoOutputSection,
648 Bytes = Buffer;
649 }
650
651 // The expression location data might be updated and exceed the original size.
652 // Check whether the new data fits into the original form.
653 dwarf::Form ResultForm = AttrSpec.Form;
654 if ((ResultForm == dwarf::DW_FORM_block1 && Bytes.size() > UINT8_MAX) ||
655 (ResultForm == dwarf::DW_FORM_block2 && Bytes.size() > UINT16_MAX) ||
656 (ResultForm == dwarf::DW_FORM_block4 && Bytes.size() > UINT32_MAX))
657 ResultForm = dwarf::DW_FORM_block;
658
659 size_t FinalAttributeSize;
660 if (AttrSpec.Form == dwarf::DW_FORM_exprloc)
661 FinalAttributeSize =
662 Generator.addLocationAttribute(AttrSpec.Attr, ResultForm, Bytes).second;
663 else
664 FinalAttributeSize =
665 Generator.addBlockAttribute(AttrSpec.Attr, ResultForm, Bytes).second;
666
667 // Update patches offsets with the size of length field for Bytes.
668 for (size_t Idx = NumberOfPatchesAtStart; Idx < PatchesOffsets.size();
669 Idx++) {
670 assert(FinalAttributeSize > Bytes.size());
671 *PatchesOffsets[Idx] +=
672 (AttrOutOffset + (FinalAttributeSize - Bytes.size()));
673 }
674
676 AttrInfo.HasLiveAddress =
677 VarAddressAdjustment.has_value() ||
678 InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
679
680 return FinalAttributeSize;
681}
682
684 const DWARFFormValue &Val,
686 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
687 AttrInfo.HasLiveAddress = true;
688
689 if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
690 return Generator
691 .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Val.getRawUValue())
692 .second;
693
694 if (OutUnit.isTypeUnit())
695 return 0;
696
697 // Cloned Die may have address attributes relocated to a
698 // totally unrelated value. This can happen:
699 // - If high_pc is an address (Dwarf version == 2), then it might have been
700 // relocated to a totally unrelated value (because the end address in the
701 // object file might be start address of another function which got moved
702 // independently by the linker).
703 // - If address relocated in an inline_subprogram that happens at the
704 // beginning of its inlining function.
705 // To avoid above cases and to not apply relocation twice (in
706 // applyValidRelocs and here), read address attribute from InputDIE and apply
707 // Info.PCOffset here.
708
709 std::optional<DWARFFormValue> AddrAttribute =
710 InUnit.find(InputDieEntry, AttrSpec.Attr);
711 if (!AddrAttribute)
712 llvm_unreachable("Cann't find attribute");
713
714 std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();
715 if (!Addr) {
716 InUnit.warn("cann't read address attribute value.");
717 return 0;
718 }
719
720 if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
721 AttrSpec.Attr == dwarf::DW_AT_low_pc) {
722 if (std::optional<uint64_t> LowPC = OutUnit.getAsCompileUnit()->getLowPc())
723 Addr = *LowPC;
724 else
725 return 0;
726 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
727 AttrSpec.Attr == dwarf::DW_AT_high_pc) {
728 if (uint64_t HighPc = OutUnit.getAsCompileUnit()->getHighPc())
729 Addr = HighPc;
730 else
731 return 0;
732 } else {
733 if (AttrSpec.Attr == dwarf::DW_AT_high_pc)
734 Addr = constrainHighPC(*Addr, /*IsLength=*/false);
736 *Addr += *VarAddressAdjustment;
737 else if (FuncAddressAdjustment)
738 *Addr += *FuncAddressAdjustment;
739 }
740
741 if (AttrSpec.Form == dwarf::DW_FORM_addr) {
742 return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, *Addr)
743 .second;
744 }
745
746 return Generator
747 .addScalarAttribute(AttrSpec.Attr, dwarf::Form::DW_FORM_addrx,
748 OutUnit.getAsCompileUnit()->getDebugAddrIndex(*Addr))
749 .second;
750}
751
752uint64_t DIEAttributeCloner::constrainHighPC(uint64_t HighPC, bool IsLength) {
754 return HighPC;
755 std::optional<uint64_t> LowPC =
756 dwarf::toAddress(InUnit.find(InputDieEntry, dwarf::DW_AT_low_pc));
757 if (!LowPC)
758 return HighPC;
759 uint64_t Constrained =
760 InUnit.getContainingFile().Addresses->constrainCodeRangeHighPC(
761 *LowPC, IsLength ? *LowPC + HighPC : HighPC, *FuncAddressAdjustment);
762 return IsLength ? Constrained - *LowPC : Constrained;
763}
764
765unsigned DIEAttributeCloner::finalizeAbbreviations(bool HasChildrenToClone) {
766 // Add the size of the abbreviation number to the output offset.
768 Generator.finalizeAbbreviations(HasChildrenToClone, &PatchesOffsets);
769
770 return AttrOutOffset;
771}
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:577
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:1963
static LLVM_ABI bool mayHaveLocationList(dwarf::Attribute Attr)
Identify DWARF attributes that may contain a pointer to a location list.
Definition DWARFDie.cpp:836
static LLVM_ABI bool mayHaveLocationExpr(dwarf::Attribute Attr)
Identifies DWARF attributes that may contain a reference to a DWARF expression.
Definition DWARFDie.cpp:853
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