LLVM: lib/DWARFLinker/Parallel/DIEAttributeCloner.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
11
12using namespace llvm;
15
17
19
21
22
23
26 : InUnit.getOrigUnit().getNextUnitOffset();
27
28
29
30
34
35
36 InUnit.getContaingFile().Addresses->applyValidRelocs(DIECopy, Offset,
37 Data.isLittleEndian());
38
39
40
42
43 const auto *Abbrev = InputDieEntry->getAbbreviationDeclarationPtr();
45
46
48 for (const auto &AttrSpec : Abbrev->attributes()) {
49
52 InUnit.getFormParams());
53 continue;
54 }
55
58 &InUnit.getOrigUnit());
59
60
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:
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:
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:
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:
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:
108 break;
109 default:
110 InUnit.warn("unsupported attribute form " +
112 " in DieAttributeCloner::clone(). Dropping.",
114 }
115 }
116
117
118
119
120 if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
121 InUnit.getVersion() >= 5 && .HasStringOffsetBaseAttr) {
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
150
153 case dwarf::DW_AT_rnglists_base:
154
155
156
157
158 return .getGlobalData().getOptions().UpdateIndexTablesOnly;
159 case dwarf::DW_AT_loclists_base:
160
161
162
163
164 return .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
171
174
175
176
179 }
180}
181
187 InUnit.warn("cann't read string attribute.");
188 return 0;
189 }
190
192 InUnit.getGlobalData().getStringPool().insert(*String).first;
193
194
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()) {
205 StringInPool});
206 } else {
209 }
211 .addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_line_strp)
212 .second;
213 }
214
216 if (OutUnit.isTypeUnit()) {
220 } else {
223 }
224
226 .addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_strp)
227 .second;
228 }
229
231 .addIndexedStringAttribute(AttrSpec.Attr, dwarf::DW_FORM_strx,
232 OutUnit->getDebugStrIndex(StringInPool))
233 .second;
234}
235
239 if (AttrSpec.Attr == dwarf::DW_AT_sibling)
240 return 0;
241
242 std::optional RefDiePair =
244 if (!RefDiePair || !RefDiePair->DieEntry) {
245
247 return 0;
248 }
249
250 TypeEntry *RefTypeName = nullptr;
252 RefDiePair->CU->getDIEInfo(RefDiePair->DieEntry);
254 RefTypeName = RefDiePair->CU->getDieTypeEntry(RefDiePair->DieEntry);
255
256 if (OutUnit.isTypeUnit()) {
257 assert(RefTypeName && "Type name for referenced DIE is not set");
259 "Type name for DIE is not set");
260
263 RefTypeName});
264
266 .addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref4, 0xBADDEF)
267 .second;
268 }
269
270 if (RefTypeName) {
273
275 .addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref_addr, 0xBADDEF)
276 .second;
277 }
278
279
280 uint64_t OutDieOffset = RefDiePair->CU->getDieOutOffset(RefDiePair->DieEntry);
281
282
283 bool IsLocal = OutUnit->getUniqueID() == RefDiePair->CU->getUniqueID();
284
285
286 dwarf::Form NewForm = IsLocal ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr;
287
288
289
290 if (IsLocal && (OutDieOffset != 0))
291 return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, OutDieOffset)
292 .second;
293
294
295
298 RefDiePair->CU,
299 RefDiePair->CU->getDIEIndex(RefDiePair->DieEntry)},
301 return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, 0xBADDEF).second;
302}
303
307
308
309
310
311 switch (AttrSpec.Attr) {
312 case dwarf::DW_AT_macro_info: {
315 InUnit.getContaingFile().Dwarf->getDebugMacinfo();
317 return 0;
318
321 &OutUnit->getOrCreateSectionDescriptor(
324 }
325 } break;
326 case dwarf::DW_AT_macros: {
329 InUnit.getContaingFile().Dwarf->getDebugMacro();
331 return 0;
332
335 &OutUnit->getOrCreateSectionDescriptor(
338 }
339 } break;
340 case dwarf::DW_AT_stmt_list: {
345 } break;
346 case dwarf::DW_AT_str_offsets_base: {
349 &OutUnit->getOrCreateSectionDescriptor(
351 true},
353
354
355
356 AttrInfo.HasStringOffsetBaseAttr = true;
358 .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form,
359 OutUnit->getDebugStrOffsetsHeaderSize())
360 .second;
361 } break;
362 case dwarf::DW_AT_decl_file: {
363
364
365
366
367
368 if (OutUnit.isTypeUnit()) {
369 if (std::optional<std::pair<StringRef, StringRef>> DirAndFilename =
370 InUnit.getDirAndFilenameFromLineTable(Val))
375 .getStringPool()
376 .insert(DirAndFilename->first)
377 .first,
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) {
398 Value = *OptionalValue;
400 Value = *OptionalValue;
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)
414 .second;
415
417 .second;
418 }
419
421 if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {
422
423
424
426 if (!Index) {
428 return 0;
429 }
430 std::optional<uint64_t> Offset =
431 InUnit.getOrigUnit().getRnglistOffset(*Index);
434 return 0;
435 }
436
438 ResultingForm = dwarf::DW_FORM_sec_offset;
439 } else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {
440
441
442
444 if (!Index) {
446 return 0;
447 }
448 std::optional<uint64_t> Offset =
449 InUnit.getOrigUnit().getLoclistOffset(*Index);
452 return 0;
453 }
454
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 (.isCompileUnit())
460 return 0;
461
462 std::optional<uint64_t> LowPC = OutUnit.getAsCompileUnit()->getLowPc();
463 if (!LowPC)
464 return 0;
465
466 Value = OutUnit.getAsCompileUnit()->getHighPc() - *LowPC;
467 } else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
469 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
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
484 InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit},
490 InUnit.getOrigUnit().getVersion())) {
491 int64_t AddrAdjustmentValue = 0;
496
497
500 } else if (AttrSpec.Attr == dwarf::DW_AT_addr_base) {
505 true},
507
508
509
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
524
525 if (OutUnit.isTypeUnit())
526 return 0;
527
528 size_t NumberOfPatchesAtStart = PatchesOffsets.size();
529
530
531
538 InUnit.getOrigUnit().isLittleEndian(),
539 InUnit.getOrigUnit().getAddressByteSize());
541 InUnit.getFormParams().Format);
542
545 Bytes = Buffer;
546 }
547
548
549
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
565 for (size_t Idx = NumberOfPatchesAtStart; Idx < PatchesOffsets.size();
566 Idx++) {
567 assert(FinalAttributeSize > Bytes.size());
570 }
571
575 InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
576
577 return FinalAttributeSize;
578}
579
583 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
584 AttrInfo.HasLiveAddress = true;
585
586 if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
589 .second;
590
591 if (OutUnit.isTypeUnit())
592 return 0;
593
594
595
596
597
598
599
600
601
602
603
604
605
606 std::optional AddrAttribute =
608 if (!AddrAttribute)
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 {
634 }
635
636 if (AttrSpec.Form == dwarf::DW_FORM_addr) {
637 return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, *Addr)
638 .second;
639 }
640
642 .addScalarAttribute(AttrSpec.Attr, dwarf::Form::DW_FORM_addrx,
643 OutUnit.getAsCompileUnit()->getDebugAddrIndex(*Addr))
644 .second;
645}
646
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
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...
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.
LLVM Value Representation.
size_t cloneBlockAttr(const DWARFFormValue &Val, const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec)
Clone block or exprloc attribute.
Definition DIEAttributeCloner.cpp:521
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.
Definition DIEAttributeCloner.cpp:647
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.
Definition DIEAttributeCloner.cpp:304
OffsetsPtrVector PatchesOffsets
Patches for the cloned attributes.
void clone()
Clone attributes of input DIE.
Definition DIEAttributeCloner.cpp:16
size_t cloneDieRefAttr(const DWARFFormValue &Val, const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec)
Clone attribute referencing another DIE.
Definition DIEAttributeCloner.cpp:236
bool shouldSkipAttribute(DWARFAbbreviationDeclaration::AttributeSpec AttrSpec)
Returns true if attribute should be skipped.
Definition DIEAttributeCloner.cpp:138
size_t cloneStringAttr(const DWARFFormValue &Val, const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec)
Clone string attribute.
Definition DIEAttributeCloner.cpp:182
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.
Definition DIEAttributeCloner.cpp:580
uint32_t InputDIEIdx
Input DIE index.
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)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
StringMapEntry< EmptyStringSetTag > StringEntry
StringEntry keeps data of the string: the length, external offset and a string body which is placed r...
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.
LLVM_ABI unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
static LLVM_ABI bool mayHaveLocationList(dwarf::Attribute Attr)
Identify DWARF attributes that may contain a pointer to a location list.
static LLVM_ABI bool mayHaveLocationExpr(dwarf::Attribute Attr)
Identifies DWARF attributes that may contain a reference to a DWARF expression.
Information gathered about source DIEs.
bool needToPlaceInTypeTable() const
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.