[Committed]: S/390 Fix reloc handling for protected symbols

Andreas Krebbel krebbel@linux.vnet.ibm.com
Fri Mar 20 13:07:00 GMT 2009


Hello,

the attached patch fixes a problem with ld on s390x.  Consider the
following example:

void protsym (void) __attribute__((noinline,visibility("protected")));
void protsym (void)
{
  static count = 0;
  count++;
}
void callit (void) { protsym (); }

The problem is that elf_s390_relocate_section fails to resolve the
.text relocation for symbol protsym.  The symbol is protected and can
therefore not been overwritten.  So we don't need to go over the PLT
in this case.

readelf -r t.so

Relocation section '.rela.dyn' at offset 0x250 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
00000000027e  000200000013 R_390_PC32DBL     0000000000000268 protsym + 2

This is fixed with the attached patch.

I've committed the patch after testing succeeded on s390 and s390x.

Bye,

-Andreas-


2009-03-20  Martin Schwidefsky  <schwidefsky@de.ibm.com>
	    Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	* elf32-s390.c (elf_s390_check_relocs): Use the SYMBOL_*
        macros for visibilty and locality checks.
	(elf_s390_adjust_dynamic_symbol): Likewise.
	(allocate_dynrelocs): Likewise.
	(elf_s390_relocate_section): Likewise.
	(elf_s390_finish_dynamic_symbol): Likewise.
	* elf64-s390.c (elf_s390_check_relocs): Likewise.
	(elf_s390_adjust_dynamic_symbol): Likewise.
	(allocate_dynrelocs): Likewise.
	(elf_s390_relocate_section): Likewise.
	(elf_s390_finish_dynamic_symbol): Likewise.


Index: src/bfd/elf32-s390.c
===================================================================
--- src.orig/bfd/elf32-s390.c
+++ src/bfd/elf32-s390.c
@@ -1261,7 +1261,7 @@ elf_s390_check_relocs (abfd, info, sec, 
 		    && ELF32_R_TYPE (rel->r_info) != R_390_PC32DBL
 		    && ELF32_R_TYPE (rel->r_info) != R_390_PC32)
 		   || (h != NULL
-		       && (! info->symbolic
+		       && (! SYMBOLIC_BIND (info, h)
 			   || h->root.type == bfd_link_hash_defweak
 			   || !h->def_regular))))
 	      || (ELIMINATE_COPY_RELOCS
@@ -1566,11 +1566,9 @@ elf_s390_adjust_dynamic_symbol (info, h)
       || h->needs_plt)
     {
       if (h->plt.refcount <= 0
-	  || (! info->shared
-	      && !h->def_dynamic
-	      && !h->ref_dynamic
-	      && h->root.type != bfd_link_hash_undefweak
-	      && h->root.type != bfd_link_hash_undefined))
+	  || SYMBOL_CALLS_LOCAL (info, h)
+	  || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+	      && h->root.type != bfd_link_hash_undefweak))
 	{
 	  /* This case can occur if we saw a PLT32 reloc in an input
 	     file, but the symbol was never referred to by a dynamic
@@ -1709,9 +1707,7 @@ allocate_dynrelocs (h, inf)
   htab = elf_s390_hash_table (info);
 
   if (htab->elf.dynamic_sections_created
-      && h->plt.refcount > 0
-      && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-	  || h->root.type != bfd_link_hash_undefweak))
+      && h->plt.refcount > 0)
     {
       /* Make sure this symbol is output as a dynamic symbol.
 	 Undefined weak syms won't yet be marked as dynamic.  */
@@ -1840,7 +1836,7 @@ allocate_dynrelocs (h, inf)
 
   if (info->shared)
     {
-      if (SYMBOL_REFERENCES_LOCAL (info, h))
+      if (SYMBOL_CALLS_LOCAL (info, h))
 	{
 	  struct elf_s390_dyn_relocs **pp;
 
@@ -2364,10 +2360,7 @@ elf_s390_relocate_section (output_bfd, i
 	      dyn = htab->elf.dynamic_sections_created;
 	      if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
 		  || (info->shared
-		      && (info->symbolic
-			  || h->dynindx == -1
-			  || h->forced_local)
-		      && h->def_regular)
+		      && SYMBOL_REFERENCES_LOCAL (info, h))
 		  || (ELF_ST_VISIBILITY (h->other)
 		      && h->root.type == bfd_link_hash_undefweak))
 		{
@@ -2537,8 +2530,7 @@ elf_s390_relocate_section (output_bfd, i
 		    && r_type != R_390_PC16DBL
 		    && r_type != R_390_PC32DBL
 		    && r_type != R_390_PC32)
-		   || (h != NULL
-		       && !SYMBOL_REFERENCES_LOCAL (info, h))))
+		   || !SYMBOL_CALLS_LOCAL (info, h)))
 	      || (ELIMINATE_COPY_RELOCS
 		  && !info->shared
 		  && h != NULL
@@ -2580,7 +2572,7 @@ elf_s390_relocate_section (output_bfd, i
 			   || r_type == R_390_PC32DBL
 			   || r_type == R_390_PC32
 			   || !info->shared
-			   || !info->symbolic
+			   || !SYMBOLIC_BIND (info, h)
 			   || !h->def_regular))
 		{
 		  outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
@@ -3262,11 +3254,10 @@ elf_s390_finish_dynamic_symbol (output_b
 	 The entry in the global offset table will already have been
 	 initialized in the relocate_section function.  */
       if (info->shared
-	  && (info->symbolic
-	      || h->dynindx == -1
-	      || h->forced_local)
-	  && h->def_regular)
+	  && SYMBOL_REFERENCES_LOCAL (info, h))
 	{
+	  if (!h->def_regular)
+	    return FALSE;
 	  BFD_ASSERT((h->got.offset & 1) != 0);
 	  rela.r_info = ELF32_R_INFO (0, R_390_RELATIVE);
 	  rela.r_addend = (h->root.u.def.value
Index: src/bfd/elf64-s390.c
===================================================================
--- src.orig/bfd/elf64-s390.c
+++ src/bfd/elf64-s390.c
@@ -1228,7 +1228,7 @@ elf_s390_check_relocs (abfd, info, sec, 
 		    && ELF64_R_TYPE (rel->r_info) != R_390_PC32DBL
 		    && ELF64_R_TYPE (rel->r_info) != R_390_PC64)
 		   || (h != NULL
-		       && (! info->symbolic
+		       && (! SYMBOLIC_BIND (info, h)
 			   || h->root.type == bfd_link_hash_defweak
 			   || !h->def_regular))))
 	      || (ELIMINATE_COPY_RELOCS
@@ -1541,11 +1541,9 @@ elf_s390_adjust_dynamic_symbol (info, h)
       || h->needs_plt)
     {
       if (h->plt.refcount <= 0
-	  || (! info->shared
-	      && !h->def_dynamic
-	      && !h->ref_dynamic
-	      && h->root.type != bfd_link_hash_undefweak
-	      && h->root.type != bfd_link_hash_undefined))
+	  || SYMBOL_CALLS_LOCAL (info, h)
+	  || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+	      && h->root.type == bfd_link_hash_undefweak))
 	{
 	  /* This case can occur if we saw a PLT32 reloc in an input
 	     file, but the symbol was never referred to by a dynamic
@@ -1684,9 +1682,7 @@ allocate_dynrelocs (h, inf)
   htab = elf_s390_hash_table (info);
 
   if (htab->elf.dynamic_sections_created
-      && h->plt.refcount > 0
-      && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-	  || h->root.type != bfd_link_hash_undefweak))
+      && h->plt.refcount > 0)
     {
       /* Make sure this symbol is output as a dynamic symbol.
 	 Undefined weak syms won't yet be marked as dynamic.  */
@@ -1815,7 +1811,7 @@ allocate_dynrelocs (h, inf)
 
   if (info->shared)
     {
-      if (SYMBOL_REFERENCES_LOCAL (info, h))
+      if (SYMBOL_CALLS_LOCAL (info, h))
 	{
 	  struct elf_s390_dyn_relocs **pp;
 
@@ -2340,10 +2336,7 @@ elf_s390_relocate_section (output_bfd, i
 	      dyn = htab->elf.dynamic_sections_created;
 	      if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
 		  || (info->shared
-		      && (info->symbolic
-			  || h->dynindx == -1
-			  || h->forced_local)
-		      && h->def_regular)
+		      && SYMBOL_REFERENCES_LOCAL (info, h))
 		  || (ELF_ST_VISIBILITY (h->other)
 		      && h->root.type == bfd_link_hash_undefweak))
 		{
@@ -2519,8 +2512,7 @@ elf_s390_relocate_section (output_bfd, i
 		    && r_type != R_390_PC32
 		    && r_type != R_390_PC32DBL
 		    && r_type != R_390_PC64)
-		   || (h != NULL
-		       && !SYMBOL_REFERENCES_LOCAL (info, h))))
+		   || !SYMBOL_CALLS_LOCAL (info, h)))
 	      || (ELIMINATE_COPY_RELOCS
 		  && !info->shared
 		  && h != NULL
@@ -2563,7 +2555,7 @@ elf_s390_relocate_section (output_bfd, i
 			   || r_type == R_390_PC32DBL
 			   || r_type == R_390_PC64
 			   || !info->shared
-			   || !info->symbolic
+			   || !SYMBOLIC_BIND (info, h)
 			   || !h->def_regular))
 		{
 		  outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
@@ -3168,11 +3160,10 @@ elf_s390_finish_dynamic_symbol (output_b
 	 The entry in the global offset table will already have been
 	 initialized in the relocate_section function.  */
       if (info->shared
-	  && (info->symbolic
-	      || h->dynindx == -1
-	      || h->forced_local)
-	  && h->def_regular)
+	  && SYMBOL_REFERENCES_LOCAL (info, h))
 	{
+	  if (!h->def_regular)
+	    return FALSE;
 	  BFD_ASSERT((h->got.offset & 1) != 0);
 	  rela.r_info = ELF64_R_INFO (0, R_390_RELATIVE);
 	  rela.r_addend = (h->root.u.def.value



More information about the Binutils mailing list