This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC][PATCH] Check ELF relocs after opening all all input files


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.

Any comments, feedbacks?


H.J.
---
bfd/

	* elf-bfd.h (_bfd_elf_link_check_relocs): New.
	* elf32-i386.c (elf_i386_tls_transition): Use
	info->callbacks->einfo instead of _bfd_error_handler on
	error.
	* 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/

	* ldmisc.c (vfinfo): Add support for %x and %lx.
	* 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.
---
 bfd/elf-bfd.h                     |   2 +
 bfd/elf32-i386.c                  |  10 ++--
 bfd/elf64-x86-64.c                |   8 +--
 bfd/elflink.c                     | 117 +++++++++++++++++++++-----------------
 include/bfdlink.h                 |   4 ++
 ld/emulparams/elf32_x86_64.sh     |   1 +
 ld/emulparams/elf_i386.sh         |   1 +
 ld/emulparams/elf_i386_be.sh      |   1 +
 ld/emulparams/elf_i386_chaos.sh   |   1 +
 ld/emulparams/elf_i386_ldso.sh    |   1 +
 ld/emulparams/elf_i386_vxworks.sh |   1 +
 ld/emulparams/elf_x86_64.sh       |   1 +
 ld/emulparams/i386nto.sh          |   1 +
 ld/emultempl/elf32.em             |  11 ++++
 ld/ldmisc.c                       |  13 +++++
 15 files changed, 113 insertions(+), 60 deletions(-)

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 5c93d78..5dce70e 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -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 *);
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 470fcd1..d745a89 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1491,11 +1491,11 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
 	    }
 	}
 
-      (*_bfd_error_handler)
-	(_("%B: TLS transition from %s to %s against `%s' at 0x%lx "
-	   "in section `%A' failed"),
-	 abfd, sec, from->name, to->name, name,
-	 (unsigned long) rel->r_offset);
+      info->callbacks->einfo
+	(_("%B%X: TLS transition from %s to %s against `%s' at 0x%lx "
+	   "in section `%A' failed\n"),
+	 abfd, from->name, to->name, name,
+	 (unsigned long) rel->r_offset, sec);
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
     }
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 5533b4a..14dc3a1 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1572,11 +1572,11 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
 	    }
 	}
 
-      (*_bfd_error_handler)
-	(_("%B: TLS transition from %s to %s against `%s' at 0x%lx "
+      info->callbacks->einfo
+	(_("%B%X: TLS transition from %s to %s against `%s' at 0x%lx "
 	   "in section `%A' failed"),
-	 abfd, sec, from->name, to->name, name,
-	 (unsigned long) rel->r_offset);
+	 abfd, from->name, to->name, name,
+	 (unsigned long) rel->r_offset, sec);
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
     }
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 37638b2..5af334a 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -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.  */
diff --git a/include/bfdlink.h b/include/bfdlink.h
index a285f6d..90467b5 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -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;
 
diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh
index 967c1b4..9050730 100644
--- a/ld/emulparams/elf32_x86_64.sh
+++ b/ld/emulparams/elf32_x86_64.sh
@@ -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)"
diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh
index 3451bb2..b08e661 100644
--- a/ld/emulparams/elf_i386.sh
+++ b/ld/emulparams/elf_i386.sh
@@ -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)"
diff --git a/ld/emulparams/elf_i386_be.sh b/ld/emulparams/elf_i386_be.sh
index 70db443..4a24b02 100644
--- a/ld/emulparams/elf_i386_be.sh
+++ b/ld/emulparams/elf_i386_be.sh
@@ -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)"
diff --git a/ld/emulparams/elf_i386_chaos.sh b/ld/emulparams/elf_i386_chaos.sh
index aa36cb5..5349108 100644
--- a/ld/emulparams/elf_i386_chaos.sh
+++ b/ld/emulparams/elf_i386_chaos.sh
@@ -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
diff --git a/ld/emulparams/elf_i386_ldso.sh b/ld/emulparams/elf_i386_ldso.sh
index 1328520..dc4eef4 100644
--- a/ld/emulparams/elf_i386_ldso.sh
+++ b/ld/emulparams/elf_i386_ldso.sh
@@ -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)"
diff --git a/ld/emulparams/elf_i386_vxworks.sh b/ld/emulparams/elf_i386_vxworks.sh
index aaea8c4..ac1bbeb 100644
--- a/ld/emulparams/elf_i386_vxworks.sh
+++ b/ld/emulparams/elf_i386_vxworks.sh
@@ -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)"
diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh
index e935f90..6055204 100644
--- a/ld/emulparams/elf_x86_64.sh
+++ b/ld/emulparams/elf_x86_64.sh
@@ -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)"
diff --git a/ld/emulparams/i386nto.sh b/ld/emulparams/i386nto.sh
index 626f9c1..51284be 100644
--- a/ld/emulparams/i386nto.sh
+++ b/ld/emulparams/i386nto.sh
@@ -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 = .;'
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 3e9f684..1cfe65c 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -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,16 @@ 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))
+	  return;
+    }
+
   if (emit_note_gnu_build_id != NULL)
     {
       bfd *abfd;
diff --git a/ld/ldmisc.c b/ld/ldmisc.c
index 70e12ea..a744586 100644
--- a/ld/ldmisc.c
+++ b/ld/ldmisc.c
@@ -58,6 +58,8 @@
  %d integer, like printf
  %ld long, like printf
  %lu unsigned long, like printf
+ %x integer in hex, like printf
+ %lx long in hex, like printf
  %p native (host) void* pointer, like printf
  %s arbitrary string, like printf
  %u integer, like printf
@@ -409,6 +411,11 @@ vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
 	      fprintf (fp, "%u", va_arg (arg, unsigned int));
 	      break;
 
+	    case 'x':
+	      /* integer in hex, like printf */
+	      fprintf (fp, "%x", va_arg (arg, int));
+	      break;
+
 	    case 'l':
 	      if (*fmt == 'd')
 		{
@@ -422,6 +429,12 @@ vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
 		  ++fmt;
 		  break;
 		}
+	      else if (*fmt == 'x')
+		{
+		  fprintf (fp, "%lx", va_arg (arg, long));
+		  ++fmt;
+		  break;
+		}
 	      /* Fall thru */
 
 	    default:
-- 
2.5.5


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]