173 lines
5.2 KiB
ArmAsm
173 lines
5.2 KiB
ArmAsm
// REQUIRES: arm
|
|
// RUN: rm -rf %t && split-file %s %t
|
|
|
|
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi --arm-add-build-attributes %t/a.s -o %t/a.o
|
|
// RUN: ld.lld %t/a.o -T %t/exidx-non-zero-offset.t -o %t/non-zero
|
|
// RUN: llvm-readelf --program-headers --unwind --symbols -x .exceptions %t/non-zero | FileCheck %s
|
|
// RUN: ld.lld %t/a.o -T %t/exidx-zero-offset.t -o %t/zero
|
|
// RUN: llvm-readelf --program-headers --unwind --symbols -x .exceptions %t/zero | FileCheck %s
|
|
|
|
/// On platforms that load ELF files directly the ARM.exidx sections
|
|
/// are located with the PT_ARM_EXIDX program header. This requires
|
|
/// all .ARM.exidx input sections to be placed in a single
|
|
/// .ARM.exidx output section. Embedded systems that do not load
|
|
/// from an ELF file use the linker defined symbols __exidx_start and
|
|
/// __exidx_stop. There is no requirement to place the .ARM.exidx
|
|
/// input sections in their own output section. This test case checks
|
|
/// that a .ARM.exidx synthetic section that isn't at a zero offset
|
|
/// within the output section gets the correct offsets. We check
|
|
/// this by checking that equal amounts of alignment padding
|
|
/// inserted before and after the section start produce the same
|
|
/// results.
|
|
|
|
/// For the two linker scripts, one with the .ARM.exidx table
|
|
/// at a zero offset within its output section and one with a
|
|
/// non-zero offset, but both at the same file and address;
|
|
/// the PT_ARM_EXIDX, symbols and table contents should be the
|
|
/// same.
|
|
// CHECK: EXIDX 0x010080 0x00000080 0x00000080 0x00028 0x00028 R 0x4
|
|
|
|
/// unwind entries starting from the right address are identical.
|
|
/// llvm-readelf does not seem to be able to detect Thumb functionNames
|
|
/// whereas arm-none-eabi-readelf can. Used CHECK rather than CHECK-NEXT
|
|
/// to cope with possible improvements llvm-readelf.
|
|
// CHECK: FunctionAddress: 0x0
|
|
// CHECK-NEXT: FunctionName: f1
|
|
// CHECK-NEXT: Model: Compact (Inline)
|
|
// CHECK-NEXT: PersonalityIndex: 0
|
|
// CHECK-NEXT: Opcodes [
|
|
// CHECK-NEXT: 0x97 ; vsp = r7
|
|
// CHECK-NEXT: 0x84 0x08 ; pop {r7, lr}
|
|
// CHECK-NEXT: ]
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: Entry {
|
|
// CHECK-NEXT: FunctionAddress: 0x8
|
|
// CHECK-NEXT: FunctionName: f2
|
|
// CHECK-NEXT: Model: CantUnwind
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: Entry {
|
|
// CHECK-NEXT: FunctionAddress: 0xE
|
|
// CHECK: ExceptionHandlingTable: .ARM.extab
|
|
// CHECK-NEXT: TableEntryAddress: 0xA8
|
|
// CHECK-NEXT: Model: Generic
|
|
// CHECK-NEXT: PersonalityRoutineAddress: 0x12
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: Entry {
|
|
// CHECK-NEXT: FunctionAddress: 0x10
|
|
// CHECK: Model: CantUnwind
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: Entry {
|
|
// CHECK-NEXT: FunctionAddress: 0x14
|
|
// CHECK-NEXT: FunctionName: __ARMv7ABSLongThunk_f3
|
|
// CHECK-NEXT: Model: CantUnwind
|
|
// CHECK-NEXT: }
|
|
|
|
// CHECK: {{[0-9]+}}: 00000080 {{.*}} __exidx_start
|
|
// CHECK-NEXT: {{[0-9]+}}: 000000a8 {{.*}} __exidx_end
|
|
|
|
// CHECK: 0x00000080 80ffff7f 08849780 80ffff7f 01000000
|
|
// CHECK-NEXT: 0x00000090 7effff7f 14000000 78ffff7f 01000000
|
|
// CHECK-NEXT: 0x000000a0 74ffff7f 01000000
|
|
|
|
//--- exidx-non-zero-offset.t
|
|
SECTIONS {
|
|
.text : { *(.text .text.*) }
|
|
/* Addition of thunk in .text changes alignment padding */
|
|
.exceptions : {
|
|
/* Alignment padding within .exceptions */
|
|
. = ALIGN(128);
|
|
/* Embedded C libraries find exceptions via linker defined
|
|
symbols */
|
|
__exidx_start = .;
|
|
*(.ARM.exidx) ;
|
|
__exidx_end = .;
|
|
}
|
|
.ARM.extab : { *(.ARM.extab .ARM.extab.*) }
|
|
}
|
|
|
|
//--- exidx-zero-offset.t
|
|
SECTIONS {
|
|
.text : { *(.text .text.*) }
|
|
/* Addition of thunk in .text changes alignment padding */
|
|
/* alignment padding before .exceptions starts */
|
|
.exceptions : ALIGN(128) {
|
|
/* Embedded C libraries find exceptions via linker defined
|
|
symbols */
|
|
__exidx_start = .;
|
|
*(.ARM.exidx) ;
|
|
__exidx_end = .;
|
|
}
|
|
.ARM.extab : { *(.ARM.extab .ARM.extab.*) }
|
|
}
|
|
|
|
//--- a.s
|
|
.syntax unified
|
|
|
|
/// Expect inline unwind instructions.
|
|
.section .text.01, "ax", %progbits
|
|
.arm
|
|
.balign 4
|
|
.global f1
|
|
.type f1, %function
|
|
f1:
|
|
.fnstart
|
|
/// provoke an interworking thunk.
|
|
b f3
|
|
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
|
|
.type f2, %function
|
|
.balign 4
|
|
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
|
|
.type f3, %function
|
|
.thumb
|
|
.balign 2
|
|
f3:
|
|
.fnstart
|
|
bx lr
|
|
.cantunwind
|
|
.fnend
|
|
|
|
/// Expect a section with a reference to an .ARM.extab.
|
|
.section .text.04, "ax",%progbits
|
|
.global f4
|
|
.balign 2
|
|
.type f4, %function
|
|
f4:
|
|
.fnstart
|
|
bx lr
|
|
.personality __gxx_personality_v0
|
|
.handlerdata
|
|
.long 0
|
|
.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
|
|
.type __aeabi_unwind_cpp_pr0, %function
|
|
.balign 2
|
|
__aeabi_unwind_cpp_pr0:
|
|
bx lr
|
|
|
|
.section .text.__gcc_personality_v0, "ax", %progbits
|
|
.global __gxx_personality_v0
|
|
.type __gcc_personality_v0, %function
|
|
.balign 2
|
|
__gxx_personality_v0:
|
|
bx lr
|