Thanks to visit codestin.com
Credit goes to llvm.org

LLVM 22.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("cann't find referenced DIE.", InputDieEntry);
247 return 0;
248 }
249
250 TypeEntry *RefTypeName = nullptr;
251 const CompileUnit::DIEInfo &RefDIEInfo =
252 RefDiePair->CU->getDIEInfo(RefDiePair->DieEntry);
253 if (RefDIEInfo.needToPlaceInTypeTable())
254 RefTypeName = RefDiePair->CU->getDieTypeEntry(RefDiePair->DieEntry);
255
256 if (OutUnit.isTypeUnit()) {
257 assert(RefTypeName && "Type name for referenced DIE is not set");
258 assert(InUnit.getDieTypeEntry(InputDIEIdx) &&
259 "Type name for DIE is not set");
260
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 return Generator.addScalarAttribute(AttrSpec.Attr, ResultingForm, Value)
518 .second;
519}
520
522 const DWARFFormValue &Val,
524
525 if (OutUnit.isTypeUnit())
526 return 0;
527
528 size_t NumberOfPatchesAtStart = PatchesOffsets.size();
529
530 // If the block is a DWARF Expression, clone it into the temporary
531 // buffer using cloneExpression(), otherwise copy the data directly.
533 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
537 DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()),
538 InUnit.getOrigUnit().isLittleEndian(),
539 InUnit.getOrigUnit().getAddressByteSize());
540 DWARFExpression Expr(Data, InUnit.getOrigUnit().getAddressByteSize(),
541 InUnit.getFormParams().Format);
542
543 InUnit.cloneDieAttrExpression(Expr, Buffer, DebugInfoOutputSection,
545 Bytes = Buffer;
546 }
547
548 // The expression location data might be updated and exceed the original size.
549 // Check whether the new data fits into the original form.
550 dwarf::Form ResultForm = AttrSpec.Form;
551 if ((ResultForm == dwarf::DW_FORM_block1 && Bytes.size() > UINT8_MAX) ||
552 (ResultForm == dwarf::DW_FORM_block2 && Bytes.size() > UINT16_MAX) ||
553 (ResultForm == dwarf::DW_FORM_block4 && Bytes.size() > UINT32_MAX))
554 ResultForm = dwarf::DW_FORM_block;
555
556 size_t FinalAttributeSize;
557 if (AttrSpec.Form == dwarf::DW_FORM_exprloc)
558 FinalAttributeSize =
559 Generator.addLocationAttribute(AttrSpec.Attr, ResultForm, Bytes).second;
560 else
561 FinalAttributeSize =
562 Generator.addBlockAttribute(AttrSpec.Attr, ResultForm, Bytes).second;
563
564 // Update patches offsets with the size of length field for Bytes.
565 for (size_t Idx = NumberOfPatchesAtStart; Idx < PatchesOffsets.size();
566 Idx++) {
567 assert(FinalAttributeSize > Bytes.size());
568 *PatchesOffsets[Idx] +=
569 (AttrOutOffset + (FinalAttributeSize - Bytes.size()));
570 }
571
573 AttrInfo.HasLiveAddress =
574 VarAddressAdjustment.has_value() ||
575 InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
576
577 return FinalAttributeSize;
578}
579
581 const DWARFFormValue &Val,
583 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
584 AttrInfo.HasLiveAddress = true;
585
586 if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
587 return Generator
588 .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Val.getRawUValue())
589 .second;
590
591 if (OutUnit.isTypeUnit())
592 return 0;
593
594 // Cloned Die may have address attributes relocated to a
595 // totally unrelated value. This can happen:
596 // - If high_pc is an address (Dwarf version == 2), then it might have been
597 // relocated to a totally unrelated value (because the end address in the
598 // object file might be start address of another function which got moved
599 // independently by the linker).
600 // - If address relocated in an inline_subprogram that happens at the
601 // beginning of its inlining function.
602 // To avoid above cases and to not apply relocation twice (in
603 // applyValidRelocs and here), read address attribute from InputDIE and apply
604 // Info.PCOffset here.
605
606 std::optional<DWARFFormValue> AddrAttribute =
607 InUnit.find(InputDieEntry, AttrSpec.Attr);
608 if (!AddrAttribute)
609 llvm_unreachable("Cann't find attribute");
610
611 std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();
612 if (!Addr) {
613 InUnit.warn("cann't read address attribute value.");
614 return 0;
615 }
616
617 if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
618 AttrSpec.Attr == dwarf::DW_AT_low_pc) {
619 if (std::optional<uint64_t> LowPC = OutUnit.getAsCompileUnit()->getLowPc())
620 Addr = *LowPC;
621 else
622 return 0;
623 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
624 AttrSpec.Attr == dwarf::DW_AT_high_pc) {
625 if (uint64_t HighPc = OutUnit.getAsCompileUnit()->getHighPc())
626 Addr = HighPc;
627 else
628 return 0;
629 } else {
631 *Addr += *VarAddressAdjustment;
632 else if (FuncAddressAdjustment)
633 *Addr += *FuncAddressAdjustment;
634 }
635
636 if (AttrSpec.Form == dwarf::DW_FORM_addr) {
637 return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, *Addr)
638 .second;
639 }
640
641 return Generator
642 .addScalarAttribute(AttrSpec.Attr, dwarf::Form::DW_FORM_addrx,
643 OutUnit.getAsCompileUnit()->getDebugAddrIndex(*Addr))
644 .second;
645}
646
647unsigned DIEAttributeCloner::finalizeAbbreviations(bool HasChildrenToClone) {
648 // Add the size of the abbreviation number to the output offset.
650 Generator.finalizeAbbreviations(HasChildrenToClone, &PatchesOffsets);
651
652 return AttrOutOffset;
653}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition ArrayRef.h:147
const T * data() const
Definition ArrayRef.h:144
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.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
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:27
StringMapEntry< std::nullopt_t > 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:477
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:189
static LLVM_ABI bool mayHaveLocationList(dwarf::Attribute Attr)
Identify DWARF attributes that may contain a pointer to a location list.
Definition DWARFDie.cpp:737
static LLVM_ABI bool mayHaveLocationExpr(dwarf::Attribute Attr)
Identifies DWARF attributes that may contain a reference to a DWARF expression.
Definition DWARFDie.cpp:754
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.