Index: lld/ELF/SyntheticSections.cpp =================================================================== --- lld/ELF/SyntheticSections.cpp +++ lld/ELF/SyntheticSections.cpp @@ -3363,14 +3363,14 @@ // Sort the executable sections that may or may not have associated // .ARM.exidx sections by order of ascending address. This requires the - // relative positions of InputSections to be known. + // relative positions of InputSections and OutputSections to be known. auto compareByFilePosition = [](const InputSection *a, const InputSection *b) { OutputSection *aOut = a->getParent(); OutputSection *bOut = b->getParent(); if (aOut != bOut) - return aOut->sectionIndex < bOut->sectionIndex; + return aOut->addr < bOut->addr; return a->outSecOff < b->outSecOff; }; llvm::stable_sort(executableSections, compareByFilePosition); Index: lld/ELF/Writer.cpp =================================================================== --- lld/ELF/Writer.cpp +++ lld/ELF/Writer.cpp @@ -1603,6 +1603,11 @@ } } +static void finalizeSynthetic(SyntheticSection *sec) { + if (sec && sec->isNeeded() && sec->getParent()) + sec->finalizeContents(); +} + // We need to generate and finalize the content that depends on the address of // InputSections. As the generation of the content may also alter InputSection // addresses we must converge to a fixed point. We do that here. See the comment @@ -1612,6 +1617,10 @@ AArch64Err843419Patcher a64p; ARMErr657417Patcher a32p; script->assignAddresses(); + // .ARM.exidx does not require precise addresses, but it does require the + // relative address of OutputSections. + for (Partition &part : partitions) + finalizeSynthetic(part.armExidx); // Converts call x@GDPLT to call __tls_get_addr if (config->emachine == EM_HEXAGON) @@ -1761,11 +1770,6 @@ } } -static void finalizeSynthetic(SyntheticSection *sec) { - if (sec && sec->isNeeded() && sec->getParent()) - sec->finalizeContents(); -} - // In order to allow users to manipulate linker-synthesized sections, // we had to add synthetic sections to the input section list early, // even before we make decisions whether they are needed. This allows @@ -2034,7 +2038,6 @@ // Dynamic section must be the last one in this list and dynamic // symbol table section (dynSymTab) must be the first one. for (Partition &part : partitions) { - finalizeSynthetic(part.armExidx); finalizeSynthetic(part.dynSymTab); finalizeSynthetic(part.gnuHashTab); finalizeSynthetic(part.hashTab); Index: lld/test/ELF/arm-exidx-script-order.s =================================================================== --- /dev/null +++ lld/test/ELF/arm-exidx-script-order.s @@ -0,0 +1,54 @@ +// RUN: llvm-mc --arm-add-build-attributes --triple=armv7a-linux-gnueabihf -filetype=obj %s -o %t.o +// RUN: echo "SECTIONS { \ +// RUN: . = 0x80000000; \ +// RUN: .ARM.exidx : { *(.ARM.exidx) } \ +// RUN: .text : { *(.text) } \ +// RUN: .text.1 0x80000200 : AT(0x80000200) { *(.text.1) } \ +// RUN: .text.2 0x80000100 : AT(0x80000100) { *(.text.2) } \ +// RUN: } " > %t.script +// RUN: ld.lld --script %t.script %t.o -o %t +// RUN: llvm-readobj -x .ARM.exidx %t | FileCheck %s + +/// When a linker script does not have monotonically increasing addresses +/// the .ARM.exidx table should still be in monotonically increasing order. + +// CHECK: Hex dump of section '.ARM.exidx': +// 0x80000000 + 0x28 = 0x80000028, 0x80000008 + 0xf8 = 0x80000100 +// 0x80000000 24000000 08849780 f8000000 20849980 +// 0x80000010 + 0x1f0 = 0x8000200, 0x80000018 + 0x1ec = 0x8000204 +// 0x80000010 f0010000 10849880 ec010000 01000000 + .text + .global _start + .type _start, %function +_start: + .fnstart + bx lr + .save {r7, lr} + .setfp r7, sp, #0 + .fnend + + .section .text.1, "ax", %progbits + .global fn1 + .type fn1, %function +fn1: + .fnstart + bx lr + .save {r8, lr} + .setfp r8, sp, #0 + .fnend + + .section .text.2, "ax", %progbits + .global fn2 + .type fn2, %function +fn2: + .fnstart + bx lr + .save {r9, lr} + .setfp r9, sp, #0 + .fnend + +/// dummy definition, use .data to avoid generating a cantunwind table + .section .rodata + .global __aeabi_unwind_cpp_pr0 +__aeabi_unwind_cpp_pr0: + .word 0