[binutils] backport fix from HEAD that fixes LTO + ifunc when using ld.bfd instead of gold

Kyle McMartin kyle at fedoraproject.org
Tue Aug 26 18:55:33 UTC 2014


commit d7c31854e82903e663df160ad4c26c938eca4b59
Author: Kyle McMartin <kyle at mcmartin.ca>
Date:   Tue Aug 26 10:45:37 2014 -0400

    backport fix from HEAD that fixes LTO + ifunc when using ld.bfd instead of gold
    
    also increase ELF_COMMON_PAGESIZE to 64K on aarch64 a la ppc64

 binutils-HEAD-change-ld-notice-interface.patch |  398 ++++++++++++++++++++++++
 binutils.spec                                  |   10 +-
 2 files changed, 406 insertions(+), 2 deletions(-)
---
diff --git a/binutils-HEAD-change-ld-notice-interface.patch b/binutils-HEAD-change-ld-notice-interface.patch
new file mode 100644
index 0000000..db2ea9b
--- /dev/null
+++ b/binutils-HEAD-change-ld-notice-interface.patch
@@ -0,0 +1,398 @@
+From 4613510308cea27713e8c7424b2afee9b99f6226 Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra at gmail.com>
+Date: Tue, 12 Aug 2014 10:43:33 +0930
+Subject: [PATCH] Change ld "notice" interface for better handling of
+ indirect symbols
+
+The main aim of this change was to have non_ir_ref set correctly on
+new indirect symbols.  I could have added a "copy" param to the "notice"
+function, so that indirect symbols could be created in plugin_notice,
+but it seemed cleaner to create indirect syms earlier and pass them
+rather than "string" to "notice".
+
+include/
+	* bfdlink.h (struct bfd_link_callbacks <notice>): Remove "string"
+	param, add "inh".
+bfd/
+	* coff-aux.c (coff_m68k_aux_link_add_one_symbol): Only call "notice"
+	here when not calling the generic add_symbol function.  Formatting.
+	Correct handling of indirect symbols.  Update notice call.
+	* elflink.c (_bfd_elf_notice_as_needed): Update notice call.
+	* linker.c (_bfd_generic_link_add_one_symbol): Create indirect
+	symbols early.  Update notice call.  Add comments regarding weak
+	symbols vs. indirect.
+ld/
+	* ldmain.c (notice): Update args.
+	* plugin.c (plugin_notice): Likewise.  Follow warning sym link.
+	Handle new indirect symbol.
+---
+ bfd/coff-aux.c    | 62 ++++++++++++++++++++++-------------------
+ bfd/elflink.c     |  2 +-
+ bfd/linker.c      | 82 +++++++++++++++++++++++++++++--------------------------
+ include/bfdlink.h | 13 ++++-----
+ ld/ldmain.c       |  6 ++--
+ ld/plugin.c       | 33 ++++++++++++----------
+ 9 files changed, 128 insertions(+), 91 deletions(-)
+
+diff --git a/bfd/coff-aux.c b/bfd/coff-aux.c
+index e79c77a..d95b98b 100644
+--- a/bfd/coff-aux.c
++++ b/bfd/coff-aux.c
+@@ -73,20 +73,17 @@ coff_m68k_aux_link_add_one_symbol (struct bfd_link_info *info,
+ 				   bfd_boolean collect,
+ 				   struct bfd_link_hash_entry **hashp)
+ {
+-  struct bfd_link_hash_entry *h;
++  struct bfd_link_hash_entry *h, *inh, *t;
+ 
+-  if ((flags & (BSF_WARNING | BSF_CONSTRUCTOR | BSF_WEAK)) == 0 &&
+-      !bfd_is_und_section (section) &&
+-      !bfd_is_com_section (section))
++  if ((flags & (BSF_WARNING | BSF_CONSTRUCTOR | BSF_WEAK)) == 0
++      && !bfd_is_und_section (section)
++      && !bfd_is_com_section (section))
+     {
+       /* The new symbol is a definition or an indirect definition */
+ 
+       /* This bit copied from linker.c */
+       if (hashp != NULL && *hashp != NULL)
+-	{
+-	  h = *hashp;
+-	  BFD_ASSERT (strcmp (h->root.string, name) == 0);
+-	}
++	h = *hashp;
+       else
+ 	{
+ 	  h = bfd_link_hash_lookup (info->hash, name, TRUE, copy, FALSE);
+@@ -98,37 +95,46 @@ coff_m68k_aux_link_add_one_symbol (struct bfd_link_info *info,
+ 	    }
+ 	}
+ 
+-      if (info->notice_hash != (struct bfd_hash_table *) NULL
+-	  && (bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE)
+-	      != (struct bfd_hash_entry *) NULL))
+-	{
+-	  if (! (*info->callbacks->notice) (info, h, abfd, section, value,
+-					    flags, string))
+-	    return FALSE;
+-	}
+-
+       if (hashp != (struct bfd_link_hash_entry **) NULL)
+ 	*hashp = h;
+       /* end duplication from linker.c */
+ 
+-      if (h->type == bfd_link_hash_defined
+-	  || h->type == bfd_link_hash_indirect)
++      t = h;
++      inh = NULL;
++      if (h->type == bfd_link_hash_indirect)
+ 	{
+-	  asection *msec;
++	  inh = h->u.i.link;
++	  t = inh;
++	}
+ 
+-	  if (h->type == bfd_link_hash_defined)
+-	    msec = h->u.def.section;
+-	  else
+-	    msec = bfd_ind_section_ptr;
++      if (t->type == bfd_link_hash_defined)
++	{
++	  asection *msec = t->u.def.section;
++	  bfd_boolean special = FALSE;
+ 
+ 	  if (bfd_is_abs_section (msec) && !bfd_is_abs_section (section))
+ 	    {
+-	      h->u.def.section = section;
+-	      h->u.def.value = value;
+-	      return TRUE;
++	      t->u.def.section = section;
++	      t->u.def.value = value;
++	      special = TRUE;
+ 	    }
+ 	  else if (bfd_is_abs_section (section) && !bfd_is_abs_section (msec))
+-	    return TRUE;
++	    special = TRUE;
++
++	  if (special)
++	    {
++	      if (info->notice_all
++		  || (info->notice_hash != NULL
++		      && bfd_hash_lookup (info->notice_hash, name,
++					  FALSE, FALSE) != NULL))
++		{
++		  if (!(*info->callbacks->notice) (info, h, inh,
++						   abfd, section, value, flags))
++		    return FALSE;
++		}
++
++	      return TRUE;
++	    }
+ 	}
+     }
+ 
+diff --git a/bfd/elflink.c b/bfd/elflink.c
+index 69a87a6..de0a734 100644
+--- a/bfd/elflink.c
++++ b/bfd/elflink.c
+@@ -3299,7 +3299,7 @@ _bfd_elf_notice_as_needed (bfd *ibfd,
+ 			   struct bfd_link_info *info,
+ 			   enum notice_asneeded_action act)
+ {
+-  return (*info->callbacks->notice) (info, NULL, ibfd, NULL, act, 0, NULL);
++  return (*info->callbacks->notice) (info, NULL, NULL, ibfd, NULL, act, 0);
+ }
+ 
+ /* Add symbols from an ELF object file to the linker hash table.  */
+diff --git a/bfd/linker.c b/bfd/linker.c
+index 1a5ecef..abdf5b0 100644
+--- a/bfd/linker.c
++++ b/bfd/linker.c
+@@ -1442,13 +1442,23 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
+ {
+   enum link_row row;
+   struct bfd_link_hash_entry *h;
++  struct bfd_link_hash_entry *inh = NULL;
+   bfd_boolean cycle;
+ 
+   BFD_ASSERT (section != NULL);
+ 
+   if (bfd_is_ind_section (section)
+       || (flags & BSF_INDIRECT) != 0)
+-    row = INDR_ROW;
++    {
++      row = INDR_ROW;
++      /* Create the indirect symbol here.  This is for the benefit of
++	 the plugin "notice" function.
++	 STRING is the name of the symbol we want to indirect to.  */
++      inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE,
++					  copy, FALSE);
++      if (inh == NULL)
++	return FALSE;
++    }
+   else if ((flags & BSF_WARNING) != 0)
+     row = WARN_ROW;
+   else if ((flags & BSF_CONSTRUCTOR) != 0)
+@@ -1493,8 +1503,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
+       || (info->notice_hash != NULL
+ 	  && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
+     {
+-      if (! (*info->callbacks->notice) (info, h,
+-					abfd, section, value, flags, string))
++      if (! (*info->callbacks->notice) (info, h, inh,
++					abfd, section, value, flags))
+ 	return FALSE;
+     }
+ 
+@@ -1728,44 +1738,40 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
+ 	    return FALSE;
+ 	  /* Fall through.  */
+ 	case IND:
+-	  /* Create an indirect symbol.  */
+-	  {
+-	    struct bfd_link_hash_entry *inh;
+-
+-	    /* STRING is the name of the symbol we want to indirect
+-	       to.  */
+-	    inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE,
+-						copy, FALSE);
+-	    if (inh == NULL)
++	  if (inh->type == bfd_link_hash_indirect
++	      && inh->u.i.link == h)
++	    {
++	      (*_bfd_error_handler)
++		(_("%B: indirect symbol `%s' to `%s' is a loop"),
++		 abfd, name, string);
++	      bfd_set_error (bfd_error_invalid_operation);
+ 	      return FALSE;
+-	    if (inh->type == bfd_link_hash_indirect
+-		&& inh->u.i.link == h)
+-	      {
+-		(*_bfd_error_handler)
+-		  (_("%B: indirect symbol `%s' to `%s' is a loop"),
+-		   abfd, name, string);
+-		bfd_set_error (bfd_error_invalid_operation);
+-		return FALSE;
+-	      }
+-	    if (inh->type == bfd_link_hash_new)
+-	      {
+-		inh->type = bfd_link_hash_undefined;
+-		inh->u.undef.abfd = abfd;
+-		bfd_link_add_undef (info->hash, inh);
+-	      }
++	    }
++	  if (inh->type == bfd_link_hash_new)
++	    {
++	      inh->type = bfd_link_hash_undefined;
++	      inh->u.undef.abfd = abfd;
++	      bfd_link_add_undef (info->hash, inh);
++	    }
+ 
+-	    /* If the indirect symbol has been referenced, we need to
+-	       push the reference down to the symbol we are
+-	       referencing.  */
+-	    if (h->type != bfd_link_hash_new)
+-	      {
+-		row = UNDEF_ROW;
+-		cycle = TRUE;
+-	      }
++	  /* If the indirect symbol has been referenced, we need to
++	     push the reference down to the symbol we are referencing.  */
++	  if (h->type != bfd_link_hash_new)
++	    {
++	      /* ??? If inh->type == bfd_link_hash_undefweak this
++		 converts inh to bfd_link_hash_undefined.  */
++	      row = UNDEF_ROW;
++	      cycle = TRUE;
++	    }
+ 
+-	    h->type = bfd_link_hash_indirect;
+-	    h->u.i.link = inh;
+-	  }
++	  h->type = bfd_link_hash_indirect;
++	  h->u.i.link = inh;
++	  /* Not setting h = h->u.i.link here means that when cycle is
++	     set above we'll always go to REFC, and then cycle again
++	     to the indirected symbol.  This means that any successful
++	     change of an existing symbol to indirect counts as a
++	     reference.  ??? That may not be correct when the existing
++	     symbol was defweak.  */
+ 	  break;
+ 
+ 	case SET:
+diff --git a/include/bfdlink.h b/include/bfdlink.h
+index 58dba2a..125683d 100644
+--- a/include/bfdlink.h
++++ b/include/bfdlink.h
+@@ -640,15 +640,14 @@ struct bfd_link_callbacks
+     (struct bfd_link_info *, const char *name,
+      bfd *abfd, asection *section, bfd_vma address);
+   /* A function which is called when a symbol in notice_hash is
+-     defined or referenced.  H is the symbol.  ABFD, SECTION and
+-     ADDRESS are the (new) value of the symbol.  If SECTION is
+-     bfd_und_section, this is a reference.  FLAGS are the symbol
+-     BSF_* flags.  STRING is the name of the symbol to indirect to if
+-     the sym is indirect, or the warning string if a warning sym.  */
++     defined or referenced.  H is the symbol, INH the indirect symbol
++     if applicable.  ABFD, SECTION and ADDRESS are the (new) value of
++     the symbol.  If SECTION is bfd_und_section, this is a reference.
++     FLAGS are the symbol BSF_* flags.  */
+   bfd_boolean (*notice)
+     (struct bfd_link_info *, struct bfd_link_hash_entry *h,
+-     bfd *abfd, asection *section, bfd_vma address, flagword flags,
+-     const char *string);
++     struct bfd_link_hash_entry *inh,
++     bfd *abfd, asection *section, bfd_vma address, flagword flags);
+   /* Error or warning link info message.  */
+   void (*einfo)
+     (const char *fmt, ...);
+diff --git a/ld/ldmain.c b/ld/ldmain.c
+index ea25afe..77235d5 100644
+--- a/ld/ldmain.c
++++ b/ld/ldmain.c
+@@ -137,7 +137,7 @@ static bfd_boolean unattached_reloc
+   (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
+ static bfd_boolean notice
+   (struct bfd_link_info *, struct bfd_link_hash_entry *,
+-   bfd *, asection *, bfd_vma, flagword, const char *);
++   struct bfd_link_hash_entry *, bfd *, asection *, bfd_vma, flagword);
+ 
+ static struct bfd_link_callbacks link_callbacks =
+ {
+@@ -1461,11 +1461,11 @@ unattached_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ static bfd_boolean
+ notice (struct bfd_link_info *info,
+ 	struct bfd_link_hash_entry *h,
++	struct bfd_link_hash_entry *inh ATTRIBUTE_UNUSED,
+ 	bfd *abfd,
+ 	asection *section,
+ 	bfd_vma value,
+-	flagword flags ATTRIBUTE_UNUSED,
+-	const char *string ATTRIBUTE_UNUSED)
++	flagword flags ATTRIBUTE_UNUSED)
+ {
+   const char *name;
+ 
+diff --git a/ld/plugin.c b/ld/plugin.c
+index 8d6ae05..8cca7d0 100644
+--- a/ld/plugin.c
++++ b/ld/plugin.c
+@@ -127,8 +127,9 @@ static const size_t tv_header_size = ARRAY_SIZE (tv_header_tags);
+ 
+ /* Forward references.  */
+ static bfd_boolean plugin_notice (struct bfd_link_info *,
+-				  struct bfd_link_hash_entry *, bfd *,
+-				  asection *, bfd_vma, flagword, const char *);
++				  struct bfd_link_hash_entry *,
++				  struct bfd_link_hash_entry *,
++				  bfd *, asection *, bfd_vma, flagword);
+ 
+ #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
+ 
+@@ -962,16 +963,21 @@ plugin_call_cleanup (void)
+ static bfd_boolean
+ plugin_notice (struct bfd_link_info *info,
+ 	       struct bfd_link_hash_entry *h,
++	       struct bfd_link_hash_entry *inh,
+ 	       bfd *abfd,
+ 	       asection *section,
+ 	       bfd_vma value,
+-	       flagword flags,
+-	       const char *string)
++	       flagword flags)
+ {
++  struct bfd_link_hash_entry *orig_h = h;
++
+   if (h != NULL)
+     {
+       bfd *sym_bfd;
+ 
++      if (h->type == bfd_link_hash_warning)
++	h = h->u.i.link;
++
+       /* Nothing to do here if this def/ref is from an IR dummy BFD.  */
+       if (is_ir_dummy_bfd (abfd))
+ 	;
+@@ -981,16 +987,15 @@ plugin_notice (struct bfd_link_info *info,
+       else if (bfd_is_ind_section (section)
+ 	       || (flags & BSF_INDIRECT) != 0)
+ 	{
++	  /* ??? Some of this is questionable.  See comments in
++	     _bfd_generic_link_add_one_symbol for case IND.  */
+ 	  if (h->type != bfd_link_hash_new)
+ 	    {
+-	      struct bfd_link_hash_entry *inh;
+-
+ 	      h->non_ir_ref = TRUE;
+-	      inh = bfd_wrapped_link_hash_lookup (abfd, info, string, FALSE,
+-						  FALSE, FALSE);
+-	      if (inh != NULL)
+-		inh->non_ir_ref = TRUE;
++	      inh->non_ir_ref = TRUE;
+ 	    }
++	  else if (inh->type == bfd_link_hash_new)
++	    inh->non_ir_ref = TRUE;
+ 	}
+ 
+       /* Nothing to do here for warning symbols.  */
+@@ -1031,13 +1036,13 @@ plugin_notice (struct bfd_link_info *info,
+     }
+ 
+   /* Continue with cref/nocrossref/trace-sym processing.  */
+-  if (h == NULL
++  if (orig_h == NULL
+       || orig_notice_all
+       || (info->notice_hash != NULL
+-	  && bfd_hash_lookup (info->notice_hash, h->root.string,
++	  && bfd_hash_lookup (info->notice_hash, orig_h->root.string,
+ 			      FALSE, FALSE) != NULL))
+-    return (*orig_callbacks->notice) (info, h,
+-				      abfd, section, value, flags, string);
++    return (*orig_callbacks->notice) (info, orig_h, inh,
++				      abfd, section, value, flags);
+   return TRUE;
+ }
+ 
+-- 
+1.9.3
+
diff --git a/binutils.spec b/binutils.spec
index 8d0305c..571adf4 100644
--- a/binutils.spec
+++ b/binutils.spec
@@ -71,6 +71,7 @@ Patch26: binutils-2.24-aarch64-fix-final_link_relocate.patch
 Patch27: binutils-2.24-aarch64-fix-gotplt-offset-ifunc.patch
 Patch28: binutils-2.24-aarch64-fix-static-ifunc.patch
 Patch29: binutils-2.24-aarch64-fix-ie-relax.patch
+Patch30: binutils-HEAD-change-ld-notice-interface.patch
 
 Provides: bundled(libiberty)
 
@@ -204,11 +205,13 @@ using libelf instead of BFD.
 %patch27 -p1 -b .aa64-1~
 %patch28 -p1 -b .aa64-2~
 %patch29 -p1 -b .aa64-3~
+%patch30 -p1 -b .ldplugin~
 
 # We cannot run autotools as there is an exact requirement of autoconf-2.59.
 
-# On ppc64 we might use 64KiB pages
+# On ppc64 and aarch64, we might use 64KiB pages
 sed -i -e '/#define.*ELF_COMMONPAGESIZE/s/0x1000$/0x10000/' bfd/elf*ppc.c
+sed -i -e '/#define.*ELF_COMMONPAGESIZE/s/0x1000$/0x10000/' bfd/elf*aarch64.c
 # LTP sucks
 perl -pi -e 's/i\[3-7\]86/i[34567]86/g' */conf*
 sed -i -e 's/%''{release}/%{release}/g' bfd/Makefile{.am,.in}
@@ -517,7 +520,10 @@ exit 0
 %endif # %{isnative}
 
 %changelog
-* Fri Aug 22 2014 Kyle McMartin <kmcmarti at redhat.com> - 2.24-23
+* Mon Aug 25 2014 Kyle McMartin <kmcmarti at redhat.com> - 2.24-23
+- aarch64: increase common page size to 64KB
+- binutils-HEAD-change-ld-notice-interface.patch: backport fix from HEAD
+  that fixes LTO + ifunc when using ld.bfd instead of gold.
 - binutils-2.24-aarch64-fix-gotplt-offset-ifunc.patch
   binutils-2.24-aarch64-fix-static-ifunc.patch, split elfnn-aarch64 patches
   into upstream git commits, to make it easier to figure out what's


More information about the scm-commits mailing list