diff options
author | Yuri Gribov <y.gribov@samsung.com> | 2014-02-27 14:35:37 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2014-02-27 14:35:37 +0000 |
commit | 1db37fe62781b677a37acbe801c1e69d8912a124 (patch) | |
tree | 48caffe8619eea72d91b80bb71ca0a6632bc5a63 | |
parent | fa96cb382c12b099675c5cc238aaa7352a3fd3d7 (diff) | |
download | fsf-binutils-gdb-1db37fe62781b677a37acbe801c1e69d8912a124.zip fsf-binutils-gdb-1db37fe62781b677a37acbe801c1e69d8912a124.tar.gz fsf-binutils-gdb-1db37fe62781b677a37acbe801c1e69d8912a124.tar.bz2 |
This patch adds support for ARM PLT entries that support a full 32-bit offset range.
Enabled via the use of a new linker command line option: --long-plt.
* bfd-in.h: Add export of bfd_elf32_arm_use_long_plt.
* bfd-in2.h: Regenerate.
* elf32-arm.c (elf32_arm_plt_entry_long): New array.
(elf32_arm_link_hash_table_create): Set plt_entry_size to 16 if
using long PLT entries.
(bfd_elf32_arm_use_long_plt): New function.
(elf32_arm_populate_plt_entry): Add support for long PLT entries.
* emultempl/armelf.em (OPTION_LONG_PLT): Define.
(PARSE_AND_LIST_LONGOPTS): Add long-plt.
(PARSE_AND_LIST_OPTIONS): Likewise.
(PARSE_AND_LIST_ARGS_CASES): Handle long-plt.
* ld.texinfo: Document --long-plt.
* ld-arm/long-plt-format.s: New test case.
* ld-arm/long-plt-format.d: Expected disassembly.
* ld-arm/arm-elf.exp: Run the new test.
-rw-r--r-- | bfd/ChangeLog | 10 | ||||
-rw-r--r-- | bfd/bfd-in.h | 12 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 12 | ||||
-rw-r--r-- | bfd/elf32-arm.c | 83 | ||||
-rw-r--r-- | ld/ChangeLog | 8 | ||||
-rw-r--r-- | ld/emultempl/armelf.em | 14 | ||||
-rw-r--r-- | ld/ld.texinfo | 35 | ||||
-rw-r--r-- | ld/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-arm/arm-elf.exp | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-arm/long-plt-format.d | 15 | ||||
-rw-r--r-- | ld/testsuite/ld-arm/long-plt-format.s | 7 |
11 files changed, 162 insertions, 46 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 069a6ce..472bc89 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2014-02-27 Yuri Gribov <y.gribov@samsung.com> + + * bfd-in.h: Add export of bfd_elf32_arm_use_long_plt. + * bfd-in2.h: Regenerate. + * elf32-arm.c (elf32_arm_plt_entry_long): New array. + (elf32_arm_link_hash_table_create): Set plt_entry_size to 16 if + using long PLT entries. + (bfd_elf32_arm_use_long_plt): New function. + (elf32_arm_populate_plt_entry): Add support for long PLT entries. + 2014-02-27 Alan Modra <amodra@gmail.com> * elf32-ppc.c (ppc_elf_link_hash_table_create): Provide default diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index c7c5a7d..54ddac9 100644 --- a/bfd/bfd-in.h +++ b/bfd/bfd-in.h @@ -1,6 +1,6 @@ /* Main header file for the bfd library -- portable access to object files. - Copyright 1990-2013 Free Software Foundation, Inc. + Copyright 1990-2014 Free Software Foundation, Inc. Contributed by Cygnus Support. @@ -877,15 +877,19 @@ extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking extern bfd_boolean bfd_elf32_arm_add_glue_sections_to_bfd (bfd *, struct bfd_link_info *); -/* ELF ARM mapping symbol support */ +/* ELF ARM mapping symbol support. */ #define BFD_ARM_SPECIAL_SYM_TYPE_MAP (1 << 0) #define BFD_ARM_SPECIAL_SYM_TYPE_TAG (1 << 1) #define BFD_ARM_SPECIAL_SYM_TYPE_OTHER (1 << 2) #define BFD_ARM_SPECIAL_SYM_TYPE_ANY (~0) + extern bfd_boolean bfd_is_arm_special_symbol_name - (const char * name, int type); + (const char *, int); + +extern void bfd_elf32_arm_set_byteswap_code + (struct bfd_link_info *, int); -extern void bfd_elf32_arm_set_byteswap_code (struct bfd_link_info *, int); +extern void bfd_elf32_arm_use_long_plt (void); /* ARM Note section processing. */ extern bfd_boolean bfd_arm_merge_machines diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 33792f4..ebc7496 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -7,7 +7,7 @@ /* Main header file for the bfd library -- portable access to object files. - Copyright 1990-2013 Free Software Foundation, Inc. + Copyright 1990-2014 Free Software Foundation, Inc. Contributed by Cygnus Support. @@ -884,15 +884,19 @@ extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking extern bfd_boolean bfd_elf32_arm_add_glue_sections_to_bfd (bfd *, struct bfd_link_info *); -/* ELF ARM mapping symbol support */ +/* ELF ARM mapping symbol support. */ #define BFD_ARM_SPECIAL_SYM_TYPE_MAP (1 << 0) #define BFD_ARM_SPECIAL_SYM_TYPE_TAG (1 << 1) #define BFD_ARM_SPECIAL_SYM_TYPE_OTHER (1 << 2) #define BFD_ARM_SPECIAL_SYM_TYPE_ANY (~0) + extern bfd_boolean bfd_is_arm_special_symbol_name - (const char * name, int type); + (const char *, int); + +extern void bfd_elf32_arm_set_byteswap_code + (struct bfd_link_info *, int); -extern void bfd_elf32_arm_set_byteswap_code (struct bfd_link_info *, int); +extern void bfd_elf32_arm_use_long_plt (void); /* ARM Note section processing. */ extern bfd_boolean bfd_arm_merge_machines diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 7216244..b17f4d4 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -1,5 +1,5 @@ /* 32-bit ELF support for ARM - Copyright 1998-2013 Free Software Foundation, Inc. + Copyright 1998-2014 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -2140,15 +2140,27 @@ static const bfd_vma elf32_arm_plt0_entry [] = 0x00000000, /* &GOT[0] - . */ }; -/* Subsequent entries in a procedure linkage table look like - this. */ -static const bfd_vma elf32_arm_plt_entry [] = +/* By default subsequent entries in a procedure linkage table look like + this. Offsets that don't fit into 28 bits will cause link error. */ +static const bfd_vma elf32_arm_plt_entry_short [] = { 0xe28fc600, /* add ip, pc, #0xNN00000 */ 0xe28cca00, /* add ip, ip, #0xNN000 */ 0xe5bcf000, /* ldr pc, [ip, #0xNNN]! */ }; +/* When explicitly asked, we'll use this "long" entry format + which can cope with arbitrary displacements. */ +static const bfd_vma elf32_arm_plt_entry_long [] = +{ + 0xe28fc200, /* add ip, pc, #0xN0000000 */ + 0xe28cc600, /* add ip, ip, #0xNN00000 */ + 0xe28cca00, /* add ip, ip, #0xNN000 */ + 0xe5bcf000, /* ldr pc, [ip, #0xNNN]! */ +}; + +static bfd_boolean elf32_arm_use_long_plt_entry = FALSE; + #endif /* The format of the first entry in the procedure linkage table @@ -3464,7 +3476,7 @@ elf32_arm_link_hash_table_create (bfd *abfd) ret->plt_entry_size = 16; #else ret->plt_header_size = 20; - ret->plt_entry_size = 12; + ret->plt_entry_size = elf32_arm_use_long_plt_entry ? 16 : 12; #endif ret->use_rel = 1; ret->obfd = abfd; @@ -6027,6 +6039,15 @@ arm_make_glue_section (bfd * abfd, const char * name) return TRUE; } +/* Set size of .plt entries. This function is called from the + linker scripts in ld/emultempl/{armelf}.em. */ + +void +bfd_elf32_arm_use_long_plt (void) +{ + elf32_arm_use_long_plt_entry = TRUE; +} + /* Add the glue sections to ABFD. This function is called from the linker scripts in ld/emultempl/{armelf}.em. */ @@ -7705,8 +7726,6 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, of the PLT stub. */ got_displacement = got_address - (plt_address + 8); - BFD_ASSERT ((got_displacement & 0xf0000000) == 0); - if (elf32_arm_plt_needs_thumb_stub_p (info, arm_plt)) { put_thumb_insn (htab, output_bfd, @@ -7715,21 +7734,45 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, elf32_arm_plt_thumb_stub[1], ptr - 2); } - put_arm_insn (htab, output_bfd, - elf32_arm_plt_entry[0] - | ((got_displacement & 0x0ff00000) >> 20), - ptr + 0); - put_arm_insn (htab, output_bfd, - elf32_arm_plt_entry[1] - | ((got_displacement & 0x000ff000) >> 12), - ptr+ 4); - put_arm_insn (htab, output_bfd, - elf32_arm_plt_entry[2] - | (got_displacement & 0x00000fff), - ptr + 8); + if (!elf32_arm_use_long_plt_entry) + { + BFD_ASSERT ((got_displacement & 0xf0000000) == 0); + + put_arm_insn (htab, output_bfd, + elf32_arm_plt_entry_short[0] + | ((got_displacement & 0x0ff00000) >> 20), + ptr + 0); + put_arm_insn (htab, output_bfd, + elf32_arm_plt_entry_short[1] + | ((got_displacement & 0x000ff000) >> 12), + ptr+ 4); + put_arm_insn (htab, output_bfd, + elf32_arm_plt_entry_short[2] + | (got_displacement & 0x00000fff), + ptr + 8); #ifdef FOUR_WORD_PLT - bfd_put_32 (output_bfd, elf32_arm_plt_entry[3], ptr + 12); + bfd_put_32 (output_bfd, elf32_arm_plt_entry_short[3], ptr + 12); #endif + } + else + { + put_arm_insn (htab, output_bfd, + elf32_arm_plt_entry_long[0] + | ((got_displacement & 0xf0000000) >> 28), + ptr + 0); + put_arm_insn (htab, output_bfd, + elf32_arm_plt_entry_long[1] + | ((got_displacement & 0x0ff00000) >> 20), + ptr + 4); + put_arm_insn (htab, output_bfd, + elf32_arm_plt_entry_long[2] + | ((got_displacement & 0x000ff000) >> 12), + ptr+ 8); + put_arm_insn (htab, output_bfd, + elf32_arm_plt_entry_long[3] + | (got_displacement & 0x00000fff), + ptr + 12); + } } /* Fill in the entry in the .rel(a).(i)plt section. */ diff --git a/ld/ChangeLog b/ld/ChangeLog index a0c5284..57120d1 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,11 @@ +2014-02-27 Yuri Gribov <y.gribov@samsung.com> + + * emultempl/armelf.em (OPTION_LONG_PLT): Define. + (PARSE_AND_LIST_LONGOPTS): Add long-plt. + (PARSE_AND_LIST_OPTIONS): Likewise. + (PARSE_AND_LIST_ARGS_CASES): Handle long-plt. + * ld.texinfo: Document --long-plt. + 2014-02-27 Alan Modra <amodra@gmail.com> * emulparams/elf32ppcvxworks.sh: Source plt_unwind.sh and diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em index 85e924f..6a64793 100644 --- a/ld/emultempl/armelf.em +++ b/ld/emultempl/armelf.em @@ -1,5 +1,5 @@ # This shell script emits a C file. -*- C -*- -# Copyright 1991-2013 Free Software Foundation, Inc. +# Copyright 1991-2014 Free Software Foundation, Inc. # # This file is part of the GNU Binutils. # @@ -28,10 +28,10 @@ fragment <<EOF #include "ldctor.h" #include "elf/arm.h" -static char *thumb_entry_symbol = NULL; +static char * thumb_entry_symbol = NULL; static int byteswap_code = 0; static int target1_is_rel = 0${TARGET1_IS_REL}; -static char *target2_type = "${TARGET2_TYPE}"; +static char * target2_type = "${TARGET2_TYPE}"; static int fix_v4bx = 0; static int use_blx = 0; static bfd_arm_vfp11_fix vfp11_denorm_fix = BFD_ARM_VFP11_FIX_DEFAULT; @@ -531,6 +531,7 @@ PARSE_AND_LIST_PROLOGUE=' #define OPTION_NO_MERGE_EXIDX_ENTRIES 316 #define OPTION_FIX_ARM1176 317 #define OPTION_NO_FIX_ARM1176 318 +#define OPTION_LONG_PLT 319 ' PARSE_AND_LIST_SHORTOPTS=p @@ -555,6 +556,7 @@ PARSE_AND_LIST_LONGOPTS=' { "no-merge-exidx-entries", no_argument, NULL, OPTION_NO_MERGE_EXIDX_ENTRIES }, { "fix-arm1176", no_argument, NULL, OPTION_FIX_ARM1176 }, { "no-fix-arm1176", no_argument, NULL, OPTION_NO_FIX_ARM1176 }, + { "long-plt", no_argument, NULL, OPTION_LONG_PLT }, ' PARSE_AND_LIST_OPTIONS=' @@ -572,6 +574,8 @@ PARSE_AND_LIST_OPTIONS=' fprintf (file, _(" --no-wchar-size-warning Don'\''t warn about objects with incompatible\n" " wchar_t sizes\n")); fprintf (file, _(" --pic-veneer Always generate PIC interworking veneers\n")); + fprintf (file, _(" --long-plt Generate long .plt entries\n" + " to handle large .plt/.got displacements\n")); fprintf (file, _("\ --stub-group-size=N Maximum size of a group of input sections that\n\ can be handled by one stub section. A negative\n\ @@ -675,6 +679,10 @@ PARSE_AND_LIST_ARGS_CASES=' case OPTION_NO_FIX_ARM1176: fix_arm1176 = 0; break; + + case OPTION_LONG_PLT: + bfd_elf32_arm_use_long_plt (); + break; ' # We have our own before_allocation etc. functions, but they call diff --git a/ld/ld.texinfo b/ld/ld.texinfo index b1dff79..eb0b991 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -1,6 +1,6 @@ \input texinfo @setfilename ld.info -@c Copyright 1991-2013 Free Software Foundation, Inc. +@c Copyright 1991-2014 Free Software Foundation, Inc. @syncodeindex ky cp @c man begin INCLUDE @include configdoc.texi @@ -55,7 +55,7 @@ This file documents the @sc{gnu} linker LD @end ifset version @value{VERSION}. -Copyright @copyright{} 1991-2013 Free Software Foundation, Inc. +Copyright @copyright{} 1991-2014 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 @@ -92,7 +92,7 @@ section entitled ``GNU Free Documentation License''. @vskip 0pt plus 1filll @c man begin COPYRIGHT -Copyright @copyright{} 1991-2013 Free Software Foundation, Inc. +Copyright @copyright{} 1991-2014 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 @@ -6257,17 +6257,6 @@ instructions into @code{bal} instructions when it determines that the target subroutine is a leaf routine (that is, the target subroutine does not itself call any subroutines). -@cindex Cortex-A8 erratum workaround -@kindex --fix-cortex-a8 -@kindex --no-fix-cortex-a8 -The @samp{--fix-cortex-a8} switch enables a link-time workaround for an erratum in certain Cortex-A8 processors. The workaround is enabled by default if you are targeting the ARM v7-A architecture profile. It can be enabled otherwise by specifying @samp{--fix-cortex-a8}, or disabled unconditionally by specifying @samp{--no-fix-cortex-a8}. - -The erratum only affects Thumb-2 code. Please contact ARM for further details. - -@kindex --merge-exidx-entries -@kindex --no-merge-exidx-entries -The @samp{--no-merge-exidx-entries} switch disables the merging of adjacent exidx entries in debuginfo. - @ifclear GENERIC @lowersections @end ifclear @@ -6526,6 +6515,24 @@ Farcalls stubs insertion is fully supported for the ARM-EABI target only, because it relies on object files properties not present otherwise. +@cindex Cortex-A8 erratum workaround +@kindex --fix-cortex-a8 +@kindex --no-fix-cortex-a8 +The @samp{--fix-cortex-a8} switch enables a link-time workaround for an erratum in certain Cortex-A8 processors. The workaround is enabled by default if you are targeting the ARM v7-A architecture profile. It can be enabled otherwise by specifying @samp{--fix-cortex-a8}, or disabled unconditionally by specifying @samp{--no-fix-cortex-a8}. + +The erratum only affects Thumb-2 code. Please contact ARM for further details. + +@kindex --merge-exidx-entries +@kindex --no-merge-exidx-entries +@cindex Merging exidx entries +The @samp{--no-merge-exidx-entries} switch disables the merging of adjacent exidx entries in debuginfo. + +@kindex --long-plt +@cindex 32-bit PLT entries +The @samp{--long-plt} option enables the use of 16 byte PLT entries +which support up to 4Gb of code. The default is to use 12 byte PLT +entries which only support 512Mb of code. + @ifclear GENERIC @lowersections @end ifclear diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 1af8109..84ca6b1 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2014-02-27 Yuri Gribov <y.gribov@samsung.com> + + * ld-arm/long-plt-format.s: New test case. + * ld-arm/long-plt-format.d: Expected disassembly. + * ld-arm/arm-elf.exp: Run the new test. + 2014-02-27 Nick Clifton <nickc@redhat.com> * ld-pe/longsecn-1.d: Allow for extra sections. diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index 4c0f802..ec569ca 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -1,5 +1,5 @@ # Expect script for various ARM ELF tests. -# Copyright 2002-2013 Free Software Foundation, Inc. +# Copyright 2002-2014 Free Software Foundation, Inc. # # This file is part of the GNU Binutils. # @@ -188,6 +188,10 @@ set armelftests_common { "" {exec-got-1b.s} {{readelf --relocs exec-got-1.d}} "exec-got-1"} + {"Long PLT entries in executables" "--long-plt -shared --section-start=.plt=0x200 --section-start=.got=0xf0000300" "" + "" {long-plt-format.s} + {{objdump "-d -j .plt" long-plt-format.d}} + "long-plt-format"} {"abs call" "-T arm.ld" "" "" {abs-call-1.s} {{objdump -d abs-call-1.d}} "abs-call-1"} diff --git a/ld/testsuite/ld-arm/long-plt-format.d b/ld/testsuite/ld-arm/long-plt-format.d new file mode 100644 index 0000000..c08cb71 --- /dev/null +++ b/ld/testsuite/ld-arm/long-plt-format.d @@ -0,0 +1,15 @@ +.*: file format elf32-.* + + +Disassembly of section .plt: + +00000200 <.plt>: + 200: .* + 204: .* + 208: .* + 20c: .* + 210: .* .word .* + 214: .* add ip, pc, #-268435456 ; 0xf0000000 + 218: .* add ip, ip, #0, 12 + 21c: .* add ip, ip, #0, 20 + 220: .* ldr pc, [ip, #[0-9]*]! ; 0x.* diff --git a/ld/testsuite/ld-arm/long-plt-format.s b/ld/testsuite/ld-arm/long-plt-format.s new file mode 100644 index 0000000..bb0c3a2 --- /dev/null +++ b/ld/testsuite/ld-arm/long-plt-format.s @@ -0,0 +1,7 @@ + .globl _start + .type _start,%function + .globl foo +_start: + bl foo(PLT) + .size _start,.-_start + |