gc-sections on powerpc64-linux

Alan Modra amodra@bigpond.net.au
Mon Jul 1 01:04:00 GMT 2002


Garbage collecting sections on PowerPC64 isn't easy.  For starters,
the official procedure descriptor section (.opd) references all
functions in an object.  Once loose in .opd, the previous, more or
less generic ppc64_elf_gc_mark_hook code would thus mark all function
sections in an object against garbage collection.  No functions were
ever thrown away.  So we need to do something special when looking at
.opd relocs.  Unfortunately, that meant changing the arguments of
gc_mark_hook, requiring a lot of boring editing.

We can't just ignore .opd relocs though;  A reference to a function
descriptor symbol in .opd means we need to keep the corresponding
function.  Problem one is that not all of these references come from
other relocs, _start for example, comes from a linker script.  So we
need some way for code in ld/ldlang.c to pass these symbol references
to the backend bfd linker code.  That's what link_info.gc_sym_list is
about.  Problem two involves local syms in .opd.  There's no easy way
to look up local syms, apart from the brute force approach of reading
and scanning them all, so mapping between function descriptor and
function entry is tricky.  I decided to build a lookup table in
check_relocs, indexed by function descriptor sym value, and tacking
this on elf_section_data->tdata.

That just about wraps up the garbage collection angle, except that
it's not nice to leave orphan opd entries.  edit_opd rips 'em out.
Of course, this meant another lot of tweakery required with local
sym values in .opd.

bfd/ChangeLog
	* elflink.h (elf_gc_mark): Pass in the section whose relocs we are
	examining to gc_mark_hook, rather than the bfd.
	(elf_gc_sections): Adjust.
	* elf-bfd.h (struct elf_backend_data <gc_mark_hook>): Likewise.
	* elf-m10300.c (mn10300_elf_gc_mark_hook): Likewise.
	* elf32-arm.h (elf32_arm_gc_mark_hook): Likewise.
	* elf32-avr.c (elf32_avr_gc_mark_hook): Likewise.
	* elf32-cris.c (cris_elf_gc_mark_hook): Likewise.
	* elf32-d10v.c (elf32_d10v_gc_mark_hook): Likewise.
	* elf32-fr30.c (fr30_elf_gc_mark_hook): Likewise.
	* elf32-hppa.c (elf32_hppa_gc_mark_hook): Likewise.
	* elf32-i386.c (elf_i386_gc_mark_hook): Likewise.
	* elf32-m32r.c (m32r_elf_gc_mark_hook): Likewise.
	* elf32-m68k.c (elf_m68k_gc_mark_hook): Likewise.
	* elf32-mcore.c (mcore_elf_gc_mark_hook): Likewise.
	* elf32-openrisc.c (openrisc_elf_gc_mark_hook): Likewise.
	* elf32-ppc.c (ppc_elf_gc_mark_hook): Likewise.
	* elf32-s390.c (elf_s390_gc_mark_hook): Likewise.
	* elf32-sh.c (sh_elf_gc_mark_hook): Likewise.
	* elf32-sparc.c (elf32_sparc_gc_mark_hook): Likewise.
	* elf32-v850.c (v850_elf_gc_mark_hook): Likewise.
	* elf32-vax.c (elf_vax_gc_mark_hook): Likewise.
	* elf32-xstormy16.c (xstormy16_elf_gc_mark_hook): Likewise.
	* elf64-mmix.c (mmix_elf_gc_mark_hook): Likewise.
	* elf64-ppc.c (ppc64_elf_gc_mark_hook): Likewise.
	* elf64-s390.c (elf_s390_gc_mark_hook): Likewise.
	* elf64-sh64.c (sh_elf64_gc_mark_hook): Likewise.
	* elfxx-mips.c (_bfd_mips_elf_gc_mark_hook): Likewise.
	* elfxx-mips.h (_bfd_mips_elf_gc_mark_hook): Likewise.
	* elf64-x86-64.c (elf64_x86_64_gc_mark_hook): Likewise.
	* elf32-frv.c (elf32_frv_gc_mark_hook): Likewise.  Also remove
	redundant local sym tests.
	* elf64-ppc.c (struct ppc_link_hash_entry): Add is_entry.
	(link_hash_newfunc): Init is_entry.
	(ppc64_elf_copy_indirect_symbol): Copy is_entry.
	(ppc64_elf_link_hash_table_create): Init all_local_syms.
	(create_linkage_sections): Use bfd_make_section_anyway rather than
	bfd_make_section.
	(ppc64_elf_mark_entry_syms): New function.
	(ppc64_elf_check_relocs): Don't bother testing elf_bad_symtab.  Set
	up opd entry to function section map.
	(ppc64_elf_gc_mark_hook): Special case opd section relocs, and
	relocs that reference the opd section.
	(edit_opd): New function.
	(ppc64_elf_size_dynamic_sections): Call get_local_syms and edit_opd.
	(ppc64_elf_setup_section_lists): Don't calculate htab->bfd_count here.
	(get_local_syms): Do so here.  Exit if we already have local syms.
	Remove bogus comment imported from elf32-hppa.c.  Don't attempt to
	read local syms on non-ELF input.
	(ppc64_elf_size_stubs): Call _bfd_elf64_link_read_relocs rather
	than duplicating it's function here.  Adjust free of internal
	relocs to suit.
	(ppc64_elf_relocate_section): Adjust local syms in opd section.
	* elf64-ppc.h (ppc64_elf_mark_entry_syms): Declare.
	* elf32-hppa.c (elf32_hppa_size_stubs): Call
	_bfd_elf32_link_read_relocs rather than duplicating it's function
	here.  Adjust free of internal relocs to suit.

include/ChangeLog
	* bfdlink.h (struct bfd_sym_chain): Declare.
	(struct bfd_link_info): Add gc_sym_list.  Formatting fixes.

ld/ChangeLog
	* ldlang.h (entry_sym): Make it a struct bfd_sym_chain.
	* ldlang.c (entry_sym): Likewise.
	(ldlang_undef_chain_list_type): Likewise.
	(lang_finish): Adjust references to entry_symbol.
	(lang_add_entry): Likewise.
	(lang_gc_sections): Use link_info.gc_sym_list.
	(lang_process): Set link_info.gc_sym_list.
	* ldlex.l: Include bfdlink.h.
	* ldmain.c (main): Init link_info.gc_sym_list.
	* emultempl/aix.em: Adjust references to entry_symbol.
	* emultempl/armcoff.em: Likewise.
	* emultempl/armelf.em: Likewise.
	* emultempl/pe.em: Likewise.
	* emultempl/ppc64elf.em (ppc_after_open): New function.
	(LDEMUL_AFTER_OPEN): Define.
	* emulparams/elf64ppc.sh: KEEP .opd sections.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.81
diff -u -p -r1.81 elf-bfd.h
--- bfd/elf-bfd.h	25 Jun 2002 09:40:43 -0000	1.81
+++ bfd/elf-bfd.h	1 Jul 2002 07:47:09 -0000
@@ -680,10 +680,9 @@ struct elf_backend_data
     PARAMS ((bfd *));
 
   /* This function is called during section gc to discover the section a
-     particular relocation refers to.  It need not be defined for hosts
-     that have no queer relocation types.  */
+     particular relocation refers to.  */
   asection * (*gc_mark_hook)
-    PARAMS ((bfd *abfd, struct bfd_link_info *, Elf_Internal_Rela *,
+    PARAMS ((asection *sec, struct bfd_link_info *, Elf_Internal_Rela *,
 	     struct elf_link_hash_entry *h, Elf_Internal_Sym *));
 
   /* This function, if defined, is called during the sweep phase of gc
Index: bfd/elf-m10300.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-m10300.c,v
retrieving revision 1.26
diff -u -p -r1.26 elf-m10300.c
--- bfd/elf-m10300.c	6 Jun 2002 00:29:20 -0000	1.26
+++ bfd/elf-m10300.c	1 Jul 2002 07:47:11 -0000
@@ -122,7 +122,7 @@ static boolean mn10300_elf_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
 	   const Elf_Internal_Rela *));
 static asection *mn10300_elf_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *info, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *info, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean mn10300_elf_relax_delete_bytes
   PARAMS ((bfd *, asection *, bfd_vma, int));
@@ -397,8 +397,8 @@ mn10300_elf_check_relocs (abfd, info, se
    relocation.  */
 
 static asection *
-mn10300_elf_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+mn10300_elf_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -428,9 +428,7 @@ mn10300_elf_gc_mark_hook (abfd, info, re
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-arm.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.h,v
retrieving revision 1.85
diff -u -p -r1.85 elf32-arm.h
--- bfd/elf32-arm.h	25 Jun 2002 06:21:51 -0000	1.85
+++ bfd/elf32-arm.h	1 Jul 2002 07:47:22 -0000
@@ -58,7 +58,7 @@ static boolean elf32_arm_relocate_sectio
   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
 	   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
 static asection * elf32_arm_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean elf32_arm_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
@@ -2529,8 +2529,8 @@ elf32_arm_get_symbol_type (elf_sym, type
 }
 
 static asection *
-elf32_arm_gc_mark_hook (abfd, info, rel, h, sym)
-       bfd *abfd;
+elf32_arm_gc_mark_hook (sec, info, rel, h, sym)
+       asection *sec;
        struct bfd_link_info *info ATTRIBUTE_UNUSED;
        Elf_Internal_Rela *rel;
        struct elf_link_hash_entry *h;
@@ -2560,9 +2560,7 @@ elf32_arm_gc_mark_hook (abfd, info, rel,
        }
      }
    else
-     {
-       return bfd_section_from_elf_index (abfd, sym->st_shndx);
-     }
+     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-avr.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-avr.c,v
retrieving revision 1.9
diff -u -p -r1.9 elf32-avr.c
--- bfd/elf32-avr.c	17 Dec 2001 00:52:35 -0000	1.9
+++ bfd/elf32-avr.c	1 Jul 2002 07:47:22 -0000
@@ -1,5 +1,5 @@
 /* AVR-specific support for 32-bit ELF
-   Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    Contributed by Denis Chertykov <denisc@overta.ru>
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -29,7 +29,7 @@ static reloc_howto_type *bfd_elf32_bfd_r
 static void avr_info_to_howto_rela
   PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
 static asection *elf32_avr_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean elf32_avr_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
@@ -399,8 +399,8 @@ avr_info_to_howto_rela (abfd, cache_ptr,
 }
 
 static asection *
-elf32_avr_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+elf32_avr_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -426,9 +426,7 @@ elf32_avr_gc_mark_hook (abfd, info, rel,
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-cris.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-cris.c,v
retrieving revision 1.31
diff -u -p -r1.31 elf32-cris.c
--- bfd/elf32-cris.c	25 Jun 2002 06:21:51 -0000	1.31
+++ bfd/elf32-cris.c	1 Jul 2002 07:47:25 -0000
@@ -52,7 +52,7 @@ static boolean cris_elf_gc_sweep_hook
 	   const Elf_Internal_Rela *));
 
 static asection * cris_elf_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 
 static boolean cris_elf_object_p PARAMS ((bfd *));
@@ -1770,8 +1770,8 @@ elf_cris_finish_dynamic_sections (output
    relocation.  */
 
 static asection *
-cris_elf_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *                        abfd;
+cris_elf_gc_mark_hook (sec, info, rel, h, sym)
+     asection *                   sec;
      struct bfd_link_info *       info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *          rel;
      struct elf_link_hash_entry * h;
@@ -1801,9 +1801,7 @@ cris_elf_gc_mark_hook (abfd, info, rel, 
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-d10v.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-d10v.c,v
retrieving revision 1.15
diff -u -p -r1.15 elf32-d10v.c
--- bfd/elf32-d10v.c	17 Jun 2002 13:43:50 -0000	1.15
+++ bfd/elf32-d10v.c	1 Jul 2002 07:47:26 -0000
@@ -29,7 +29,7 @@ static reloc_howto_type *bfd_elf32_bfd_r
 static void d10v_info_to_howto_rel
   PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
 static asection * elf32_d10v_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean elf32_d10v_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
@@ -240,12 +240,12 @@ d10v_info_to_howto_rel (abfd, cache_ptr,
 }
 
 static asection *
-elf32_d10v_gc_mark_hook (abfd, info, rel, h, sym)
-       bfd *abfd;
-       struct bfd_link_info *info ATTRIBUTE_UNUSED;
-       Elf_Internal_Rela *rel;
-       struct elf_link_hash_entry *h;
-       Elf_Internal_Sym *sym;
+elf32_d10v_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     Elf_Internal_Rela *rel;
+     struct elf_link_hash_entry *h;
+     Elf_Internal_Sym *sym;
 {
   if (h != NULL)
     {
@@ -271,9 +271,8 @@ elf32_d10v_gc_mark_hook (abfd, info, rel
        }
      }
    else
-     {
-       return bfd_section_from_elf_index (abfd, sym->st_shndx);
-     }
+     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+
   return NULL;
 }
 
Index: bfd/elf32-fr30.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-fr30.c,v
retrieving revision 1.15
diff -u -p -r1.15 elf32-fr30.c
--- bfd/elf32-fr30.c	7 May 2002 00:16:51 -0000	1.15
+++ bfd/elf32-fr30.c	1 Jul 2002 07:47:26 -0000
@@ -42,7 +42,7 @@ static boolean fr30_elf_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
 	   const Elf_Internal_Rela *));
 static asection * fr30_elf_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean fr30_elf_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
@@ -664,8 +664,8 @@ fr30_elf_relocate_section (output_bfd, i
    relocation.  */
 
 static asection *
-fr30_elf_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *                        abfd;
+fr30_elf_gc_mark_hook (sec, info, rel, h, sym)
+     asection *                   sec;
      struct bfd_link_info *       info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *          rel;
      struct elf_link_hash_entry * h;
@@ -695,9 +695,7 @@ fr30_elf_gc_mark_hook (abfd, info, rel, 
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-frv.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-frv.c,v
retrieving revision 1.1
diff -u -p -r1.1 elf32-frv.c
--- bfd/elf32-frv.c	18 Jun 2002 21:10:54 -0000	1.1
+++ bfd/elf32-frv.c	1 Jul 2002 07:47:27 -0000
@@ -51,7 +51,7 @@ static bfd_reloc_status_type frv_final_l
 static boolean elf32_frv_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));
 static asection * elf32_frv_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *));
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean elf32_frv_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));
 static int elf32_frv_machine PARAMS ((bfd *));
@@ -838,8 +838,8 @@ elf32_frv_relocate_section (output_bfd, 
    relocation.  */
 
 static asection *
-elf32_frv_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *                        abfd;
+elf32_frv_gc_mark_hook (sec, info, rel, h, sym)
+     asection *                   sec;
      struct bfd_link_info *       info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *          rel;
      struct elf_link_hash_entry * h;
@@ -869,13 +869,7 @@ elf32_frv_gc_mark_hook (abfd, info, rel,
 	}
     }
   else
-    {
-      if (!(elf_bad_symtab (abfd)
-	    && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-	  && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-		&& sym->st_shndx != SHN_COMMON))
-	return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-hppa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-hppa.c,v
retrieving revision 1.85
diff -u -p -r1.85 elf32-hppa.c
--- bfd/elf32-hppa.c	25 Jun 2002 09:40:43 -0000	1.85
+++ bfd/elf32-hppa.c	1 Jul 2002 07:47:30 -0000
@@ -334,7 +334,7 @@ static boolean elf32_hppa_check_relocs
 	   asection *, const Elf_Internal_Rela *));
 
 static asection *elf32_hppa_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 
 static boolean elf32_hppa_gc_sweep_hook
@@ -1632,8 +1632,8 @@ elf32_hppa_check_relocs (abfd, info, sec
    for a given relocation.  */
 
 static asection *
-elf32_hppa_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+elf32_hppa_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -1663,9 +1663,7 @@ elf32_hppa_gc_mark_hook (abfd, info, rel
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
@@ -2996,10 +2994,7 @@ elf32_hppa_size_stubs (output_bfd, stub_
 	       section != NULL;
 	       section = section->next)
 	    {
-	      Elf_Internal_Shdr *input_rel_hdr;
-	      Elf32_External_Rela *external_relocs, *erelaend, *erela;
 	      Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
-	      bfd_size_type amt;
 
 	      /* If there aren't any relocs, then there's nothing more
 		 to do.  */
@@ -3013,47 +3008,13 @@ elf32_hppa_size_stubs (output_bfd, stub_
 		  || section->output_section->owner != output_bfd)
 		continue;
 
-	      /* Allocate space for the external relocations.  */
-	      amt = section->reloc_count;
-	      amt *= sizeof (Elf32_External_Rela);
-	      external_relocs = (Elf32_External_Rela *) bfd_malloc (amt);
-	      if (external_relocs == NULL)
-		{
-		  goto error_ret_free_local;
-		}
-
-	      /* Likewise for the internal relocations.  */
-	      amt = section->reloc_count;
-	      amt *= sizeof (Elf_Internal_Rela);
-	      internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt);
+	      /* Get the relocs.  */
+	      internal_relocs
+		= _bfd_elf32_link_read_relocs (input_bfd, section, NULL,
+					       (Elf_Internal_Rela *) NULL,
+					       info->keep_memory);
 	      if (internal_relocs == NULL)
-		{
-		  free (external_relocs);
-		  goto error_ret_free_local;
-		}
-
-	      /* Read in the external relocs.  */
-	      input_rel_hdr = &elf_section_data (section)->rel_hdr;
-	      if (bfd_seek (input_bfd, input_rel_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) external_relocs,
-				input_rel_hdr->sh_size,
-				input_bfd) != input_rel_hdr->sh_size)
-		{
-		  free (external_relocs);
-		error_ret_free_internal:
-		  free (internal_relocs);
-		  goto error_ret_free_local;
-		}
-
-	      /* Swap in the relocs.  */
-	      erela = external_relocs;
-	      erelaend = erela + section->reloc_count;
-	      irela = internal_relocs;
-	      for (; erela < erelaend; erela++, irela++)
-		bfd_elf32_swap_reloca_in (input_bfd, erela, irela);
-
-	      /* We're done with the external relocs, free them.  */
-	      free (external_relocs);
+		goto error_ret_free_local;
 
 	      /* Now examine each relocation.  */
 	      irela = internal_relocs;
@@ -3076,7 +3037,10 @@ elf32_hppa_size_stubs (output_bfd, stub_
 		  if (r_type >= (unsigned int) R_PARISC_UNIMPLEMENTED)
 		    {
 		      bfd_set_error (bfd_error_bad_value);
-		      goto error_ret_free_internal;
+		    error_ret_free_internal:
+		      if (elf_section_data (section)->relocs == NULL)
+			free (internal_relocs);
+		      goto error_ret_free_local;
 		    }
 
 		  /* Only look for stubs on call instructions.  */
@@ -3179,7 +3143,7 @@ elf32_hppa_size_stubs (output_bfd, stub_
 		  if (stub_entry == NULL)
 		    {
 		      free (stub_name);
-		      goto error_ret_free_local;
+		      goto error_ret_free_internal;
 		    }
 
 		  stub_entry->target_value = sym_value;
@@ -3197,7 +3161,8 @@ elf32_hppa_size_stubs (output_bfd, stub_
 		}
 
 	      /* We're done with the internal relocs, free them.  */
-	      free (internal_relocs);
+	      if (elf_section_data (section)->relocs == NULL)
+		free (internal_relocs);
 	    }
 	}
 
Index: bfd/elf32-i386.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-i386.c,v
retrieving revision 1.73
diff -u -p -r1.73 elf32-i386.c
--- bfd/elf32-i386.c	25 Jun 2002 06:21:52 -0000	1.73
+++ bfd/elf32-i386.c	1 Jul 2002 07:47:32 -0000
@@ -57,7 +57,7 @@ static boolean elf_i386_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
 	   const Elf_Internal_Rela *));
 static asection *elf_i386_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean elf_i386_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
@@ -1174,8 +1174,8 @@ elf_i386_check_relocs (abfd, info, sec, 
    relocation.  */
 
 static asection *
-elf_i386_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+elf_i386_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -1205,9 +1205,7 @@ elf_i386_gc_mark_hook (abfd, info, rel, 
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-m32r.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-m32r.c,v
retrieving revision 1.23
diff -u -p -r1.23 elf32-m32r.c
--- bfd/elf32-m32r.c	7 May 2002 00:16:51 -0000	1.23
+++ bfd/elf32-m32r.c	1 Jul 2002 07:47:34 -0000
@@ -1,5 +1,5 @@
 /* M32R-specific support for 32-bit ELF.
-   Copyright 1996, 1997, 1998, 1999, 2000, 2001
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -78,7 +78,7 @@ static boolean m32r_elf_check_relocs
 	   const Elf_Internal_Rela *));
 
 asection * m32r_elf_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 
 #define NOP_INSN		0x7000
@@ -2033,12 +2033,12 @@ m32r_elf_print_private_bfd_data (abfd, p
 }
 
 asection *
-m32r_elf_gc_mark_hook (abfd, info, rel, h, sym)
-       bfd *abfd;
-       struct bfd_link_info *info ATTRIBUTE_UNUSED;
-       Elf_Internal_Rela *rel;
-       struct elf_link_hash_entry *h;
-       Elf_Internal_Sym *sym;
+m32r_elf_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     Elf_Internal_Rela *rel;
+     struct elf_link_hash_entry *h;
+     Elf_Internal_Sym *sym;
 {
   if (h != NULL)
     {
@@ -2064,9 +2064,8 @@ m32r_elf_gc_mark_hook (abfd, info, rel, 
        }
      }
    else
-     {
-       return bfd_section_from_elf_index (abfd, sym->st_shndx);
-     }
+     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+
   return NULL;
 }
 
Index: bfd/elf32-m68k.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-m68k.c,v
retrieving revision 1.43
diff -u -p -r1.43 elf32-m68k.c
--- bfd/elf32-m68k.c	6 Jun 2002 00:29:21 -0000	1.43
+++ bfd/elf32-m68k.c	1 Jul 2002 07:47:36 -0000
@@ -37,7 +37,7 @@ static boolean elf_m68k_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
 	   const Elf_Internal_Rela *));
 static asection *elf_m68k_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean elf_m68k_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
@@ -754,8 +754,8 @@ elf_m68k_check_relocs (abfd, info, sec, 
    relocation.  */
 
 static asection *
-elf_m68k_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+elf_m68k_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -785,9 +785,7 @@ elf_m68k_gc_mark_hook (abfd, info, rel, 
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-mcore.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-mcore.c,v
retrieving revision 1.22
diff -u -p -r1.22 elf32-mcore.c
--- bfd/elf32-mcore.c	25 Jun 2002 06:21:52 -0000	1.22
+++ bfd/elf32-mcore.c	1 Jul 2002 07:47:36 -0000
@@ -48,7 +48,7 @@ static boolean mcore_elf_relocate_sectio
   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
 	   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
 static asection * mcore_elf_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean mcore_elf_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
@@ -573,8 +573,8 @@ mcore_elf_relocate_section (output_bfd, 
    relocation.  */
 
 static asection *
-mcore_elf_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *                        abfd;
+mcore_elf_gc_mark_hook (sec, info, rel, h, sym)
+     asection *                   sec;
      struct bfd_link_info *       info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *          rel;
      struct elf_link_hash_entry * h;
@@ -604,9 +604,7 @@ mcore_elf_gc_mark_hook (abfd, info, rel,
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-openrisc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-openrisc.c,v
retrieving revision 1.9
diff -u -p -r1.9 elf32-openrisc.c
--- bfd/elf32-openrisc.c	4 Jun 2002 05:28:52 -0000	1.9
+++ bfd/elf32-openrisc.c	1 Jul 2002 07:47:37 -0000
@@ -41,7 +41,7 @@ static boolean openrisc_elf_gc_sweep_hoo
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
            const Elf_Internal_Rela *));
 static asection * openrisc_elf_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean openrisc_elf_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
@@ -468,8 +468,8 @@ openrisc_elf_relocate_section (output_bf
    relocation.  */
 
 static asection *
-openrisc_elf_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+openrisc_elf_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -499,9 +499,7 @@ openrisc_elf_gc_mark_hook (abfd, info, r
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.47
diff -u -p -r1.47 elf32-ppc.c
--- bfd/elf32-ppc.c	27 Jun 2002 11:29:15 -0000	1.47
+++ bfd/elf32-ppc.c	1 Jul 2002 07:47:39 -0000
@@ -71,7 +71,7 @@ static boolean ppc_elf_check_relocs PARA
 					     asection *,
 					     const Elf_Internal_Rela *));
 
-static asection * ppc_elf_gc_mark_hook PARAMS ((bfd *abfd,
+static asection * ppc_elf_gc_mark_hook PARAMS ((asection *sec,
 						struct bfd_link_info *info,
 						Elf_Internal_Rela *rel,
 						struct elf_link_hash_entry *h,
@@ -2481,8 +2481,8 @@ ppc_elf_check_relocs (abfd, info, sec, r
    relocation.  */
 
 static asection *
-ppc_elf_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+ppc_elf_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -2512,9 +2512,7 @@ ppc_elf_gc_mark_hook (abfd, info, rel, h
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-s390.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-s390.c,v
retrieving revision 1.26
diff -u -p -r1.26 elf32-s390.c
--- bfd/elf32-s390.c	3 Jun 2002 01:57:09 -0000	1.26
+++ bfd/elf32-s390.c	1 Jul 2002 07:47:42 -0000
@@ -45,7 +45,7 @@ static boolean elf_s390_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
 	   const Elf_Internal_Rela *));
 static asection *elf_s390_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean elf_s390_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
@@ -903,8 +903,8 @@ elf_s390_check_relocs (abfd, info, sec, 
    relocation.  */
 
 static asection *
-elf_s390_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+elf_s390_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -934,9 +934,7 @@ elf_s390_gc_mark_hook (abfd, info, rel, 
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-sh.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sh.c,v
retrieving revision 1.50
diff -u -p -r1.50 elf32-sh.c
--- bfd/elf32-sh.c	25 Jun 2002 06:21:52 -0000	1.50
+++ bfd/elf32-sh.c	1 Jul 2002 07:47:45 -0000
@@ -78,7 +78,7 @@ static bfd_reloc_status_type sh_elf_relo
 static boolean sh_elf_create_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 static asection * sh_elf_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean sh_elf_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
@@ -4978,8 +4978,8 @@ sh_elf_get_relocated_section_contents (o
 }
 
 static asection *
-sh_elf_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+sh_elf_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -5009,9 +5009,7 @@ sh_elf_gc_mark_hook (abfd, info, rel, h,
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-sparc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sparc.c,v
retrieving revision 1.38
diff -u -p -r1.38 elf32-sparc.c
--- bfd/elf32-sparc.c	3 Apr 2002 17:42:39 -0000	1.38
+++ bfd/elf32-sparc.c	1 Jul 2002 07:47:46 -0000
@@ -1,5 +1,5 @@
 /* SPARC-specific support for 32-bit ELF
-   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -55,7 +55,7 @@ static void elf32_sparc_final_write_proc
 static enum elf_reloc_type_class elf32_sparc_reloc_type_class
   PARAMS ((const Elf_Internal_Rela *));
 static asection * elf32_sparc_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean elf32_sparc_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
@@ -637,14 +637,13 @@ elf32_sparc_check_relocs (abfd, info, se
 }
 
 static asection *
-elf32_sparc_gc_mark_hook (abfd, info, rel, h, sym)
-       bfd *abfd;
+elf32_sparc_gc_mark_hook (sec, info, rel, h, sym)
+       asection *sec;
        struct bfd_link_info *info ATTRIBUTE_UNUSED;
        Elf_Internal_Rela *rel;
        struct elf_link_hash_entry *h;
        Elf_Internal_Sym *sym;
 {
-
   if (h != NULL)
     {
       switch (ELF32_R_TYPE (rel->r_info))
@@ -669,9 +668,7 @@ elf32_sparc_gc_mark_hook (abfd, info, re
        }
      }
    else
-     {
-       return bfd_section_from_elf_index (abfd, sym->st_shndx);
-     }
+     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-v850.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-v850.c,v
retrieving revision 1.22
diff -u -p -r1.22 elf32-v850.c
--- bfd/elf32-v850.c	25 Jun 2002 06:21:52 -0000	1.22
+++ bfd/elf32-v850.c	1 Jul 2002 07:47:48 -0000
@@ -84,7 +84,7 @@ static boolean v850_elf_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
 	   const Elf_Internal_Rela *));
 static asection * v850_elf_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *,
+  PARAMS ((asection *, struct bfd_link_info *,
 	   Elf_Internal_Rela *, struct elf_link_hash_entry *,
 	   Elf_Internal_Sym *));
 
@@ -1740,8 +1740,8 @@ v850_elf_gc_sweep_hook (abfd, info, sec,
 }
 
 static asection *
-v850_elf_gc_mark_hook (abfd, info, rel, h, sym)
-       bfd *abfd;
+v850_elf_gc_mark_hook (sec, info, rel, h, sym)
+       asection *sec;
        struct bfd_link_info *info ATTRIBUTE_UNUSED;
        Elf_Internal_Rela *rel;
        struct elf_link_hash_entry *h;
@@ -1771,9 +1771,7 @@ v850_elf_gc_mark_hook (abfd, info, rel, 
        }
      }
    else
-     {
-       return bfd_section_from_elf_index (abfd, sym->st_shndx);
-     }
+     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-vax.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-vax.c,v
retrieving revision 1.3
diff -u -p -r1.3 elf32-vax.c
--- bfd/elf32-vax.c	4 Jun 2002 05:28:52 -0000	1.3
+++ bfd/elf32-vax.c	1 Jul 2002 07:47:49 -0000
@@ -38,7 +38,7 @@ static boolean elf_vax_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
 	   const Elf_Internal_Rela *));
 static asection *elf_vax_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean elf_vax_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
@@ -855,8 +855,8 @@ elf_vax_check_relocs (abfd, info, sec, r
    relocation.  */
 
 static asection *
-elf_vax_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+elf_vax_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -886,9 +886,7 @@ elf_vax_gc_mark_hook (abfd, info, rel, h
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf32-xstormy16.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-xstormy16.c,v
retrieving revision 1.8
diff -u -p -r1.8 elf32-xstormy16.c
--- bfd/elf32-xstormy16.c	6 Jun 2002 00:29:21 -0000	1.8
+++ bfd/elf32-xstormy16.c	1 Jul 2002 07:47:51 -0000
@@ -54,7 +54,7 @@ static boolean xstormy16_elf_gc_sweep_ho
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
 	   const Elf_Internal_Rela *));
 static asection * xstormy16_elf_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 
 static reloc_howto_type xstormy16_elf_howto_table [] =
@@ -1021,8 +1021,8 @@ xstormy16_elf_finish_dynamic_sections (a
    relocation.  */
 
 static asection *
-xstormy16_elf_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *                        abfd;
+xstormy16_elf_gc_mark_hook (sec, info, rel, h, sym)
+     asection *                   sec;
      struct bfd_link_info *       info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *          rel;
      struct elf_link_hash_entry * h;
@@ -1052,9 +1052,7 @@ xstormy16_elf_gc_mark_hook (abfd, info, 
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf64-mmix.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-mmix.c,v
retrieving revision 1.15
diff -u -p -r1.15 elf64-mmix.c
--- bfd/elf64-mmix.c	16 Jun 2002 20:48:46 -0000	1.15
+++ bfd/elf64-mmix.c	1 Jul 2002 07:47:53 -0000
@@ -148,7 +148,7 @@ static boolean mmix_elf_relocate_section
 	   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
 
 static asection * mmix_elf_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 
 static boolean mmix_elf_gc_sweep_hook
@@ -1524,8 +1524,8 @@ mmix_final_link_relocate (howto, input_s
    relocation.  */
 
 static asection *
-mmix_elf_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+mmix_elf_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -1555,9 +1555,7 @@ mmix_elf_gc_mark_hook (abfd, info, rel, 
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.54
diff -u -p -r1.54 elf64-ppc.c
--- bfd/elf64-ppc.c	27 Jun 2002 11:29:15 -0000	1.54
+++ bfd/elf64-ppc.c	1 Jul 2002 07:47:56 -0000
@@ -127,8 +127,7 @@ static boolean ppc64_elf_section_from_sh
 /* Since .opd is an array of descriptors and each entry will end up
    with identical R_PPC64_RELATIVE relocs, there is really no need to
    propagate .opd relocs;  The dynamic linker should be taught to
-   relocate .opd without reloc entries.  FIXME: .opd should be trimmed
-   of unused values.  */
+   relocate .opd without reloc entries.  */
 #ifndef NO_OPD_RELOCS
 #define NO_OPD_RELOCS 0
 #endif
@@ -2005,6 +2004,7 @@ struct ppc_link_hash_entry
   /* Flag function code and descriptor symbols.  */
   unsigned int is_func:1;
   unsigned int is_func_descriptor:1;
+  unsigned int is_entry:1;
 };
 
 /* ppc64 ELF linker hash table.  */
@@ -2100,11 +2100,11 @@ static boolean ppc64_elf_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
 	   const Elf_Internal_Rela *));
 static asection * ppc64_elf_gc_mark_hook
-  PARAMS ((bfd *abfd, struct bfd_link_info *info, Elf_Internal_Rela *rel,
-	   struct elf_link_hash_entry *h, Elf_Internal_Sym *sym));
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
+	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean ppc64_elf_gc_sweep_hook
-  PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
-	   const Elf_Internal_Rela *relocs));
+  PARAMS ((bfd *, struct bfd_link_info *, asection *,
+	   const Elf_Internal_Rela *));
 static boolean func_desc_adjust
   PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean ppc64_elf_func_desc_adjust
@@ -2113,6 +2113,8 @@ static boolean ppc64_elf_adjust_dynamic_
   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
 static void ppc64_elf_hide_symbol
   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, boolean));
+static boolean edit_opd
+  PARAMS ((bfd *, struct bfd_link_info *));
 static boolean allocate_dynrelocs
   PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean readonly_dynrelocs
@@ -2256,6 +2258,7 @@ link_hash_newfunc (entry, table, string)
       eh->oh = NULL;
       eh->is_func = 0;
       eh->is_func_descriptor = 0;
+      eh->is_entry = 0;
     }
 
   return entry;
@@ -2292,6 +2295,7 @@ ppc64_elf_link_hash_table_create (abfd)
   htab->add_stub_section = NULL;
   htab->layout_sections_again = NULL;
   htab->stub_group = NULL;
+  htab->all_local_syms = NULL;
   htab->sgot = NULL;
   htab->srelgot = NULL;
   htab->splt = NULL;
@@ -2514,7 +2518,7 @@ create_linkage_sections (dynobj, info)
     {
       flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
 	       | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-      htab->srelbrlt = bfd_make_section (dynobj, ".rela.branch_lt");
+      htab->srelbrlt = bfd_make_section_anyway (dynobj, ".rela.branch_lt");
       if (!htab->srelbrlt
 	  || ! bfd_set_section_flags (dynobj, htab->srelbrlt, flags)
 	  || ! bfd_set_section_alignment (dynobj, htab->srelbrlt, 3))
@@ -2628,10 +2632,33 @@ ppc64_elf_copy_indirect_symbol (dir, ind
 
   edir->is_func |= eind->is_func;
   edir->is_func_descriptor |= eind->is_func_descriptor;
+  edir->is_entry |= eind->is_entry;
 
   _bfd_elf_link_hash_copy_indirect (dir, ind);
 }
 
+/* Set a flag, used by ppc64_elf_gc_mark_hook, on the entry symbol and
+   symbols undefined on the command-line.  */
+
+boolean
+ppc64_elf_mark_entry_syms (info)
+     struct bfd_link_info *info;
+{
+  struct ppc_link_hash_table *htab;
+  struct bfd_sym_chain *sym;
+
+  htab = ppc_hash_table (info);
+  for (sym = info->gc_sym_list; sym; sym = sym->next)
+    {
+      struct elf_link_hash_entry *h;
+
+      h = elf_link_hash_lookup (&htab->elf, sym->name, false, false, false);
+      if (h != NULL)
+	((struct ppc_link_hash_entry *) h)->is_entry = 1;
+    }
+  return true;
+}
+
 /* Look through the relocs for a section during the first phase, and
    calculate needed space in the global offset table, procedure
    linkage table, and dynamic reloc sections.  */
@@ -2649,7 +2676,7 @@ ppc64_elf_check_relocs (abfd, info, sec,
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
   asection *sreloc;
-  boolean is_opd;
+  asection **opd_sym_map;
 
   if (info->relocateable)
     return true;
@@ -2659,12 +2686,34 @@ ppc64_elf_check_relocs (abfd, info, sec,
 
   sym_hashes = elf_sym_hashes (abfd);
   sym_hashes_end = (sym_hashes
-		    + symtab_hdr->sh_size / sizeof (Elf64_External_Sym));
-  if (!elf_bad_symtab (abfd))
-    sym_hashes_end -= symtab_hdr->sh_info;
+		    + symtab_hdr->sh_size / sizeof (Elf64_External_Sym)
+		    - symtab_hdr->sh_info);
 
   sreloc = NULL;
-  is_opd = strcmp (bfd_get_section_name (abfd, sec), ".opd") == 0;
+  opd_sym_map = NULL;
+  if (strcmp (bfd_get_section_name (abfd, sec), ".opd") == 0)
+    {
+      /* Garbage collection needs some extra help with .opd sections.
+	 We don't want to necessarily keep everything referenced by
+	 relocs in .opd, as that would keep all functions.  Instead,
+	 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;
+      };
+      bfd_size_type amt;
+
+      amt = sec->_raw_size * sizeof (union opd_info) / 24;
+      opd_sym_map = (asection **) bfd_zalloc (abfd, amt);
+      if (opd_sym_map == NULL)
+	return false;
+      elf_section_data (sec)->tdata = opd_sym_map;
+    }
 
   if (htab->elf.dynobj == NULL)
     htab->elf.dynobj = abfd;
@@ -2801,7 +2850,7 @@ ppc64_elf_check_relocs (abfd, info, sec,
 	  break;
 
 	case R_PPC64_ADDR64:
-	  if (is_opd
+	  if (opd_sym_map != NULL
 	      && h != NULL
 	      && h->root.root.string[0] == '.'
 	      && h->root.root.string[1] != 0)
@@ -2818,6 +2867,21 @@ ppc64_elf_check_relocs (abfd, info, sec,
 		  ((struct ppc_link_hash_entry *) h)->oh = fdh;
 		}
 	    }
+	  if (opd_sym_map != NULL
+	      && h == NULL
+	      && rel + 1 < rel_end
+	      && ((enum elf_ppc_reloc_type) ELF64_R_TYPE ((rel + 1)->r_info)
+		  == R_PPC64_TOC))
+	    {
+	      asection *s;
+
+	      s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec,
+					     r_symndx);
+	      if (s == NULL)
+		return false;
+	      else if (s != sec)
+		opd_sym_map[rel->r_offset / 24] = s;
+	    }
 	  /* Fall through.  */
 
 	case R_PPC64_REL64:
@@ -2843,7 +2907,7 @@ ppc64_elf_check_relocs (abfd, info, sec,
 	case R_PPC64_UADDR64:
 	case R_PPC64_TOC:
 	  /* Don't propagate .opd relocs.  */
-	  if (NO_OPD_RELOCS && is_opd)
+	  if (NO_OPD_RELOCS && opd_sym_map != NULL)
 	    break;
 
 	  /* If we are creating a shared library, and this is a reloc
@@ -2984,16 +3048,19 @@ ppc64_elf_check_relocs (abfd, info, sec,
    relocation.  */
 
 static asection *
-ppc64_elf_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+ppc64_elf_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
      Elf_Internal_Sym *sym;
 {
+  asection *rsec = NULL;
+
   if (h != NULL)
     {
       enum elf_ppc_reloc_type r_type;
+      struct ppc_link_hash_entry *fdh;
 
       r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE (rel->r_info);
       switch (r_type)
@@ -3007,10 +3074,26 @@ ppc64_elf_gc_mark_hook (abfd, info, rel,
 	    {
 	    case bfd_link_hash_defined:
 	    case bfd_link_hash_defweak:
-	      return h->root.u.def.section;
+	      fdh = (struct ppc_link_hash_entry *) h;
+
+	      /* Function descriptor syms cause the associated
+		 function code sym section to be marked.  */
+	      if (fdh->is_func_descriptor)
+		rsec = fdh->oh->root.u.def.section;
+
+	      /* Function entry syms return NULL if they are in .opd
+		 and are not ._start (or others undefined on the ld
+		 command line).  Thus we avoid marking all function
+		 sections, as all functions are referenced in .opd.  */ 
+	      else if ((fdh->oh != NULL
+			&& ((struct ppc_link_hash_entry *) fdh->oh)->is_entry)
+		       || elf_section_data (sec)->tdata == NULL)
+		rsec = h->root.u.def.section;
+	      break;
 
 	    case bfd_link_hash_common:
-	      return h->root.u.c.p->section;
+	      rsec = h->root.u.c.p->section;
+	      break;
 
 	    default:
 	      break;
@@ -3019,10 +3102,17 @@ ppc64_elf_gc_mark_hook (abfd, info, rel,
     }
   else
     {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
+      asection **opd_sym_section;
+
+      rsec = bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+      opd_sym_section = (asection **) elf_section_data (rsec)->tdata;
+      if (opd_sym_section != NULL)
+	rsec = opd_sym_section[sym->st_value / 24];
+      else if (elf_section_data (sec)->tdata != NULL)
+	rsec = NULL;
     }
 
-  return NULL;
+  return rsec;
 }
 
 /* Update the .got, .plt. and dynamic reloc reference counts for the
@@ -3592,6 +3682,268 @@ ppc64_elf_hide_symbol (info, h, force_lo
     }
 }
 
+static boolean
+edit_opd (obfd, info)
+     bfd *obfd;
+     struct bfd_link_info *info;
+{
+  bfd *ibfd;
+  unsigned int bfd_indx;
+  struct ppc_link_hash_table *htab = ppc_hash_table (info);
+
+  for (bfd_indx = 0, ibfd = info->input_bfds;
+       ibfd != NULL;
+       ibfd = ibfd->link_next, bfd_indx++)
+    {
+      asection *sec;
+      Elf_Internal_Rela *relstart, *rel, *relend;
+      Elf_Internal_Shdr *symtab_hdr;
+      struct elf_link_hash_entry **sym_hashes;
+      bfd_vma offset;
+      long *adjust;
+      boolean need_edit;
+
+      sec = bfd_get_section_by_name (ibfd, ".opd");
+      if (sec == NULL)
+	continue;
+
+      adjust = (long *) elf_section_data (sec)->tdata;
+      BFD_ASSERT (adjust != NULL);
+      memset (adjust, 0, (size_t) sec->_raw_size * sizeof (long) / 24);
+
+      if (sec->output_section == bfd_abs_section_ptr)
+	continue;
+
+      /* Look through the section relocs.  */
+      if ((sec->flags & SEC_RELOC) == 0 || sec->reloc_count == 0)
+	continue;
+
+      symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
+      sym_hashes = elf_sym_hashes (ibfd);
+
+      /* Read the relocations.  */
+      relstart = _bfd_elf64_link_read_relocs (obfd, sec, (PTR) NULL,
+					      (Elf_Internal_Rela *) NULL,
+					      info->keep_memory);
+      if (relstart == NULL)
+	return false;
+
+      /* First run through the relocs to check they are sane, and to
+	 determine whether we need to edit this opd section.  */
+      need_edit = false;
+      offset = 0;
+      relend = relstart + sec->reloc_count;
+      for (rel = relstart; rel < relend; rel++)
+	{
+	  enum elf_ppc_reloc_type r_type;
+	  unsigned long r_symndx;
+	  asection *sym_sec;
+	  struct elf_link_hash_entry *h;
+	  Elf_Internal_Sym *sym;
+
+	  /* .opd contains a regular array of 24 byte entries.  We're
+	     only interested in the reloc pointing to a function entry
+	     point.  */
+	  r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE (rel->r_info);
+	  if (r_type == R_PPC64_TOC)
+	    continue;
+
+	  if (r_type != R_PPC64_ADDR64)
+	    {
+	      (*_bfd_error_handler)
+		(_("%s: unexpected reloc type %u in .opd section"),
+		 bfd_archive_filename (ibfd), r_type);
+	      need_edit = false;
+	      break;
+	    }
+
+	  if (rel + 1 >= relend)
+	    continue;
+	  r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE ((rel + 1)->r_info);
+	  if (r_type != R_PPC64_TOC)
+	    continue;
+
+	  if (rel->r_offset != offset)
+	    {
+	      /* If someone messes with .opd alignment then after a
+		 "ld -r" we might have padding in the middle of .opd.
+		 Also, there's nothing to prevent someone putting
+		 something silly in .opd with the assembler.  No .opd
+		 optimization for them!  */ 
+	      (*_bfd_error_handler)
+		(_("%s: .opd is not a regular array of opd entries"),
+		 bfd_archive_filename (ibfd));
+	      need_edit = false;
+	      break;
+	    }
+
+	  r_symndx = ELF64_R_SYM (rel->r_info);
+	  sym_sec = NULL;
+	  h = NULL;
+	  sym = NULL;
+	  if (r_symndx >= symtab_hdr->sh_info)
+	    {
+	      h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+	      while (h->root.type == bfd_link_hash_indirect
+		     || h->root.type == bfd_link_hash_warning)
+		h = (struct elf_link_hash_entry *) h->root.u.i.link;
+	      if (h->root.type == bfd_link_hash_defined
+		  || h->root.type == bfd_link_hash_defweak)
+		sym_sec = h->root.u.def.section;
+	    }
+	  else
+	    {
+	      sym = htab->all_local_syms[bfd_indx] + r_symndx;
+	      if ((sym->st_shndx != SHN_UNDEF
+		   && sym->st_shndx < SHN_LORESERVE)
+		  || sym->st_shndx > SHN_HIRESERVE)
+		sym_sec = bfd_section_from_elf_index (ibfd, sym->st_shndx);
+	    }
+
+	  if (sym_sec == NULL || sym_sec->owner == NULL)
+	    {
+	      (*_bfd_error_handler)
+		(_("%s: undefined sym `%s' in .opd section"),
+		 bfd_archive_filename (ibfd),
+		 h != NULL ? h->root.root.string : "<local symbol>");
+	      need_edit = false;
+	      break;
+	    }
+
+	  if (sym_sec->output_section == bfd_abs_section_ptr)
+	    {
+	      /* OK, we've found a function that's excluded from the
+		 link.  */
+	      need_edit = true;
+	    }
+
+	  offset += 24;
+	}
+
+      if (need_edit)
+	{
+	  Elf_Internal_Rela *write_rel;
+	  bfd_byte *rptr, *wptr;
+	  boolean skip;
+
+	  /* This seems a waste of time as input .opd sections are all
+	     zeros as generated by gcc, but I suppose there's no reason
+	     this will always be so.  We might start putting something in
+	     the third word of .opd entries.  */
+	  if ((sec->flags & SEC_IN_MEMORY) == 0)
+	    {
+	      bfd_byte *loc = bfd_alloc (ibfd, sec->_raw_size);
+	      if (loc == NULL)
+		return false;
+	      if (! bfd_get_section_contents (ibfd, sec, loc, (bfd_vma) 0,
+					      sec->_raw_size))
+		return false;
+	      sec->contents = loc;
+	      sec->flags |= (SEC_IN_MEMORY | SEC_HAS_CONTENTS);
+	    }
+
+	  elf_section_data (sec)->relocs = relstart;
+
+	  wptr = sec->contents;
+	  rptr = sec->contents;
+	  write_rel = relstart;
+	  skip = false;
+	  offset = 0;
+	  for (rel = relstart; rel < relend; rel++)
+	    {
+	      if (rel->r_offset == offset)
+		{
+		  unsigned long r_symndx;
+		  asection *sym_sec;
+		  struct elf_link_hash_entry *h;
+		  Elf_Internal_Sym *sym;
+
+		  r_symndx = ELF64_R_SYM (rel->r_info);
+		  sym_sec = NULL;
+		  h = NULL;
+		  sym = NULL;
+		  if (r_symndx >= symtab_hdr->sh_info)
+		    {
+		      h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+		      while (h->root.type == bfd_link_hash_indirect
+			     || h->root.type == bfd_link_hash_warning)
+			h = (struct elf_link_hash_entry *) h->root.u.i.link;
+		      if (h->root.type == bfd_link_hash_defined
+			  || h->root.type == bfd_link_hash_defweak)
+			sym_sec = h->root.u.def.section;
+		    }
+		  else
+		    {
+		      sym = htab->all_local_syms[bfd_indx] + r_symndx;
+		      if ((sym->st_shndx != SHN_UNDEF
+			   && sym->st_shndx < SHN_LORESERVE)
+			  || sym->st_shndx > SHN_HIRESERVE)
+			sym_sec = bfd_section_from_elf_index (ibfd,
+							      sym->st_shndx);
+		    }
+
+		  skip = sym_sec->output_section == bfd_abs_section_ptr;
+		  if (!skip)
+		    {
+		      /* We'll be keeping this opd entry.  */
+
+		      if (h != NULL)
+			{
+			  /* Redefine the function descriptor symbol
+			     to this location in the opd section.
+			     We've checked above that opd relocs are
+			     ordered.  */
+			  struct elf_link_hash_entry *fdh;
+			  struct ppc_link_hash_entry *fh;
+
+			  fh = (struct ppc_link_hash_entry *) h;
+			  BFD_ASSERT (fh->is_func);
+			  fdh = fh->oh;
+			  fdh->root.u.def.value = wptr - sec->contents;
+			}
+		      else
+			{
+			  /* Local syms are a bit tricky.  Other parts
+			     of the linker re-read them so it's not
+			     possible to tweak local sym values.  In
+			     any case, we'd need to look through the
+			     local syms for the function descriptor
+			     sym which we don't have at the moment.
+			     So keep an array of adjustments.  */
+			  adjust[(rel->r_offset + wptr - rptr) / 24]
+			    = wptr - rptr;
+			}
+
+		      if (wptr != rptr)
+			memcpy (wptr, rptr, 24);
+		      wptr += 24;
+		    }
+		  rptr += 24;
+		  offset += 24;
+		}
+
+	      /* 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.  */
+	      if (!skip)
+		{
+		  rel->r_offset += wptr - rptr;
+		  if (write_rel != rel)
+		    memcpy (write_rel, rel, sizeof (*rel));
+		  ++write_rel;
+		}
+	    }
+
+	  sec->_cooked_size = wptr - sec->contents;
+	  sec->reloc_count = write_rel - relstart;
+	}
+      else if (elf_section_data (sec)->relocs == NULL)
+	free (relstart);
+    }
+
+  return true;
+}
+     
 /* This is the condition under which ppc64_elf_finish_dynamic_symbol
    will be called from elflink.h.  If elflink.h doesn't call our
    finish_dynamic_symbol routine, we'll need to do something about
@@ -3890,6 +4242,12 @@ ppc64_elf_size_dynamic_sections (output_
 	}
     }
 
+  if (!get_local_syms (info->input_bfds, htab))
+    return false;
+
+  if (!edit_opd (output_bfd, info))
+    return false;
+
   /* Allocate global sym .plt and .got entries, and space for global
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
@@ -4365,7 +4723,6 @@ ppc64_elf_setup_section_lists (output_bf
      struct bfd_link_info *info;
 {
   bfd *input_bfd;
-  unsigned int bfd_count;
   int top_id, top_index;
   asection *section;
   asection **input_list, **list;
@@ -4376,12 +4733,11 @@ ppc64_elf_setup_section_lists (output_bf
       || htab->sbrlt == NULL)
     return 0;
 
-  /* Count the number of input BFDs and find the top input section id.  */
-  for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0;
+  /* Find the top input section id.  */
+  for (input_bfd = info->input_bfds, top_id = 0;
        input_bfd != NULL;
        input_bfd = input_bfd->link_next)
     {
-      bfd_count += 1;
       for (section = input_bfd->sections;
 	   section != NULL;
 	   section = section->next)
@@ -4390,7 +4746,6 @@ ppc64_elf_setup_section_lists (output_bf
 	    top_id = section->id;
 	}
     }
-  htab->bfd_count = bfd_count;
 
   amt = sizeof (struct map_stub) * (top_id + 1);
   htab->stub_group = (struct map_stub *) bfd_zmalloc (amt);
@@ -4543,20 +4898,26 @@ get_local_syms (input_bfd, htab)
      struct ppc_link_hash_table *htab;
 {
   unsigned int bfd_indx;
+  bfd *ibfd;
   Elf_Internal_Sym *local_syms, **all_local_syms;
+  bfd_size_type amt;
+
+  if (htab->all_local_syms != NULL)
+    return true;
 
   /* We want to read in symbol extension records only once.  To do this
      we need to read in the local symbols in parallel and save them for
      later use; so hold pointers to the local symbols in an array.  */
-  bfd_size_type amt = sizeof (Elf_Internal_Sym *) * htab->bfd_count;
+  for (ibfd = input_bfd, bfd_indx = 0; ibfd != NULL; ibfd = ibfd->link_next)
+    bfd_indx += 1;
+  htab->bfd_count = bfd_indx;
+  amt = sizeof (Elf_Internal_Sym *) * bfd_indx;
   all_local_syms = (Elf_Internal_Sym **) bfd_zmalloc (amt);
   htab->all_local_syms = all_local_syms;
   if (all_local_syms == NULL)
     return false;
 
-  /* Walk over all the input BFDs, swapping in local symbols.
-     If we are creating a shared library, create hash entries for the
-     export stubs.  */
+  /* Walk over all the input BFDs, swapping in local symbols.  */
   for (bfd_indx = 0;
        input_bfd != NULL;
        input_bfd = input_bfd->link_next, bfd_indx++)
@@ -4568,6 +4929,9 @@ get_local_syms (input_bfd, htab)
       Elf_External_Sym_Shndx *shndx_buf, *shndx;
       bfd_size_type sec_size;
 
+      if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour)
+	continue;
+
       /* We'll need the symbol table in a second.  */
       symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
       if (symtab_hdr->sh_info == 0)
@@ -4707,10 +5071,7 @@ ppc64_elf_size_stubs (output_bfd, stub_b
 	       section != NULL;
 	       section = section->next)
 	    {
-	      Elf_Internal_Shdr *input_rel_hdr;
-	      Elf64_External_Rela *external_relocs, *erelaend, *erela;
 	      Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
-	      bfd_size_type amt;
 
 	      /* If there aren't any relocs, then there's nothing more
 		 to do.  */
@@ -4724,47 +5085,13 @@ ppc64_elf_size_stubs (output_bfd, stub_b
 		  || section->output_section->owner != output_bfd)
 		continue;
 
-	      /* Allocate space for the external relocations.  */
-	      amt = section->reloc_count;
-	      amt *= sizeof (Elf64_External_Rela);
-	      external_relocs = (Elf64_External_Rela *) bfd_malloc (amt);
-	      if (external_relocs == NULL)
-		{
-		  goto error_ret_free_local;
-		}
-
-	      /* Likewise for the internal relocations.  */
-	      amt = section->reloc_count;
-	      amt *= sizeof (Elf_Internal_Rela);
-	      internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt);
+	      /* Get the relocs.  */
+	      internal_relocs
+		= _bfd_elf64_link_read_relocs (input_bfd, section, NULL,
+					       (Elf_Internal_Rela *) NULL,
+					       info->keep_memory);
 	      if (internal_relocs == NULL)
-		{
-		  free (external_relocs);
-		  goto error_ret_free_local;
-		}
-
-	      /* Read in the external relocs.  */
-	      input_rel_hdr = &elf_section_data (section)->rel_hdr;
-	      if (bfd_seek (input_bfd, input_rel_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) external_relocs,
-				input_rel_hdr->sh_size,
-				input_bfd) != input_rel_hdr->sh_size)
-		{
-		  free (external_relocs);
-		error_ret_free_internal:
-		  free (internal_relocs);
-		  goto error_ret_free_local;
-		}
-
-	      /* Swap in the relocs.  */
-	      erela = external_relocs;
-	      erelaend = erela + section->reloc_count;
-	      irela = internal_relocs;
-	      for (; erela < erelaend; erela++, irela++)
-		bfd_elf64_swap_reloca_in (input_bfd, erela, irela);
-
-	      /* We're done with the external relocs, free them.  */
-	      free (external_relocs);
+		goto error_ret_free_local;
 
 	      /* Now examine each relocation.  */
 	      irela = internal_relocs;
@@ -4787,7 +5114,10 @@ ppc64_elf_size_stubs (output_bfd, stub_b
 		  if (r_type >= (unsigned int) R_PPC_max)
 		    {
 		      bfd_set_error (bfd_error_bad_value);
-		      goto error_ret_free_internal;
+		    error_ret_free_internal:
+		      if (elf_section_data (section)->relocs == NULL)
+			free (internal_relocs);
+		      goto error_ret_free_local;
 		    }
 
 		  /* Only look for stubs on branch instructions.  */
@@ -4880,7 +5210,7 @@ ppc64_elf_size_stubs (output_bfd, stub_b
 		  if (stub_entry == NULL)
 		    {
 		      free (stub_name);
-		      goto error_ret_free_local;
+		      goto error_ret_free_internal;
 		    }
 
 		  stub_entry->target_value = sym_value;
@@ -4891,7 +5221,8 @@ ppc64_elf_size_stubs (output_bfd, stub_b
 		}
 
 	      /* We're done with the internal relocs, free them.  */
-	      free (internal_relocs);
+	      if (elf_section_data (section)->relocs == NULL)
+		free (internal_relocs);
 	    }
 	}
 
@@ -5151,7 +5482,7 @@ ppc64_elf_relocate_section (output_bfd, 
   TOCstart = elf_gp (output_bfd);
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
-  is_opd = strcmp (bfd_get_section_name (abfd, input_section), ".opd") == 0;
+  is_opd = elf_section_data (input_section)->tdata != NULL;
 
   rel = relocs;
   relend = relocs + input_section->reloc_count;
@@ -5202,6 +5533,15 @@ ppc64_elf_relocate_section (output_bfd, 
 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
 	  /* rel may have changed, update our copy of addend.  */
 	  addend = rel->r_addend;
+
+	  if (elf_section_data (sec) != NULL)
+	    {
+	      long *opd_sym_adjust;
+
+	      opd_sym_adjust = (long *) elf_section_data (sec)->tdata;
+	      if (opd_sym_adjust != NULL && sym->st_value % 24 == 0)
+		relocation += opd_sym_adjust[sym->st_value / 24];
+	    }
 	}
       else
 	{
@@ -5650,8 +5990,7 @@ ppc64_elf_relocate_section (output_bfd, 
 			     shared lib.  (I believe this is a generic
 			     bug in binutils handling of weak syms.)
 			     In these cases we won't use the opd
-			     entry in this lib;  We ought to edit the
-			     opd section to remove unused entries.  */
+			     entry in this lib.  */
 			  unresolved_reloc = false;
 			}
 		      outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
Index: bfd/elf64-ppc.h
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.h,v
retrieving revision 1.3
diff -u -p -r1.3 elf64-ppc.h
--- bfd/elf64-ppc.h	2 May 2002 09:48:13 -0000	1.3
+++ bfd/elf64-ppc.h	1 Jul 2002 07:47:56 -0000
@@ -17,6 +17,8 @@ You should have received a copy of the G
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
+boolean ppc64_elf_mark_entry_syms
+  PARAMS ((struct bfd_link_info *));
 bfd_vma ppc64_elf_toc
   PARAMS ((bfd *));
 int ppc64_elf_setup_section_lists
Index: bfd/elf64-s390.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-s390.c,v
retrieving revision 1.26
diff -u -p -r1.26 elf64-s390.c
--- bfd/elf64-s390.c	5 Jun 2002 13:32:01 -0000	1.26
+++ bfd/elf64-s390.c	1 Jul 2002 07:47:58 -0000
@@ -45,7 +45,7 @@ static boolean elf_s390_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
 	   const Elf_Internal_Rela *));
 static asection *elf_s390_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean elf_s390_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
@@ -855,8 +855,8 @@ elf_s390_check_relocs (abfd, info, sec, 
    relocation.  */
 
 static asection *
-elf_s390_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+elf_s390_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -886,9 +886,7 @@ elf_s390_gc_mark_hook (abfd, info, rel, 
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf64-sh64.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-sh64.c,v
retrieving revision 1.13
diff -u -p -r1.13 elf64-sh64.c
--- bfd/elf64-sh64.c	25 Jun 2002 06:21:53 -0000	1.13
+++ bfd/elf64-sh64.c	1 Jul 2002 07:48:01 -0000
@@ -127,7 +127,7 @@ static bfd_byte *sh_elf64_get_relocated_
 static boolean sh_elf64_set_mach_from_flags PARAMS ((bfd *));
 static boolean sh_elf64_set_private_flags PARAMS ((bfd *, flagword));
 static asection *sh_elf64_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean sh_elf64_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
@@ -2450,12 +2450,12 @@ sh_elf64_merge_private_data (ibfd, obfd)
    relocation.  */
 
 static asection *
-sh_elf64_gc_mark_hook (abfd, info, rel, h, sym)
-       bfd *abfd;
-       struct bfd_link_info *info ATTRIBUTE_UNUSED;
-       Elf_Internal_Rela *rel;
-       struct elf_link_hash_entry *h;
-       Elf_Internal_Sym *sym;
+sh_elf64_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     Elf_Internal_Rela *rel;
+     struct elf_link_hash_entry *h;
+     Elf_Internal_Sym *sym;
 {
   if (h != NULL)
     {
@@ -2481,9 +2481,7 @@ sh_elf64_gc_mark_hook (abfd, info, rel, 
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elf64-x86-64.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-x86-64.c,v
retrieving revision 1.44
diff -u -p -r1.44 elf64-x86-64.c
--- bfd/elf64-x86-64.c	1 Jul 2002 06:42:27 -0000	1.44
+++ bfd/elf64-x86-64.c	1 Jul 2002 07:48:03 -0000
@@ -142,7 +142,7 @@ static boolean elf64_x86_64_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *sec,
 	   const Elf_Internal_Rela *));
 static asection *elf64_x86_64_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 
 static boolean elf64_x86_64_gc_sweep_hook
@@ -856,8 +856,8 @@ elf64_x86_64_check_relocs (abfd, info, s
    relocation.	*/
 
 static asection *
-elf64_x86_64_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+elf64_x86_64_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -887,9 +887,7 @@ elf64_x86_64_gc_mark_hook (abfd, info, r
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elflink.h
===================================================================
RCS file: /cvs/src/src/bfd/elflink.h,v
retrieving revision 1.171
diff -u -p -r1.171 elflink.h
--- bfd/elflink.h	25 Jun 2002 09:40:43 -0000	1.171
+++ bfd/elflink.h	1 Jul 2002 07:48:10 -0000
@@ -7729,7 +7729,7 @@ elf_finish_pointer_linker_section (outpu
 static boolean elf_gc_mark
   PARAMS ((struct bfd_link_info *info, asection *sec,
 	   asection * (*gc_mark_hook)
-	     PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+	     PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 		      struct elf_link_hash_entry *, Elf_Internal_Sym *))));
 
 static boolean elf_gc_sweep
@@ -7759,7 +7759,7 @@ elf_gc_mark (info, sec, gc_mark_hook)
      struct bfd_link_info *info;
      asection *sec;
      asection * (*gc_mark_hook)
-       PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+       PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 		struct elf_link_hash_entry *, Elf_Internal_Sym *));
 {
   boolean ret;
@@ -7862,17 +7862,17 @@ elf_gc_mark (info, sec, gc_mark_hook)
 				  (const PTR) locshndx,
 				  &s);
 	      if (ELF_ST_BIND (s.st_info) == STB_LOCAL)
-		rsec = (*gc_mark_hook) (sec->owner, info, rel, NULL, &s);
+		rsec = (*gc_mark_hook) (sec, info, rel, NULL, &s);
 	      else
 		{
 		  h = sym_hashes[r_symndx - extsymoff];
-		  rsec = (*gc_mark_hook) (sec->owner, info, rel, h, NULL);
+		  rsec = (*gc_mark_hook) (sec, info, rel, h, NULL);
 		}
 	    }
 	  else if (r_symndx >= nlocsyms)
 	    {
 	      h = sym_hashes[r_symndx - extsymoff];
-	      rsec = (*gc_mark_hook) (sec->owner, info, rel, h, NULL);
+	      rsec = (*gc_mark_hook) (sec, info, rel, h, NULL);
 	    }
 	  else
 	    {
@@ -7881,7 +7881,7 @@ elf_gc_mark (info, sec, gc_mark_hook)
 				  (const PTR) (locsyms + r_symndx),
 				  (const PTR) locshndx,
 				  &s);
-	      rsec = (*gc_mark_hook) (sec->owner, info, rel, NULL, &s);
+	      rsec = (*gc_mark_hook) (sec, info, rel, NULL, &s);
 	    }
 
 	  if (rsec && !rsec->gc_mark)
@@ -8129,7 +8129,7 @@ elf_gc_sections (abfd, info)
   boolean ok = true;
   bfd *sub;
   asection * (*gc_mark_hook)
-    PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+    PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	     struct elf_link_hash_entry *h, Elf_Internal_Sym *));
 
   if (!get_elf_backend_data (abfd)->can_gc_sections
Index: bfd/elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.11
diff -u -p -r1.11 elfxx-mips.c
--- bfd/elfxx-mips.c	25 Jun 2002 06:21:53 -0000	1.11
+++ bfd/elfxx-mips.c	1 Jul 2002 07:48:17 -0000
@@ -6274,8 +6274,8 @@ _bfd_mips_elf_modify_segment_map (abfd)
    relocation.  */
 
 asection *
-_bfd_mips_elf_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+_bfd_mips_elf_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -6285,7 +6285,7 @@ _bfd_mips_elf_gc_mark_hook (abfd, info, 
 
   if (h != NULL)
     {
-      switch (ELF_R_TYPE (abfd, rel->r_info))
+      switch (ELF_R_TYPE (sec->owner, rel->r_info))
 	{
 	case R_MIPS_GNU_VTINHERIT:
 	case R_MIPS_GNU_VTENTRY:
@@ -6307,9 +6307,7 @@ _bfd_mips_elf_gc_mark_hook (abfd, info, 
 	}
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
Index: bfd/elfxx-mips.h
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.h,v
retrieving revision 1.3
diff -u -p -r1.3 elfxx-mips.h
--- bfd/elfxx-mips.h	5 Jun 2002 10:31:47 -0000	1.3
+++ bfd/elfxx-mips.h	1 Jul 2002 07:48:17 -0000
@@ -62,7 +62,7 @@ extern int _bfd_mips_elf_additional_prog
 extern boolean _bfd_mips_elf_modify_segment_map
   PARAMS ((bfd *));
 extern asection * _bfd_mips_elf_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
 extern boolean _bfd_mips_elf_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
Index: include/bfdlink.h
===================================================================
RCS file: /cvs/src/src/include/bfdlink.h,v
retrieving revision 1.19
diff -u -p -r1.19 bfdlink.h
--- include/bfdlink.h	7 Jun 2002 14:56:01 -0000	1.19
+++ include/bfdlink.h	1 Jul 2002 07:48:21 -0000
@@ -183,6 +183,12 @@ extern void bfd_link_hash_traverse
 /* Add an entry to the undefs list.  */
 extern void bfd_link_add_undef
   PARAMS ((struct bfd_link_hash_table *, struct bfd_link_hash_entry *));
+
+struct bfd_sym_chain
+{
+  struct bfd_sym_chain *next;
+  const char *name;
+};
 
 /* This structure holds all the information needed to communicate
    between BFD and the linker when doing a link.  */
@@ -191,33 +197,46 @@ struct bfd_link_info
 {
   /* Function callbacks.  */
   const struct bfd_link_callbacks *callbacks;
+
   /* true if BFD should generate a relocateable object file.  */
   boolean relocateable;
-  /* true if BFD should generate relocation information in the final executable.  */
+
+  /* true if BFD should generate relocation information in the final
+     executable.  */
   boolean emitrelocations;
+
   /* true if BFD should generate a "task linked" object file,
-     similar to relocatable but also with globals converted to statics. */
+     similar to relocatable but also with globals converted to
+     statics.  */
   boolean task_link;
+
   /* true if BFD should generate a shared object.  */
   boolean shared;
+
   /* true if BFD should pre-bind symbols in a shared object.  */
   boolean symbolic;
+
   /* true if BFD should export all symbols in the dynamic symbol table
      of an executable, rather than only those used.  */
   boolean export_dynamic;
+
   /* true if shared objects should be linked directly, not shared.  */
   boolean static_link;
+
   /* true if the output file should be in a traditional format.  This
      is equivalent to the setting of the BFD_TRADITIONAL_FORMAT flag
      on the output file, but may be checked when reading the input
      files.  */
   boolean traditional_format;
+
   /* true if we want to produced optimized output files.  This might
      need much more time and therefore must be explicitly selected.  */
   boolean optimize;
+
   /* true if BFD should generate errors for undefined symbols
      even if generating a shared object.  */
   boolean no_undefined;
+
   /* true if BFD should allow undefined symbols in shared objects even
      when no_undefined is set to disallow undefined symbols.  The net
      result will be that undefined symbols in regular objects will
@@ -231,39 +250,55 @@ struct bfd_link_info
      select an appropriate memset function.  Apparently it is also
      normal for HPPA shared libraries to have undefined symbols.  */
   boolean allow_shlib_undefined;
-  /* True if ok to have multiple definition.  */
+
+  /* true if ok to have multiple definition.  */
   boolean allow_multiple_definition;
+
   /* Which symbols to strip.  */
   enum bfd_link_strip strip;
+
   /* Which local symbols to discard.  */
   enum bfd_link_discard discard;
+
   /* true if symbols should be retained in memory, false if they
      should be freed and reread.  */
   boolean keep_memory;
+
   /* The list of input BFD's involved in the link.  These are chained
      together via the link_next field.  */
   bfd *input_bfds;
+
   /* If a symbol should be created for each input BFD, this is section
      where those symbols should be placed.  It must be a section in
      the output BFD.  It may be NULL, in which case no such symbols
      will be created.  This is to support CREATE_OBJECT_SYMBOLS in the
      linker command language.  */
   asection *create_object_symbols_section;
+
+  /* List of global symbol names that are starting points for marking
+     sections against garbage collection.  */
+  struct bfd_sym_chain *gc_sym_list;
+
   /* Hash table handled by BFD.  */
   struct bfd_link_hash_table *hash;
+
   /* Hash table of symbols to keep.  This is NULL unless strip is
      strip_some.  */
   struct bfd_hash_table *keep_hash;
+
   /* true if every symbol should be reported back via the notice
      callback.  */
   boolean notice_all;
+
   /* Hash table of symbols to report back via the notice callback.  If
      this is NULL, and notice_all is false, then no symbols are
      reported back.  */
   struct bfd_hash_table *notice_hash;
+
   /* Hash table of symbols which are being wrapped (the --wrap linker
      option).  If this is NULL, no symbols are being wrapped.  */
   struct bfd_hash_table *wrap_hash;
+
   /* If a base output file is wanted, then this points to it */
   PTR base_file;
 
@@ -275,6 +310,7 @@ struct bfd_link_info
   /* The function to call when the executable or shared object is
      loaded.  */
   const char *init_function;
+
   /* The function to call when the executable or shared object is
      unloaded.  */
   const char *fini_function;
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.90
diff -u -p -r1.90 ldlang.c
--- ld/ldlang.c	10 Jun 2002 16:12:04 -0000	1.90
+++ ld/ldlang.c	1 Jul 2002 07:48:30 -0000
@@ -184,7 +184,7 @@ lang_output_section_statement_type *abs_
 lang_statement_list_type lang_output_section_statement;
 lang_statement_list_type *stat_ptr = &statement_list;
 lang_statement_list_type file_chain = { NULL, NULL };
-const char *entry_symbol = NULL;
+struct bfd_sym_chain entry_symbol = { NULL, NULL };
 const char *entry_section = ".text";
 boolean entry_from_cmdline;
 boolean lang_has_input_file = false;
@@ -2030,13 +2030,9 @@ lang_reasonable_defaults ()
    on a list, then, once the output file has been opened, transfer the
    name to the symbol table.  */
 
-typedef struct ldlang_undef_chain_list
-{
-  struct ldlang_undef_chain_list *next;
-  char *name;
-}                       ldlang_undef_chain_list_type;
+typedef struct bfd_sym_chain ldlang_undef_chain_list_type;
 
-static ldlang_undef_chain_list_type *ldlang_undef_chain_list_head;
+#define ldlang_undef_chain_list_head entry_symbol.next
 
 void
 ldlang_add_undef (name)
@@ -3523,15 +3519,16 @@ lang_finish ()
   else
     warn = true;
 
-  if (entry_symbol == (char *) NULL)
+  if (entry_symbol.name == (const char *) NULL)
     {
       /* No entry has been specified.  Look for start, but don't warn
 	 if we don't find it.  */
-      entry_symbol = "start";
+      entry_symbol.name = "start";
       warn = false;
     }
 
-  h = bfd_link_hash_lookup (link_info.hash, entry_symbol, false, false, true);
+  h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name,
+			    false, false, true);
   if (h != (struct bfd_link_hash_entry *) NULL
       && (h->type == bfd_link_hash_defined
 	  || h->type == bfd_link_hash_defweak)
@@ -3544,7 +3541,7 @@ lang_finish ()
 				    h->u.def.section->output_section)
 	     + h->u.def.section->output_offset);
       if (! bfd_set_start_address (output_bfd, val))
-	einfo (_("%P%F:%s: can't set start address\n"), entry_symbol);
+	einfo (_("%P%F:%s: can't set start address\n"), entry_symbol.name);
     }
   else
     {
@@ -3553,7 +3550,7 @@ lang_finish ()
 
       /* We couldn't find the entry symbol.  Try parsing it as a
          number.  */
-      val = bfd_scan_vma (entry_symbol, &send, 0);
+      val = bfd_scan_vma (entry_symbol.name, &send, 0);
       if (*send == '\0')
 	{
 	  if (! bfd_set_start_address (output_bfd, val))
@@ -3570,7 +3567,8 @@ lang_finish ()
 	    {
 	      if (warn)
 		einfo (_("%P: warning: cannot find entry symbol %s; defaulting to %V\n"),
-		       entry_symbol, bfd_get_section_vma (output_bfd, ts));
+		       entry_symbol.name,
+		       bfd_get_section_vma (output_bfd, ts));
 	      if (! bfd_set_start_address (output_bfd,
 					   bfd_get_section_vma (output_bfd,
 								ts)))
@@ -3580,7 +3578,7 @@ lang_finish ()
 	    {
 	      if (warn)
 		einfo (_("%P: warning: cannot find entry symbol %s; not setting start address\n"),
-		       entry_symbol);
+		       entry_symbol.name);
 	    }
 	}
     }
@@ -4146,25 +4144,16 @@ static void
 lang_gc_sections ()
 {
   struct bfd_link_hash_entry *h;
-  ldlang_undef_chain_list_type *ulist, fake_list_start;
+  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.
-     Handle the entry symbol at the same time.  */
-
-  if (entry_symbol != NULL)
-    {
-      fake_list_start.next = ldlang_undef_chain_list_head;
-      fake_list_start.name = (char *) entry_symbol;
-      ulist = &fake_list_start;
-    }
-  else
-    ulist = ldlang_undef_chain_list_head;
+  /* Keep all sections containing symbols undefined on the command-line,
+     and the section containing the entry symbol.  */
 
-  for (; ulist; ulist = ulist->next)
+  for (ulist = link_info.gc_sym_list; ulist; ulist = ulist->next)
     {
       h = bfd_link_hash_lookup (link_info.hash, ulist->name,
 				false, false, false);
@@ -4201,6 +4190,10 @@ lang_process ()
   current_target = default_target;
   open_input_bfds (statement_list.head, false);
 
+  link_info.gc_sym_list = &entry_symbol;
+  if (entry_symbol.name == NULL)
+    link_info.gc_sym_list = ldlang_undef_chain_list_head;
+
   ldemul_after_open ();
 
   already_linked_table_free ();
@@ -4391,11 +4384,11 @@ lang_add_entry (name, cmdline)
      const char *name;
      boolean cmdline;
 {
-  if (entry_symbol == NULL
+  if (entry_symbol.name == NULL
       || cmdline
       || ! entry_from_cmdline)
     {
-      entry_symbol = name;
+      entry_symbol.name = name;
       entry_from_cmdline = cmdline;
     }
 }
Index: ld/ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.19
diff -u -p -r1.19 ldlang.h
--- ld/ldlang.h	7 May 2002 11:04:54 -0000	1.19
+++ ld/ldlang.h	1 Jul 2002 07:48:30 -0000
@@ -364,7 +364,7 @@ extern etree_type *base;
 extern lang_statement_list_type *stat_ptr;
 extern boolean delete_output_file_on_failure;
 
-extern const char *entry_symbol;
+extern struct bfd_sym_chain entry_symbol;
 extern const char *entry_section;
 extern boolean entry_from_cmdline;
 extern lang_statement_list_type file_chain;
Index: ld/ldlex.l
===================================================================
RCS file: /cvs/src/src/ld/ldlex.l,v
retrieving revision 1.15
diff -u -p -r1.15 ldlex.l
--- ld/ldlex.l	8 Jun 2002 07:39:45 -0000	1.15
+++ ld/ldlex.l	1 Jul 2002 07:48:31 -0000
@@ -37,6 +37,7 @@ This was written by steve chamberlain
 #include "bfd.h"
 #include "sysdep.h"
 #include "safe-ctype.h"
+#include "bfdlink.h"
 #include "ld.h"
 #include "ldmisc.h"
 #include "ldexp.h"
Index: ld/ldmain.c
===================================================================
RCS file: /cvs/src/src/ld/ldmain.c,v
retrieving revision 1.48
diff -u -p -r1.48 ldmain.c
--- ld/ldmain.c	7 Jun 2002 14:56:00 -0000	1.48
+++ ld/ldmain.c	1 Jul 2002 07:48:31 -0000
@@ -245,6 +245,7 @@ main (argc, argv)
   link_info.keep_memory = true;
   link_info.input_bfds = NULL;
   link_info.create_object_symbols_section = NULL;
+  link_info.gc_sym_list = NULL;
   link_info.hash = NULL;
   link_info.keep_hash = NULL;
   link_info.notice_all = false;
Index: ld/emulparams/elf64ppc.sh
===================================================================
RCS file: /cvs/src/src/ld/emulparams/elf64ppc.sh,v
retrieving revision 1.4
diff -u -p -r1.4 elf64ppc.sh
--- ld/emulparams/elf64ppc.sh	22 May 2002 08:44:53 -0000	1.4
+++ ld/emulparams/elf64ppc.sh	1 Jul 2002 07:48:33 -0000
@@ -27,7 +27,7 @@ OTHER_GOT_RELOC_SECTIONS="
   .rela.toc	${RELOCATING-0} : { *(.rela.toc) }"
 OTHER_READWRITE_SECTIONS="
   .toc1		${RELOCATING-0}${RELOCATING+ALIGN(8)} : { *(.toc1) }
-  .opd		${RELOCATING-0}${RELOCATING+ALIGN(8)} : { *(.opd) }"
+  .opd		${RELOCATING-0}${RELOCATING+ALIGN(8)} : { KEEP (*(.opd)) }"
 
 # Treat a host that matches the target with the possible exception of "64"
 # in the name as if it were native.
Index: ld/emultempl/aix.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/aix.em,v
retrieving revision 1.25
diff -u -p -r1.25 aix.em
--- ld/emultempl/aix.em	22 May 2002 09:04:47 -0000	1.25
+++ ld/emultempl/aix.em	1 Jul 2002 07:48:33 -0000
@@ -9,7 +9,7 @@ cat >e${EMULATION_NAME}.c <<EOF
 /* This file is is generated by a shell script.  DO NOT EDIT! */
 
 /* AIX emulation code for ${EMULATION_NAME}
-   Copyright 1991, 1993, 1995, 1996, 1997, 1998, 2000, 2001
+   Copyright 1991, 1993, 1995, 1996, 1997, 1998, 2000, 2001, 2002
    Free Software Foundation, Inc.
    Written by Steve Chamberlain <sac@cygnus.com>
    AIX support by Ian Lance Taylor <ian@cygnus.com>
@@ -682,7 +682,7 @@ gld${EMULATION_NAME}_before_allocation (
 
   /* Let the XCOFF backend set up the .loader section.  */
   if (!bfd_xcoff_size_dynamic_sections 
-      (output_bfd, &link_info, libpath,	entry_symbol, file_align,
+      (output_bfd, &link_info, libpath,	entry_symbol.name, file_align,
        maxstack, maxdata, gc && !unix_ld ? true : false,
        modtype,	textro ? true : false, unix_ld, special_sections, 
        rtld ? true : false))
Index: ld/emultempl/armcoff.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/armcoff.em,v
retrieving revision 1.12
diff -u -p -r1.12 armcoff.em
--- ld/emultempl/armcoff.em	22 May 2002 09:02:04 -0000	1.12
+++ ld/emultempl/armcoff.em	1 Jul 2002 07:48:33 -0000
@@ -4,7 +4,7 @@ cat >e${EMULATION_NAME}.c <<EOF
 /* This file is is generated by a shell script.  DO NOT EDIT! */
 
 /* emulate the original gld for the given ${EMULATION_NAME}
-   Copyright 1991, 1993, 1996, 1997, 1998, 1999, 2000, 2001
+   Copyright 1991, 1993, 1996, 1997, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
    Written by Steve Chamberlain steve@cygnus.com
 
@@ -203,10 +203,10 @@ gld${EMULATION_NAME}_finish PARAMS((void
       
       sprintf_vma (buffer + 2, val);
 
-      if (entry_symbol != NULL && entry_from_cmdline)
+      if (entry_symbol.name != NULL && entry_from_cmdline)
 	einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
-	       thumb_entry_symbol, entry_symbol);
-      entry_symbol = buffer;
+	       thumb_entry_symbol, entry_symbol.name);
+      entry_symbol.name = buffer;
     }
   else
     einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol);
Index: ld/emultempl/armelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/armelf.em,v
retrieving revision 1.26
diff -u -p -r1.26 armelf.em
--- ld/emultempl/armelf.em	29 May 2002 16:02:57 -0000	1.26
+++ ld/emultempl/armelf.em	1 Jul 2002 07:48:33 -0000
@@ -172,10 +172,10 @@ arm_elf_finish ()
       
       sprintf_vma (buffer + 2, val);
 
-      if (entry_symbol != NULL && entry_from_cmdline)
+      if (entry_symbol.name != NULL && entry_from_cmdline)
 	einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
-	       thumb_entry_symbol, entry_symbol);
-      entry_symbol = buffer;
+	       thumb_entry_symbol, entry_symbol.name);
+      entry_symbol.name = buffer;
     }
   else
     einfo (_("%P: warning: connot find thumb start symbol %s\n"),
Index: ld/emultempl/pe.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/pe.em,v
retrieving revision 1.64
diff -u -p -r1.64 pe.em
--- ld/emultempl/pe.em	7 Jun 2002 14:56:00 -0000	1.64
+++ ld/emultempl/pe.em	1 Jul 2002 07:48:38 -0000
@@ -758,8 +758,8 @@ gld_${EMULATION_NAME}_after_parse ()
      opened, so registering the symbol as undefined will make a
      difference.  */
 
-  if (! link_info.relocateable && entry_symbol != NULL)
-    ldlang_add_undef (entry_symbol);
+  if (! link_info.relocateable && entry_symbol.name != NULL)
+    ldlang_add_undef (entry_symbol.name);
 }
 
 /* pe-dll.c directly accesses pe_data_import_dll,
@@ -1418,10 +1418,10 @@ gld_${EMULATION_NAME}_finish ()
 
 	  sprintf_vma (buffer + 2, val);
 
-	  if (entry_symbol != NULL && entry_from_cmdline)
+	  if (entry_symbol.name != NULL && entry_from_cmdline)
 	    einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
-		   thumb_entry_symbol, entry_symbol);
-	  entry_symbol = buffer;
+		   thumb_entry_symbol, entry_symbol.name);
+	  entry_symbol.name = buffer;
 	}
       else
 	einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol);
Index: ld/emultempl/ppc64elf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/ppc64elf.em,v
retrieving revision 1.8
diff -u -p -r1.8 ppc64elf.em
--- ld/emultempl/ppc64elf.em	7 Jun 2002 15:09:21 -0000	1.8
+++ ld/emultempl/ppc64elf.em	1 Jul 2002 07:48:38 -0000
@@ -42,6 +42,7 @@ static bfd_signed_vma group_size = 1;
 static int dotsyms = 1;
 
 static void ppc_create_output_section_statements PARAMS ((void));
+static void ppc_after_open PARAMS ((void));
 static asection *ppc_add_stub_section PARAMS ((const char *, asection *));
 static void ppc_layout_sections_again PARAMS ((void));
 static void gld${EMULATION_NAME}_after_allocation PARAMS ((void));
@@ -71,6 +72,17 @@ ppc_create_output_section_statements ()
   ldlang_add_file (stub_file);
 }
 
+static void
+ppc_after_open ()
+{
+  if (!ppc64_elf_mark_entry_syms (&link_info))
+    {
+      einfo ("%X%P: can not mark entry symbols %E\n");
+      return;
+    }
+
+  gld${EMULATION_NAME}_after_open ();
+}
 
 struct hook_stub_info
 {
@@ -473,6 +485,7 @@ PARSE_AND_LIST_ARGS_CASES='
 
 # Put these extra ppc64elf routines in ld_${EMULATION_NAME}_emulation
 #
+LDEMUL_AFTER_OPEN=ppc_after_open
 LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
 LDEMUL_FINISH=gld${EMULATION_NAME}_finish
 LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=ppc_create_output_section_statements



More information about the Binutils mailing list