[ELF] Add terminating sentinel .ARM.exidx table entry

The .ARM.exidx table has an entry for each function with the first entry
giving the start address of the function, the table is sorted in ascending
order of function address. Given a PC value, the unwinder will search the
table for the entry that contains the PC value.
    
If the table entry happens to be the last, the range of the addresses that
the final unwinding table describes will extend to the end of the address
space. To prevent an incorrect address outside the address range of the
program matching the last entry we follow ld.bfd's example and add a
sentinel EXIDX_CANTUNWIND entry at the end of the table. This gives the
final real table entry an upper bound.
    
In addition the llvm libunwind unwinder currently depends on the presence
of a sentinel entry (PR31091).

Differential revision: https://reviews.llvm.org/D26977

llvm-svn: 287869
This commit is contained in:
Peter Smith 2016-11-24 11:43:55 +00:00
parent d056b5be51
commit 719eb8efa5
13 changed files with 123 additions and 39 deletions

View File

@ -88,6 +88,10 @@ OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t Type, uintX_t Flags)
template <typename ELFT>
static bool compareByFilePosition(InputSection<ELFT> *A,
InputSection<ELFT> *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<InputSection<ELFT>>(A->getLinkOrderDep());
auto *LB = cast<InputSection<ELFT>>(B->getLinkOrderDep());
OutputSectionBase *AOut = LA->OutSec;

View File

@ -1666,6 +1666,26 @@ template <class ELFT> void MipsRldMapSection<ELFT>::writeTo(uint8_t *Buf) {
memcpy(Buf, &Filler, getSize());
}
template <class ELFT>
ARMExidxSentinelSection<ELFT>::ARMExidxSentinelSection()
: SyntheticSection<ELFT>(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 <class ELFT> void ARMExidxSentinelSection<ELFT>::writeTo(uint8_t *Buf){
// Get the InputSection before us, we are by definition last
auto RI = cast<OutputSection<ELFT>>(this->OutSec)->Sections.rbegin();
InputSection<ELFT> *LE = *(++RI);
InputSection<ELFT> *LC = cast<InputSection<ELFT>>(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<ELF32LE> *elf::createCommonSection();
template InputSection<ELF32BE> *elf::createCommonSection();
template InputSection<ELF64LE> *elf::createCommonSection();
@ -1780,3 +1800,8 @@ template class elf::MipsRldMapSection<ELF32LE>;
template class elf::MipsRldMapSection<ELF32BE>;
template class elf::MipsRldMapSection<ELF64LE>;
template class elf::MipsRldMapSection<ELF64BE>;
template class elf::ARMExidxSentinelSection<ELF32LE>;
template class elf::ARMExidxSentinelSection<ELF32BE>;
template class elf::ARMExidxSentinelSection<ELF64LE>;
template class elf::ARMExidxSentinelSection<ELF64BE>;

View File

@ -612,6 +612,13 @@ public:
void writeTo(uint8_t *Buf) override;
};
template <class ELFT> class ARMExidxSentinelSection : public SyntheticSection<ELFT> {
public:
ARMExidxSentinelSection();
size_t getSize() const override { return 8; }
void writeTo(uint8_t *Buf) override;
};
template <class ELFT> InputSection<ELFT> *createCommonSection();
template <class ELFT> InputSection<ELFT> *createInterpSection();
template <class ELFT> MergeInputSection<ELFT> *createCommentSection();

View File

@ -1025,6 +1025,10 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
addInputSec(In<ELFT>::EhFrameHdr);
if (Out<ELFT>::Bss->Size > 0)
Add(Out<ELFT>::Bss);
auto OS = dyn_cast_or_null<OutputSection<ELFT>>(findSection(".ARM.exidx"));
if (OS && !OS->Sections.empty() && !Config->Relocatable)
OS->addSection(make<ARMExidxSentinelSection<ELFT>>());
}
// The linker is expected to define SECNAME_start and SECNAME_end

View File

@ -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 @@ __aeabi_unwind_cpp_pr0:
// 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 @@ __aeabi_unwind_cpp_pr0:
// 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: )

View File

@ -68,11 +68,13 @@ _start:
// 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 @@ _start:
// 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: ]

View File

@ -113,11 +113,13 @@ _start:
// 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

View File

@ -109,14 +109,14 @@ f3:
// 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 @@ f3:
// 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

View File

@ -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

View File

@ -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

View File

@ -41,5 +41,5 @@ __aeabi_unwind_cpp_pr0:
// 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

View File

@ -23,7 +23,7 @@ _start:
.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

View File

@ -39,22 +39,22 @@ _ZTIi: .word 0
// 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