Index: include/llvm/MC/MCObjectFileInfo.h =================================================================== --- include/llvm/MC/MCObjectFileInfo.h +++ include/llvm/MC/MCObjectFileInfo.h @@ -14,6 +14,7 @@ #ifndef LLVM_MC_MCOBJECTFILEINFO_H #define LLVM_MC_MCOBJECTFILEINFO_H +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/CodeGen.h" @@ -153,6 +154,7 @@ /// /// It is initialized on demand so it can be overwritten (with uniquing). MCSection *EHFrameSection; + llvm::DenseMap EHFrameUniquing; // ELF specific sections. MCSection *DataRelROSection; @@ -342,9 +344,7 @@ MCSection *getXDataSection() const { return XDataSection; } MCSection *getSXDataSection() const { return SXDataSection; } - MCSection *getEHFrameSection() { - return EHFrameSection; - } + MCSection *getEHFrameSection(const MCSection &TextSec); enum Environment { IsMachO, IsELF, IsCOFF, IsWasm }; Environment getObjectFileType() const { return Env; } Index: lib/MC/ELFObjectWriter.cpp =================================================================== --- lib/MC/ELFObjectWriter.cpp +++ lib/MC/ELFObjectWriter.cpp @@ -1196,6 +1196,13 @@ sh_link = SymbolTableIndex; sh_info = GroupSymbolIndex; break; + + case ELF::SHT_X86_64_UNWIND: + if (const MCSymbol *Sym = Section.getAssociatedSymbol()) { + const MCSectionELF *Sec = cast(&Sym->getSection()); + sh_link = SectionIndexMap.lookup(Sec); + } + break; } if (Section.getFlags() & ELF::SHF_LINK_ORDER) { Index: lib/MC/MCDwarf.cpp =================================================================== --- lib/MC/MCDwarf.cpp +++ lib/MC/MCDwarf.cpp @@ -1458,26 +1458,29 @@ struct CIEKey { static const CIEKey getEmptyKey() { - return CIEKey(nullptr, 0, -1, false, false, static_cast(INT_MAX)); + return CIEKey(nullptr, nullptr, 0, -1, false, false, + static_cast(INT_MAX)); } static const CIEKey getTombstoneKey() { - return CIEKey(nullptr, -1, 0, false, false, static_cast(INT_MAX)); + return CIEKey(nullptr, nullptr, -1, 0, false, false, + static_cast(INT_MAX)); } - CIEKey(const MCSymbol *Personality, unsigned PersonalityEncoding, - unsigned LSDAEncoding, bool IsSignalFrame, bool IsSimple, - unsigned RAReg) - : Personality(Personality), PersonalityEncoding(PersonalityEncoding), - LsdaEncoding(LSDAEncoding), IsSignalFrame(IsSignalFrame), - IsSimple(IsSimple), RAReg(RAReg) {} + CIEKey(const MCSection *TextSec, const MCSymbol *Personality, + unsigned PersonalityEncoding, unsigned LSDAEncoding, + bool IsSignalFrame, bool IsSimple, unsigned RAReg) + : TextSec(TextSec), Personality(Personality), + PersonalityEncoding(PersonalityEncoding), LsdaEncoding(LSDAEncoding), + IsSignalFrame(IsSignalFrame), IsSimple(IsSimple), RAReg(RAReg) {} explicit CIEKey(const MCDwarfFrameInfo &Frame) - : Personality(Frame.Personality), + : TextSec(&Frame.Begin->getSection()), Personality(Frame.Personality), PersonalityEncoding(Frame.PersonalityEncoding), LsdaEncoding(Frame.LsdaEncoding), IsSignalFrame(Frame.IsSignalFrame), IsSimple(Frame.IsSimple), RAReg(Frame.RAReg) {} + const MCSection *TextSec; const MCSymbol *Personality; unsigned PersonalityEncoding; unsigned LsdaEncoding; @@ -1495,18 +1498,17 @@ static CIEKey getTombstoneKey() { return CIEKey::getTombstoneKey(); } static unsigned getHashValue(const CIEKey &Key) { - return static_cast( - hash_combine(Key.Personality, Key.PersonalityEncoding, Key.LsdaEncoding, - Key.IsSignalFrame, Key.IsSimple, Key.RAReg)); + return static_cast(hash_combine( + Key.TextSec, Key.Personality, Key.PersonalityEncoding, Key.LsdaEncoding, + Key.IsSignalFrame, Key.IsSimple, Key.RAReg)); } static bool isEqual(const CIEKey &LHS, const CIEKey &RHS) { - return LHS.Personality == RHS.Personality && + return LHS.TextSec == RHS.TextSec && LHS.Personality == RHS.Personality && LHS.PersonalityEncoding == RHS.PersonalityEncoding && LHS.LsdaEncoding == RHS.LsdaEncoding && LHS.IsSignalFrame == RHS.IsSignalFrame && - LHS.IsSimple == RHS.IsSimple && - LHS.RAReg == RHS.RAReg; + LHS.IsSimple == RHS.IsSimple && LHS.RAReg == RHS.RAReg; } }; @@ -1540,35 +1542,43 @@ } } - if (!NeedsEHFrameSection) return; - - MCSection &Section = - IsEH ? *const_cast(MOFI)->getEHFrameSection() - : *MOFI->getDwarfFrameSection(); - - Streamer.SwitchSection(&Section); - MCSymbol *SectionStart = Context.createTempSymbol(); - Streamer.EmitLabel(SectionStart); - - DenseMap CIEStarts; + if (!NeedsEHFrameSection) + return; - const MCSymbol *DummyDebugKey = nullptr; - bool CanOmitDwarf = MOFI->getOmitDwarfIfHaveCompactUnwind(); - for (auto I = FrameArray.begin(), E = FrameArray.end(); I != E;) { - const MCDwarfFrameInfo &Frame = *I; - ++I; - if (CanOmitDwarf && Frame.CompactUnwindEncoding != - MOFI->getCompactUnwindDwarfEHFrameOnly()) - // Don't generate an EH frame if we don't need one. I.e., it's taken care - // of by the compact unwind encoding. + MapVector> EHSections; + for (const MCDwarfFrameInfo& FI : FrameArray) { + // Don't generate an EH frame if we don't need one. I.e., + // it's taken care of by the compact unwind encoding. + if (MOFI->getOmitDwarfIfHaveCompactUnwind() && + FI.CompactUnwindEncoding != MOFI->getCompactUnwindDwarfEHFrameOnly()) continue; - CIEKey Key(Frame); - const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey; - if (!CIEStart) - CIEStart = &Emitter.EmitCIE(Frame); + const MCSection &FrameSec = FI.Begin->getSection(); + MCSection *Section = + IsEH ? const_cast(MOFI)->getEHFrameSection(FrameSec) + : MOFI->getDwarfFrameSection(); + EHSections[Section].push_back(&FI); + } - Emitter.EmitFDE(*CIEStart, Frame, I == E, *SectionStart); + DenseMap CIEStarts; + const MCSymbol *DummyDebugKey = nullptr; + for (auto &P : EHSections) { + Streamer.SwitchSection(P.first); + MCSymbol *SectionStart = Context.createTempSymbol(); + Streamer.EmitLabel(SectionStart); + + std::vector &Frames = P.second; + size_t I = 0; + for (const MCDwarfFrameInfo *Frame : Frames) { + CIEKey Key(*Frame); + const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey; + if (!CIEStart) + CIEStart = &Emitter.EmitCIE(*Frame); + + bool LastFrame = I == Frames.size() - 1; + Emitter.EmitFDE(*CIEStart, *Frame, LastFrame, *SectionStart); + ++I; + } } } Index: lib/MC/MCObjectFileInfo.cpp =================================================================== --- lib/MC/MCObjectFileInfo.cpp +++ lib/MC/MCObjectFileInfo.cpp @@ -903,3 +903,20 @@ return Ctx->getELFSection(".debug_types", ELF::SHT_PROGBITS, ELF::SHF_GROUP, 0, utostr(Hash)); } + +MCSection *MCObjectFileInfo::getEHFrameSection(const MCSection &TextSec) { + if (Env != IsELF) + return EHFrameSection; + + unsigned ID = + EHFrameUniquing.insert({&TextSec, EHFrameUniquing.size()}).first->second; + + // Set flags and type corresponding to default .eh_frame section attributes + // for ELF target. Specify corresponding .text section as a Link so that we + // can set sh_link field later. + const MCSectionELF &EHSec = cast(*EHFrameSection); + const MCSymbolELF *Link = cast(TextSec.getBeginSymbol()); + return Ctx->getELFSection( + ".eh_frame", EHSec.getType(), EHSec.getFlags() /*| ELF::SHF_LINK_ORDER*/, + 0 /*EntrySize*/, "" /*Group*/, ID /*UniqueID*/, Link); +}