From f0bdd7589a225589c1fda7ce8762663ee9176746 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Tue, 20 Mar 2018 10:56:17 +0100 Subject: [ARM] FDPIC: Implement Thumb-only PLT for FDPIC. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2018-XX-XX Christophe Lyon Mickaël Guêné bfd/ * elf32-arm.c (elf32_arm_fdpic_thumb_plt_entry): New. (elf32_arm_plt_needs_thumb_stub_p): Handle thumb-only case. (elf32_arm_populate_plt_entry): Likewise. (elf32_arm_output_plt_map_1): Likewise. (elf32_arm_output_arch_local_syms): Likewise. ld/testsuite/ * arm-elf.exp: Execute the new FDPIC Thumb-only tests. * fdpic-main-m.d: New test. * fdpic-main-m.s: New. * fdpic-main-m.sym: New. * fdpic-shared-m.d: New test. * fdpic-shared-m.s: New. * fdpic-shared-m.sym: New. --- bfd/elf32-arm.c | 64 ++++++++++++++++--------- ld/testsuite/ld-arm/arm-elf.exp | 12 +++++ ld/testsuite/ld-arm/fdpic-main-m.d | 73 +++++++++++++++++++++++++++++ ld/testsuite/ld-arm/fdpic-main-m.s | 86 ++++++++++++++++++++++++++++++++++ ld/testsuite/ld-arm/fdpic-main-m.sym | 14 ++++++ ld/testsuite/ld-arm/fdpic-shared-m.d | 37 +++++++++++++++ ld/testsuite/ld-arm/fdpic-shared-m.s | 52 ++++++++++++++++++++ ld/testsuite/ld-arm/fdpic-shared-m.sym | 15 ++++++ 8 files changed, 332 insertions(+), 21 deletions(-) create mode 100644 ld/testsuite/ld-arm/fdpic-main-m.d create mode 100644 ld/testsuite/ld-arm/fdpic-main-m.s create mode 100644 ld/testsuite/ld-arm/fdpic-main-m.sym create mode 100644 ld/testsuite/ld-arm/fdpic-shared-m.d create mode 100644 ld/testsuite/ld-arm/fdpic-shared-m.s create mode 100644 ld/testsuite/ld-arm/fdpic-shared-m.sym diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index b72e397..a42db44 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -2290,6 +2290,22 @@ static const bfd_vma elf32_arm_fdpic_plt_entry [] = 0xe599f000, /* ldr pc, [r9] */ }; +/* Thumb FDPIC PLT entry. */ +/* The last 5 words contain PLT lazy fragment code and data. */ +static const bfd_vma elf32_arm_fdpic_thumb_plt_entry [] = + { + 0xc00cf8df, /* ldr.w r12, .L1 */ + 0x0c09eb0c, /* add.w r12, r12, r9 */ + 0x9004f8dc, /* ldr.w r9, [r12, #4] */ + 0xf000f8dc, /* ldr.w pc, [r12] */ + 0x00000000, /* .L1 .word foo(GOTOFFFUNCDESC) */ + 0x00000000, /* .L2 .word foo(funcdesc_value_reloc_offset) */ + 0xc008f85f, /* ldr.w r12, .L2 */ + 0xcd04f84d, /* push {r12} */ + 0xc004f8d9, /* ldr.w r12, [r9, #4] */ + 0xf000f8d9, /* ldr.w pc, [r9] */ + }; + #ifdef FOUR_WORD_PLT /* The first entry in a procedure linkage table looks like @@ -3620,6 +3636,8 @@ elf32_arm_get_plt_info (bfd *abfd, struct elf32_arm_link_hash_table *globals, return TRUE; } +static bfd_boolean using_thumb_only (struct elf32_arm_link_hash_table *globals); + /* Return true if the PLT described by ARM_PLT requires a Thumb stub before it. */ @@ -3630,8 +3648,9 @@ elf32_arm_plt_needs_thumb_stub_p (struct bfd_link_info *info, struct elf32_arm_link_hash_table *htab; htab = elf32_arm_hash_table (info); - return (arm_plt->thumb_refcount != 0 - || (!htab->use_blx && arm_plt->maybe_thumb_refcount != 0)); + + return (!using_thumb_only(htab) && (arm_plt->thumb_refcount != 0 + || (!htab->use_blx && arm_plt->maybe_thumb_refcount != 0))); } /* Return a pointer to the head of the dynamic reloc list that should @@ -9729,6 +9748,10 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, } else if (htab->fdpic_p) { + const bfd_vma *plt_entry = using_thumb_only(htab) + ? elf32_arm_fdpic_thumb_plt_entry + : elf32_arm_fdpic_plt_entry; + /* Fill-up Thumb stub if needed. */ if (elf32_arm_plt_needs_thumb_stub_p (info, arm_plt)) { @@ -9737,14 +9760,13 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, put_thumb_insn (htab, output_bfd, elf32_arm_plt_thumb_stub[1], ptr - 2); } - put_arm_insn(htab, output_bfd, - elf32_arm_fdpic_plt_entry[0], ptr + 0); - put_arm_insn(htab, output_bfd, - elf32_arm_fdpic_plt_entry[1], ptr + 4); - put_arm_insn(htab, output_bfd, - elf32_arm_fdpic_plt_entry[2], ptr + 8); - put_arm_insn(htab, output_bfd, - elf32_arm_fdpic_plt_entry[3], ptr + 12); + /* As we are using 32 bit instructions even for the Thumb + version, we have to use 'put_arm_insn' instead of + 'put_thumb_insn'. */ + put_arm_insn(htab, output_bfd, plt_entry[0], ptr + 0); + put_arm_insn(htab, output_bfd, plt_entry[1], ptr + 4); + put_arm_insn(htab, output_bfd, plt_entry[2], ptr + 8); + put_arm_insn(htab, output_bfd, plt_entry[3], ptr + 12); bfd_put_32 (output_bfd, got_offset, ptr + 16); if (!(info->flags & DF_BIND_NOW)) @@ -9753,14 +9775,10 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, bfd_put_32 (output_bfd, htab->root.srelplt->reloc_count * RELOC_SIZE (htab), ptr + 20); - put_arm_insn(htab, output_bfd, - elf32_arm_fdpic_plt_entry[6], ptr + 24); - put_arm_insn(htab, output_bfd, - elf32_arm_fdpic_plt_entry[7], ptr + 28); - put_arm_insn(htab, output_bfd, - elf32_arm_fdpic_plt_entry[8], ptr + 32); - put_arm_insn(htab, output_bfd, - elf32_arm_fdpic_plt_entry[9], ptr + 36); + put_arm_insn(htab, output_bfd, plt_entry[6], ptr + 24); + put_arm_insn(htab, output_bfd, plt_entry[7], ptr + 28); + put_arm_insn(htab, output_bfd, plt_entry[8], ptr + 32); + put_arm_insn(htab, output_bfd, plt_entry[9], ptr + 36); } } else if (using_thumb_only (htab)) @@ -17767,15 +17785,19 @@ elf32_arm_output_plt_map_1 (output_arch_syminfo *osi, } else if (htab->fdpic_p) { + enum map_symbol_type type = using_thumb_only(htab) + ? ARM_MAP_THUMB + : ARM_MAP_ARM; + if (elf32_arm_plt_needs_thumb_stub_p (osi->info, arm_plt)) if (!elf32_arm_output_map_sym (osi, ARM_MAP_THUMB, addr - 4)) return FALSE; - if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr)) + if (!elf32_arm_output_map_sym (osi, type, addr)) return FALSE; if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 16)) return FALSE; if (htab->plt_entry_size == 4 * ARRAY_SIZE(elf32_arm_fdpic_plt_entry)) - if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr + 24)) + if (!elf32_arm_output_map_sym (osi, type, addr + 24)) return FALSE; } else if (using_thumb_only (htab)) @@ -18134,7 +18156,7 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd, if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, 0)) return FALSE; } - else if (using_thumb_only (htab)) + else if (using_thumb_only (htab) && !htab->fdpic_p) { if (!elf32_arm_output_map_sym (&osi, ARM_MAP_THUMB, 0)) return FALSE; diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index 30e01c5..88775bb 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -1043,6 +1043,18 @@ set armfdpiceabitests { {{objdump -fdw fdpic-main.d} {objdump -Rw fdpic-main.r} {readelf -Ds fdpic-main.sym}} "fdpic-main"} + {"FDPIC ARM shared library little endian M profile" + "-shared -T fdpic-shared.ld --hash-style=sysv -EL -m armelf_linux_fdpiceabi" "" + "-EL -fdpic" {fdpic-shared-m.s} + {{objdump -fdw fdpic-shared-m.d} {objdump -Rw fdpic-shared.r} + {readelf -Ds fdpic-shared-m.sym}} + "fdpic-shared.so"} + {"FDPIC ARM dynamic executable little endian M profile" + "tmpdir/fdpic-shared.so -T fdpic-main.ld --hash-style=sysv -EL -m armelf_linux_fdpiceabi" "" + "-EL -fdpic" {fdpic-main-m.s} + {{objdump -fdw fdpic-main-m.d} {objdump -Rw fdpic-main.r} + {readelf -Ds fdpic-main-m.sym}} + "fdpic-main"} } # Massage the $armeabitests_common list into run_ld_link_tests standard form. diff --git a/ld/testsuite/ld-arm/fdpic-main-m.d b/ld/testsuite/ld-arm/fdpic-main-m.d new file mode 100644 index 0000000..ed0f41a --- /dev/null +++ b/ld/testsuite/ld-arm/fdpic-main-m.d @@ -0,0 +1,73 @@ + +tmpdir/fdpic-main: file format elf32-(little|big)arm +architecture: arm.*, flags 0x00000112: +EXEC_P, HAS_SYMS, D_PAGED +start address 0x.* + +Disassembly of section .plt: + +.* <.plt>: + .*: f8df c00c ldr.w ip, \[pc, #12\] ; .* <.plt\+0x10> + .*: eb0c 0c09 add.w ip, ip, r9 + .*: f8dc 9004 ldr.w r9, \[ip, #4\] + .*: f8dc f000 ldr.w pc, \[ip\] + .*: 0000000c .word 0x0000000c + .*: 00000000 .word 0x00000000 + .*: f85f c008 ldr.w ip, \[pc, #-8\] ; .* <.plt\+0x14> + .*: f84d cd04 str.w ip, \[sp, #-4\]! + .*: f8d9 c004 ldr.w ip, \[r9, #4\] + .*: f8d9 f000 ldr.w pc, \[r9\] + .*: f8df c00c ldr.w ip, \[pc, #12\] ; .* <.plt\+0x38> + .*: eb0c 0c09 add.w ip, ip, r9 + .*: f8dc 9004 ldr.w r9, \[ip, #4\] + .*: f8dc f000 ldr.w pc, \[ip] + .*: 00000014 .word 0x00000014 + .*: 00000008 .word 0x00000008 + .*: f85f c008 ldr.w ip, \[pc, #-8\] ; .* <.plt\+0x3c> + .*: f84d cd04 str.w ip, \[sp, #-4\]! + .*: f8d9 c004 ldr.w ip, \[r9, #4\] + .*: f8d9 f000 ldr.w pc, \[r9\] + +Disassembly of section .text: + +.* <_start>: + .*: f000 b800 b.w .*
+ +.*
: + .*: 4a11 ldr r2, \[pc, #68\] ; .* .* + .*: 4b12 ldr r3, \[pc, #72\] ; .* .* + .*: b570 push {r4, r5, r6, lr} + .*: f859 5002 ldr.w r5, \[r9, r2\] + .*: 464c mov r4, r9 + .*: f859 3003 ldr.w r3, \[r9, r3\] + .*: 602b str r3, \[r5, #0\] + .*: f7ff ffcb bl .* <.plt> + .*: 4606 mov r6, r0 + .*: 46a1 mov r9, r4 + .*: 6828 ldr r0, \[r5, #0\] + .*: 46a1 mov r9, r4 + .*: f7ff ffd9 bl .* <.plt\+0x28> + .*: 4b0b ldr r3, \[pc, #44\] ; .* .* + .*: 46a1 mov r9, r4 + .*: 444b add r3, r9 + .*: 4618 mov r0, r3 + .*: 602b str r3, \[r5, #0\] + .*: 46a1 mov r9, r4 + .*: f7ff ffd1 bl .* <.plt\+0x28> + .*: 4b08 ldr r3, \[pc, #32\] ; .* .* + .*: 46a1 mov r9, r4 + .*: f859 3003 ldr.w r3, \[r9, r3\] + .*: 6818 ldr r0, \[r3, #0\] + .*: 46a1 mov r9, r4 + .*: f7ff ffc9 bl .* <.plt\+0x28> + .*: 4630 mov r0, r6 + .*: 46a1 mov r9, r4 + .*: bd70 pop {r4, r5, r6, pc} + .*: 0000002c .word 0x0000002c + .*: 00000024 .word 0x00000024 + .*: 0000001c .word 0x0000001c + .*: 00000028 .word 0x00000028 + +.* : + .*: 4770 bx lr + .*: bf00 nop diff --git a/ld/testsuite/ld-arm/fdpic-main-m.s b/ld/testsuite/ld-arm/fdpic-main-m.s new file mode 100644 index 0000000..4fb40ca --- /dev/null +++ b/ld/testsuite/ld-arm/fdpic-main-m.s @@ -0,0 +1,86 @@ + .arch armv7-m + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 26, 2 + .eabi_attribute 30, 2 + .eabi_attribute 34, 1 + .eabi_attribute 18, 4 + .file "hello.c" + .text + .align 2 + .syntax unified + .thumb + .fpu softvfp + .type my_local_func, %function +my_local_func: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. + bx lr + .size my_local_func, .-my_local_func + .section .text.startup,"ax",%progbits + .align 2 + .global _start + .syntax unified + .thumb + .fpu softvfp + .type _start, %function +_start: + b main + + .global main + .syntax unified + .thumb + .fpu softvfp + .type main, %function +main: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + ldr r2, .L4 + ldr r3, .L4+4 + push {r4, r5, r6, lr} + ldr r5, [r9, r2] + mov r4, r9 + ldr r3, [r9, r3] + str r3, [r5] + bl my_shared_func1(PLT) + mov r6, r0 + mov r9, r4 + ldr r0, [r5] + mov r9, r4 + bl my_shared_func2(PLT) + ldr r3, .L4+8 + mov r9, r4 + add r3, r3, r9 + mov r0, r3 + str r3, [r5] + mov r9, r4 + bl my_shared_func2(PLT) + ldr r3, .L4+12 + mov r9, r4 + ldr r3, [r9, r3] + ldr r0, [r3] + mov r9, r4 + bl my_shared_func2(PLT) + mov r0, r6 + mov r9, r4 + pop {r4, r5, r6, pc} +.L5: + .align 2 +.L4: + .word funcptr(GOT) + .word my_shared_func1(GOTFUNCDESC) + .word my_local_func(GOTOFFFUNCDESC) + .word funcptr2(GOT) + .size main, .-main + .global funcptr2 + .comm funcptr,4,4 + .section .data.rel,"aw",%progbits + .align 2 + .type funcptr2, %object + .size funcptr2, 4 +funcptr2: + .word my_shared_func1(FUNCDESC) diff --git a/ld/testsuite/ld-arm/fdpic-main-m.sym b/ld/testsuite/ld-arm/fdpic-main-m.sym new file mode 100644 index 0000000..9eaf617 --- /dev/null +++ b/ld/testsuite/ld-arm/fdpic-main-m.sym @@ -0,0 +1,14 @@ + +Symbol table for image: + +Num +Buc: +Value +Size +Type +Bind +Vis +Ndx +Name + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _edata + +.. +..: ........ +0 +FUNC +GLOBAL +DEFAULT +UND my_shared_func2 + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start__ + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +13 _end + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +13 __bss_end__ + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +13 __end__ + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT + 9 __ROFIXUP_LIST__ + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT + 9 __ROFIXUP_END__ + +.. +..: ........ +0 +FUNC +GLOBAL +DEFAULT +UND my_shared_func1 + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +13 _bss_end__ diff --git a/ld/testsuite/ld-arm/fdpic-shared-m.d b/ld/testsuite/ld-arm/fdpic-shared-m.d new file mode 100644 index 0000000..49e4d2c --- /dev/null +++ b/ld/testsuite/ld-arm/fdpic-shared-m.d @@ -0,0 +1,37 @@ + +tmpdir/fdpic-shared.so: file format elf32-(little|big)arm +architecture: arm.*, flags 0x00000150: +HAS_SYMS, DYNAMIC, D_PAGED +start address 0x.* + +Disassembly of section .plt: + +.* <.plt>: + .*: f8df c00c ldr.w ip, \[pc, #12\] ; .* <.plt\+0x10> + .*: eb0c 0c09 add.w ip, ip, r9 + .*: f8dc 9004 ldr.w r9, \[ip, #4\] + .*: f8dc f000 ldr.w pc, \[ip\] + .*: 0000000c .word 0x0000000c + .*: 00000000 .word 0x00000000 + .*: f85f c008 ldr.w ip, \[pc, #-8\] ; .* <.plt\+0x14> + .*: f84d cd04 str.w ip, \[sp, #-4\]! + .*: f8d9 c004 ldr.w ip, \[r9, #4\] + .*: f8d9 f000 ldr.w pc, \[r9\] + +Disassembly of section .text: + +.* : + .*: 4770 bx lr + .*: bf00 nop + +.* : + .*: f04f 0000 mov.w r0, #0 + .*: 4770 bx lr + .*: bf00 nop + +.* : + .*: b510 push {r4, lr} + .*: 464c mov r4, r9 + .*: f7ff ffe2 bl .* <.plt> + .*: 46a1 mov r9, r4 + .*: bd10 pop {r4, pc} diff --git a/ld/testsuite/ld-arm/fdpic-shared-m.s b/ld/testsuite/ld-arm/fdpic-shared-m.s new file mode 100644 index 0000000..ab01a08 --- /dev/null +++ b/ld/testsuite/ld-arm/fdpic-shared-m.s @@ -0,0 +1,52 @@ + .arch armv7-m + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 26, 2 + .eabi_attribute 30, 2 + .eabi_attribute 34, 1 + .eabi_attribute 18, 4 + .file "shared.c" + .text + .align 2 + .global my_shared_func1 + .syntax unified + .thumb + .fpu softvfp + .type my_shared_func1, %function +my_shared_func1: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. + bx lr + .size my_shared_func1, .-my_shared_func1 + .align 2 + .global my_shared_func3 + .syntax unified + .thumb + .fpu softvfp + .type my_shared_func3, %function +my_shared_func3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. + mov r0, #0 + bx lr + .size my_shared_func3, .-my_shared_func3 + .align 2 + .global my_shared_func2 + .syntax unified + .thumb + .fpu softvfp + .type my_shared_func2, %function +my_shared_func2: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + push {r4, lr} + mov r4, r9 + bl my_shared_func3(PLT) + mov r9, r4 + pop {r4, pc} + .size my_shared_func2, .-my_shared_func2 diff --git a/ld/testsuite/ld-arm/fdpic-shared-m.sym b/ld/testsuite/ld-arm/fdpic-shared-m.sym new file mode 100644 index 0000000..1475370 --- /dev/null +++ b/ld/testsuite/ld-arm/fdpic-shared-m.sym @@ -0,0 +1,15 @@ + +Symbol table for image: + +Num +Buc: +Value +Size +Type +Bind +Vis +Ndx +Name + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _edata + +.. +..: ........ +12 +FUNC +GLOBAL +DEFAULT +6 my_shared_func2 + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start__ + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _end + +.. +..: ........ +6 +FUNC +GLOBAL +DEFAULT +6 my_shared_func3 + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_end__ + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __end__ + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +7 __ROFIXUP_LIST__ + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +7 __ROFIXUP_END__ + +.. +..: ........ +2 +FUNC +GLOBAL +DEFAULT +6 my_shared_func1 + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _bss_end__ -- cgit v1.1