.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