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