those relocs against removed linkonce section syms

Alan Modra amodra@bigpond.net.au
Mon Oct 22 21:07:00 GMT 2001


I've applied the following which, as well as fixing a few small problems
in elf32-hppa.c, reverts HJ's BFD_RELOC_NONE patch for relocs against
removed linkonce section syms, and instead simply zeros the relocs.  The
hppa port is a little rude, and uses R_PARISC_* instead of BFD_RELOC_*
args for bfd_reloc_type_lookup.  Worse, there's no easy way to implement
a bfd_reloc_type_lookup for BFD_RELOC_* without the format and field args
as in elf-hppa.h:_bfd_elf_hppa_gen_reloc_type.

bfd/ChangeLog
	* elflink.h (elf_link_input_bfd): Zero the reloc instead of doing
	bfd_reloc_type_lookup (bfd, BFD_RELOC_NONE) as bfd_reloc_type_lookup
	doesn't accept BFD_RELOC_* on some targets, eg. hppa.

	* elf32-hppa.c (elf32_hppa_link_hash_entry): Remove plt_abs.
	(hppa_link_hash_newfunc): Likewise.
	(elf32_hppa_finish_dynamic_symbol): Likewise.
	(allocate_dynrelocs): Always allocate .got relocs if shared.
	(elf32_hppa_relocate_section): Output them too.  Similarly
	consolidate .plt reloc code, and no longer initialise .plt
	when a reloc is output.
	(elf32_hppa_finish_dynamic_symbol): Only initialise .plt entries
	when no reloc is output.

	From Herbert Xu <herbert@gondor.apana.org.au>
	* elf32-hppa.c (final_link_relocate): Call bfd_set_error for
	unreachable branches.

Index: bfd/elf32-hppa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-hppa.c,v
retrieving revision 1.54
diff -u -p -r1.54 elf32-hppa.c
--- elf32-hppa.c	2001/10/15 09:45:46	1.54
+++ elf32-hppa.c	2001/10/23 03:52:08
@@ -213,10 +213,6 @@ struct elf32_hppa_link_hash_entry {
 
   /* Set if this symbol is used by a plabel reloc.  */
   unsigned int plabel:1;
-
-  /* Set if this symbol is an init or fini function and thus should
-     use an absolute reloc.  */
-  unsigned int plt_abs:1;
 };
 
 struct elf32_hppa_link_hash_table {
@@ -462,7 +458,6 @@ hppa_link_hash_newfunc (entry, table, st
       eh->maybe_pic_call = 0;
       eh->pic_call = 0;
       eh->plabel = 0;
-      eh->plt_abs = 0;
     }
 
   return entry;
@@ -2065,8 +2060,6 @@ allocate_dynrelocs (h, inf)
 
   if (h->got.refcount > 0)
     {
-      boolean dyn;
-
       /* Make sure this symbol is output as a dynamic symbol.
 	 Undefined weak syms won't yet be marked as dynamic.  */
       if (h->dynindx == -1
@@ -2080,9 +2073,13 @@ allocate_dynrelocs (h, inf)
       s = htab->sgot;
       h->got.offset = s->_raw_size;
       s->_raw_size += GOT_ENTRY_SIZE;
-      dyn = htab->elf.dynamic_sections_created;
-      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
-	htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
+      if (htab->elf.dynamic_sections_created
+	  && (info->shared
+	      || (h->dynindx != -1
+		  && h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0))
+	{
+	  htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
+	}
     }
   else
     h->got.offset = (bfd_vma) -1;
@@ -3468,6 +3465,7 @@ final_link_relocate (input_section, cont
 	 input_section->name,
 	 (long) rel->r_offset,
 	 stub_entry->root.string);
+      bfd_set_error (bfd_error_bad_value);
       return bfd_reloc_notsupported;
     }
 
@@ -3539,7 +3537,6 @@ elf32_hppa_relocate_section (output_bfd,
       bfd_reloc_status_type r;
       const char *sym_name;
       boolean plabel;
-      bfd_vma off;
 
       r_type = ELF32_R_TYPE (rel->r_info);
       if (r_type >= (unsigned int) R_PARISC_UNIMPLEMENTED)
@@ -3639,87 +3636,88 @@ elf32_hppa_relocate_section (output_bfd,
 	case R_PARISC_DLTIND14F:
 	case R_PARISC_DLTIND14R:
 	case R_PARISC_DLTIND21L:
-	  /* Relocation is to the entry for this symbol in the global
-	     offset table.  */
-	  if (h != NULL)
-	    {
-	      boolean dyn;
-
-	      off = h->elf.got.offset;
-	      dyn = htab->elf.dynamic_sections_created;
-	      if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, &h->elf))
-		{
-		  /* This is actually a static link, or it is a
-		     -Bsymbolic link and the symbol is defined
-		     locally, or the symbol was forced to be local
-		     because of a version file.  We must initialize
-		     this entry in the global offset table.  Since the
-		     offset must always be a multiple of 4, we use the
-		     least significant bit to record whether we have
-		     initialized it already.
-
-		     When doing a dynamic link, we create a .rela.got
-		     relocation entry to initialize the value.  This
-		     is done in the finish_dynamic_symbol routine.  */
-		  if ((off & 1) != 0)
-		    off &= ~1;
-		  else
-		    {
-		      bfd_put_32 (output_bfd, relocation,
-				  htab->sgot->contents + off);
-		      h->elf.got.offset |= 1;
-		    }
-		}
-	    }
-	  else
-	    {
-	      /* Local symbol case.  */
-	      if (local_got_offsets == NULL)
-		abort ();
+	  {
+	    bfd_vma off;
+	    boolean do_got = 0;
 
-	      off = local_got_offsets[r_symndx];
+	    /* Relocation is to the entry for this symbol in the
+	       global offset table.  */
+	    if (h != NULL)
+	      {
+		boolean dyn;
+
+		off = h->elf.got.offset;
+		dyn = htab->elf.dynamic_sections_created;
+		if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, &h->elf))
+		  {
+		    /* If we aren't going to call finish_dynamic_symbol,
+		       then we need to handle initialisation of the .got
+		       entry and create needed relocs here.  Since the
+		       offset must always be a multiple of 4, we use the
+		       least significant bit to record whether we have
+		       initialised it already.  */
+		    if ((off & 1) != 0)
+		      off &= ~1;
+		    else
+		      {
+			h->elf.got.offset |= 1;
+			do_got = 1;
+		      }
+		  }
+	      }
+	    else
+	      {
+		/* Local symbol case.  */
+		if (local_got_offsets == NULL)
+		  abort ();
+
+		off = local_got_offsets[r_symndx];
+
+		/* The offset must always be a multiple of 4.  We use
+		   the least significant bit to record whether we have
+		   already generated the necessary reloc.  */
+		if ((off & 1) != 0)
+		  off &= ~1;
+		else
+		  {
+		    local_got_offsets[r_symndx] |= 1;
+		    do_got = 1;
+		  }
+	      }
 
-	      /* The offset must always be a multiple of 4.  We use
-		 the least significant bit to record whether we have
-		 already generated the necessary reloc.  */
-	      if ((off & 1) != 0)
-		off &= ~1;
-	      else
-		{
+	    if (do_got)
+	      {
+		if (info->shared)
+		  {
+		    /* Output a dynamic relocation for this GOT entry.
+		       In this case it is relative to the base of the
+		       object because the symbol index is zero.  */
+		    Elf_Internal_Rela outrel;
+		    asection *srelgot = htab->srelgot;
+		    Elf32_External_Rela *loc;
+
+		    outrel.r_offset = (off
+				       + htab->sgot->output_offset
+				       + htab->sgot->output_section->vma);
+		    outrel.r_info = ELF32_R_INFO (0, R_PARISC_DIR32);
+		    outrel.r_addend = relocation;
+		    loc = (Elf32_External_Rela *) srelgot->contents;
+		    loc += srelgot->reloc_count++;
+		    bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+		  }
+		else
 		  bfd_put_32 (output_bfd, relocation,
 			      htab->sgot->contents + off);
+	      }
 
-		  if (info->shared)
-		    {
-		      /* Output a dynamic relocation for this GOT
-			 entry.  In this case it is relative to the
-			 base of the object because the symbol index
-			 is zero.  */
-		      Elf_Internal_Rela outrel;
-		      asection *srelgot = htab->srelgot;
-		      Elf32_External_Rela *loc;
+	    if (off >= (bfd_vma) -2)
+	      abort ();
 
-		      outrel.r_offset = (off
-					 + htab->sgot->output_offset
-					 + htab->sgot->output_section->vma);
-		      outrel.r_info = ELF32_R_INFO (0, R_PARISC_DIR32);
-		      outrel.r_addend = relocation;
-		      loc = (Elf32_External_Rela *) srelgot->contents;
-		      loc += srelgot->reloc_count++;
-		      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
-		    }
-
-		  local_got_offsets[r_symndx] |= 1;
-		}
-	    }
-
-	  if (off >= (bfd_vma) -2)
-	    abort ();
-
-	  /* Add the base of the GOT to the relocation value.  */
-	  relocation = (off
-			+ htab->sgot->output_offset
-			+ htab->sgot->output_section->vma);
+	    /* Add the base of the GOT to the relocation value.  */
+	    relocation = (off
+			  + htab->sgot->output_offset
+			  + htab->sgot->output_section->vma);
+	  }
 	  break;
 
 	case R_PARISC_SEGREL32:
@@ -3734,6 +3732,9 @@ elf32_hppa_relocate_section (output_bfd,
 	case R_PARISC_PLABEL32:
 	  if (htab->elf.dynamic_sections_created)
 	    {
+	      bfd_vma off;
+	      boolean do_plt = 0;
+
 	      /* If we have a global symbol with a PLT slot, then
 		 redirect this relocation to it.  */
 	      if (h != NULL)
@@ -3748,13 +3749,8 @@ elf32_hppa_relocate_section (output_bfd,
 			off &= ~1;
 		      else
 			{
-			  bfd_put_32 (output_bfd,
-				      relocation,
-				      htab->splt->contents + off);
-			  bfd_put_32 (output_bfd,
-				      elf_gp (htab->splt->output_section->owner),
-				      htab->splt->contents + off + 4);
 			  h->elf.plt.offset |= 1;
+			  do_plt = 1;
 			}
 		    }
 		}
@@ -3775,32 +3771,38 @@ elf32_hppa_relocate_section (output_bfd,
 		    off &= ~1;
 		  else
 		    {
+		      local_plt_offsets[r_symndx] |= 1;
+		      do_plt = 1;
+		    }
+		}
+
+	      if (do_plt)
+		{
+		  if (info->shared)
+		    {
+		      /* Output a dynamic IPLT relocation for this
+			 PLT entry.  */
+		      Elf_Internal_Rela outrel;
+		      asection *srelplt = htab->srelplt;
+		      Elf32_External_Rela *loc;
+
+		      outrel.r_offset = (off
+					 + htab->splt->output_offset
+					 + htab->splt->output_section->vma);
+		      outrel.r_info = ELF32_R_INFO (0, R_PARISC_IPLT);
+		      outrel.r_addend = relocation;
+		      loc = (Elf32_External_Rela *) srelplt->contents;
+		      loc += srelplt->reloc_count++;
+		      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+		    }
+		  else
+		    {
 		      bfd_put_32 (output_bfd,
 				  relocation,
 				  htab->splt->contents + off);
 		      bfd_put_32 (output_bfd,
 				  elf_gp (htab->splt->output_section->owner),
 				  htab->splt->contents + off + 4);
-
-		      if (info->shared)
-			{
-			  /* Output a dynamic IPLT relocation for this
-			     PLT entry.  */
-			  Elf_Internal_Rela outrel;
-			  asection *srelplt = htab->srelplt;
-			  Elf32_External_Rela *loc;
-
-			  outrel.r_offset = (off
-					     + htab->splt->output_offset
-					     + htab->splt->output_section->vma);
-			  outrel.r_info = ELF32_R_INFO (0, R_PARISC_IPLT);
-			  outrel.r_addend = relocation;
-			  loc = (Elf32_External_Rela *) srelplt->contents;
-			  loc += srelplt->reloc_count++;
-			  bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
-			}
-
-		      local_plt_offsets[r_symndx] |= 1;
 		    }
 		}
 
@@ -3881,6 +3883,8 @@ elf32_hppa_relocate_section (output_bfd,
 	      skip = false;
 	      if (elf_section_data (input_section)->stab_info != NULL)
 		{
+		  bfd_vma off;
+
 		  off = (_bfd_stab_section_offset
 			 (output_bfd, &htab->elf.stab_info,
 			  input_section,
@@ -4076,8 +4080,7 @@ elf32_hppa_finish_dynamic_symbol (output
 	  rel.r_offset = (h->plt.offset
 			  + htab->splt->output_offset
 			  + htab->splt->output_section->vma);
-	  if (! ((struct elf32_hppa_link_hash_entry *) h)->plt_abs
-	      && h->dynindx != -1)
+	  if (h->dynindx != -1)
 	    {
 	      /* To support lazy linking, the function pointer is
 		 initialised to point to a special stub stored at the
@@ -4104,19 +4107,14 @@ elf32_hppa_finish_dynamic_symbol (output
 	  bfd_elf32_swap_reloca_out (htab->splt->output_section->owner,
 				     &rel, loc);
 	}
-
-      bfd_put_32 (htab->splt->owner,
-		  value,
-		  htab->splt->contents + h->plt.offset);
-      bfd_put_32 (htab->splt->owner,
-		  elf_gp (htab->splt->output_section->owner),
-		  htab->splt->contents + h->plt.offset + 4);
-      if (PLABEL_PLT_ENTRY_SIZE != PLT_ENTRY_SIZE
-	  && ((struct elf32_hppa_link_hash_entry *) h)->plabel
-	  && h->dynindx != -1)
+      else
 	{
-	  memset (htab->splt->contents + h->plt.offset + 8,
-		  0, PLABEL_PLT_ENTRY_SIZE - PLT_ENTRY_SIZE);
+	  bfd_put_32 (htab->splt->owner,
+		      value,
+		      htab->splt->contents + h->plt.offset);
+	  bfd_put_32 (htab->splt->owner,
+		      elf_gp (htab->splt->output_section->owner),
+		      htab->splt->contents + h->plt.offset + 4);
 	}
 
       if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
Index: bfd/elflink.h
===================================================================
RCS file: /cvs/src/src/bfd/elflink.h,v
retrieving revision 1.117
diff -u -p -r1.117 elflink.h
--- elflink.h	2001/10/17 12:01:05	1.117
+++ elflink.h	2001/10/23 03:52:16
@@ -5897,8 +5897,6 @@ elf_link_input_bfd (finfo, input_bfd)
   asection *o;
   struct elf_backend_data *bed;
   boolean emit_relocs;
-  reloc_howto_type *none_howto;
-  bfd_vma none_r_info;
 
   output_bfd = finfo->output_bfd;
   bed = get_elf_backend_data (output_bfd);
@@ -6070,9 +6068,6 @@ elf_link_input_bfd (finfo, input_bfd)
 	return false;
     }
 
-  none_howto = bfd_reloc_type_lookup (output_bfd, BFD_RELOC_NONE);
-  none_r_info = ELF_R_INFO (0, none_howto->type);
-
   /* Relocate the contents of each section.  */
   for (o = input_bfd->sections; o != NULL; o = o->next)
     {
@@ -6125,13 +6120,12 @@ elf_link_input_bfd (finfo, input_bfd)
 	  {
 	    Elf_Internal_Rela *rel, *relend;
 	    /* Run through the relocs looking for any against section
-	       symbols from removed link-once sections.  Set any such
-	       relocs to be against 0.  We should really complain if
-	       anything in the final link tries to use it, but
-	       DWARF-based exception handling might have an entry in
-	       .eh_frame to describe a routine in the linkonce section,
-	       and it turns out to be hard to remove the .eh_frame entry
-	       too.  FIXME.  */
+	       symbols from removed link-once sections.  Zero any such
+	       relocs.  We should really complain if anything in the
+	       final link tries to use it, but DWARF-based exception
+	       handling might have an entry in .eh_frame to describe a
+	       routine in the linkonce section, and it turns out to be
+	       hard to remove the .eh_frame entry too.  FIXME.  */
 	    rel = internal_relocs;
 	    relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
 	    for ( ; rel < relend; rel++)
@@ -6151,21 +6145,20 @@ elf_link_input_bfd (finfo, input_bfd)
 			    && (sec->flags & SEC_LINK_ONCE) != 0
 			    && bfd_is_abs_section (sec->output_section))
 			  {
-			    rel->r_info = none_r_info;
-
 #if BFD_VERSION_DATE > 20021005
 			    (*finfo->info->callbacks->warning)
 			      (finfo->info,
 			       _("warning: relocation against removed section; zeroing"),
 			       NULL, input_bfd, o, rel->r_offset);
 #endif
+			    memset (rel, 0, sizeof (*rel));
 			  }
 		      }
 		  }
 	      }
 	  }
 #else
-#error "This kludge ought to be fixed properly in gcc by now"
+#error "gcc should be fixed by now, and this kludge no longer needed"
 #endif
 
 	  /* Relocate the section by invoking a back end routine.



More information about the Binutils mailing list