This patch adds support for ARM PLT entries that support a full 32-bit offset range.
authorYuri Gribov <y.gribov@samsung.com>
Thu, 27 Feb 2014 14:35:37 +0000 (14:35 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 27 Feb 2014 14:35:37 +0000 (14:35 +0000)
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.

bfd/ChangeLog
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/elf32-arm.c
ld/ChangeLog
ld/emultempl/armelf.em
ld/ld.texinfo
ld/testsuite/ChangeLog
ld/testsuite/ld-arm/arm-elf.exp
ld/testsuite/ld-arm/long-plt-format.d [new file with mode: 0644]
ld/testsuite/ld-arm/long-plt-format.s [new file with mode: 0644]

index 069a6ce..472bc89 100644 (file)
@@ -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
index c7c5a7d..54ddac9 100644 (file)
@@ -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
index 33792f4..ebc7496 100644 (file)
@@ -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
index 7216244..b17f4d4 100644 (file)
@@ -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.  */
index a0c5284..57120d1 100644 (file)
@@ -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
index 85e924f..6a64793 100644 (file)
@@ -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
index b1dff79..eb0b991 100644 (file)
@@ -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
index 1af8109..84ca6b1 100644 (file)
@@ -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.
index 4c0f802..ec569ca 100644 (file)
@@ -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 (file)
index 0000000..c08cb71
--- /dev/null
@@ -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 (file)
index 0000000..bb0c3a2
--- /dev/null
@@ -0,0 +1,7 @@
+       .globl  _start
+       .type   _start,%function
+       .globl foo
+_start:
+       bl foo(PLT)
+       .size   _start,.-_start
+