Check ELF relocs after opening all input files
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 20 Apr 2016 12:26:37 +0000 (05:26 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 20 Apr 2016 12:26:51 +0000 (05:26 -0700)
Delaying checking ELF relocations until opening all input files so
that symbol information is final when relocations are checked.  This
is only enabled for x86 targets.

bfd/

* elf-bfd.h (_bfd_elf_link_check_relocs): New.
* elflink.c (_bfd_elf_link_check_relocs): New function.
(elf_link_add_object_symbols): Call _bfd_elf_link_check_relocs
if check_relocs_after_open_input is FALSE.

include/

* bfdlink.h (bfd_link_info): Add check_relocs_after_open_input.

ld/

* emulparams/elf32_x86_64.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
New.
* emulparams/elf_i386.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
Likewise.
* emulparams/elf_i386_be.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
Likewise.
* emulparams/elf_i386_chaos.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
Likewise.
* emulparams/elf_i386_ldso.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
Likewise.
* emulparams/elf_i386_vxworks.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
Likewise.
* emulparams/elf_x86_64.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
Likewise.
* emulparams/i386nto.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
Likewise.
* emultempl/elf32.em (gld${EMULATION_NAME}_before_parse):
Set check_relocs_after_open_input to TRUE if
CHECK_RELOCS_AFTER_OPEN_INPUT is yes.
(gld${EMULATION_NAME}_after_open): Call
_bfd_elf_link_check_relocs on all inputs if
check_relocs_after_open_input is TRUE.

15 files changed:
bfd/ChangeLog
bfd/elf-bfd.h
bfd/elflink.c
include/ChangeLog
include/bfdlink.h
ld/ChangeLog
ld/emulparams/elf32_x86_64.sh
ld/emulparams/elf_i386.sh
ld/emulparams/elf_i386_be.sh
ld/emulparams/elf_i386_chaos.sh
ld/emulparams/elf_i386_ldso.sh
ld/emulparams/elf_i386_vxworks.sh
ld/emulparams/elf_x86_64.sh
ld/emulparams/i386nto.sh
ld/emultempl/elf32.em

index f4bebd9d28d0c4b8be6d38fa1c48ce5761908ebf..a0304b682a2f4d847e8c2b5dd14d437cd6e31059 100644 (file)
@@ -1,3 +1,10 @@
+2016-04-20  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * elf-bfd.h (_bfd_elf_link_check_relocs): New.
+       * elflink.c (_bfd_elf_link_check_relocs): New function.
+       (elf_link_add_object_symbols): Call _bfd_elf_link_check_relocs
+       if check_relocs_after_open_input is FALSE.
+
 2016-04-20  Trevor Saunders  <tbsaunde+binutils@tbsaunde.org>
 
        * cache.c: Update old style function definitions.
index 5c93d78c394ec29dd479c1db8c23675315e06b7a..5dce70e93d5e74385b93a091b6d08f798a9080bf 100644 (file)
@@ -2261,6 +2261,8 @@ extern bfd_boolean bfd_elf_link_add_symbols
   (bfd *, struct bfd_link_info *);
 extern bfd_boolean _bfd_elf_add_dynamic_entry
   (struct bfd_link_info *, bfd_vma, bfd_vma);
+extern bfd_boolean _bfd_elf_link_check_relocs
+  (bfd *, struct bfd_link_info *);
 
 extern bfd_boolean bfd_elf_link_record_dynamic_symbol
   (struct bfd_link_info *, struct elf_link_hash_entry *);
index 37638b2f2c88134ace1abe4bf0ce30f835623dae..5af334ad172f3b2098dd814f7de6ccc834332a10 100644 (file)
@@ -3480,6 +3480,69 @@ _bfd_elf_notice_as_needed (bfd *ibfd,
   return (*info->callbacks->notice) (info, NULL, NULL, ibfd, NULL, act, 0);
 }
 
+/* Check relocations an ELF object file.  */
+
+bfd_boolean
+_bfd_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
+{
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  struct elf_link_hash_table *htab = elf_hash_table (info);
+
+  /* If this object is the same format as the output object, and it is
+     not a shared library, then let the backend look through the
+     relocs.
+
+     This is required to build global offset table entries and to
+     arrange for dynamic relocs.  It is not required for the
+     particular common case of linking non PIC code, even when linking
+     against shared libraries, but unfortunately there is no way of
+     knowing whether an object file has been compiled PIC or not.
+     Looking through the relocs is not particularly time consuming.
+     The problem is that we must either (1) keep the relocs in memory,
+     which causes the linker to require additional runtime memory or
+     (2) read the relocs twice from the input file, which wastes time.
+     This would be a good case for using mmap.
+
+     I have no idea how to handle linking PIC code into a file of a
+     different format.  It probably can't be done.  */
+  if ((abfd->flags & DYNAMIC) == 0
+      && is_elf_hash_table (htab)
+      && bed->check_relocs != NULL
+      && elf_object_id (abfd) == elf_hash_table_id (htab)
+      && (*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
+    {
+      asection *o;
+
+      for (o = abfd->sections; o != NULL; o = o->next)
+       {
+         Elf_Internal_Rela *internal_relocs;
+         bfd_boolean ok;
+
+         if ((o->flags & SEC_RELOC) == 0
+             || o->reloc_count == 0
+             || ((info->strip == strip_all || info->strip == strip_debugger)
+                 && (o->flags & SEC_DEBUGGING) != 0)
+             || bfd_is_abs_section (o->output_section))
+           continue;
+
+         internal_relocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
+                                                      info->keep_memory);
+         if (internal_relocs == NULL)
+           return FALSE;
+
+         ok = (*bed->check_relocs) (abfd, info, o, internal_relocs);
+
+         if (elf_section_data (o)->relocs != internal_relocs)
+           free (internal_relocs);
+
+         if (! ok)
+           return FALSE;
+       }
+    }
+
+  return TRUE;
+}
+
 /* Add symbols from an ELF object file to the linker hash table.  */
 
 static bfd_boolean
@@ -4950,57 +5013,9 @@ error_free_dyn:
       && !(*bed->check_directives) (abfd, info))
     return FALSE;
 
-  /* If this object is the same format as the output object, and it is
-     not a shared library, then let the backend look through the
-     relocs.
-
-     This is required to build global offset table entries and to
-     arrange for dynamic relocs.  It is not required for the
-     particular common case of linking non PIC code, even when linking
-     against shared libraries, but unfortunately there is no way of
-     knowing whether an object file has been compiled PIC or not.
-     Looking through the relocs is not particularly time consuming.
-     The problem is that we must either (1) keep the relocs in memory,
-     which causes the linker to require additional runtime memory or
-     (2) read the relocs twice from the input file, which wastes time.
-     This would be a good case for using mmap.
-
-     I have no idea how to handle linking PIC code into a file of a
-     different format.  It probably can't be done.  */
-  if (! dynamic
-      && is_elf_hash_table (htab)
-      && bed->check_relocs != NULL
-      && elf_object_id (abfd) == elf_hash_table_id (htab)
-      && (*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
-    {
-      asection *o;
-
-      for (o = abfd->sections; o != NULL; o = o->next)
-       {
-         Elf_Internal_Rela *internal_relocs;
-         bfd_boolean ok;
-
-         if ((o->flags & SEC_RELOC) == 0
-             || o->reloc_count == 0
-             || ((info->strip == strip_all || info->strip == strip_debugger)
-                 && (o->flags & SEC_DEBUGGING) != 0)
-             || bfd_is_abs_section (o->output_section))
-           continue;
-
-         internal_relocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
-                                                      info->keep_memory);
-         if (internal_relocs == NULL)
-           goto error_return;
-
-         ok = (*bed->check_relocs) (abfd, info, o, internal_relocs);
-
-         if (elf_section_data (o)->relocs != internal_relocs)
-           free (internal_relocs);
-
-         if (! ok)
-           goto error_return;
-       }
-    }
+  if (!info->check_relocs_after_open_input
+      && !_bfd_elf_link_check_relocs (abfd, info))
+    return FALSE;
 
   /* If this is a non-traditional link, try to optimize the handling
      of the .stab/.stabstr sections.  */
index c4bc144675f089b51b5732bf95a52ceb355b6530..a419ef227930e7779c92be0824c3ba16bb218f14 100644 (file)
@@ -1,3 +1,7 @@
+2016-04-20  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * bfdlink.h (bfd_link_info): Add check_relocs_after_open_input.
+
 2016-04-20  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * elf/arc-reloc.def (ARC_NPS_CMEM16): Add ME modifier to formula.
index a285f6dc5e2d9844844e2a877454bdcfbba23201..90467b54edc46f6d27241e2aba921a253bff7aae 100644 (file)
@@ -440,6 +440,10 @@ struct bfd_link_info
   /* TRUE if the linker script contained an explicit PHDRS command.  */
   unsigned int user_phdrs: 1;
 
+  /* TRUE if we should check relocations after all input files have
+     been opened.  */
+  unsigned int check_relocs_after_open_input: 1;
+
   /* TRUE if BND prefix in PLT entries is always generated.  */
   unsigned int bndplt: 1;
 
index c1dc58948c0aa3be733f68fd6d57e8c0f972e4a7..ac908e5239259d3f25cef1419e48cefe9f6e0487 100644 (file)
@@ -1,3 +1,28 @@
+2016-04-20  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * emulparams/elf32_x86_64.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
+       New.
+       * emulparams/elf_i386.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
+       Likewise.
+       * emulparams/elf_i386_be.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
+       Likewise.
+       * emulparams/elf_i386_chaos.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
+       Likewise.
+       * emulparams/elf_i386_ldso.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
+       Likewise.
+       * emulparams/elf_i386_vxworks.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
+       Likewise.
+       * emulparams/elf_x86_64.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
+       Likewise.
+       * emulparams/i386nto.sh (CHECK_RELOCS_AFTER_OPEN_INPUT):
+       Likewise.
+       * emultempl/elf32.em (gld${EMULATION_NAME}_before_parse):
+       Set check_relocs_after_open_input to TRUE if
+       CHECK_RELOCS_AFTER_OPEN_INPUT is yes.
+       (gld${EMULATION_NAME}_after_open): Call
+       _bfd_elf_link_check_relocs on all inputs if
+       check_relocs_after_open_input is TRUE.
+
 2016-04-20  H.J. Lu  <hongjiu.lu@intel.com>
 
        * testsuite/ld-elf/eh6.s: Replace .long with .dc.a on
index 967c1b45cd0076f33cedd6fbf2baebfc2da3fd88..9050730834f4b484e2d1b472cb27a1d71461d484 100644 (file)
@@ -6,6 +6,7 @@
 SCRIPT_NAME=elf
 ELFSIZE=32
 OUTPUT_FORMAT="elf32-x86-64"
+CHECK_RELOCS_AFTER_OPEN_INPUT=yes
 NO_REL_RELOCS=yes
 TEXT_START_ADDR=0x400000
 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
index 3451bb2b1ea7a20c146ba8facb8262458f558387..b08e6610d0bc222fd0513ab31384e4cb6353f0d6 100644 (file)
@@ -4,6 +4,7 @@
 . ${srcdir}/emulparams/call_nop.sh
 SCRIPT_NAME=elf
 OUTPUT_FORMAT="elf32-i386"
+CHECK_RELOCS_AFTER_OPEN_INPUT=yes
 NO_RELA_RELOCS=yes
 TEXT_START_ADDR=0x08048000
 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
index 70db443239597eeef9575777104c4572bfbc4f64..4a24b020123731b48e475e80aa68bd74c930b5bb 100644 (file)
@@ -3,6 +3,7 @@
 . ${srcdir}/emulparams/call_nop.sh
 SCRIPT_NAME=elf
 OUTPUT_FORMAT="elf32-i386"
+CHECK_RELOCS_AFTER_OPEN_INPUT=yes
 NO_RELA_RELOCS=yes
 TEXT_START_ADDR=0x80000000
 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
index aa36cb51c2d38962df88bf87b66fa15bac5b6d1a..534910817441134d3c73681d9c027071d998ee1a 100644 (file)
@@ -4,6 +4,7 @@
 . ${srcdir}/emulparams/call_nop.sh
 SCRIPT_NAME=elf_chaos
 OUTPUT_FORMAT="elf32-i386"
+CHECK_RELOCS_AFTER_OPEN_INPUT=yes
 TEXT_START_ADDR=0x40000000
 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
 ARCH=i386
index 1328520c57cfc5828cde151abd78efeab994ea40..dc4eef48896c3f77fdac49cc5a51315595106777 100644 (file)
@@ -4,6 +4,7 @@
 . ${srcdir}/emulparams/call_nop.sh
 SCRIPT_NAME=elf
 OUTPUT_FORMAT="elf32-i386"
+CHECK_RELOCS_AFTER_OPEN_INPUT=yes
 NO_RELA_RELOCS=yes
 TEXT_START_ADDR=0x08048000
 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
index aaea8c48743438ca8c5eac2999755532b91e66fc..ac1bbeb4e342fcacb027ad4d613652e1c6ab64e9 100644 (file)
@@ -1,5 +1,6 @@
 SCRIPT_NAME=elf
 OUTPUT_FORMAT="elf32-i386-vxworks"
+CHECK_RELOCS_AFTER_OPEN_INPUT=yes
 NO_RELA_RELOCS=yes
 TEXT_START_ADDR=0x08048000
 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
index e935f90d7e630d741dae04bd4820a603558e4021..6055204874e298bdd13dfc7d60c7858542977c20 100644 (file)
@@ -6,6 +6,7 @@
 SCRIPT_NAME=elf
 ELFSIZE=64
 OUTPUT_FORMAT="elf64-x86-64"
+CHECK_RELOCS_AFTER_OPEN_INPUT=yes
 NO_REL_RELOCS=yes
 TEXT_START_ADDR=0x400000
 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
index 626f9c13aa156766289c3db9c84799514138275e..51284be2bd43ec0e6d8d98a8743e06167b6f7d68 100644 (file)
@@ -1,5 +1,6 @@
 SCRIPT_NAME=elf
 OUTPUT_FORMAT="elf32-i386"
+CHECK_RELOCS_AFTER_OPEN_INPUT=yes
 NO_RELA_RELOCS=yes
 TEXT_START_ADDR=0x08048000
 TEXT_START_SYMBOLS='_btext = .;'
index 3e9f684985b8080677092753437a453e6f12dfc8..312f935e6a12b1741e0c541b6901b0acbadd2d19 100644 (file)
@@ -104,6 +104,7 @@ gld${EMULATION_NAME}_before_parse (void)
   config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
   config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;
   `if test -n "$CALL_NOP_BYTE" ; then echo link_info.call_nop_byte = $CALL_NOP_BYTE; fi`;
+  link_info.check_relocs_after_open_input = `if test "x${CHECK_RELOCS_AFTER_OPEN_INPUT}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;
 }
 
 EOF
@@ -1025,6 +1026,20 @@ gld${EMULATION_NAME}_after_open (void)
   if (!is_elf_hash_table (htab))
     return;
 
+  if (link_info.check_relocs_after_open_input)
+    {
+      bfd *abfd;
+
+      for (abfd = link_info.input_bfds;
+          abfd != (bfd *) NULL; abfd = abfd->link.next)
+       if (!_bfd_elf_link_check_relocs (abfd, &link_info))
+         {
+           /* no object output, fail return */
+           config.make_executable = FALSE;
+           return;
+         }
+    }
+
   if (emit_note_gnu_build_id != NULL)
     {
       bfd *abfd;