PR 5604 fix

Alan Modra amodra@bigpond.net.au
Thu Jan 17 00:52:00 GMT 2008


This patch fixes both the issues identified in PR 5604.
a) The mapping from offset to destination section kept for .opd
sections in struct _ppc64_elf_section_data now needs to persist past
the point where we reused the space for something else, and
b) Use of gc_mark_hook by the .eh_frame editing code means we really
need to fire off marking of sections in a separate function rather
than the hack I added to ppc64_elf_gc_mark_hook.

bfd/
	PR 5604
	* elf-bfd.h (struct elf_backend_data): Add gc_keep.  Remove param
	names from others.
	(_bfd_elf_gc_keep): Declare.
	* elfxx-target.h (elf_backend_gc_keep): Define.
	(elfNN_bed): Init new field.
	* elflink.c (_bfd_elf_gc_keep): New function.
	(bfd_elf_gc_sections): Call gc_keep.
	* elf64-ppc.c (elf_backend_gc_keep): Define.
	(struct _ppc64_elf_section_data): Move .opd related fields to
	a struct so they don't occupy the same storage.  Adjust accesses
	throughout file.
	(ppc64_elf_gc_keep): New function, split out from..
	(ppc64_elf_gc_mark_hook): ..here.  Don't call _bfd_elf_gc_mark
	to mark .opd section, just set gc_mark.
	(ppc64_elf_edit_opd): Remove no_opd_opt parm.  Don't set opd->adjust
	unless we are changing .opd.  Test non-NULL opd->adjust at all
	accesses throughout file.
	* elf64-ppc.h (ppc64_elf_edit_opd): Update prototype.
ld/
	PR 5604
	* ldlang.c (lang_gc_sections): Move code to set SEC_KEEP on entry
	syms to _bfd_elf_gc_keep.
	* emultempl/ppc64elf.em (ppc_before_allocation): Don't call
	ppc64_elf_edit_opd if no_opd_opt.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.256
diff -u -p -r1.256 elf-bfd.h
--- bfd/elf-bfd.h	9 Jan 2008 09:36:11 -0000	1.256
+++ bfd/elf-bfd.h	15 Jan 2008 00:37:08 -0000
@@ -915,10 +915,15 @@ struct elf_backend_data
   bfd_boolean (*elf_backend_modify_program_headers)
     (bfd *, struct bfd_link_info *);
 
+  /* This function is called before section garbage collection to
+     mark entry symbol sections.  */
+  void (*gc_keep)
+    (struct bfd_link_info *);
+
   /* This function is called during section garbage collection to
      mark sections that define global symbols.  */
   bfd_boolean (*gc_mark_dynamic_ref)
-    (struct elf_link_hash_entry *h, void *inf);
+    (struct elf_link_hash_entry *, void *);
 
   /* This function is called during section gc to discover the section a
      particular relocation refers to.  */
@@ -927,14 +932,13 @@ struct elf_backend_data
   /* This function, if defined, is called after the first gc marking pass
      to allow the backend to mark additional sections.  */
   bfd_boolean (*gc_mark_extra_sections)
-    (struct bfd_link_info *info, elf_gc_mark_hook_fn gc_mark_hook);
+    (struct bfd_link_info *, elf_gc_mark_hook_fn);
 
   /* This function, if defined, is called during the sweep phase of gc
      in order that a backend might update any data structures it might
      be maintaining.  */
   bfd_boolean (*gc_sweep_hook)
-    (bfd *abfd, struct bfd_link_info *info, asection *o,
-     const Elf_Internal_Rela *relocs);
+    (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
 
   /* This function, if defined, is called after the ELF headers have
      been created.  This allows for things like the OS and ABI versions
@@ -2034,6 +2038,9 @@ extern bfd_reloc_status_type _bfd_elf_re
 extern bfd_boolean bfd_elf_final_link
   (bfd *, struct bfd_link_info *);
 
+extern void _bfd_elf_gc_keep
+  (struct bfd_link_info *info);
+
 extern bfd_boolean bfd_elf_gc_mark_dynamic_ref_symbol
   (struct elf_link_hash_entry *h, void *inf);
 
Index: bfd/elfxx-target.h
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-target.h,v
retrieving revision 1.111
diff -u -p -r1.111 elfxx-target.h
--- bfd/elfxx-target.h	18 Oct 2007 09:13:50 -0000	1.111
+++ bfd/elfxx-target.h	15 Jan 2008 00:37:20 -0000
@@ -132,6 +132,9 @@
 #ifndef elf_backend_want_got_sym
 #define elf_backend_want_got_sym 1
 #endif
+#ifndef elf_backend_gc_keep
+#define elf_backend_gc_keep		_bfd_elf_gc_keep
+#endif
 #ifndef elf_backend_gc_mark_dynamic_ref
 #define elf_backend_gc_mark_dynamic_ref	bfd_elf_gc_mark_dynamic_ref_symbol
 #endif
@@ -656,6 +659,7 @@ static struct elf_backend_data elfNN_bed
   elf_backend_additional_program_headers,
   elf_backend_modify_segment_map,
   elf_backend_modify_program_headers,
+  elf_backend_gc_keep,
   elf_backend_gc_mark_dynamic_ref,
   elf_backend_gc_mark_hook,
   elf_backend_gc_mark_extra_sections,
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.292
diff -u -p -r1.292 elflink.c
--- bfd/elflink.c	11 Jan 2008 09:07:04 -0000	1.292
+++ bfd/elflink.c	15 Jan 2008 00:37:19 -0000
@@ -11463,6 +11463,29 @@ bfd_elf_gc_mark_dynamic_ref_symbol (stru
   return TRUE;
 }
 
+/* Keep all sections containing symbols undefined on the command-line,
+   and the section containing the entry symbol.  */
+
+void
+_bfd_elf_gc_keep (struct bfd_link_info *info)
+{
+  struct bfd_sym_chain *sym;
+
+  for (sym = info->gc_sym_list; sym != NULL; sym = sym->next)
+    {
+      struct elf_link_hash_entry *h;
+
+      h = elf_link_hash_lookup (elf_hash_table (info), sym->name,
+				FALSE, FALSE, FALSE);
+
+      if (h != NULL
+	  && (h->root.type == bfd_link_hash_defined
+	      || h->root.type == bfd_link_hash_defweak)
+	  && !bfd_is_abs_section (h->root.u.def.section))
+	h->root.u.def.section->flags |= SEC_KEEP;
+    }
+}
+
 /* Do mark and sweep of unused sections.  */
 
 bfd_boolean
@@ -11480,6 +11503,8 @@ bfd_elf_gc_sections (bfd *abfd, struct b
       return TRUE;
     }
 
+  bed->gc_keep (info);
+
   /* Try to parse each bfd's .eh_frame section.  Point elf_eh_frame_section
      at the .eh_frame section if we can mark the FDEs individually.  */
   _bfd_elf_begin_eh_frame_parsing (info);
@@ -11536,7 +11561,7 @@ bfd_elf_gc_sections (bfd *abfd, struct b
 
   /* Allow the backend to mark additional target specific sections.  */
   if (bed->gc_mark_extra_sections)
-    bed->gc_mark_extra_sections(info, gc_mark_hook);
+    bed->gc_mark_extra_sections (info, gc_mark_hook);
 
   /* ... and mark SEC_EXCLUDE for those that go.  */
   return elf_gc_sweep (abfd, info);
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.272
diff -u -p -r1.272 elf64-ppc.c
--- bfd/elf64-ppc.c	11 Jan 2008 09:07:04 -0000	1.272
+++ bfd/elf64-ppc.c	15 Jan 2008 00:37:13 -0000
@@ -96,6 +96,7 @@ static bfd_vma opd_entry_value
 #define elf_backend_as_needed_cleanup	      ppc64_elf_as_needed_cleanup
 #define elf_backend_archive_symbol_lookup     ppc64_elf_archive_symbol_lookup
 #define elf_backend_check_relocs	      ppc64_elf_check_relocs
+#define elf_backend_gc_keep		      ppc64_elf_gc_keep
 #define elf_backend_gc_mark_dynamic_ref       ppc64_elf_gc_mark_dynamic_ref
 #define elf_backend_gc_mark_hook	      ppc64_elf_gc_mark_hook
 #define elf_backend_gc_sweep_hook	      ppc64_elf_gc_sweep_hook
@@ -2608,13 +2609,17 @@ struct _ppc64_elf_section_data
 {
   struct bfd_elf_section_data elf;
 
-  /* An array with one entry for each opd function descriptor.  */
   union
   {
-    /* Points to the function code section for local opd entries.  */
-    asection **opd_func_sec;
-    /* After editing .opd, adjust references to opd local syms.  */
-    long *opd_adjust;
+    /* An array with one entry for each opd function descriptor.  */
+    struct _opd_sec_data
+    {
+      /* Points to the function code section for local opd entries.  */
+      asection **func_sec;
+
+      /* After editing .opd, adjust references to opd local syms.  */
+      long *adjust;
+    } opd;
 
     /* An array for toc sections, indexed by offset/8.
        Specifies the relocation symbol index used at a given toc offset.  */
@@ -2648,13 +2653,13 @@ ppc64_elf_new_section_hook (bfd *abfd, a
   return _bfd_elf_new_section_hook (abfd, sec);
 }
 
-static void *
+static struct _opd_sec_data *
 get_opd_info (asection * sec)
 {
   if (sec != NULL
       && ppc64_elf_section_data (sec) != NULL
       && ppc64_elf_section_data (sec)->sec_type == sec_opd)
-    return ppc64_elf_section_data (sec)->u.opd_adjust;
+    return &ppc64_elf_section_data (sec)->u.opd;
   return NULL;
 }
 
@@ -4438,20 +4443,14 @@ ppc64_elf_check_relocs (bfd *abfd, struc
 	 if we reference an .opd symbol (a function descriptor), we
 	 want to keep the function code symbol's section.  This is
 	 easy for global symbols, but for local syms we need to keep
-	 information about the associated function section.  Later, if
-	 edit_opd deletes entries, we'll use this array to adjust
-	 local syms in .opd.  */
-      union opd_info {
-	asection *func_section;
-	long entry_adjust;
-      };
+	 information about the associated function section.  */
       bfd_size_type amt;
 
-      amt = sec->size * sizeof (union opd_info) / 8;
+      amt = sec->size * sizeof (*opd_sym_map) / 8;
       opd_sym_map = bfd_zalloc (abfd, amt);
       if (opd_sym_map == NULL)
 	return FALSE;
-      ppc64_elf_section_data (sec)->u.opd_func_sec = opd_sym_map;
+      ppc64_elf_section_data (sec)->u.opd.func_sec = opd_sym_map;
       BFD_ASSERT (ppc64_elf_section_data (sec)->sec_type == sec_normal);
       ppc64_elf_section_data (sec)->sec_type = sec_opd;
     }
@@ -5069,6 +5068,45 @@ opd_entry_value (asection *opd_sec,
   return val;
 }
 
+/* Mark all our entry sym sections, both opd and code section.  */
+
+static void
+ppc64_elf_gc_keep (struct bfd_link_info *info)
+{
+  struct ppc_link_hash_table *htab = ppc_hash_table (info);
+  struct bfd_sym_chain *sym;
+
+  for (sym = info->gc_sym_list; sym != NULL; sym = sym->next)
+    {
+      struct ppc_link_hash_entry *eh;
+      asection *sec;
+
+      eh = (struct ppc_link_hash_entry *)
+	elf_link_hash_lookup (&htab->elf, sym->name, FALSE, FALSE, FALSE);
+      if (eh == NULL)
+	continue;
+      if (eh->elf.root.type != bfd_link_hash_defined
+	  && eh->elf.root.type != bfd_link_hash_defweak)
+	continue;
+
+      if (eh->is_func_descriptor
+	  && (eh->oh->elf.root.type == bfd_link_hash_defined
+	      || eh->oh->elf.root.type == bfd_link_hash_defweak))
+	{
+	  sec = eh->oh->elf.root.u.def.section;
+	  sec->flags |= SEC_KEEP;
+	}
+      else if (get_opd_info (eh->elf.root.u.def.section) != NULL
+	       && opd_entry_value (eh->elf.root.u.def.section,
+				   eh->elf.root.u.def.value,
+				   &sec, NULL) != (bfd_vma) -1)
+	sec->flags |= SEC_KEEP;
+
+      sec = eh->elf.root.u.def.section;
+      sec->flags |= SEC_KEEP;
+    }
+}
+
 /* Mark sections containing dynamically referenced symbols.  When
    building shared libraries, we must assume that any visible symbol is
    referenced.  */
@@ -5122,53 +5160,13 @@ ppc64_elf_gc_mark_dynamic_ref (struct el
 
 static asection *
 ppc64_elf_gc_mark_hook (asection *sec,
-			struct bfd_link_info *info,
+			struct bfd_link_info *info ATTRIBUTE_UNUSED,
 			Elf_Internal_Rela *rel,
 			struct elf_link_hash_entry *h,
 			Elf_Internal_Sym *sym)
 {
   asection *rsec;
 
-  /* First mark all our entry sym sections.  */
-  if (info->gc_sym_list != NULL)
-    {
-      struct ppc_link_hash_table *htab = ppc_hash_table (info);
-      struct bfd_sym_chain *sym = info->gc_sym_list;
-
-      info->gc_sym_list = NULL;
-      for (; sym != NULL; sym = sym->next)
-	{
-	  struct ppc_link_hash_entry *eh;
-
-	  eh = (struct ppc_link_hash_entry *)
-	    elf_link_hash_lookup (&htab->elf, sym->name, FALSE, FALSE, FALSE);
-	  if (eh == NULL)
-	    continue;
-	  if (eh->elf.root.type != bfd_link_hash_defined
-	      && eh->elf.root.type != bfd_link_hash_defweak)
-	    continue;
-
-	  if (eh->is_func_descriptor
-	      && (eh->oh->elf.root.type == bfd_link_hash_defined
-		  || eh->oh->elf.root.type == bfd_link_hash_defweak))
-	    rsec = eh->oh->elf.root.u.def.section;
-	  else if (get_opd_info (eh->elf.root.u.def.section) != NULL
-		   && opd_entry_value (eh->elf.root.u.def.section,
-				       eh->elf.root.u.def.value,
-				       &rsec, NULL) != (bfd_vma) -1)
-	    ;
-	  else
-	    continue;
-
-	  if (!rsec->gc_mark)
-	    _bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook);
-
-	  rsec = eh->elf.root.u.def.section;
-	  if (!rsec->gc_mark)
-	    _bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook);
-	}
-    }
-
   /* Syms return NULL if we're marking .opd, so we avoid marking all
      function sections, as all functions are referenced in .opd.  */
   rsec = NULL;
@@ -5206,9 +5204,7 @@ ppc64_elf_gc_mark_hook (asection *sec,
 		      || eh->oh->elf.root.type == bfd_link_hash_defweak))
 		{
 		  /* They also mark their opd section.  */
-		  if (!eh->elf.root.u.def.section->gc_mark)
-		    _bfd_elf_gc_mark (info, eh->elf.root.u.def.section,
-				      ppc64_elf_gc_mark_hook);
+		  eh->elf.root.u.def.section->gc_mark = 1;
 
 		  rsec = eh->oh->elf.root.u.def.section;
 		}
@@ -5216,11 +5212,7 @@ ppc64_elf_gc_mark_hook (asection *sec,
 		       && opd_entry_value (eh->elf.root.u.def.section,
 					   eh->elf.root.u.def.value,
 					   &rsec, NULL) != (bfd_vma) -1)
-		{
-		  if (!eh->elf.root.u.def.section->gc_mark)
-		    _bfd_elf_gc_mark (info, eh->elf.root.u.def.section,
-				      ppc64_elf_gc_mark_hook);
-		}
+		eh->elf.root.u.def.section->gc_mark = 1;
 	      else
 		rsec = h->root.u.def.section;
 	      break;
@@ -5236,16 +5228,15 @@ ppc64_elf_gc_mark_hook (asection *sec,
     }
   else
     {
-      asection **opd_sym_section;
+      struct _opd_sec_data *opd;
 
       rsec = bfd_section_from_elf_index (sec->owner, sym->st_shndx);
-      opd_sym_section = get_opd_info (rsec);
-      if (opd_sym_section != NULL)
+      opd = get_opd_info (rsec);
+      if (opd != NULL && opd->func_sec != NULL)
 	{
-	  if (!rsec->gc_mark)
-	    _bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook);
+	  rsec->gc_mark = 1;
 
-	  rsec = opd_sym_section[(sym->st_value + rel->r_addend) / 8];
+	  rsec = opd->func_sec[(sym->st_value + rel->r_addend) / 8];
 	}
     }
 
@@ -6159,7 +6150,7 @@ adjust_opd_syms (struct elf_link_hash_en
 {
   struct ppc_link_hash_entry *eh;
   asection *sym_sec;
-  long *opd_adjust;
+  struct _opd_sec_data *opd;
 
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
@@ -6176,10 +6167,10 @@ adjust_opd_syms (struct elf_link_hash_en
     return TRUE;
 
   sym_sec = eh->elf.root.u.def.section;
-  opd_adjust = get_opd_info (sym_sec);
-  if (opd_adjust != NULL)
+  opd = get_opd_info (sym_sec);
+  if (opd != NULL && opd->adjust != NULL)
     {
-      long adjust = opd_adjust[eh->elf.root.u.def.value / 8];
+      long adjust = opd->adjust[eh->elf.root.u.def.value / 8];
       if (adjust == -1)
 	{
 	  /* This entry has been deleted.  */
@@ -6345,7 +6336,6 @@ dec_dynrel_count (bfd_vma r_info,
 
 bfd_boolean
 ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
-		    bfd_boolean no_opd_opt,
 		    bfd_boolean non_overlapping)
 {
   bfd *ibfd;
@@ -6360,8 +6350,7 @@ ppc64_elf_edit_opd (bfd *obfd, struct bf
       Elf_Internal_Sym *local_syms;
       struct elf_link_hash_entry **sym_hashes;
       bfd_vma offset;
-      bfd_size_type amt;
-      long *opd_adjust;
+      struct _opd_sec_data *opd;
       bfd_boolean need_edit, add_aux_fields;
       bfd_size_type cnt_16b = 0;
 
@@ -6369,24 +6358,6 @@ ppc64_elf_edit_opd (bfd *obfd, struct bf
       if (sec == NULL || sec->size == 0)
 	continue;
 
-      amt = sec->size * sizeof (long) / 8;
-      opd_adjust = get_opd_info (sec);
-      if (opd_adjust == NULL)
-	{
-	  /* check_relocs hasn't been called.  Must be a ld -r link
-	     or --just-symbols object.   */
-	  opd_adjust = bfd_alloc (obfd, amt);
-	  if (opd_adjust == NULL)
-	    return FALSE;
-	  ppc64_elf_section_data (sec)->u.opd_adjust = opd_adjust;
-	  BFD_ASSERT (ppc64_elf_section_data (sec)->sec_type == sec_normal);
-	  ppc64_elf_section_data (sec)->sec_type = sec_opd;
-	}
-      memset (opd_adjust, 0, amt);
-
-      if (no_opd_opt)
-	continue;
-
       if (sec->sec_info_type == ELF_INFO_TYPE_JUST_SYMS)
 	continue;
 
@@ -6530,6 +6501,14 @@ ppc64_elf_edit_opd (bfd *obfd, struct bf
 	  bfd_byte *new_contents = NULL;
 	  bfd_boolean skip;
 	  long opd_ent_size;
+	  bfd_size_type amt;
+
+	  amt = sec->size * sizeof (long) / 8;
+	  opd = &ppc64_elf_section_data (sec)->u.opd;
+	  opd->adjust = bfd_zalloc (obfd, amt);
+	  if (opd->adjust == NULL)
+	    return FALSE;
+	  ppc64_elf_section_data (sec)->sec_type = sec_opd;
 
 	  /* This seems a waste of time as input .opd sections are all
 	     zeros as generated by gcc, but I suppose there's no reason
@@ -6621,7 +6600,7 @@ ppc64_elf_edit_opd (bfd *obfd, struct bf
 			  fdh->elf.root.u.def.value = 0;
 			  fdh->elf.root.u.def.section = sym_sec;
 			}
-		      opd_adjust[rel->r_offset / 8] = -1;
+		      opd->adjust[rel->r_offset / 8] = -1;
 		    }
 		  else
 		    {
@@ -6646,7 +6625,7 @@ ppc64_elf_edit_opd (bfd *obfd, struct bf
 			 for the function descriptor sym which we
 			 don't have at the moment.  So keep an
 			 array of adjustments.  */
-		      opd_adjust[rel->r_offset / 8]
+		      opd->adjust[rel->r_offset / 8]
 			= (wptr - new_contents) - (rptr - sec->contents);
 
 		      if (wptr != rptr)
@@ -6675,7 +6654,7 @@ ppc64_elf_edit_opd (bfd *obfd, struct bf
 		  /* We need to adjust any reloc offsets to point to the
 		     new opd entries.  While we're at it, we may as well
 		     remove redundant relocs.  */
-		  rel->r_offset += opd_adjust[(offset - opd_ent_size) / 8];
+		  rel->r_offset += opd->adjust[(offset - opd_ent_size) / 8];
 		  if (write_rel != rel)
 		    memcpy (write_rel, rel, sizeof (*rel));
 		  ++write_rel;
@@ -8964,7 +8943,7 @@ toc_adjusting_stub_needed (struct bfd_li
       struct elf_link_hash_entry *h;
       Elf_Internal_Sym *sym;
       asection *sym_sec;
-      long *opd_adjust;
+      struct _opd_sec_data *opd;
       bfd_vma sym_value;
       bfd_vma dest;
 
@@ -9022,14 +9001,14 @@ toc_adjusting_stub_needed (struct bfd_li
       sym_value += rel->r_addend;
 
       /* If this branch reloc uses an opd sym, find the code section.  */
-      opd_adjust = get_opd_info (sym_sec);
-      if (opd_adjust != NULL)
+      opd = get_opd_info (sym_sec);
+      if (opd != NULL)
 	{
-	  if (h == NULL)
+	  if (h == NULL && opd->adjust != NULL)
 	    {
 	      long adjust;
 
-	      adjust = opd_adjust[sym->st_value / 8];
+	      adjust = opd->adjust[sym->st_value / 8];
 	      if (adjust == -1)
 		/* Assume deleted functions won't ever be called.  */
 		continue;
@@ -9384,7 +9363,7 @@ ppc64_elf_size_stubs (bfd *output_bfd,
 		  Elf_Internal_Sym *sym;
 		  char *stub_name;
 		  const asection *id_sec;
-		  long *opd_adjust;
+		  struct _opd_sec_data *opd;
 
 		  r_type = ELF64_R_TYPE (irela->r_info);
 		  r_indx = ELF64_R_SYM (irela->r_info);
@@ -9461,14 +9440,14 @@ ppc64_elf_size_stubs (bfd *output_bfd,
 		    }
 
 		  code_sec = sym_sec;
-		  opd_adjust = get_opd_info (sym_sec);
-		  if (opd_adjust != NULL)
+		  opd = get_opd_info (sym_sec);
+		  if (opd != NULL)
 		    {
 		      bfd_vma dest;
 
-		      if (hash == NULL)
+		      if (hash == NULL && opd->adjust != NULL)
 			{
-			  long adjust = opd_adjust[sym_value / 8];
+			  long adjust = opd->adjust[sym_value / 8];
 			  if (adjust == -1)
 			    continue;
 			  sym_value += adjust;
@@ -10032,17 +10011,17 @@ ppc64_elf_relocate_section (bfd *output_
       if (r_symndx < symtab_hdr->sh_info)
 	{
 	  /* It's a local symbol.  */
-	  long *opd_adjust;
+	  struct _opd_sec_data *opd;
 
 	  sym = local_syms + r_symndx;
 	  sec = local_sections[r_symndx];
 	  sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec);
 	  sym_type = ELF64_ST_TYPE (sym->st_info);
 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
-	  opd_adjust = get_opd_info (sec);
-	  if (opd_adjust != NULL)
+	  opd = get_opd_info (sec);
+	  if (opd != NULL && opd->adjust != NULL)
 	    {
-	      long adjust = opd_adjust[(sym->st_value + rel->r_addend) / 8];
+	      long adjust = opd->adjust[(sym->st_value + rel->r_addend) / 8];
 	      if (adjust == -1)
 		relocation = 0;
 	      else
@@ -11361,21 +11340,22 @@ ppc64_elf_output_symbol_hook (struct bfd
 			      asection *input_sec,
 			      struct elf_link_hash_entry *h)
 {
-  long *opd_adjust, adjust;
+  struct _opd_sec_data *opd;
+  long adjust;
   bfd_vma value;
 
   if (h != NULL)
     return TRUE;
 
-  opd_adjust = get_opd_info (input_sec);
-  if (opd_adjust == NULL)
+  opd = get_opd_info (input_sec);
+  if (opd == NULL || opd->adjust == NULL)
     return TRUE;
 
   value = elfsym->st_value - input_sec->output_offset;
   if (!info->relocatable)
     value -= input_sec->output_section->vma;
 
-  adjust = opd_adjust[value / 8];
+  adjust = opd->adjust[value / 8];
   if (adjust == -1)
     elfsym->st_value = 0;
   else
Index: bfd/elf64-ppc.h
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.h,v
retrieving revision 1.24
diff -u -p -r1.24 elf64-ppc.h
--- bfd/elf64-ppc.h	3 Jul 2007 14:26:41 -0000	1.24
+++ bfd/elf64-ppc.h	15 Jan 2008 00:37:13 -0000
@@ -21,7 +21,7 @@
 void ppc64_elf_init_stub_bfd
   (bfd *, struct bfd_link_info *);
 bfd_boolean ppc64_elf_edit_opd
-  (bfd *, struct bfd_link_info *, bfd_boolean, bfd_boolean);
+  (bfd *, struct bfd_link_info *, bfd_boolean);
 asection *ppc64_elf_tls_setup
   (bfd *, struct bfd_link_info *);
 bfd_boolean ppc64_elf_tls_optimize
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.275
diff -u -p -r1.275 ldlang.c
--- ld/ldlang.c	11 Jan 2008 09:11:17 -0000	1.275
+++ ld/ldlang.c	15 Jan 2008 00:37:40 -0000
@@ -5670,30 +5670,10 @@ lang_gc_sections_1 (lang_statement_union
 static void
 lang_gc_sections (void)
 {
-  struct bfd_link_hash_entry *h;
-  ldlang_undef_chain_list_type *ulist;
-
   /* Keep all sections so marked in the link script.  */
 
   lang_gc_sections_1 (statement_list.head);
 
-  /* Keep all sections containing symbols undefined on the command-line,
-     and the section containing the entry symbol.  */
-
-  for (ulist = link_info.gc_sym_list; ulist; ulist = ulist->next)
-    {
-      h = bfd_link_hash_lookup (link_info.hash, ulist->name,
-				FALSE, FALSE, FALSE);
-
-      if (h != NULL
-	  && (h->type == bfd_link_hash_defined
-	      || h->type == bfd_link_hash_defweak)
-	  && ! bfd_is_abs_section (h->u.def.section))
-	{
-	  h->u.def.section->flags |= SEC_KEEP;
-	}
-    }
-
   /* SEC_EXCLUDE is ignored when doing a relocatable link, except in
      the special case of debug info.  (See bfd/stabs.c)
      Twiddle the flag here, to simplify later linker code.  */
Index: ld/emultempl/ppc64elf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/ppc64elf.em,v
retrieving revision 1.56
diff -u -p -r1.56 ppc64elf.em
--- ld/emultempl/ppc64elf.em	17 Aug 2007 13:50:48 -0000	1.56
+++ ld/emultempl/ppc64elf.em	15 Jan 2008 00:37:40 -0000
@@ -103,8 +103,8 @@ ppc_before_allocation (void)
 {
   if (stub_file != NULL)
     {
-      if (!ppc64_elf_edit_opd (output_bfd, &link_info, no_opd_opt,
-			       non_overlapping_opd))
+      if (!no_opd_opt
+	  && !ppc64_elf_edit_opd (output_bfd, &link_info, non_overlapping_opd))
 	einfo ("%X%P: can not edit %s %E\n", "opd");
 
       if (ppc64_elf_tls_setup (output_bfd, &link_info) && !no_tls_opt)

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list