.dynsym pain

Richard Henderson rth@cygnus.com
Wed Jul 14 17:04:00 GMT 1999


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)


More information about the Binutils mailing list