This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

consolidate elf symbol reading


This patch deletes a whole lot of duplicated code.  The best kind of
patch.  :-)  I've moved all the raw elf symbol reading code into a new
function, bfd_elf_get_elf_syms.  Saved 20k in ld's text size on an
x86 --enable-targets=all build.

Slightly more controversially, I've also changed caching of local syms
from raw ELF to internal form.  This uses more memory per sym, 20 vs.
16 bytes for ELF32, 32 vs 24 bytes for ELF64, but I feel the change is
well worth it because:
 a) swapping syms in isn't a zero cost operation.
 b) some back-ends edit local syms, requiring the syms to be swapped
    back out to a raw cache.
 c) >64k elf section support complicates caching of raw symbols.
    You'd need to cache symbol section extension entries as well, or
    include code to read the SHT_SYMTAB_SHNDX section with every place
    that reads symbols.

While doing this, I noticed that freeing of internal relocs and other
possibly cached info, was wrong.  Typically, code looked like:

  free_relocs = NULL;
  relocs = _bfd_elfNN_link_read_relocs (abfd, sec, NULL, NULL,
					info->keep_memory);
  if (relocs == NULL)
    goto error_return;
  if (!info->keep_memory)
    free_relocs = relocs;
  .
  .
  .
  if (free_relocs != NULL)
    free (free_relocs);

This is wrong for !info->keep_memory when the relocs are already
cached before the link_read_relocs call, as can happen for backends
that edit relocs like powerpc64-linux.  Correct is to set free_relocs
with

  if (elf_section_data (sec)->relocs != relocs)
    free_relocs = relocs;

or to dispense with free_relocs entirely as I've done.

bfd/ChangeLog
	* elf-bfd.h (struct elf_reloc_cookie): Remove locsym_shndx,
	change type of locsyms.
	(bfd_elf_get_elf_syms): Declare.
	* elf.c (bfd_elf_get_elf_syms): New function.
	(group_signature): Use bfd_elf_get_elf_syms.
	(bfd_section_from_r_symndx): Likewise.
	* elfcode.h (elf_slurp_symbol_table): Likewise.
	* elflink.h (elf_link_is_defined_archive_symbol): Likewise.
	(elf_link_add_object_symbols): Likewise.  Reorganise to increase
	locality of various data structures.  Properly free internal relocs.
	(elf_bfd_final_link): Properly free internal relocs.
	(elf_link_check_versioned_symbol): Use bfd_elf_get_elf_syms.
	(elf_link_input_bfd): Likewise.
	(elf_gc_mark): Likewise.  Properly free internal relocs.
	(elf_gc_sweep): Properly free internal relocs.
	(elf_reloc_symbol_deleted_p): No need to swap syms in.
	(elf_bfd_discard_info): Use bfd_elf_get_elf_syms.  Properly free
	internal relocs.
	* elf-m10200.c (mn10200_elf_relax_section): Use bfd_elf_get_elf_syms.
	Properly free possibly cached info.
	(mn10200_elf_relax_delete_bytes): Remove symbol swapping code.
	(mn10200_elf_symbol_address_p): Pass in internal syms.  Remove
	symbol swapping code.
	(mn10200_elf_get_relocated_section_contents): Use bfd_elf_get_elf_syms.
	Properly free possibly cached info.
	* elf-m10300.c (mn10300_elf_relax_section): As above for elf-m10200.c.
	(mn10300_elf_relax_delete_bytes): Likewise.
	(mn10300_elf_symbol_address_p): Likewise.
	(mn10300_elf_get_relocated_section_contents): Likewise.
	* elf32-h8300.c (elf32_h8_relax_section): As above for elf-m10200.c.
	(elf32_h8_relax_delete_bytes): Likewise.
	(elf32_h8_symbol_address_p): Likewise.
	(elf32_h8_get_relocated_section_contents): Likewise.
	* elf32-m32r.c (m32r_elf_relax_section): As above for elf-m10200.c.
	(m32r_elf_relax_delete_bytes): Likewise.
	(m32r_elf_get_relocated_section_contents): Likewise.
	* elf32-sh.c (sh_elf_reloc_loop): Free section contents using
	elf_section_data to determine whether cached.
	(sh_elf_relax_section): As above for elf-m10200.c.
	(sh_elf_relax_delete_bytes): Likewise.
	(sh_elf_get_relocated_section_contents): Likewise.
	* elf32-xstormy16.c (xstormy16_elf_relax_section): As above.
	* elf64-alpha.c (elf64_alpha_relax_section): As above.  Also delay
	reading of local syms.
	* elf64-mmix.c (mmix_elf_relax_section): Likewise.
	* elf64-sh64.c (sh_elf64_get_relocated_section_contents): As above.
	* elfxx-ia64.c (elfNN_ia64_relax_section): As above.
	* elfxx-mips.c (_bfd_mips_elf_check_relocs): Properly free internal
	relocs.
	* elf32-arm.h (bfd_elf32_arm_process_before_allocation): Properly
	free internal relocs and section contents.  Don't read symbols.
	* elf32-hppa.c (get_local_syms): Use bfd_elf_get_elf_syms.
	(elf32_hppa_size_stubs): Don't free local syms.
	* elf32-m68k.c (bfd_m68k_elf32_create_embedded_relocs): Delay
	reading of local syms.  Use bfd_elf_get_elf_syms.  Properly free
	possibly cached info.
	* elf32-mips.c (bfd_mips_elf32_create_embedded_relocs): Likewise.
	* elf64-hppa.c (elf64_hppa_check_relocs): Use bfd_elf_get_elf_syms.
	* elf64-ppc.c (struct ppc_link_hash_table): Delete bfd_count and
	all_local_syms.
	(get_local_syms): Delete function.
	(edit_opd): Use bfd_elf_get_elf_syms.  Free on error exit.  Cache
	on exit.
	(ppc64_elf_size_stubs): Use bfd_elf_get_elf_syms.  Free/cache on exit.

-- 
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.82
diff -u -p -r1.82 elf-bfd.h
--- bfd/elf-bfd.h	1 Jul 2002 08:06:40 -0000	1.82
+++ bfd/elf-bfd.h	7 Jul 2002 06:58:46 -0000
@@ -417,8 +417,7 @@ enum elf_reloc_type_class {
 struct elf_reloc_cookie
 {
   Elf_Internal_Rela *rels, *rel, *relend;
-  PTR locsyms;
-  PTR locsym_shndx;
+  Elf_Internal_Sym *locsyms;
   bfd *abfd;
   size_t locsymcount;
   size_t extsymoff;
@@ -1216,6 +1215,9 @@ extern char *bfd_elf_string_from_elf_sec
   PARAMS ((bfd *, unsigned, unsigned));
 extern char *bfd_elf_get_str_section
   PARAMS ((bfd *, unsigned));
+extern Elf_Internal_Sym *bfd_elf_get_elf_syms
+  PARAMS ((bfd *, Elf_Internal_Shdr *, size_t, size_t,
+	   Elf_Internal_Sym *, PTR, Elf_External_Sym_Shndx *));
 
 extern boolean _bfd_elf_copy_private_bfd_data
   PARAMS ((bfd *, bfd *));
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.152
diff -u -p -r1.152 elf.c
--- bfd/elf.c	4 Jul 2002 13:26:30 -0000	1.152
+++ bfd/elf.c	7 Jul 2002 06:58:52 -0000
@@ -352,6 +352,107 @@ bfd_elf_string_from_elf_section (abfd, s
   return ((char *) hdr->contents) + strindex;
 }
 
+/* Read and convert symbols to internal format.
+   SYMCOUNT specifies the number of symbols to read, starting from
+   symbol SYMOFFSET.  If any of INTSYM_BUF, EXTSYM_BUF or EXTSHNDX_BUF
+   are non-NULL, they are used to store the internal symbols, external
+   symbols, and symbol section index extensions, respectively.  */
+
+Elf_Internal_Sym *
+bfd_elf_get_elf_syms (ibfd, symtab_hdr, symcount, symoffset,
+		      intsym_buf, extsym_buf, extshndx_buf)
+     bfd *ibfd;
+     Elf_Internal_Shdr *symtab_hdr;
+     size_t symcount;
+     size_t symoffset;
+     Elf_Internal_Sym *intsym_buf;
+     PTR extsym_buf;
+     Elf_External_Sym_Shndx *extshndx_buf;
+{
+  Elf_Internal_Shdr *shndx_hdr;
+  PTR alloc_ext;
+  const PTR esym;
+  Elf_External_Sym_Shndx *alloc_extshndx;
+  Elf_External_Sym_Shndx *shndx;
+  Elf_Internal_Sym *isym;
+  Elf_Internal_Sym *isymend;
+  struct elf_backend_data *bed;
+  size_t extsym_size;
+  bfd_size_type amt;
+  file_ptr pos;
+
+  if (symcount == 0)
+    return intsym_buf;
+
+  /* Normal syms might have section extension entries.  */
+  shndx_hdr = NULL;
+  if (symtab_hdr == &elf_tdata (ibfd)->symtab_hdr)
+    shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr;
+
+  /* Read the symbols.  */
+  alloc_ext = NULL;
+  alloc_extshndx = NULL;
+  bed = get_elf_backend_data (ibfd);
+  extsym_size = bed->s->sizeof_sym;
+  amt = symcount * extsym_size;
+  pos = symtab_hdr->sh_offset + symoffset * extsym_size;
+  if (extsym_buf == NULL)
+    {
+      alloc_ext = bfd_malloc (amt);
+      extsym_buf = alloc_ext;
+    }
+  if (extsym_buf == NULL
+      || bfd_seek (ibfd, pos, SEEK_SET) != 0
+      || bfd_bread (extsym_buf, amt, ibfd) != amt)
+    {
+      intsym_buf = NULL;
+      goto out;
+    }
+
+  if (shndx_hdr == NULL || shndx_hdr->sh_size == 0)
+    extshndx_buf = NULL;
+  else
+    {
+      amt = symcount * sizeof (Elf_External_Sym_Shndx);
+      pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx);
+      if (extshndx_buf == NULL)
+	{
+	  alloc_extshndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+	  extshndx_buf = alloc_extshndx;
+	}
+      if (extshndx_buf == NULL
+	  || bfd_seek (ibfd, pos, SEEK_SET) != 0
+	  || bfd_bread (extshndx_buf, amt, ibfd) != amt)
+	{
+	  intsym_buf = NULL;
+	  goto out;
+	}
+    }
+
+  if (intsym_buf == NULL)
+    {
+      bfd_size_type amt = symcount * sizeof (Elf_Internal_Sym);
+      intsym_buf = (Elf_Internal_Sym *) bfd_malloc (amt);
+      if (intsym_buf == NULL)
+	goto out;
+    }
+
+  /* Convert the symbols to internal form.  */
+  isymend = intsym_buf + symcount;
+  for (esym = extsym_buf, isym = intsym_buf, shndx = extshndx_buf;
+       isym < isymend;
+       esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL)
+    (*bed->s->swap_symbol_in) (ibfd, esym, (const PTR) shndx, isym);
+
+ out:
+  if (alloc_ext != NULL)
+    free (alloc_ext);
+  if (alloc_extshndx != NULL)
+    free (alloc_extshndx);
+
+  return intsym_buf;
+}
+
 /* Elf_Internal_Shdr->contents is an array of these for SHT_GROUP
    sections.  The first element is the flags, the rest are section
    pointers.  */
@@ -369,11 +470,7 @@ group_signature (abfd, ghdr)
      bfd *abfd;
      Elf_Internal_Shdr *ghdr;
 {
-  struct elf_backend_data *bed;
-  file_ptr pos;
-  bfd_size_type amt;
   Elf_Internal_Shdr *hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   unsigned char esym[sizeof (Elf64_External_Sym)];
   Elf_External_Sym_Shndx eshndx;
   Elf_Internal_Sym isym;
@@ -386,29 +483,10 @@ group_signature (abfd, ghdr)
 
   /* Go read the symbol.  */
   hdr = &elf_tdata (abfd)->symtab_hdr;
-  bed = get_elf_backend_data (abfd);
-  amt = bed->s->sizeof_sym;
-  pos = hdr->sh_offset + ghdr->sh_info * amt;
-  if (bfd_seek (abfd, pos, SEEK_SET) != 0
-      || bfd_bread (esym, amt, abfd) != amt)
+  if (bfd_elf_get_elf_syms (abfd, hdr, 1, ghdr->sh_info,
+			    &isym, esym, &eshndx) == NULL)
     return NULL;
 
-  /* And possibly the symbol section index extension.  */
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-  if (elf_elfsections (abfd) != NULL
-      && elf_elfsections (abfd)[shndx_hdr->sh_link] == hdr)
-    {
-      amt = sizeof (Elf_External_Sym_Shndx);
-      pos = shndx_hdr->sh_offset + ghdr->sh_info * amt;
-      if (bfd_seek (abfd, pos, SEEK_SET) != 0
-	  || bfd_bread ((PTR) &eshndx, amt, abfd) != amt)
-	return NULL;
-    }
-
-  /* Convert to internal format.  */
-  (*bed->s->swap_symbol_in) (abfd, (const PTR *) &esym, (const PTR *) &eshndx,
-			     &isym);
-
   /* Look up the symbol name.  */
   iname = isym.st_name;
   shindex = hdr->sh_link;
@@ -1976,50 +2054,19 @@ bfd_section_from_r_symndx (abfd, cache, 
      asection *sec;
      unsigned long r_symndx;
 {
-  unsigned char esym_shndx[4];
-  unsigned int isym_shndx;
   Elf_Internal_Shdr *symtab_hdr;
-  file_ptr pos;
-  bfd_size_type amt;
+  unsigned char esym[sizeof (Elf64_External_Sym)];
+  Elf_External_Sym_Shndx eshndx;
+  Elf_Internal_Sym isym;
   unsigned int ent = r_symndx % LOCAL_SYM_CACHE_SIZE;
 
   if (cache->abfd == abfd && cache->indx[ent] == r_symndx)
     return cache->sec[ent];
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  pos = symtab_hdr->sh_offset;
-  if (get_elf_backend_data (abfd)->s->sizeof_sym
-      == sizeof (Elf64_External_Sym))
-    {
-      pos += r_symndx * sizeof (Elf64_External_Sym);
-      pos += offsetof (Elf64_External_Sym, st_shndx);
-      amt = sizeof (((Elf64_External_Sym *) 0)->st_shndx);
-    }
-  else
-    {
-      pos += r_symndx * sizeof (Elf32_External_Sym);
-      pos += offsetof (Elf32_External_Sym, st_shndx);
-      amt = sizeof (((Elf32_External_Sym *) 0)->st_shndx);
-    }
-  if (bfd_seek (abfd, pos, SEEK_SET) != 0
-      || bfd_bread ((PTR) esym_shndx, amt, abfd) != amt)
+  if (bfd_elf_get_elf_syms (abfd, symtab_hdr, 1, r_symndx,
+			    &isym, esym, &eshndx) == NULL)
     return NULL;
-  isym_shndx = H_GET_16 (abfd, esym_shndx);
-
-  if (isym_shndx == SHN_XINDEX)
-    {
-      Elf_Internal_Shdr *shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-      if (shndx_hdr->sh_size != 0)
-	{
-	  pos = shndx_hdr->sh_offset;
-	  pos += r_symndx * sizeof (Elf_External_Sym_Shndx);
-	  amt = sizeof (Elf_External_Sym_Shndx);
-	  if (bfd_seek (abfd, pos, SEEK_SET) != 0
-	      || bfd_bread ((PTR) esym_shndx, amt, abfd) != amt)
-	    return NULL;
-	  isym_shndx = H_GET_32 (abfd, esym_shndx);
-	}
-    }
 
   if (cache->abfd != abfd)
     {
@@ -2028,10 +2075,10 @@ bfd_section_from_r_symndx (abfd, cache, 
     }
   cache->indx[ent] = r_symndx;
   cache->sec[ent] = sec;
-  if (isym_shndx < SHN_LORESERVE || isym_shndx > SHN_HIRESERVE)
+  if (isym.st_shndx < SHN_LORESERVE || isym.st_shndx > SHN_HIRESERVE)
     {
       asection *s;
-      s = bfd_section_from_elf_index (abfd, isym_shndx);
+      s = bfd_section_from_elf_index (abfd, isym.st_shndx);
       if (s != NULL)
 	cache->sec[ent] = s;
     }
Index: bfd/elfcode.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcode.h,v
retrieving revision 1.32
diff -u -p -r1.32 elfcode.h
--- bfd/elfcode.h	25 Jun 2002 06:21:53 -0000	1.32
+++ bfd/elfcode.h	7 Jul 2002 06:58:53 -0000
@@ -1133,10 +1133,12 @@ elf_slurp_symbol_table (abfd, symptrs, d
   unsigned long symcount;	/* Number of external ELF symbols */
   elf_symbol_type *sym;		/* Pointer to current bfd symbol */
   elf_symbol_type *symbase;	/* Buffer for generated bfd symbols */
-  Elf_Internal_Sym i_sym;
-  Elf_External_Sym *x_symp = NULL;
-  Elf_External_Sym_Shndx *x_shndx = NULL;
-  Elf_External_Versym *x_versymp = NULL;
+  Elf_Internal_Sym *isym;
+  Elf_Internal_Sym *isymend;
+  Elf_Internal_Sym *isymbuf = NULL;
+  Elf_External_Versym *xver;
+  Elf_External_Versym *xverbuf = NULL;
+  struct elf_backend_data *ebd;
   bfd_size_type amt;
 
   /* Read each raw ELF symbol, converting from external ELF form to
@@ -1151,24 +1153,8 @@ elf_slurp_symbol_table (abfd, symptrs, d
 
   if (! dynamic)
     {
-      Elf_Internal_Shdr *shndx_hdr;
-
       hdr = &elf_tdata (abfd)->symtab_hdr;
-      shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
       verhdr = NULL;
-
-      /* If we have a SHT_SYMTAB_SHNDX section for the symbol table,
-	 read the raw contents.  */
-      if (elf_elfsections (abfd) != NULL
-	  && elf_elfsections (abfd)[shndx_hdr->sh_link] == hdr)
-	{
-	  amt = shndx_hdr->sh_size;
-	  x_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	  if (x_shndx == NULL
-	      || bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread ((PTR) x_shndx, amt, abfd) != amt)
-	    goto error_return;
-	}
     }
   else
     {
@@ -1187,39 +1173,24 @@ elf_slurp_symbol_table (abfd, symptrs, d
 	}
     }
 
-  if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0)
-    goto error_return;
-
+  ebd = get_elf_backend_data (abfd);
   symcount = hdr->sh_size / sizeof (Elf_External_Sym);
-
   if (symcount == 0)
     sym = symbase = NULL;
   else
     {
-      unsigned long i;
-
-      if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0)
-	goto error_return;
+      isymbuf = bfd_elf_get_elf_syms (abfd, hdr, symcount, 0,
+				      NULL, NULL, NULL);
+      if (isymbuf == NULL)
+	return -1;
 
       amt = symcount;
       amt *= sizeof (elf_symbol_type);
       symbase = (elf_symbol_type *) bfd_zalloc (abfd, amt);
       if (symbase == (elf_symbol_type *) NULL)
 	goto error_return;
-      sym = symbase;
-
-      /* Temporarily allocate room for the raw ELF symbols.  */
-      amt = symcount;
-      amt *= sizeof (Elf_External_Sym);
-      x_symp = (Elf_External_Sym *) bfd_malloc (amt);
-      if (x_symp == NULL)
-	goto error_return;
-
-      if (bfd_bread ((PTR) x_symp, amt, abfd) != amt)
-	goto error_return;
 
       /* Read the raw ELF version symbol information.  */
-
       if (verhdr != NULL
 	  && verhdr->sh_size / sizeof (Elf_External_Versym) != symcount)
 	{
@@ -1239,42 +1210,40 @@ elf_slurp_symbol_table (abfd, symptrs, d
 	  if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0)
 	    goto error_return;
 
-	  x_versymp = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size);
-	  if (x_versymp == NULL && verhdr->sh_size != 0)
+	  xverbuf = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size);
+	  if (xverbuf == NULL && verhdr->sh_size != 0)
 	    goto error_return;
 
-	  if (bfd_bread ((PTR) x_versymp, verhdr->sh_size, abfd)
+	  if (bfd_bread ((PTR) xverbuf, verhdr->sh_size, abfd)
 	      != verhdr->sh_size)
 	    goto error_return;
 	}
 
       /* Skip first symbol, which is a null dummy.  */
-      for (i = 1; i < symcount; i++)
+      xver = xverbuf;
+      if (xver != NULL)
+	++xver;
+      isymend = isymbuf + symcount;
+      for (isym = isymbuf + 1, sym = symbase; isym < isymend; isym++, sym++)
 	{
-	  elf_swap_symbol_in (abfd, (const PTR) (x_symp + i),
-			      (const PTR) (x_shndx + (x_shndx ? i : 0)),
-			      &i_sym);
-	  memcpy (&sym->internal_elf_sym, &i_sym, sizeof (Elf_Internal_Sym));
-#ifdef ELF_KEEP_EXTSYM
-	  memcpy (&sym->native_elf_sym, x_symp + i, sizeof (Elf_External_Sym));
-#endif
+	  memcpy (&sym->internal_elf_sym, isym, sizeof (Elf_Internal_Sym));
 	  sym->symbol.the_bfd = abfd;
 
 	  sym->symbol.name = bfd_elf_string_from_elf_section (abfd,
 							      hdr->sh_link,
-							      i_sym.st_name);
+							      isym->st_name);
 
-	  sym->symbol.value = i_sym.st_value;
+	  sym->symbol.value = isym->st_value;
 
-	  if (i_sym.st_shndx == SHN_UNDEF)
+	  if (isym->st_shndx == SHN_UNDEF)
 	    {
 	      sym->symbol.section = bfd_und_section_ptr;
 	    }
-	  else if (i_sym.st_shndx < SHN_LORESERVE
-		   || i_sym.st_shndx > SHN_HIRESERVE)
+	  else if (isym->st_shndx < SHN_LORESERVE
+		   || isym->st_shndx > SHN_HIRESERVE)
 	    {
 	      sym->symbol.section = section_from_elf_index (abfd,
-							    i_sym.st_shndx);
+							    isym->st_shndx);
 	      if (sym->symbol.section == NULL)
 		{
 		  /* This symbol is in a section for which we did not
@@ -1283,18 +1252,18 @@ elf_slurp_symbol_table (abfd, symptrs, d
 		  sym->symbol.section = bfd_abs_section_ptr;
 		}
 	    }
-	  else if (i_sym.st_shndx == SHN_ABS)
+	  else if (isym->st_shndx == SHN_ABS)
 	    {
 	      sym->symbol.section = bfd_abs_section_ptr;
 	    }
-	  else if (i_sym.st_shndx == SHN_COMMON)
+	  else if (isym->st_shndx == SHN_COMMON)
 	    {
 	      sym->symbol.section = bfd_com_section_ptr;
 	      /* Elf puts the alignment into the `value' field, and
 		 the size into the `size' field.  BFD wants to see the
 		 size in the value field, and doesn't care (at the
 		 moment) about the alignment.  */
-	      sym->symbol.value = i_sym.st_size;
+	      sym->symbol.value = isym->st_size;
 	    }
 	  else
 	    sym->symbol.section = bfd_abs_section_ptr;
@@ -1304,14 +1273,13 @@ elf_slurp_symbol_table (abfd, symptrs, d
 	  if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
 	    sym->symbol.value -= sym->symbol.section->vma;
 
-	  switch (ELF_ST_BIND (i_sym.st_info))
+	  switch (ELF_ST_BIND (isym->st_info))
 	    {
 	    case STB_LOCAL:
 	      sym->symbol.flags |= BSF_LOCAL;
 	      break;
 	    case STB_GLOBAL:
-	      if (i_sym.st_shndx != SHN_UNDEF
-		  && i_sym.st_shndx != SHN_COMMON)
+	      if (isym->st_shndx != SHN_UNDEF && isym->st_shndx != SHN_COMMON)
 		sym->symbol.flags |= BSF_GLOBAL;
 	      break;
 	    case STB_WEAK:
@@ -1319,7 +1287,7 @@ elf_slurp_symbol_table (abfd, symptrs, d
 	      break;
 	    }
 
-	  switch (ELF_ST_TYPE (i_sym.st_info))
+	  switch (ELF_ST_TYPE (isym->st_info))
 	    {
 	    case STT_SECTION:
 	      sym->symbol.flags |= BSF_SECTION_SYM | BSF_DEBUGGING;
@@ -1338,31 +1306,24 @@ elf_slurp_symbol_table (abfd, symptrs, d
 	  if (dynamic)
 	    sym->symbol.flags |= BSF_DYNAMIC;
 
-	  if (x_versymp != NULL)
+	  if (xver != NULL)
 	    {
 	      Elf_Internal_Versym iversym;
 
-	      _bfd_elf_swap_versym_in (abfd, x_versymp + i, &iversym);
+	      _bfd_elf_swap_versym_in (abfd, xver, &iversym);
 	      sym->version = iversym.vs_vers;
+	      xver++;
 	    }
 
 	  /* Do some backend-specific processing on this symbol.  */
-	  {
-	    struct elf_backend_data *ebd = get_elf_backend_data (abfd);
-	    if (ebd->elf_backend_symbol_processing)
-	      (*ebd->elf_backend_symbol_processing) (abfd, &sym->symbol);
-	  }
-
-	  sym++;
+	  if (ebd->elf_backend_symbol_processing)
+	    (*ebd->elf_backend_symbol_processing) (abfd, &sym->symbol);
 	}
     }
 
   /* Do some backend-specific processing on this symbol table.  */
-  {
-    struct elf_backend_data *ebd = get_elf_backend_data (abfd);
-    if (ebd->elf_backend_symbol_table_processing)
-      (*ebd->elf_backend_symbol_table_processing) (abfd, symbase, symcount);
-  }
+  if (ebd->elf_backend_symbol_table_processing)
+    (*ebd->elf_backend_symbol_table_processing) (abfd, symbase, symcount);
 
   /* We rely on the zalloc to clear out the final symbol entry.  */
 
@@ -1382,21 +1343,17 @@ elf_slurp_symbol_table (abfd, symptrs, d
       *symptrs = 0;		/* Final null pointer */
     }
 
-  if (x_shndx != NULL)
-    free (x_shndx);
-  if (x_versymp != NULL)
-    free (x_versymp);
-  if (x_symp != NULL)
-    free (x_symp);
+  if (xverbuf != NULL)
+    free (xverbuf);
+  if (isymbuf != NULL && hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
   return symcount;
 
 error_return:
-  if (x_shndx != NULL)
-    free (x_shndx);
-  if (x_versymp != NULL)
-    free (x_versymp);
-  if (x_symp != NULL)
-    free (x_symp);
+  if (xverbuf != NULL)
+    free (xverbuf);
+  if (isymbuf != NULL && hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
   return -1;
 }
 
Index: bfd/elflink.h
===================================================================
RCS file: /cvs/src/src/bfd/elflink.h,v
retrieving revision 1.173
diff -u -p -r1.173 elflink.h
--- bfd/elflink.h	4 Jul 2002 13:26:30 -0000	1.173
+++ bfd/elflink.h	7 Jul 2002 06:59:01 -0000
@@ -149,18 +149,13 @@ elf_link_is_defined_archive_symbol (abfd
      carsym * symdef;
 {
   Elf_Internal_Shdr * hdr;
-  Elf_Internal_Shdr * shndx_hdr;
-  Elf_External_Sym *  esym;
-  Elf_External_Sym *  esymend;
-  Elf_External_Sym *  buf = NULL;
-  Elf_External_Sym_Shndx * shndx_buf = NULL;
-  Elf_External_Sym_Shndx * shndx;
   bfd_size_type symcount;
   bfd_size_type extsymcount;
   bfd_size_type extsymoff;
-  boolean result = false;
-  file_ptr pos;
-  bfd_size_type amt;
+  Elf_Internal_Sym *isymbuf;
+  Elf_Internal_Sym *isym;
+  Elf_Internal_Sym *isymend;
+  boolean result;
 
   abfd = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);
   if (abfd == (bfd *) NULL)
@@ -178,15 +173,9 @@ elf_link_is_defined_archive_symbol (abfd
 
   /* Select the appropriate symbol table.  */
   if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
-    {
-      hdr = &elf_tdata (abfd)->symtab_hdr;
-      shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-    }
+    hdr = &elf_tdata (abfd)->symtab_hdr;
   else
-    {
-      hdr = &elf_tdata (abfd)->dynsymtab_hdr;
-      shndx_hdr = NULL;
-    }
+    hdr = &elf_tdata (abfd)->dynsymtab_hdr;
 
   symcount = hdr->sh_size / sizeof (Elf_External_Sym);
 
@@ -203,58 +192,34 @@ elf_link_is_defined_archive_symbol (abfd
       extsymoff = hdr->sh_info;
     }
 
-  amt = extsymcount * sizeof (Elf_External_Sym);
-  buf = (Elf_External_Sym *) bfd_malloc (amt);
-  if (buf == NULL && extsymcount != 0)
-    return false;
-
-  /* Read in the symbol table.
-     FIXME:  This ought to be cached somewhere.  */
-  pos = hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym);
-  if (bfd_seek (abfd, pos, SEEK_SET) != 0
-      || bfd_bread ((PTR) buf, amt, abfd) != amt)
-    goto error_exit;
-
-  if (shndx_hdr != NULL && shndx_hdr->sh_size != 0)
-    {
-      amt = extsymcount * sizeof (Elf_External_Sym_Shndx);
-      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-      if (shndx_buf == NULL && extsymcount != 0)
-	goto error_exit;
-
-      pos = shndx_hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym_Shndx);
-      if (bfd_seek (abfd, pos, SEEK_SET) != 0
-	  || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
-	goto error_exit;
-    }
+  if (extsymcount == 0)
+    return false;
+
+  /* Read in the symbol table.  */
+  isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff,
+				  NULL, NULL, NULL);
+  if (isymbuf == NULL)
+    return false;
 
   /* Scan the symbol table looking for SYMDEF.  */
-  esymend = buf + extsymcount;
-  for (esym = buf, shndx = shndx_buf;
-       esym < esymend;
-       esym++, shndx = (shndx != NULL ? shndx + 1 : NULL))
+  result = false;
+  for (isym = isymbuf, isymend = isymbuf + extsymcount; isym < isymend; isym++)
     {
-      Elf_Internal_Sym sym;
-      const char * name;
-
-      elf_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, &sym);
+      const char *name;
 
-      name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name);
+      name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
+					      isym->st_name);
       if (name == (const char *) NULL)
 	break;
 
       if (strcmp (name, symdef->name) == 0)
 	{
-	  result = is_global_data_symbol_definition (abfd, & sym);
+	  result = is_global_data_symbol_definition (abfd, isym);
 	  break;
 	}
     }
 
- error_exit:
-  if (shndx_buf != NULL)
-    free (shndx_buf);
-  if (buf != NULL)
-    free (buf);
+  free (isymbuf);
 
   return result;
 }
@@ -1186,25 +1151,20 @@ elf_link_add_object_symbols (abfd, info)
 				   asection *, const Elf_Internal_Rela *));
   boolean collect;
   Elf_Internal_Shdr *hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   bfd_size_type symcount;
   bfd_size_type extsymcount;
   bfd_size_type extsymoff;
-  Elf_External_Sym *buf = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
-  Elf_External_Sym_Shndx *shndx;
   struct elf_link_hash_entry **sym_hash;
   boolean dynamic;
   Elf_External_Versym *extversym = NULL;
   Elf_External_Versym *ever;
-  Elf_External_Dyn *dynbuf = NULL;
   struct elf_link_hash_entry *weaks;
-  Elf_External_Sym *esym;
-  Elf_External_Sym *esymend;
+  Elf_Internal_Sym *isymbuf = NULL;
+  Elf_Internal_Sym *isym;
+  Elf_Internal_Sym *isymend;
   struct elf_backend_data *bed;
   boolean dt_needed;
   struct elf_link_hash_table * hash_table;
-  file_ptr pos;
   bfd_size_type amt;
 
   hash_table = elf_hash_table (info);
@@ -1303,85 +1263,7 @@ elf_link_add_object_symbols (abfd, info)
 	}
     }
 
-  /* If this is a dynamic object, we always link against the .dynsym
-     symbol table, not the .symtab symbol table.  The dynamic linker
-     will only see the .dynsym symbol table, so there is no reason to
-     look at .symtab for a dynamic object.  */
-
-  if (! dynamic || elf_dynsymtab (abfd) == 0)
-    {
-      hdr = &elf_tdata (abfd)->symtab_hdr;
-      shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-    }
-  else
-    {
-      hdr = &elf_tdata (abfd)->dynsymtab_hdr;
-      shndx_hdr = NULL;
-    }
-
-  if (dynamic)
-    {
-      /* Read in any version definitions.  */
-
-      if (! _bfd_elf_slurp_version_tables (abfd))
-	goto error_return;
-
-      /* Read in the symbol versions, but don't bother to convert them
-	 to internal format.  */
-      if (elf_dynversym (abfd) != 0)
-	{
-	  Elf_Internal_Shdr *versymhdr;
-
-	  versymhdr = &elf_tdata (abfd)->dynversym_hdr;
-	  extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);
-	  if (extversym == NULL)
-	    goto error_return;
-	  amt = versymhdr->sh_size;
-	  if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread ((PTR) extversym, amt, abfd) != amt)
-	    goto error_return;
-	}
-    }
-
-  symcount = hdr->sh_size / sizeof (Elf_External_Sym);
-
-  /* The sh_info field of the symtab header tells us where the
-     external symbols start.  We don't care about the local symbols at
-     this point.  */
-  if (elf_bad_symtab (abfd))
-    {
-      extsymcount = symcount;
-      extsymoff = 0;
-    }
-  else
-    {
-      extsymcount = symcount - hdr->sh_info;
-      extsymoff = hdr->sh_info;
-    }
-
-  amt = extsymcount * sizeof (Elf_External_Sym);
-  buf = (Elf_External_Sym *) bfd_malloc (amt);
-  if (buf == NULL && extsymcount != 0)
-    goto error_return;
-
-  if (shndx_hdr != NULL && shndx_hdr->sh_size != 0)
-    {
-      amt = extsymcount * sizeof (Elf_External_Sym_Shndx);
-      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-      if (shndx_buf == NULL && extsymcount != 0)
-	goto error_return;
-    }
-
-  /* We store a pointer to the hash table entry for each external
-     symbol.  */
-  amt = extsymcount * sizeof (struct elf_link_hash_entry *);
-  sym_hash = (struct elf_link_hash_entry **) bfd_alloc (abfd, amt);
-  if (sym_hash == NULL)
-    goto error_return;
-  elf_sym_hashes (abfd) = sym_hash;
-
   dt_needed = false;
-
   if (! dynamic)
     {
       /* If we are creating a shared library, create all the dynamic
@@ -1431,6 +1313,7 @@ elf_link_add_object_symbols (abfd, info)
       s = bfd_get_section_by_name (abfd, ".dynamic");
       if (s != NULL)
 	{
+	  Elf_External_Dyn *dynbuf = NULL;
 	  Elf_External_Dyn *extdyn;
 	  Elf_External_Dyn *extdynend;
 	  int elfsec;
@@ -1444,11 +1327,11 @@ elf_link_add_object_symbols (abfd, info)
 
 	  if (! bfd_get_section_contents (abfd, s, (PTR) dynbuf,
 					  (file_ptr) 0, s->_raw_size))
-	    goto error_return;
+	    goto error_free_dyn;
 
 	  elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
 	  if (elfsec == -1)
-	    goto error_return;
+	    goto error_free_dyn;
 	  shlink = elf_elfsections (abfd)[elfsec]->sh_link;
 
 	  extdyn = dynbuf;
@@ -1465,7 +1348,7 @@ elf_link_add_object_symbols (abfd, info)
 		  unsigned int tagv = dyn.d_un.d_val;
 		  name = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
 		  if (name == NULL)
-		    goto error_return;
+		    goto error_free_dyn;
 		}
 	      if (dyn.d_tag == DT_NEEDED)
 		{
@@ -1477,11 +1360,11 @@ elf_link_add_object_symbols (abfd, info)
 		  n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
 		  fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
 		  if (n == NULL || fnm == NULL)
-		    goto error_return;
+		    goto error_free_dyn;
 		  amt = strlen (fnm) + 1;
 		  anm = bfd_alloc (abfd, amt);
 		  if (anm == NULL)
-		    goto error_return;
+		    goto error_free_dyn;
 		  memcpy (anm, fnm, (size_t) amt);
 		  n->name = anm;
 		  n->by = abfd;
@@ -1509,11 +1392,11 @@ elf_link_add_object_symbols (abfd, info)
 		  n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
 		  fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
 		  if (n == NULL || fnm == NULL)
-		    goto error_return;
+		    goto error_free_dyn;
 		  amt = strlen (fnm) + 1;
 		  anm = bfd_alloc (abfd, amt);
 		  if (anm == NULL)
-		    goto error_return;
+		    goto error_free_dyn;
 		  memcpy (anm, fnm, (size_t) amt);
 		  n->name = anm;
 		  n->by = abfd;
@@ -1537,11 +1420,15 @@ elf_link_add_object_symbols (abfd, info)
 		  n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
 		  fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
 		  if (n == NULL || fnm == NULL)
-		    goto error_return;
+		    goto error_free_dyn;
 		  amt = strlen (fnm) + 1;
 		  anm = bfd_alloc (abfd, amt);
 		  if (anm == NULL)
-		    goto error_return;
+		    {
+		    error_free_dyn:
+		      free (dynbuf);
+		      goto error_return;
+		    }
 		  memcpy (anm, fnm, (size_t) amt);
 		  n->name = anm;
 		  n->by = abfd;
@@ -1556,7 +1443,6 @@ elf_link_add_object_symbols (abfd, info)
 	    }
 
 	  free (dynbuf);
-	  dynbuf = NULL;
 	}
 
       /* We do not want to include any of the sections in a dynamic
@@ -1606,10 +1492,6 @@ elf_link_add_object_symbols (abfd, info)
 		  if (dyn.d_tag == DT_NEEDED
 		      && dyn.d_un.d_val == strindex)
 		    {
-		      if (buf != NULL)
-			free (buf);
-		      if (extversym != NULL)
-			free (extversym);
 		      _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
 		      return true;
 		    }
@@ -1627,31 +1509,79 @@ elf_link_add_object_symbols (abfd, info)
       elf_dt_name (abfd) = name;
     }
 
-  pos = hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym);
-  amt = extsymcount * sizeof (Elf_External_Sym);
-  if (bfd_seek (abfd, pos, SEEK_SET) != 0
-      || bfd_bread ((PTR) buf, amt, abfd) != amt)
-    goto error_return;
+  /* If this is a dynamic object, we always link against the .dynsym
+     symbol table, not the .symtab symbol table.  The dynamic linker
+     will only see the .dynsym symbol table, so there is no reason to
+     look at .symtab for a dynamic object.  */
+
+  if (! dynamic || elf_dynsymtab (abfd) == 0)
+    hdr = &elf_tdata (abfd)->symtab_hdr;
+  else
+    hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+
+  symcount = hdr->sh_size / sizeof (Elf_External_Sym);
 
-  if (shndx_hdr != NULL && shndx_hdr->sh_size != 0)
+  /* The sh_info field of the symtab header tells us where the
+     external symbols start.  We don't care about the local symbols at
+     this point.  */
+  if (elf_bad_symtab (abfd))
+    {
+      extsymcount = symcount;
+      extsymoff = 0;
+    }
+  else
     {
-      amt = extsymcount * sizeof (Elf_External_Sym_Shndx);
-      pos = shndx_hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym_Shndx);
-      if (bfd_seek (abfd, pos, SEEK_SET) != 0
-	  || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
+      extsymcount = symcount - hdr->sh_info;
+      extsymoff = hdr->sh_info;
+    }
+
+  sym_hash = NULL;
+  if (extsymcount != 0)
+    {
+      isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff,
+				      NULL, NULL, NULL);
+      if (isymbuf == NULL)
 	goto error_return;
+
+      /* We store a pointer to the hash table entry for each external
+	 symbol.  */
+      amt = extsymcount * sizeof (struct elf_link_hash_entry *);
+      sym_hash = (struct elf_link_hash_entry **) bfd_alloc (abfd, amt);
+      if (sym_hash == NULL)
+	goto error_free_sym;
+      elf_sym_hashes (abfd) = sym_hash;
+    }
+
+  if (dynamic)
+    {
+      /* Read in any version definitions.  */
+      if (! _bfd_elf_slurp_version_tables (abfd))
+	goto error_free_sym;
+
+      /* Read in the symbol versions, but don't bother to convert them
+	 to internal format.  */
+      if (elf_dynversym (abfd) != 0)
+	{
+	  Elf_Internal_Shdr *versymhdr;
+
+	  versymhdr = &elf_tdata (abfd)->dynversym_hdr;
+	  extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);
+	  if (extversym == NULL)
+	    goto error_free_sym;
+	  amt = versymhdr->sh_size;
+	  if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0
+	      || bfd_bread ((PTR) extversym, amt, abfd) != amt)
+	    goto error_free_vers;
+	}
     }
 
   weaks = NULL;
 
   ever = extversym != NULL ? extversym + extsymoff : NULL;
-  esymend = buf + extsymcount;
-  for (esym = buf, shndx = shndx_buf;
-       esym < esymend;
-       esym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL),
-	 shndx = (shndx != NULL ? shndx + 1 : NULL))
+  for (isym = isymbuf, isymend = isymbuf + extsymcount;
+       isym < isymend;
+       isym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL))
     {
-      Elf_Internal_Sym sym;
       int bind;
       bfd_vma value;
       asection *sec;
@@ -1666,14 +1596,12 @@ elf_link_add_object_symbols (abfd, info)
 
       override = false;
 
-      elf_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, &sym);
-
       flags = BSF_NO_FLAGS;
       sec = NULL;
-      value = sym.st_value;
+      value = isym->st_value;
       *sym_hash = NULL;
 
-      bind = ELF_ST_BIND (sym.st_info);
+      bind = ELF_ST_BIND (isym->st_info);
       if (bind == STB_LOCAL)
 	{
 	  /* This should be impossible, since ELF requires that all
@@ -1684,8 +1612,8 @@ elf_link_add_object_symbols (abfd, info)
 	}
       else if (bind == STB_GLOBAL)
 	{
-	  if (sym.st_shndx != SHN_UNDEF
-	      && sym.st_shndx != SHN_COMMON)
+	  if (isym->st_shndx != SHN_UNDEF
+	      && isym->st_shndx != SHN_COMMON)
 	    flags = BSF_GLOBAL;
 	}
       else if (bind == STB_WEAK)
@@ -1695,35 +1623,37 @@ elf_link_add_object_symbols (abfd, info)
 	  /* Leave it up to the processor backend.  */
 	}
 
-      if (sym.st_shndx == SHN_UNDEF)
+      if (isym->st_shndx == SHN_UNDEF)
 	sec = bfd_und_section_ptr;
-      else if (sym.st_shndx < SHN_LORESERVE || sym.st_shndx > SHN_HIRESERVE)
+      else if (isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
 	{
-	  sec = section_from_elf_index (abfd, sym.st_shndx);
+	  sec = section_from_elf_index (abfd, isym->st_shndx);
 	  if (sec == NULL)
 	    sec = bfd_abs_section_ptr;
 	  else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
 	    value -= sec->vma;
 	}
-      else if (sym.st_shndx == SHN_ABS)
+      else if (isym->st_shndx == SHN_ABS)
 	sec = bfd_abs_section_ptr;
-      else if (sym.st_shndx == SHN_COMMON)
+      else if (isym->st_shndx == SHN_COMMON)
 	{
 	  sec = bfd_com_section_ptr;
 	  /* What ELF calls the size we call the value.  What ELF
 	     calls the value we call the alignment.  */
-	  value = sym.st_size;
+	  value = isym->st_size;
 	}
       else
 	{
 	  /* Leave it up to the processor backend.  */
 	}
 
-      name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name);
+      name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
+					      isym->st_name);
       if (name == (const char *) NULL)
-	goto error_return;
+	goto error_free_vers;
 
-      if (sym.st_shndx == SHN_COMMON && ELF_ST_TYPE (sym.st_info) == STT_TLS)
+      if (isym->st_shndx == SHN_COMMON
+	  && ELF_ST_TYPE (isym->st_info) == STT_TLS)
 	{
 	  asection *tcomm = bfd_get_section_by_name (abfd, ".tcommon");
 
@@ -1735,15 +1665,15 @@ elf_link_add_object_symbols (abfd, info)
 							   | SEC_IS_COMMON
 							   | SEC_LINKER_CREATED
 							   | SEC_THREAD_LOCAL)))
-		goto error_return;
+		goto error_free_vers;
 	    }
 	  sec = tcomm;
 	}
       else if (add_symbol_hook)
 	{
-	  if (! (*add_symbol_hook) (abfd, info, &sym, &name, &flags, &sec,
+	  if (! (*add_symbol_hook) (abfd, info, isym, &name, &flags, &sec,
 				    &value))
-	    goto error_return;
+	    goto error_free_vers;
 
 	  /* The hook function sets the name to NULL if this symbol
 	     should be skipped for some reason.  */
@@ -1755,7 +1685,7 @@ elf_link_add_object_symbols (abfd, info)
       if (sec == (asection *) NULL)
 	{
 	  bfd_set_error (bfd_error_bad_value);
-	  goto error_return;
+	  goto error_free_vers;
 	}
 
       if (bfd_is_und_section (sec)
@@ -1789,7 +1719,7 @@ elf_link_add_object_symbols (abfd, info)
 		  size_t namelen, verlen, newlen;
 		  char *newname, *p;
 
-		  if (sym.st_shndx != SHN_UNDEF)
+		  if (isym->st_shndx != SHN_UNDEF)
 		    {
 		      if (vernum > elf_tdata (abfd)->dynverdef_hdr.sh_info)
 			{
@@ -1798,7 +1728,7 @@ elf_link_add_object_symbols (abfd, info)
 			     bfd_archive_filename (abfd), name, vernum,
 			     elf_tdata (abfd)->dynverdef_hdr.sh_info);
 			  bfd_set_error (bfd_error_bad_value);
-			  goto error_return;
+			  goto error_free_vers;
 			}
 		      else if (vernum > 1)
 			verstr =
@@ -1838,7 +1768,7 @@ elf_link_add_object_symbols (abfd, info)
 			    (_("%s: %s: invalid needed version %d"),
 			     bfd_archive_filename (abfd), name, vernum);
 			  bfd_set_error (bfd_error_bad_value);
-			  goto error_return;
+			  goto error_free_vers;
 			}
 		    }
 
@@ -1846,12 +1776,12 @@ elf_link_add_object_symbols (abfd, info)
 		  verlen = strlen (verstr);
 		  newlen = namelen + verlen + 2;
 		  if ((iver.vs_vers & VERSYM_HIDDEN) == 0
-		      && sym.st_shndx != SHN_UNDEF)
+		      && isym->st_shndx != SHN_UNDEF)
 		    ++newlen;
 
 		  newname = (char *) bfd_alloc (abfd, (bfd_size_type) newlen);
 		  if (newname == NULL)
-		    goto error_return;
+		    goto error_free_vers;
 		  memcpy (newname, name, namelen);
 		  p = newname + namelen;
 		  *p++ = ELF_VER_CHR;
@@ -1859,7 +1789,7 @@ elf_link_add_object_symbols (abfd, info)
 		     we add another @ to the name.  This indicates the
 		     default version of the symbol.  */
 		  if ((iver.vs_vers & VERSYM_HIDDEN) == 0
-		      && sym.st_shndx != SHN_UNDEF)
+		      && isym->st_shndx != SHN_UNDEF)
 		    *p++ = ELF_VER_CHR;
 		  memcpy (p, verstr, verlen + 1);
 
@@ -1867,10 +1797,10 @@ elf_link_add_object_symbols (abfd, info)
 		}
 	    }
 
-	  if (! elf_merge_symbol (abfd, info, name, &sym, &sec, &value,
+	  if (! elf_merge_symbol (abfd, info, name, isym, &sec, &value,
 				  sym_hash, &override, &type_change_ok,
 				  &size_change_ok, dt_needed))
-	    goto error_return;
+	    goto error_free_vers;
 
 	  if (override)
 	    definition = false;
@@ -1898,7 +1828,7 @@ elf_link_add_object_symbols (abfd, info)
       if (! (_bfd_generic_link_add_one_symbol
 	     (info, abfd, name, flags, sec, value, (const char *) NULL,
 	      false, collect, (struct bfd_link_hash_entry **) sym_hash)))
-	goto error_return;
+	goto error_free_vers;
 
       h = *sym_hash;
       while (h->root.type == bfd_link_hash_indirect
@@ -1910,7 +1840,7 @@ elf_link_add_object_symbols (abfd, info)
       if (dynamic
 	  && definition
 	  && (flags & BSF_WEAK) != 0
-	  && ELF_ST_TYPE (sym.st_info) != STT_FUNC
+	  && ELF_ST_TYPE (isym->st_info) != STT_FUNC
 	  && info->hash->creator->flavour == bfd_target_elf_flavour
 	  && h->weakdef == NULL)
 	{
@@ -1932,16 +1862,16 @@ elf_link_add_object_symbols (abfd, info)
 	}
 
       /* Set the alignment of a common symbol.  */
-      if (sym.st_shndx == SHN_COMMON
+      if (isym->st_shndx == SHN_COMMON
 	  && h->root.type == bfd_link_hash_common)
 	{
 	  unsigned int align;
 
-	  align = bfd_log2 (sym.st_value);
+	  align = bfd_log2 (isym->st_value);
 	  if (align > old_alignment
 	      /* Permit an alignment power of zero if an alignment of one
 		 is specified and no other alignments have been specified.  */
-	      || (sym.st_value == 1 && old_alignment == 0))
+	      || (isym->st_value == 1 && old_alignment == 0))
 	    h->root.u.c.p->alignment_power = align;
 	}
 
@@ -1952,16 +1882,16 @@ elf_link_add_object_symbols (abfd, info)
 	  int new_flag;
 
 	  /* Remember the symbol size and type.  */
-	  if (sym.st_size != 0
+	  if (isym->st_size != 0
 	      && (definition || h->size == 0))
 	    {
-	      if (h->size != 0 && h->size != sym.st_size && ! size_change_ok)
+	      if (h->size != 0 && h->size != isym->st_size && ! size_change_ok)
 		(*_bfd_error_handler)
 		  (_("Warning: size of symbol `%s' changed from %lu to %lu in %s"),
-		   name, (unsigned long) h->size, (unsigned long) sym.st_size,
-		   bfd_archive_filename (abfd));
+		   name, (unsigned long) h->size,
+		   (unsigned long) isym->st_size, bfd_archive_filename (abfd));
 
-	      h->size = sym.st_size;
+	      h->size = isym->st_size;
 	    }
 
 	  /* If this is a common symbol, then we always want H->SIZE
@@ -1972,37 +1902,37 @@ elf_link_add_object_symbols (abfd, info)
 	  if (h->root.type == bfd_link_hash_common)
 	    h->size = h->root.u.c.size;
 
-	  if (ELF_ST_TYPE (sym.st_info) != STT_NOTYPE
+	  if (ELF_ST_TYPE (isym->st_info) != STT_NOTYPE
 	      && (definition || h->type == STT_NOTYPE))
 	    {
 	      if (h->type != STT_NOTYPE
-		  && h->type != ELF_ST_TYPE (sym.st_info)
+		  && h->type != ELF_ST_TYPE (isym->st_info)
 		  && ! type_change_ok)
 		(*_bfd_error_handler)
 		  (_("Warning: type of symbol `%s' changed from %d to %d in %s"),
-		   name, h->type, ELF_ST_TYPE (sym.st_info),
+		   name, h->type, ELF_ST_TYPE (isym->st_info),
 		   bfd_archive_filename (abfd));
 
-	      h->type = ELF_ST_TYPE (sym.st_info);
+	      h->type = ELF_ST_TYPE (isym->st_info);
 	    }
 
 	  /* If st_other has a processor-specific meaning, specific code
 	     might be needed here.  */
-	  if (sym.st_other != 0)
+	  if (isym->st_other != 0)
 	    {
 	      /* Combine visibilities, using the most constraining one.  */
 	      unsigned char hvis   = ELF_ST_VISIBILITY (h->other);
-	      unsigned char symvis = ELF_ST_VISIBILITY (sym.st_other);
+	      unsigned char symvis = ELF_ST_VISIBILITY (isym->st_other);
 
 	      if (symvis && (hvis > symvis || hvis == 0))
-		h->other = sym.st_other;
+		h->other = isym->st_other;
 
 	      /* If neither has visibility, use the st_other of the
 		 definition.  This is an arbitrary choice, since the
 		 other bits have no general meaning.  */
 	      if (!symvis && !hvis
 		  && (definition || h->other == 0))
-		h->other = sym.st_other;
+		h->other = isym->st_other;
 	    }
 
 	  /* Set a flag in the hash table entry indicating the type of
@@ -2046,21 +1976,21 @@ elf_link_add_object_symbols (abfd, info)
 	  /* Check to see if we need to add an indirect symbol for
 	     the default name.  */
 	  if (definition || h->root.type == bfd_link_hash_common)
-	    if (! elf_add_default_symbol (abfd, info, h, name, &sym,
+	    if (! elf_add_default_symbol (abfd, info, h, name, isym,
 					  &sec, &value, &dynsym,
 					  override, dt_needed))
-	      goto error_return;
+	      goto error_free_vers;
 
 	  if (dynsym && h->dynindx == -1)
 	    {
 	      if (! _bfd_elf_link_record_dynamic_symbol (info, h))
-		goto error_return;
+		goto error_free_vers;
 	      if (h->weakdef != NULL
 		  && ! new_weakdef
 		  && h->weakdef->dynindx == -1)
 		{
 		  if (! _bfd_elf_link_record_dynamic_symbol (info, h->weakdef))
-		    goto error_return;
+		    goto error_free_vers;
 		}
 	    }
 	  else if (dynsym && h->dynindx != -1)
@@ -2083,7 +2013,7 @@ elf_link_add_object_symbols (abfd, info)
 	      bfd_size_type strindex;
 
 	      if (! is_elf_hash_table (info))
-		goto error_return;
+		goto error_free_vers;
 
 	      /* The symbol from a DT_NEEDED object is referenced from
 		 the regular object to create a dynamic executable. We
@@ -2094,7 +2024,7 @@ elf_link_add_object_symbols (abfd, info)
 	      strindex = _bfd_elf_strtab_add (hash_table->dynstr,
 					      elf_dt_soname (abfd), false);
 	      if (strindex == (bfd_size_type) -1)
-		goto error_return;
+		goto error_free_vers;
 
 	      if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr))
 		{
@@ -2120,11 +2050,21 @@ elf_link_add_object_symbols (abfd, info)
 		}
 
 	      if (! elf_add_dynamic_entry (info, (bfd_vma) DT_NEEDED, strindex))
-		goto error_return;
+		goto error_free_vers;
 	    }
 	}
     }
 
+  if (extversym != NULL)
+    {
+      free (extversym);
+      extversym = NULL;
+    }
+
+  if (isymbuf != NULL)
+    free (isymbuf);
+  isymbuf = NULL;
+
   /* Now set the weakdefs field correctly for all the weak defined
      symbols we found.  The only way to do this is to search all the
      symbols.  Since we only need the information for non functions in
@@ -2192,24 +2132,11 @@ elf_link_add_object_symbols (abfd, info)
 		  if (! _bfd_elf_link_record_dynamic_symbol (info, hlook))
 		    goto error_return;
 		}
-
 	      break;
 	    }
 	}
     }
 
-  if (buf != NULL)
-    {
-      free (buf);
-      buf = NULL;
-    }
-
-  if (extversym != NULL)
-    {
-      free (extversym);
-      extversym = NULL;
-    }
-
   /* If this object is the same format as the output object, and it is
      not a shared library, then let the backend look through the
      relocs.
@@ -2255,7 +2182,7 @@ elf_link_add_object_symbols (abfd, info)
 
 	  ok = (*check_relocs) (abfd, info, o, internal_relocs);
 
-	  if (! info->keep_memory)
+	  if (elf_section_data (o)->relocs != internal_relocs)
 	    free (internal_relocs);
 
 	  if (! ok)
@@ -2334,13 +2261,13 @@ elf_link_add_object_symbols (abfd, info)
 
   return true;
 
- error_return:
-  if (buf != NULL)
-    free (buf);
-  if (dynbuf != NULL)
-    free (dynbuf);
+ error_free_vers:
   if (extversym != NULL)
     free (extversym);
+ error_free_sym:
+  if (isymbuf != NULL)
+    free (isymbuf);
+ error_return:
   return false;
 }
 
@@ -5050,7 +4977,7 @@ elf_bfd_final_link (abfd, info)
 		  o->reloc_count
 		    += (*bed->elf_backend_count_relocs) (sec, relocs);
 
-		  if (!info->keep_memory)
+		  if (elf_section_data (o)->relocs != relocs)
 		    free (relocs);
 		}
 
@@ -6072,8 +5999,6 @@ elf_link_check_versioned_symbol (info, h
 {
   bfd *undef_bfd = h->root.u.undef.abfd;
   struct elf_link_loaded_list *loaded;
-  Elf_External_Sym *buf;
-  Elf_External_Versym *extversym;
 
   if ((undef_bfd->flags & DYNAMIC) == 0
       || info->hash->creator->flavour != bfd_target_elf_flavour
@@ -6090,11 +6015,11 @@ elf_link_check_versioned_symbol (info, h
       bfd_size_type extsymcount;
       bfd_size_type extsymoff;
       Elf_Internal_Shdr *versymhdr;
+      Elf_Internal_Sym *isym;
+      Elf_Internal_Sym *isymend;
+      Elf_Internal_Sym *isymbuf;
       Elf_External_Versym *ever;
-      Elf_External_Sym *esym;
-      Elf_External_Sym *esymend;
-      bfd_size_type count;
-      file_ptr pos;
+      Elf_External_Versym *extversym;
 
       input = loaded->abfd;
 
@@ -6121,17 +6046,11 @@ elf_link_check_versioned_symbol (info, h
       if (extsymcount == 0)
 	continue;
 
-      count = extsymcount * sizeof (Elf_External_Sym);
-      buf = (Elf_External_Sym *) bfd_malloc (count);
-      if (buf == NULL)
+      isymbuf = bfd_elf_get_elf_syms (input, hdr, extsymcount, extsymoff,
+				      NULL, NULL, NULL);
+      if (isymbuf == NULL)
 	return false;
 
-      /* Read in the symbol table.  */
-      pos = hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym);
-      if (bfd_seek (input, pos, SEEK_SET) != 0
-	  || bfd_bread ((PTR) buf, count, input) != count)
-	goto error_ret;
-
       /* Read in any version definitions.  */
       versymhdr = &elf_tdata (input)->dynversym_hdr;
       extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);
@@ -6144,26 +6063,24 @@ elf_link_check_versioned_symbol (info, h
 	{
 	  free (extversym);
 	error_ret:
-	  free (buf);
+	  free (isymbuf);
 	  return false;
 	}
 
       ever = extversym + extsymoff;
-      esymend = buf + extsymcount;
-      for (esym = buf; esym < esymend; esym++, ever++)
+      isymend = isymbuf + extsymcount;
+      for (isym = isymbuf; isym < isymend; isym++, ever++)
 	{
 	  const char *name;
-	  Elf_Internal_Sym sym;
 	  Elf_Internal_Versym iver;
 
-	  elf_swap_symbol_in (input, esym, NULL, &sym);
-	  if (ELF_ST_BIND (sym.st_info) == STB_LOCAL
-	      || sym.st_shndx == SHN_UNDEF)
+	  if (ELF_ST_BIND (isym->st_info) == STB_LOCAL
+	      || isym->st_shndx == SHN_UNDEF)
 	    continue;
 
 	  name = bfd_elf_string_from_elf_section (input,
 						  hdr->sh_link,
-						  sym.st_name);
+						  isym->st_name);
 	  if (strcmp (name, h->root.root.string) != 0)
 	    continue;
 
@@ -6180,13 +6097,13 @@ elf_link_check_versioned_symbol (info, h
 	    {
 	      /* This is the oldest (default) sym.  We can use it.  */
 	      free (extversym);
-	      free (buf);
+	      free (isymbuf);
 	      return true;
 	    }
 	}
 
       free (extversym);
-      free (buf);
+      free (isymbuf);
     }
 
   return false;
@@ -6611,15 +6528,11 @@ elf_link_input_bfd (finfo, input_bfd)
 				       Elf_Internal_Sym *, asection **));
   bfd *output_bfd;
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   size_t locsymcount;
   size_t extsymoff;
-  Elf_External_Sym *external_syms;
-  Elf_External_Sym *esym;
-  Elf_External_Sym *esymend;
-  Elf_External_Sym_Shndx *shndx_buf;
-  Elf_External_Sym_Shndx *shndx;
+  Elf_Internal_Sym *isymbuf;
   Elf_Internal_Sym *isym;
+  Elf_Internal_Sym *isymend;
   long *pindex;
   asection **ppsection;
   asection *o;
@@ -6654,45 +6567,29 @@ elf_link_input_bfd (finfo, input_bfd)
     }
 
   /* Read the local symbols.  */
-  if (symtab_hdr->contents != NULL)
-    external_syms = (Elf_External_Sym *) symtab_hdr->contents;
-  else if (locsymcount == 0)
-    external_syms = NULL;
-  else
+  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+  if (isymbuf == NULL && locsymcount != 0)
     {
-      bfd_size_type amt = locsymcount * sizeof (Elf_External_Sym);
-      external_syms = finfo->external_syms;
-      if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	  || bfd_bread (external_syms, amt, input_bfd) != amt)
+      isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0,
+				      finfo->internal_syms,
+				      finfo->external_syms,
+				      finfo->locsym_shndx);
+      if (isymbuf == NULL)
 	return false;
     }
 
-  shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr;
-  shndx_buf = NULL;
-  if (shndx_hdr->sh_size != 0 && locsymcount != 0)
-    {
-      bfd_size_type amt = locsymcount * sizeof (Elf_External_Sym_Shndx);
-      shndx_buf = finfo->locsym_shndx;
-      if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	  || bfd_bread (shndx_buf, amt, input_bfd) != amt)
-	return false;
-    }
-
-  /* Swap in the local symbols and write out the ones which we know
-     are going into the output file.  */
-  for (esym = external_syms, esymend = esym + locsymcount,
-	 isym = finfo->internal_syms, pindex = finfo->indices,
-	 ppsection = finfo->sections, shndx = shndx_buf;
-       esym < esymend;
-       esym++, isym++, pindex++, ppsection++,
-	 shndx = (shndx != NULL ? shndx + 1 : NULL))
+  /* Find local symbol sections and adjust values of symbols in
+     SEC_MERGE sections.  Write out those local symbols we know are
+     going into the output file.  */
+  isymend = isymbuf + locsymcount;
+  for (isym = isymbuf, pindex = finfo->indices, ppsection = finfo->sections;
+       isym < isymend;
+       isym++, pindex++, ppsection++)
     {
       asection *isec;
       const char *name;
       Elf_Internal_Sym osym;
 
-      elf_swap_symbol_in (input_bfd, (const PTR) esym, (const PTR) shndx,
-			  isym);
       *pindex = -1;
 
       if (elf_bad_symtab (input_bfd))
@@ -6731,7 +6628,7 @@ elf_link_input_bfd (finfo, input_bfd)
       *ppsection = isec;
 
       /* Don't output the first, undefined, symbol.  */
-      if (esym == external_syms)
+      if (ppsection == finfo->sections)
 	continue;
 
       if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
@@ -7001,7 +6898,7 @@ elf_link_input_bfd (finfo, input_bfd)
 	  if (! (*relocate_section) (output_bfd, finfo->info,
 				     input_bfd, o, contents,
 				     internal_relocs,
-				     finfo->internal_syms,
+				     isymbuf,
 				     finfo->sections))
 	    return false;
 
@@ -7085,7 +6982,7 @@ elf_link_input_bfd (finfo, input_bfd)
 		  /* This is a reloc against a local symbol.  */
 
 		  *rel_hash = NULL;
-		  isym = finfo->internal_syms + r_symndx;
+		  isym = isymbuf + r_symndx;
 		  sec = finfo->sections[r_symndx];
 		  if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
 		    {
@@ -7762,17 +7659,12 @@ elf_gc_mark (info, sec, gc_mark_hook)
     {
       Elf_Internal_Rela *relstart, *rel, *relend;
       Elf_Internal_Shdr *symtab_hdr;
-      Elf_Internal_Shdr *shndx_hdr;
       struct elf_link_hash_entry **sym_hashes;
       size_t nlocsyms;
       size_t extsymoff;
-      Elf_External_Sym *locsyms, *freesyms = NULL;
-      Elf_External_Sym_Shndx *locsym_shndx;
       bfd *input_bfd = sec->owner;
       struct elf_backend_data *bed = get_elf_backend_data (input_bfd);
-
-      /* GCFIXME: how to arrange so that relocs and symbols are not
-	 reread continually?  */
+      Elf_Internal_Sym *isym = NULL;
 
       symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
       sym_hashes = elf_sym_hashes (input_bfd);
@@ -7786,37 +7678,18 @@ elf_gc_mark (info, sec, gc_mark_hook)
       else
 	extsymoff = nlocsyms = symtab_hdr->sh_info;
 
-      if (symtab_hdr->contents)
-	locsyms = (Elf_External_Sym *) symtab_hdr->contents;
-      else if (nlocsyms == 0)
-	locsyms = NULL;
-      else
-	{
-	  bfd_size_type amt = nlocsyms * sizeof (Elf_External_Sym);
-	  locsyms = freesyms = bfd_malloc (amt);
-	  if (freesyms == NULL
-	      || bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread (locsyms, amt, input_bfd) != amt)
-	    {
-	      ret = false;
-	      goto out1;
-	    }
-	}
-
-      shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr;
-      locsym_shndx = NULL;
-      if (shndx_hdr->sh_size != 0 && nlocsyms != 0)
+      isym = (Elf_Internal_Sym *) symtab_hdr->contents;
+      if (isym == NULL && nlocsyms != 0)
 	{
-	  bfd_size_type amt = nlocsyms * sizeof (Elf_External_Sym_Shndx);
-	  locsym_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	  if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread (locsym_shndx, amt, input_bfd) != amt)
+	  isym = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, nlocsyms, 0,
+				       NULL, NULL, NULL);
+	  if (isym == NULL)
 	    return false;
 	}
 
       /* Read the relocations.  */
       relstart = (NAME(_bfd_elf,link_read_relocs)
-		  (sec->owner, sec, NULL, (Elf_Internal_Rela *) NULL,
+		  (input_bfd, sec, NULL, (Elf_Internal_Rela *) NULL,
 		   info->keep_memory));
       if (relstart == NULL)
 	{
@@ -7830,41 +7703,20 @@ elf_gc_mark (info, sec, gc_mark_hook)
 	  unsigned long r_symndx;
 	  asection *rsec;
 	  struct elf_link_hash_entry *h;
-	  Elf_Internal_Sym s;
-	  Elf_External_Sym_Shndx *locshndx;
 
 	  r_symndx = ELF_R_SYM (rel->r_info);
 	  if (r_symndx == 0)
 	    continue;
 
-	  if (elf_bad_symtab (sec->owner))
-	    {
-	      locshndx = locsym_shndx + (locsym_shndx ? r_symndx : 0);
-	      elf_swap_symbol_in (input_bfd,
-				  (const PTR) (locsyms + r_symndx),
-				  (const PTR) locshndx,
-				  &s);
-	      if (ELF_ST_BIND (s.st_info) == STB_LOCAL)
-		rsec = (*gc_mark_hook) (sec, info, rel, NULL, &s);
-	      else
-		{
-		  h = sym_hashes[r_symndx - extsymoff];
-		  rsec = (*gc_mark_hook) (sec, info, rel, h, NULL);
-		}
-	    }
-	  else if (r_symndx >= nlocsyms)
+	  if (r_symndx >= nlocsyms
+	      || ELF_ST_BIND (isym[r_symndx].st_info) != STB_LOCAL)
 	    {
 	      h = sym_hashes[r_symndx - extsymoff];
 	      rsec = (*gc_mark_hook) (sec, info, rel, h, NULL);
 	    }
 	  else
 	    {
-	      locshndx = locsym_shndx + (locsym_shndx ? r_symndx : 0);
-	      elf_swap_symbol_in (input_bfd,
-				  (const PTR) (locsyms + r_symndx),
-				  (const PTR) locshndx,
-				  &s);
-	      rsec = (*gc_mark_hook) (sec, info, rel, NULL, &s);
+	      rsec = (*gc_mark_hook) (sec, info, rel, NULL, &isym[r_symndx]);
 	    }
 
 	  if (rsec && !rsec->gc_mark)
@@ -7880,11 +7732,16 @@ elf_gc_mark (info, sec, gc_mark_hook)
 	}
 
     out2:
-      if (!info->keep_memory)
+      if (elf_section_data (sec)->relocs != relstart)
 	free (relstart);
     out1:
-      if (freesyms)
-	free (freesyms);
+      if (isym != NULL && symtab_hdr->contents != (unsigned char *) isym)
+	{
+	  if (! info->keep_memory)
+	    free (isym);
+	  else
+	    symtab_hdr->contents = (unsigned char *) isym;
+	}
     }
 
   return ret;
@@ -7941,7 +7798,7 @@ elf_gc_sweep (info, gc_sweep_hook)
 
 	      r = (*gc_sweep_hook) (o->owner, info, o, internal_relocs);
 
-	      if (!info->keep_memory)
+	      if (elf_section_data (o)->relocs != internal_relocs)
 		free (internal_relocs);
 
 	      if (!r)
@@ -8439,7 +8296,6 @@ elf_reloc_symbol_deleted_p (offset, cook
   for (; rcookie->rel < rcookie->relend; rcookie->rel++)
     {
       unsigned long r_symndx = ELF_R_SYM (rcookie->rel->r_info);
-      Elf_Internal_Sym isym;
 
       if (! rcookie->bad_symtab)
 	if (rcookie->rel->r_offset > offset)
@@ -8447,22 +8303,8 @@ elf_reloc_symbol_deleted_p (offset, cook
       if (rcookie->rel->r_offset != offset)
 	continue;
 
-      if (rcookie->locsyms && r_symndx < rcookie->locsymcount)
-	{
-	  Elf_External_Sym *lsym;
-	  Elf_External_Sym_Shndx *lshndx;
-
-	  lsym = (Elf_External_Sym *) rcookie->locsyms + r_symndx;
-	  lshndx = (Elf_External_Sym_Shndx *) rcookie->locsym_shndx;
-	  if (lshndx != NULL)
-	    lshndx += r_symndx;
-	  elf_swap_symbol_in (rcookie->abfd, (const PTR) lsym,
-			      (const PTR) lshndx, &isym);
-	}
-
       if (r_symndx >= rcookie->locsymcount
-	  || (rcookie->locsyms
-	      && ELF_ST_BIND (isym.st_info) != STB_LOCAL))
+	  || ELF_ST_BIND (rcookie->locsyms[r_symndx].st_info) != STB_LOCAL)
 	{
 	  struct elf_link_hash_entry *h;
 
@@ -8479,17 +8321,19 @@ elf_reloc_symbol_deleted_p (offset, cook
 	  else
 	    return false;
 	}
-      else if (rcookie->locsyms)
+      else
 	{
 	  /* It's not a relocation against a global symbol,
 	     but it could be a relocation against a local
 	     symbol for a discarded section.  */
 	  asection *isec;
+	  Elf_Internal_Sym *isym;
 
 	  /* Need to: get the symbol; get the section.  */
-	  if (isym.st_shndx < SHN_LORESERVE || isym.st_shndx > SHN_HIRESERVE)
+	  isym = &rcookie->locsyms[r_symndx];
+	  if (isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
 	    {
-	      isec = section_from_elf_index (rcookie->abfd, isym.st_shndx);
+	      isec = section_from_elf_index (rcookie->abfd, isym->st_shndx);
 	      if (isec != NULL && elf_discarded_section (isec))
 		return true;
 	    }
@@ -8512,8 +8356,6 @@ elf_bfd_discard_info (output_bfd, info)
   struct elf_reloc_cookie cookie;
   asection *stab, *eh, *ehdr;
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
-  Elf_External_Sym *freesyms;
   struct elf_backend_data *bed;
   bfd *abfd;
   boolean ret = false;
@@ -8564,8 +8406,6 @@ elf_bfd_discard_info (output_bfd, info)
 	continue;
 
       symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-      shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-
       cookie.abfd = abfd;
       cookie.sym_hashes = elf_sym_hashes (abfd);
       cookie.bad_symtab = elf_bad_symtab (abfd);
@@ -8581,48 +8421,20 @@ elf_bfd_discard_info (output_bfd, info)
 	  cookie.extsymoff = symtab_hdr->sh_info;
 	}
 
-      freesyms = NULL;
-      if (symtab_hdr->contents)
-	cookie.locsyms = (void *) symtab_hdr->contents;
-      else if (cookie.locsymcount == 0)
-	cookie.locsyms = NULL;
-      else
+      cookie.locsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
+      if (cookie.locsyms == NULL && cookie.locsymcount != 0)
 	{
-	  bfd_size_type amt = cookie.locsymcount * sizeof (Elf_External_Sym);
-	  cookie.locsyms = bfd_malloc (amt);
+	  cookie.locsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+						 cookie.locsymcount, 0,
+						 NULL, NULL, NULL);
 	  if (cookie.locsyms == NULL)
 	    return false;
-	  freesyms = cookie.locsyms;
-	  if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread (cookie.locsyms, amt, abfd) != amt)
-	    {
-	    error_ret_free_loc:
-	      free (cookie.locsyms);
-	      return false;
-	    }
-	}
-
-      cookie.locsym_shndx = NULL;
-      if (shndx_hdr->sh_size != 0 && cookie.locsymcount != 0)
-	{
-	  bfd_size_type amt;
-	  amt = cookie.locsymcount * sizeof (Elf_External_Sym_Shndx);
-	  cookie.locsym_shndx = bfd_malloc (amt);
-	  if (cookie.locsym_shndx == NULL)
-	    goto error_ret_free_loc;
-	  if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread (cookie.locsym_shndx, amt, abfd) != amt)
-	    {
-	      free (cookie.locsym_shndx);
-	      goto error_ret_free_loc;
-	    }
 	}
 
       if (stab)
 	{
 	  cookie.rels = (NAME(_bfd_elf,link_read_relocs)
-			 (abfd, stab, (PTR) NULL,
-			  (Elf_Internal_Rela *) NULL,
+			 (abfd, stab, (PTR) NULL, (Elf_Internal_Rela *) NULL,
 			  info->keep_memory));
 	  if (cookie.rels)
 	    {
@@ -8634,7 +8446,7 @@ elf_bfd_discard_info (output_bfd, info)
 					      elf_reloc_symbol_deleted_p,
 					      &cookie))
 		ret = true;
-	      if (! info->keep_memory)
+	      if (elf_section_data (stab)->relocs != cookie.rels)
 		free (cookie.rels);
 	    }
 	}
@@ -8658,7 +8470,7 @@ elf_bfd_discard_info (output_bfd, info)
 						 elf_reloc_symbol_deleted_p,
 						 &cookie))
 	    ret = true;
-	  if (! info->keep_memory)
+	  if (cookie.rels && elf_section_data (eh)->relocs != cookie.rels)
 	    free (cookie.rels);
 	}
 
@@ -8668,11 +8480,14 @@ elf_bfd_discard_info (output_bfd, info)
 	    ret = true;
 	}
 
-      if (cookie.locsym_shndx != NULL)
-	free (cookie.locsym_shndx);
-
-      if (freesyms != NULL)
-	free (freesyms);
+      if (cookie.locsyms != NULL
+	  && symtab_hdr->contents != (unsigned char *) cookie.locsyms)
+	{
+	  if (! info->keep_memory)
+	    free (cookie.locsyms);
+	  else
+	    symtab_hdr->contents = (unsigned char *) cookie.locsyms;
+	}
     }
 
   if (ehdr && _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info, ehdr))
Index: bfd/elf-m10200.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-m10200.c,v
retrieving revision 1.16
diff -u -p -r1.16 elf-m10200.c
--- bfd/elf-m10200.c	6 Jun 2002 00:29:20 -0000	1.16
+++ bfd/elf-m10200.c	7 Jul 2002 06:59:01 -0000
@@ -30,7 +30,7 @@ static void mn10200_info_to_howto
 static boolean mn10200_elf_relax_delete_bytes
   PARAMS ((bfd *, asection *, bfd_vma, int));
 static boolean mn10200_elf_symbol_address_p
-  PARAMS ((bfd *, asection *, bfd_vma));
+  PARAMS ((bfd *, asection *, Elf_Internal_Sym *, bfd_vma));
 static bfd_reloc_status_type mn10200_elf_final_link_relocate
   PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *,
 	   bfd_byte *, bfd_vma, bfd_vma, bfd_vma,
@@ -508,15 +508,10 @@ mn10200_elf_relax_section (abfd, sec, li
      boolean *again;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *free_relocs = NULL;
   Elf_Internal_Rela *irel, *irelend;
   bfd_byte *contents = NULL;
-  bfd_byte *free_contents = NULL;
-  Elf32_External_Sym *extsyms = NULL;
-  Elf32_External_Sym *free_extsyms = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
 
   /* Assume nothing changes.  */
   *again = false;
@@ -536,7 +531,6 @@ mn10200_elf_relax_section (abfd, sec, li
     sec->_cooked_size = sec->_raw_size;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
 
   /* Get a copy of the native relocations.  */
   internal_relocs = (_bfd_elf32_link_read_relocs
@@ -544,8 +538,6 @@ mn10200_elf_relax_section (abfd, sec, li
 		      link_info->keep_memory));
   if (internal_relocs == NULL)
     goto error_return;
-  if (! link_info->keep_memory)
-    free_relocs = internal_relocs;
 
   /* Walk through them looking for relaxing opportunities.  */
   irelend = internal_relocs + sec->reloc_count;
@@ -572,7 +564,6 @@ mn10200_elf_relax_section (abfd, sec, li
 	      contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
 	      if (contents == NULL)
 		goto error_return;
-	      free_contents = contents;
 
 	      if (! bfd_get_section_contents (abfd, sec, contents,
 					      (file_ptr) 0, sec->_raw_size))
@@ -580,68 +571,35 @@ mn10200_elf_relax_section (abfd, sec, li
 	    }
 	}
 
-      /* Read this BFD's symbols if we haven't done so already.  */
-      if (extsyms == NULL)
+      /* Read this BFD's local symbols if we haven't done so already.  */
+      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
 	{
-	  /* Get cached copy if it exists.  */
-	  if (symtab_hdr->contents != NULL)
-	    extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-	  else
-	    {
-	      /* Go get them off disk.  */
-	      bfd_size_type amt;
-
-	      amt = symtab_hdr->sh_info;
-	      amt *= sizeof (Elf32_External_Sym);
-	      extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
-	      if (extsyms == NULL)
-		goto error_return;
-	      free_extsyms = extsyms;
-	      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) extsyms, amt, abfd) != amt)
-		goto error_return;
-	      symtab_hdr->contents = (bfd_byte *) extsyms;
-	    }
-
-	  if (shndx_hdr->sh_size != 0)
-	    {
-	      bfd_size_type amt;
-
-	      amt = symtab_hdr->sh_info;
-	      amt *= sizeof (Elf_External_Sym_Shndx);
-	      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	      if (shndx_buf == NULL)
-		goto error_return;
-	      if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
-		goto error_return;
-	      shndx_hdr->contents = (bfd_byte *) shndx_buf;
-	    }
+	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	  if (isymbuf == NULL)
+	    isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+					    symtab_hdr->sh_info, 0,
+					    NULL, NULL, NULL);
+	  if (isymbuf == NULL)
+	    goto error_return;
 	}
 
       /* Get the value of the symbol referred to by the reloc.  */
       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
 	{
 	  /* A local symbol.  */
-	  Elf32_External_Sym *esym;
-	  Elf_External_Sym_Shndx *shndx;
-	  Elf_Internal_Sym isym;
+	  Elf_Internal_Sym *isym;
 	  asection *sym_sec;
 
-	  esym = extsyms + ELF32_R_SYM (irel->r_info);
-	  shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0);
-	  bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				    &isym);
-
-	  if (isym.st_shndx == SHN_UNDEF)
+	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
+	  if (isym->st_shndx == SHN_UNDEF)
 	    sym_sec = bfd_und_section_ptr;
-	  else if (isym.st_shndx == SHN_ABS)
+	  else if (isym->st_shndx == SHN_ABS)
 	    sym_sec = bfd_abs_section_ptr;
-	  else if (isym.st_shndx == SHN_COMMON)
+	  else if (isym->st_shndx == SHN_COMMON)
 	    sym_sec = bfd_com_section_ptr;
 	  else
-	    sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);
-	  symval = (isym.st_value
+	    sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+	  symval = (isym->st_value
 		    + sym_sec->output_section->vma
 		    + sym_sec->output_offset);
 	}
@@ -702,12 +660,8 @@ mn10200_elf_relax_section (abfd, sec, li
 
 	      /* Note that we've changed the relocs, section contents, etc.  */
 	      elf_section_data (sec)->relocs = internal_relocs;
-	      free_relocs = NULL;
-
 	      elf_section_data (sec)->this_hdr.contents = contents;
-	      free_contents = NULL;
-
-	      free_extsyms = NULL;
+	      symtab_hdr->contents = (unsigned char *) isymbuf;
 
 	      /* Fix the opcode.  */
 	      if (code == 0xe0)
@@ -759,12 +713,8 @@ mn10200_elf_relax_section (abfd, sec, li
 
 	      /* Note that we've changed the relocs, section contents, etc.  */
 	      elf_section_data (sec)->relocs = internal_relocs;
-	      free_relocs = NULL;
-
 	      elf_section_data (sec)->this_hdr.contents = contents;
-	      free_contents = NULL;
-
-	      free_extsyms = NULL;
+	      symtab_hdr->contents = (unsigned char *) isymbuf;
 
 	      /* Fix the opcode.  */
 	      bfd_put_8 (abfd, 0xea, contents + irel->r_offset - 1);
@@ -849,17 +799,14 @@ mn10200_elf_relax_section (abfd, sec, li
 
 	  /* We also have to be sure there is no symbol/label
 	     at the unconditional branch.  */
-	  if (mn10200_elf_symbol_address_p (abfd, sec, irel->r_offset + 1))
+	  if (mn10200_elf_symbol_address_p (abfd, sec, isymbuf,
+					    irel->r_offset + 1))
 	    continue;
 
 	  /* Note that we've changed the relocs, section contents, etc.  */
 	  elf_section_data (sec)->relocs = internal_relocs;
-	  free_relocs = NULL;
-
 	  elf_section_data (sec)->this_hdr.contents = contents;
-	  free_contents = NULL;
-
-	  free_extsyms = NULL;
+	  symtab_hdr->contents = (unsigned char *) isymbuf;
 
 	  /* Reverse the condition of the first branch.  */
 	  switch (code)
@@ -977,12 +924,8 @@ mn10200_elf_relax_section (abfd, sec, li
 
 		  /* Note that we've changed the reldection contents, etc.  */
 		  elf_section_data (sec)->relocs = internal_relocs;
-		  free_relocs = NULL;
-
 		  elf_section_data (sec)->this_hdr.contents = contents;
-		  free_contents = NULL;
-
-		  free_extsyms = NULL;
+		  symtab_hdr->contents = (unsigned char *) isymbuf;
 
 		  /* Fix the opcode.  */
 		  bfd_put_8 (abfd, 0xf8 + (code & 0x03),
@@ -1020,12 +963,8 @@ mn10200_elf_relax_section (abfd, sec, li
 		case 0xc8:
 		  /* Note that we've changed the reldection contents, etc.  */
 		  elf_section_data (sec)->relocs = internal_relocs;
-		  free_relocs = NULL;
-
 		  elf_section_data (sec)->this_hdr.contents = contents;
-		  free_contents = NULL;
-
-		  free_extsyms = NULL;
+		  symtab_hdr->contents = (unsigned char *) isymbuf;
 
 		  if ((code & 0xfc) == 0x74)
 		    code = 0xdc + (code & 0x03);
@@ -1107,12 +1046,8 @@ mn10200_elf_relax_section (abfd, sec, li
 
 		  /* Note that we've changed the reldection contents, etc.  */
 		  elf_section_data (sec)->relocs = internal_relocs;
-		  free_relocs = NULL;
-
 		  elf_section_data (sec)->this_hdr.contents = contents;
-		  free_contents = NULL;
-
-		  free_extsyms = NULL;
+		  symtab_hdr->contents = (unsigned char *) isymbuf;
 
 		  /* Fix the opcode.  */
 		  bfd_put_8 (abfd, 0xf7, contents + irel->r_offset - 2);
@@ -1170,12 +1105,8 @@ mn10200_elf_relax_section (abfd, sec, li
 		case 0xc4:
 		  /* Note that we've changed the reldection contents, etc.  */
 		  elf_section_data (sec)->relocs = internal_relocs;
-		  free_relocs = NULL;
-
 		  elf_section_data (sec)->this_hdr.contents = contents;
-		  free_contents = NULL;
-
-		  free_extsyms = NULL;
+		  symtab_hdr->contents = (unsigned char *) isymbuf;
 
 		  bfd_put_8 (abfd, 0xcc + (code & 0x03),
 			     contents + irel->r_offset - 2);
@@ -1205,52 +1136,46 @@ mn10200_elf_relax_section (abfd, sec, li
 	}
     }
 
-  if (free_relocs != NULL)
-    free (free_relocs);
-
-  if (free_contents != NULL)
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
     {
       if (! link_info->keep_memory)
-	free (free_contents);
+	free (isymbuf);
       else
 	{
-	  /* Cache the section contents for elf_link_input_bfd.  */
-	  elf_section_data (sec)->this_hdr.contents = contents;
+	  /* Cache the symbols for elf_link_input_bfd.  */
+	  symtab_hdr->contents = (unsigned char *) isymbuf;
 	}
     }
 
-  if (shndx_buf != NULL)
-    {
-      shndx_hdr->contents = NULL;
-      free (shndx_buf);
-    }
-
-  if (free_extsyms != NULL)
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
     {
       if (! link_info->keep_memory)
+	free (contents);
+      else
 	{
-	  symtab_hdr->contents = NULL;
-	  free (free_extsyms);
+	  /* Cache the section contents for elf_link_input_bfd.  */
+	  elf_section_data (sec)->this_hdr.contents = contents;
 	}
     }
 
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
+
   return true;
 
  error_return:
-  if (free_relocs != NULL)
-    free (free_relocs);
-  if (free_contents != NULL)
-    free (free_contents);
-  if (shndx_buf != NULL)
-    {
-      shndx_hdr->contents = NULL;
-      free (shndx_buf);
-    }
-  if (free_extsyms != NULL)
-    {
-      symtab_hdr->contents = NULL;
-      free (free_extsyms);
-    }
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
+    free (contents);
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
 
   return false;
 }
@@ -1265,22 +1190,17 @@ mn10200_elf_relax_delete_bytes (abfd, se
      int count;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
-  Elf32_External_Sym *extsyms;
   unsigned int sec_shndx;
   bfd_byte *contents;
   Elf_Internal_Rela *irel, *irelend;
   Elf_Internal_Rela *irelalign;
   bfd_vma toaddr;
-  Elf32_External_Sym *esym, *esymend;
-  Elf_External_Sym_Shndx *shndx;
+  Elf_Internal_Sym *isym;
+  Elf_Internal_Sym *isymend;
   struct elf_link_hash_entry **sym_hashes;
   struct elf_link_hash_entry **end_hashes;
   unsigned int symcount;
 
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-
   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
   contents = elf_section_data (sec)->this_hdr.contents;
@@ -1309,25 +1229,14 @@ mn10200_elf_relax_delete_bytes (abfd, se
     }
 
   /* Adjust the local symbols defined in this section.  */
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-  shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
-  esym = extsyms;
-  esymend = esym + symtab_hdr->sh_info;
-  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
+  for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
     {
-      Elf_Internal_Sym isym;
-      Elf_External_Sym_Shndx dummy;
-
-      bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				&isym);
-
-      if (isym.st_shndx == sec_shndx
-	  && isym.st_value > addr
-	  && isym.st_value < toaddr)
-	{
-	  isym.st_value -= count;
-	  bfd_elf32_swap_symbol_out (abfd, &isym, (PTR) esym, (PTR) &dummy);
-	}
+      if (isym->st_shndx == sec_shndx
+	  && isym->st_value > addr
+	  && isym->st_value < toaddr)
+	isym->st_value -= count;
     }
 
   /* Now adjust the global symbols defined in this section.  */
@@ -1354,37 +1263,27 @@ mn10200_elf_relax_delete_bytes (abfd, se
 /* Return true if a symbol exists at the given address, else return
    false.  */
 static boolean
-mn10200_elf_symbol_address_p (abfd, sec, addr)
+mn10200_elf_symbol_address_p (abfd, sec, isym, addr)
      bfd *abfd;
      asection *sec;
+     Elf_Internal_Sym *isym;
      bfd_vma addr;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   unsigned int sec_shndx;
-  Elf32_External_Sym *esym, *esymend;
-  Elf_External_Sym_Shndx *shndx;
+  Elf_Internal_Sym *isymend;
   struct elf_link_hash_entry **sym_hashes;
   struct elf_link_hash_entry **end_hashes;
   unsigned int symcount;
 
   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
-  /* Examine all the symbols.  */
+  /* Examine all the local symbols.  */
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-  shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
-  esym = (Elf32_External_Sym *) symtab_hdr->contents;
-  esymend = esym + symtab_hdr->sh_info;
-  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
+  for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
     {
-      Elf_Internal_Sym isym;
-
-      bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				&isym);
-
-      if (isym.st_shndx == sec_shndx
-	  && isym.st_value == addr)
+      if (isym->st_shndx == sec_shndx
+	  && isym->st_value == addr)
 	return true;
     }
 
@@ -1419,15 +1318,11 @@ mn10200_elf_get_relocated_section_conten
      asymbol **symbols;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   asection *input_section = link_order->u.indirect.section;
   bfd *input_bfd = input_section->owner;
   asection **sections = NULL;
   Elf_Internal_Rela *internal_relocs = NULL;
-  Elf32_External_Sym *external_syms = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
-  Elf_External_Sym_Shndx *shndx;
-  Elf_Internal_Sym *internal_syms = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
 
   /* We only need to handle the case of relaxing, or of having a
      particular set of section contents, specially.  */
@@ -1439,7 +1334,6 @@ mn10200_elf_get_relocated_section_conten
 						       symbols);
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
-  shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr;
 
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
 	  (size_t) input_section->_raw_size);
@@ -1447,48 +1341,27 @@ mn10200_elf_get_relocated_section_conten
   if ((input_section->flags & SEC_RELOC) != 0
       && input_section->reloc_count > 0)
     {
-      Elf_Internal_Sym *isymp;
+      Elf_Internal_Sym *isym;
+      Elf_Internal_Sym *isymend;
       asection **secpp;
-      Elf32_External_Sym *esym, *esymend;
       bfd_size_type amt;
 
-      if (symtab_hdr->contents != NULL)
-	external_syms = (Elf32_External_Sym *) symtab_hdr->contents;
-      else if (symtab_hdr->sh_info != 0)
-	{
-	  amt = symtab_hdr->sh_info;
-	  amt *= sizeof (Elf32_External_Sym);
-	  external_syms = (Elf32_External_Sym *) bfd_malloc (amt);
-	  if (external_syms == NULL)
-	    goto error_return;
-	  if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread ((PTR) external_syms, amt, input_bfd) != amt)
-	    goto error_return;
-	}
-
-      if (symtab_hdr->sh_info != 0 && shndx_hdr->sh_size != 0)
-	{
-	  amt = symtab_hdr->sh_info;
-	  amt *= sizeof (Elf_External_Sym_Shndx);
-	  shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	  if (shndx_buf == NULL)
-	    goto error_return;
-	  if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread ((PTR) shndx_buf, amt, input_bfd) != amt)
-	    goto error_return;
-	}
-
       internal_relocs = (_bfd_elf32_link_read_relocs
 			 (input_bfd, input_section, (PTR) NULL,
 			  (Elf_Internal_Rela *) NULL, false));
       if (internal_relocs == NULL)
 	goto error_return;
 
-      amt = symtab_hdr->sh_info;
-      amt *= sizeof (Elf_Internal_Sym);
-      internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt);
-      if (internal_syms == NULL && amt != 0)
-	goto error_return;
+      if (symtab_hdr->sh_info != 0)
+	{
+	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	  if (isymbuf == NULL)
+	    isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
+					    symtab_hdr->sh_info, 0,
+					    NULL, NULL, NULL);
+	  if (isymbuf == NULL)
+	    goto error_return;
+	}
 
       amt = symtab_hdr->sh_info;
       amt *= sizeof (asection *);
@@ -1496,59 +1369,48 @@ mn10200_elf_get_relocated_section_conten
       if (sections == NULL && amt != 0)
 	goto error_return;
 
-      for (isymp = internal_syms, secpp = sections, shndx = shndx_buf,
-	     esym = external_syms, esymend = esym + symtab_hdr->sh_info;
-	   esym < esymend;
-	   ++esym, ++isymp, ++secpp, shndx = (shndx ? shndx + 1 : NULL))
+      isymend = isymbuf + symtab_hdr->sh_info;
+      for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
 	{
 	  asection *isec;
 
-	  bfd_elf32_swap_symbol_in (input_bfd, (const PTR) esym,
-				    (const PTR) shndx, isymp);
-
-	  if (isymp->st_shndx == SHN_UNDEF)
+	  if (isym->st_shndx == SHN_UNDEF)
 	    isec = bfd_und_section_ptr;
-	  else if (isymp->st_shndx == SHN_ABS)
+	  else if (isym->st_shndx == SHN_ABS)
 	    isec = bfd_abs_section_ptr;
-	  else if (isymp->st_shndx == SHN_COMMON)
+	  else if (isym->st_shndx == SHN_COMMON)
 	    isec = bfd_com_section_ptr;
 	  else
-	    isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
+	    isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
 
 	  *secpp = isec;
 	}
 
       if (! mn10200_elf_relocate_section (output_bfd, link_info, input_bfd,
 				     input_section, data, internal_relocs,
-				     internal_syms, sections))
+				     isymbuf, sections))
 	goto error_return;
 
       if (sections != NULL)
 	free (sections);
-      if (internal_syms != NULL)
-	free (internal_syms);
-      if (shndx_buf != NULL)
-	free (shndx_buf);
-      if (external_syms != NULL && symtab_hdr->contents == NULL)
-	free (external_syms);
-      if (internal_relocs != elf_section_data (input_section)->relocs)
+      if (isymbuf != NULL
+	  && symtab_hdr->contents != (unsigned char *) isymbuf)
+	free (isymbuf);
+      if (elf_section_data (input_section)->relocs != internal_relocs)
 	free (internal_relocs);
     }
 
   return data;
 
  error_return:
-  if (internal_relocs != NULL
-      && internal_relocs != elf_section_data (input_section)->relocs)
-    free (internal_relocs);
-  if (shndx_buf != NULL)
-    free (shndx_buf);
-  if (external_syms != NULL && symtab_hdr->contents == NULL)
-    free (external_syms);
-  if (internal_syms != NULL)
-    free (internal_syms);
   if (sections != NULL)
     free (sections);
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
+  if (internal_relocs != NULL
+      && elf_section_data (input_section)->relocs != internal_relocs)
+    free (internal_relocs);
   return NULL;
 }
 
Index: bfd/elf-m10300.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-m10300.c,v
retrieving revision 1.27
diff -u -p -r1.27 elf-m10300.c
--- bfd/elf-m10300.c	1 Jul 2002 08:06:40 -0000	1.27
+++ bfd/elf-m10300.c	7 Jul 2002 06:59:04 -0000
@@ -127,7 +127,7 @@ static asection *mn10300_elf_gc_mark_hoo
 static boolean mn10300_elf_relax_delete_bytes
   PARAMS ((bfd *, asection *, bfd_vma, int));
 static boolean mn10300_elf_symbol_address_p
-  PARAMS ((bfd *, asection *, bfd_vma));
+PARAMS ((bfd *, asection *, Elf_Internal_Sym *, bfd_vma));
 static boolean elf32_mn10300_finish_hash_table_entry
   PARAMS ((struct bfd_hash_entry *, PTR));
 static void compute_function_info
@@ -783,16 +783,12 @@ mn10300_elf_relax_section (abfd, sec, li
      boolean *again;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   Elf_Internal_Rela *internal_relocs = NULL;
-  Elf_Internal_Rela *free_relocs = NULL;
   Elf_Internal_Rela *irel, *irelend;
   bfd_byte *contents = NULL;
-  bfd_byte *free_contents = NULL;
-  Elf32_External_Sym *extsyms = NULL;
-  Elf32_External_Sym *free_extsyms = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
   struct elf32_mn10300_link_hash_table *hash_table;
+  asection *section = sec;
 
   /* Assume nothing changes.  */
   *again = false;
@@ -810,42 +806,16 @@ mn10300_elf_relax_section (abfd, sec, li
 	   input_bfd != NULL;
 	   input_bfd = input_bfd->link_next)
 	{
-	  asection *section;
-
 	  /* We're going to need all the symbols for each bfd.  */
 	  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
-	  shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr;
-
-	  /* Get cached copy if it exists.  */
-	  if (symtab_hdr->contents != NULL)
-	    extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-	  else
-	    {
-	      /* Go get them off disk.  */
-	      bfd_size_type amt;
-
-	      amt = symtab_hdr->sh_info;
-	      amt *= sizeof (Elf32_External_Sym);
-	      extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
-	      if (extsyms == NULL)
-		goto error_return;
-	      free_extsyms = extsyms;
-	      if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) extsyms, amt, input_bfd) != amt)
-		goto error_return;
-	    }
-
-	  if (shndx_hdr->sh_size != 0)
+	  if (symtab_hdr->sh_info != 0)
 	    {
-	      bfd_size_type amt;
-
-	      amt = symtab_hdr->sh_info;
-	      amt *= sizeof (Elf_External_Sym_Shndx);
-	      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	      if (shndx_buf == NULL)
-		goto error_return;
-	      if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) shndx_buf, amt, input_bfd) != amt)
+	      isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	      if (isymbuf == NULL)
+		isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
+						symtab_hdr->sh_info, 0,
+						NULL, NULL, NULL);
+	      if (isymbuf == NULL)
 		goto error_return;
 	    }
 
@@ -875,7 +845,6 @@ mn10300_elf_relax_section (abfd, sec, li
 		  contents = (bfd_byte *) bfd_malloc (section->_raw_size);
 		  if (contents == NULL)
 		    goto error_return;
-		  free_contents = contents;
 
 		  if (!bfd_get_section_contents (input_bfd, section,
 						 contents, (file_ptr) 0,
@@ -883,10 +852,7 @@ mn10300_elf_relax_section (abfd, sec, li
 		    goto error_return;
 		}
 	      else
-		{
-		  contents = NULL;
-		  free_contents = NULL;
-		}
+		contents = NULL;
 
 	      /* If there aren't any relocs, then there's nothing to do.  */
 	      if ((section->flags & SEC_RELOC) != 0
@@ -900,8 +866,6 @@ mn10300_elf_relax_section (abfd, sec, li
 				      link_info->keep_memory));
 		  if (internal_relocs == NULL)
 		    goto error_return;
-		  if (! link_info->keep_memory)
-		    free_relocs = internal_relocs;
 
 		  /* Now examine each relocation.  */
 		  irel = internal_relocs;
@@ -927,40 +891,31 @@ mn10300_elf_relax_section (abfd, sec, li
 		      if (r_index < symtab_hdr->sh_info)
 			{
 			  /* A local symbol.  */
-			  Elf32_External_Sym *esym;
-			  Elf_External_Sym_Shndx *shndx;
-			  Elf_Internal_Sym isym;
+			  Elf_Internal_Sym *isym;
 			  struct elf_link_hash_table *elftab;
 			  bfd_size_type amt;
 
-			  esym = extsyms + r_index;
-			  shndx = shndx_buf + (shndx_buf ? r_index : 0);
-			  bfd_elf32_swap_symbol_in (input_bfd,
-						    (const PTR) esym,
-						    (const PTR) shndx,
-						    &isym);
-
-			  if (isym.st_shndx == SHN_UNDEF)
+			  isym = isymbuf + r_index;
+			  if (isym->st_shndx == SHN_UNDEF)
 			    sym_sec = bfd_und_section_ptr;
-			  else if (isym.st_shndx == SHN_ABS)
+			  else if (isym->st_shndx == SHN_ABS)
 			    sym_sec = bfd_abs_section_ptr;
-			  else if (isym.st_shndx == SHN_COMMON)
+			  else if (isym->st_shndx == SHN_COMMON)
 			    sym_sec = bfd_com_section_ptr;
 			  else
 			    sym_sec
 			      = bfd_section_from_elf_index (input_bfd,
-							    isym.st_shndx);
+							    isym->st_shndx);
 
 			  sym_name
 			    = bfd_elf_string_from_elf_section (input_bfd,
 							       (symtab_hdr
 								->sh_link),
-							       isym.st_name);
+							       isym->st_name);
 
 			  /* If it isn't a function, then we don't care
 			     about it.  */
-			  if (r_index < symtab_hdr->sh_info
-			      && ELF_ST_TYPE (isym.st_info) != STT_FUNC)
+			  if (ELF_ST_TYPE (isym->st_info) != STT_FUNC)
 			    continue;
 
 			  /* Tack on an ID so we can uniquely identify this
@@ -995,8 +950,9 @@ mn10300_elf_relax_section (abfd, sec, li
 		      if (code != 0xdd && code != 0xcd)
 			hash->flags |= MN10300_CONVERT_CALL_TO_CALLS;
 
-		      /* If this is a jump/call, then bump the direct_calls
-			 counter.  Else force "call" to "calls" conversions.  */
+		      /* If this is a jump/call, then bump the
+			 direct_calls counter.  Else force "call" to
+			 "calls" conversions.  */
 		      if (r_type == R_MN10300_PCREL32
 			  || r_type == R_MN10300_PCREL16)
 			hash->direct_calls++;
@@ -1010,46 +966,40 @@ mn10300_elf_relax_section (abfd, sec, li
 		 (ie movm_args).  */
 	      if ((section->flags & SEC_CODE) != 0)
 		{
-
-		  Elf32_External_Sym *esym, *esymend;
-		  Elf_External_Sym_Shndx *shndx;
-		  int idx;
+		  Elf_Internal_Sym *isym, *isymend;
 		  unsigned int sec_shndx;
+		  struct elf_link_hash_entry **hashes;
+		  struct elf_link_hash_entry **end_hashes;
+		  unsigned int symcount;
 
 		  sec_shndx = _bfd_elf_section_from_bfd_section (input_bfd,
 								 section);
 
 		  /* Look at each function defined in this section and
 		     update info for that function.  */
-		  for (esym = extsyms, esymend = esym + symtab_hdr->sh_info,
-			 shndx = shndx_buf;
-		       esym < esymend;
-		       esym++, shndx = (shndx ? shndx + 1 : NULL))
+		  isymend = isymbuf + symtab_hdr->sh_info;
+		  for (isym = isymbuf; isym < isymend; isym++)
 		    {
-		      Elf_Internal_Sym isym;
-
-		      bfd_elf32_swap_symbol_in (input_bfd, (const PTR) esym,
-						(const PTR) shndx, &isym);
-		      if (isym.st_shndx == sec_shndx
-			  && ELF_ST_TYPE (isym.st_info) == STT_FUNC)
+		      if (isym->st_shndx == sec_shndx
+			  && ELF_ST_TYPE (isym->st_info) == STT_FUNC)
 			{
 			  struct elf_link_hash_table *elftab;
 			  bfd_size_type amt;
 
-			  if (isym.st_shndx == SHN_UNDEF)
+			  if (isym->st_shndx == SHN_UNDEF)
 			    sym_sec = bfd_und_section_ptr;
-			  else if (isym.st_shndx == SHN_ABS)
+			  else if (isym->st_shndx == SHN_ABS)
 			    sym_sec = bfd_abs_section_ptr;
-			  else if (isym.st_shndx == SHN_COMMON)
+			  else if (isym->st_shndx == SHN_COMMON)
 			    sym_sec = bfd_com_section_ptr;
 			  else
 			    sym_sec
 			      = bfd_section_from_elf_index (input_bfd,
-							    isym.st_shndx);
+							    isym->st_shndx);
 
 			  sym_name = (bfd_elf_string_from_elf_section
 				      (input_bfd, symtab_hdr->sh_link,
-				       isym.st_name));
+				       isym->st_name));
 
 			  /* Tack on an ID so we can uniquely identify this
 			     local symbol in the global hash table.  */
@@ -1068,23 +1018,21 @@ mn10300_elf_relax_section (abfd, sec, li
 							true, true, false));
 			  free (new_name);
 			  compute_function_info (input_bfd, hash,
-						 isym.st_value, contents);
+						 isym->st_value, contents);
 			}
 		    }
 
-		  esym = extsyms + symtab_hdr->sh_info;
-		  esymend = extsyms + (symtab_hdr->sh_size
-				       / sizeof (Elf32_External_Sym));
-		  for (idx = 0; esym < esymend; esym++, idx++)
+		  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
+			      - symtab_hdr->sh_info);
+		  hashes = elf_sym_hashes (abfd);
+		  end_hashes = hashes + symcount;
+		  for (; hashes < end_hashes; hashes++)
 		    {
-		      Elf_Internal_Sym isym;
-
-		      hash = (struct elf32_mn10300_link_hash_entry *)
-			       elf_sym_hashes (input_bfd)[idx];
+		      hash = (struct elf32_mn10300_link_hash_entry *) *hashes;
 		      if ((hash->root.root.type == bfd_link_hash_defined
 			   || hash->root.root.type == bfd_link_hash_defweak)
 			  && hash->root.root.u.def.section == section
-			  && ELF_ST_TYPE (isym.st_info) == STT_FUNC)
+			  && ELF_ST_TYPE (isym->st_info) == STT_FUNC)
 			compute_function_info (input_bfd, hash,
 					       (hash)->root.root.u.def.value,
 					       contents);
@@ -1092,44 +1040,39 @@ mn10300_elf_relax_section (abfd, sec, li
 		}
 
 	      /* Cache or free any memory we allocated for the relocs.  */
-	      if (free_relocs != NULL)
-		{
-		  free (free_relocs);
-		  free_relocs = NULL;
-		}
+	      if (internal_relocs != NULL
+		  && elf_section_data (section)->relocs != internal_relocs)
+		free (internal_relocs);
+	      internal_relocs = NULL;
 
 	      /* Cache or free any memory we allocated for the contents.  */
-	      if (free_contents != NULL)
+	      if (contents != NULL
+		  && elf_section_data (section)->this_hdr.contents != contents)
 		{
 		  if (! link_info->keep_memory)
-		    free (free_contents);
+		    free (contents);
 		  else
 		    {
 		      /* Cache the section contents for elf_link_input_bfd.  */
 		      elf_section_data (section)->this_hdr.contents = contents;
 		    }
-		  free_contents = NULL;
 		}
-	    }
-
-	  if (shndx_buf != NULL)
-	    {
-	      free (shndx_buf);
-	      shndx_buf = NULL;
+	      contents = NULL;
 	    }
 
 	  /* Cache or free any memory we allocated for the symbols.  */
-	  if (free_extsyms != NULL)
+	  if (isymbuf != NULL
+	      && symtab_hdr->contents != (unsigned char *) isymbuf)
 	    {
 	      if (! link_info->keep_memory)
-		free (free_extsyms);
+		free (isymbuf);
 	      else
 		{
 		  /* Cache the symbols for elf_link_input_bfd.  */
-		  symtab_hdr->contents = (unsigned char *) extsyms;
+		  symtab_hdr->contents = (unsigned char *) isymbuf;
 		}
-	      free_extsyms = NULL;
 	    }
+	  isymbuf = NULL;
 	}
 
       /* Now iterate on each symbol in the hash table and perform
@@ -1152,45 +1095,17 @@ mn10300_elf_relax_section (abfd, sec, li
 	   input_bfd != NULL;
 	   input_bfd = input_bfd->link_next)
 	{
-	  asection *section;
-
 	  /* We're going to need all the local symbols for each bfd.  */
 	  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
-	  shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr;
-
-	  /* Get cached copy if it exists.  */
-	  if (symtab_hdr->contents != NULL)
-	    extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-	  else
-	    {
-	      /* Go get them off disk.  */
-	      bfd_size_type amt;
-
-	      amt = symtab_hdr->sh_info;
-	      amt *= sizeof (Elf32_External_Sym);
-	      extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
-	      if (extsyms == NULL)
-		goto error_return;
-	      free_extsyms = extsyms;
-	      if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) extsyms, amt, input_bfd) != amt)
-		goto error_return;
-	      symtab_hdr->contents = (bfd_byte *) extsyms;
-	    }
-
-	  if (shndx_hdr->sh_size != 0)
+	  if (symtab_hdr->sh_info != 0)
 	    {
-	      bfd_size_type amt;
-
-	      amt = symtab_hdr->sh_info;
-	      amt *= sizeof (Elf_External_Sym_Shndx);
-	      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	      if (shndx_buf == NULL)
-		goto error_return;
-	      if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) shndx_buf, amt, input_bfd) != amt)
+	      isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	      if (isymbuf == NULL)
+		isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
+						symtab_hdr->sh_info, 0,
+						NULL, NULL, NULL);
+	      if (isymbuf == NULL)
 		goto error_return;
-	      shndx_hdr->contents = (bfd_byte *) shndx_buf;
 	    }
 
 	  /* Walk over each section in this bfd.  */
@@ -1199,9 +1114,10 @@ mn10300_elf_relax_section (abfd, sec, li
 	       section = section->next)
 	    {
 	      unsigned int sec_shndx;
-	      Elf32_External_Sym *esym, *esymend;
-	      Elf_External_Sym_Shndx *shndx;
-	      unsigned int idx;
+	      Elf_Internal_Sym *isym, *isymend;
+	      struct elf_link_hash_entry **hashes;
+	      struct elf_link_hash_entry **end_hashes;
+	      unsigned int symcount;
 
 	      /* Skip non-code sections and empty sections.  */
 	      if ((section->flags & SEC_CODE) == 0 || section->_raw_size == 0)
@@ -1216,8 +1132,6 @@ mn10300_elf_relax_section (abfd, sec, li
 				      link_info->keep_memory));
 		  if (internal_relocs == NULL)
 		    goto error_return;
-		  if (! link_info->keep_memory)
-		    free_relocs = internal_relocs;
 		}
 
 	      /* Get cached copy of section contents if it exists.  */
@@ -1229,7 +1143,6 @@ mn10300_elf_relax_section (abfd, sec, li
 		  contents = (bfd_byte *) bfd_malloc (section->_raw_size);
 		  if (contents == NULL)
 		    goto error_return;
-		  free_contents = contents;
 
 		  if (!bfd_get_section_contents (input_bfd, section,
 						 contents, (file_ptr) 0,
@@ -1242,12 +1155,9 @@ mn10300_elf_relax_section (abfd, sec, li
 
 	      /* Now look for any function in this section which needs
 		 insns deleted from its prologue.  */
-	      for (esym = extsyms, esymend = esym + symtab_hdr->sh_info,
-		     shndx = shndx_buf;
-		   esym < esymend;
-		   esym++, shndx = (shndx ? shndx + 1 : NULL))
+	      isymend = isymbuf + symtab_hdr->sh_info;
+	      for (isym = isymbuf; isym < isymend; isym++)
 		{
-		  Elf_Internal_Sym isym;
 		  struct elf32_mn10300_link_hash_entry *sym_hash;
 		  asection *sym_sec = NULL;
 		  const char *sym_name;
@@ -1255,26 +1165,23 @@ mn10300_elf_relax_section (abfd, sec, li
 		  struct elf_link_hash_table *elftab;
 		  bfd_size_type amt;
 
-		  bfd_elf32_swap_symbol_in (input_bfd, (const PTR) esym,
-					    (const PTR) shndx, &isym);
-
-		  if (isym.st_shndx != sec_shndx)
+		  if (isym->st_shndx != sec_shndx)
 		    continue;
 
-		  if (isym.st_shndx == SHN_UNDEF)
+		  if (isym->st_shndx == SHN_UNDEF)
 		    sym_sec = bfd_und_section_ptr;
-		  else if (isym.st_shndx == SHN_ABS)
+		  else if (isym->st_shndx == SHN_ABS)
 		    sym_sec = bfd_abs_section_ptr;
-		  else if (isym.st_shndx == SHN_COMMON)
+		  else if (isym->st_shndx == SHN_COMMON)
 		    sym_sec = bfd_com_section_ptr;
 		  else
 		    sym_sec
-		      = bfd_section_from_elf_index (input_bfd, isym.st_shndx);
+		      = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
 
 		  sym_name
 		    = bfd_elf_string_from_elf_section (input_bfd,
 						       symtab_hdr->sh_link,
-						       isym.st_name);
+						       isym->st_name);
 
 		  /* Tack on an ID so we can uniquely identify this
 		     local symbol in the global hash table.  */
@@ -1301,12 +1208,8 @@ mn10300_elf_relax_section (abfd, sec, li
 
 		      /* Note that we've changed things.  */
 		      elf_section_data (section)->relocs = internal_relocs;
-		      free_relocs = NULL;
-
 		      elf_section_data (section)->this_hdr.contents = contents;
-		      free_contents = NULL;
-
-		      free_extsyms = NULL;
+		      symtab_hdr->contents = (unsigned char *) isymbuf;
 
 		      /* Count how many bytes we're going to delete.  */
 		      if (sym_hash->movm_args)
@@ -1325,7 +1228,7 @@ mn10300_elf_relax_section (abfd, sec, li
 		      /* Actually delete the bytes.  */
 		      if (!mn10300_elf_relax_delete_bytes (input_bfd,
 							   section,
-							   isym.st_value,
+							   isym->st_value,
 							   bytes))
 			goto error_return;
 
@@ -1337,15 +1240,15 @@ mn10300_elf_relax_section (abfd, sec, li
 
 	      /* Look for any global functions in this section which
 		 need insns deleted from their prologues.  */
-	      for (idx = 0;
-		   idx < (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
+	      symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
 			  - symtab_hdr->sh_info);
-		   idx++)
+	      hashes = elf_sym_hashes (abfd);
+	      end_hashes = hashes + symcount;
+	      for (; hashes < end_hashes; hashes++)
 		{
 		  struct elf32_mn10300_link_hash_entry *sym_hash;
 
-		  sym_hash = (struct elf32_mn10300_link_hash_entry *)
-			       (elf_sym_hashes (input_bfd)[idx]);
+		  sym_hash = (struct elf32_mn10300_link_hash_entry *) *hashes;
 		  if ((sym_hash->root.root.type == bfd_link_hash_defined
 		       || sym_hash->root.root.type == bfd_link_hash_defweak)
 		      && sym_hash->root.root.u.def.section == section
@@ -1357,12 +1260,8 @@ mn10300_elf_relax_section (abfd, sec, li
 
 		      /* Note that we've changed things.  */
 		      elf_section_data (section)->relocs = internal_relocs;
-		      free_relocs = NULL;
-
 		      elf_section_data (section)->this_hdr.contents = contents;
-		      free_contents = NULL;
-
-		      free_extsyms = NULL;
+		      symtab_hdr->contents = (unsigned char *) isymbuf;
 
 		      /* Count how many bytes we're going to delete.  */
 		      if (sym_hash->movm_args)
@@ -1393,53 +1292,48 @@ mn10300_elf_relax_section (abfd, sec, li
 		}
 
 	      /* Cache or free any memory we allocated for the relocs.  */
-	      if (free_relocs != NULL)
-		{
-		  free (free_relocs);
-		  free_relocs = NULL;
-		}
+	      if (internal_relocs != NULL
+		  && elf_section_data (section)->relocs != internal_relocs)
+		free (internal_relocs);
+	      internal_relocs = NULL;
 
 	      /* Cache or free any memory we allocated for the contents.  */
-	      if (free_contents != NULL)
+	      if (contents != NULL
+		  && elf_section_data (section)->this_hdr.contents != contents)
 		{
 		  if (! link_info->keep_memory)
-		    free (free_contents);
+		    free (contents);
 		  else
 		    {
 		      /* Cache the section contents for elf_link_input_bfd.  */
 		      elf_section_data (section)->this_hdr.contents = contents;
 		    }
-		  free_contents = NULL;
 		}
-	    }
-
-	  if (shndx_buf != NULL)
-	    {
-	      shndx_hdr->contents = NULL;
-	      free (shndx_buf);
-	      shndx_buf = NULL;
+	      contents = NULL;
 	    }
 
 	  /* Cache or free any memory we allocated for the symbols.  */
-	  if (free_extsyms != NULL)
+	  if (isymbuf != NULL
+	      && symtab_hdr->contents != (unsigned char *) isymbuf)
 	    {
 	      if (! link_info->keep_memory)
+		free (isymbuf);
+	      else
 		{
-		  symtab_hdr->contents = NULL;
-		  free (free_extsyms);
+		  /* Cache the symbols for elf_link_input_bfd.  */
+		  symtab_hdr->contents = (unsigned char *) isymbuf;
 		}
-	      free_extsyms = NULL;
 	    }
+	  isymbuf = NULL;
 	}
     }
 
   /* (Re)initialize for the basic instruction shortening/relaxing pass.  */
   contents = NULL;
-  extsyms = NULL;
   internal_relocs = NULL;
-  free_relocs = NULL;
-  free_contents = NULL;
-  free_extsyms = NULL;
+  isymbuf = NULL;
+  /* For error_return.  */
+  section = sec;
 
   /* We don't have to do anything for a relocateable link, if
      this section does not have relocs, or if this is not a
@@ -1456,7 +1350,6 @@ mn10300_elf_relax_section (abfd, sec, li
     sec->_cooked_size = sec->_raw_size;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
 
   /* Get a copy of the native relocations.  */
   internal_relocs = (_bfd_elf32_link_read_relocs
@@ -1464,8 +1357,6 @@ mn10300_elf_relax_section (abfd, sec, li
 		      link_info->keep_memory));
   if (internal_relocs == NULL)
     goto error_return;
-  if (! link_info->keep_memory)
-    free_relocs = internal_relocs;
 
   /* Walk through them looking for relaxing opportunities.  */
   irelend = internal_relocs + sec->reloc_count;
@@ -1493,7 +1384,6 @@ mn10300_elf_relax_section (abfd, sec, li
 	      contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
 	      if (contents == NULL)
 		goto error_return;
-	      free_contents = contents;
 
 	      if (! bfd_get_section_contents (abfd, sec, contents,
 					      (file_ptr) 0, sec->_raw_size))
@@ -1501,76 +1391,43 @@ mn10300_elf_relax_section (abfd, sec, li
 	    }
 	}
 
-      /* Read this BFD's symbols if we haven't done so already.  */
-      if (extsyms == NULL)
+      /* Read this BFD's symbols if we haven't done so already.  */ 
+      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
 	{
-	  /* Get cached copy if it exists.  */
-	  if (symtab_hdr->contents != NULL)
-	    extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-	  else
-	    {
-	      /* Go get them off disk.  */
-	      bfd_size_type amt;
-
-	      amt = symtab_hdr->sh_info;
-	      amt *= sizeof (Elf32_External_Sym);
-	      extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
-	      if (extsyms == NULL)
-		goto error_return;
-	      free_extsyms = extsyms;
-	      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) extsyms, amt, abfd) != amt)
-		goto error_return;
-	      symtab_hdr->contents = (bfd_byte *) extsyms;
-	    }
-
-	  if (shndx_hdr->sh_size != 0)
-	    {
-	      bfd_size_type amt;
-
-	      amt = symtab_hdr->sh_info;
-	      amt *= sizeof (Elf_External_Sym_Shndx);
-	      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	      if (shndx_buf == NULL)
-		goto error_return;
-	      if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
-		goto error_return;
-	      shndx_hdr->contents = (bfd_byte *) shndx_buf;
-	    }
+	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	  if (isymbuf == NULL)
+	    isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+					    symtab_hdr->sh_info, 0,
+					    NULL, NULL, NULL);
+	  if (isymbuf == NULL)
+	    goto error_return;
 	}
 
       /* Get the value of the symbol referred to by the reloc.  */
       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
 	{
-	  Elf32_External_Sym *esym;
-	  Elf_External_Sym_Shndx *shndx;
-	  Elf_Internal_Sym isym;
+	  Elf_Internal_Sym *isym;
 	  asection *sym_sec = NULL;
 	  const char *sym_name;
 	  char *new_name;
 
 	  /* A local symbol.  */
-	  esym = extsyms + ELF32_R_SYM (irel->r_info);
-	  shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0);
-	  bfd_elf32_swap_symbol_in (abfd, (const PTR) esym,
-				    (const PTR) shndx, &isym);
-
-	  if (isym.st_shndx == SHN_UNDEF)
+	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
+	  if (isym->st_shndx == SHN_UNDEF)
 	    sym_sec = bfd_und_section_ptr;
-	  else if (isym.st_shndx == SHN_ABS)
+	  else if (isym->st_shndx == SHN_ABS)
 	    sym_sec = bfd_abs_section_ptr;
-	  else if (isym.st_shndx == SHN_COMMON)
+	  else if (isym->st_shndx == SHN_COMMON)
 	    sym_sec = bfd_com_section_ptr;
 	  else
-	    sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);
+	    sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
 
-	  symval = (isym.st_value
+	  symval = (isym->st_value
 		    + sym_sec->output_section->vma
 		    + sym_sec->output_offset);
 	  sym_name = bfd_elf_string_from_elf_section (abfd,
 						      symtab_hdr->sh_link,
-						      isym.st_name);
+						      isym->st_name);
 
 	  /* Tack on an ID so we can uniquely identify this
 	     local symbol in the global hash table.  */
@@ -1638,12 +1495,8 @@ mn10300_elf_relax_section (abfd, sec, li
 		  /* Note that we've changed the relocs, section contents,
 		     etc.  */
 		  elf_section_data (sec)->relocs = internal_relocs;
-		  free_relocs = NULL;
-
 		  elf_section_data (sec)->this_hdr.contents = contents;
-		  free_contents = NULL;
-
-		  free_extsyms = NULL;
+		  symtab_hdr->contents = (unsigned char *) isymbuf;
 
 		  /* Fix the opcode.  */
 		  bfd_put_8 (abfd, 0xfc, contents + irel->r_offset - 1);
@@ -1702,12 +1555,8 @@ mn10300_elf_relax_section (abfd, sec, li
 
 	      /* Note that we've changed the relocs, section contents, etc.  */
 	      elf_section_data (sec)->relocs = internal_relocs;
-	      free_relocs = NULL;
-
 	      elf_section_data (sec)->this_hdr.contents = contents;
-	      free_contents = NULL;
-
-	      free_extsyms = NULL;
+	      symtab_hdr->contents = (unsigned char *) isymbuf;
 
 	      /* Fix the opcode.  */
 	      if (code == 0xdc)
@@ -1753,12 +1602,8 @@ mn10300_elf_relax_section (abfd, sec, li
 		  /* Note that we've changed the relocs, section contents,
 		     etc.  */
 		  elf_section_data (sec)->relocs = internal_relocs;
-		  free_relocs = NULL;
-
 		  elf_section_data (sec)->this_hdr.contents = contents;
-		  free_contents = NULL;
-
-		  free_extsyms = NULL;
+		  symtab_hdr->contents = (unsigned char *) isymbuf;
 
 		  /* Fix the opcode.  */
 		  bfd_put_8 (abfd, 0xfa, contents + irel->r_offset - 1);
@@ -1815,12 +1660,8 @@ mn10300_elf_relax_section (abfd, sec, li
 
 	      /* Note that we've changed the relocs, section contents, etc.  */
 	      elf_section_data (sec)->relocs = internal_relocs;
-	      free_relocs = NULL;
-
 	      elf_section_data (sec)->this_hdr.contents = contents;
-	      free_contents = NULL;
-
-	      free_extsyms = NULL;
+	      symtab_hdr->contents = (unsigned char *) isymbuf;
 
 	      /* Fix the opcode.  */
 	      bfd_put_8 (abfd, 0xca, contents + irel->r_offset - 1);
@@ -1904,17 +1745,14 @@ mn10300_elf_relax_section (abfd, sec, li
 
 	  /* We also have to be sure there is no symbol/label
 	     at the unconditional branch.  */
-	  if (mn10300_elf_symbol_address_p (abfd, sec, irel->r_offset + 1))
+	  if (mn10300_elf_symbol_address_p (abfd, sec, isymbuf,
+					    irel->r_offset + 1))
 	    continue;
 
 	  /* Note that we've changed the relocs, section contents, etc.  */
 	  elf_section_data (sec)->relocs = internal_relocs;
-	  free_relocs = NULL;
-
 	  elf_section_data (sec)->this_hdr.contents = contents;
-	  free_contents = NULL;
-
-	  free_extsyms = NULL;
+	  symtab_hdr->contents = (unsigned char *) isymbuf;
 
 	  /* Reverse the condition of the first branch.  */
 	  switch (code)
@@ -2022,12 +1860,8 @@ mn10300_elf_relax_section (abfd, sec, li
 			  /* Note that we've changed the relocation contents,
 			     etc.  */
 			  elf_section_data (sec)->relocs = internal_relocs;
-			  free_relocs = NULL;
-
 			  elf_section_data (sec)->this_hdr.contents = contents;
-			  free_contents = NULL;
-
-			  free_extsyms = NULL;
+			  symtab_hdr->contents = (unsigned char *) isymbuf;
 
 			  /* Fix the opcode.  */
 			  bfd_put_8 (abfd, 0xfb, contents + irel->r_offset - 3);
@@ -2097,12 +1931,8 @@ mn10300_elf_relax_section (abfd, sec, li
 			  /* Note that we've changed the relocation contents,
 			     etc.  */
 			  elf_section_data (sec)->relocs = internal_relocs;
-			  free_relocs = NULL;
-
 			  elf_section_data (sec)->this_hdr.contents = contents;
-			  free_contents = NULL;
-
-			  free_extsyms = NULL;
+			  symtab_hdr->contents = (unsigned char *) isymbuf;
 
 			  /* Fix the opcode.  */
 			  bfd_put_8 (abfd, 0xfd, contents + irel->r_offset - 3);
@@ -2180,12 +2010,8 @@ mn10300_elf_relax_section (abfd, sec, li
 
 		    /* Note that we've changed the relocation contents, etc.  */
 		    elf_section_data (sec)->relocs = internal_relocs;
-		    free_relocs = NULL;
-
 		    elf_section_data (sec)->this_hdr.contents = contents;
-		    free_contents = NULL;
-
-		    free_extsyms = NULL;
+		    symtab_hdr->contents = (unsigned char *) isymbuf;
 
 		    /* Fix the opcode.  */
 		    bfd_put_8 (abfd, 0xfa, contents + irel->r_offset - 2);
@@ -2217,12 +2043,8 @@ mn10300_elf_relax_section (abfd, sec, li
 		  case 0x83:
 		    /* Note that we've changed the relocation contents, etc.  */
 		    elf_section_data (sec)->relocs = internal_relocs;
-		    free_relocs = NULL;
-
 		    elf_section_data (sec)->this_hdr.contents = contents;
-		    free_contents = NULL;
-
-		    free_extsyms = NULL;
+		    symtab_hdr->contents = (unsigned char *) isymbuf;
 
 		    if ((code & 0xf3) == 0x81)
 		      code = 0x01 + (code & 0x0c);
@@ -2271,12 +2093,8 @@ mn10300_elf_relax_section (abfd, sec, li
 
 		    /* Note that we've changed the relocation contents, etc.  */
 		    elf_section_data (sec)->relocs = internal_relocs;
-		    free_relocs = NULL;
-
 		    elf_section_data (sec)->this_hdr.contents = contents;
-		    free_contents = NULL;
-
-		    free_extsyms = NULL;
+		    symtab_hdr->contents = (unsigned char *) isymbuf;
 
 		    /* Fix the opcode.  */
 		    bfd_put_8 (abfd, 0xfa, contents + irel->r_offset - 2);
@@ -2323,12 +2141,8 @@ mn10300_elf_relax_section (abfd, sec, li
 
 		    /* Note that we've changed the relocation contents, etc.  */
 		    elf_section_data (sec)->relocs = internal_relocs;
-		    free_relocs = NULL;
-
 		    elf_section_data (sec)->this_hdr.contents = contents;
-		    free_contents = NULL;
-
-		    free_extsyms = NULL;
+		    symtab_hdr->contents = (unsigned char *) isymbuf;
 
 		    if ((code & 0xfc) == 0xcc)
 		      code = 0x2c + (code & 0x03);
@@ -2404,12 +2218,8 @@ mn10300_elf_relax_section (abfd, sec, li
 
 		    /* Note that we've changed the relocation contents, etc.  */
 		    elf_section_data (sec)->relocs = internal_relocs;
-		    free_relocs = NULL;
-
 		    elf_section_data (sec)->this_hdr.contents = contents;
-		    free_contents = NULL;
-
-		    free_extsyms = NULL;
+		    symtab_hdr->contents = (unsigned char *) isymbuf;
 
 		    /* Fix the opcode.  */
 		    bfd_put_8 (abfd, 0xfa, contents + irel->r_offset - 2);
@@ -2435,12 +2245,8 @@ mn10300_elf_relax_section (abfd, sec, li
 
 		  /* Note that we've changed the relocation contents, etc.  */
 		  elf_section_data (sec)->relocs = internal_relocs;
-		  free_relocs = NULL;
-
 		  elf_section_data (sec)->this_hdr.contents = contents;
-		  free_contents = NULL;
-
-		  free_extsyms = NULL;
+		  symtab_hdr->contents = (unsigned char *) isymbuf;
 
 		  /* Fix the opcode.  */
 		  bfd_put_8 (abfd, 0xfa, contents + irel->r_offset - 2);
@@ -2464,52 +2270,46 @@ mn10300_elf_relax_section (abfd, sec, li
 	}
     }
 
-  if (free_relocs != NULL)
-    free (free_relocs);
-
-  if (free_contents != NULL)
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
     {
       if (! link_info->keep_memory)
-	free (free_contents);
+	free (isymbuf);
       else
 	{
-	  /* Cache the section contents for elf_link_input_bfd.  */
-	  elf_section_data (sec)->this_hdr.contents = contents;
+	  /* Cache the symbols for elf_link_input_bfd.  */
+	  symtab_hdr->contents = (unsigned char *) isymbuf;
 	}
     }
 
-  if (shndx_buf != NULL)
-    {
-      shndx_hdr->contents = NULL;
-      free (shndx_buf);
-    }
-
-  if (free_extsyms != NULL)
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
     {
       if (! link_info->keep_memory)
+	free (contents);
+      else
 	{
-	  symtab_hdr->contents = NULL;
-	  free (free_extsyms);
+	  /* Cache the section contents for elf_link_input_bfd.  */
+	  elf_section_data (sec)->this_hdr.contents = contents;
 	}
     }
 
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
+
   return true;
 
  error_return:
-  if (free_relocs != NULL)
-    free (free_relocs);
-  if (free_contents != NULL)
-    free (free_contents);
-  if (shndx_buf != NULL)
-    {
-      shndx_hdr->contents = NULL;
-      free (shndx_buf);
-    }
-  if (free_extsyms != NULL)
-    {
-      symtab_hdr->contents = NULL;
-      free (free_extsyms);
-    }
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
+  if (contents != NULL
+      && elf_section_data (section)->this_hdr.contents != contents)
+    free (contents);
+  if (internal_relocs != NULL
+      && elf_section_data (section)->relocs != internal_relocs)
+    free (internal_relocs);
 
   return false;
 }
@@ -2624,22 +2424,16 @@ mn10300_elf_relax_delete_bytes (abfd, se
      int count;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
-  Elf32_External_Sym *extsyms;
   unsigned int sec_shndx;
   bfd_byte *contents;
   Elf_Internal_Rela *irel, *irelend;
   Elf_Internal_Rela *irelalign;
   bfd_vma toaddr;
-  Elf32_External_Sym *esym, *esymend;
-  Elf_External_Sym_Shndx *shndx;
+  Elf_Internal_Sym *isym, *isymend;
   struct elf_link_hash_entry **sym_hashes;
   struct elf_link_hash_entry **end_hashes;
   unsigned int symcount;
 
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-
   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
   contents = elf_section_data (sec)->this_hdr.contents;
@@ -2668,25 +2462,14 @@ mn10300_elf_relax_delete_bytes (abfd, se
     }
 
   /* Adjust the local symbols defined in this section.  */
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-  shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
-  esym = extsyms;
-  esymend = esym + symtab_hdr->sh_info;
-  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
+  for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
     {
-      Elf_Internal_Sym isym;
-      Elf_External_Sym_Shndx dummy;
-
-      bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				&isym);
-
-      if (isym.st_shndx == sec_shndx
-	  && isym.st_value > addr
-	  && isym.st_value < toaddr)
-	{
-	  isym.st_value -= count;
-	  bfd_elf32_swap_symbol_out (abfd, &isym, (PTR) esym, (PTR) &dummy);
-	}
+      if (isym->st_shndx == sec_shndx
+	  && isym->st_value > addr
+	  && isym->st_value < toaddr)
+	isym->st_value -= count;
     }
 
   /* Now adjust the global symbols defined in this section.  */
@@ -2713,16 +2496,15 @@ mn10300_elf_relax_delete_bytes (abfd, se
 /* Return true if a symbol exists at the given address, else return
    false.  */
 static boolean
-mn10300_elf_symbol_address_p (abfd, sec, addr)
+mn10300_elf_symbol_address_p (abfd, sec, isym, addr)
      bfd *abfd;
      asection *sec;
+     Elf_Internal_Sym *isym;
      bfd_vma addr;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   unsigned int sec_shndx;
-  Elf32_External_Sym *esym, *esymend;
-  Elf_External_Sym_Shndx *shndx;
+  Elf_Internal_Sym *isymend;
   struct elf_link_hash_entry **sym_hashes;
   struct elf_link_hash_entry **end_hashes;
   unsigned int symcount;
@@ -2731,19 +2513,10 @@ mn10300_elf_symbol_address_p (abfd, sec,
 
   /* Examine all the symbols.  */
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-  shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
-  esym = (Elf32_External_Sym *) symtab_hdr->contents;
-  esymend = esym + symtab_hdr->sh_info;
-  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
+  for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
     {
-      Elf_Internal_Sym isym;
-
-      bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				&isym);
-
-      if (isym.st_shndx == sec_shndx
-	  && isym.st_value == addr)
+      if (isym->st_shndx == sec_shndx
+	  && isym->st_value == addr)
 	return true;
     }
 
@@ -2778,15 +2551,11 @@ mn10300_elf_get_relocated_section_conten
      asymbol **symbols;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   asection *input_section = link_order->u.indirect.section;
   bfd *input_bfd = input_section->owner;
   asection **sections = NULL;
   Elf_Internal_Rela *internal_relocs = NULL;
-  Elf32_External_Sym *external_syms = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
-  Elf_External_Sym_Shndx *shndx;
-  Elf_Internal_Sym *internal_syms = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
 
   /* We only need to handle the case of relaxing, or of having a
      particular set of section contents, specially.  */
@@ -2798,7 +2567,6 @@ mn10300_elf_get_relocated_section_conten
 						       symbols);
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
-  shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr;
 
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
 	  (size_t) input_section->_raw_size);
@@ -2806,48 +2574,26 @@ mn10300_elf_get_relocated_section_conten
   if ((input_section->flags & SEC_RELOC) != 0
       && input_section->reloc_count > 0)
     {
-      Elf_Internal_Sym *isymp;
       asection **secpp;
-      Elf32_External_Sym *esym, *esymend;
+      Elf_Internal_Sym *isym, *isymend;
       bfd_size_type amt;
 
-      if (symtab_hdr->contents != NULL)
-	external_syms = (Elf32_External_Sym *) symtab_hdr->contents;
-      else if (symtab_hdr->sh_info != 0)
-	{
-	  amt = symtab_hdr->sh_info;
-	  amt *= sizeof (Elf32_External_Sym);
-	  external_syms = (Elf32_External_Sym *) bfd_malloc (amt);
-	  if (external_syms == NULL)
-	    goto error_return;
-	  if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread ((PTR) external_syms, amt, input_bfd) != amt)
-	    goto error_return;
-	}
-
-      if (symtab_hdr->sh_info != 0 && shndx_hdr->sh_size != 0)
-	{
-	  amt = symtab_hdr->sh_info;
-	  amt *= sizeof (Elf_External_Sym_Shndx);
-	  shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	  if (shndx_buf == NULL)
-	    goto error_return;
-	  if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread ((PTR) shndx_buf, amt, input_bfd) != amt)
-	    goto error_return;
-	}
-
       internal_relocs = (_bfd_elf32_link_read_relocs
 			 (input_bfd, input_section, (PTR) NULL,
 			  (Elf_Internal_Rela *) NULL, false));
       if (internal_relocs == NULL)
 	goto error_return;
 
-      amt = symtab_hdr->sh_info;
-      amt *= sizeof (Elf_Internal_Sym);
-      internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt);
-      if (internal_syms == NULL && amt != 0)
-	goto error_return;
+      if (symtab_hdr->sh_info != 0)
+	{
+	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	  if (isymbuf == NULL)
+	    isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
+					    symtab_hdr->sh_info, 0,
+					    NULL, NULL, NULL);
+	  if (isymbuf == NULL)
+	    goto error_return;
+	}
 
       amt = symtab_hdr->sh_info;
       amt *= sizeof (asection *);
@@ -2855,41 +2601,32 @@ mn10300_elf_get_relocated_section_conten
       if (sections == NULL && amt != 0)
 	goto error_return;
 
-      for (isymp = internal_syms, secpp = sections, shndx = shndx_buf,
-	     esym = external_syms, esymend = esym + symtab_hdr->sh_info;
-	   esym < esymend;
-	   ++esym, ++isymp, ++secpp, shndx = (shndx ? shndx + 1 : NULL))
+      isymend = isymbuf + symtab_hdr->sh_info;
+      for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
 	{
 	  asection *isec;
 
-	  bfd_elf32_swap_symbol_in (input_bfd, (const PTR) esym,
-				    (const PTR) shndx, isymp);
-
-	  if (isymp->st_shndx == SHN_UNDEF)
+	  if (isym->st_shndx == SHN_UNDEF)
 	    isec = bfd_und_section_ptr;
-	  else if (isymp->st_shndx == SHN_ABS)
+	  else if (isym->st_shndx == SHN_ABS)
 	    isec = bfd_abs_section_ptr;
-	  else if (isymp->st_shndx == SHN_COMMON)
+	  else if (isym->st_shndx == SHN_COMMON)
 	    isec = bfd_com_section_ptr;
 	  else
-	    isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
+	    isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
 
 	  *secpp = isec;
 	}
 
       if (! mn10300_elf_relocate_section (output_bfd, link_info, input_bfd,
 				     input_section, data, internal_relocs,
-				     internal_syms, sections))
+				     isymbuf, sections))
 	goto error_return;
 
       if (sections != NULL)
 	free (sections);
-      if (internal_syms != NULL)
-	free (internal_syms);
-      if (shndx_buf != NULL)
-	free (shndx_buf);
-      if (external_syms != NULL && symtab_hdr->contents == NULL)
-	free (external_syms);
+      if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
+	free (isymbuf);
       if (internal_relocs != elf_section_data (input_section)->relocs)
 	free (internal_relocs);
     }
@@ -2897,17 +2634,13 @@ mn10300_elf_get_relocated_section_conten
   return data;
 
  error_return:
+  if (sections != NULL)
+    free (sections);
+  if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
   if (internal_relocs != NULL
       && internal_relocs != elf_section_data (input_section)->relocs)
     free (internal_relocs);
-  if (shndx_buf != NULL)
-    free (shndx_buf);
-  if (external_syms != NULL && symtab_hdr->contents == NULL)
-    free (external_syms);
-  if (internal_syms != NULL)
-    free (internal_syms);
-  if (sections != NULL)
-    free (sections);
   return NULL;
 }
 
Index: bfd/elf32-h8300.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-h8300.c,v
retrieving revision 1.13
diff -u -p -r1.13 elf32-h8300.c
--- bfd/elf32-h8300.c	6 Jun 2002 21:33:11 -0000	1.13
+++ bfd/elf32-h8300.c	7 Jul 2002 06:59:04 -0000
@@ -688,15 +688,10 @@ elf32_h8_relax_section (abfd, sec, link_
      boolean *again;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *free_relocs = NULL;
   Elf_Internal_Rela *irel, *irelend;
   bfd_byte *contents = NULL;
-  bfd_byte *free_contents = NULL;
-  Elf32_External_Sym *extsyms = NULL;
-  Elf32_External_Sym *free_extsyms = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
   static asection *last_input_section = NULL;
   static Elf_Internal_Rela *last_reloc = NULL;
 
@@ -718,7 +713,6 @@ elf32_h8_relax_section (abfd, sec, link_
     sec->_cooked_size = sec->_raw_size;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
 
   /* Get a copy of the native relocations.  */
   internal_relocs = (_bfd_elf32_link_read_relocs
@@ -726,8 +720,6 @@ elf32_h8_relax_section (abfd, sec, link_
 		      link_info->keep_memory));
   if (internal_relocs == NULL)
     goto error_return;
-  if (! link_info->keep_memory)
-    free_relocs = internal_relocs;
 
   if (sec != last_input_section)
     last_reloc = NULL;
@@ -764,7 +756,6 @@ elf32_h8_relax_section (abfd, sec, link_
 	      contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
 	      if (contents == NULL)
 		goto error_return;
-	      free_contents = contents;
 
 	      if (! bfd_get_section_contents (abfd, sec, contents,
 					      (file_ptr) 0, sec->_raw_size))
@@ -773,58 +764,27 @@ elf32_h8_relax_section (abfd, sec, link_
 	}
 
       /* Read this BFD's local symbols if we haven't done so already.  */
-      if (extsyms == NULL)
+      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
 	{
-	  /* Get cached copy if it exists.  */
-	  if (symtab_hdr->contents != NULL)
-	    extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-	  else
-	    {
-	      /* Go get them off disk.  */
-	      bfd_size_type amt;
-
-	      amt = symtab_hdr->sh_info * sizeof (Elf32_External_Sym);
-	      extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
-	      if (extsyms == NULL)
-		goto error_return;
-	      free_extsyms = extsyms;
-	      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) extsyms, amt, abfd) != amt)
-		goto error_return;
-	      symtab_hdr->contents = (PTR) extsyms;
-	    }
-
-	  if (shndx_hdr->sh_size != 0)
-	    {
-	      bfd_size_type amt;
-
-	      amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx);
-	      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	      if (shndx_buf == NULL)
-		goto error_return;
-	      if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
-		goto error_return;
-	      shndx_hdr->contents = (PTR) shndx_buf;
-	    }
+	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	  if (isymbuf == NULL)
+	    isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+					    symtab_hdr->sh_info, 0,
+					    NULL, NULL, NULL);
+	  if (isymbuf == NULL)
+	    goto error_return;
 	}
 
       /* Get the value of the symbol referred to by the reloc.  */
       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
 	{
-	  Elf32_External_Sym *esym;
-	  Elf_External_Sym_Shndx *shndx;
-	  Elf_Internal_Sym isym;
-	  asection *sym_sec;
-
 	  /* A local symbol.  */
-	  esym = extsyms + ELF32_R_SYM (irel->r_info);
-	  shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0);
-	  bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				    &isym);
+	  Elf_Internal_Sym *isym;
+	  asection *sym_sec;
 
-	  sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);
-	  symval = (isym.st_value
+	  isym = isymbuf + ELF64_R_SYM (irel->r_info);
+	  sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+	  symval = (isym->st_value
 		    + sym_sec->output_section->vma
 		    + sym_sec->output_offset);
 	}
@@ -884,12 +844,8 @@ elf32_h8_relax_section (abfd, sec, link_
 		/* Note that we've changed the relocs, section contents,
 		   etc.  */
 		elf_section_data (sec)->relocs = internal_relocs;
-		free_relocs = NULL;
-
 		elf_section_data (sec)->this_hdr.contents = contents;
-		free_contents = NULL;
-
-		free_extsyms = NULL;
+		symtab_hdr->contents = (unsigned char *) isymbuf;
 
 		/* If the previous instruction conditionally jumped around
 		   this instruction, we may be able to reverse the condition
@@ -904,26 +860,17 @@ elf32_h8_relax_section (abfd, sec, link_
 		    && ELF32_R_TYPE (last_reloc->r_info) == R_H8_PCREL8
 		    && ELF32_R_SYM (last_reloc->r_info) < symtab_hdr->sh_info)
 		  {
-		    Elf32_External_Sym *esym;
-		    Elf_External_Sym_Shndx *shndx;
 		    bfd_vma last_value;
 		    asection *last_sym_sec;
-		    Elf_Internal_Sym last_symbol;
+		    Elf_Internal_Sym *last_sym;
 
 		    /* We will need to examine the symbol used by the
 		       previous relocation.  */
 
-		    esym = extsyms + ELF32_R_SYM (last_reloc->r_info);
-		    shndx = shndx_buf;
-		    if (shndx != NULL)
-		      shndx += ELF32_R_SYM (last_reloc->r_info);
-		    bfd_elf32_swap_symbol_in (abfd, (const PTR) esym,
-					      (const PTR) shndx,
-					      &last_symbol);
-
+		    last_sym = isymbuf + ELF32_R_SYM (last_reloc->r_info);
 		    last_sym_sec
-		      = bfd_section_from_elf_index (abfd, last_symbol.st_shndx);
-		    last_value = (last_symbol.st_value
+		      = bfd_section_from_elf_index (abfd, last_sym->st_shndx);
+		    last_value = (last_sym->st_value
 				  + last_sym_sec->output_section->vma
 				  + last_sym_sec->output_offset);
 
@@ -1015,12 +962,8 @@ elf32_h8_relax_section (abfd, sec, link_
 	        /* Note that we've changed the relocs, section contents,
 		   etc.  */
 	        elf_section_data (sec)->relocs = internal_relocs;
-	        free_relocs = NULL;
-
 	        elf_section_data (sec)->this_hdr.contents = contents;
-	        free_contents = NULL;
-
-	        free_extsyms = NULL;
+		symtab_hdr->contents = (unsigned char *) isymbuf;
 
 	        /* Get the opcode.  */
 	        code = bfd_get_8 (abfd, contents + irel->r_offset - 2);
@@ -1076,12 +1019,8 @@ elf32_h8_relax_section (abfd, sec, link_
 	        /* Note that we've changed the relocs, section contents,
 		   etc.  */
 	        elf_section_data (sec)->relocs = internal_relocs;
-	        free_relocs = NULL;
-
 	        elf_section_data (sec)->this_hdr.contents = contents;
-	        free_contents = NULL;
-
-	        free_extsyms = NULL;
+		symtab_hdr->contents = (unsigned char *) isymbuf;
 
 	        /* Get the opcode.  */
 	        code = bfd_get_8 (abfd, contents + irel->r_offset - 2);
@@ -1138,12 +1077,8 @@ elf32_h8_relax_section (abfd, sec, link_
 	        /* Note that we've changed the relocs, section contents,
 		   etc.  */
 	        elf_section_data (sec)->relocs = internal_relocs;
-	        free_relocs = NULL;
-
 	        elf_section_data (sec)->this_hdr.contents = contents;
-	        free_contents = NULL;
-
-	        free_extsyms = NULL;
+		symtab_hdr->contents = (unsigned char *) isymbuf;
 
 	        /* Get the opcode.  */
 	        code = bfd_get_8 (abfd, contents + irel->r_offset - 2);
@@ -1194,12 +1129,8 @@ elf32_h8_relax_section (abfd, sec, link_
 	        /* Note that we've changed the relocs, section contents,
 		   etc.  */
 	        elf_section_data (sec)->relocs = internal_relocs;
-	        free_relocs = NULL;
-
 	        elf_section_data (sec)->this_hdr.contents = contents;
-	        free_contents = NULL;
-
-	        free_extsyms = NULL;
+		symtab_hdr->contents = (unsigned char *) isymbuf;
 
 	        /* Get the opcode.  */
 	        code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
@@ -1230,56 +1161,43 @@ elf32_h8_relax_section (abfd, sec, link_
 	}
     }
 
-  if (free_relocs != NULL)
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
     {
-      free (free_relocs);
-      free_relocs = NULL;
+      if (! link_info->keep_memory)
+	free (isymbuf);
+      else
+	symtab_hdr->contents = (unsigned char *) isymbuf;
     }
 
-  if (free_contents != NULL)
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
     {
       if (! link_info->keep_memory)
-	free (free_contents);
+	free (contents);
       else
 	{
 	  /* Cache the section contents for elf_link_input_bfd.  */
 	  elf_section_data (sec)->this_hdr.contents = contents;
 	}
-      free_contents = NULL;
     }
 
-  if (shndx_buf != NULL)
-    {
-      shndx_hdr->contents = NULL;
-      free (shndx_buf);
-    }
-
-  if (free_extsyms != NULL)
-    {
-      if (! link_info->keep_memory)
-	{
-	  symtab_hdr->contents = NULL;
-	  free (free_extsyms);
-	}
-    }
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
 
   return true;
 
  error_return:
-  if (free_relocs != NULL)
-    free (free_relocs);
-  if (free_contents != NULL)
-    free (free_contents);
-  if (shndx_buf != NULL)
-    {
-      shndx_hdr->contents = NULL;
-      free (shndx_buf);
-    }
-  if (free_extsyms != NULL)
-    {
-      symtab_hdr->contents = NULL;
-      free (free_extsyms);
-    }
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
+    free (contents);
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
   return false;
 }
 
@@ -1293,22 +1211,17 @@ elf32_h8_relax_delete_bytes (abfd, sec, 
      int count;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
-  Elf32_External_Sym *extsyms;
   unsigned int sec_shndx;
   bfd_byte *contents;
   Elf_Internal_Rela *irel, *irelend;
   Elf_Internal_Rela *irelalign;
+  Elf_Internal_Sym *isym;
+  Elf_Internal_Sym *isymend;
   bfd_vma toaddr;
-  Elf32_External_Sym *esym, *esymend;
-  Elf_External_Sym_Shndx *shndx;
   struct elf_link_hash_entry **sym_hashes;
   struct elf_link_hash_entry **end_hashes;
   unsigned int symcount;
 
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-
   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
   contents = elf_section_data (sec)->this_hdr.contents;
@@ -1337,25 +1250,15 @@ elf32_h8_relax_delete_bytes (abfd, sec, 
     }
 
   /* Adjust the local symbols defined in this section.  */
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-  shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
-  esym = extsyms;
-  esymend = esym + symtab_hdr->sh_info;
-  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
-    {
-      Elf_Internal_Sym isym;
-      Elf_External_Sym_Shndx dummy;
-
-      bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				&isym);
-
-      if (isym.st_shndx == sec_shndx
-	  && isym.st_value > addr
-	  && isym.st_value < toaddr)
-	{
-	  isym.st_value -= count;
-	  bfd_elf32_swap_symbol_out (abfd, &isym, esym, &dummy);
-	}
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
+  isymend = isym + symtab_hdr->sh_info;
+  for (; isym < isymend; isym++)
+    {
+      if (isym->st_shndx == sec_shndx
+	  && isym->st_value > addr
+	  && isym->st_value < toaddr)
+	isym->st_value -= count;
     }
 
   /* Now adjust the global symbols defined in this section.  */
@@ -1388,10 +1291,9 @@ elf32_h8_symbol_address_p (abfd, sec, ad
      bfd_vma addr;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   unsigned int sec_shndx;
-  Elf32_External_Sym *esym, *esymend;
-  Elf_External_Sym_Shndx *shndx;
+  Elf_Internal_Sym *isym;
+  Elf_Internal_Sym *isymend;
   struct elf_link_hash_entry **sym_hashes;
   struct elf_link_hash_entry **end_hashes;
   unsigned int symcount;
@@ -1400,19 +1302,12 @@ elf32_h8_symbol_address_p (abfd, sec, ad
 
   /* Examine all the symbols.  */
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-  shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
-  esym = (Elf32_External_Sym *) symtab_hdr->contents;
-  esymend = esym + symtab_hdr->sh_info;
-  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
+  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
+  isymend = isym + symtab_hdr->sh_info;
+  for (; isym < isymend; isym++)
     {
-      Elf_Internal_Sym isym;
-
-      bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				&isym);
-
-      if (isym.st_shndx == sec_shndx
-	  && isym.st_value == addr)
+      if (isym->st_shndx == sec_shndx
+	  && isym->st_value == addr)
 	return true;
     }
 
@@ -1447,15 +1342,11 @@ elf32_h8_get_relocated_section_contents 
      asymbol **symbols;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   asection *input_section = link_order->u.indirect.section;
   bfd *input_bfd = input_section->owner;
   asection **sections = NULL;
   Elf_Internal_Rela *internal_relocs = NULL;
-  Elf32_External_Sym *external_syms = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
-  Elf_External_Sym_Shndx *shndx;
-  Elf_Internal_Sym *internal_syms = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
 
   /* We only need to handle the case of relaxing, or of having a
      particular set of section contents, specially.  */
@@ -1467,7 +1358,6 @@ elf32_h8_get_relocated_section_contents 
 						       symbols);
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
-  shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr;
 
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
 	  (size_t) input_section->_raw_size);
@@ -1475,48 +1365,26 @@ elf32_h8_get_relocated_section_contents 
   if ((input_section->flags & SEC_RELOC) != 0
       && input_section->reloc_count > 0)
     {
-      Elf_Internal_Sym *isymp;
       asection **secpp;
-      Elf32_External_Sym *esym, *esymend;
+      Elf_Internal_Sym *isym, *isymend;
       bfd_size_type amt;
 
-      if (symtab_hdr->contents != NULL)
-	external_syms = (Elf32_External_Sym *) symtab_hdr->contents;
-      else if (symtab_hdr->sh_info != 0)
-	{
-	  amt = symtab_hdr->sh_info;
-	  amt *= sizeof (Elf32_External_Sym);
-	  external_syms = (Elf32_External_Sym *) bfd_malloc (amt);
-	  if (external_syms == NULL)
-	    goto error_return;
-	  if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread ((PTR) external_syms, amt, input_bfd) != amt)
-	    goto error_return;
-	}
-
-      if (symtab_hdr->sh_info != 0 && shndx_hdr->sh_size != 0)
-	{
-	  amt = symtab_hdr->sh_info;
-	  amt *= sizeof (Elf_External_Sym_Shndx);
-	  shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	  if (shndx_buf == NULL)
-	    goto error_return;
-	  if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread ((PTR) shndx_buf, amt, input_bfd) != amt)
-	    goto error_return;
-	}
-
       internal_relocs = (_bfd_elf32_link_read_relocs
 			 (input_bfd, input_section, (PTR) NULL,
 			  (Elf_Internal_Rela *) NULL, false));
       if (internal_relocs == NULL)
 	goto error_return;
 
-      amt = symtab_hdr->sh_info;
-      amt *= sizeof (Elf_Internal_Sym);
-      internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt);
-      if (internal_syms == NULL && amt != 0)
-	goto error_return;
+      if (symtab_hdr->sh_info != 0)
+	{
+	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	  if (isymbuf == NULL)
+	    isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
+					    symtab_hdr->sh_info, 0,
+					    NULL, NULL, NULL);
+	  if (isymbuf == NULL)
+	    goto error_return;
+	}
 
       amt = symtab_hdr->sh_info;
       amt *= sizeof (asection *);
@@ -1524,59 +1392,48 @@ elf32_h8_get_relocated_section_contents 
       if (sections == NULL && amt != 0)
 	goto error_return;
 
-      for (isymp = internal_syms, secpp = sections, shndx = shndx_buf,
-	     esym = external_syms, esymend = esym + symtab_hdr->sh_info;
-	   esym < esymend;
-	   ++esym, ++isymp, ++secpp, shndx = (shndx ? shndx + 1 : NULL))
+      isymend = isymbuf + symtab_hdr->sh_info;
+      for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
 	{
 	  asection *isec;
 
-	  bfd_elf32_swap_symbol_in (input_bfd, (const PTR) esym,
-				    (const PTR) shndx, isymp);
-
-	  if (isymp->st_shndx == SHN_UNDEF)
+	  if (isym->st_shndx == SHN_UNDEF)
 	    isec = bfd_und_section_ptr;
-	  else if (isymp->st_shndx == SHN_ABS)
+	  else if (isym->st_shndx == SHN_ABS)
 	    isec = bfd_abs_section_ptr;
-	  else if (isymp->st_shndx == SHN_COMMON)
+	  else if (isym->st_shndx == SHN_COMMON)
 	    isec = bfd_com_section_ptr;
 	  else
-	    isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
+	    isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
 
 	  *secpp = isec;
 	}
 
       if (! elf32_h8_relocate_section (output_bfd, link_info, input_bfd,
 				       input_section, data, internal_relocs,
-				       internal_syms, sections))
+				       isymbuf, sections))
 	goto error_return;
 
       if (sections != NULL)
 	free (sections);
-      if (internal_syms != NULL)
-	free (internal_syms);
-      if (shndx_buf != NULL)
-	free (shndx_buf);
-      if (external_syms != NULL && symtab_hdr->contents == NULL)
-	free (external_syms);
-      if (internal_relocs != elf_section_data (input_section)->relocs)
+      if (isymbuf != NULL
+	  && symtab_hdr->contents != (unsigned char *) isymbuf)
+	free (isymbuf);
+      if (elf_section_data (input_section)->relocs != internal_relocs)
 	free (internal_relocs);
     }
 
   return data;
 
  error_return:
-  if (internal_relocs != NULL
-      && internal_relocs != elf_section_data (input_section)->relocs)
-    free (internal_relocs);
-  if (shndx_buf != NULL)
-    free (shndx_buf);
-  if (external_syms != NULL && symtab_hdr->contents == NULL)
-    free (external_syms);
-  if (internal_syms != NULL)
-    free (internal_syms);
   if (sections != NULL)
     free (sections);
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
+  if (internal_relocs != NULL
+      && elf_section_data (input_section)->relocs != internal_relocs)
+    free (internal_relocs);
   return NULL;
 }
 
Index: bfd/elf32-m32r.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-m32r.c,v
retrieving revision 1.24
diff -u -p -r1.24 elf32-m32r.c
--- bfd/elf32-m32r.c	1 Jul 2002 08:06:44 -0000	1.24
+++ bfd/elf32-m32r.c	7 Jul 2002 06:59:06 -0000
@@ -1337,13 +1337,10 @@ m32r_elf_relax_section (abfd, sec, link_
   /* The Rela structures are used here because that's what
      _bfd_elf32_link_read_relocs uses [for convenience - it sets the addend
      field to 0].  */
-  Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *free_relocs = NULL;
+  Elf_Internal_Rela *internal_relocs = NULL;
   Elf_Internal_Rela *irel, *irelend;
   bfd_byte *contents = NULL;
-  bfd_byte *free_contents = NULL;
-  Elf32_External_Sym *extsyms = NULL;
-  Elf32_External_Sym *free_extsyms = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
 
   /* Assume nothing changes.  */
   *again = false;
@@ -1371,8 +1368,6 @@ m32r_elf_relax_section (abfd, sec, link_
 		      link_info->keep_memory));
   if (internal_relocs == NULL)
     goto error_return;
-  if (! link_info->keep_memory)
-    free_relocs = internal_relocs;
 
   /* Walk through them looking for relaxing opportunities.  */
   irelend = internal_relocs + sec->reloc_count;
@@ -1397,7 +1392,6 @@ m32r_elf_relax_section (abfd, sec, link_
 	      contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
 	      if (contents == NULL)
 		goto error_return;
-	      free_contents = contents;
 
 	      if (! bfd_get_section_contents (abfd, sec, contents,
 					      (file_ptr) 0, sec->_raw_size))
@@ -1405,39 +1399,28 @@ m32r_elf_relax_section (abfd, sec, link_
 	    }
 	}
 
-      /* Read this BFD's symbols if we haven't done so already.  */
-      if (extsyms == NULL)
+      /* Read this BFD's local symbols if we haven't done so already.  */
+      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
 	{
-	  /* Get cached copy if it exists.  */
-	  if (symtab_hdr->contents != NULL)
-	    extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-	  else
-	    {
-	      bfd_size_type amt = symtab_hdr->sh_size;
-	      /* Go get them off disk.  */
-	      extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
-	      if (extsyms == NULL)
-		goto error_return;
-	      free_extsyms = extsyms;
-	      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread (extsyms, amt, abfd) != amt)
-		goto error_return;
-	    }
+	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	  if (isymbuf == NULL)
+	    isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+					    symtab_hdr->sh_info, 0,
+					    NULL, NULL, NULL);
+	  if (isymbuf == NULL)
+	    goto error_return;
 	}
 
       /* Get the value of the symbol referred to by the reloc.  */
       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
 	{
-	  Elf_Internal_Sym isym;
-	  asection *sym_sec;
-
 	  /* A local symbol.  */
-	  bfd_elf32_swap_symbol_in (abfd,
-				    extsyms + ELF32_R_SYM (irel->r_info),
-				    &isym);
+	  Elf_Internal_Sym *isym;
+	  asection *sym_sec;
 
-	  sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);
-	  symval = (isym.st_value
+	  isym = isymbuf + ELF32_R_SYM (irel->r_info),
+	  sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+	  symval = (isym->st_value
 		    + sym_sec->output_section->vma
 		    + sym_sec->output_offset);
 	}
@@ -1599,13 +1582,8 @@ m32r_elf_relax_section (abfd, sec, link_
 
 	  /* Note that we've changed the relocs, section contents, etc.  */
 	  elf_section_data (sec)->relocs = internal_relocs;
-	  free_relocs = NULL;
-
 	  elf_section_data (sec)->this_hdr.contents = contents;
-	  free_contents = NULL;
-
-	  symtab_hdr->contents = (bfd_byte *) extsyms;
-	  free_extsyms = NULL;
+	  symtab_hdr->contents = (unsigned char *) isymbuf;
 
 	  /* Delete TO_DELETE bytes of data.  */
 	  if (!m32r_elf_relax_delete_bytes (abfd, sec,
@@ -1633,45 +1611,47 @@ m32r_elf_relax_section (abfd, sec, link_
       /* loop to try the next reloc */
     }
 
-  if (free_relocs != NULL)
-    {
-      free (free_relocs);
-      free_relocs = NULL;
-    }
-
-  if (free_contents != NULL)
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
     {
       if (! link_info->keep_memory)
-	free (free_contents);
+	free (isymbuf);
       else
 	{
-	  /* Cache the section contents for elf_link_input_bfd.  */
-	  elf_section_data (sec)->this_hdr.contents = contents;
+	  /* Cache the symbols for elf_link_input_bfd.  */
+	  symtab_hdr->contents = (unsigned char *) isymbuf;
 	}
-      free_contents = NULL;
     }
 
-  if (free_extsyms != NULL)
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
     {
       if (! link_info->keep_memory)
-	free (free_extsyms);
+	free (contents);
       else
 	{
-	  /* Cache the symbols for elf_link_input_bfd.  */
-	  symtab_hdr->contents = extsyms;
+	  /* Cache the section contents for elf_link_input_bfd.  */
+	  elf_section_data (sec)->this_hdr.contents = contents;
 	}
-      free_extsyms = NULL;
     }
 
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
+
   return true;
 
  error_return:
-  if (free_relocs != NULL)
-    free (free_relocs);
-  if (free_contents != NULL)
-    free (free_contents);
-  if (free_extsyms != NULL)
-    free (free_extsyms);
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
+    free (contents);
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
+
   return false;
 }
 
@@ -1685,17 +1665,15 @@ m32r_elf_relax_delete_bytes (abfd, sec, 
      int count;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf32_External_Sym *extsyms;
-  int shndx, index;
+  int shndx;
   bfd_byte *contents;
   Elf_Internal_Rela *irel, *irelend;
   Elf_Internal_Rela *irelalign;
   bfd_vma toaddr;
-  Elf32_External_Sym *esym, *esymend;
-  struct elf_link_hash_entry *sym_hash;
-
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
+  Elf_Internal_Sym *isym, *isymend;
+  struct elf_link_hash_entry **sym_hashes;
+  struct elf_link_hash_entry **end_hashes;
+  unsigned int symcount;
 
   shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
@@ -1724,40 +1702,32 @@ m32r_elf_relax_delete_bytes (abfd, sec, 
     }
 
   /* Adjust the local symbols defined in this section.  */
-  esym = extsyms;
-  esymend = esym + symtab_hdr->sh_info;
-  for (; esym < esymend; esym++)
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
+  for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
     {
-      Elf_Internal_Sym isym;
-
-      bfd_elf32_swap_symbol_in (abfd, esym, &isym);
-
-      if (isym.st_shndx == shndx
-	  && isym.st_value > addr
-	  && isym.st_value < toaddr)
-	{
-	  isym.st_value -= count;
-	  bfd_elf32_swap_symbol_out (abfd, &isym, esym);
-	}
+      if (isym->st_shndx == shndx
+	  && isym->st_value > addr
+	  && isym->st_value < toaddr)
+	isym->st_value -= count;
     }
 
   /* Now adjust the global symbols defined in this section.  */
-  esym = extsyms + symtab_hdr->sh_info;
-  esymend = extsyms + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym));
-  for (index = 0; esym < esymend; esym++, index++)
+  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
+	      - symtab_hdr->sh_info);
+  sym_hashes = elf_sym_hashes (abfd);
+  end_hashes = sym_hashes + symcount;
+  for (; sym_hashes < end_hashes; sym_hashes++)
     {
-      Elf_Internal_Sym isym;
+      struct elf_link_hash_entry *sym_hash = *sym_hashes;
 
-      bfd_elf32_swap_symbol_in (abfd, esym, &isym);
-      sym_hash = elf_sym_hashes (abfd)[index];
-      if (isym.st_shndx == shndx
-	  && ((sym_hash)->root.type == bfd_link_hash_defined
-	      || (sym_hash)->root.type == bfd_link_hash_defweak)
-	  && (sym_hash)->root.u.def.section == sec
-	  && (sym_hash)->root.u.def.value > addr
-	  && (sym_hash)->root.u.def.value < toaddr)
+      if ((sym_hash->root.type == bfd_link_hash_defined
+	   || sym_hash->root.type == bfd_link_hash_defweak)
+	  && sym_hash->root.u.def.section == sec
+	  && sym_hash->root.u.def.value > addr
+	  && sym_hash->root.u.def.value < toaddr)
 	{
-	  (sym_hash)->root.u.def.value -= count;
+	  sym_hash->root.u.def.value -= count;
 	}
     }
 
@@ -1782,8 +1752,7 @@ m32r_elf_get_relocated_section_contents 
   bfd *input_bfd = input_section->owner;
   asection **sections = NULL;
   Elf_Internal_Rela *internal_relocs = NULL;
-  Elf32_External_Sym *external_syms = NULL;
-  Elf_Internal_Sym *internal_syms = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
   bfd_size_type amt;
 
   /* We only need to handle the case of relaxing, or of having a
@@ -1807,31 +1776,22 @@ m32r_elf_get_relocated_section_contents 
       asection **secpp;
       Elf32_External_Sym *esym, *esymend;
 
-      if (symtab_hdr->contents != NULL)
-	external_syms = (Elf32_External_Sym *) symtab_hdr->contents;
-      else
-	{
-	  amt = symtab_hdr->sh_info;
-	  amt *= sizeof (Elf32_External_Sym);
-	  external_syms = (Elf32_External_Sym *) bfd_malloc (amt);
-	  if (external_syms == NULL && symtab_hdr->sh_info > 0)
-	    goto error_return;
-	  if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread (external_syms, amt, input_bfd) != amt)
-	    goto error_return;
-	}
-
       internal_relocs = (_bfd_elf32_link_read_relocs
 			 (input_bfd, input_section, (PTR) NULL,
 			  (Elf_Internal_Rela *) NULL, false));
       if (internal_relocs == NULL)
 	goto error_return;
 
-      amt = symtab_hdr->sh_info;
-      amt *= sizeof (Elf_Internal_Sym);
-      internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt);
-      if (internal_syms == NULL && symtab_hdr->sh_info > 0)
-	goto error_return;
+      if (symtab_hdr->sh_info != 0)
+	{
+	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	  if (isymbuf == NULL)
+	    isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
+					    symtab_hdr->sh_info, 0,
+					    NULL, NULL, NULL);
+	  if (isymbuf == NULL)
+	    goto error_return;
+	}
 
       amt = symtab_hdr->sh_info;
       amt *= sizeof (asection *);
@@ -1839,61 +1799,50 @@ m32r_elf_get_relocated_section_contents 
       if (sections == NULL && symtab_hdr->sh_info > 0)
 	goto error_return;
 
-      isymp = internal_syms;
-      secpp = sections;
-      esym = external_syms;
-      esymend = esym + symtab_hdr->sh_info;
-      for (; esym < esymend; ++esym, ++isymp, ++secpp)
+      isymend = isymbuf + symtab_hdr->sh_info;
+      for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
 	{
 	  asection *isec;
 
-	  bfd_elf32_swap_symbol_in (input_bfd, esym, isymp);
-
-	  if (isymp->st_shndx == SHN_UNDEF)
+	  if (isym->st_shndx == SHN_UNDEF)
 	    isec = bfd_und_section_ptr;
-	  else if (isymp->st_shndx == SHN_ABS)
+	  else if (isym->st_shndx == SHN_ABS)
 	    isec = bfd_abs_section_ptr;
-	  else if (isymp->st_shndx == SHN_COMMON)
+	  else if (isym->st_shndx == SHN_COMMON)
 	    isec = bfd_com_section_ptr;
-	  else if (isymp->st_shndx == SHN_M32R_SCOMMON)
+	  else if (isym->st_shndx == SHN_M32R_SCOMMON)
 	    isec = &m32r_elf_scom_section;
 	  else
-	    isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
+	    isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
 
 	  *secpp = isec;
 	}
 
       if (! m32r_elf_relocate_section (output_bfd, link_info, input_bfd,
 				       input_section, data, internal_relocs,
-				       internal_syms, sections))
+				       isymbuf, sections))
 	goto error_return;
 
       if (sections != NULL)
 	free (sections);
-      sections = NULL;
-      if (internal_syms != NULL)
-	free (internal_syms);
-      internal_syms = NULL;
-      if (external_syms != NULL && symtab_hdr->contents == NULL)
-	free (external_syms);
-      external_syms = NULL;
-      if (internal_relocs != elf_section_data (input_section)->relocs)
+      if (isymbuf != NULL
+	  && symtab_hdr->contents != (unsigned char *) isymbuf)
+	free (isymbuf);
+      if (elf_section_data (input_section)->relocs != internal_relocs)
 	free (internal_relocs);
-      internal_relocs = NULL;
     }
 
   return data;
 
  error_return:
-  if (internal_relocs != NULL
-      && internal_relocs != elf_section_data (input_section)->relocs)
-    free (internal_relocs);
-  if (external_syms != NULL && symtab_hdr->contents == NULL)
-    free (external_syms);
-  if (internal_syms != NULL)
-    free (internal_syms);
   if (sections != NULL)
     free (sections);
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
+  if (internal_relocs != NULL
+      && elf_section_data (input_section)->relocs != internal_relocs)
+    free (internal_relocs);
   return NULL;
 }
 
Index: bfd/elf32-sh.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sh.c,v
retrieving revision 1.51
diff -u -p -r1.51 elf32-sh.c
--- bfd/elf32-sh.c	1 Jul 2002 08:06:44 -0000	1.51
+++ bfd/elf32-sh.c	7 Jul 2002 06:59:09 -0000
@@ -1546,7 +1546,6 @@ sh_elf_reloc_loop (r_type, input_bfd, in
 {
   static bfd_vma last_addr;
   static asection *last_symbol_section;
-  bfd_byte *free_contents = NULL;
   bfd_byte *start_ptr, *ptr, *last_ptr;
   int diff, cum_diff;
   bfd_signed_vma x;
@@ -1581,7 +1580,6 @@ sh_elf_reloc_loop (r_type, input_bfd, in
 	  contents = (bfd_byte *) bfd_malloc (symbol_section->_raw_size);
 	  if (contents == NULL)
 	    return bfd_reloc_outofrange;
-	  free_contents = contents;
 	  if (! bfd_get_section_contents (input_bfd, symbol_section, contents,
 					  (file_ptr) 0,
 					  symbol_section->_raw_size))
@@ -1621,8 +1619,9 @@ sh_elf_reloc_loop (r_type, input_bfd, in
       end = start0;
     }
 
-  if (free_contents)
-    free (free_contents);
+  if (contents != NULL
+      && elf_section_data (symbol_section)->this_hdr.contents != contents)
+    free (contents);
 
   insn = bfd_get_16 (input_bfd, contents + addr);
 
@@ -1888,16 +1887,11 @@ sh_elf_relax_section (abfd, sec, link_in
      boolean *again;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *free_relocs = NULL;
   boolean have_code;
   Elf_Internal_Rela *irel, *irelend;
   bfd_byte *contents = NULL;
-  bfd_byte *free_contents = NULL;
-  Elf32_External_Sym *extsyms = NULL;
-  Elf32_External_Sym *free_extsyms = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
 
   *again = false;
 
@@ -1920,15 +1914,12 @@ sh_elf_relax_section (abfd, sec, link_in
     sec->_cooked_size = sec->_raw_size;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
 
   internal_relocs = (_bfd_elf32_link_read_relocs
 		     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
 		      link_info->keep_memory));
   if (internal_relocs == NULL)
     goto error_return;
-  if (! link_info->keep_memory)
-    free_relocs = internal_relocs;
 
   have_code = false;
 
@@ -1956,7 +1947,6 @@ sh_elf_relax_section (abfd, sec, link_in
 	      contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
 	      if (contents == NULL)
 		goto error_return;
-	      free_contents = contents;
 
 	      if (! bfd_get_section_contents (abfd, sec, contents,
 					      (file_ptr) 0, sec->_raw_size))
@@ -2021,56 +2011,25 @@ sh_elf_relax_section (abfd, sec, link_in
 	}
 
       /* Read this BFD's symbols if we haven't done so already.  */
-      if (extsyms == NULL)
+      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
 	{
-	  if (symtab_hdr->contents != NULL)
-	    extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-	  else
-	    {
-	      bfd_size_type amt;
-
-	      amt = symtab_hdr->sh_info;
-	      amt *= sizeof (Elf32_External_Sym);
-	      extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
-	      if (extsyms == NULL)
-		goto error_return;
-	      free_extsyms = extsyms;
-	      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) extsyms, amt, abfd) != amt)
-		goto error_return;
-	      symtab_hdr->contents = (bfd_byte *) extsyms;
-	    }
-
-	  if (shndx_hdr->sh_size != 0)
-	    {
-	      bfd_size_type amt;
-
-	      amt = symtab_hdr->sh_info;
-	      amt *= sizeof (Elf_External_Sym_Shndx);
-	      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	      if (shndx_buf == NULL)
-		goto error_return;
-	      if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
-		goto error_return;
-	      shndx_hdr->contents = (bfd_byte *) shndx_buf;
-	    }
+	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	  if (isymbuf == NULL)
+	    isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+					    symtab_hdr->sh_info, 0,
+					    NULL, NULL, NULL);
+	  if (isymbuf == NULL)
+	    goto error_return;
 	}
 
       /* Get the value of the symbol referred to by the reloc.  */
       if (ELF32_R_SYM (irelfn->r_info) < symtab_hdr->sh_info)
 	{
 	  /* A local symbol.  */
-	  Elf32_External_Sym *esym;
-	  Elf_External_Sym_Shndx *shndx;
-	  Elf_Internal_Sym isym;
-
-	  esym = extsyms + ELF32_R_SYM (irelfn->r_info);
-	  shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irelfn->r_info) : 0);
-	  bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				    &isym);
+	  Elf_Internal_Sym *isym;
 
-	  if (isym.st_shndx
+	  isym = isymbuf + ELF32_R_SYM (irelfn->r_info);
+	  if (isym->st_shndx
 	      != (unsigned int) _bfd_elf_section_from_bfd_section (abfd, sec))
 	    {
 	      ((*_bfd_error_handler)
@@ -2079,7 +2038,7 @@ sh_elf_relax_section (abfd, sec, link_in
 	      continue;
 	    }
 
-	  symval = (isym.st_value
+	  symval = (isym->st_value
 		    + sec->output_section->vma
 		    + sec->output_offset);
 	}
@@ -2130,12 +2089,8 @@ sh_elf_relax_section (abfd, sec, link_in
 	 the linker is run.  */
 
       elf_section_data (sec)->relocs = internal_relocs;
-      free_relocs = NULL;
-
       elf_section_data (sec)->this_hdr.contents = contents;
-      free_contents = NULL;
-
-      free_extsyms = NULL;
+      symtab_hdr->contents = (unsigned char *) isymbuf;
 
       /* Replace the jsr with a bsr.  */
 
@@ -2240,7 +2195,6 @@ sh_elf_relax_section (abfd, sec, link_in
 	      contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
 	      if (contents == NULL)
 		goto error_return;
-	      free_contents = contents;
 
 	      if (! bfd_get_section_contents (abfd, sec, contents,
 					      (file_ptr) 0, sec->_raw_size))
@@ -2255,61 +2209,51 @@ sh_elf_relax_section (abfd, sec, link_in
       if (swapped)
 	{
 	  elf_section_data (sec)->relocs = internal_relocs;
-	  free_relocs = NULL;
-
 	  elf_section_data (sec)->this_hdr.contents = contents;
-	  free_contents = NULL;
-
-	  free_extsyms = NULL;
+	  symtab_hdr->contents = (unsigned char *) isymbuf;
 	}
     }
 
-  if (free_relocs != NULL)
-    free (free_relocs);
-
-  if (free_contents != NULL)
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
     {
       if (! link_info->keep_memory)
-	free (free_contents);
+	free (isymbuf);
       else
 	{
-	  /* Cache the section contents for elf_link_input_bfd.  */
-	  elf_section_data (sec)->this_hdr.contents = contents;
+	  /* Cache the symbols for elf_link_input_bfd.  */
+	  symtab_hdr->contents = (unsigned char *) isymbuf;
 	}
     }
 
-  if (shndx_buf != NULL)
-    {
-      shndx_hdr->contents = NULL;
-      free (shndx_buf);
-    }
-
-  if (free_extsyms != NULL)
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
     {
       if (! link_info->keep_memory)
+	free (contents);
+      else
 	{
-	  symtab_hdr->contents = NULL;
-	  free (free_extsyms);
+	  /* Cache the section contents for elf_link_input_bfd.  */
+	  elf_section_data (sec)->this_hdr.contents = contents;
 	}
     }
 
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
+
   return true;
 
  error_return:
-  if (free_relocs != NULL)
-    free (free_relocs);
-  if (free_contents != NULL)
-    free (free_contents);
-  if (shndx_buf != NULL)
-    {
-      shndx_hdr->contents = NULL;
-      free (shndx_buf);
-    }
-  if (free_extsyms != NULL)
-    {
-      symtab_hdr->contents = NULL;
-      free (free_extsyms);
-    }
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
+    free (contents);
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
 
   return false;
 }
@@ -2326,25 +2270,19 @@ sh_elf_relax_delete_bytes (abfd, sec, ad
      int count;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
-  Elf32_External_Sym *extsyms;
   unsigned int sec_shndx;
   bfd_byte *contents;
   Elf_Internal_Rela *irel, *irelend;
   Elf_Internal_Rela *irelalign;
   bfd_vma toaddr;
-  Elf32_External_Sym *esym, *esymend;
-  Elf_External_Sym_Shndx *shndx_buf, *shndx;
+  Elf_Internal_Sym *isymbuf, *isym, *isymend;
   struct elf_link_hash_entry **sym_hashes;
   struct elf_link_hash_entry **end_hashes;
   unsigned int symcount;
   asection *o;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-  shndx_buf = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
+  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
 
   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
@@ -2392,7 +2330,6 @@ sh_elf_relax_delete_bytes (abfd, sec, ad
       bfd_vma nraddr, stop;
       bfd_vma start = 0;
       int insn = 0;
-      Elf_Internal_Sym sym;
       int off, adjust, oinsn;
       bfd_signed_vma voff = 0;
       boolean overflow;
@@ -2446,19 +2383,15 @@ sh_elf_relax_delete_bytes (abfd, sec, ad
              range to be adjusted, and hence must be changed.  */
 	  if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
 	    {
-	      esym = extsyms + ELF32_R_SYM (irel->r_info);
-	      shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0);
-	      bfd_elf32_swap_symbol_in (abfd, (const PTR) esym,
-					(const PTR) shndx, &sym);
-
-	      if (sym.st_shndx == sec_shndx
-		  && (sym.st_value <= addr
-		      || sym.st_value >= toaddr))
+	      isym = isymbuf + ELF32_R_SYM (irel->r_info);
+	      if (isym->st_shndx == sec_shndx
+		  && (isym->st_value <= addr
+		      || isym->st_value >= toaddr))
 		{
 		  bfd_vma val;
 
 		  val = bfd_get_32 (abfd, contents + nraddr);
-		  val += sym.st_value;
+		  val += isym->st_value;
 		  if (val > addr && val < toaddr)
 		    bfd_put_32 (abfd, val - count, contents + nraddr);
 		}
@@ -2651,8 +2584,6 @@ sh_elf_relax_delete_bytes (abfd, sec, ad
       irelscanend = internal_relocs + o->reloc_count;
       for (irelscan = internal_relocs; irelscan < irelscanend; irelscan++)
 	{
-	  Elf_Internal_Sym sym;
-
 	  /* Dwarf line numbers use R_SH_SWITCH32 relocs.  */
 	  if (ELF32_R_TYPE (irelscan->r_info) == (int) R_SH_SWITCH32)
 	    {
@@ -2710,14 +2641,10 @@ sh_elf_relax_delete_bytes (abfd, sec, ad
 	    continue;
 
 
-	  esym = extsyms + ELF32_R_SYM (irelscan->r_info);
-	  shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irelscan->r_info) : 0);
-	  bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				    &sym);
-
-	  if (sym.st_shndx == sec_shndx
-	      && (sym.st_value <= addr
-		  || sym.st_value >= toaddr))
+	  isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
+	  if (isym->st_shndx == sec_shndx
+	      && (isym->st_value <= addr
+		  || isym->st_value >= toaddr))
 	    {
 	      bfd_vma val;
 
@@ -2743,7 +2670,7 @@ sh_elf_relax_delete_bytes (abfd, sec, ad
 		}
 
 	      val = bfd_get_32 (abfd, ocontents + irelscan->r_offset);
-	      val += sym.st_value;
+	      val += isym->st_value;
 	      if (val > addr && val < toaddr)
 		bfd_put_32 (abfd, val - count,
 			    ocontents + irelscan->r_offset);
@@ -2752,24 +2679,13 @@ sh_elf_relax_delete_bytes (abfd, sec, ad
     }
 
   /* Adjust the local symbols defined in this section.  */
-  shndx = shndx_buf;
-  esym = extsyms;
-  esymend = esym + symtab_hdr->sh_info;
-  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
-    {
-      Elf_Internal_Sym isym;
-      Elf_External_Sym_Shndx dummy;
-
-      bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				&isym);
-
-      if (isym.st_shndx == sec_shndx
-	  && isym.st_value > addr
-	  && isym.st_value < toaddr)
-	{
-	  isym.st_value -= count;
-	  bfd_elf32_swap_symbol_out (abfd, &isym, (PTR) esym, (PTR) &dummy);
-	}
+  isymend = isymbuf + symtab_hdr->sh_info;
+  for (isym = isymbuf; isym < isymend; isym++)
+    {
+      if (isym->st_shndx == sec_shndx
+	  && isym->st_value > addr
+	  && isym->st_value < toaddr)
+	isym->st_value -= count;
     }
 
   /* Now adjust the global symbols defined in this section.  */
@@ -4844,15 +4760,11 @@ sh_elf_get_relocated_section_contents (o
      asymbol **symbols;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   asection *input_section = link_order->u.indirect.section;
   bfd *input_bfd = input_section->owner;
   asection **sections = NULL;
   Elf_Internal_Rela *internal_relocs = NULL;
-  Elf32_External_Sym *external_syms = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
-  Elf_External_Sym_Shndx *shndx;
-  Elf_Internal_Sym *internal_syms = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
 
   /* We only need to handle the case of relaxing, or of having a
      particular set of section contents, specially.  */
@@ -4864,7 +4776,6 @@ sh_elf_get_relocated_section_contents (o
 						       symbols);
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
-  shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr;
 
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
 	  (size_t) input_section->_raw_size);
@@ -4872,48 +4783,26 @@ sh_elf_get_relocated_section_contents (o
   if ((input_section->flags & SEC_RELOC) != 0
       && input_section->reloc_count > 0)
     {
-      Elf_Internal_Sym *isymp;
       asection **secpp;
-      Elf32_External_Sym *esym, *esymend;
+      Elf_Internal_Sym *isym, *isymend;
       bfd_size_type amt;
 
-      if (symtab_hdr->contents != NULL)
-	external_syms = (Elf32_External_Sym *) symtab_hdr->contents;
-      else if (symtab_hdr->sh_info != 0)
-	{
-	  amt = symtab_hdr->sh_info;
-	  amt *= sizeof (Elf32_External_Sym);
-	  external_syms = (Elf32_External_Sym *) bfd_malloc (amt);
-	  if (external_syms == NULL)
-	    goto error_return;
-	  if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread ((PTR) external_syms, amt, input_bfd) != amt)
-	    goto error_return;
-	}
-
-      if (symtab_hdr->sh_info != 0 && shndx_hdr->sh_size != 0)
-	{
-	  amt = symtab_hdr->sh_info;
-	  amt *= sizeof (Elf_External_Sym_Shndx);
-	  shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	  if (shndx_buf == NULL)
-	    goto error_return;
-	  if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread ((PTR) shndx_buf, amt, input_bfd) != amt)
-	    goto error_return;
-	}
-
       internal_relocs = (_bfd_elf32_link_read_relocs
 			 (input_bfd, input_section, (PTR) NULL,
 			  (Elf_Internal_Rela *) NULL, false));
       if (internal_relocs == NULL)
 	goto error_return;
 
-      amt = symtab_hdr->sh_info;
-      amt *= sizeof (Elf_Internal_Sym);
-      internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt);
-      if (internal_syms == NULL && amt != 0)
-	goto error_return;
+      if (symtab_hdr->sh_info != 0)
+	{
+	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	  if (isymbuf == NULL)
+	    isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
+					    symtab_hdr->sh_info, 0,
+					    NULL, NULL, NULL);
+	  if (isymbuf == NULL)
+	    goto error_return;
+	}
 
       amt = symtab_hdr->sh_info;
       amt *= sizeof (asection *);
@@ -4921,59 +4810,48 @@ sh_elf_get_relocated_section_contents (o
       if (sections == NULL && amt != 0)
 	goto error_return;
 
-      for (isymp = internal_syms, secpp = sections, shndx = shndx_buf,
-	     esym = external_syms, esymend = esym + symtab_hdr->sh_info;
-	   esym < esymend;
-	   ++esym, ++isymp, ++secpp, shndx = (shndx ? shndx + 1 : NULL))
+      isymend = isymbuf + symtab_hdr->sh_info;
+      for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
 	{
 	  asection *isec;
 
-	  bfd_elf32_swap_symbol_in (input_bfd, (const PTR) esym,
-				    (const PTR) shndx, isymp);
-
-	  if (isymp->st_shndx == SHN_UNDEF)
+	  if (isym->st_shndx == SHN_UNDEF)
 	    isec = bfd_und_section_ptr;
-	  else if (isymp->st_shndx == SHN_ABS)
+	  else if (isym->st_shndx == SHN_ABS)
 	    isec = bfd_abs_section_ptr;
-	  else if (isymp->st_shndx == SHN_COMMON)
+	  else if (isym->st_shndx == SHN_COMMON)
 	    isec = bfd_com_section_ptr;
 	  else
-	    isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
+	    isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
 
 	  *secpp = isec;
 	}
 
       if (! sh_elf_relocate_section (output_bfd, link_info, input_bfd,
 				     input_section, data, internal_relocs,
-				     internal_syms, sections))
+				     isymbuf, sections))
 	goto error_return;
 
       if (sections != NULL)
 	free (sections);
-      if (internal_syms != NULL)
-	free (internal_syms);
-      if (shndx_buf != NULL)
-	free (shndx_buf);
-      if (external_syms != NULL && symtab_hdr->contents == NULL)
-	free (external_syms);
-      if (internal_relocs != elf_section_data (input_section)->relocs)
+      if (isymbuf != NULL
+	  && symtab_hdr->contents != (unsigned char *) isymbuf)
+	free (isymbuf);
+      if (elf_section_data (input_section)->relocs != internal_relocs)
 	free (internal_relocs);
     }
 
   return data;
 
  error_return:
-  if (internal_relocs != NULL
-      && internal_relocs != elf_section_data (input_section)->relocs)
-    free (internal_relocs);
-  if (shndx_buf != NULL)
-    free (shndx_buf);
-  if (external_syms != NULL && symtab_hdr->contents == NULL)
-    free (external_syms);
-  if (internal_syms != NULL)
-    free (internal_syms);
   if (sections != NULL)
     free (sections);
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
+  if (internal_relocs != NULL
+      && elf_section_data (input_section)->relocs != internal_relocs)
+    free (internal_relocs);
   return NULL;
 }
 
Index: bfd/elf32-xstormy16.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-xstormy16.c,v
retrieving revision 1.9
diff -u -p -r1.9 elf32-xstormy16.c
--- bfd/elf32-xstormy16.c	1 Jul 2002 08:06:45 -0000	1.9
+++ bfd/elf32-xstormy16.c	7 Jul 2002 06:59:11 -0000
@@ -586,88 +586,51 @@ xstormy16_elf_relax_section (dynobj, spl
 			  &relax_plt_data);
 
   /* Likewise for local symbols, though that's somewhat less convenient
-     as we have walk the list of input bfds and swap in symbol data.  */
+     as we have to walk the list of input bfds and swap in symbol data.  */
   for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
     {
       bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
       Elf_Internal_Shdr *symtab_hdr;
-      Elf_Internal_Shdr *shndx_hdr;
-      Elf32_External_Sym *extsyms;
-      Elf_External_Sym_Shndx *shndx_buf;
+      Elf_Internal_Sym *isymbuf = NULL;
       unsigned int idx;
 
       if (! local_plt_offsets)
 	continue;
 
       symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
-      shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr;
-
-      if (symtab_hdr->contents != NULL)
-	extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-      else
+      if (symtab_hdr->sh_info != 0)
 	{
-	  bfd_size_type amt;
-
-	  amt = symtab_hdr->sh_info;
-	  amt *= sizeof (Elf32_External_Sym);
-	  extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
-	  if (extsyms == NULL)
+	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	  if (isymbuf == NULL)
+	    isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
+					    symtab_hdr->sh_info, 0,
+					    NULL, NULL, NULL);
+	  if (isymbuf == NULL)
 	    return false;
-	  if (bfd_seek (ibfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread ((PTR) extsyms, amt, ibfd) != amt)
-	    {
-	    error_ret_free_extsyms:
-	      free (extsyms);
-	      return false;
-	    }
-	}
-
-      shndx_buf = NULL;
-      if (shndx_hdr->sh_size != 0)
-	{
-	  bfd_size_type amt;
-
-	  amt = symtab_hdr->sh_info;
-	  amt *= sizeof (Elf_External_Sym_Shndx);
-	  shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	  if (shndx_buf == NULL)
-	    goto error_ret_free_extsyms;
-	  if (bfd_seek (ibfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread ((PTR) shndx_buf, amt, ibfd) != amt)
-	    {
-	      free (shndx_buf);
-	      goto error_ret_free_extsyms;
-	    }
-	  shndx_hdr->contents = (bfd_byte *) shndx_buf;
 	}
 
       for (idx = 0; idx < symtab_hdr->sh_info; ++idx)
 	{
-	  Elf_External_Sym_Shndx *shndx;
-	  Elf_Internal_Sym isym;
+	  Elf_Internal_Sym *isym;
 	  asection *tsec;
 	  bfd_vma address;
 
 	  if (local_plt_offsets[idx] == (bfd_vma) -1)
 	    continue;
 
-	  shndx = shndx_buf;
-	  if (shndx != NULL)
-	    shndx += idx;
-	  bfd_elf32_swap_symbol_in (ibfd, (const PTR) (extsyms + idx),
-				    (const PTR) shndx, &isym);
-	  if (isym.st_shndx == SHN_UNDEF)
+	  isym = &isymbuf[idx];
+	  if (isym->st_shndx == SHN_UNDEF)
 	    continue;
-	  else if (isym.st_shndx == SHN_ABS)
+	  else if (isym->st_shndx == SHN_ABS)
 	    tsec = bfd_abs_section_ptr;
-	  else if (isym.st_shndx == SHN_COMMON)
+	  else if (isym->st_shndx == SHN_COMMON)
 	    tsec = bfd_com_section_ptr;
 	  else
-	    tsec = bfd_section_from_elf_index (ibfd, isym.st_shndx);
+	    tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx);
 
 	  address = (tsec->output_section->vma
 		     + tsec->output_offset
-		     + isym.st_value);
+		     + isym->st_value);
 	  if (address <= 0xffff)
 	    {
 	      local_plt_offsets[idx] = -1;
@@ -676,11 +639,17 @@ xstormy16_elf_relax_section (dynobj, spl
 	    }
 	}
 
-      if (shndx_buf != NULL)
-	free (shndx_buf);
-
-      if ((Elf32_External_Sym *) symtab_hdr->contents != extsyms)
-        free (extsyms);
+      if (isymbuf != NULL
+	  && symtab_hdr->contents != (unsigned char *) isymbuf)
+	{
+	  if (! info->keep_memory)
+	    free (isymbuf);
+	  else
+	    {
+	      /* Cache the symbols for elf_link_input_bfd.  */
+	      symtab_hdr->contents = (unsigned char *) isymbuf;
+	    }
+	}
     }
 
   /* If we changed anything, walk the symbols again to reallocate
Index: bfd/elf64-alpha.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-alpha.c,v
retrieving revision 1.76
diff -u -p -r1.76 elf64-alpha.c
--- bfd/elf64-alpha.c	25 Jun 2002 06:21:53 -0000	1.76
+++ bfd/elf64-alpha.c	7 Jul 2002 08:02:46 -0000
@@ -2037,14 +2037,9 @@ elf64_alpha_relax_section (abfd, sec, li
      boolean *again;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *free_relocs = NULL;
   Elf_Internal_Rela *irel, *irelend;
-  bfd_byte *free_contents = NULL;
-  Elf64_External_Sym *extsyms;
-  Elf64_External_Sym *free_extsyms = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
   struct alpha_elf_got_entry **local_got_entries;
   struct alpha_relax_info info;
   struct elf_link_tls_segment tls_segment;
@@ -2070,9 +2065,7 @@ elf64_alpha_relax_section (abfd, sec, li
 		     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
 		      link_info->keep_memory));
   if (internal_relocs == NULL)
-    goto error_return;
-  if (! link_info->keep_memory)
-    free_relocs = internal_relocs;
+    return false;
 
   memset(&info, 0, sizeof (info));
   info.abfd = abfd;
@@ -2101,41 +2094,12 @@ elf64_alpha_relax_section (abfd, sec, li
       info.contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
       if (info.contents == NULL)
 	goto error_return;
-      free_contents = info.contents;
 
       if (! bfd_get_section_contents (abfd, sec, info.contents,
 				      (file_ptr) 0, sec->_raw_size))
 	goto error_return;
     }
 
-  /* Read this BFD's symbols.  */
-  if (symtab_hdr->contents != NULL)
-    extsyms = (Elf64_External_Sym *) symtab_hdr->contents;
-  else
-    {
-      bfd_size_type amt = symtab_hdr->sh_info * sizeof (Elf64_External_Sym);
-      extsyms = (Elf64_External_Sym *) bfd_malloc (amt);
-      if (extsyms == NULL)
-	goto error_return;
-      free_extsyms = extsyms;
-      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	  || bfd_bread ((PTR) extsyms, amt, abfd) != amt)
-	goto error_return;
-    }
-
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-  if (shndx_hdr->sh_size != 0)
-    {
-      bfd_size_type amt;
-      amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx);
-      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-      if (shndx_buf == NULL)
-	goto error_return;
-      if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	  || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
-	goto error_return;
-    }
-
   /* Compute the TLS segment information.  The version normally found in
      elf_hash_table (link_info)->tls_segment isn't built until final_link.
      ??? Probably should look into extracting this into a common function.  */
@@ -2144,7 +2108,6 @@ elf64_alpha_relax_section (abfd, sec, li
   for (irel = internal_relocs; irel < irelend; irel++)
     {
       bfd_vma symval;
-      Elf_Internal_Sym isym;
       struct alpha_elf_got_entry *gotent;
       unsigned long r_type = ELF64_R_TYPE (irel->r_info);
 
@@ -2167,26 +2130,34 @@ elf64_alpha_relax_section (abfd, sec, li
       if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
 	{
 	  /* A local symbol.  */
-	  Elf64_External_Sym *esym;
-	  Elf_External_Sym_Shndx *shndx;
+	  Elf_Internal_Sym *isym;
 
-	  esym = extsyms + ELF64_R_SYM (irel->r_info);
-	  shndx = shndx_buf + (shndx_buf ? ELF64_R_SYM (irel->r_info) : 0);
-	  bfd_elf64_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				    &isym);
-	  if (isym.st_shndx == SHN_UNDEF)
+	  /* Read this BFD's local symbols.  */
+	  if (isymbuf == NULL)
+	    {
+	      isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	      if (isymbuf == NULL)
+		isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+						symtab_hdr->sh_info, 0,
+						NULL, NULL, NULL);
+	      if (isymbuf == NULL)
+		goto error_return;
+	    }
+
+	  isym = isymbuf + ELF64_R_SYM (irel->r_info);
+	  if (isym->st_shndx == SHN_UNDEF)
 	    continue;
-	  else if (isym.st_shndx == SHN_ABS)
+	  else if (isym->st_shndx == SHN_ABS)
 	    info.tsec = bfd_abs_section_ptr;
-	  else if (isym.st_shndx == SHN_COMMON)
+	  else if (isym->st_shndx == SHN_COMMON)
 	    info.tsec = bfd_com_section_ptr;
 	  else
-	    info.tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
+	    info.tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
 
 	  info.h = NULL;
-	  info.other = isym.st_other;
+	  info.other = isym->st_other;
 	  info.first_gotent = &local_got_entries[ELF64_R_SYM(irel->r_info)];
-	  symval = isym.st_value;
+	  symval = isym->st_value;
 	}
       else
 	{
@@ -2281,51 +2252,52 @@ elf64_alpha_relax_section (abfd, sec, li
   if (!elf64_alpha_size_rela_got_section (link_info))
     return false;
 
-  if (info.changed_relocs)
-    elf_section_data (sec)->relocs = internal_relocs;
-  else if (free_relocs != NULL)
-    free (free_relocs);
-
-  if (info.changed_contents)
-    elf_section_data (sec)->this_hdr.contents = info.contents;
-  else if (free_contents != NULL)
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
     {
-      if (! link_info->keep_memory)
-	free (free_contents);
+      if (!link_info->keep_memory)
+	free (isymbuf);
       else
 	{
-	  /* Cache the section contents for elf_link_input_bfd.  */
-	  elf_section_data (sec)->this_hdr.contents = info.contents;
+	  /* Cache the symbols for elf_link_input_bfd.  */
+	  symtab_hdr->contents = (unsigned char *) isymbuf;
 	}
     }
 
-  if (shndx_buf != NULL)
-    free (shndx_buf);
-
-  if (free_extsyms != NULL)
+  if (info.contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != info.contents)
     {
-      if (! link_info->keep_memory)
-	free (free_extsyms);
+      if (!info.changed_contents && !link_info->keep_memory)
+	free (info.contents);
       else
 	{
-	  /* Cache the symbols for elf_link_input_bfd.  */
-	  symtab_hdr->contents = (unsigned char *) extsyms;
+	  /* Cache the section contents for elf_link_input_bfd.  */
+	  elf_section_data (sec)->this_hdr.contents = info.contents;
 	}
     }
 
+  if (elf_section_data (sec)->relocs != internal_relocs)
+    {
+      if (!info.changed_relocs)
+	free (internal_relocs);
+      else
+	elf_section_data (sec)->relocs = internal_relocs;
+    }
+
   *again = info.changed_contents || info.changed_relocs;
 
   return true;
 
  error_return:
-  if (free_relocs != NULL)
-    free (free_relocs);
-  if (free_contents != NULL)
-    free (free_contents);
-  if (shndx_buf != NULL)
-    free (shndx_buf);
-  if (free_extsyms != NULL)
-    free (free_extsyms);
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
+  if (info.contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != info.contents)
+    free (info.contents);
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
   return false;
 }
 
Index: bfd/elf64-mmix.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-mmix.c,v
retrieving revision 1.16
diff -u -p -r1.16 elf64-mmix.c
--- bfd/elf64-mmix.c	1 Jul 2002 08:06:45 -0000	1.16
+++ bfd/elf64-mmix.c	7 Jul 2002 06:59:17 -0000
@@ -2305,9 +2305,7 @@ mmix_elf_relax_section (abfd, sec, link_
      boolean *again;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *free_relocs = NULL;
   Elf_Internal_Rela *irel, *irelend;
   asection *bpo_gregs_section = NULL;
   struct bpo_greg_section_info *gregdata;
@@ -2316,9 +2314,7 @@ mmix_elf_relax_section (abfd, sec, link_
     elf_section_data (sec)->tdata;
   size_t bpono;
   bfd *bpo_greg_owner;
-  Elf64_External_Sym *extsyms = NULL;
-  Elf64_External_Sym *free_extsyms = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
 
   /* Assume nothing changes.  */
   *again = false;
@@ -2341,7 +2337,6 @@ mmix_elf_relax_section (abfd, sec, link_
     return true;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
 
   bpo_greg_owner = (bfd *) link_info->base_file;
   bpo_gregs_section = bpodata->bpo_greg_section;
@@ -2357,8 +2352,6 @@ mmix_elf_relax_section (abfd, sec, link_
 				   link_info->keep_memory);
   if (internal_relocs == NULL)
     goto error_return;
-  if (! link_info->keep_memory)
-    free_relocs = internal_relocs;
 
   /* Walk through them looking for relaxing opportunities.  */
   irelend = internal_relocs + sec->reloc_count;
@@ -2369,70 +2362,35 @@ mmix_elf_relax_section (abfd, sec, link_
       if (ELF64_R_TYPE (irel->r_info) != (int) R_MMIX_BASE_PLUS_OFFSET)
 	continue;
 
-      /* Read this BFD's symbols if we haven't done so already.  */
-      if (extsyms == NULL)
-	{
-	  /* Get cached copy if it exists.  */
-	  if (symtab_hdr->contents != NULL)
-	    extsyms = (Elf64_External_Sym *) symtab_hdr->contents;
-	  else
-	    {
-	      /* Go get them off disk.  */
-	      bfd_size_type amt;
-
-	      amt = symtab_hdr->sh_info;
-	      amt *= sizeof (Elf64_External_Sym);
-	      extsyms = (Elf64_External_Sym *) bfd_malloc (amt);
-	      if (extsyms == NULL)
-		goto error_return;
-	      free_extsyms = extsyms;
-	      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) extsyms, amt, abfd) != amt)
-		goto error_return;
-	      symtab_hdr->contents = (bfd_byte *) extsyms;
-	    }
-
-	  /* If >64k sections, this presumable happens.  No test-case.  */
-	  if (shndx_hdr->sh_size != 0)
-	    {
-	      bfd_size_type amt;
-
-	      amt = symtab_hdr->sh_info;
-	      amt *= sizeof (Elf_External_Sym_Shndx);
-	      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	      if (shndx_buf == NULL)
-		goto error_return;
-	      if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-		  || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
-		goto error_return;
-	      shndx_hdr->contents = (bfd_byte *) shndx_buf;
-	    }
-	}
-
       /* Get the value of the symbol referred to by the reloc.  */
       if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
 	{
 	  /* A local symbol.  */
-	  Elf64_External_Sym *esym;
-	  Elf_External_Sym_Shndx *shndx;
-	  Elf_Internal_Sym isym;
+	  Elf_Internal_Sym *isym;
 	  asection *sym_sec;
 
-	  esym = extsyms + ELF64_R_SYM (irel->r_info);
-	  shndx = shndx_buf + (shndx_buf
-			       ? ELF64_R_SYM (irel->r_info) : 0);
-	  bfd_elf64_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				    &isym);
+	  /* Read this BFD's local symbols if we haven't already.  */
+	  if (isymbuf == NULL)
+	    {
+	      isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	      if (isymbuf == NULL)
+		isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+						symtab_hdr->sh_info, 0,
+						NULL, NULL, NULL);
+	      if (isymbuf == 0)
+		goto error_return;
+	    }
 
-	  if (isym.st_shndx == SHN_UNDEF)
+	  isym = isymbuf + ELF64_R_SYM (irel->r_info);
+	  if (isym->st_shndx == SHN_UNDEF)
 	    sym_sec = bfd_und_section_ptr;
-	  else if (isym.st_shndx == SHN_ABS)
+	  else if (isym->st_shndx == SHN_ABS)
 	    sym_sec = bfd_abs_section_ptr;
-	  else if (isym.st_shndx == SHN_COMMON)
+	  else if (isym->st_shndx == SHN_COMMON)
 	    sym_sec = bfd_com_section_ptr;
 	  else
-	    sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);
-	  symval = (isym.st_value
+	    sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+	  symval = (isym->st_value
 		    + sym_sec->output_section->vma
 		    + sym_sec->output_offset);
 	}
@@ -2529,40 +2487,29 @@ mmix_elf_relax_section (abfd, sec, link_
       bpo_gregs_section->_cooked_size = (regindex + 1) * 8;
     }
 
-  if (free_relocs != NULL)
-    free (free_relocs);
-
-  if (shndx_buf != NULL)
-    {
-      shndx_hdr->contents = NULL;
-      free (shndx_buf);
-    }
-
-  if (free_extsyms != NULL)
+  if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents)
     {
       if (! link_info->keep_memory)
+	free (isymbuf);
+      else
 	{
-	  symtab_hdr->contents = NULL;
-	  free (free_extsyms);
+	  /* Cache the symbols for elf_link_input_bfd.  */
+	  symtab_hdr->contents = (unsigned char *) isymbuf;
 	}
     }
 
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
+
   return true;
 
  error_return:
-  if (free_relocs != NULL)
-    free (free_relocs);
-  if (shndx_buf != NULL)
-    {
-      shndx_hdr->contents = NULL;
-      free (shndx_buf);
-    }
-  if (free_extsyms != NULL)
-    {
-      symtab_hdr->contents = NULL;
-      free (free_extsyms);
-    }
-
+  if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents)
+    free (isymbuf);
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
   return false;
 }
 
Index: bfd/elf64-sh64.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-sh64.c,v
retrieving revision 1.14
diff -u -p -r1.14 elf64-sh64.c
--- bfd/elf64-sh64.c	1 Jul 2002 08:06:45 -0000	1.14
+++ bfd/elf64-sh64.c	7 Jul 2002 06:59:20 -0000
@@ -2144,15 +2144,11 @@ sh_elf64_get_relocated_section_contents 
      asymbol **symbols;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   asection *input_section = link_order->u.indirect.section;
   bfd *input_bfd = input_section->owner;
   asection **sections = NULL;
   Elf_Internal_Rela *internal_relocs = NULL;
-  Elf64_External_Sym *external_syms = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
-  Elf_External_Sym_Shndx *shndx;
-  Elf_Internal_Sym *internal_syms = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
 
   /* We only need to handle the case of relaxing, or of having a
      particular set of section contents, specially.  */
@@ -2164,7 +2160,6 @@ sh_elf64_get_relocated_section_contents 
 						       symbols);
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
-  shndx_hdr  = &elf_tdata (input_bfd)->symtab_shndx_hdr;
 
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
 	  input_section->_raw_size);
@@ -2173,37 +2168,18 @@ sh_elf64_get_relocated_section_contents 
       && input_section->reloc_count > 0)
     {
       Elf_Internal_Sym *isymp;
+      Elf_Internal_Sym *isymend;
       asection **secpp;
-      Elf64_External_Sym *esym, *esymend;
-      bfd_size_type amt;
 
-      if (symtab_hdr->contents != NULL)
-	external_syms = (Elf64_External_Sym *) symtab_hdr->contents;
-      else
+      /* Read this BFD's local symbols.  */
+      if (symtab_hdr->sh_info != 0)
 	{
-	  amt = symtab_hdr->sh_info;
-	  amt *= sizeof (Elf64_External_Sym);
-
-	  external_syms = (Elf64_External_Sym *) bfd_malloc (amt);
-	  if (external_syms == NULL && symtab_hdr->sh_info > 0)
-	    goto error_return;
-
-	  if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	      || (bfd_bread ((PTR) external_syms, amt, input_bfd) != amt))
-	    goto error_return;
-	}
-
-      if (symtab_hdr->sh_info != 0 && shndx_hdr->sh_size != 0)
-	{
-	  amt = symtab_hdr->sh_info;
-	  amt *= sizeof (Elf_External_Sym_Shndx);
-
-	  shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	  if (shndx_buf == NULL)
-	    goto error_return;
-
-	  if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread ((PTR) shndx_buf, amt, input_bfd) != amt)
+	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	  if (isymbuf == NULL)
+	    isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
+					    symtab_hdr->sh_info, 0,
+					    NULL, NULL, NULL);
+	  if (isymbuf == NULL)
 	    goto error_return;
 	}
 
@@ -2213,30 +2189,17 @@ sh_elf64_get_relocated_section_contents 
       if (internal_relocs == NULL)
 	goto error_return;
 
-      internal_syms = ((Elf_Internal_Sym *)
-		       bfd_malloc (symtab_hdr->sh_info
-				   * sizeof (Elf_Internal_Sym)));
-      if (internal_syms == NULL && symtab_hdr->sh_info > 0)
-	goto error_return;
-
       sections = (asection **) bfd_malloc (symtab_hdr->sh_info
 					   * sizeof (asection *));
       if (sections == NULL && symtab_hdr->sh_info > 0)
 	goto error_return;
 
-      isymp = internal_syms;
       secpp = sections;
-      esym = external_syms;
-      esymend = esym + symtab_hdr->sh_info;
-      shndx = shndx_buf;
-      for (; esym < esymend;
-	   ++esym, ++isymp, ++secpp, shndx = (shndx ? shndx + 1 : NULL))
+      isymend = isymbuf + symtab_hdr->sh_info;
+      for (isymp = isymbuf; isymp < isymend; ++isymp, ++secpp)
 	{
 	  asection *isec;
 
-	  bfd_elf64_swap_symbol_in (input_bfd, (const PTR) esym,
-				    (const PTR) shndx, isymp);
-
 	  if (isymp->st_shndx == SHN_UNDEF)
 	    isec = bfd_und_section_ptr;
 	  else if (isymp->st_shndx > 0 && isymp->st_shndx < SHN_LORESERVE)
@@ -2256,35 +2219,29 @@ sh_elf64_get_relocated_section_contents 
 
       if (! sh_elf64_relocate_section (output_bfd, link_info, input_bfd,
 				       input_section, data, internal_relocs,
-				       internal_syms, sections))
+				       isymbuf, sections))
 	goto error_return;
 
       if (sections != NULL)
 	free (sections);
-      sections = NULL;
-      if (internal_syms != NULL)
-	free (internal_syms);
-      internal_syms = NULL;
-      if (external_syms != NULL && symtab_hdr->contents == NULL)
-	free (external_syms);
-      external_syms = NULL;
       if (internal_relocs != elf_section_data (input_section)->relocs)
 	free (internal_relocs);
-      internal_relocs = NULL;
+      if (isymbuf != NULL
+	  && (unsigned char *) isymbuf != symtab_hdr->contents)
+	free (isymbuf);
     }
 
   return data;
 
  error_return:
+  if (sections != NULL)
+    free (sections);
   if (internal_relocs != NULL
       && internal_relocs != elf_section_data (input_section)->relocs)
     free (internal_relocs);
-  if (external_syms != NULL && symtab_hdr->contents == NULL)
-    free (external_syms);
-  if (internal_syms != NULL)
-    free (internal_syms);
-  if (sections != NULL)
-    free (sections);
+  if (isymbuf != NULL
+      && (unsigned char *) isymbuf != symtab_hdr->contents)
+    free (isymbuf);
   return NULL;
 }
 
Index: bfd/elfxx-ia64.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-ia64.c,v
retrieving revision 1.51
diff -u -p -r1.51 elfxx-ia64.c
--- bfd/elfxx-ia64.c	6 Jun 2002 00:29:22 -0000	1.51
+++ bfd/elfxx-ia64.c	7 Jul 2002 08:17:07 -0000
@@ -691,15 +691,10 @@ elfNN_ia64_relax_section (abfd, sec, lin
     };
 
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *free_relocs = NULL;
   Elf_Internal_Rela *irel, *irelend;
   bfd_byte *contents;
-  bfd_byte *free_contents = NULL;
-  ElfNN_External_Sym *extsyms;
-  ElfNN_External_Sym *free_extsyms = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
   struct elfNN_ia64_link_hash_table *ia64_info;
   struct one_fixup *fixups = NULL;
   boolean changed_contents = false;
@@ -726,10 +721,7 @@ elfNN_ia64_relax_section (abfd, sec, lin
 		     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
 		      link_info->keep_memory));
   if (internal_relocs == NULL)
-    goto error_return;
-
-  if (! link_info->keep_memory)
-    free_relocs = internal_relocs;
+    return false;
 
   ia64_info = elfNN_ia64_hash_table (link_info);
   irelend = internal_relocs + sec->reloc_count;
@@ -741,8 +733,8 @@ elfNN_ia64_relax_section (abfd, sec, lin
   /* No branch-type relocations.  */
   if (irel == irelend)
     {
-      if (free_relocs != NULL)
-	free (free_relocs);
+      if (elf_section_data (sec)->relocs != internal_relocs)
+	free (internal_relocs);
       return true;
     }
 
@@ -754,48 +746,15 @@ elfNN_ia64_relax_section (abfd, sec, lin
       contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
       if (contents == NULL)
 	goto error_return;
-      free_contents = contents;
 
       if (! bfd_get_section_contents (abfd, sec, contents,
 				      (file_ptr) 0, sec->_raw_size))
 	goto error_return;
     }
 
-  /* Read this BFD's local symbols.  */
-  if (symtab_hdr->contents != NULL)
-    extsyms = (ElfNN_External_Sym *) symtab_hdr->contents;
-  else
-    {
-      bfd_size_type amt;
-
-      amt = symtab_hdr->sh_info * sizeof (ElfNN_External_Sym);
-      extsyms = (ElfNN_External_Sym *) bfd_malloc (amt);
-      if (extsyms == NULL)
-	goto error_return;
-      free_extsyms = extsyms;
-      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	  || bfd_bread (extsyms, amt, abfd) != amt)
-	goto error_return;
-    }
-
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-  if (shndx_hdr->sh_size != 0)
-    {
-      bfd_size_type amt;
-
-      amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx);
-      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-      if (shndx_buf == NULL)
-	goto error_return;
-      if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	  || bfd_bread (shndx_buf, amt, abfd) != amt)
-	goto error_return;
-    }
-
   for (; irel < irelend; irel++)
     {
       bfd_vma symaddr, reladdr, trampoff, toff, roff;
-      Elf_Internal_Sym isym;
       asection *tsec;
       struct one_fixup *f;
       bfd_size_type amt;
@@ -806,26 +765,34 @@ elfNN_ia64_relax_section (abfd, sec, lin
       /* Get the value of the symbol referred to by the reloc.  */
       if (ELFNN_R_SYM (irel->r_info) < symtab_hdr->sh_info)
 	{
-	  ElfNN_External_Sym *esym;
-	  Elf_External_Sym_Shndx *shndx;
-
 	  /* A local symbol.  */
-	  esym = extsyms + ELFNN_R_SYM (irel->r_info);
-	  shndx = shndx_buf + (shndx_buf ? ELFNN_R_SYM (irel->r_info) : 0);
-	  bfd_elfNN_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				    &isym);
-	  if (isym.st_shndx == SHN_UNDEF)
+	  Elf_Internal_Sym *isym;
+
+	  /* Read this BFD's local symbols.  */
+	  if (isymbuf == NULL)
+	    {
+	      isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	      if (isymbuf == NULL)
+		isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+						symtab_hdr->sh_info, 0,
+						NULL, NULL, NULL);
+	      if (isymbuf == 0)
+		goto error_return;
+	    }
+
+	  isym = isymbuf + ELF64_R_SYM (irel->r_info);
+	  if (isym->st_shndx == SHN_UNDEF)
 	    continue;	/* We can't do anthing with undefined symbols.  */
-	  else if (isym.st_shndx == SHN_ABS)
+	  else if (isym->st_shndx == SHN_ABS)
 	    tsec = bfd_abs_section_ptr;
-	  else if (isym.st_shndx == SHN_COMMON)
+	  else if (isym->st_shndx == SHN_COMMON)
 	    tsec = bfd_com_section_ptr;
-	  else if (isym.st_shndx == SHN_IA_64_ANSI_COMMON)
+	  else if (isym->st_shndx == SHN_IA_64_ANSI_COMMON)
 	    tsec = bfd_com_section_ptr;
 	  else
-	    tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
+	    tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
 
-	  toff = isym.st_value;
+	  toff = isym->st_value;
 	}
       else
 	{
@@ -973,50 +940,50 @@ elfNN_ia64_relax_section (abfd, sec, lin
       free (f);
     }
 
-  if (changed_relocs)
-    elf_section_data (sec)->relocs = internal_relocs;
-  else if (free_relocs != NULL)
-    free (free_relocs);
-
-  if (changed_contents)
-    elf_section_data (sec)->this_hdr.contents = contents;
-  else if (free_contents != NULL)
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
     {
       if (! link_info->keep_memory)
-	free (free_contents);
+	free (isymbuf);
       else
 	{
-	  /* Cache the section contents for elf_link_input_bfd.  */
-	  elf_section_data (sec)->this_hdr.contents = contents;
+	  /* Cache the symbols for elf_link_input_bfd.  */
+	  symtab_hdr->contents = (unsigned char *) isymbuf;
 	}
     }
 
-  if (shndx_buf != NULL)
-    free (shndx_buf);
-
-  if (free_extsyms != NULL)
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
     {
-      if (! link_info->keep_memory)
-	free (free_extsyms);
+      if (!changed_contents && !link_info->keep_memory)
+	free (contents);
       else
 	{
-	  /* Cache the symbols for elf_link_input_bfd.  */
-	  symtab_hdr->contents = (unsigned char *) extsyms;
+	  /* Cache the section contents for elf_link_input_bfd.  */
+	  elf_section_data (sec)->this_hdr.contents = contents;
 	}
     }
 
+  if (elf_section_data (sec)->relocs != internal_relocs)
+    {
+      if (!changed_relocs)
+	free (internal_relocs);
+      else
+	elf_section_data (sec)->relocs = internal_relocs;
+    }
+
   *again = changed_contents || changed_relocs;
   return true;
 
  error_return:
-  if (free_relocs != NULL)
-    free (free_relocs);
-  if (free_contents != NULL)
-    free (free_contents);
-  if (shndx_buf != NULL)
-    free (shndx_buf);
-  if (free_extsyms != NULL)
-    free (free_extsyms);
+  if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents)
+    free (isymbuf);
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
+    free (contents);
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
   return false;
 }
 
Index: bfd/elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.13
diff -u -p -r1.13 elfxx-mips.c
--- bfd/elfxx-mips.c	1 Jul 2002 10:01:01 -0000	1.13
+++ bfd/elfxx-mips.c	7 Jul 2002 06:59:30 -0000
@@ -4122,7 +4122,7 @@ _bfd_mips_elf_check_relocs (abfd, info, 
 		    && ELF_R_TYPE (abfd, r->r_info) != R_MIPS16_26)
 		  break;
 
-	      if (! info->keep_memory)
+	      if (elf_section_data (o)->relocs != sec_relocs)
 		free (sec_relocs);
 
 	      if (r < rend)
Index: bfd/elf32-arm.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.h,v
retrieving revision 1.86
diff -u -p -r1.86 elf32-arm.h
--- bfd/elf32-arm.h	1 Jul 2002 08:06:41 -0000	1.86
+++ bfd/elf32-arm.h	7 Jul 2002 06:59:32 -0000
@@ -639,12 +639,9 @@ bfd_elf32_arm_process_before_allocation 
      int no_pipeline_knowledge;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Rela *free_relocs = NULL;
+  Elf_Internal_Rela *internal_relocs = NULL;
   Elf_Internal_Rela *irel, *irelend;
   bfd_byte *contents = NULL;
-  bfd_byte *free_contents = NULL;
-  Elf32_External_Sym *extsyms = NULL;
-  Elf32_External_Sym *free_extsyms = NULL;
 
   asection *sec;
   struct elf32_arm_link_hash_table *globals;
@@ -677,13 +674,15 @@ bfd_elf32_arm_process_before_allocation 
       symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
 
       /* Load the relocs.  */
-      irel = (_bfd_elf32_link_read_relocs (abfd, sec, (PTR) NULL,
-					   (Elf_Internal_Rela *) NULL, false));
+      internal_relocs
+	= _bfd_elf32_link_read_relocs (abfd, sec, (PTR) NULL,
+				       (Elf_Internal_Rela *) NULL, false);
 
-      BFD_ASSERT (irel != 0);
+      if (internal_relocs == NULL)
+	goto error_return;
 
-      irelend = irel + sec->reloc_count;
-      for (; irel < irelend; irel++)
+      irelend = internal_relocs + sec->reloc_count;
+      for (irel = internal_relocs; irel < irelend; irel++)
 	{
 	  long r_type;
 	  unsigned long r_index;
@@ -711,37 +710,12 @@ bfd_elf32_arm_process_before_allocation 
 		  if (contents == NULL)
 		    goto error_return;
 
-		  free_contents = contents;
-
 		  if (!bfd_get_section_contents (abfd, sec, contents,
 						 (file_ptr) 0, sec->_raw_size))
 		    goto error_return;
 		}
 	    }
 
-	  /* Read this BFD's symbols if we haven't done so already.  */
-	  if (extsyms == NULL)
-	    {
-	      /* Get cached copy if it exists.  */
-	      if (symtab_hdr->contents != NULL)
-		extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-	      else
-		{
-		  /* Go get them off disk.  */
-		  extsyms = ((Elf32_External_Sym *)
-			     bfd_malloc (symtab_hdr->sh_size));
-		  if (extsyms == NULL)
-		    goto error_return;
-
-		  free_extsyms = extsyms;
-
-		  if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-		      || (bfd_bread (extsyms, symtab_hdr->sh_size, abfd)
-			  != symtab_hdr->sh_size))
-		    goto error_return;
-		}
-	    }
-
 	  /* If the relocation is not against a symbol it cannot concern us.  */
 	  h = NULL;
 
@@ -781,17 +755,27 @@ bfd_elf32_arm_process_before_allocation 
 	      break;
 	    }
 	}
+
+      if (contents != NULL
+	  && elf_section_data (sec)->this_hdr.contents != contents)
+	free (contents);
+      contents = NULL;
+
+      if (internal_relocs != NULL
+	  && elf_section_data (sec)->relocs != internal_relocs)
+	free (internal_relocs);
+      internal_relocs = NULL;
     }
 
   return true;
 
 error_return:
-  if (free_relocs != NULL)
-    free (free_relocs);
-  if (free_contents != NULL)
-    free (free_contents);
-  if (free_extsyms != NULL)
-    free (free_extsyms);
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
+    free (contents);
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
 
   return false;
 }
Index: bfd/elf32-hppa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-hppa.c,v
retrieving revision 1.86
diff -u -p -r1.86 elf32-hppa.c
--- bfd/elf32-hppa.c	1 Jul 2002 08:06:43 -0000	1.86
+++ bfd/elf32-hppa.c	7 Jul 2002 06:59:36 -0000
@@ -2770,69 +2770,26 @@ get_local_syms (output_bfd, input_bfd, i
        input_bfd = input_bfd->link_next, bfd_indx++)
     {
       Elf_Internal_Shdr *symtab_hdr;
-      Elf_Internal_Shdr *shndx_hdr;
-      Elf_Internal_Sym *isym;
-      Elf32_External_Sym *ext_syms, *esym, *end_sy;
-      Elf_External_Sym_Shndx *shndx_buf, *shndx;
-      bfd_size_type sec_size;
 
       /* We'll need the symbol table in a second.  */
       symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
       if (symtab_hdr->sh_info == 0)
 	continue;
 
-      /* We need an array of the local symbols attached to the input bfd.
-	 Unfortunately, we're going to have to read & swap them in.  */
-      sec_size = symtab_hdr->sh_info;
-      sec_size *= sizeof (Elf_Internal_Sym);
-      local_syms = (Elf_Internal_Sym *) bfd_malloc (sec_size);
+      /* We need an array of the local symbols attached to the input bfd.  */
+      local_syms = (Elf_Internal_Sym *) symtab_hdr->contents;
       if (local_syms == NULL)
-	return -1;
-
-      all_local_syms[bfd_indx] = local_syms;
-      sec_size = symtab_hdr->sh_info;
-      sec_size *= sizeof (Elf32_External_Sym);
-      ext_syms = (Elf32_External_Sym *) bfd_malloc (sec_size);
-      if (ext_syms == NULL)
-	return -1;
-
-      if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	  || bfd_bread ((PTR) ext_syms, sec_size, input_bfd) != sec_size)
-	{
-	error_ret_free_ext_syms:
-	  free (ext_syms);
-	  return -1;
-	}
-
-      shndx_buf = NULL;
-      shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr;
-      if (shndx_hdr->sh_size != 0)
 	{
-	  sec_size = symtab_hdr->sh_info;
-	  sec_size *= sizeof (Elf_External_Sym_Shndx);
-	  shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (sec_size);
-	  if (shndx_buf == NULL)
-	    goto error_ret_free_ext_syms;
-
-	  if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread ((PTR) shndx_buf, sec_size, input_bfd) != sec_size)
-	    {
-	      free (shndx_buf);
-	      goto error_ret_free_ext_syms;
-	    }
+	  local_syms = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
+					     symtab_hdr->sh_info, 0,
+					     NULL, NULL, NULL);
+	  /* Cache them for elf_link_input_bfd.  */
+	  symtab_hdr->contents = (unsigned char *) local_syms;
 	}
+      if (local_syms == NULL)
+	return -1;
 
-      /* Swap the local symbols in.  */
-      for (esym = ext_syms, end_sy = esym + symtab_hdr->sh_info,
-	     isym = local_syms, shndx = shndx_buf;
-	   esym < end_sy;
-	   esym++, isym++, shndx = (shndx ? shndx + 1 : NULL))
-	bfd_elf32_swap_symbol_in (input_bfd, (const PTR) esym,
-				  (const PTR) shndx, isym);
-
-      /* Now we can free the external symbols.  */
-      free (shndx_buf);
-      free (ext_syms);
+      all_local_syms[bfd_indx] = local_syms;
 
       if (info->shared && htab->multi_subspace)
 	{
@@ -2927,7 +2884,6 @@ elf32_hppa_size_stubs (output_bfd, stub_
   bfd_size_type stub_group_size;
   boolean stubs_always_before_branch;
   boolean stub_changed;
-  boolean ret = 0;
   struct elf32_hppa_link_hash_table *htab = hppa_link_hash_table (info);
 
   /* Stash our params away.  */
@@ -3186,15 +3142,12 @@ elf32_hppa_size_stubs (output_bfd, stub_
       stub_changed = false;
     }
 
-  ret = true;
+  free (htab->all_local_syms);
+  return true;
 
  error_ret_free_local:
-  while (htab->bfd_count-- > 0)
-    if (htab->all_local_syms[htab->bfd_count])
-      free (htab->all_local_syms[htab->bfd_count]);
   free (htab->all_local_syms);
-
-  return ret;
+  return false;
 }
 
 /* For a final link, this function is called after we have sized the
Index: bfd/elf32-m68k.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-m68k.c,v
retrieving revision 1.44
diff -u -p -r1.44 elf32-m68k.c
--- bfd/elf32-m68k.c	1 Jul 2002 08:06:44 -0000	1.44
+++ bfd/elf32-m68k.c	7 Jul 2002 06:59:38 -0000
@@ -2111,12 +2111,8 @@ bfd_m68k_elf32_create_embedded_relocs (a
      char **errmsg;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
-  Elf32_External_Sym *extsyms;
-  Elf32_External_Sym *free_extsyms = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
-  Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *free_relocs = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
+  Elf_Internal_Rela *internal_relocs = NULL;
   Elf_Internal_Rela *irel, *irelend;
   bfd_byte *p;
   bfd_size_type amt;
@@ -2129,40 +2125,6 @@ bfd_m68k_elf32_create_embedded_relocs (a
     return true;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  /* Read this BFD's symbols if we haven't done so already, or get the cached
-     copy if it exists.  */
-  if (symtab_hdr->contents != NULL)
-    extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-  else
-    {
-      /* Go get them off disk.  */
-      amt = symtab_hdr->sh_info * sizeof (Elf32_External_Sym);
-      if (info->keep_memory)
-	extsyms = (Elf32_External_Sym *) bfd_alloc (abfd, amt);
-      else
-	extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
-      if (extsyms == NULL)
-	goto error_return;
-      if (! info->keep_memory)
-	free_extsyms = extsyms;
-      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	  || bfd_bread (extsyms, amt, abfd) != amt)
-	goto error_return;
-      if (info->keep_memory)
-	symtab_hdr->contents = (unsigned char *) extsyms;
-    }
-
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-  if (shndx_hdr->sh_size != 0)
-    {
-      amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx);
-      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-      if (shndx_buf == NULL)
-	goto error_return;
-      if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	  || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
-	goto error_return;
-    }
 
   /* Get a copy of the native relocations.  */
   internal_relocs = (_bfd_elf32_link_read_relocs
@@ -2170,8 +2132,6 @@ bfd_m68k_elf32_create_embedded_relocs (a
 		      info->keep_memory));
   if (internal_relocs == NULL)
     goto error_return;
-  if (! info->keep_memory)
-    free_relocs = internal_relocs;
 
   amt = (bfd_size_type) datasec->reloc_count * 12;
   relsec->contents = (bfd_byte *) bfd_alloc (abfd, amt);
@@ -2202,17 +2162,23 @@ bfd_m68k_elf32_create_embedded_relocs (a
       /* Get the target section referred to by the reloc.  */
       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
 	{
-	  Elf32_External_Sym *esym;
-	  Elf_External_Sym_Shndx *shndx;
-	  Elf_Internal_Sym isym;
-
 	  /* A local symbol.  */
-	  esym = extsyms + ELF32_R_SYM (irel->r_info);
-	  shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0);
-	  bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				    &isym);
+	  Elf_Internal_Sym *isym;
+
+	  /* Read this BFD's local symbols if we haven't done so already.  */
+	  if (isymbuf == NULL)
+	    {
+	      isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+	      if (isymbuf == NULL)
+		isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+						symtab_hdr->sh_info, 0,
+						NULL, NULL, NULL);
+	      if (isymbuf == NULL)
+		goto error_return;
+	    }
 
-	  targetsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
+	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
+	  targetsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
 	}
       else
 	{
@@ -2236,21 +2202,19 @@ bfd_m68k_elf32_create_embedded_relocs (a
 	strncpy (p + 4, targetsec->output_section->name, 8);
     }
 
-  if (shndx_buf != NULL)
-    free (shndx_buf);
-  if (free_extsyms != NULL)
-    free (free_extsyms);
-  if (free_relocs != NULL)
-    free (free_relocs);
+  if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
+  if (internal_relocs != NULL
+      && elf_section_data (datasec)->relocs != internal_relocs)
+    free (internal_relocs);
   return true;
 
 error_return:
-  if (shndx_buf != NULL)
-    free (shndx_buf);
-  if (free_extsyms != NULL)
-    free (free_extsyms);
-  if (free_relocs != NULL)
-    free (free_relocs);
+  if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
+  if (internal_relocs != NULL
+      && elf_section_data (datasec)->relocs != internal_relocs)
+    free (internal_relocs);
   return false;
 }
 
Index: bfd/elf32-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-mips.c,v
retrieving revision 1.154
diff -u -p -r1.154 elf32-mips.c
--- bfd/elf32-mips.c	6 Jun 2002 00:29:21 -0000	1.154
+++ bfd/elf32-mips.c	7 Jul 2002 06:59:40 -0000
@@ -1786,15 +1786,10 @@ bfd_mips_elf32_create_embedded_relocs (a
      char **errmsg;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
-  Elf32_External_Sym *extsyms;
-  Elf32_External_Sym *free_extsyms = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
-  Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *free_relocs = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
+  Elf_Internal_Rela *internal_relocs = NULL;
   Elf_Internal_Rela *irel, *irelend;
   bfd_byte *p;
-  bfd_size_type amt;
 
   BFD_ASSERT (! info->relocateable);
 
@@ -1803,41 +1798,17 @@ bfd_mips_elf32_create_embedded_relocs (a
   if (datasec->reloc_count == 0)
     return true;
 
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   /* Read this BFD's symbols if we haven't done so already, or get the cached
      copy if it exists.  */
-  if (symtab_hdr->contents != NULL)
-    extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-  else
-    {
-      /* Go get them off disk.  */
-      if (info->keep_memory)
-	extsyms = ((Elf32_External_Sym *)
-		   bfd_alloc (abfd, symtab_hdr->sh_size));
-      else
-	extsyms = ((Elf32_External_Sym *)
-		   bfd_malloc (symtab_hdr->sh_size));
-      if (extsyms == NULL)
-	goto error_return;
-      if (! info->keep_memory)
-	free_extsyms = extsyms;
-      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	  || (bfd_bread (extsyms, symtab_hdr->sh_size, abfd)
-	      != symtab_hdr->sh_size))
-	goto error_return;
-      if (info->keep_memory)
-	symtab_hdr->contents = (unsigned char *) extsyms;
-    }
-
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-  if (shndx_hdr->sh_size != 0)
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  if (symtab_hdr->sh_info != 0)
     {
-      amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx);
-      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-      if (shndx_buf == NULL)
-	goto error_return;
-      if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	  || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
+      isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+      if (isymbuf == NULL)
+	isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+					symtab_hdr->sh_info, 0,
+					NULL, NULL, NULL);
+      if (isymbuf == NULL)
 	goto error_return;
     }
 
@@ -1847,8 +1818,6 @@ bfd_mips_elf32_create_embedded_relocs (a
 		      info->keep_memory));
   if (internal_relocs == NULL)
     goto error_return;
-  if (! info->keep_memory)
-    free_relocs = internal_relocs;
 
   relsec->contents = (bfd_byte *) bfd_alloc (abfd, datasec->reloc_count * 12);
   if (relsec->contents == NULL)
@@ -1879,17 +1848,11 @@ bfd_mips_elf32_create_embedded_relocs (a
       /* Get the target section referred to by the reloc.  */
       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
 	{
-          Elf32_External_Sym *esym;
-          Elf_External_Sym_Shndx *shndx;
-          Elf_Internal_Sym isym;
+          Elf_Internal_Sym *isym;
 
           /* A local symbol.  */
-          esym = extsyms + ELF32_R_SYM (irel->r_info);
-          shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0);
-	  bfd_elf32_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				    &isym);
-
-	  targetsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
+	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
+	  targetsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
 	}
       else
 	{
@@ -1926,21 +1889,21 @@ bfd_mips_elf32_create_embedded_relocs (a
 	strncpy (p + 4, targetsec->output_section->name, 8);
     }
 
-  if (shndx_buf != NULL)
-    free (shndx_buf);
-  if (free_extsyms != NULL)
-    free (free_extsyms);
-  if (free_relocs != NULL)
-    free (free_relocs);
+  if (internal_relocs != NULL
+      && elf_section_data (datasec)->relocs != internal_relocs)
+    free (internal_relocs);
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
   return true;
 
  error_return:
-  if (shndx_buf != NULL)
-    free (shndx_buf);
-  if (free_extsyms != NULL)
-    free (free_extsyms);
-  if (free_relocs != NULL)
-    free (free_relocs);
+  if (internal_relocs != NULL
+      && elf_section_data (datasec)->relocs != internal_relocs)
+    free (internal_relocs);
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
   return false;
 }
 
Index: bfd/elf64-hppa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-hppa.c,v
retrieving revision 1.25
diff -u -p -r1.25 elf64-hppa.c
--- bfd/elf64-hppa.c	27 Jun 2002 22:57:02 -0000	1.25
+++ bfd/elf64-hppa.c	7 Jul 2002 06:59:41 -0000
@@ -591,7 +591,6 @@ elf64_hppa_check_relocs (abfd, info, sec
   struct elf64_hppa_link_hash_table *hppa_info;
   const Elf_Internal_Rela *relend;
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Shdr *shndx_hdr;
   const Elf_Internal_Rela *rel;
   asection *dlt, *plt, *stubs;
   char *buf;
@@ -613,15 +612,14 @@ elf64_hppa_check_relocs (abfd, info, sec
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
 
   /* If necessary, build a new table holding section symbols indices
-     for this BFD.  This is disgusting.  */
+     for this BFD.  */
 
   if (info->shared && hppa_info->section_syms_bfd != abfd)
     {
       unsigned long i;
       unsigned int highest_shndx;
-      Elf_Internal_Sym *local_syms, *isym;
-      Elf64_External_Sym *ext_syms, *esym;
-      Elf_External_Sym_Shndx *shndx_buf, *shndx;
+      Elf_Internal_Sym *local_syms = NULL;
+      Elf_Internal_Sym *isym, *isymend;
       bfd_size_type amt;
 
       /* We're done with the old cache of section index to section symbol
@@ -632,72 +630,27 @@ elf64_hppa_check_relocs (abfd, info, sec
       if (hppa_info->section_syms)
 	free (hppa_info->section_syms);
 
-      /* Allocate memory for the internal and external symbols.  */
-      amt = symtab_hdr->sh_info;
-      amt *= sizeof (Elf_Internal_Sym);
-      local_syms = (Elf_Internal_Sym *) bfd_malloc (amt);
-      if (local_syms == NULL)
-	return false;
-
-      amt = symtab_hdr->sh_info;
-      amt *= sizeof (Elf64_External_Sym);
-      ext_syms = (Elf64_External_Sym *) bfd_malloc (amt);
-      if (ext_syms == NULL)
-	{
-	  free (local_syms);
-	  return false;
-	}
-
-      /* Read in the local symbols.  */
-      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	  || bfd_bread (ext_syms, amt, abfd) != amt)
+      /* Read this BFD's local symbols.  */
+      if (symtab_hdr->sh_info != 0)
 	{
-	  free (ext_syms);
-	  free (local_syms);
-	  return false;
-	}
-
-      shndx_buf = NULL;
-      shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-      if (shndx_hdr->sh_size != 0)
-	{
-	  amt = symtab_hdr->sh_info;
-	  amt *= sizeof (Elf_External_Sym_Shndx);
-	  shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
-	  if (shndx_buf == NULL)
-	    {
-	      free (ext_syms);
-	      free (local_syms);
-	      return false;
-	    }
-
-	  if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread (shndx_buf, amt, abfd) != amt)
-	    {
-	      free (shndx_buf);
-	      free (ext_syms);
-	      free (local_syms);
-	      return false;
-	    }
+	  local_syms = (Elf_Internal_Sym *) symtab_hdr->contents;
+	  if (local_syms == NULL)
+	    local_syms = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+					       symtab_hdr->sh_info, 0,
+					       NULL, NULL, NULL);
+	  if (local_syms == NULL)
+	    return false;
 	}
 
-      /* Swap in the local symbols, also record the highest section index
-	 referenced by the local symbols.  */
+      /* Record the highest section index referenced by the local symbols.  */
       highest_shndx = 0;
-      for (i = 0, isym = local_syms, esym = ext_syms, shndx = shndx_buf;
-	   i < symtab_hdr->sh_info;
-	   i++, esym++, isym++, shndx = (shndx != NULL ? shndx + 1 : NULL))
+      isymend = local_syms + symtab_hdr->sh_info;
+      for (isym = local_syms; isym < isymend; isym++)
 	{
-	  bfd_elf64_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx,
-				    isym);
 	  if (isym->st_shndx > highest_shndx)
 	    highest_shndx = isym->st_shndx;
 	}
 
-      /* Now we can free the external symbols.  */
-      free (shndx_buf);
-      free (ext_syms);
-
       /* Allocate an array to hold the section index to section symbol index
 	 mapping.  Bump by one since we start counting at zero.  */
       highest_shndx++;
@@ -707,14 +660,24 @@ elf64_hppa_check_relocs (abfd, info, sec
 
       /* Now walk the local symbols again.  If we find a section symbol,
 	 record the index of the symbol into the section_syms array.  */
-      for (isym = local_syms, i = 0; i < symtab_hdr->sh_info; i++, isym++)
+      for (i = 0, isym = local_syms; isym < isymend; i++, isym++)
 	{
 	  if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
 	    hppa_info->section_syms[isym->st_shndx] = i;
 	}
 
-      /* We are finished with the local symbols.  Get rid of them.  */
-      free (local_syms);
+      /* We are finished with the local symbols.  */
+      if (local_syms != NULL
+	  && symtab_hdr->contents != (unsigned char *) local_syms)
+	{
+	  if (! info->keep_memory)
+	    free (local_syms);
+	  else
+	    {
+	      /* Cache the symbols for elf_link_input_bfd.  */
+	      symtab_hdr->contents = (unsigned char *) local_syms;
+	    }
+	}
 
       /* Record which BFD we built the section_syms mapping for.  */
       hppa_info->section_syms_bfd = abfd;
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.55
diff -u -p -r1.55 elf64-ppc.c
--- bfd/elf64-ppc.c	1 Jul 2002 08:06:45 -0000	1.55
+++ bfd/elf64-ppc.c	7 Jul 2002 06:59:46 -0000
@@ -2036,10 +2036,8 @@ struct ppc_link_hash_table
   } *stub_group;
 
   /* Assorted information used by ppc64_elf_size_stubs.  */
-  unsigned int bfd_count;
   int top_index;
   asection **input_list;
-  Elf_Internal_Sym **all_local_syms;
 
   /* Short-cuts to get to dynamic linker sections.  */
   asection *sgot;
@@ -2134,8 +2132,6 @@ static boolean ppc_size_one_stub
   PARAMS ((struct bfd_hash_entry *, PTR));
 static void group_sections
   PARAMS ((struct ppc_link_hash_table *, bfd_size_type, boolean));
-static boolean get_local_syms
-  PARAMS ((bfd *, struct ppc_link_hash_table *));
 static boolean ppc64_elf_fake_sections
   PARAMS ((bfd *, Elf64_Internal_Shdr *, asection *));
 static boolean ppc64_elf_relocate_section
@@ -2295,7 +2291,6 @@ 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;
@@ -3689,7 +3684,6 @@ edit_opd (obfd, 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;
@@ -3698,6 +3692,7 @@ edit_opd (obfd, info)
       asection *sec;
       Elf_Internal_Rela *relstart, *rel, *relend;
       Elf_Internal_Shdr *symtab_hdr;
+      Elf_Internal_Sym *local_syms;
       struct elf_link_hash_entry **sym_hashes;
       bfd_vma offset;
       long *adjust;
@@ -3718,6 +3713,7 @@ edit_opd (obfd, info)
       if ((sec->flags & SEC_RELOC) == 0 || sec->reloc_count == 0)
 	continue;
 
+      local_syms = NULL;
       symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
       sym_hashes = elf_sym_hashes (ibfd);
 
@@ -3793,7 +3789,17 @@ edit_opd (obfd, info)
 	    }
 	  else
 	    {
-	      sym = htab->all_local_syms[bfd_indx] + r_symndx;
+	      if (local_syms == NULL)
+		{
+		  local_syms = (Elf_Internal_Sym *) symtab_hdr->contents;
+		  if (local_syms == NULL)
+		    local_syms = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
+						       symtab_hdr->sh_info, 0,
+						       NULL, NULL, NULL);
+		  if (local_syms == NULL)
+		    goto error_free_rel;
+		}
+	      sym = local_syms + r_symndx;
 	      if ((sym->st_shndx != SHN_UNDEF
 		   && sym->st_shndx < SHN_LORESERVE)
 		  || sym->st_shndx > SHN_HIRESERVE)
@@ -3833,11 +3839,18 @@ edit_opd (obfd, info)
 	  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;
+	      if (loc == NULL
+		  || !bfd_get_section_contents (ibfd, sec, loc, (bfd_vma) 0,
+						sec->_raw_size))
+		{
+		  if (local_syms != NULL
+		      && symtab_hdr->contents != (unsigned char *) local_syms)
+		    free (local_syms);
+		error_free_rel:
+		  if (elf_section_data (sec)->relocs != relstart)
+		    free (relstart);
+		  return false;
+		}
 	      sec->contents = loc;
 	      sec->flags |= (SEC_IN_MEMORY | SEC_HAS_CONTENTS);
 	    }
@@ -3874,7 +3887,7 @@ edit_opd (obfd, info)
 		    }
 		  else
 		    {
-		      sym = htab->all_local_syms[bfd_indx] + r_symndx;
+		      sym = local_syms + r_symndx;
 		      if ((sym->st_shndx != SHN_UNDEF
 			   && sym->st_shndx < SHN_LORESERVE)
 			  || sym->st_shndx > SHN_HIRESERVE)
@@ -3903,13 +3916,12 @@ edit_opd (obfd, info)
 			}
 		      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.  */
+			  /* Local syms are a bit tricky.  We could
+			     tweak them as they can be cached, but
+			     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;
 			}
@@ -3937,8 +3949,17 @@ edit_opd (obfd, info)
 	  sec->_cooked_size = wptr - sec->contents;
 	  sec->reloc_count = write_rel - relstart;
 	}
-      else if (elf_section_data (sec)->relocs == NULL)
+      else if (elf_section_data (sec)->relocs != relstart)
 	free (relstart);
+
+      if (local_syms != NULL
+	  && symtab_hdr->contents != (unsigned char *) local_syms)
+	{
+	  if (!info->keep_memory)
+	    free (local_syms);
+	  else
+	    symtab_hdr->contents = (unsigned char *) local_syms;
+	}
     }
 
   return true;
@@ -4242,9 +4263,6 @@ ppc64_elf_size_dynamic_sections (output_
 	}
     }
 
-  if (!get_local_syms (info->input_bfds, htab))
-    return false;
-
   if (!edit_opd (output_bfd, info))
     return false;
 
@@ -4890,110 +4908,6 @@ group_sections (htab, stub_group_size, s
 #undef PREV_SEC
 }
 
-/* Read in all local syms for all input bfds.  */
-
-static boolean
-get_local_syms (input_bfd, htab)
-     bfd *input_bfd;
-     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.  */
-  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.  */
-  for (bfd_indx = 0;
-       input_bfd != NULL;
-       input_bfd = input_bfd->link_next, bfd_indx++)
-    {
-      Elf_Internal_Shdr *symtab_hdr;
-      Elf_Internal_Shdr *shndx_hdr;
-      Elf_Internal_Sym *isym;
-      Elf64_External_Sym *ext_syms, *esym, *end_sy;
-      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)
-	continue;
-
-      /* We need an array of the local symbols attached to the input bfd.
-	 Unfortunately, we're going to have to read & swap them in.  */
-      sec_size = symtab_hdr->sh_info;
-      sec_size *= sizeof (Elf_Internal_Sym);
-      local_syms = (Elf_Internal_Sym *) bfd_malloc (sec_size);
-      if (local_syms == NULL)
-	return false;
-
-      all_local_syms[bfd_indx] = local_syms;
-      sec_size = symtab_hdr->sh_info;
-      sec_size *= sizeof (Elf64_External_Sym);
-      ext_syms = (Elf64_External_Sym *) bfd_malloc (sec_size);
-      if (ext_syms == NULL)
-	return false;
-
-      if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-	  || bfd_bread ((PTR) ext_syms, sec_size, input_bfd) != sec_size)
-	{
-	error_ret_free_ext_syms:
-	  free (ext_syms);
-	  return false;
-	}
-
-      shndx_buf = NULL;
-      shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr;
-      if (shndx_hdr->sh_size != 0)
-	{
-	  sec_size = symtab_hdr->sh_info;
-	  sec_size *= sizeof (Elf_External_Sym_Shndx);
-	  shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (sec_size);
-	  if (shndx_buf == NULL)
-	    goto error_ret_free_ext_syms;
-
-	  if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-	      || bfd_bread ((PTR) shndx_buf, sec_size, input_bfd) != sec_size)
-	    {
-	      free (shndx_buf);
-	      goto error_ret_free_ext_syms;
-	    }
-	}
-
-      /* Swap the local symbols in.  */
-      for (esym = ext_syms, end_sy = esym + symtab_hdr->sh_info,
-	     isym = local_syms, shndx = shndx_buf;
-	   esym < end_sy;
-	   esym++, isym++, shndx = (shndx ? shndx + 1 : NULL))
-	bfd_elf64_swap_symbol_in (input_bfd, (const PTR) esym,
-				  (const PTR) shndx, isym);
-
-      /* Now we can free the external symbols.  */
-      free (shndx_buf);
-      free (ext_syms);
-    }
-
-  return true;
-}
-
 /* Determine and set the size of the stub section for a final link.
 
    The basic idea here is to examine all the relocations looking for
@@ -5012,7 +4926,6 @@ ppc64_elf_size_stubs (output_bfd, stub_b
 {
   bfd_size_type stub_group_size;
   boolean stubs_always_before_branch;
-  boolean ret = false;
   struct ppc_link_hash_table *htab = ppc_hash_table (info);
 
   /* Stash our params away.  */
@@ -5034,13 +4947,6 @@ ppc64_elf_size_stubs (output_bfd, stub_b
 
   group_sections (htab, stub_group_size, stubs_always_before_branch);
 
-  if (! get_local_syms (info->input_bfds, htab))
-    {
-      if (htab->all_local_syms)
-	goto error_ret_free_local;
-      return false;
-    }
-
   while (1)
     {
       bfd *input_bfd;
@@ -5057,15 +4963,13 @@ ppc64_elf_size_stubs (output_bfd, stub_b
 	{
 	  Elf_Internal_Shdr *symtab_hdr;
 	  asection *section;
-	  Elf_Internal_Sym *local_syms;
+	  Elf_Internal_Sym *local_syms = NULL;
 
 	  /* We'll need the symbol table in a second.  */
 	  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
 	  if (symtab_hdr->sh_info == 0)
 	    continue;
 
-	  local_syms = htab->all_local_syms[bfd_indx];
-
 	  /* Walk over each section attached to the input bfd.  */
 	  for (section = input_bfd->sections;
 	       section != NULL;
@@ -5114,10 +5018,7 @@ ppc64_elf_size_stubs (output_bfd, stub_b
 		  if (r_type >= (unsigned int) R_PPC_max)
 		    {
 		      bfd_set_error (bfd_error_bad_value);
-		    error_ret_free_internal:
-		      if (elf_section_data (section)->relocs == NULL)
-			free (internal_relocs);
-		      goto error_ret_free_local;
+		      goto error_ret_free_internal;
 		    }
 
 		  /* Only look for stubs on branch instructions.  */
@@ -5139,6 +5040,18 @@ ppc64_elf_size_stubs (output_bfd, stub_b
 		      Elf_Internal_Sym *sym;
 		      Elf_Internal_Shdr *hdr;
 
+		      if (local_syms == NULL)
+			{
+			  local_syms
+			    = (Elf_Internal_Sym *) symtab_hdr->contents;
+			  if (local_syms == NULL)
+			    local_syms
+			      = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
+						      symtab_hdr->sh_info, 0,
+						      NULL, NULL, NULL);
+			  if (local_syms == NULL)
+			    goto error_ret_free_internal;
+			}
 		      sym = local_syms + r_indx;
 		      hdr = elf_elfsections (input_bfd)[sym->st_shndx];
 		      sym_sec = hdr->bfd_section;
@@ -5210,7 +5123,15 @@ ppc64_elf_size_stubs (output_bfd, stub_b
 		  if (stub_entry == NULL)
 		    {
 		      free (stub_name);
-		      goto error_ret_free_internal;
+		    error_ret_free_internal:
+		      if (elf_section_data (section)->relocs == NULL)
+			free (internal_relocs);
+		    error_ret_free_local:
+		      if (local_syms != NULL
+			  && (symtab_hdr->contents
+			      != (unsigned char *) local_syms))
+			free (local_syms);
+		      return false;
 		    }
 
 		  stub_entry->target_value = sym_value;
@@ -5221,9 +5142,18 @@ ppc64_elf_size_stubs (output_bfd, stub_b
 		}
 
 	      /* We're done with the internal relocs, free them.  */
-	      if (elf_section_data (section)->relocs == NULL)
+	      if (elf_section_data (section)->relocs != internal_relocs)
 		free (internal_relocs);
 	    }
+
+	  if (local_syms != NULL
+	      && symtab_hdr->contents != (unsigned char *) local_syms)
+	    {
+	      if (!info->keep_memory)
+		free (local_syms);
+	      else
+		symtab_hdr->contents = (unsigned char *) local_syms;
+	    }
 	}
 
       if (!stub_changed)
@@ -5252,15 +5182,7 @@ ppc64_elf_size_stubs (output_bfd, stub_b
      the dynamic symbol table is corrupted since the section symbol
      for the stripped section isn't written.  */
 
-  ret = true;
-
- error_ret_free_local:
-  while (htab->bfd_count-- > 0)
-    if (htab->all_local_syms[htab->bfd_count])
-      free (htab->all_local_syms[htab->bfd_count]);
-  free (htab->all_local_syms);
-
-  return ret;
+  return true;
 }
 
 /* Called after we have determined section placement.  If sections


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