Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -268,6 +268,9 @@ } InputSection *InputSectionBase::getLinkOrderDep() const { + // Synthetic LinkOrder dependency stores Section directly. + if (auto *ARMExidx = dyn_cast(this)) + return ARMExidx->LinkSec; assert(Link); assert(Flags & SHF_LINK_ORDER); return cast(File->getSections()[Link]); Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -930,19 +930,54 @@ void writeTo(uint8_t *Buf) override {} }; -class ARMExidxSentinelSection : public SyntheticSection { +// Represent a linker generated .ARM.exidx exception index table section. +// The .ARM.exidx sections after SHF_LINK_ORDER processing is done form a table +// that the unwinder can derive (Addresses are encoded as offsets from table): +// | Address of function | Unwind instructions for function | +// where the unwind instructions are either a small number of unwind or the +// special EXIDX_CANTUNWIND entry representing no unwinding information. +// When an exception is thrown from an address A, the unwinder searches the +// table for the closest table entry with Address of function <= A. This means +// that for two consecutive table entries: +// | A1 | U1 | +// | A2 | U2 | +// The range of addresses described by U1 is [A1, A2) +// +// There are two cases where we need a linker generated table entry to fixup +// the address ranges in the table +// Case 1: +// - A sentinel entry added with an address higher than all +// executable sections. This was needed to work around libunwind bug pr31091. +// - After address assignment we need to find the highest addressed executable +// section and use the limit of that section so that the unwinder never +// matches it. +// Case 2: +// - InputSections without a .ARM.exidx section (usually from Assembly) +// need a table entry so that they terminate the range of the previously +// function. This is pr40277. +// - We know at creation time the InputSection we need to get the address of. + +// Terminating sentinel entry; IsSentinel = true, LinkSec = nullptr until +// all InputSections are sorted. +// Normal entry for a known Section; IsSentinel = false, LinkSec = Section. +class ARMExidxSyntheticSection : public SyntheticSection { public: - ARMExidxSentinelSection(); - size_t getSize() const override { return 8; } + // Use LinkSec = nullptr to create terminating sentinel entry. + ARMExidxSyntheticSection(InputSection *LinkSec); + size_t getSize() const override { return sizeof(Data); } void writeTo(uint8_t *Buf) override; bool empty() const override; static bool classof(const SectionBase *D); - // The last section referenced by a regular .ARM.exidx section. - // It is found and filled in Writer::resolveShfLinkOrder(). - // The sentinel points at the end of that section. - InputSection *Highest = nullptr; + // All instances will have the same unwind instructions. + static const uint8_t Data[8]; + + // At creation time the Sentinel has IsSentinel = true, LinkSec = nullptr + // A non Sentinel section has IsSentinel = false and LinkSec = Section we + // are creating entry for. + InputSection *LinkSec; + bool IsSentinel; }; // A container for one or more linker generated thunks. Instances of these Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -3044,33 +3044,45 @@ : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Config->Wordsize, ".rld_map") {} -ARMExidxSentinelSection::ARMExidxSentinelSection() +const uint8_t ARMExidxSyntheticSection::Data[8] = { + 0, 0, 0, 0, // PREL31 to target + 1, 0, 0, 0}; // EXIDX_CANTUNWIND + +ARMExidxSyntheticSection::ARMExidxSyntheticSection(InputSection *Link) : SyntheticSection(SHF_ALLOC | SHF_LINK_ORDER, SHT_ARM_EXIDX, - Config->Wordsize, ".ARM.exidx") {} + Config->Wordsize, ".ARM.exidx"), + LinkSec(Link) { + IsSentinel = Link == nullptr; + RawData = Data; +} -// 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. +// Write a EXIDX_CANTUNWIND entry to the .ARM.exidx table. This will either be +// a terminating sentinel entry or a synthetic entry for a code section that +// had no exception tables. +// The sentinel 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 | // The sentinel must have the PREL31 value of an address higher than any // address described by any other table entry. -void ARMExidxSentinelSection::writeTo(uint8_t *Buf) { - assert(Highest); - uint64_t S = Highest->getVA(Highest->getSize()); +// A synthetic table entry will have the form: +// | PREL31 start of LinkSec | EXIDX_CANTUNWIND | +void ARMExidxSyntheticSection::writeTo(uint8_t *Buf) { + uint64_t S = + IsSentinel ? LinkSec->getVA(LinkSec->getSize()) : LinkSec->getVA(); uint64_t P = getVA(); Target->relocateOne(Buf, R_ARM_PREL31, S - P); write32le(Buf + 4, 1); } // The sentinel has to be removed if there are no other .ARM.exidx entries. -bool ARMExidxSentinelSection::empty() const { +bool ARMExidxSyntheticSection::empty() const { for (InputSection *IS : getInputSections(getParent())) - if (!isa(IS)) + if (!isa(IS)) return false; return true; } -bool ARMExidxSentinelSection::classof(const SectionBase *D) { +bool ARMExidxSyntheticSection::classof(const SectionBase *D) { return D->kind() == InputSectionBase::Synthetic && D->Type == SHT_ARM_EXIDX; } Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -438,10 +438,27 @@ if (In.StrTab) Add(In.StrTab); - if (Config->EMachine == EM_ARM && !Config->Relocatable) - // Add a sentinel to terminate .ARM.exidx. It helps an unwinder - // to find the exact address range of the last entry. - Add(make()); + if (Config->EMachine == EM_ARM && !Config->Relocatable) { + // Add Linker Synthesized .ARM.exidx sections, we do this for InputSections + // without an associated .ARM.exidx section and a sentinel to terminate the + // .ARM.exidx table that helps an unwinder find the exact address range of + // the last entry. + auto ExecWithNoARMExidx = [](InputSection *IS) { + if (!IS->Live || IS->kind() == InputSectionBase::Synthetic || + !(IS->Flags & SHF_EXECINSTR) || IS->getSize() == 0) + return false; + for (InputSection *Dep : IS->DependentSections) + if (Dep->Type & SHT_ARM_EXIDX) + return false; + return true; + }; + + for (InputSectionBase *ISB : InputSections) + if (auto *IS = dyn_cast(ISB)) + if (ExecWithNoARMExidx(IS)) + Add(make(IS)); + Add(make(nullptr)); + } } // The main function of the writer. @@ -1399,13 +1416,13 @@ } static bool compareByFilePosition(InputSection *A, InputSection *B) { - // Synthetic, i. e. a sentinel section, should go last. - if (A->kind() == InputSectionBase::Synthetic || - B->kind() == InputSectionBase::Synthetic) - return A->kind() != InputSectionBase::Synthetic; - InputSection *LA = A->getLinkOrderDep(); InputSection *LB = B->getLinkOrderDep(); + // There is a single synthetic sentinel section that must go last. + // getLinkOrderDep() returns nullptr for it. + if (LA == nullptr || LB == nullptr) + return LA != nullptr; + OutputSection *AOut = LA->getParent(); OutputSection *BOut = LB->getParent(); @@ -1483,14 +1500,16 @@ if (!Config->Relocatable && Config->EMachine == EM_ARM && Sec->Type == SHT_ARM_EXIDX) { - if (auto *Sentinel = dyn_cast(Sections.back())) { + if (auto *Sentinel = + dyn_cast(Sections.back())) { assert(Sections.size() >= 2 && "We should create a sentinel section only if there are " "alive regular exidx sections."); // The last executable section is required to fill the sentinel. // Remember it here so that we don't have to find it again. - Sentinel->Highest = Sections[Sections.size() - 2]->getLinkOrderDep(); + assert(Sentinel->IsSentinel); + Sentinel->LinkSec = Sections[Sections.size() - 2]->getLinkOrderDep(); } // The EHABI for the Arm Architecture permits consecutive identical Index: test/ELF/arm-exidx-add-missing.s =================================================================== --- /dev/null +++ test/ELF/arm-exidx-add-missing.s @@ -0,0 +1,66 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi --arm-add-build-attributes %s -o %t +// RUN: ld-lld %t --no-merge-exidx-entries -o %t2 +// RUN: llvm-objdump -s %t2 | FileCheck %s +// RUN: ld-lld %t -o %t3 +// RUN: llvm-objdump -s %t3 | FileCheck %s -check-prefix=CHECK-MERGE + +// The ARM.exidx section is a table of 8-byte entries of the form: +// | PREL31 Relocation to start of function | Unwinding information | +// The range of addresses covered by the table entry is terminated by the +// next table entry. This means that an executable section without a .ARM.exidx +// section does not terminate the range of addresses. To fix this the linker +// synthesises an EXIDX_CANTUNWIND entry for each section wihout a .ARM.exidx +// section. + + .syntax unified + + // Expect inline unwind instructions + .section .text.01, "ax", %progbits + .global f1 +f1: + .fnstart + bx lr + .save {r7, lr} + .setfp r7, sp, #0 + .fnend + + // Expect no unwind information from assembler. The linker must + // synthesise an EXIDX_CANTUNWIND entry to prevent an exception + // thrown through f2 from matching against the unwind instructions + // for f1. + .section .text.02, "ax", %progbits + .global f2 +f2: + bx lr + + + // Expect 1 EXIDX_CANTUNWIND entry that can be merged into the linker + // generated EXIDX_CANTUNWIND as if the assembler had generated it. + .section .text.03, "ax",%progbits + .global f3 +f3: + .fnstart + bx lr + .cantunwind + .fnend + + // Dummy implementation of personality routines to satisfy reference + // from exception tables, linker will generate EXIDX_CANTUNWIND. + .section .text.__aeabi_unwind_cpp_pr0, "ax", %progbits + .global __aeabi_unwind_cpp_pr0 +__aeabi_unwind_cpp_pr0: + bx lr + +// f1, f2 +// CHECK: 100d4 2c0f0000 08849780 280f0000 01000000 +// f3, __aeabi_unwind_cpp_pr0 +// CHECK-NEXT: 100e4 240f0000 01000000 200f0000 01000000 +// sentinel +// CHECK-NEXT: 100f4 1c0f0000 01000000 + +// f1, (f2, f3, __aeabi_unwind_cpp_pr0) +// CHECK-MERGE: 100d4 2c0f0000 08849780 280f0000 01000000 +// sentinel +// CHECK-MERGE-NEXT: 100e4 2c0f0000 01000000 + Index: test/ELF/arm-exidx-canunwind.s =================================================================== --- test/ELF/arm-exidx-canunwind.s +++ test/ELF/arm-exidx-canunwind.s @@ -1,6 +1,6 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t -// RUN: ld.lld %t -o %t2 2>&1 +// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: ld.lld %t -o %t2 // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s // RUN: llvm-readobj --program-headers --sections %t2 | FileCheck -check-prefix=CHECK-PT %s @@ -66,15 +66,14 @@ // CHECK: __aeabi_unwind_cpp_pr0: // CHECK-NEXT: 11018: 1e ff 2f e1 bx lr -// CHECK-EXIDX: Contents of section .ARM.exidx: -// 100d4 + f38 = 1100c = func1 (inline unwinding data) -// 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: -// 100ec + f28 = 11014 = __gxx_personality_v0 -// CHECK-EXIDX-NEXT: 100ec 280f0000 b0b0b000 00000000 +// 100d4 + f2c = 11000 = main (linker generated cantunwind) +// 100dc + f30 = 1100c = func1 (inline unwinding data) +// CHECK-EXIDX: 100d4 2c0f0000 01000000 300f0000 08849780 +// 100e4 + f2c = 11010 = func2 (100e8 + 14 = 100fc = .ARM.extab entry) +// 100ec + f28 = 11014 = __gcc_personality_v0 (linker generated cantunwind) +// CHECK-EXIDX-NEXT: 100e4 2c0f0000 14000000 280f0000 01000000 +// 100f4 + f28 = 1101c = sentinel +// CHECK-EXIDX-NEXT: 100f4 280f0000 01000000 // CHECK-PT: Name: .ARM.exidx // CHECK-PT-NEXT: Type: SHT_ARM_EXIDX (0x70000001) @@ -84,14 +83,14 @@ // CHECK-PT-NEXT: ] // CHECK-PT-NEXT: Address: 0x100D4 // CHECK-PT-NEXT: Offset: 0xD4 -// CHECK-PT-NEXT: Size: 24 +// CHECK-PT-NEXT: Size: 40 // 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: 24 -// CHECK-PT-NEXT: MemSize: 24 +// CHECK-PT-NEXT: FileSize: 40 +// CHECK-PT-NEXT: MemSize: 40 // CHECK-PT-NEXT: Flags [ (0x4) // CHECK-PT-NEXT: PF_R (0x4) // CHECK-PT-NEXT: ] Index: test/ELF/arm-exidx-dedup.s =================================================================== --- test/ELF/arm-exidx-dedup.s +++ test/ELF/arm-exidx-dedup.s @@ -1,27 +1,29 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld %t --no-merge-exidx-entries -o %t2 // RUN: llvm-objdump -s %t2 | FileCheck --check-prefix CHECK-DUPS %s // RUN: ld.lld %t -o %t3 // RUN: llvm-objdump -s %t3 | FileCheck %s + // Test that lld can at least remove duplicate .ARM.exidx sections. A more // fine grained implementation will be able to remove duplicate entries within // a .ARM.exidx section. // With duplicate entries // CHECK-DUPS: Contents of section .ARM.exidx: -// CHECK-DUPS-NEXT: 100d4 2c0f0000 01000000 280f0000 01000000 -// CHECK-DUPS-NEXT: 100e4 240f0000 01000000 200f0000 01000000 -// CHECK-DUPS-NEXT: 100f4 1c0f0000 08849780 180f0000 08849780 -// CHECK-DUPS-NEXT: 10104 140f0000 08849780 100f0000 14000000 -// CHECK-DUPS-NEXT: 10114 0c0f0000 18000000 080f0000 01000000 +// CHECK-DUPS-NEXT: 100d4 2c0f0000 01000000 280f0000 01000000 +// CHECK-DUPS-NEXT: 100e4 240f0000 01000000 200f0000 01000000 +// CHECK-DUPS-NEXT: 100f4 1c0f0000 08849780 180f0000 08849780 +// CHECK-DUPS-NEXT: 10104 140f0000 08849780 100f0000 24000000 +// CHECK-DUPS-NEXT: 10114 0c0f0000 28000000 080f0000 01000000 +// CHECK-DUPS-NEXT: 10124 040f0000 01000000 000f0000 01000000 // CHECK-DUPS-NEXT: Contents of section .ARM.extab: // After duplicate entry removal // CHECK: Contents of section .ARM.exidx: -// CHECK-NEXT: 100d4 2c0f0000 01000000 340f0000 08849780 -// CHECK-NEXT: 100e4 380f0000 14000000 340f0000 18000000 -// CHECK-NEXT: 100f4 300f0000 01000000 +// CHECK-NEXT: 100d4 2c0f0000 01000000 340f0000 08849780 +// CHECK-NEXT: 100e4 380f0000 1c000000 340f0000 20000000 +// CHECK-NEXT: 100f4 300f0000 01000000 300f0000 01000000 // CHECK-NEXT: Contents of section .ARM.extab: .syntax unified @@ -113,8 +115,9 @@ .long 0 .fnend - // Dummy implementation of personality routines to satisfy reference from - // exception tables +// Dummy implementation of personality routines to satisfy reference from +// exception tables +// Expect Linker generated EXIDX_CANTUNWIND tables .section .text.__gcc_personality_v0, "ax", %progbits .global __gxx_personality_v0 __gxx_personality_v0: Index: test/ELF/arm-exidx-gc.s =================================================================== --- test/ELF/arm-exidx-gc.s +++ test/ELF/arm-exidx-gc.s @@ -1,5 +1,5 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld %t --no-merge-exidx-entries -o %t2 --gc-sections 2>&1 // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s @@ -111,14 +111,15 @@ // CHECK-NOT: __gxx_personality_v1 // CHECK-EXIDX: Contents of section .ARM.exidx: -// 100d4 + f38 = 1100c = func1 -// 100dc + f34 = 11010 = func2 (100e0 + 1c = 100fc = .ARM.extab) -// 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 +// 100d4 + f2c = 11000 +// 100dc + f30 = 1100c = func1 +// CHECK-EXIDX-NEXT: 100d4 2c0f0000 01000000 300f0000 08849780 +// 100e4 + f2c = 11010 = func2 (100e8 + 1c = 10104 = .ARM.extab) +// 100ec + f28 = 11014 = __gxx_personality_v0 +// CHECK-EXIDX-NEXT: 100e4 2c0f0000 1c000000 280f0000 01000000 +// 100f4 + f24 = 11018 = __aeabi_unwind_cpp_pr0 +// 100fc + f20 = 1101c = __aeabi_unwind_cpp_pr0 + sizeof(__aeabi_unwind_cpp_pr0) +// CHECK-EXIDX-NEXT: 100f4 240f0000 01000000 200f0000 01000000 // CHECK-EXIDX-NEXT: Contents of section .ARM.extab: -// 100fc + f18 = 11014 = __gxx_personality_v0 -// CHECK-EXIDX-NEXT: 100fc 180f0000 b0b0b000 +// 10104 + f10 = 11014 = __gxx_personality_v0 +// CHECK-EXIDX-NEXT: 10104 100f0000 b0b0b000 Index: test/ELF/arm-exidx-no-add-missing.s =================================================================== --- /dev/null +++ test/ELF/arm-exidx-no-add-missing.s @@ -0,0 +1,16 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi --arm-add-build-attributes %s -o %t +// RUN: ld-lld %t -o %t2 +// RUN: llvm-objdump -s %t2 | FileCheck %s + +// We do not want to generate missing EXIDX_CANTUNWIND entries if there are no +// input .ARM.exidx sections. + +// CHECK-NOT: .ARM.exidx + .syntax unified + .text + .globl _start + .type _start, %function +_start: + bx lr + Index: test/ELF/arm-exidx-shared.s =================================================================== --- test/ELF/arm-exidx-shared.s +++ test/ELF/arm-exidx-shared.s @@ -1,5 +1,5 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld --hash-style=sysv %t --shared -o %t2 2>&1 // RUN: llvm-readobj --relocations %t2 | FileCheck %s // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXTAB %s @@ -41,5 +41,5 @@ // CHECK-NEXT: 0x200C R_ARM_JUMP_SLOT __gxx_personality_v0 // CHECK-EXTAB: Contents of section .ARM.extab: -// 0x0210 + 0x0e20 = 0x1030 = __gxx_personality_v0(PLT) -// CHECK-EXTAB-NEXT: 0210 200e0000 b0b0b000 00000000 +// 0x0218 + 0x0e18 = 0x1030 = __gxx_personality_v0(PLT) +// CHECK-EXTAB-NEXT: 0218 180e0000 b0b0b000 00000000 Index: test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s =================================================================== --- test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s +++ test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s @@ -1,5 +1,5 @@ # REQUIRES: arm -# RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o +# RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t.o # RUN: echo "SECTIONS { \ # RUN: .ARM.exidx 0x1000 : { *(.ARM.exidx*) foo = .; } \ # RUN: .text 0x2000 : { *(.text*) } \ @@ -19,6 +19,11 @@ bx lr .fnend +# Check that linker synthesized sections are added before symbol + .section .text.01, "ax", %progbits + .global fn1 +fn1: + bx lr # CHECK: Contents of section .ARM.exidx: # 1000 + 1000 = 0x2000 = _start # 1008 + 0ffc = 0x2004 = _start + sizeof(_start) @@ -33,9 +38,9 @@ # SYMBOL-NEXT: ] # SYMBOL-NEXT: Address: 0x1000 # SYMBOL-NEXT: Offset: -# SYMBOL-NEXT: Size: 16 +# SYMBOL-NEXT: Size: 24 # Symbol 'foo' is expected to point at the end of the section. # SYMBOL: Symbol { # SYMBOL: Name: foo -# SYMBOL-NEXT: Value: 0x1010 +# SYMBOL-NEXT: Value: 0x1018