Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -132,11 +132,25 @@ if (!IS->Assigned) { IS->Assigned = true; - if (SectionCommands.empty() || - !isa(SectionCommands.back())) + // Find the last existing InputSectionDescription. + // Add a new only if we cannot find one. + // As a result, if we have a description for an output section like + // .foo : { *(.foo) bar = . } + // we will place the new section before the assignment so that it will + // affect the value of 'bar', which is, probably, expected. + // We also had a crash in the similar situation with an .ARM.exidx sentinel, + // because 'ARMExidxSentinelSection::writeTo()' expected it to be placed + // into a non-empty bucket. + auto ISD = std::find_if(SectionCommands.rbegin(), SectionCommands.rend(), + [](const BaseCommand *Base) { + return isa(Base); + }); + if (ISD == SectionCommands.rend()) { SectionCommands.push_back(make("")); - auto *ISD = cast(SectionCommands.back()); - ISD->Sections.push_back(IS); + ISD = SectionCommands.rbegin(); + } + auto L = cast(*ISD); + L->Sections.push_back(IS); } } Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -2578,6 +2578,7 @@ return isa(Base); }); auto L = cast(*ISD); + assert(L->Sections.size() >= 2); InputSection *Highest = L->Sections[L->Sections.size() - 2]; InputSection *LS = Highest->getLinkOrderDep(); uint64_t S = LS->getParent()->Addr + LS->getOffset(LS->getSize()); Index: test/ELF/linkerscript/arm-exidx-sentinel.s =================================================================== --- /dev/null +++ test/ELF/linkerscript/arm-exidx-sentinel.s @@ -0,0 +1,27 @@ +# 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 +# RUN: ld.lld -T %t.script %t.o -shared -o %t.so +# RUN: llvm-readobj -s -t %t.so | FileCheck %s + +# CHECK: Section { +# CHECK: Name: .ARM.exidx +# CHECK-NEXT: Type: SHT_ARM_EXIDX +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_LINK_ORDER +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x0 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 16 + +# Symbol 'foo' is expected to point at the end of the section. +# CHECK: Symbol { +# CHECK: Name: foo +# CHECK-NEXT: Value: 0x10 + +.fnstart +.cantunwind +.fnend