Index: lld/trunk/ELF/OutputSections.cpp =================================================================== --- lld/trunk/ELF/OutputSections.cpp +++ lld/trunk/ELF/OutputSections.cpp @@ -88,6 +88,10 @@ template static bool compareByFilePosition(InputSection *A, InputSection *B) { + // Synthetic doesn't have link order dependecy, stable_sort will keep it last + if (A->kind() == InputSectionData::Synthetic || + B->kind() == InputSectionData::Synthetic) + return false; auto *LA = cast>(A->getLinkOrderDep()); auto *LB = cast>(B->getLinkOrderDep()); OutputSectionBase *AOut = LA->OutSec; Index: lld/trunk/ELF/SyntheticSections.h =================================================================== --- lld/trunk/ELF/SyntheticSections.h +++ lld/trunk/ELF/SyntheticSections.h @@ -612,6 +612,13 @@ void writeTo(uint8_t *Buf) override; }; +template class ARMExidxSentinelSection : public SyntheticSection { +public: + ARMExidxSentinelSection(); + size_t getSize() const override { return 8; } + void writeTo(uint8_t *Buf) override; +}; + template InputSection *createCommonSection(); template InputSection *createInterpSection(); template MergeInputSection *createCommentSection(); Index: lld/trunk/ELF/SyntheticSections.cpp =================================================================== --- lld/trunk/ELF/SyntheticSections.cpp +++ lld/trunk/ELF/SyntheticSections.cpp @@ -1666,6 +1666,26 @@ memcpy(Buf, &Filler, getSize()); } +template +ARMExidxSentinelSection::ARMExidxSentinelSection() + : SyntheticSection(SHF_ALLOC | SHF_LINK_ORDER, SHT_ARM_EXIDX, + sizeof(typename ELFT::uint), ".ARM.exidx") {} + +// Write a terminating sentinel entry to the end of the .ARM.exidx table. +// This section will have been sorted last in the .ARM.exidx table. +// This table entry will have the form: +// | PREL31 upper bound of code that has exception tables | EXIDX_CANTUNWIND | +template void ARMExidxSentinelSection::writeTo(uint8_t *Buf){ + // Get the InputSection before us, we are by definition last + auto RI = cast>(this->OutSec)->Sections.rbegin(); + InputSection *LE = *(++RI); + InputSection *LC = cast>(LE->getLinkOrderDep()); + uint64_t S = LC->OutSec->Addr + LC->getOffset(LC->getSize()); + uint64_t P = this->getVA(); + Target->relocateOne(Buf, R_ARM_PREL31, S - P); + write32le(Buf + 4, 0x1); +} + template InputSection *elf::createCommonSection(); template InputSection *elf::createCommonSection(); template InputSection *elf::createCommonSection(); @@ -1780,3 +1800,8 @@ template class elf::MipsRldMapSection; template class elf::MipsRldMapSection; template class elf::MipsRldMapSection; + +template class elf::ARMExidxSentinelSection; +template class elf::ARMExidxSentinelSection; +template class elf::ARMExidxSentinelSection; +template class elf::ARMExidxSentinelSection; Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -1025,6 +1025,10 @@ addInputSec(In::EhFrameHdr); if (Out::Bss->Size > 0) Add(Out::Bss); + + auto OS = dyn_cast_or_null>(findSection(".ARM.exidx")); + if (OS && !OS->Sections.empty() && !Config->Relocatable) + OS->addSection(make>()); } // The linker is expected to define SECNAME_start and SECNAME_end Index: lld/trunk/test/ELF/arm-data-prel.s =================================================================== --- lld/trunk/test/ELF/arm-data-prel.s +++ lld/trunk/test/ELF/arm-data-prel.s @@ -1,8 +1,8 @@ // RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o %t.o // RUN: echo "SECTIONS { \ // RUN: .text : { *(.text) } \ -// RUN: .ARM.exidx : { *(.ARM.exidx) } \ -// RUN: .ARM.exidx.TEST1 : { *(.ARM.exidx.TEST1) } \ +// RUN: .prel.test : { *(.ARM.exidx) } \ +// RUN: .prel.test.TEST1 : { *(.ARM.exidx.TEST1) } \ // RUN: .TEST1 : { *(.TEST1) } } " > %t.script // RUN: ld.lld --script %t.script %t.o -o %t // RUN: llvm-readobj -s -sd %t | FileCheck --check-prefix=CHECK %s @@ -47,7 +47,7 @@ // The expected value of the exception table is // Word0 0 in bit 31, -4 encoded in 31-bit signed offset // Word1 Inline table entry EHT Inline Personality Routine #0 -// CHECK: Name: .ARM.exidx +// CHECK: Name: .prel.test // CHECK: SectionData ( // CHECK: 0000: FCFFFF7F B0B0B080 // CHECK: ) @@ -57,7 +57,7 @@ // Word1 Inline table entry EHT Inline Personality Routine #0 // set vsp = r11 // pop r11, r14 -// CHECK: Name: .ARM.exidx.TEST1 +// CHECK: Name: .prel.test.TEST1 // CHECK: SectionData ( // CHECK: 0000: 08000000 80849B80 // CHECK: ) Index: lld/trunk/test/ELF/arm-exidx-canunwind.s =================================================================== --- lld/trunk/test/ELF/arm-exidx-canunwind.s +++ lld/trunk/test/ELF/arm-exidx-canunwind.s @@ -68,11 +68,13 @@ // CHECK-EXIDX: Contents of section .ARM.exidx: // 100d4 + f38 = 1100c = func1 (inline unwinding data) -// 100dc + f34 = 11010 = func2 (100e0 + 4 = 100e4 = .ARM.extab entry) -// CHECK-EXIDX-NEXT: 100d4 380f0000 08849780 340f0000 04000000 -// 100e4 + f30 = 11014 = __gxx_personality_v0 +// 100dc + f34 = 11010 = func2 (100e0 + c = 100ec = .ARM.extab entry) +// CHECK-EXIDX-NEXT: 100d4 380f0000 08849780 340f0000 0c000000 +// 100e4 + f30 = 11014 = terminate = func2 + sizeof(func2) +// CHECK-EXIDX-NEXT: 100e4 300f0000 01000000 // CHECK-EXIDX-NEXT: Contents of section .ARM.extab.text.func2: -// CHECK-EXIDX-NEXT: 100e4 300f0000 b0b0b000 00000000 +// 100ec + f28 = 11014 = __gxx_personality_v0 +// CHECK-EXIDX-NEXT: 100ec 280f0000 b0b0b000 00000000 // CHECK-PT: Name: .ARM.exidx // CHECK-PT-NEXT: Type: SHT_ARM_EXIDX (0x70000001) @@ -82,14 +84,14 @@ // CHECK-PT-NEXT: ] // CHECK-PT-NEXT: Address: 0x100D4 // CHECK-PT-NEXT: Offset: 0xD4 -// CHECK-PT-NEXT: Size: 16 +// CHECK-PT-NEXT: Size: 24 // CHECK-PT: Type: PT_ARM_EXIDX (0x70000001) // CHECK-PT-NEXT: Offset: 0xD4 // CHECK-PT-NEXT: VirtualAddress: 0x100D4 // CHECK-PT-NEXT: PhysicalAddress: 0x100D4 -// CHECK-PT-NEXT: FileSize: 16 -// CHECK-PT-NEXT: MemSize: 16 +// CHECK-PT-NEXT: FileSize: 24 +// CHECK-PT-NEXT: MemSize: 24 // CHECK-PT-NEXT: Flags [ (0x4) // CHECK-PT-NEXT: PF_R (0x4) // CHECK-PT-NEXT: ] Index: lld/trunk/test/ELF/arm-exidx-gc.s =================================================================== --- lld/trunk/test/ELF/arm-exidx-gc.s +++ lld/trunk/test/ELF/arm-exidx-gc.s @@ -113,11 +113,13 @@ // CHECK-EXIDX-NOT: Contents of section .ARM.extab.text.unusedfunc2: // CHECK-EXIDX: Contents of section .ARM.exidx: // 100d4 + f38 = 1100c = func1 -// 100dc + f34 = 11010 = func2 (100e0 + 14 = 100f4 = .ARM.extab.text.func2) -// CHECK-EXIDX-NEXT: 100d4 380f0000 08849780 340f0000 14000000 +// 100dc + f34 = 11010 = func2 (100e0 + 1c = 100fc = .ARM.extab.text.func2) +// CHECK-EXIDX-NEXT: 100d4 380f0000 08849780 340f0000 1c000000 // 100e4 + f30 = 11014 = __gxx_personality_v0 // 100ec + f2c = 11018 = __aeabi_unwind_cpp_pr0 // CHECK-EXIDX-NEXT: 100e4 300f0000 01000000 2c0f0000 01000000 +// 100f4 + f28 = 1101c = __aeabi_unwind_cpp_pr0 + sizeof(__aeabi_unwind_cpp_pr0) +// CHECK-EXIDX-NEXT: 100f4 280f0000 01000000 // CHECK-EXIDX-NEXT: Contents of section .ARM.extab.text.func2: -// 100f4 + f20 = 11014 = __gxx_personality_v0 -// CHECK-EXIDX-NEXT: 100f4 200f0000 b0b0b000 +// 100fc + f18 = 11014 = __gxx_personality_v0 +// CHECK-EXIDX-NEXT: 100fc 180f0000 b0b0b000 Index: lld/trunk/test/ELF/arm-exidx-order.s =================================================================== --- lld/trunk/test/ELF/arm-exidx-order.s +++ lld/trunk/test/ELF/arm-exidx-order.s @@ -109,14 +109,14 @@ // CHECK-PT-NEXT: ] // CHECK-PT-NEXT: Address: 0x100D4 // CHECK-PT-NEXT: Offset: 0xD4 -// CHECK-PT-NEXT: Size: 72 +// CHECK-PT-NEXT: Size: 80 // CHECK-PT: Type: PT_ARM_EXIDX (0x70000001) // CHECK-PT-NEXT: Offset: 0xD4 // CHECK-PT-NEXT: VirtualAddress: 0x100D4 // CHECK-PT-NEXT: PhysicalAddress: 0x100D4 -// CHECK-PT-NEXT: FileSize: 72 -// CHECK-PT-NEXT: MemSize: 72 +// CHECK-PT-NEXT: FileSize: 80 +// CHECK-PT-NEXT: MemSize: 80 // CHECK-PT-NEXT: Flags [ (0x4) // CHECK-PT-NEXT: PF_R (0x4) // CHECK-PT-NEXT: ] @@ -142,28 +142,28 @@ // CHECK-SCRIPT-NEXT: 11014: 1e ff 2f e1 bx lr // CHECK-SCRIPT-NEXT: Disassembly of section .func1: // CHECK-SCRIPT-NEXT: func1: -// CHECK-SCRIPT-NEXT: 11060: 1e ff 2f e1 bx lr +// CHECK-SCRIPT-NEXT: 11068: 1e ff 2f e1 bx lr // CHECK-SCRIPT-NEXT: Disassembly of section .func2: // CHECK-SCRIPT-NEXT: func2: -// CHECK-SCRIPT-NEXT: 11064: 1e ff 2f e1 bx lr +// CHECK-SCRIPT-NEXT: 1106c: 1e ff 2f e1 bx lr // CHECK-SCRIPT-NEXT: Disassembly of section .func3: // CHECK-SCRIPT-NEXT: func3: -// CHECK-SCRIPT-NEXT: 11068: 1e ff 2f e1 bx lr +// CHECK-SCRIPT-NEXT: 11070: 1e ff 2f e1 bx lr // Check that the .ARM.exidx section is sorted in order as the functions // The offset in field 1, is 32-bit so in the binary the most significant bit -// CHECK-SCRIPT-EXIDX: Contents of section .ARM.exidx: // 11018 - 18 = 11000 func4 // 11020 - 1c = 11004 func5 -// CHECK-SCRIPT-EXIDX-NEXT: 11018 e8ffff7f 01000000 e4ffff7f 01000000 +// CHECK-SCRIPT-EXIDX: 11018 e8ffff7f 01000000 e4ffff7f 01000000 // 11028 - 20 = 11008 _start // 11030 - 24 = 1100c f1 // CHECK-SCRIPT-EXIDX-NEXT: 11028 e0ffff7f 01000000 dcffff7f 01000000 // 11038 - 28 = 11010 f2 // 11040 - 2c = 11014 f3 // CHECK-SCRIPT-EXIDX-NEXT: 11038 d8ffff7f 01000000 d4ffff7f 01000000 -// 11048 + 18 = 11060 = func1 -// 11050 + 14 = 11064 = func2 -// CHECK-SCRIPT-EXIDX-NEXT: 11048 18000000 01000000 14000000 01000000 -// 11058 + 10 = 11068 = func3 -// CHECK-SCRIPT-EXIDX-NEXT: 11058 10000000 01000000 +// 11048 + 20 = 11068 func1 +// 11050 + 1c = 1106c func2 +// CHECK-SCRIPT-EXIDX-NEXT: 11048 20000000 01000000 1c000000 01000000 +// 11058 + 18 = 11070 func3 +// 11060 + 14 = 11074 func3 + sizeof(func3) +// CHECK-SCRIPT-EXIDX-NEXT: 11058 18000000 01000000 14000000 01000000 Index: lld/trunk/test/ELF/arm-exidx-sentinel-norelocatable.s =================================================================== --- lld/trunk/test/ELF/arm-exidx-sentinel-norelocatable.s +++ lld/trunk/test/ELF/arm-exidx-sentinel-norelocatable.s @@ -0,0 +1,17 @@ +// RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o %t.o +// RUN: ld.lld -r %t.o -o %t +// REQUIRES: arm +// RUN: llvm-readobj -s %t | FileCheck %s +// Check that when doing a relocatable link we don't add a terminating entry +// to the .ARM.exidx section + .syntax unified + .text +_start: + .fnstart + .cantunwind + bx lr + .fnend + +// Expect 1 table entry of size 8 +// CHECK: Name: .ARM.exidx +// CHECK: Size: 8 Index: lld/trunk/test/ELF/arm-exidx-sentinel-orphan.s =================================================================== --- lld/trunk/test/ELF/arm-exidx-sentinel-orphan.s +++ lld/trunk/test/ELF/arm-exidx-sentinel-orphan.s @@ -0,0 +1,23 @@ +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// Use Linker script without .ARM.exidx Output Section so it is treated as +// an orphan. We must still add the sentinel table entry +// RUN: echo "SECTIONS { \ +// RUN: .text 0x11000 : { *(.text*) } \ +// RUN: } " > %t.script +// RUN: ld.lld --script %t.script %t -o %t2 +// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s +// REQUIRES: arm + + .syntax unified + .text + .global _start +_start: + .fnstart + .cantunwind + bx lr + .fnend + +// CHECK: Contents of section .ARM.exidx: +// 11004 - 4 = 0x11000 = _start +// 1100c - 8 = 0x11004 = _start + sizeof(_start) +// CHECK-NEXT: 11004 fcffff7f 01000000 f8ffff7f 01000000 Index: lld/trunk/test/ELF/arm-exidx-shared.s =================================================================== --- lld/trunk/test/ELF/arm-exidx-shared.s +++ lld/trunk/test/ELF/arm-exidx-shared.s @@ -41,5 +41,5 @@ // CHECK-NEXT: 0x300C R_ARM_JUMP_SLOT __gxx_personality_v0 // CHECK-EXTAB: Contents of section .ARM.extab.text.func2: -// 0144 + 0ee0 = 0x1024 = __gxx_personality_v0(PLT) -// CHECK-EXTAB-NEXT: 0144 e00e0000 b0b0b000 00000000 +// 014c + 0ed8 = 0x1024 = __gxx_personality_v0(PLT) +// CHECK-EXTAB-NEXT: 014c d80e0000 b0b0b000 00000000 Index: lld/trunk/test/ELF/arm-static-defines.s =================================================================== --- lld/trunk/test/ELF/arm-static-defines.s +++ lld/trunk/test/ELF/arm-static-defines.s @@ -23,7 +23,7 @@ .fnend // CHECK: Name: __exidx_end -// CHECK-NEXT: Value: 0x100DC +// CHECK-NEXT: Value: 0x100E4 // CHECK-NEXT: Size: 0 // CHECK-NEXT: Binding: Local // CHECK-NEXT: Type: None Index: lld/trunk/test/ELF/arm-target2.s =================================================================== --- lld/trunk/test/ELF/arm-target2.s +++ lld/trunk/test/ELF/arm-target2.s @@ -39,22 +39,22 @@ // CHECK-NEXT: 10114 f00e0000 b0b0b000 e41e0000 // CHECK-ABS: Contents of section .ARM.extab: -// 100e8 = .rodata -// CHECK-ABS-NEXT: 100d4 300f0000 b0b0b000 e8000100 +// 100f0 = .rodata +// CHECK-ABS-NEXT: 100d4 300f0000 b0b0b000 f0000100 // CHECK-REL: Contents of section .ARM.extab: // 100dc + c = 100e8 = .rodata -// CHECK-REL-NEXT: 100d4 300f0000 b0b0b000 0c000000 +// CHECK-REL-NEXT: 100d4 300f0000 b0b0b000 14000000 // CHECK: Contents of section .rodata: -// CHECK-NEXT: 10128 00000000 +// CHECK-NEXT: 10130 00000000 // CHECK-ABS: Contents of section .rodata: -// CHECK-ABS-NEXT: 100e8 00000000 +// CHECK-ABS-NEXT: 100f0 00000000 // CHECK-REL: Contents of section .rodata: -// CHECK-REL-NEXT: 100e8 00000000 +// CHECK-REL-NEXT: 100f0 00000000 // CHECK: Contents of section .got: -// 10128 = _ZTIi -// CHECK-NEXT: 12000 28010100 +// 10130 = _ZTIi +// CHECK-NEXT: 12000 30010100