diff options
-rw-r--r-- | lld/ELF/SyntheticSections.cpp | 24 | ||||
-rw-r--r-- | lld/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s | 24 |
2 files changed, 39 insertions, 9 deletions
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 0afe90102c9..c9d31d735d7 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -2569,16 +2569,22 @@ ARMExidxSentinelSection::ARMExidxSentinelSection() 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<InputSectionDescription>(Base); - }); - auto L = cast<InputSectionDescription>(*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<InputSectionDescription>(Base)) + continue; + auto L = cast<InputSectionDescription>(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(); diff --git a/lld/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s b/lld/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s new file mode 100644 index 00000000000..cbf295aa706 --- /dev/null +++ b/lld/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s @@ -0,0 +1,24 @@ +# REQUIRES: arm +# RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o +# RUN: echo "SECTIONS { \ +# RUN: .ARM.exidx 0x1000 : { *(.ARM.exidx*) foo = .; } \ +# RUN: .text 0x2000 : { *(.text*) } \ +# RUN: }" > %t.script +## We used to crash if 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 +# RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s + + .syntax unified + .text + .global _start +_start: + .fnstart + .cantunwind + bx lr + .fnend + +// CHECK: Contents of section .ARM.exidx: +// 1000 + 1000 = 0x2000 = _start +// 1008 + 0ffc = 0x2004 = _start + sizeof(_start) +// CHECK-NEXT: 1000 00100000 01000000 fc0f0000 01000000 |