Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -424,6 +424,11 @@ if (auto *OutSec = dyn_cast>(CurOutSec)) { for (InputSection *I : OutSec->Sections) output(I); + if (OutSec->Name == ".ARM.exidx") { + // Reserve space for a sentinel table entry to be filled in by Writer + OutSec->Size += 8; + Dot += 8; + } } else { Dot += CurOutSec->Size; } Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -954,6 +954,14 @@ for (OutputSectionBase *Sec : OutputSections) Sec->finalize(); + if (!ScriptConfig->HasSections) { + // Make room for a terminating sentinel. If we are using linker scripts + // we must make the alteration in LinkerScript instead. + OutputSectionBase *Sec = findSection(".ARM.exidx"); + if (Sec && !Config->Relocatable) + Sec->Size += 8; + } + // Dynamic section must be the last one in this list and dynamic // symbol table section (DynSymTab) must be the first one. finalizeSynthetic( @@ -1488,6 +1496,21 @@ Sec->writeTo(Buf + Sec->Offset); } +// Write a terminating sentinel entry to the end of the .ARM.exidx table. +// This table entry will have the form: +// | PREL31 upper bound of code that has exception tables | EXIDX_CANTUNWIND | +// we have previously reserved the 8 bytes space needed for the extra entry +template +static void writeARMExidxSentinel(OutputSection *Out, uint8_t *Buf) { + InputSection *LE = Out->Sections.back(); + InputSection *LC = cast>(LE->getLinkOrderDep()); + uint64_t S = LC->OutSec->Addr + LC->getOffset(LC->getSize()); + uint64_t P = Out->Addr + Out->Size - 8; + uint8_t *Entry = Buf + Out->Size - 8; + Target->relocateOne(Entry, R_ARM_PREL31, S - P); + write32le(Entry + 4, 0x1); +} + // Write section contents to a mmap'ed file. template void Writer::writeSections() { uint8_t *Buf = Buffer->getBufferStart(); @@ -1510,6 +1533,12 @@ // it should be written after .eh_frame is written. if (!Out::EhFrame->empty() && EhFrameHdr) EhFrameHdr->writeTo(Buf + EhFrameHdr->Offset); + + // Add a terminating EXIDX_CANTUNWIND table entry for + // the highest executable address in program + OutputSectionBase *Sec = findSection(".ARM.exidx"); + if (!Config->Relocatable && Sec) + writeARMExidxSentinel(cast>(Sec), Buf + Sec->Offset); } template void Writer::writeBuildId() { Index: test/ELF/arm-data-prel.s =================================================================== --- test/ELF/arm-data-prel.s +++ 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: test/ELF/arm-exidx-canunwind.s =================================================================== --- test/ELF/arm-exidx-canunwind.s +++ 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: test/ELF/arm-exidx-gc.s =================================================================== --- test/ELF/arm-exidx-gc.s +++ 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: test/ELF/arm-exidx-order.s =================================================================== --- test/ELF/arm-exidx-order.s +++ 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: test/ELF/arm-exidx-sentinel-norelocatable.s =================================================================== --- /dev/null +++ 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: test/ELF/arm-exidx-shared.s =================================================================== --- test/ELF/arm-exidx-shared.s +++ 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: test/ELF/arm-static-defines.s =================================================================== --- test/ELF/arm-static-defines.s +++ 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: test/ELF/arm-target2.s =================================================================== --- test/ELF/arm-target2.s +++ 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