From mboxrd@z Thu Jan 1 00:00:00 1970 From: Richard Henderson To: Mark Mitchell Cc: binutils@sourceware.cygnus.com Subject: Re: .dynsym pain Date: Wed, 14 Jul 1999 17:04:00 -0000 Message-id: <19990714142741.A8153@cygnus.com> References: <19990714000728.D7058@cygnus.com> <19990714010018W.mitchell@codesourcery.com> <19990714021747.B7300@cygnus.com> <19990714083849E.mitchell@codesourcery.com> X-SW-Source: 1999-q3/msg00207.html 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)