diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h --- a/llvm/include/llvm/MC/MCDwarf.h +++ b/llvm/include/llvm/MC/MCDwarf.h @@ -696,6 +696,9 @@ unsigned RAReg = static_cast(INT_MAX); bool IsBKeyFrame = false; bool IsMTETaggedFrame = false; + // If true, this frame's personality symbol is one of the three "canonical": + // __gxx_personality_v0, __gcc_personality_v0,__objc_personality_v0. + bool IsCanonicalPersonality = false; }; class MCDwarfFrameEmitter { diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -1858,20 +1858,22 @@ ArrayRef FrameArray = Streamer.getDwarfFrameInfos(); // Emit the compact unwind info if available. + // But only for canonical personality functions (gxx, gcc and objc). bool NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame(); if (IsEH && MOFI->getCompactUnwindSection()) { Streamer.generateCompactUnwindEncodings(MAB); bool SectionEmitted = false; for (const MCDwarfFrameInfo &Frame : FrameArray) { - if (Frame.CompactUnwindEncoding == 0) continue; + if (Frame.CompactUnwindEncoding == 0 || !Frame.IsCanonicalPersonality) + continue; if (!SectionEmitted) { Streamer.switchSection(MOFI->getCompactUnwindSection()); Streamer.emitValueToAlignment(Align(AsmInfo->getCodePointerSize())); SectionEmitted = true; } - NeedsEHFrameSection |= - Frame.CompactUnwindEncoding == - MOFI->getCompactUnwindDwarfEHFrameOnly(); + NeedsEHFrameSection |= Frame.CompactUnwindEncoding == + MOFI->getCompactUnwindDwarfEHFrameOnly() || + !Frame.IsCanonicalPersonality; Emitter.EmitCompactUnwind(Frame); } } @@ -1902,10 +1904,14 @@ for (auto I = FrameArrayX.begin(), E = FrameArrayX.end(); I != E;) { const MCDwarfFrameInfo &Frame = *I; ++I; - if (CanOmitDwarf && Frame.CompactUnwindEncoding != - MOFI->getCompactUnwindDwarfEHFrameOnly()) + if (CanOmitDwarf && + Frame.CompactUnwindEncoding != + MOFI->getCompactUnwindDwarfEHFrameOnly() && + Frame.IsCanonicalPersonality) // Don't generate an EH frame if we don't need one. I.e., it's taken care // of by the compact unwind encoding. + // But if the frame contains non-canonical personality, then always emits + // DWARF. continue; CIEKey Key(Frame); diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -573,6 +573,16 @@ return; CurFrame->Personality = Sym; CurFrame->PersonalityEncoding = Encoding; + + if (Sym && Sym.isMachO()) { + StringRef name = Sym.getName(); + // FIXME: Could have a set here for quick lookup - but we only have 3 + // entries. + CurFrame->IsCanonicalPersonality = + name.compare("__gxx_personality_v0,") == 0 || + name.compare("__gcc_personality_v0,") == 0 || + name.compare("__objc_personality_v0") == 0; + } } void MCStreamer::emitCFILsda(const MCSymbol *Sym, unsigned Encoding) {