Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -2569,16 +2569,22 @@ void ARMExidxSentinelSection::writeTo(uint8_t *Buf) { // The Sections are sorted in order of ascending PREL31 address with the // sentinel last. We need to find the InputSection that precedes the - // sentinel. By construction the Sentinel is in the last - // InputSectionDescription as the InputSection that precedes it. + // sentinel. OutputSection *C = getParent(); - auto ISD = - std::find_if(C->SectionCommands.rbegin(), C->SectionCommands.rend(), - [](const BaseCommand *Base) { - return isa(Base); - }); - auto L = cast(*ISD); - InputSection *Highest = L->Sections[L->Sections.size() - 2]; + InputSection *Highest = nullptr; + int Skip = 1; + for (const BaseCommand *Base : llvm::reverse(C->SectionCommands)) { + if (!isa(Base)) + continue; + auto L = cast(Base); + if (Skip >= L->Sections.size()) { + Skip -= L->Sections.size(); + continue; + } + Highest = L->Sections[L->Sections.size() - Skip - 1]; + break; + } + assert(Highest); InputSection *LS = Highest->getLinkOrderDep(); uint64_t S = LS->getParent()->Addr + LS->getOffset(LS->getSize()); uint64_t P = getVA(); Index: test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s =================================================================== --- /dev/null +++ test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s @@ -0,0 +1,12 @@ +# REQUIRES: arm +# RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o +# RUN: echo "SECTIONS { \ +# RUN: .ARM.exidx : { *(.ARM.exidx*) foo = .; } \ +# RUN: }" > %t.script +## We used to crash in the case when the last output section command +## for .ARM.exidx was anything but an input section description. +# RUN: ld.lld -T %t.script %t.o -shared -o %t.so + +.fnstart +.cantunwind +.fnend