ifunc tidy

Alan Modra amodra@bigpond.net.au
Fri Jul 10 10:06:00 GMT 2009


This patch removes one ugly wart added with the ifunc support, the
setting of needs_plt in elf_link_add_object_symbols.  I reckon it
incorrect to set the flag there:  The mere presence of a symbol
shouldn't require a PLT entry (*).  Rather, it's the use of a symbol
by certain relocations that requires a PLT entry, so set needs_plt in
the backend check_relocs functions.

I also change the condition under which elf_link_output_extsym calls
the backend finish_dynamic_symbol routine for ifunc symbols.  It
doesn't seem correct to me to special case ref_regular.  Consider

defined		referenced
dynamic		regular			=> ifunc sym dynamic, plt
dynamic		!regular		=> ifunc sym not dynamic, no plt
regular		!regular, dynamic	=> ifunc sym dynamic, no plt
regular		!regular, !dynamic	=> ifunc sym not dynamic, no plt
regular		regular, dynamic	=> ifunc sym dynamic, plt
regular		regular, !dynamic	=> ifunc sym not dynamic, plt

I reckon all of these cases are the same for non-ifunc function
symbols, except the last two, which would be

regular		regular, dynamic	=> sym dynamic, no plt
regular		regular, !dynamic	=> sym not dynamic, no plt

Thus we really ought to be conditioning on def_regular && ref_regular
for ifunc syms, but ref_regular isn't always set when there are
regular references.  I see HJ sets ref_regular in the x86 and
x86_64 backends to make the flag valid, but I think it would be better
to not rely on this in the generic elf code.

*) I'll note that merely setting needs_plt in add_object_symbols
didn't result in a PLT entry, since the backends also require some
non-zero plt reference count.  Correct output doesn't make it
conceptually correct.

	* elf-bfd.h (struct elf_link_hash_entry): Clarify ref_regular
	and ref_regular_nonweak comment.
	* elflink.c (elf_link_output_extsym): Special case ifunc syms
	when def_regular, not ref_regular.
	(elf_link_add_object_symbols): Don't set needs_plt on ifunc syms,..
	* elf32-i386.c (elf_i386_check_relocs): ..set it here instead..
	* elf64-x86-64.c (elf64_x86_64_check_relocs): ..and here.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.290
diff -u -p -r1.290 elf-bfd.h
--- bfd/elf-bfd.h	18 Jun 2009 14:18:28 -0000	1.290
+++ bfd/elf-bfd.h	10 Jul 2009 08:08:16 -0000
@@ -138,7 +138,8 @@ struct elf_link_hash_entry
   /* Symbol st_other value, symbol visibility.  */
   unsigned int other : 8;
 
-  /* Symbol is referenced by a non-shared object.  */
+  /* Symbol is referenced by a non-shared object (other than the object
+     in which it is defined).  */
   unsigned int ref_regular : 1;
   /* Symbol is defined by a non-shared object.  */
   unsigned int def_regular : 1;
@@ -146,7 +147,8 @@ struct elf_link_hash_entry
   unsigned int ref_dynamic : 1;
   /* Symbol is defined by a shared object.  */
   unsigned int def_dynamic : 1;
-  /* Symbol has a non-weak reference from a non-shared object.  */
+  /* Symbol has a non-weak reference from a non-shared object (other than
+     the object in which it is defined).  */
   unsigned int ref_regular_nonweak : 1;
   /* Dynamic symbol has been adjustd.  */
   unsigned int dynamic_adjusted : 1;
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.345
diff -u -p -r1.345 elflink.c
--- bfd/elflink.c	20 Jun 2009 13:13:11 -0000	1.345
+++ bfd/elflink.c	10 Jul 2009 08:08:45 -0000
@@ -4290,10 +4290,6 @@ error_free_dyn:
 	      h->type = ELF_ST_TYPE (isym->st_info);
 	    }
 
-	  /* STT_GNU_IFUNC symbol must go through PLT.  */
-	  if (h->type == STT_GNU_IFUNC)
-	    h->needs_plt = 1;
-
 	  /* Merge st_other field.  */
 	  elf_merge_st_other (abfd, h, isym, definition, dynamic);
 
@@ -8657,7 +8653,7 @@ elf_link_output_extsym (struct elf_link_
      forced local syms when non-shared is due to a historical quirk.
      STT_GNU_IFUNC symbol must go through PLT.  */
   if ((h->type == STT_GNU_IFUNC
-       && h->ref_regular
+       && h->def_regular
        && !finfo->info->relocatable)
       || ((h->dynindx != -1
 	   || h->forced_local)
Index: bfd/elf32-i386.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-i386.c,v
retrieving revision 1.218
diff -u -p -r1.218 elf32-i386.c
--- bfd/elf32-i386.c	20 Jun 2009 00:43:21 -0000	1.218
+++ bfd/elf32-i386.c	10 Jul 2009 08:08:22 -0000
@@ -1366,6 +1366,7 @@ elf_i386_check_relocs (bfd *abfd,
 	    {
 	      /* It is referenced by a non-shared object. */
 	      h->ref_regular = 1;
+	      h->needs_plt = 1;
  
 	      /* STT_GNU_IFUNC symbol must go through PLT.  */
 	      h->plt.refcount += 1;
Index: bfd/elf64-x86-64.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-x86-64.c,v
retrieving revision 1.176
diff -u -p -r1.176 elf64-x86-64.c
--- bfd/elf64-x86-64.c	20 Jun 2009 00:43:21 -0000	1.176
+++ bfd/elf64-x86-64.c	10 Jul 2009 08:08:37 -0000
@@ -1150,6 +1150,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	    {
 	      /* It is referenced by a non-shared object. */
 	      h->ref_regular = 1;
+	      h->needs_plt = 1;
  
 	      /* STT_GNU_IFUNC symbol must go through PLT.  */
 	      h->plt.refcount += 1;

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list