This is the mail archive of the binutils@sources.redhat.com 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]

Re: PATCH: Fix linkonce for ELF/PPC.


On Wed, Nov 07, 2001 at 12:45:29AM +1030, Alan Modra wrote:
> OK, I've spent some time debugging this problem.
> 
> Looking at .rela.eh_frame in the bad libstdc++, I see a bunch of
> RELATIVE relocs, none of which should cause problems, ADDR32 relocs
> against __gxx_personality_v0, again no problem, and some NONE relocs.
> These are the infamous relocs against removed linkonce sections.
> 
> From a little investigation under gdb, it appears that they were
> originally all ADDR32 relocs (with something like HJ's patch of
> http://sources.redhat.com/ml/binutils/2001-10/msg00589.html applied,
> they are massaged to RELATIVE relocs before being written, see
> elf32-ppc.c:3244).  Now the problem with turning these relocs into
> R_PPC_NONE, as the current code does, is that ppc gas puts the addend
> into the section contents as well as the reloc.  Furthermore,
> gcc-3.0.x eh_frame data has relocations against local syms in linkonce
> sections.  That means the section contents for things like a fde
> pc_begin might be left non-zero.  Thus code in gcc/unwind-dw2-fde.c
> that tries to discard these bogus fdes won't work.
> 
> One curious fact about turning the reloc into a RELATIVE reloc is that
> if the reloc is copied to the shared lib the final value won't be
> zero unless the shared lib loads at zero.  So, I'm not sure why HJ's
> patch works at all.
> 
> I'm leaning towards the following fix, which ensures that any
> relocation against a removed linkonce section sym resolves to zero,
> regardless of addend.  Seems to cure the ppc problem.  Not tested
> terribly well yet, and needs similar changes in other back-ends to
> code that copies relocs into shared libs.  The reason I'm posting this
> now is a) the above explanation for what is wrong may prompt a better
> fix from someone, b) I'm not dead certain that trimming off STN_UNDEF
> relocs is always correct.  ie. There may be some reason for them to
> appear in input sections during a shared link.  Anyone like to comment
> on this?

Here is the (almost) full patch.  For elf32-i386, elf32-hppa and elf64-ppc,
I've implemented a scheme to ensure NONE relocs don't appear in the final
link.  Most other targets allocate space for the relocs too soon to be
able to avoid NONE relocs.

I'd like some feedback from target maintainers before I apply this patch
as I can't test all these targets very well.  Oh, and I haven't done
anything with elf64-hppa.c yet as it's painfully different from other
targets.

bfd/ChangeLog
	* elf32-arm.h (elf32_arm_final_link_relocate): Don't copy STN_UNDEF
	relocs into shared libs.
	* elf32-cris.c (cris_elf_relocate_section): Likewise.
	* elf32-i370.c (i370_elf_relocate_section): Likewise.
	* elf32-m68k.c (elf_m68k_relocate_section): Likewise.
	* elf32-mips.c (mips_elf_calculate_relocation): Likewise.
	* elf32-ppc.c (ppc_elf_relocate_section): Likewise.
	* elf32-s390.c (elf_s390_relocate_section): Likewise.
	* elf32-sh.c (sh_elf_relocate_section): Likewise.
	* elf32-sparc.c (elf32_sparc_relocate_section): Likewise.
	* elf64-alpha.c (elf64_alpha_relocate_section): Likewise.
	* elf64-s390.c (elf_s390_relocate_section): Likewise.
	* elf64-sparc.c (sparc64_elf_relocate_section): Likewise.
	* elf64-x86-64.c (elf64_x86_64_relocate_section): Likewise.
	* elfxx-ia64.c (elfNN_ia64_relocate_section): Likewise.

	* elf.c (bfd_section_from_r_symndx): New function.
	* elf-bfd.h (struct sym_sec_cache): New.
	(bfd_section_from_r_symndx): Declare.
	(struct bfd_elf_section_data): Change local_dynrel type to PTR.
	* elflink.h (elf_link_input_bfd <removed linkonce relocs>): Don't
	zero entire reloc, just zero the addend and sym.  Add r_symndx
	assertion.
	* elf32-hppa.c (LOCAL_SYM_CACHE_SIZE): Define.
	(struct elf32_hppa_link_hash_table): Add sym_sec.
	(elf32_hppa_link_hash_table_create): Init it.
	(elf32_hppa_check_relocs): Track dynamic relocs needed for local
	syms on a per-section basis as we do for globals.
	(elf32_hppa_gc_sweep_hook): Update for local_dynrel change.
	(allocate_dynrelocs): Warning fix.
	(elf32_hppa_size_dynamic_sections): Don't allocate relocs when
	section has been discarded.
	(elf32_hppa_relocate_section): Don't copy STN_UNDEF relocs
	into shared libs.
	* elf32-i386.c (LOCAL_SYM_CACHE_SIZE): Define.
	(struct elf_i386_link_hash_table): Add sym_sec.
	(elf_i386_link_hash_table_create): Init it.
	(elf_i386_check_relocs): Track dynamic relocs needed for local
	syms on a per-section basis as we do for globals.
	(elf_i386_gc_sweep_hook): Update for local_dynrel change.
	Remove dead code.
	(allocate_dynrelocs): Warning fix.
	(elf_i386_size_dynamic_sections): Don't allocate relocs when
	section has been discarded.
	(elf_i386_relocate_section): Don't copy STN_UNDEF relocs
	into shared libs.
	* elf64-ppc.c (LOCAL_SYM_CACHE_SIZE): Define.
	(struct ppc_link_hash_table): Add sym_sec.
	(ppc64_link_hash_table_create): Init it.
	(ppc64_elf_check_relocs): Track dynamic relocs needed for local
	syms on a per-section basis as we do for globals.
	(ppc64_elf_gc_sweep_hook): Update for local_dynrel change.
	(allocate_dynrelocs): Call the correct record_dynamic_dymbol
	function.  Warning fix.
	(ppc64_elf_size_dynamic_sections): Don't allocate relocs when
	section has been discarded.
	(ppc64_elf_relocate_section): Don't copy STN_UNDEF relocs
	into shared libs.

-- 
Alan Modra

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.52
diff -u -p -r1.52 elf-bfd.h
--- elf-bfd.h	2001/10/09 13:12:19	1.52
+++ elf-bfd.h	2001/11/08 13:36:34
@@ -297,6 +297,16 @@ struct elf_link_hash_table
 /* Returns true if the hash table is a struct elf_link_hash_table.  */
 #define is_elf_hash_table(p)					      	\
   ((p)->hash->type == bfd_link_elf_hash_table)
+
+/* Used by bfd_section_from_r_symndx to cache a small number of local
+   symbol to section mappings.  */
+#define LOCAL_SYM_CACHE_SIZE 32
+struct sym_sec_cache
+{
+  bfd *abfd;
+  unsigned long indx[LOCAL_SYM_CACHE_SIZE];
+  asection *sec[LOCAL_SYM_CACHE_SIZE];
+};
 
 /* Constant information held for an ELF backend.  */
 
@@ -776,8 +786,9 @@ struct bfd_elf_section_data
   /* The number of relocations currently assigned to REL_HDR2.  */
   unsigned int rel_count2;
 
-  /* The number of dynamic relocs copied for local symbols.  */
-  unsigned int local_dynrel;
+  /* A pointer to a linked list tracking dynamic relocs copied for
+     local symbols.  */
+  PTR local_dynrel;
 
   /* A pointer to the bfd section used for dynamic relocs.  */
   asection *sreloc;
@@ -1196,6 +1207,8 @@ extern boolean bfd_section_from_phdr
 extern int _bfd_elf_symbol_from_bfd_symbol
   PARAMS ((bfd *, asymbol **));
 
+extern asection *bfd_section_from_r_symndx
+  PARAMS ((bfd *, struct sym_sec_cache *, asection *, unsigned long));
 extern asection *bfd_section_from_elf_index
   PARAMS ((bfd *, unsigned int));
 extern boolean _bfd_elf_create_dynamic_sections
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.104
diff -u -p -r1.104 elf.c
--- elf.c	2001/10/30 11:40:28	1.104
+++ elf.c	2001/11/08 13:36:38
@@ -1747,6 +1747,62 @@ bfd_section_from_shdr (abfd, shindex)
   return true;
 }
 
+/* Return the section for the local symbol specified by ABFD, R_SYMNDX.
+   Return SEC for sections that have no elf section, and NULL on error.  */
+
+asection *
+bfd_section_from_r_symndx (abfd, cache, sec, r_symndx)
+     bfd *abfd;
+     struct sym_sec_cache *cache;
+     asection *sec;
+     unsigned long r_symndx;
+{
+  unsigned char esym_shndx[2];
+  unsigned int isym_shndx;
+  Elf_Internal_Shdr *symtab_hdr;
+  file_ptr pos;
+  bfd_size_type amt;
+  unsigned int ent = r_symndx % LOCAL_SYM_CACHE_SIZE;
+
+  if (cache->abfd == abfd && cache->indx[ent] == r_symndx)
+    return cache->sec[ent];
+
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  pos = symtab_hdr->sh_offset;
+  if (get_elf_backend_data (abfd)->s->sizeof_sym
+      == sizeof (Elf64_External_Sym))
+    {
+      pos += r_symndx * sizeof (Elf64_External_Sym);
+      pos += offsetof (Elf64_External_Sym, st_shndx);
+    }
+  else
+    {
+      pos += r_symndx * sizeof (Elf32_External_Sym);
+      pos += offsetof (Elf32_External_Sym, st_shndx);
+    }
+  amt = sizeof (esym_shndx);
+  if (bfd_seek (abfd, pos, SEEK_SET) != 0
+      || bfd_bread ((PTR) esym_shndx, amt, abfd) != amt)
+    return NULL;
+  isym_shndx = H_GET_16 (abfd, esym_shndx);
+
+  if (cache->abfd != abfd)
+    {
+      memset (cache->indx, -1, sizeof (cache->indx));
+      cache->abfd = abfd;
+    }
+  cache->indx[ent] = r_symndx;
+  cache->sec[ent] = sec;
+  if (isym_shndx > 0 && isym_shndx < SHN_LORESERVE)
+    {
+      asection *s;
+      s = bfd_section_from_elf_index (abfd, isym_shndx);
+      if (s != NULL)
+	cache->sec[ent] = s;
+    }
+  return cache->sec[ent];
+}
+
 /* Given an ELF section number, retrieve the corresponding BFD
    section.  */
 
Index: bfd/elf32-arm.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.h,v
retrieving revision 1.62
diff -u -p -r1.62 elf32-arm.h
--- elf32-arm.h	2001/10/12 11:16:21	1.62
+++ elf32-arm.h	2001/11/08 13:36:41
@@ -1116,6 +1116,7 @@ elf32_arm_final_link_relocate (howto, in
       /* When generating a shared object, these relocations are copied
 	 into the output file to be resolved at run time.  */
       if (info->shared
+	  && r_symndx != 0
 	  && (r_type != R_ARM_PC24
 	      || (h != NULL
 	          && h->dynindx != -1
Index: bfd/elf32-cris.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-cris.c,v
retrieving revision 1.17
diff -u -p -r1.17 elf32-cris.c
--- elf32-cris.c	2001/11/02 07:20:24	1.17
+++ elf32-cris.c	2001/11/08 13:36:45
@@ -1233,6 +1233,7 @@ cris_elf_relocate_section (output_bfd, i
 	case R_CRIS_16:
 	case R_CRIS_32:
 	  if (info->shared
+	      && r_symndx != 0
 	      && (input_section->flags & SEC_ALLOC) != 0
 	      && ((r_type != R_CRIS_8_PCREL
 		   && r_type != R_CRIS_16_PCREL
Index: bfd/elf32-hppa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-hppa.c,v
retrieving revision 1.58
diff -u -p -r1.58 elf32-hppa.c
--- elf32-hppa.c	2001/11/02 10:37:04	1.58
+++ elf32-hppa.c	2001/11/08 13:36:47
@@ -263,6 +263,9 @@ struct elf32_hppa_link_hash_table {
 
   /* Set if we need a .plt stub to support lazy dynamic linking.  */
   unsigned int need_plt_stub:1;
+
+  /* Small local sym to section mapping cache.  */
+  struct sym_sec_cache sym_sec;
 };
 
 /* Various hash macros and functions.  */
@@ -507,6 +510,7 @@ elf32_hppa_link_hash_table_create (abfd)
   ret->has_12bit_branch = 0;
   ret->has_17bit_branch = 0;
   ret->need_plt_stub = 0;
+  ret->sym_sec.abfd = NULL;
 
   return &ret->elf.root;
 }
@@ -1514,6 +1518,9 @@ elf32_hppa_check_relocs (abfd, info, sec
 		      || (h->elf.elf_link_hash_flags
 			  & ELF_LINK_HASH_DEF_REGULAR) == 0)))
 	    {
+	      struct elf32_hppa_dyn_reloc_entry *p;
+	      struct elf32_hppa_dyn_reloc_entry **head;
+
 	      /* Create a reloc section in dynobj and make room for
 		 this reloc.  */
 	      if (sreloc == NULL)
@@ -1561,36 +1568,46 @@ elf32_hppa_check_relocs (abfd, info, sec
 		 relocations we need for this symbol.  */
 	      if (h != NULL)
 		{
-		  struct elf32_hppa_dyn_reloc_entry *p;
+		  head = &h->dyn_relocs;
+		}
+	      else
+		{
+		  /* Track dynamic relocs needed for local syms too.
+		     We really need local syms available to do this
+		     easily.  Oh well.  */
+
+		  asection *s;
+		  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
+						 sec, r_symndx);
+		  if (s == NULL)
+		    return false;
 
-		  p = h->dyn_relocs;
-		  if (p == NULL || p->sec != sec)
-		    {
-		      p = ((struct elf32_hppa_dyn_reloc_entry *)
-			   bfd_alloc (htab->elf.dynobj,
-				      (bfd_size_type) sizeof *p));
-		      if (p == NULL)
-			return false;
-		      p->next = h->dyn_relocs;
-		      h->dyn_relocs = p;
-		      p->sec = sec;
-		      p->count = 0;
+		  head = ((struct elf32_hppa_dyn_reloc_entry **)
+			  &elf_section_data (s)->local_dynrel);
+		}
+
+	      p = *head;
+	      if (p == NULL || p->sec != sec)
+		{
+		  p = ((struct elf32_hppa_dyn_reloc_entry *)
+		       bfd_alloc (htab->elf.dynobj,
+				  (bfd_size_type) sizeof *p));
+		  if (p == NULL)
+		    return false;
+		  p->next = *head;
+		  *head = p;
+		  p->sec = sec;
+		  p->count = 0;
 #if RELATIVE_DYNRELOCS
-		      p->relative_count = 0;
+		  p->relative_count = 0;
 #endif
-		    }
+		}
 
-		  p->count += 1;
+	      p->count += 1;
 #if RELATIVE_DYNRELOCS
-		  if (!IS_ABSOLUTE_RELOC (rtype))
-		    p->relative_count += 1;
+	      if (!IS_ABSOLUTE_RELOC (rtype))
+		p->relative_count += 1;
 #endif
-		}
-	      else
-		{
-		  /* Track dynamic relocs needed for local syms too.  */
-		  elf_section_data (sec)->local_dynrel += 1;
-		}
 	    }
 	}
     }
@@ -1666,7 +1683,7 @@ elf32_hppa_gc_sweep_hook (abfd, info, se
   struct elf32_hppa_link_hash_table *htab;
   bfd *dynobj;
 
-  elf_section_data (sec)->local_dynrel = 0;
+  elf_section_data (sec)->local_dynrel = NULL;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
@@ -2184,7 +2201,7 @@ allocate_dynrelocs (h, inf)
       eh->dyn_relocs = NULL;
       return true;
 
-    keep:
+    keep: ;
     }
 
   /* Finally, allocate space.  */
@@ -2311,12 +2328,26 @@ elf32_hppa_size_dynamic_sections (output
 
       for (s = ibfd->sections; s != NULL; s = s->next)
 	{
-	  bfd_size_type count = elf_section_data (s)->local_dynrel;
+	  struct elf32_hppa_dyn_reloc_entry *p;
 
-	  if (count != 0)
-	    {
-	      srel = elf_section_data (s)->sreloc;
-	      srel->_raw_size += count * sizeof (Elf32_External_Rela);
+	  for (p = ((struct elf32_hppa_dyn_reloc_entry *)
+		    elf_section_data (s)->local_dynrel);
+	       p != NULL;
+	       p = p->next)
+	    {
+	      if (!bfd_is_abs_section (p->sec)
+		  && bfd_is_abs_section (p->sec->output_section))
+		{
+		  /* Input section has been discarded, either because
+		     it is a copy of a linkonce section or due to
+		     linker script /DISCARD/, so we'll be discarding
+		     the relocs too.  */
+		}
+	      else
+		{
+		  srel = elf_section_data (p->sec)->sreloc;
+		  srel->_raw_size += p->count * sizeof (Elf32_External_Rela);
+		}
 	    }
 	}
 
@@ -3877,12 +3908,19 @@ elf32_hppa_relocate_section (output_bfd,
 	case R_PARISC_DPREL14R:
 	case R_PARISC_DPREL21L:
 	case R_PARISC_DIR32:
+	  /* r_symndx will be zero only for relocs against symbols
+	     from removed linkonce sections, or sections discarded by
+	     a linker script.  */
+	  if (r_symndx == 0
+	      || (input_section->flags & SEC_ALLOC) == 0)
+	    break;
+
 	  /* The reloc types handled here and this conditional
 	     expression must match the code in ..check_relocs and
-	     ..discard_relocs.  ie. We need exactly the same condition
+	     allocate_dynrelocs.  ie. We need exactly the same condition
 	     as in ..check_relocs, with some extra conditions (dynindx
 	     test in this case) to cater for relocs removed by
-	     ..discard_relocs.  If you squint, the non-shared test
+	     allocate_dynrelocs.  If you squint, the non-shared test
 	     here does indeed match the one in ..check_relocs, the
 	     difference being that here we test DEF_DYNAMIC as well as
 	     !DEF_REGULAR.  All common syms end up with !DEF_REGULAR,
@@ -3890,7 +3928,6 @@ elf32_hppa_relocate_section (output_bfd,
 	     Conversely, DEF_DYNAMIC can't be used in check_relocs as
 	     there all files have not been loaded.  */
 	  if ((info->shared
-	       && (input_section->flags & SEC_ALLOC) != 0
 	       && (IS_ABSOLUTE_RELOC (r_type)
 		   || (h != NULL
 		       && h->elf.dynindx != -1
@@ -3898,7 +3935,6 @@ elf32_hppa_relocate_section (output_bfd,
 			   || (h->elf.elf_link_hash_flags
 			       & ELF_LINK_HASH_DEF_REGULAR) == 0))))
 	      || (!info->shared
-		  && (input_section->flags & SEC_ALLOC) != 0
 		  && h != NULL
 		  && h->elf.dynindx != -1
 		  && (h->elf.elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
Index: bfd/elf32-i370.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-i370.c,v
retrieving revision 1.12
diff -u -p -r1.12 elf32-i370.c
--- elf32-i370.c	2001/10/19 02:11:04	1.12
+++ elf32-i370.c	2001/11/08 13:36:49
@@ -1449,7 +1449,8 @@ i370_elf_relocate_section (output_bfd, i
            object.  */
 	case (int)R_I370_ADDR31:
 	case (int)R_I370_ADDR16:
-	  if (info->shared)
+	  if (info->shared
+	      && r_symndx != 0)
 	    {
 	      Elf_Internal_Rela outrel;
 	      boolean skip;
Index: bfd/elf32-i386.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-i386.c,v
retrieving revision 1.57
diff -u -p -r1.57 elf32-i386.c
--- elf32-i386.c	2001/10/15 12:58:48	1.57
+++ elf32-i386.c	2001/11/08 13:36:52
@@ -497,6 +497,9 @@ struct elf_i386_link_hash_table
   asection *srelplt;
   asection *sdynbss;
   asection *srelbss;
+
+  /* Small local sym to section mapping cache.  */
+  struct sym_sec_cache sym_sec;
 };
 
 /* Get the i386 ELF linker hash table from a link_info structure.  */
@@ -561,6 +564,7 @@ elf_i386_link_hash_table_create (abfd)
   ret->srelplt = NULL;
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
+  ret->sym_sec.abfd = NULL;
 
   return &ret->elf.root;
 }
@@ -833,6 +837,9 @@ elf_i386_check_relocs (abfd, info, sec, 
 		      || (h->elf_link_hash_flags
 			  & ELF_LINK_HASH_DEF_REGULAR) == 0)))
 	    {
+	      struct elf_i386_dyn_relocs *p;
+	      struct elf_i386_dyn_relocs **head;
+
 	      /* We must copy these reloc types into the output file.
 		 Create a reloc section in dynobj and make room for
 		 this reloc.  */
@@ -883,35 +890,42 @@ elf_i386_check_relocs (abfd, info, sec, 
 		 relocations we need for this symbol.  */
 	      if (h != NULL)
 		{
-		  struct elf_i386_link_hash_entry *eh;
-		  struct elf_i386_dyn_relocs *p;
-
-		  eh = (struct elf_i386_link_hash_entry *) h;
-		  p = eh->dyn_relocs;
-
-		  if (p == NULL || p->sec != sec)
-		    {
-		      bfd_size_type amt = sizeof *p;
-		      p = ((struct elf_i386_dyn_relocs *)
-			   bfd_alloc (htab->elf.dynobj, amt));
-		      if (p == NULL)
-			return false;
-		      p->next = eh->dyn_relocs;
-		      eh->dyn_relocs = p;
-		      p->sec = sec;
-		      p->count = 0;
-		      p->pc_count = 0;
-		    }
-
-		  p->count += 1;
-		  if (ELF32_R_TYPE (rel->r_info) == R_386_PC32)
-		    p->pc_count += 1;
+		  head = &((struct elf_i386_link_hash_entry *) h)->dyn_relocs;
 		}
 	      else
 		{
-		  /* Track dynamic relocs needed for local syms too.  */
-		  elf_section_data (sec)->local_dynrel += 1;
+		  /* Track dynamic relocs needed for local syms too.
+		     We really need local syms available to do this
+		     easily.  Oh well.  */
+
+		  asection *s;
+		  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
+						 sec, r_symndx);
+		  if (s == NULL)
+		    return false;
+
+		  head = ((struct elf_i386_dyn_relocs **)
+			  &elf_section_data (s)->local_dynrel);
+		}
+
+	      p = *head;
+	      if (p == NULL || p->sec != sec)
+		{
+		  bfd_size_type amt = sizeof *p;
+		  p = ((struct elf_i386_dyn_relocs *)
+		       bfd_alloc (htab->elf.dynobj, amt));
+		  if (p == NULL)
+		    return false;
+		  p->next = *head;
+		  *head = p;
+		  p->sec = sec;
+		  p->count = 0;
+		  p->pc_count = 0;
 		}
+
+	      p->count += 1;
+	      if (ELF32_R_TYPE (rel->r_info) == R_386_PC32)
+		p->pc_count += 1;
 	    }
 	  break;
 
@@ -1000,13 +1014,8 @@ elf_i386_gc_sweep_hook (abfd, info, sec,
   const Elf_Internal_Rela *rel, *relend;
   unsigned long r_symndx;
   struct elf_link_hash_entry *h;
-  bfd *dynobj;
 
-  elf_section_data (sec)->local_dynrel = 0;
-
-  dynobj = elf_hash_table (info)->dynobj;
-  if (dynobj == NULL)
-    return true;
+  elf_section_data (sec)->local_dynrel = NULL;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
@@ -1393,7 +1402,7 @@ allocate_dynrelocs (h, inf)
 
       eh->dyn_relocs = NULL;
 
-    keep:
+    keep: ;
     }
 
   /* Finally, allocate space.  */
@@ -1480,12 +1489,27 @@ elf_i386_size_dynamic_sections (output_b
 
       for (s = ibfd->sections; s != NULL; s = s->next)
 	{
-	  bfd_size_type count = elf_section_data (s)->local_dynrel;
+	  struct elf_i386_dyn_relocs *p;
 
-	  if (count != 0)
+	  for (p = *((struct elf_i386_dyn_relocs **)
+		     &elf_section_data (s)->local_dynrel);
+	       p != NULL;
+	       p = p->next)
 	    {
-	      srel = elf_section_data (s)->sreloc;
-	      srel->_raw_size += count * sizeof (Elf32_External_Rel);
+	      if (!bfd_is_abs_section (p->sec)
+		  && bfd_is_abs_section (p->sec->output_section))
+		{
+		  /* Input section has been discarded, either because
+		     it is a copy of a linkonce section or due to
+		     linker script /DISCARD/, so we'll be discarding
+		     the relocs too.  */
+		}
+	      else
+		{
+		  srel = elf_section_data (p->sec)->sreloc;
+
+		  srel->_raw_size += p->count * sizeof (Elf32_External_Rel);
+		}
 	    }
 	}
 
@@ -1924,8 +1948,14 @@ elf_i386_relocate_section (output_bfd, i
 
 	case R_386_32:
 	case R_386_PC32:
+	  /* r_symndx will be zero only for relocs against symbols
+	     from removed linkonce sections, or sections discarded by
+	     a linker script.  */
+	  if (r_symndx == 0
+	      || (input_section->flags & SEC_ALLOC) == 0)
+	    break;
+
 	  if ((info->shared
-	       && (input_section->flags & SEC_ALLOC) != 0
 	       && (r_type != R_386_PC32
 		   || (h != NULL
 		       && h->dynindx != -1
@@ -1933,7 +1963,6 @@ elf_i386_relocate_section (output_bfd, i
 			   || (h->elf_link_hash_flags
 			       & ELF_LINK_HASH_DEF_REGULAR) == 0))))
 	      || (!info->shared
-		  && (input_section->flags & SEC_ALLOC) != 0
 		  && h != NULL
 		  && h->dynindx != -1
 		  && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
@@ -2010,7 +2039,6 @@ elf_i386_relocate_section (output_bfd, i
 	      if (! relocate)
 		continue;
 	    }
-
 	  break;
 
 	default:
Index: bfd/elf32-m68k.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-m68k.c,v
retrieving revision 1.29
diff -u -p -r1.29 elf32-m68k.c
--- elf32-m68k.c	2001/10/17 12:01:05	1.29
+++ elf32-m68k.c	2001/11/08 13:36:54
@@ -1644,6 +1644,7 @@ elf_m68k_relocate_section (output_bfd, i
 	case R_68K_16:
 	case R_68K_32:
 	  if (info->shared
+	      && r_symndx != 0
 	      && (input_section->flags & SEC_ALLOC) != 0
 	      && ((r_type != R_68K_PC8
 		   && r_type != R_68K_PC16
Index: bfd/elf32-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-mips.c,v
retrieving revision 1.123
diff -u -p -r1.123 elf32-mips.c
--- elf32-mips.c	2001/11/02 19:46:59	1.123
+++ elf32-mips.c	2001/11/08 13:37:01
@@ -6325,6 +6325,7 @@ mips_elf_calculate_relocation (abfd,
 		    & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
 	       && ((h->root.elf_link_hash_flags
 		    & ELF_LINK_HASH_DEF_REGULAR) == 0)))
+	  && r_symndx != 0
 	  && (input_section->flags & SEC_ALLOC) != 0)
 	{
 	  /* If we're creating a shared library, or this relocation is
Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.34
diff -u -p -r1.34 elf32-ppc.c
--- elf32-ppc.c	2001/10/19 02:11:04	1.34
+++ elf32-ppc.c	2001/11/08 13:37:03
@@ -3175,7 +3175,7 @@ ppc_elf_relocate_section (output_bfd, in
 	case (int) R_PPC_ADDR14:
 	case (int) R_PPC_UADDR32:
 	case (int) R_PPC_UADDR16:
-	  if (info->shared)
+	  if (info->shared && r_symndx != 0)
 	    {
 	      Elf_Internal_Rela outrel;
 	      boolean skip;
Index: bfd/elf32-s390.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-s390.c,v
retrieving revision 1.10
diff -u -p -r1.10 elf32-s390.c
--- elf32-s390.c	2001/10/15 07:28:45	1.10
+++ elf32-s390.c	2001/11/08 13:37:05
@@ -1606,6 +1606,7 @@ elf_s390_relocate_section (output_bfd, i
         case R_390_PC16DBL:
         case R_390_PC32:
           if (info->shared
+	      && r_symndx != 0
               && (input_section->flags & SEC_ALLOC) != 0
               && ((r_type != R_390_PC16 &&
                    r_type != R_390_PC16DBL &&
Index: bfd/elf32-sh.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sh.c,v
retrieving revision 1.37
diff -u -p -r1.37 elf32-sh.c
--- elf32-sh.c	2001/10/17 12:01:05	1.37
+++ elf32-sh.c	2001/11/08 13:37:08
@@ -3216,6 +3216,7 @@ sh_elf_relocate_section (output_bfd, inf
 	case R_SH_DIR32:
 	case R_SH_REL32:
 	  if (info->shared
+	      && r_symndx != 0
 	      && (input_section->flags & SEC_ALLOC) != 0
 	      && (r_type != R_SH_REL32
 		  || (h != NULL
Index: bfd/elf32-sparc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sparc.c,v
retrieving revision 1.28
diff -u -p -r1.28 elf32-sparc.c
--- elf32-sparc.c	2001/09/24 01:38:31	1.28
+++ elf32-sparc.c	2001/11/08 13:37:10
@@ -1409,7 +1409,9 @@ elf32_sparc_relocate_section (output_bfd
 	case R_SPARC_LO10:
 	case R_SPARC_UA16:
 	case R_SPARC_UA32:
-	  if (info->shared && (input_section->flags & SEC_ALLOC))
+	  if (info->shared
+	      && r_symndx != 0
+	      && (input_section->flags & SEC_ALLOC))
 	    {
 	      Elf_Internal_Rela outrel;
 	      boolean skip;
Index: bfd/elf64-alpha.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-alpha.c,v
retrieving revision 1.45
diff -u -p -r1.45 elf64-alpha.c
--- elf64-alpha.c	2001/10/17 12:01:05	1.45
+++ elf64-alpha.c	2001/11/08 13:37:13
@@ -3516,7 +3516,9 @@ elf64_alpha_relocate_section (output_bfd
 		outrel.r_addend = addend;
 		addend = 0, relocation = 0;
 	      }
-	    else if (info->shared && (input_section->flags & SEC_ALLOC))
+	    else if (info->shared
+		     && r_symndx != 0
+		     && (input_section->flags & SEC_ALLOC))
 	      {
 		outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE);
 		outrel.r_addend = relocation + addend;
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.10
diff -u -p -r1.10 elf64-ppc.c
--- elf64-ppc.c	2001/11/01 05:35:10	1.10
+++ elf64-ppc.c	2001/11/08 13:37:15
@@ -1639,6 +1639,9 @@ struct ppc_link_hash_table
   asection *sdynbss;
   asection *srelbss;
   asection *sglink;
+
+  /* Small local sym to section mapping cache.  */
+  struct sym_sec_cache sym_sec;
 };
 
 /* Get the ppc64 ELF linker hash table from a link_info structure.  */
@@ -1701,6 +1704,7 @@ ppc64_elf_link_hash_table_create (abfd)
   htab->sdynbss = NULL;
   htab->srelbss = NULL;
   htab->sglink = NULL;
+  htab->sym_sec.abfd = NULL;
 
   return &htab->elf.root;
 }
@@ -2035,6 +2039,9 @@ ppc64_elf_check_relocs (abfd, info, sec,
 		      || (h->elf_link_hash_flags
 			  & ELF_LINK_HASH_DEF_REGULAR) == 0)))
 	    {
+	      struct ppc_dyn_relocs *p;
+	      struct ppc_dyn_relocs **head;
+
 	      /* We must copy these reloc types into the output file.
 		 Create a reloc section in dynobj and make room for
 		 this reloc.  */
@@ -2085,35 +2092,42 @@ ppc64_elf_check_relocs (abfd, info, sec,
 		 relocations we need for this symbol.  */
 	      if (h != NULL)
 		{
-		  struct ppc_link_hash_entry *eh;
-		  struct ppc_dyn_relocs *p;
-
-		  eh = (struct ppc_link_hash_entry *) h;
-		  p = eh->dyn_relocs;
-
-		  if (p == NULL || p->sec != sec)
-		    {
-		      p = ((struct ppc_dyn_relocs *)
-			   bfd_alloc (htab->elf.dynobj,
-				      (bfd_size_type) sizeof *p));
-		      if (p == NULL)
-			return false;
-		      p->next = eh->dyn_relocs;
-		      eh->dyn_relocs = p;
-		      p->sec = sec;
-		      p->count = 0;
-		      p->pc_count = 0;
-		    }
-
-		  p->count += 1;
-		  if (!IS_ABSOLUTE_RELOC (r_type))
-		    p->pc_count += 1;
+		  head = &((struct ppc_link_hash_entry *) h)->dyn_relocs;
 		}
 	      else
 		{
-		  /* Track dynamic relocs needed for local syms too.  */
-		  elf_section_data (sec)->local_dynrel += 1;
+		  /* Track dynamic relocs needed for local syms too.
+		     We really need local syms available to do this
+		     easily.  Oh well.  */
+
+		  asection *s;
+		  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
+						 sec, r_symndx);
+		  if (s == NULL)
+		    return false;
+
+		  head = ((struct ppc_dyn_relocs **)
+			  &elf_section_data (s)->local_dynrel);
 		}
+
+	      p = *head;
+	      if (p == NULL || p->sec != sec)
+		{
+		  p = ((struct ppc_dyn_relocs *)
+		       bfd_alloc (htab->elf.dynobj,
+				  (bfd_size_type) sizeof *p));
+		  if (p == NULL)
+		    return false;
+		  p->next = *head;
+		  *head = p;
+		  p->sec = sec;
+		  p->count = 0;
+		  p->pc_count = 0;
+		}
+
+	      p->count += 1;
+	      if (!IS_ABSOLUTE_RELOC (r_type))
+		p->pc_count += 1;
 	    }
 	  break;
 
@@ -2190,6 +2204,8 @@ ppc64_elf_gc_sweep_hook (abfd, info, sec
   bfd_signed_vma *local_got_refcounts;
   const Elf_Internal_Rela *rel, *relend;
 
+  elf_section_data (sec)->local_dynrel = NULL;
+
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
   local_got_refcounts = elf_local_got_refcounts (abfd);
@@ -2660,7 +2676,7 @@ allocate_dynrelocs (h, inf)
 	  if (h->dynindx == -1
 	      && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
 	    {
-	      if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+	      if (! bfd_elf64_link_record_dynamic_symbol (info, h))
 		return false;
 	    }
 
@@ -2672,7 +2688,7 @@ allocate_dynrelocs (h, inf)
 
       eh->dyn_relocs = NULL;
 
-    keep:
+    keep: ;
     }
 
   /* Finally, allocate space.  */
@@ -2759,12 +2775,26 @@ ppc64_elf_size_dynamic_sections (output_
 
       for (s = ibfd->sections; s != NULL; s = s->next)
 	{
-	  bfd_size_type count = elf_section_data (s)->local_dynrel;
+	  struct ppc_dyn_relocs *p;
 
-	  if (count != 0)
+	  for (p = *((struct ppc_dyn_relocs **)
+		     &elf_section_data (s)->local_dynrel);
+	       p != NULL;
+	       p = p->next)
 	    {
-	      srel = elf_section_data (s)->sreloc;
-	      srel->_raw_size += count * sizeof (Elf64_External_Rela);
+	      if (!bfd_is_abs_section (p->sec)
+		  && bfd_is_abs_section (p->sec->output_section))
+		{
+		  /* Input section has been discarded, either because
+		     it is a copy of a linkonce section or due to
+		     linker script /DISCARD/, so we'll be discarding
+		     the relocs too.  */
+		}
+	      else
+		{
+		  srel = elf_section_data (p->sec)->sreloc;
+		  srel->_raw_size += p->count * sizeof (Elf64_External_Rela);
+		}
 	    }
 	}
 
@@ -3429,8 +3459,14 @@ ppc64_elf_relocate_section (output_bfd, 
 	case R_PPC64_UADDR32:
 	case R_PPC64_UADDR64:
 	case R_PPC64_TOC:
+	  /* r_symndx will be zero only for relocs against symbols
+	     from removed linkonce sections, or sections discarded by
+	     a linker script.  */
+	  if (r_symndx == 0
+	      || (input_section->flags & SEC_ALLOC) == 0)
+	    break;
+
 	  if ((info->shared
-	       && (input_section->flags & SEC_ALLOC) != 0
 	       && (IS_ABSOLUTE_RELOC (r_type)
 		   || (h != NULL
 		       && h->dynindx != -1
@@ -3438,7 +3474,6 @@ ppc64_elf_relocate_section (output_bfd, 
 			   || (h->elf_link_hash_flags
 			       & ELF_LINK_HASH_DEF_REGULAR) == 0))))
 	      || (!info->shared
-		  && (input_section->flags & SEC_ALLOC) != 0
 		  && h != NULL
 		  && h->dynindx != -1
 		  && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
Index: bfd/elf64-s390.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-s390.c,v
retrieving revision 1.10
diff -u -p -r1.10 elf64-s390.c
--- elf64-s390.c	2001/10/15 07:28:45	1.10
+++ elf64-s390.c	2001/11/08 13:37:18
@@ -1609,6 +1609,7 @@ elf_s390_relocate_section (output_bfd, i
 	case R_390_PC32DBL:
         case R_390_PC64:
           if (info->shared
+	      && r_symndx != 0
               && (input_section->flags & SEC_ALLOC) != 0
               && (r_type == R_390_8
                   || r_type == R_390_16
Index: bfd/elf64-sparc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-sparc.c,v
retrieving revision 1.38
diff -u -p -r1.38 elf64-sparc.c
--- elf64-sparc.c	2001/09/25 22:12:29	1.38
+++ elf64-sparc.c	2001/11/08 13:37:20
@@ -2103,7 +2103,7 @@ sparc64_elf_relocate_section (output_bfd
 
       /* When generating a shared object, these relocations are copied
 	 into the output file to be resolved at run time.  */
-      if (info->shared && (input_section->flags & SEC_ALLOC))
+      if (info->shared && r_symndx != 0 && (input_section->flags & SEC_ALLOC))
 	{
 	  switch (r_type)
 	    {
Index: bfd/elf64-x86-64.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-x86-64.c,v
retrieving revision 1.30
diff -u -p -r1.30 elf64-x86-64.c
--- elf64-x86-64.c	2001/10/15 07:28:45	1.30
+++ elf64-x86-64.c	2001/11/08 13:37:21
@@ -1442,7 +1442,9 @@ elf64_x86_64_relocate_section (output_bf
 	case R_X86_64_64:
 	  /* FIXME: The ABI says the linker should make sure the value is
 	     the same when it's zeroextended to 64 bit.	 */
-	  if (info->shared && (input_section->flags & SEC_ALLOC) != 0)
+	  if (info->shared
+	      && r_symndx != 0
+	      && (input_section->flags & SEC_ALLOC) != 0)
 	    {
 	      Elf_Internal_Rela outrel;
 	      boolean skip, relocate;
Index: bfd/elflink.h
===================================================================
RCS file: /cvs/src/src/bfd/elflink.h,v
retrieving revision 1.121
diff -u -p -r1.121 elflink.h
--- elflink.h	2001/11/07 04:07:09	1.121
+++ elflink.h	2001/11/08 13:37:29
@@ -6135,8 +6135,15 @@ elf_link_input_bfd (finfo, input_bfd)
 	    relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
 	    for ( ; rel < relend; rel++)
 	      {
-		unsigned long r_symndx = ELF_R_SYM (rel->r_info);
+		unsigned long r_symndx;
 
+		if (rel->r_info == 0)
+		  /* See elf_gc_smash_unused_vtentry_relocs.  */
+		  continue;
+
+		r_symndx = ELF_R_SYM (rel->r_info);
+		BFD_ASSERT (r_symndx != 0);
+
 		if (r_symndx >= locsymcount
 		    || (elf_bad_symtab (input_bfd)
 			&& finfo->sections[r_symndx] == NULL))
@@ -6199,7 +6206,9 @@ elf_link_input_bfd (finfo, input_bfd)
 				   _("warning: relocation against removed section"),
 				   NULL, input_bfd, o, rel->r_offset);
 #endif
-				memset (rel, 0, sizeof (*rel));
+				rel->r_info
+				  = ELF_R_INFO (0, ELF_R_TYPE (rel->r_info));
+				rel->r_addend = 0;
 			      }
 			    else
 #endif
Index: bfd/elfxx-ia64.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-ia64.c,v
retrieving revision 1.30
diff -u -p -r1.30 elfxx-ia64.c
--- elfxx-ia64.c	2001/10/17 12:01:05	1.30
+++ elfxx-ia64.c	2001/11/08 13:37:31
@@ -3560,6 +3560,7 @@ elfNN_ia64_relocate_section (output_bfd,
 		   /* Don't emit relocs for __GLOB_DATA_PTR on AIX. */
 		   && (!h || strcmp (h->root.root.string,
 				     "__GLOB_DATA_PTR") != 0)))
+	      && r_symndx != 0
 	      && (input_section->flags & SEC_ALLOC) != 0)
 	    {
 	      unsigned int dyn_r_type;
@@ -3754,8 +3755,9 @@ elfNN_ia64_relocate_section (output_bfd,
 	case R_IA64_PCREL64MSB:
 	case R_IA64_PCREL64LSB:
 	  /* Install a dynamic relocation for this reloc.  */
-	  if (dynamic_symbol_p
-	      || elfNN_ia64_aix_vec (info->hash->creator))
+	  if ((dynamic_symbol_p
+	       || elfNN_ia64_aix_vec (info->hash->creator))
+	      && r_symndx != 0)
 	    {
 	      BFD_ASSERT (srel != NULL);
 


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