7
7
// ===----------------------------------------------------------------------===//
8
8
9
9
#include " llvm/DebugInfo/DWARF/DWARFDie.h"
10
+ #include " llvm/ADT/SmallPtrSet.h"
10
11
#include " llvm/ADT/SmallSet.h"
11
12
#include " llvm/ADT/StringRef.h"
12
13
#include " llvm/BinaryFormat/Dwarf.h"
@@ -489,18 +490,23 @@ void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
489
490
CallDiscriminator = toUnsigned (find (DW_AT_GNU_discriminator), 0 );
490
491
}
491
492
492
- std::optional<uint64_t > DWARFDie::getTypeSize (uint64_t PointerSize) {
493
- if (auto SizeAttr = find (DW_AT_byte_size))
493
+ static std::optional<uint64_t >
494
+ getTypeSizeImpl (DWARFDie Die, uint64_t PointerSize,
495
+ SmallPtrSetImpl<const DWARFDebugInfoEntry *> &Visited) {
496
+ // Cycle detected?
497
+ if (!Visited.insert (Die.getDebugInfoEntry ()).second )
498
+ return {};
499
+ if (auto SizeAttr = Die.find (DW_AT_byte_size))
494
500
if (std::optional<uint64_t > Size = SizeAttr->getAsUnsignedConstant ())
495
501
return Size;
496
502
497
- switch (getTag ()) {
503
+ switch (Die. getTag ()) {
498
504
case DW_TAG_pointer_type:
499
505
case DW_TAG_reference_type:
500
506
case DW_TAG_rvalue_reference_type:
501
507
return PointerSize;
502
508
case DW_TAG_ptr_to_member_type: {
503
- if (DWARFDie BaseType = getAttributeValueAsReferencedDie (DW_AT_type))
509
+ if (DWARFDie BaseType = Die. getAttributeValueAsReferencedDie (DW_AT_type))
504
510
if (BaseType.getTag () == DW_TAG_subroutine_type)
505
511
return 2 * PointerSize;
506
512
return PointerSize;
@@ -510,19 +516,20 @@ std::optional<uint64_t> DWARFDie::getTypeSize(uint64_t PointerSize) {
510
516
case DW_TAG_volatile_type:
511
517
case DW_TAG_restrict_type:
512
518
case DW_TAG_typedef: {
513
- if (DWARFDie BaseType = getAttributeValueAsReferencedDie (DW_AT_type))
514
- return BaseType. getTypeSize ( PointerSize);
519
+ if (DWARFDie BaseType = Die. getAttributeValueAsReferencedDie (DW_AT_type))
520
+ return getTypeSizeImpl (BaseType, PointerSize, Visited );
515
521
break ;
516
522
}
517
523
case DW_TAG_array_type: {
518
- DWARFDie BaseType = getAttributeValueAsReferencedDie (DW_AT_type);
524
+ DWARFDie BaseType = Die. getAttributeValueAsReferencedDie (DW_AT_type);
519
525
if (!BaseType)
520
526
return std::nullopt;
521
- std::optional<uint64_t > BaseSize = BaseType.getTypeSize (PointerSize);
527
+ std::optional<uint64_t > BaseSize =
528
+ getTypeSizeImpl (BaseType, PointerSize, Visited);
522
529
if (!BaseSize)
523
530
return std::nullopt;
524
531
uint64_t Size = *BaseSize;
525
- for (DWARFDie Child : * this ) {
532
+ for (DWARFDie Child : Die ) {
526
533
if (Child.getTag () != DW_TAG_subrange_type)
527
534
continue ;
528
535
@@ -542,13 +549,18 @@ std::optional<uint64_t> DWARFDie::getTypeSize(uint64_t PointerSize) {
542
549
return Size;
543
550
}
544
551
default :
545
- if (DWARFDie BaseType = getAttributeValueAsReferencedDie (DW_AT_type))
546
- return BaseType. getTypeSize ( PointerSize);
552
+ if (DWARFDie BaseType = Die. getAttributeValueAsReferencedDie (DW_AT_type))
553
+ return getTypeSizeImpl (BaseType, PointerSize, Visited );
547
554
break ;
548
555
}
549
556
return std::nullopt;
550
557
}
551
558
559
+ std::optional<uint64_t > DWARFDie::getTypeSize (uint64_t PointerSize) {
560
+ SmallPtrSet<const DWARFDebugInfoEntry *, 4 > Visited;
561
+ return getTypeSizeImpl (*this , PointerSize, Visited);
562
+ }
563
+
552
564
// / Helper to dump a DIE with all of its parents, but no siblings.
553
565
static unsigned dumpParentChain (DWARFDie Die, raw_ostream &OS, unsigned Indent,
554
566
DIDumpOptions DumpOpts, unsigned Depth = 0 ) {
0 commit comments