public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* .dynsym pain
@ 1999-07-12 18:05 Richard Henderson
  1999-07-12 20:37 ` Ian Lance Taylor
  1999-07-12 21:57 ` Mark Mitchell
  0 siblings, 2 replies; 11+ messages in thread
From: Richard Henderson @ 1999-07-12 18:05 UTC (permalink / raw)
  To: binutils

I've a need to install certain STB_LOCAL symbols in the dynamic symbol
table.  I can't tell you the reason at the moment, but suffice to say
that they should act like STB_LOCAL symbols do in the normal symbol table.

There are multiple sources of pain here --

First, symbols that began life as local symbols do not have an
elf_link_hash_entry struct, so there's no existing place to record the
dynindx.  Further, they're not in the hash table to been seen in the
several _bfd_elf_link_adjust_dynindx traversals.

Second, symbols that begain life as global symbols, but which were hidden
by symbol versioning or whatnot, are supposed to have a dynindx of -1. 
Which gets in the way of the fact that I need it to have an index, but
to be pushed out with STB_LOCAL rather than whatever it had had before.

So I'm wondering how best to go about this.  My current thought is to 
add a table or linked list to elf_link_hash_table that keeps track of
the local symbols we want in the dynamic symbol table.  That, plus a
_bfd_elf_link_record_local_dynamic_symbol entry point, would add direct
support for this feature to the generic elf linker, and would avoid the
creation of yet more bed hooks (or alternately introduce yet more 
hidden order of evaluation fragility).

It would also necessitate the cleanup of the addition of the sections
to the dynamic symbol table, as currently happens scattered across all
the backends and elflink.h.  Because calls to record_dynamic_symbol
and record_local_dynamic_symbol would be interleaved, we'd need to make
a pass at the end of bfd_elf,size_dynamic_sections to renumber the 
dynindx of sections then local syms then global syms.  So we'd actually
make fewer passes across the data structures.

Comments?


r~

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: .dynsym pain
  1999-07-12 18:05 .dynsym pain Richard Henderson
@ 1999-07-12 20:37 ` Ian Lance Taylor
  1999-07-13 18:20   ` Richard Henderson
  1999-07-12 21:57 ` Mark Mitchell
  1 sibling, 1 reply; 11+ messages in thread
From: Ian Lance Taylor @ 1999-07-12 20:37 UTC (permalink / raw)
  To: rth; +Cc: binutils

   Date: Mon, 12 Jul 1999 18:05:12 -0700
   From: Richard Henderson <rth@cygnus.com>

   I've a need to install certain STB_LOCAL symbols in the dynamic symbol
   table.  I can't tell you the reason at the moment, but suffice to say
   that they should act like STB_LOCAL symbols do in the normal symbol table.

I assume you mean by this that dynamic relocations can refer to them.
I gather there is some reason that you can't convert the dynamic
relocations to refer to section symbols instead; presumably there is
extra information attached to the STB_LOCAL dynamic symbols somehow.

   First, symbols that began life as local symbols do not have an
   elf_link_hash_entry struct, so there's no existing place to record the
   dynindx.  Further, they're not in the hash table to been seen in the
   several _bfd_elf_link_adjust_dynindx traversals.

Yeah, I don't see how you can put them in the hash table since they
shouldn't have globally visible names.

   Second, symbols that begain life as global symbols, but which were hidden
   by symbol versioning or whatnot, are supposed to have a dynindx of -1. 
   Which gets in the way of the fact that I need it to have an index, but
   to be pushed out with STB_LOCAL rather than whatever it had had before.

I'm not sure why this matters, but I agree with it.

   So I'm wondering how best to go about this.  My current thought is to 
   add a table or linked list to elf_link_hash_table that keeps track of
   the local symbols we want in the dynamic symbol table.  That, plus a
   _bfd_elf_link_record_local_dynamic_symbol entry point, would add direct
   support for this feature to the generic elf linker, and would avoid the
   creation of yet more bed hooks (or alternately introduce yet more 
   hidden order of evaluation fragility).

What type are you going to be put on the linked list?  A hash table
entry?  I guess you basically need enough information to output the
dynamic symbol.  You'll then need to run through the list specially at
some point; you won't want to call elf_link_output_extsym since you
won't want an external symbol.

   It would also necessitate the cleanup of the addition of the sections
   to the dynamic symbol table, as currently happens scattered across all
   the backends and elflink.h.  Because calls to record_dynamic_symbol
   and record_local_dynamic_symbol would be interleaved, we'd need to make
   a pass at the end of bfd_elf,size_dynamic_sections to renumber the 
   dynindx of sections then local syms then global syms.  So we'd actually
   make fewer passes across the data structures.

Yes, I can't think of any reason why we really need to set the dynamic
symbol index in _bfd_elf_link_record_dynamic_symbol.  We just need to
somehow record that the symbol needs a dynamic symbol entry, which
could be done with a flag.  As you say, we could just set all the
dynamic symbol indices near the end of size_dynamic_sections, and that
would be simpler than the current procedure.

Ian

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: .dynsym pain
  1999-07-12 18:05 .dynsym pain Richard Henderson
  1999-07-12 20:37 ` Ian Lance Taylor
@ 1999-07-12 21:57 ` Mark Mitchell
  1999-07-13 19:12   ` Richard Henderson
  1 sibling, 1 reply; 11+ messages in thread
From: Mark Mitchell @ 1999-07-12 21:57 UTC (permalink / raw)
  To: rth; +Cc: binutils

>>>>> "Richard" == Richard Henderson <rth@cygnus.com> writes:

    Richard> It would also necessitate the cleanup of the addition of
    Richard> the sections to the dynamic symbol table, as currently
    Richard> happens scattered across all the backends and elflink.h.

I don't fully understand all the issues you've raised, but doing the
cleanup you mention here is clearly a good idea.  I stumbled across
this more than once recently.

It seems to be that dynamic symbols, whether local or not, should be
in the hash table.  I found it vaguely offensive that the section
symbols, which wind up in the dynamic symbol table, had to be handled
specially.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: .dynsym pain
  1999-07-12 20:37 ` Ian Lance Taylor
@ 1999-07-13 18:20   ` Richard Henderson
  0 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 1999-07-13 18:20 UTC (permalink / raw)
  To: binutils

On Mon, Jul 12, 1999 at 11:36:25PM -0400, Ian Lance Taylor wrote:
> I assume you mean by this that dynamic relocations can refer to them.

Yep.

> I gather there is some reason that you can't convert the dynamic
> relocations to refer to section symbols instead; presumably there is
> extra information attached to the STB_LOCAL dynamic symbols somehow.

Not quite -- just a bit of ABI silliness that requires r_addend
to be zero for the relocations in question.

>    Which gets in the way of the fact that I need it to have an index, but
>    to be pushed out with STB_LOCAL rather than whatever it had had before.
> 
> I'm not sure why this matters, but I agree with it.

Explained in a comment I added in elf-bfd.h.

> What type are you going to be put on the linked list?

The pair <input_bfd, input_symbol_index> is the unique token.  I'm
also keeping around the entire Elf_Internal_Sym, just because it's
painful to acquire, and I didn't want to have to do it twice.

> You'll then need to run through the list specially at some point;

Yep.  In final_link, just before we call elf_link_output_extsym.

For reference, here's the patch I checked in.  I've tested it
against my new target and on Alpha.  It also fixes a bug on x86,
since we were failing to output the section symbols in shared
libraries there.


r~


	* elf-bfd.h (struct elf_link_local_dynamic_entry): New.
	(struct elf_link_hash_table): Add dynlocal.
	(_bfd_elf_link_lookup_local_dynindx): Prototype.
	(_bfd_elf_link_adjust_dynindx): Delete.
	(_bfd_elf_link_renumber_dynsyms): Prototype.
	(_bfd_elf,link_record_local_dynamic_symbol): Prototype.
	* elfcode.h (elf_link_record_local_dynamic_symbol): New alias.
	* elflink.c (_bfd_elf_link_adjust_dynindx): Delete.
	(_bfd_elf_link_lookup_local_dynindx): New function.
	(elf_link_renumber_hash_table_dynsyms): New function.
	(_bfd_elf_link_renumber_dynsyms): New function.
	* elflink.h (elf_link_record_local_dynamic_symbol): New function.
	(struct elf_assign_sym_version_info): Delete removed_dynamic.
	(bfd_elf,size_dynamic_sections): Use _bfd_strip_section_from_output
	instead of elf_link_remove_section_and_adjust_dynindices.
	Remove removed_dynamic code.  Use _bfd_elf_link_renumber_dynsyms.
	(elf_link_assign_sym_version): Remove removed_dynamic code.
	(elf_link_renumber_dynsyms): Delete.
	(elf_bfd_final_link): Install section and local symbols into .dynsym.

	* elf32-m68k.c (elf_m68k_adjust_dynindx): Delete.
	(elf_m68k_size_dynamic_sections): Don't set section dynindicies.
	(elf_m68k_finish_dynamic_sections): Don't write section dynsyms.
	* elf32-mips.c: Similarly.
	* elf32-ppc.c: Similarly.
	* elf32-sparc.c: Similarly.
	* elf64-alpha.c: Similarly.
	* elf64-sparc.c: Similarly.

Index: elf-bfd.h
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elf-bfd.h,v
retrieving revision 1.10
diff -c -p -d -r1.10 elf-bfd.h
*** elf-bfd.h	1999/07/11 17:13:34	1.10
--- elf-bfd.h	1999/07/14 01:04:15
*************** struct elf_link_hash_entry
*** 86,91 ****
--- 86,101 ----
  
    /* Symbol index as a dynamic symbol.  Initialized to -1, and remains
       -1 if this is not a dynamic symbol.  */
+   /* ??? Note that this is consistently used as a synonym for tests
+      against whether we can perform various simplifying transformations
+      to the code.  (E.g. changing a pc-relative jump to a PLT entry
+      into a pc-relative jump to the target function.)  That test, which
+      is often relatively complex, and someplaces wrong or incomplete,
+      should really be replaced by a predicate in elflink.c.
+ 
+      End result: this field -1 does not indicate that the symbol is
+      not in the dynamic symbol table, but rather that the symbol is
+      not visible outside this DSO.  */
    long dynindx;
  
    /* String table index in .dynstr if this is a dynamic symbol.  */
*************** struct elf_link_hash_entry
*** 181,186 ****
--- 191,215 ----
  #define ELF_LINK_HASH_MARK 04000
  };
  
+ /* Records local symbols to be emitted in the dynamic symbol table.  */
+ 
+ struct elf_link_local_dynamic_entry
+ {
+   struct elf_link_local_dynamic_entry *next;
+ 
+   /* The input bfd this symbol came from.  */
+   bfd *input_bfd;
+ 
+   /* The index of the local symbol being copied.  */
+   long input_indx;
+ 
+   /* The index in the outgoing dynamic symbol table.  */
+   long dynindx;
+   
+   /* A copy of the input symbol.  */
+   Elf_Internal_Sym isym;
+ };
+ 
  /* ELF linker hash table.  */
  
  struct elf_link_hash_table
*************** struct elf_link_hash_table
*** 209,214 ****
--- 238,245 ----
    struct elf_link_hash_entry *hgot;
    /* A pointer to information used to link stabs in sections.  */
    PTR stab_info;
+   /* A linked list of local symbols to be added to .dynsym.  */
+   struct elf_link_local_dynamic_entry *dynlocal;
  };
  
  /* Look up an entry in an ELF linker hash table.  */
*************** struct bfd_strtab_hash *_bfd_elf_stringt
*** 956,961 ****
--- 987,995 ----
  boolean
  _bfd_elf_link_record_dynamic_symbol PARAMS ((struct bfd_link_info *,
  					     struct elf_link_hash_entry *));
+ long
+ _bfd_elf_link_lookup_local_dynindx PARAMS ((struct bfd_link_info *,
+ 					    bfd *, long));
  boolean
  _bfd_elf_compute_section_file_positions PARAMS ((bfd *,
  						 struct bfd_link_info *));
*************** boolean _bfd_elf_create_dynamic_sections
*** 970,977 ****
  						  struct bfd_link_info *));
  boolean _bfd_elf_create_got_section PARAMS ((bfd *,
  					     struct bfd_link_info *));
! boolean _bfd_elf_link_adjust_dynindx PARAMS ((struct elf_link_hash_entry *,
! 					      PTR));
  
  elf_linker_section_t *_bfd_elf_create_linker_section
    PARAMS ((bfd *abfd,
--- 1004,1011 ----
  						  struct bfd_link_info *));
  boolean _bfd_elf_create_got_section PARAMS ((bfd *,
  					     struct bfd_link_info *));
! unsigned long _bfd_elf_link_renumber_dynsyms PARAMS ((bfd *,
! 						      struct bfd_link_info *));
  
  elf_linker_section_t *_bfd_elf_create_linker_section
    PARAMS ((bfd *abfd,
*************** extern boolean bfd_elf64_link_create_dyn
*** 1113,1120 ****
  extern Elf_Internal_Rela *_bfd_elf64_link_read_relocs
    PARAMS ((bfd *, asection *, PTR, Elf_Internal_Rela *, boolean));
  
! #define bfd_elf32_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
! #define bfd_elf64_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
  
  extern boolean _bfd_elf_close_and_cleanup PARAMS ((bfd *));
  extern bfd_reloc_status_type _bfd_elf_rel_vtable_reloc_fn
--- 1147,1161 ----
  extern Elf_Internal_Rela *_bfd_elf64_link_read_relocs
    PARAMS ((bfd *, asection *, PTR, Elf_Internal_Rela *, boolean));
  
! #define bfd_elf32_link_record_dynamic_symbol \
!   _bfd_elf_link_record_dynamic_symbol
! #define bfd_elf64_link_record_dynamic_symbol \
!   _bfd_elf_link_record_dynamic_symbol
! 
! boolean _bfd_elf32_link_record_local_dynamic_symbol
!   PARAMS ((struct bfd_link_info *, bfd *, long));
! boolean _bfd_elf64_link_record_local_dynamic_symbol
!   PARAMS ((struct bfd_link_info *, bfd *, long));
  
  extern boolean _bfd_elf_close_and_cleanup PARAMS ((bfd *));
  extern bfd_reloc_status_type _bfd_elf_rel_vtable_reloc_fn
Index: elf32-m68k.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elf32-m68k.c,v
retrieving revision 1.6
diff -c -p -d -r1.6 elf32-m68k.c
*** elf32-m68k.c	1999/07/12 08:15:16	1.6
--- elf32-m68k.c	1999/07/14 01:04:15
*************** static boolean elf_m68k_gc_sweep_hook
*** 43,50 ****
  	   const Elf_Internal_Rela *));
  static boolean elf_m68k_adjust_dynamic_symbol
    PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
- static boolean elf_m68k_adjust_dynindx
-   PARAMS ((struct elf_link_hash_entry *, PTR));
  static boolean elf_m68k_size_dynamic_sections
    PARAMS ((bfd *, struct bfd_link_info *));
  static boolean elf_m68k_relocate_section
--- 43,48 ----
*************** elf_m68k_size_dynamic_sections (output_b
*** 1312,1365 ****
  	}
      }
  
-   /* If we are generating a shared library, we generate a section
-      symbol for each output section for which we might need to copy
-      relocs.  These are local symbols, which means that they must come
-      first in the dynamic symbol table.  That means we must increment
-      the dynamic symbol index of every other dynamic symbol.  */
-   if (info->shared)
-     {
-       int c;
- 
-       c = 0;
-       for (s = output_bfd->sections; s != NULL; s = s->next)
- 	{
- 	  if ((s->flags & SEC_LINKER_CREATED) != 0
- 	      || (s->flags & SEC_ALLOC) == 0)
- 	    continue;
- 
- 	  elf_section_data (s)->dynindx = c + 1;
- 
- 	  /* These symbols will have no names, so we don't need to
-              fiddle with dynstr_index.  */
- 
- 	  ++c;
- 	}
- 
-       elf_link_hash_traverse (elf_hash_table (info),
- 			      elf_m68k_adjust_dynindx,
- 			      (PTR) &c);
-       elf_hash_table (info)->dynsymcount += c;
-     }
- 
    return true;
  }
  
- /* Increment the index of a dynamic symbol by a given amount.  Called
-    via elf_link_hash_traverse.  */
- 
- static boolean
- elf_m68k_adjust_dynindx (h, cparg)
-      struct elf_link_hash_entry *h;
-      PTR cparg;
- {
-   int *cp = (int *) cparg;
- 
-   if (h->dynindx != -1)
-     h->dynindx += *cp;
-   return true;
- }
- 
  /* This function is called via elf_m68k_link_hash_traverse if we are
     creating a shared object with -Bsymbolic.  It discards the space
     allocated to copy PC relative relocs against symbols which are defined
--- 1310,1318 ----
*************** elf_m68k_finish_dynamic_sections (output
*** 2212,2261 ****
      }
  
    elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
- 
-   if (info->shared)
-     {
-       asection *sdynsym;
-       asection *s;
-       Elf_Internal_Sym sym;
-       int c;
- 
-       /* Set up the section symbols for the output sections.  */
- 
-       sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
-       BFD_ASSERT (sdynsym != NULL);
- 
-       sym.st_size = 0;
-       sym.st_name = 0;
-       sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
-       sym.st_other = 0;
- 
-       c = 0;
-       for (s = output_bfd->sections; s != NULL; s = s->next)
- 	{
- 	  int indx;
- 
- 	  if (elf_section_data (s)->dynindx == 0)
- 	    continue;
- 
- 	  sym.st_value = s->vma;
- 
- 	  indx = elf_section_data (s)->this_idx;
- 	  BFD_ASSERT (indx > 0);
- 	  sym.st_shndx = indx;
- 
- 	  bfd_elf32_swap_symbol_out (output_bfd, &sym,
- 				     (PTR) (((Elf32_External_Sym *)
- 					     sdynsym->contents)
- 					    + elf_section_data (s)->dynindx));
- 
- 	  ++c;
- 	}
- 
-       /* Set the sh_info field of the output .dynsym section to the
-          index of the first global symbol.  */
-       elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1;
-     }
  
    return true;
  }
--- 2165,2170 ----
Index: elf32-mips.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elf32-mips.c,v
retrieving revision 1.20
diff -c -p -d -r1.20 elf32-mips.c
*** elf32-mips.c	1999/07/13 15:23:22	1.20
--- elf32-mips.c	1999/07/14 01:04:15
*************** _bfd_mips_elf_size_dynamic_sections (out
*** 7693,7724 ****
  	return false;
      }
  
-   /* If we use dynamic linking, we generate a section symbol for each
-      output section.  These are local symbols, which means that they
-      must come first in the dynamic symbol table.
-      That means we must increment the dynamic symbol index of every
-      other dynamic symbol.  */
-   {
-     unsigned int c, i;
- 
-     c = 0;
-     if (elf_hash_table (info)->dynamic_sections_created)
-       {
- 	c = bfd_count_sections (output_bfd);
- 	elf_link_hash_traverse (elf_hash_table (info),
- 				_bfd_elf_link_adjust_dynindx,
- 				(PTR) &c);
- 	elf_hash_table (info)->dynsymcount += c;
- 
- 	for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++)
- 	  {
- 	    elf_section_data (s)->dynindx = i;
- 	    /* These symbols will have no names, so we don't need to
- 	       fiddle with dynstr_index.  */
- 	  }
-       }
-   }
- 
    return true;
  }
  
--- 7693,7698 ----
*************** _bfd_mips_elf_finish_dynamic_sections (o
*** 8163,8221 ****
        = MIPS_ELF_GOT_SIZE (output_bfd);
  
    {
-     asection *sdynsym;
      asection *smsym;
      asection *s;
-     Elf_Internal_Sym sym;
      Elf32_compact_rel cpt;
  
!     /* Set up the section symbols for the output sections. SGI sets
!        the STT_NOTYPE attribute for these symbols.  Should we do so?  */
  
-     sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
      smsym = bfd_get_section_by_name (dynobj, 
  				     MIPS_ELF_MSYM_SECTION_NAME (dynobj));
!     if (sdynsym != NULL)
        {
  	Elf32_Internal_Msym msym;
  
- 	sym.st_size = 0;
- 	sym.st_name = 0;
- 	sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
- 	sym.st_other = 0;
- 
  	msym.ms_hash_value = 0;
  	msym.ms_info = ELF32_MS_INFO (0, 1);
  
  	for (s = output_bfd->sections; s != NULL; s = s->next)
  	  {
! 	    int indx;
! 	    long dynindx;
! 
! 	    sym.st_value = s->vma;
! 
! 	    indx = elf_section_data (s)->this_idx;
! 	    BFD_ASSERT (indx > 0);
! 	    sym.st_shndx = indx;
! 		
! 	    dynindx  = elf_section_data (s)->dynindx;
  
! 	    (*get_elf_backend_data (output_bfd)->s->swap_symbol_out)
! 	      (output_bfd, &sym, 
! 	       sdynsym->contents 
! 	       + (dynindx * MIPS_ELF_SYM_SIZE (output_bfd)));
! 		
! 	    if (smsym)
! 	      bfd_mips_elf_swap_msym_out 
! 		(output_bfd, &msym,
! 		 (((Elf32_External_Msym *) smsym->contents)
! 		  + dynindx));
  	  }
- 
- 	/* Set the sh_info field of the output .dynsym section to
- 	       the index of the first global symbol.  */
- 	elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
- 	  bfd_count_sections (output_bfd) + 1;
        }
  
      if (SGI_COMPAT (output_bfd))
--- 8137,8168 ----
        = MIPS_ELF_GOT_SIZE (output_bfd);
  
    {
      asection *smsym;
      asection *s;
      Elf32_compact_rel cpt;
  
!     /* ??? The section symbols for the output sections were set up in
!        _bfd_elf_final_link.  SGI sets the STT_NOTYPE attribute for these
!        symbols.  Should we do so?  */
  
      smsym = bfd_get_section_by_name (dynobj, 
  				     MIPS_ELF_MSYM_SECTION_NAME (dynobj));
!     if (smsym != NULL)
        {
  	Elf32_Internal_Msym msym;
  
  	msym.ms_hash_value = 0;
  	msym.ms_info = ELF32_MS_INFO (0, 1);
  
  	for (s = output_bfd->sections; s != NULL; s = s->next)
  	  {
! 	    long dynindx = elf_section_data (s)->dynindx;
  
! 	    bfd_mips_elf_swap_msym_out 
! 	      (output_bfd, &msym,
! 	       (((Elf32_External_Msym *) smsym->contents)
! 		+ dynindx));
  	  }
        }
  
      if (SGI_COMPAT (output_bfd))
Index: elf32-ppc.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elf32-ppc.c,v
retrieving revision 1.5
diff -c -p -d -r1.5 elf32-ppc.c
*** elf32-ppc.c	1999/07/12 10:29:28	1.5
--- elf32-ppc.c	1999/07/14 01:04:15
*************** static boolean ppc_elf_gc_sweep_hook PAR
*** 80,87 ****
  static boolean ppc_elf_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *,
  						      struct elf_link_hash_entry *));
  
- static boolean ppc_elf_adjust_dynindx PARAMS ((struct elf_link_hash_entry *, PTR));
- 
  static boolean ppc_elf_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *));
  
  static boolean ppc_elf_relocate_section PARAMS ((bfd *,
--- 80,85 ----
*************** ppc_elf_adjust_dynamic_symbol (info, h)
*** 1881,1907 ****
  }
  
  \f
- /* Increment the index of a dynamic symbol by a given amount.  Called
-    via elf_link_hash_traverse.  */
- 
- static boolean
- ppc_elf_adjust_dynindx (h, cparg)
-      struct elf_link_hash_entry *h;
-      PTR cparg;
- {
-   int *cp = (int *) cparg;
- 
- #ifdef DEBUG
-   fprintf (stderr, "ppc_elf_adjust_dynindx called, h->dynindx = %d, *cp = %d\n", h->dynindx, *cp);
- #endif
- 
-   if (h->dynindx != -1)
-     h->dynindx += *cp;
- 
-   return true;
- }
- 
- \f
  /* Set the sizes of the dynamic sections.  */
  
  static boolean
--- 1879,1884 ----
*************** ppc_elf_size_dynamic_sections (output_bf
*** 2083,2125 ****
  	}
      }
  
-   /* If we are generating a shared library, we generate a section
-      symbol for each output section.  These are local symbols, which
-      means that they must come first in the dynamic symbol table.
-      That means we must increment the dynamic symbol index of every
-      other dynamic symbol.
- 
-      FIXME: We assume that there will never be relocations to
-      locations in linker-created sections that do not have
-      externally-visible names. Instead, we should work out precisely
-      which sections relocations are targetted at.  */
-   if (info->shared)
-     {
-       int c;
- 
-       for (c = 0, s = output_bfd->sections; s != NULL; s = s->next)
- 	{
- 	  if ((s->flags & SEC_LINKER_CREATED) != 0
- 	      || (s->flags & SEC_ALLOC) == 0)
- 	    {
- 	      elf_section_data (s)->dynindx = 0;
- 	      continue;
- 	    }
- 
- 	  /* These symbols will have no names, so we don't need to
- 	     fiddle with dynstr_index.  */
- 
- 	  elf_section_data (s)->dynindx = c + 1;
- 
- 	  c++;
- 	}
- 
-       elf_link_hash_traverse (elf_hash_table (info),
- 			      ppc_elf_adjust_dynindx,
- 			      (PTR) &c);
-       elf_hash_table (info)->dynsymcount += c;
-     }
- 
    return true;
  }
  
--- 2060,2065 ----
*************** ppc_elf_finish_dynamic_sections (output_
*** 2922,2975 ****
  		    contents+4);
  
        elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
-     }
- 
-   if (info->shared)
-     {
-       asection *sdynsym;
-       asection *s;
-       Elf_Internal_Sym sym;
-       int maxdindx = 0;
- 
-       /* Set up the section symbols for the output sections.  */
- 
-       sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
-       BFD_ASSERT (sdynsym != NULL);
- 
-       sym.st_size = 0;
-       sym.st_name = 0;
-       sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
-       sym.st_other = 0;
- 
-       for (s = output_bfd->sections; s != NULL; s = s->next)
- 	{
- 	  int indx, dindx;
- 
- 	  sym.st_value = s->vma;
- 
- 	  indx = elf_section_data (s)->this_idx;
- 	  dindx = elf_section_data (s)->dynindx;
- 	  if (dindx > 0)
- 	    {
- 	      BFD_ASSERT(indx > 0);
- 	      BFD_ASSERT(dindx > 0);
- 
- 	      if (dindx > maxdindx)
- 		maxdindx = dindx;
- 
- 	      sym.st_shndx = indx;
- 
- 	      bfd_elf32_swap_symbol_out (output_bfd, &sym,
- 					 (PTR) (((Elf32_External_Sym *)
- 						 sdynsym->contents)
- 						+ dindx));
- 	    }
- 	}
- 
-       /* Set the sh_info field of the output .dynsym section to the
-          index of the first global symbol.  */
-       elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
- 	maxdindx + 1;
      }
  
    return true;
--- 2862,2867 ----
Index: elf32-sparc.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elf32-sparc.c,v
retrieving revision 1.4
diff -c -p -d -r1.4 elf32-sparc.c
*** elf32-sparc.c	1999/07/12 10:29:33	1.4
--- elf32-sparc.c	1999/07/14 01:04:16
*************** static boolean elf32_sparc_check_relocs
*** 33,40 ****
  	   const Elf_Internal_Rela *));
  static boolean elf32_sparc_adjust_dynamic_symbol
    PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
- static boolean elf32_sparc_adjust_dynindx
-   PARAMS ((struct elf_link_hash_entry *, PTR));
  static boolean elf32_sparc_size_dynamic_sections
    PARAMS ((bfd *, struct bfd_link_info *));
  static boolean elf32_sparc_relocate_section
--- 33,38 ----
*************** elf32_sparc_size_dynamic_sections (outpu
*** 1043,1096 ****
  	}
      }
  
-   /* If we are generating a shared library, we generate a section
-      symbol for each output section for which we might need to copy
-      relocs.  These are local symbols, which means that they must come
-      first in the dynamic symbol table.  That means we must increment
-      the dynamic symbol index of every other dynamic symbol.  */
-   if (info->shared)
-     {
-       int c;
- 
-       c = 0;
-       for (s = output_bfd->sections; s != NULL; s = s->next)
- 	{
- 	  if ((s->flags & SEC_LINKER_CREATED) != 0
- 	      || (s->flags & SEC_ALLOC) == 0)
- 	    continue;
- 
- 	  elf_section_data (s)->dynindx = c + 1;
- 
- 	  /* These symbols will have no names, so we don't need to
-              fiddle with dynstr_index.  */
- 
- 	  ++c;
- 	}
- 
-       elf_link_hash_traverse (elf_hash_table (info),
- 			      elf32_sparc_adjust_dynindx,
- 			      (PTR) &c);
-       elf_hash_table (info)->dynsymcount += c;
-     }
- 
    return true;
  }
  
- /* Increment the index of a dynamic symbol by a given amount.  Called
-    via elf_link_hash_traverse.  */
- 
- static boolean
- elf32_sparc_adjust_dynindx (h, cparg)
-      struct elf_link_hash_entry *h;
-      PTR cparg;
- {
-   int *cp = (int *) cparg;
- 
-   if (h->dynindx != -1)
-     h->dynindx += *cp;
-   return true;
- }
- 
  /* Relocate a SPARC ELF section.  */
  
  static boolean
--- 1041,1049 ----
*************** elf32_sparc_finish_dynamic_sections (out
*** 1849,1898 ****
      }
  
    elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
- 
-   if (info->shared)
-     {
-       asection *sdynsym;
-       asection *s;
-       Elf_Internal_Sym sym;
-       int c;
- 
-       /* Set up the section symbols for the output sections.  */
- 
-       sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
-       BFD_ASSERT (sdynsym != NULL);
- 
-       sym.st_size = 0;
-       sym.st_name = 0;
-       sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
-       sym.st_other = 0;
- 
-       c = 0;
-       for (s = output_bfd->sections; s != NULL; s = s->next)
- 	{
- 	  int indx;
- 
- 	  if (elf_section_data (s)->dynindx == 0)
- 	    continue;
- 
- 	  sym.st_value = s->vma;
- 
- 	  indx = elf_section_data (s)->this_idx;
- 	  BFD_ASSERT (indx > 0);
- 	  sym.st_shndx = indx;
- 
- 	  bfd_elf32_swap_symbol_out (output_bfd, &sym,
- 				     (PTR) (((Elf32_External_Sym *)
- 					     sdynsym->contents)
- 					    + elf_section_data (s)->dynindx));
- 
- 	  ++c;
- 	}
- 
-       /* Set the sh_info field of the output .dynsym section to the
-          index of the first global symbol.  */
-       elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1;
-     }
  
    return true;
  }
--- 1802,1807 ----
Index: elf64-alpha.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elf64-alpha.c,v
retrieving revision 1.2
diff -c -p -d -r1.2 elf64-alpha.c
*** elf64-alpha.c	1999/06/18 04:25:56	1.2
--- elf64-alpha.c	1999/07/14 01:04:16
*************** static boolean elf64_alpha_adjust_dynami
*** 115,122 ****
    PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *));
  static boolean elf64_alpha_size_dynamic_sections
    PARAMS((bfd *, struct bfd_link_info *));
- static boolean elf64_alpha_adjust_dynindx
-   PARAMS((struct elf_link_hash_entry *, PTR));
  static boolean elf64_alpha_relocate_section
    PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
  	  Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
--- 115,120 ----
*************** elf64_alpha_size_dynamic_sections (outpu
*** 3264,3297 ****
  	}
      }
  
-   /* If we are generating a shared library, we generate a section
-      symbol for each output section.  These are local symbols, which
-      means that they must come first in the dynamic symbol table.
-      That means we must increment the dynamic symbol index of every
-      other dynamic symbol.  */
-   if (info->shared)
-     {
-       long c[2], i;
-       asection *p;
- 
-       c[0] = 0;
-       c[1] = bfd_count_sections (output_bfd);
- 
-       elf_hash_table (info)->dynsymcount += c[1];
-       elf_link_hash_traverse (elf_hash_table(info),
- 			      elf64_alpha_adjust_dynindx,
- 			      (PTR) c);
- 
-       for (i = 1, p = output_bfd->sections;
- 	   p != NULL;
- 	   p = p->next, i++)
- 	{
- 	  elf_section_data (p)->dynindx = i;
- 	  /* These symbols will have no names, so we don't need to
- 	     fiddle with dynstr_index.  */
- 	}
-     }
- 
    if (elf_hash_table (info)->dynamic_sections_created)
      {
        /* Add some entries to the .dynamic section.  We fill in the
--- 3262,3267 ----
*************** elf64_alpha_size_dynamic_sections (outpu
*** 3332,3353 ****
    return true;
  }
  
- /* Increment the index of a dynamic symbol by a given amount.  Called
-    via elf_link_hash_traverse.  */
- 
- static boolean
- elf64_alpha_adjust_dynindx (h, cparg)
-      struct elf_link_hash_entry *h;
-      PTR cparg;
- {
-   long *cp = (long *)cparg;
- 
-   if (h->dynindx >= cp[0])
-     h->dynindx += cp[1];
- 
-   return true;
- }
- 
  /* Relocate an Alpha ELF section.  */
  
  static boolean
--- 3302,3307 ----
*************** elf64_alpha_finish_dynamic_sections (out
*** 3989,4032 ****
  	  elf_section_data (splt->output_section)->this_hdr.sh_entsize =
  	    PLT_HEADER_SIZE;
  	}
-     }
- 
-   if (info->shared)
-     {
-       asection *sdynsym;
-       asection *s;
-       Elf_Internal_Sym sym;
- 
-       /* Set up the section symbols for the output sections.  */
- 
-       sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
-       BFD_ASSERT (sdynsym != NULL);
- 
-       sym.st_size = 0;
-       sym.st_name = 0;
-       sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
-       sym.st_other = 0;
- 
-       for (s = output_bfd->sections; s != NULL; s = s->next)
- 	{
- 	  int indx;
- 
- 	  sym.st_value = s->vma;
- 
- 	  indx = elf_section_data (s)->this_idx;
- 	  BFD_ASSERT (indx > 0);
- 	  sym.st_shndx = indx;
- 
- 	  bfd_elf64_swap_symbol_out (output_bfd, &sym,
- 				     (PTR) (((Elf64_External_Sym *)
- 					     sdynsym->contents)
- 					    + elf_section_data (s)->dynindx));
- 	}
- 
-       /* Set the sh_info field of the output .dynsym section to the
-          index of the first global symbol.  */
-       elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
- 	bfd_count_sections (output_bfd) + 1;
      }
  
    return true;
--- 3943,3948 ----
Index: elf64-sparc.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elf64-sparc.c,v
retrieving revision 1.2
diff -c -p -d -r1.2 elf64-sparc.c
*** elf64-sparc.c	1999/06/10 20:59:54	1.2
--- elf64-sparc.c	1999/07/14 01:04:16
*************** static boolean sparc64_elf_adjust_dynami
*** 51,58 ****
    PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *));
  static boolean sparc64_elf_size_dynamic_sections
    PARAMS((bfd *, struct bfd_link_info *));
- static boolean sparc64_elf_adjust_dynindx
-   PARAMS((struct elf_link_hash_entry *, PTR));
  
  static boolean sparc64_elf_merge_private_bfd_data
    PARAMS ((bfd *, bfd *));
--- 51,56 ----
*************** sparc64_elf_size_dynamic_sections (outpu
*** 1146,1199 ****
  	}
      }
  
-   /* If we are generating a shared library, we generate a section
-      symbol for each output section for which we might need to copy
-      relocs.  These are local symbols, which means that they must come
-      first in the dynamic symbol table.  That means we must increment
-      the dynamic symbol index of every other dynamic symbol.  */
-   if (info->shared)
-     {
-       int c;
- 
-       c = 0;
-       for (s = output_bfd->sections; s != NULL; s = s->next)
- 	{
- 	  if ((s->flags & SEC_LINKER_CREATED) != 0
- 	      || (s->flags & SEC_ALLOC) == 0)
- 	    continue;
- 
- 	  elf_section_data (s)->dynindx = c + 1;
- 
- 	  /* These symbols will have no names, so we don't need to
-              fiddle with dynstr_index.  */
- 
- 	  ++c;
- 	}
- 
-       elf_link_hash_traverse (elf_hash_table (info),
- 			      sparc64_elf_adjust_dynindx,
- 			      (PTR) &c);
-       elf_hash_table (info)->dynsymcount += c;
-     }
- 
-   return true;
- }
- 
- /* Increment the index of a dynamic symbol by a given amount.  Called
-    via elf_link_hash_traverse.  */
- 
- static boolean
- sparc64_elf_adjust_dynindx (h, cparg)
-      struct elf_link_hash_entry *h;
-      PTR cparg;
- {
-   int *cp = (int *) cparg;
- 
-   if (h->dynindx != -1)
-     h->dynindx += *cp;
    return true;
  }
- 
  \f
  /* Relocate a SPARC64 ELF section.  */
  
--- 1144,1151 ----
*************** sparc64_elf_finish_dynamic_sections (out
*** 2089,2138 ****
      }
  
    elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 8;
- 
-   if (info->shared)
-     {
-       asection *sdynsym;
-       asection *s;
-       Elf_Internal_Sym sym;
-       int c;
- 
-       /* Set up the section symbols for the output sections.  */
- 
-       sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
-       BFD_ASSERT (sdynsym != NULL);
- 
-       sym.st_size = 0;
-       sym.st_name = 0;
-       sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
-       sym.st_other = 0;
- 
-       c = 0;
-       for (s = output_bfd->sections; s != NULL; s = s->next)
- 	{
- 	  int indx;
- 
- 	  if (elf_section_data (s)->dynindx == 0)
- 	    continue;
- 
- 	  sym.st_value = s->vma;
- 
- 	  indx = elf_section_data (s)->this_idx;
- 	  BFD_ASSERT (indx > 0);
- 	  sym.st_shndx = indx;
- 
- 	  bfd_elf64_swap_symbol_out (output_bfd, &sym,
- 				     (PTR) (((Elf64_External_Sym *)
- 					     sdynsym->contents)
- 					    + elf_section_data (s)->dynindx));
- 
- 	  ++c;
- 	}
- 
-       /* Set the sh_info field of the output .dynsym section to the
-          index of the first global symbol.  */
-       elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1;
-     }
  
    return true;
  }
--- 2041,2046 ----
Index: elfcode.h
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elfcode.h,v
retrieving revision 1.5
diff -c -p -d -r1.5 elfcode.h
*** elfcode.h	1999/07/07 17:50:55	1.5
--- elfcode.h	1999/07/14 01:04:16
*************** Foundation, Inc., 59 Temple Place - Suit
*** 130,135 ****
--- 130,137 ----
  #define elf_gc_common_final_link	NAME(_bfd_elf,gc_common_final_link)
  #define elf_gc_record_vtinherit		NAME(_bfd_elf,gc_record_vtinherit)
  #define elf_gc_record_vtentry		NAME(_bfd_elf,gc_record_vtentry)
+ #define elf_link_record_local_dynamic_symbol \
+   NAME(_bfd_elf,link_record_local_dynamic_symbol)
  
  #if ARCH_SIZE == 64
  #define ELF_R_INFO(X,Y)	ELF64_R_INFO(X,Y)
Index: elflink.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elflink.c,v
retrieving revision 1.5
diff -c -p -d -r1.5 elflink.c
*** elflink.c	1999/07/11 19:49:34	1.5
--- elflink.c	1999/07/14 01:04:16
*************** _bfd_elf_link_record_dynamic_symbol (inf
*** 260,281 ****
    return true;
  }
  
! /* Increase the index at which H will appear in the dynamic symbol
!    table by INCREMENT (which is really an `int *').  Called via
!    elf_link_hash_traverse.  */
  
! boolean
! _bfd_elf_link_adjust_dynindx (h, increment)
       struct elf_link_hash_entry *h;
!      PTR increment;
  {
    if (h->dynindx != -1)
!     h->dynindx += *((int *) increment);
!     
    return true;
  }
  \f
! /* Create a special linker section, or return a pointer to a linker section already created  */
  
  elf_linker_section_t *
  _bfd_elf_create_linker_section (abfd, info, which, defaults)
--- 260,342 ----
    return true;
  }
  
! /* Return the dynindex of a local dynamic symbol.  */
  
! long
! _bfd_elf_link_lookup_local_dynindx (info, input_bfd, input_indx)
!      struct bfd_link_info *info;
!      bfd *input_bfd;
!      long input_indx;
! {
!   struct elf_link_local_dynamic_entry *e;
! 
!   for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
!     if (e->input_bfd == input_bfd && e->input_indx == input_indx)
!       return e->dynindx;
!   return -1;
! }
! 
! /* This function is used to renumber the dynamic symbols, if some of
!    them are removed because they are marked as local.  This is called
!    via elf_link_hash_traverse.  */
! 
! static boolean elf_link_renumber_hash_table_dynsyms
!   PARAMS ((struct elf_link_hash_entry *, PTR));
! 
! static boolean
! elf_link_renumber_hash_table_dynsyms (h, data)
       struct elf_link_hash_entry *h;
!      PTR data;
  {
+   size_t *count = (size_t *) data;
+ 
    if (h->dynindx != -1)
!     h->dynindx = ++(*count);
! 
    return true;
  }
+ 
+ /* Assign dynsym indicies.  In a shared library we generate a section
+    symbol for each output section, which come first.  Next come all of
+    the back-end allocated local dynamic syms, followed by the rest of
+    the global symbols.  */
+ 
+ unsigned long
+ _bfd_elf_link_renumber_dynsyms (output_bfd, info)
+      bfd *output_bfd;
+      struct bfd_link_info *info;
+ {
+   unsigned long dynsymcount = 0;
+ 
+   if (info->shared)
+     {
+       asection *p;
+       for (p = output_bfd->sections; p ; p = p->next)
+ 	elf_section_data (p)->dynindx = ++dynsymcount;
+     }
+ 
+   if (elf_hash_table (info)->dynlocal)
+     {
+       struct elf_link_local_dynamic_entry *p;
+       for (p = elf_hash_table (info)->dynlocal; p ; p = p->next)
+ 	p->dynindx = ++dynsymcount;
+     }
+ 
+   elf_link_hash_traverse (elf_hash_table (info),
+ 			  elf_link_renumber_hash_table_dynsyms,
+ 			  &dynsymcount);
+ 
+   /* There is an unused NULL entry at the head of the table which
+      we must account for in our count.  Unless there weren't any
+      symbols, which means we'll have no table at all.  */
+   if (dynsymcount != 0)
+     ++dynsymcount;
+ 
+   return elf_hash_table (info)->dynsymcount = dynsymcount;
+ }
  \f
! /* Create a special linker section, or return a pointer to a linker
!    section already created */
  
  elf_linker_section_t *
  _bfd_elf_create_linker_section (abfd, info, which, defaults)
Index: elflink.h
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elflink.h,v
retrieving revision 1.15
diff -c -p -d -r1.15 elflink.h
*** elflink.h	1999/07/11 19:49:35	1.15
--- elflink.h	1999/07/14 01:04:16
*************** static boolean elf_link_find_version_dep
*** 48,61 ****
    PARAMS ((struct elf_link_hash_entry *, PTR));
  static boolean elf_link_assign_sym_version
    PARAMS ((struct elf_link_hash_entry *, PTR));
- static boolean elf_link_renumber_dynsyms
-   PARAMS ((struct elf_link_hash_entry *, PTR));
  static boolean elf_collect_hash_codes
    PARAMS ((struct elf_link_hash_entry *, PTR));
  static boolean elf_link_read_relocs_from_section 
    PARAMS ((bfd *, Elf_Internal_Shdr *, PTR, Elf_Internal_Rela *));
- static void elf_link_remove_section_and_adjust_dynindices 
-   PARAMS ((struct bfd_link_info *, asection *));
  static void elf_link_output_relocs
    PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *));
  static boolean elf_link_size_reloc_section
--- 48,57 ----
*************** elf_add_dynamic_entry (info, tag, val)
*** 2051,2056 ****
--- 2047,2119 ----
  
    return true;
  }
+ 
+ /* Record a new local dynamic symbol.  */
+ 
+ boolean
+ elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx)
+      struct bfd_link_info *info;
+      bfd *input_bfd;
+      long input_indx;
+ {
+   struct elf_link_local_dynamic_entry *entry;
+   struct elf_link_hash_table *eht;
+   struct bfd_strtab_hash *dynstr;
+   Elf_External_Sym esym;
+   unsigned long dynstr_index;
+   char *name;
+   int elfsec, link;
+ 
+   /* See if the entry exists already.  */
+   for (entry = elf_hash_table (info)->dynlocal; entry ; entry = entry->next)
+     if (entry->input_bfd == input_bfd && entry->input_indx == input_indx)
+       return true;
+ 
+   entry = (struct elf_link_local_dynamic_entry *)
+     bfd_alloc (input_bfd, sizeof (*entry));
+   if (entry == NULL)
+     return false;
+ 
+   /* Go find the symbol, so that we can find it's name.  */
+   if (bfd_seek (input_bfd,
+ 		(elf_tdata (input_bfd)->symtab_hdr.sh_offset
+ 		 + input_indx * sizeof (Elf_External_Sym)),
+ 		SEEK_SET) != 0
+       || (bfd_read (&esym, sizeof (Elf_External_Sym), 1, input_bfd)
+ 	  != sizeof (Elf_External_Sym)))
+     return false;
+   elf_swap_symbol_in (input_bfd, &esym, &entry->isym);
+ 
+   name = (bfd_elf_string_from_elf_section
+ 	  (input_bfd, elf_tdata (input_bfd)->symtab_hdr.sh_link,
+ 	   entry->isym.st_name));
+ 
+   dynstr = elf_hash_table (info)->dynstr;
+   if (dynstr == NULL)
+     {
+       /* Create a strtab to hold the dynamic symbol names.  */
+       elf_hash_table (info)->dynstr = dynstr = _bfd_elf_stringtab_init ();
+       if (dynstr == NULL)
+ 	return false;
+     }
+ 
+   dynstr_index = _bfd_stringtab_add (dynstr, name, true, false);
+   if (dynstr_index == (unsigned long) -1)
+     return false;
+   entry->isym.st_name = dynstr_index;
+ 
+   eht = elf_hash_table (info);
+ 
+   entry->next = eht->dynlocal;
+   eht->dynlocal = entry;
+   entry->input_bfd = input_bfd;
+   entry->input_indx = input_indx;
+   eht->dynsymcount++;
+ 
+   /* The dynindx will be set at the end of size_dynamic_sections.  */
+ 
+   return true;
+ }
  \f
  
  /* Read and swap the relocs from the section indicated by SHDR.  This
*************** struct elf_assign_sym_version_info
*** 2310,2317 ****
    struct bfd_elf_version_tree *verdefs;
    /* Whether we are exporting all dynamic symbols.  */
    boolean export_dynamic;
-   /* Whether we removed any symbols from the dynamic symbol table.  */
-   boolean removed_dynamic;
    /* Whether we had a failure.  */
    boolean failed;
  };
--- 2373,2378 ----
*************** compute_bucket_count (info)
*** 2486,2527 ****
    return best_size;
  }
  
- /* Remove SECTION from the BFD.  If a symbol for SECTION was going to
-    be put into the dynamic symbol table, remove it, and renumber
-    subsequent entries.  */
- 
- static void
- elf_link_remove_section_and_adjust_dynindices (info, section)
-      struct bfd_link_info *info;
-      asection *section;
- {
-   /* Remove the section from the output list.  */
-   _bfd_strip_section_from_output (section);
- 
-   if (elf_section_data (section->output_section)->dynindx)
-     {
-       asection *s;
-       int increment = -1;
- 
-       /* We were going to output an entry in the dynamic symbol table
- 	 for the symbol corresponding to this section.  Now, the
- 	 section is gone.  So, we must renumber the dynamic indices of
- 	 all subsequent sections and all other entries in the dynamic
- 	 symbol table.  */
-       elf_section_data (section->output_section)->dynindx = 0;
-       for (s = section->output_section->next; s; s = s->next)
- 	if (elf_section_data (s)->dynindx)
- 	  --elf_section_data (s)->dynindx;
-       
-       elf_link_hash_traverse (elf_hash_table (info),
- 			      _bfd_elf_link_adjust_dynindx,
- 			      &increment);
- 
-       /* There is one less dynamic symbol than there was before.  */
-       --elf_hash_table (info)->dynsymcount;
-     }
- }
- 
  /* Set up the sizes and contents of the ELF dynamic sections.  This is
     called by the ELF linker emulation before_allocation routine.  We
     must set the sizes of the sections before the linker sets the
--- 2547,2552 ----
*************** NAME(bfd_elf,size_dynamic_sections) (out
*** 2545,2551 ****
    bfd_size_type soname_indx;
    bfd *dynobj;
    struct elf_backend_data *bed;
-   bfd_size_type old_dynsymcount;
    struct elf_assign_sym_version_info asvinfo;
  
    *sinterpptr = NULL;
--- 2570,2575 ----
*************** NAME(bfd_elf,size_dynamic_sections) (out
*** 2650,2656 ****
        asvinfo.info = info;
        asvinfo.verdefs = verdefs;
        asvinfo.export_dynamic = export_dynamic;
-       asvinfo.removed_dynamic = false;
        asvinfo.failed = false;
  
        elf_link_hash_traverse (elf_hash_table (info),
--- 2674,2679 ----
*************** NAME(bfd_elf,size_dynamic_sections) (out
*** 2712,2718 ****
  
    /* The backend must work out the sizes of all the other dynamic
       sections.  */
-   old_dynsymcount = elf_hash_table (info)->dynsymcount;
    if (bed->elf_backend_size_dynamic_sections
        && ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
      return false;
--- 2735,2740 ----
*************** NAME(bfd_elf,size_dynamic_sections) (out
*** 2734,2740 ****
        verdefs = asvinfo.verdefs;
  
        if (verdefs == NULL)
! 	elf_link_remove_section_and_adjust_dynindices (info, s);
        else
  	{
  	  unsigned int cdefs;
--- 2756,2762 ----
        verdefs = asvinfo.verdefs;
  
        if (verdefs == NULL)
! 	_bfd_strip_section_from_output (s);
        else
  	{
  	  unsigned int cdefs;
*************** NAME(bfd_elf,size_dynamic_sections) (out
*** 2744,2766 ****
  	  Elf_Internal_Verdef def;
  	  Elf_Internal_Verdaux defaux;
  
- 	  if (asvinfo.removed_dynamic)
- 	    {
- 	      /* Some dynamic symbols were changed to be local
- 		 symbols.  In this case, we renumber all of the
- 		 dynamic symbols, so that we don't have a hole.  If
- 		 the backend changed dynsymcount, then assume that the
- 		 new symbols are at the start.  This is the case on
- 		 the MIPS.  FIXME: The names of the removed symbols
- 		 will still be in the dynamic string table, wasting
- 		 space.  */
- 	      elf_hash_table (info)->dynsymcount =
- 		1 + (elf_hash_table (info)->dynsymcount - old_dynsymcount);
- 	      elf_link_hash_traverse (elf_hash_table (info),
- 				      elf_link_renumber_dynsyms,
- 				      (PTR) info);
- 	    }
- 
  	  cdefs = 0;
  	  size = 0;
  
--- 2766,2771 ----
*************** NAME(bfd_elf,size_dynamic_sections) (out
*** 2927,2933 ****
  				(PTR) &sinfo);
  
  	if (elf_tdata (output_bfd)->verref == NULL)
! 	  elf_link_remove_section_and_adjust_dynindices (info, s);
  	else
  	  {
  	    Elf_Internal_Verneed *t;
--- 2932,2938 ----
  				(PTR) &sinfo);
  
  	if (elf_tdata (output_bfd)->verref == NULL)
! 	  _bfd_strip_section_from_output (s);
  	else
  	  {
  	    Elf_Internal_Verneed *t;
*************** NAME(bfd_elf,size_dynamic_sections) (out
*** 3018,3024 ****
  	  }
        }
  
!       dynsymcount = elf_hash_table (info)->dynsymcount;
  
        /* Work out the size of the symbol version section.  */
        s = bfd_get_section_by_name (dynobj, ".gnu.version");
--- 3023,3034 ----
  	  }
        }
  
!       /* Assign dynsym indicies.  In a shared library we generate a 
! 	 section symbol for each output section, which come first.
! 	 Next come all of the back-end allocated local dynamic syms,
! 	 followed by the rest of the global symbols.  */
! 
!       dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info);
  
        /* Work out the size of the symbol version section.  */
        s = bfd_get_section_by_name (dynobj, ".gnu.version");
*************** NAME(bfd_elf,size_dynamic_sections) (out
*** 3026,3035 ****
        if (dynsymcount == 0
  	  || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL))
  	{
! 	  elf_link_remove_section_and_adjust_dynindices (info, s);
  	  /* The DYNSYMCOUNT might have changed if we were going to
  	     output a dynamic symbol table entry for S.  */
! 	  dynsymcount = elf_hash_table (info)->dynsymcount;
  	}
        else
  	{
--- 3036,3045 ----
        if (dynsymcount == 0
  	  || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL))
  	{
! 	  _bfd_strip_section_from_output (s);
  	  /* The DYNSYMCOUNT might have changed if we were going to
  	     output a dynamic symbol table entry for S.  */
! 	  dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info);
  	}
        else
  	{
*************** elf_link_assign_sym_version (h, data)
*** 3513,3519 ****
  			      && info->shared
  			      && ! sinfo->export_dynamic)
  			    {
- 			      sinfo->removed_dynamic = true;
  			      h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
  			      h->elf_link_hash_flags &=~
  				ELF_LINK_HASH_NEEDS_PLT;
--- 3523,3528 ----
*************** elf_link_assign_sym_version (h, data)
*** 3629,3635 ****
  			  && info->shared
  			  && ! sinfo->export_dynamic)
  			{
- 			  sinfo->removed_dynamic = true;
  			  h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
  			  h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT;
  			  h->dynindx = -1;
--- 3638,3643 ----
*************** elf_link_assign_sym_version (h, data)
*** 3654,3660 ****
  	      && info->shared
  	      && ! sinfo->export_dynamic)
  	    {
- 	      sinfo->removed_dynamic = true;
  	      h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
  	      h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT;
  	      h->dynindx = -1;
--- 3662,3667 ----
*************** elf_link_assign_sym_version (h, data)
*** 3667,3692 ****
  
    return true;
  }
- 
- /* This function is used to renumber the dynamic symbols, if some of
-    them are removed because they are marked as local.  This is called
-    via elf_link_hash_traverse.  */
- 
- static boolean
- elf_link_renumber_dynsyms (h, data)
-      struct elf_link_hash_entry *h;
-      PTR data;
- {
-   struct bfd_link_info *info = (struct bfd_link_info *) data;
- 
-   if (h->dynindx != -1)
-     {
-       h->dynindx = elf_hash_table (info)->dynsymcount;
-       ++elf_hash_table (info)->dynsymcount;
-     }
- 
-   return true;
- }
  \f
  /* Final phase of ELF linker.  */
  
--- 3674,3679 ----
*************** elf_bfd_final_link (abfd, info)
*** 4161,4171 ****
  	return false;
      }
  
!   /* The sh_info field records the index of the first non local
!      symbol.  */
    symtab_hdr->sh_info = bfd_get_symcount (abfd);
    if (dynamic)
!     elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info = 1;
  
    /* We get the global symbols from the hash table.  */
    eoinfo.failed = false;
--- 4148,4224 ----
  	return false;
      }
  
!   /* The sh_info field records the index of the first non local symbol.  */
    symtab_hdr->sh_info = bfd_get_symcount (abfd);
+ 
    if (dynamic)
!     {
!       Elf_Internal_Sym sym;
!       Elf_External_Sym *dynsym =
! 	(Elf_External_Sym *)finfo.dynsym_sec->contents;
!       unsigned long last_local = 0;
! 
!       /* Write out the section symbols for the output sections.  */
!       if (info->shared)
! 	{
! 	  asection *s;
! 
! 	  sym.st_size = 0;
! 	  sym.st_name = 0;
! 	  sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
! 	  sym.st_other = 0;
! 
! 	  for (s = abfd->sections; s != NULL; s = s->next)
! 	    {
! 	      int indx;
! 	      indx = elf_section_data (s)->this_idx;
! 	      BFD_ASSERT (indx > 0);
! 	      sym.st_shndx = indx;
! 	      sym.st_value = s->vma;
! 
! 	      elf_swap_symbol_out (abfd, &sym,
! 				   dynsym + elf_section_data (s)->dynindx);
! 	    }
! 
! 	  last_local = bfd_count_sections (abfd);
! 	}
! 
!       /* Write out the local dynsyms.  */
!       if (elf_hash_table (info)->dynlocal)
! 	{
! 	  struct elf_link_local_dynamic_entry *e;
! 	  for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
! 	    {
! 	      asection *s, *os;
! 
! 	      sym.st_size = e->isym.st_size;
! 	      sym.st_other = e->isym.st_other;
! 
! 	      /* Note that we saved a word of storage and overwrote
!                  the original st_name with the dynstr_index.  */
! 	      sym.st_name = e->isym.st_name;
! 
! 	      /* Whatever binding the symbol had before, it's now local.  */
! 	      sym.st_info = ELF_ST_INFO (STB_LOCAL,
! 					 ELF_ST_TYPE (e->isym.st_info));
! 
! 	      s = bfd_section_from_elf_index (e->input_bfd, e->isym.st_shndx);
! 
! 	      sym.st_shndx = elf_section_data (s->output_section)->this_idx;
! 	      sym.st_value = (s->output_section->vma
! 			      + s->output_offset
! 			      + e->isym.st_value);
! 
! 	      if (last_local < e->dynindx)
! 		last_local = e->dynindx;
! 
! 	      elf_swap_symbol_out (abfd, &sym, dynsym + e->dynindx);
! 	    }
! 	}
! 
!       elf_section_data (finfo.dynsym_sec->output_section)
! 	->this_hdr.sh_info = last_local;
!     }
  
    /* We get the global symbols from the hash table.  */
    eoinfo.failed = false;

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: .dynsym pain
  1999-07-12 21:57 ` Mark Mitchell
@ 1999-07-13 19:12   ` Richard Henderson
  1999-07-13 22:42     ` Mark Mitchell
  0 siblings, 1 reply; 11+ messages in thread
From: Richard Henderson @ 1999-07-13 19:12 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: binutils

Mark, 

  I just noticed that my patch breaks mips.  Your mips_elf_sort_hash_table
stuff gets called before I completely renumber the symbols.  What do you 
think of the following fix?


r~


	* elf32-mips.c (mips_elf_sort_hash_table): Add output_bfd argument.
	Set the base dynindx based on the number of output sections.
	(_bfd_mips_elf_final_link): Call it.

Index: elf32-mips.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elf32-mips.c,v
retrieving revision 1.21
diff -c -p -d -r1.21 elf32-mips.c
*** elf32-mips.c	1999/07/13 18:21:19	1.21
--- elf32-mips.c	1999/07/14 02:10:47
*************** static boolean mips_elf_assign_gp PARAMS
*** 176,182 ****
  static boolean mips_elf_sort_hash_table_f 
    PARAMS ((struct mips_elf_link_hash_entry *, PTR));
  static boolean mips_elf_sort_hash_table 
!   PARAMS ((struct bfd_link_info *));
  static asection * mips_elf_got_section PARAMS ((bfd *));
  static struct mips_got_info *mips_elf_got_info 
    PARAMS ((bfd *, asection **));
--- 176,182 ----
  static boolean mips_elf_sort_hash_table_f 
    PARAMS ((struct mips_elf_link_hash_entry *, PTR));
  static boolean mips_elf_sort_hash_table 
!   PARAMS ((bfd *, struct bfd_link_info *));
  static asection * mips_elf_got_section PARAMS ((bfd *));
  static struct mips_got_info *mips_elf_got_info 
    PARAMS ((bfd *, asection **));
*************** _bfd_mips_elf_final_link (abfd, info)
*** 4319,4324 ****
--- 4319,4331 ----
        elf_elfheader (abfd)->e_flags |= EF_MIPS_CPIC;
      }
  
+   /* ??? We'd carefully arranged the dynamic symbol indices, and then the
+      generic size_dynamic_sections renumbered them out from under us.
+      Rather than trying somehow to prevent the renumbering, just do
+      the sort again.  */
+   if (!mips_elf_sort_hash_table (abfd, info))
+     return false;
+ 
    /* On IRIX5, we omit the .options section.  On IRIX6, however, we
       include it, even though we don't process it quite right.  (Some
       entries are supposed to be merged.)  Empirically, we seem to be
*************** mips_elf_sort_hash_table_f (h, data)
*** 5307,5313 ****
     required.  */
  
  static boolean
! mips_elf_sort_hash_table (info)
       struct bfd_link_info *info;
  {
    struct mips_elf_hash_sort_data hsd;
--- 5314,5321 ----
     required.  */
  
  static boolean
! mips_elf_sort_hash_table (output_bfd, info)
!      bfd *output_bfd;
       struct bfd_link_info *info;
  {
    struct mips_elf_hash_sort_data hsd;
*************** mips_elf_sort_hash_table (info)
*** 5318,5324 ****
  
    hsd.low = NULL;
    hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount;
!   hsd.max_non_got_dynindx = 1;
    mips_elf_link_hash_traverse (((struct mips_elf_link_hash_table *) 
  				elf_hash_table (info)), 
  			       mips_elf_sort_hash_table_f, 
--- 5326,5332 ----
  
    hsd.low = NULL;
    hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount;
!   hsd.max_non_got_dynindx = bfd_count_sections (output_bfd) + 1;
    mips_elf_link_hash_traverse (((struct mips_elf_link_hash_table *) 
  				elf_hash_table (info)), 
  			       mips_elf_sort_hash_table_f, 
*************** _bfd_mips_elf_size_dynamic_sections (out
*** 7530,7536 ****
   	     higher.  Therefore, it make sense to put those symbols
   	     that need GOT entries at the end of the symbol table.  We
   	     do that here.  */
!  	  if (!mips_elf_sort_hash_table (info))
   	    return false;
  
   	  i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx;
--- 7538,7544 ----
   	     higher.  Therefore, it make sense to put those symbols
   	     that need GOT entries at the end of the symbol table.  We
   	     do that here.  */
!  	  if (!mips_elf_sort_hash_table (output_bfd, info))
   	    return false;
  
   	  i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx;

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: .dynsym pain
  1999-07-13 19:12   ` Richard Henderson
@ 1999-07-13 22:42     ` Mark Mitchell
  1999-07-14  0:20       ` Richard Henderson
  0 siblings, 1 reply; 11+ messages in thread
From: Mark Mitchell @ 1999-07-13 22:42 UTC (permalink / raw)
  To: rth; +Cc: binutils

Richard --

  Is MIPS really broken, or do you just think it is?  

  If you renumber the dynamic symbols by adding a constant to all of
them when you add the new sections, then all should be well.  And I'd
think you'd want to do this in the generic case.  I think that's what
the MIPS code did before your change; if we didn't need to re-sort
before, why do we need to do so now?

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: .dynsym pain
  1999-07-13 22:42     ` Mark Mitchell
@ 1999-07-14  0:20       ` Richard Henderson
  1999-07-14  1:03         ` Mark Mitchell
  0 siblings, 1 reply; 11+ messages in thread
From: Richard Henderson @ 1999-07-14  0:20 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: binutils

On Tue, Jul 13, 1999 at 10:44:23PM -0700, Mark Mitchell wrote:
>   Is MIPS really broken, or do you just think it is?  

I know it is.

>   If you renumber the dynamic symbols by adding a constant to all of
> them when you add the new sections, then all should be well.

But I don't.  I completely re-issue numbers to those that had one before.

> And I'd think you'd want to do this in the generic case.

Nope.  In the general case I need to fill the holes left by 
elf_link_assign_sym_version (previously also fixed up by
complete renumbering -- also after bed->size_dynamic_sections!)
and also fill holes left by moving the dynlocal symbols to 
initial indicies.

So actually MIPS was broken by symbol versioning before my
change.  Now it's broken all the time.

I'm doubly convinced another sort is needed.


r~

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: .dynsym pain
  1999-07-14  0:20       ` Richard Henderson
@ 1999-07-14  1:03         ` Mark Mitchell
  1999-07-14  2:17           ` Richard Henderson
  0 siblings, 1 reply; 11+ messages in thread
From: Mark Mitchell @ 1999-07-14  1:03 UTC (permalink / raw)
  To: rth; +Cc: binutils

>>>>> "Richard" == Richard Henderson <rth@cygnus.com> writes:

    Richard> On Tue, Jul 13, 1999 at 10:44:23PM -0700, Mark Mitchell
    Richard> wrote:
    >> Is MIPS really broken, or do you just think it is?

    Richard> I know it is.

OK.

    Richard> I'm doubly convinced another sort is needed.

OK.  In that case, your patch looks reasonable to me, I guess.

But, I'm nervous about the need for *two* sorts.  The reason for the
first sort is to calculate the size of the GOT:

 	  /* There has to be a global GOT entry for every symbol with
 	     a dynamic symbol table index of DT_MIPS_GOTSYM or
 	     higher.  Therefore, it make sense to put those symbols
 	     that need GOT entries at the end of the symbol table.  We
 	     do that here.  */
 	  if (!mips_elf_sort_hash_table (info))
 	    return false;

 	  i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx;
	  s->_raw_size += i * MIPS_ELF_GOT_SIZE (dynobj);

So, if we resort, and the GOT gets bigger, that's very bad.  I assume
that this can't happen.  Perhaps you could add an assertion to check
that this situation does not occur?  Just checking `elf_hash_table
(info)->dynsymcount - g->global_gotsym->dynindx' before and after the
second sort should do it.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: .dynsym pain
  1999-07-14  1:03         ` Mark Mitchell
@ 1999-07-14  2:17           ` Richard Henderson
  1999-07-14  8:35             ` Mark Mitchell
  0 siblings, 1 reply; 11+ messages in thread
From: Richard Henderson @ 1999-07-14  2:17 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: binutils

On Wed, Jul 14, 1999 at 01:00:18AM -0700, Mark Mitchell wrote:
> But, I'm nervous about the need for *two* sorts.  The reason for the
> first sort is to calculate the size of the GOT:

Yep.

> So, if we resort, and the GOT gets bigger, that's very bad.  I assume
> that this can't happen.

It surely shouldn't.  It should only shrink.

> Perhaps you could add an assertion to check
> that this situation does not occur?  Just checking `elf_hash_table
> (info)->dynsymcount - g->global_gotsym->dynindx' before and after the
> second sort should do it.

Yes, I'll add something.  I don't think that'll do it since
the versioning code doesn't decrement dynsymcount, so I just
write a new value at the end of renumber_dynsym.

But saving a g->global_gotsize should do the trick.


r~

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: .dynsym pain
  1999-07-14  2:17           ` Richard Henderson
@ 1999-07-14  8:35             ` Mark Mitchell
  1999-07-14 17:04               ` Richard Henderson
  0 siblings, 1 reply; 11+ messages in thread
From: Mark Mitchell @ 1999-07-14  8:35 UTC (permalink / raw)
  To: rth; +Cc: binutils

>>>>> "Richard" == Richard Henderson <rth@cygnus.com> writes:

    Richard> Yes, I'll add something.  I don't think that'll do it
    Richard> since the versioning code doesn't decrement dynsymcount,
    Richard> so I just write a new value at the end of
    Richard> renumber_dynsym.

    Richard> But saving a g->global_gotsize should do the trick.

Cool.  Thanks for having have paid attention closely to the MIPS
back-end over the last few weeks so that you spotted the issue right
off.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: .dynsym pain
  1999-07-14  8:35             ` Mark Mitchell
@ 1999-07-14 17:04               ` Richard Henderson
  0 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 1999-07-14 17:04 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: binutils

Here's what I committed for this problem.


r~


        * elf32-mips.c (struct mips_got_info): Add global_gotno.
        (_bfd_mips_elf_size_dynamic_sections): Set it.
        (_bfd_mips_elf_final_link): Re-sort; verify the got did not grow.
        (mips_elf_sort_hash_table): Set max_non_got_dynindex based off
        new argument max_local.

Index: elf32-mips.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elf32-mips.c,v
retrieving revision 1.24
diff -c -p -d -r1.24 elf32-mips.c
*** elf32-mips.c	1999/07/14 11:46:04	1.24
--- elf32-mips.c	1999/07/14 21:16:06
*************** struct mips_got_info
*** 51,56 ****
--- 51,58 ----
    /* The global symbol in the GOT with the lowest index in the dynamic
       symbol table.  */
    struct elf_link_hash_entry *global_gotsym;
+   /* The number of global .got entries.  */
+   unsigned int global_gotno;
    /* The number of local .got entries.  */
    unsigned int local_gotno;
    /* The number of local .got entries we have used.  */
*************** static boolean mips_elf_assign_gp PARAMS
*** 177,183 ****
  static boolean mips_elf_sort_hash_table_f 
    PARAMS ((struct mips_elf_link_hash_entry *, PTR));
  static boolean mips_elf_sort_hash_table 
!   PARAMS ((struct bfd_link_info *));
  static asection * mips_elf_got_section PARAMS ((bfd *));
  static struct mips_got_info *mips_elf_got_info 
    PARAMS ((bfd *, asection **));
--- 179,185 ----
  static boolean mips_elf_sort_hash_table_f 
    PARAMS ((struct mips_elf_link_hash_entry *, PTR));
  static boolean mips_elf_sort_hash_table 
!   PARAMS ((struct bfd_link_info *, unsigned long));
  static asection * mips_elf_got_section PARAMS ((bfd *));
  static struct mips_got_info *mips_elf_got_info 
    PARAMS ((bfd *, asection **));
*************** _bfd_mips_elf_final_link (abfd, info)
*** 4317,4322 ****
--- 4319,4348 ----
        elf_elfheader (abfd)->e_flags |= EF_MIPS_CPIC;
      }
  
+   /* We'd carefully arranged the dynamic symbol indices, and then the
+      generic size_dynamic_sections renumbered them out from under us.
+      Rather than trying somehow to prevent the renumbering, just do
+      the sort again.  */
+ 
+   if (elf_hash_table (info)->dynobj)
+     {
+       bfd *dynobj;
+       asection *got;
+       struct mips_got_info *g;
+ 
+       if (!mips_elf_sort_hash_table (info, bfd_count_sections (abfd) + 1))
+         return false;
+ 
+       /* Make sure we didn't grow the global .got region.  */
+       dynobj = elf_hash_table (info)->dynobj;
+       got = bfd_get_section_by_name (dynobj, ".got");
+       g = (struct mips_got_info *) elf_section_data (got)->tdata;
+ 
+       BFD_ASSERT ((elf_hash_table (info)->dynsymcount
+ 		   - g->global_gotsym->dynindx)
+ 		  <= g->global_gotno);
+     }
+ 
    /* On IRIX5, we omit the .options section.  On IRIX6, however, we
       include it, even though we don't process it quite right.  (Some
       entries are supposed to be merged.)  Empirically, we seem to be
*************** mips_elf_sort_hash_table_f (h, data)
*** 5302,5312 ****
  
  /* Sort the dynamic symbol table so that symbols that need GOT entries
     appear towards the end.  This reduces the amount of GOT space
!    required.  */
  
  static boolean
! mips_elf_sort_hash_table (info)
       struct bfd_link_info *info;
  {
    struct mips_elf_hash_sort_data hsd;
    struct mips_got_info *g;
--- 5328,5342 ----
  
  /* Sort the dynamic symbol table so that symbols that need GOT entries
     appear towards the end.  This reduces the amount of GOT space
!    required.  MAX_LOCAL is used to set the number of local symbols
!    known to be in the dynamic symbol table.  During
!    mips_elf_size_dynamic_sections, this value is 1.  Afterward, the
!    section symbols are added and the count is higher.  */
  
  static boolean
! mips_elf_sort_hash_table (info, max_local)
       struct bfd_link_info *info;
+      unsigned long max_local;
  {
    struct mips_elf_hash_sort_data hsd;
    struct mips_got_info *g;
*************** mips_elf_sort_hash_table (info)
*** 5316,5322 ****
  
    hsd.low = NULL;
    hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount;
!   hsd.max_non_got_dynindx = 1;
    mips_elf_link_hash_traverse (((struct mips_elf_link_hash_table *) 
  				elf_hash_table (info)), 
  			       mips_elf_sort_hash_table_f, 
--- 5346,5352 ----
  
    hsd.low = NULL;
    hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount;
!   hsd.max_non_got_dynindx = max_local;
    mips_elf_link_hash_traverse (((struct mips_elf_link_hash_table *) 
  				elf_hash_table (info)), 
  			       mips_elf_sort_hash_table_f, 
*************** _bfd_mips_elf_size_dynamic_sections (out
*** 7602,7611 ****
   	     higher.  Therefore, it make sense to put those symbols
   	     that need GOT entries at the end of the symbol table.  We
   	     do that here.  */
!  	  if (!mips_elf_sort_hash_table (info))
   	    return false;
  
   	  i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx;
  	  s->_raw_size += i * MIPS_ELF_GOT_SIZE (dynobj);
  	}
        else if (strcmp (name, MIPS_ELF_STUB_SECTION_NAME (output_bfd)) == 0)
--- 7632,7642 ----
   	     higher.  Therefore, it make sense to put those symbols
   	     that need GOT entries at the end of the symbol table.  We
   	     do that here.  */
!  	  if (!mips_elf_sort_hash_table (info, 1))
   	    return false;
  
   	  i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx;
+ 	  g->global_gotno = i;
  	  s->_raw_size += i * MIPS_ELF_GOT_SIZE (dynobj);
  	}
        else if (strcmp (name, MIPS_ELF_STUB_SECTION_NAME (output_bfd)) == 0)

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~1999-07-14 17:04 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-07-12 18:05 .dynsym pain Richard Henderson
1999-07-12 20:37 ` Ian Lance Taylor
1999-07-13 18:20   ` Richard Henderson
1999-07-12 21:57 ` Mark Mitchell
1999-07-13 19:12   ` Richard Henderson
1999-07-13 22:42     ` Mark Mitchell
1999-07-14  0:20       ` Richard Henderson
1999-07-14  1:03         ` Mark Mitchell
1999-07-14  2:17           ` Richard Henderson
1999-07-14  8:35             ` Mark Mitchell
1999-07-14 17:04               ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).