* elfxx-mips.c (mips_elf_count_got_entries): Delete.
	(mips_elf_check_recreate_got, mips_elf_recreate_got): Take a
	mips_elf_traverse_got_arg.  Count GOT entries.
	(mips_elf_resolve_final_got_entries): Take the bfd_link_info
	as argument.  Update after above changes.
	(mips_elf_merge_got, mips_elf_lay_out_got): Don't call
	mips_elf_count_got_entries.  Update the calls to
	mips_elf_resolve_final_got_entries.
This commit is contained in:
Richard Sandiford 2013-02-11 18:20:51 +00:00
parent 9ab066b4cf
commit 476366af69
2 changed files with 55 additions and 59 deletions

View File

@ -1,3 +1,14 @@
2013-02-11 Richard Sandiford <rdsandiford@googlemail.com>
* elfxx-mips.c (mips_elf_count_got_entries): Delete.
(mips_elf_check_recreate_got, mips_elf_recreate_got): Take a
mips_elf_traverse_got_arg. Count GOT entries.
(mips_elf_resolve_final_got_entries): Take the bfd_link_info
as argument. Update after above changes.
(mips_elf_merge_got, mips_elf_lay_out_got): Don't call
mips_elf_count_got_entries. Update the calls to
mips_elf_resolve_final_got_entries.
2013-02-11 Richard Sandiford <rdsandiford@googlemail.com> 2013-02-11 Richard Sandiford <rdsandiford@googlemail.com>
* elfxx-mips.c (mips_got_tls_type): New enum. * elfxx-mips.c (mips_got_tls_type): New enum.

View File

@ -2979,23 +2979,6 @@ mips_elf_count_got_entry (struct bfd_link_info *info,
g->global_gotno += 1; g->global_gotno += 1;
} }
/* A htab_traverse callback. Count the number of GOT entries and
TLS relocations required for the GOT entry in *ENTRYP. DATA points
to a mips_elf_traverse_got_arg structure. */
static int
mips_elf_count_got_entries (void **entryp, void *data)
{
struct mips_got_entry *entry;
struct mips_elf_traverse_got_arg *arg;
entry = (struct mips_got_entry *) *entryp;
arg = (struct mips_elf_traverse_got_arg *) data;
mips_elf_count_got_entry (arg->info, arg->g, entry);
return 1;
}
/* Output a simple dynamic relocation into SRELOC. */ /* Output a simple dynamic relocation into SRELOC. */
static void static void
@ -3861,17 +3844,19 @@ mips_elf_allocate_dynamic_relocations (bfd *abfd, struct bfd_link_info *info,
} }
} }
/* A htab_traverse callback for GOT entries. Set boolean *DATA to true /* A htab_traverse callback for GOT entries, with DATA pointing to a
if the GOT entry is for an indirect or warning symbol. */ mips_elf_traverse_got_arg structure. Count the number of GOT
entries and TLS relocs. Set DATA->value to true if we need
to resolve indirect or warning symbols and then recreate the GOT. */
static int static int
mips_elf_check_recreate_got (void **entryp, void *data) mips_elf_check_recreate_got (void **entryp, void *data)
{ {
struct mips_got_entry *entry; struct mips_got_entry *entry;
bfd_boolean *must_recreate; struct mips_elf_traverse_got_arg *arg;
entry = (struct mips_got_entry *) *entryp; entry = (struct mips_got_entry *) *entryp;
must_recreate = (bfd_boolean *) data; arg = (struct mips_elf_traverse_got_arg *) data;
if (entry->abfd != NULL && entry->symndx == -1) if (entry->abfd != NULL && entry->symndx == -1)
{ {
struct mips_elf_link_hash_entry *h; struct mips_elf_link_hash_entry *h;
@ -3880,27 +3865,28 @@ mips_elf_check_recreate_got (void **entryp, void *data)
if (h->root.root.type == bfd_link_hash_indirect if (h->root.root.type == bfd_link_hash_indirect
|| h->root.root.type == bfd_link_hash_warning) || h->root.root.type == bfd_link_hash_warning)
{ {
*must_recreate = TRUE; arg->value = TRUE;
return 0; return 0;
} }
} }
mips_elf_count_got_entry (arg->info, arg->g, entry);
return 1; return 1;
} }
/* A htab_traverse callback for GOT entries. Add all entries to /* A htab_traverse callback for GOT entries, with DATA pointing to a
hash table *DATA, converting entries for indirect and warning mips_elf_traverse_got_arg structure. Add all entries to DATA->g,
symbols into entries for the target symbol. Set *DATA to null converting entries for indirect and warning symbols into entries
on error. */ for the target symbol. Set DATA->g to null on error. */
static int static int
mips_elf_recreate_got (void **entryp, void *data) mips_elf_recreate_got (void **entryp, void *data)
{ {
htab_t *new_got;
struct mips_got_entry new_entry, *entry; struct mips_got_entry new_entry, *entry;
struct mips_elf_traverse_got_arg *arg;
void **slot; void **slot;
new_got = (htab_t *) data;
entry = (struct mips_got_entry *) *entryp; entry = (struct mips_got_entry *) *entryp;
arg = (struct mips_elf_traverse_got_arg *) data;
if (entry->abfd != NULL if (entry->abfd != NULL
&& entry->symndx == -1 && entry->symndx == -1
&& (entry->d.h->root.root.type == bfd_link_hash_indirect && (entry->d.h->root.root.type == bfd_link_hash_indirect
@ -3920,10 +3906,10 @@ mips_elf_recreate_got (void **entryp, void *data)
|| h->root.root.type == bfd_link_hash_warning); || h->root.root.type == bfd_link_hash_warning);
entry->d.h = h; entry->d.h = h;
} }
slot = htab_find_slot (*new_got, entry, INSERT); slot = htab_find_slot (arg->g->got_entries, entry, INSERT);
if (slot == NULL) if (slot == NULL)
{ {
*new_got = NULL; arg->g = NULL;
return 0; return 0;
} }
if (*slot == NULL) if (*slot == NULL)
@ -3933,12 +3919,13 @@ mips_elf_recreate_got (void **entryp, void *data)
entry = bfd_alloc (entry->abfd, sizeof (*entry)); entry = bfd_alloc (entry->abfd, sizeof (*entry));
if (!entry) if (!entry)
{ {
*new_got = NULL; arg->g = NULL;
return 0; return 0;
} }
*entry = new_entry; *entry = new_entry;
} }
*slot = entry; *slot = entry;
mips_elf_count_got_entry (arg->info, arg->g, entry);
} }
return 1; return 1;
} }
@ -3947,24 +3934,32 @@ mips_elf_recreate_got (void **entryp, void *data)
replace them with entries for the target symbol. */ replace them with entries for the target symbol. */
static bfd_boolean static bfd_boolean
mips_elf_resolve_final_got_entries (struct mips_got_info *g) mips_elf_resolve_final_got_entries (struct bfd_link_info *info,
struct mips_got_info *g)
{ {
bfd_boolean must_recreate; struct mips_elf_traverse_got_arg tga;
htab_t new_got; struct mips_got_info oldg;
must_recreate = FALSE; oldg = *g;
htab_traverse (g->got_entries, mips_elf_check_recreate_got, &must_recreate);
if (must_recreate) tga.info = info;
tga.g = g;
tga.value = FALSE;
htab_traverse (g->got_entries, mips_elf_check_recreate_got, &tga);
if (tga.value)
{ {
new_got = htab_create (htab_size (g->got_entries), *g = oldg;
mips_elf_got_entry_hash, g->got_entries = htab_create (htab_size (oldg.got_entries),
mips_elf_got_entry_eq, NULL); mips_elf_got_entry_hash,
htab_traverse (g->got_entries, mips_elf_recreate_got, &new_got); mips_elf_got_entry_eq, NULL);
if (new_got == NULL) if (!g->got_entries)
return FALSE; return FALSE;
htab_delete (g->got_entries); htab_traverse (oldg.got_entries, mips_elf_recreate_got, &tga);
g->got_entries = new_got; if (!tga.g)
return FALSE;
htab_delete (oldg.got_entries);
} }
return TRUE; return TRUE;
} }
@ -4134,17 +4129,12 @@ static bfd_boolean
mips_elf_merge_got (bfd *abfd, struct mips_got_info *g, mips_elf_merge_got (bfd *abfd, struct mips_got_info *g,
struct mips_elf_got_per_bfd_arg *arg) struct mips_elf_got_per_bfd_arg *arg)
{ {
struct mips_elf_traverse_got_arg tga;
unsigned int estimate; unsigned int estimate;
int result; int result;
if (!mips_elf_resolve_final_got_entries (g)) if (!mips_elf_resolve_final_got_entries (arg->info, g))
return FALSE; return FALSE;
tga.info = arg->info;
tga.g = g;
htab_traverse (g->got_entries, mips_elf_count_got_entries, &tga);
/* Work out the number of page, local and TLS entries. */ /* Work out the number of page, local and TLS entries. */
estimate = arg->max_pages; estimate = arg->max_pages;
if (estimate > g->page_gotno) if (estimate > g->page_gotno)
@ -8608,11 +8598,6 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
g->local_gotno += htab->reserved_gotno; g->local_gotno += htab->reserved_gotno;
g->assigned_gotno = htab->reserved_gotno; g->assigned_gotno = htab->reserved_gotno;
/* Replace entries for indirect and warning symbols with entries for
the target symbol. */
if (!mips_elf_resolve_final_got_entries (g))
return FALSE;
/* Decide which symbols need to go in the global part of the GOT and /* Decide which symbols need to go in the global part of the GOT and
count the number of reloc-only GOT symbols. */ count the number of reloc-only GOT symbols. */
mips_elf_link_hash_traverse (htab, mips_elf_count_got_symbols, info); mips_elf_link_hash_traverse (htab, mips_elf_count_got_symbols, info);
@ -8652,10 +8637,10 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
g->local_gotno += page_gotno; g->local_gotno += page_gotno;
/* Count the number of GOT entries and TLS relocs. */ /* Replace entries for indirect and warning symbols with entries for
tga.info = info; the target symbol. Count the number of GOT entries and TLS relocs. */
tga.g = g; if (!mips_elf_resolve_final_got_entries (info, g))
htab_traverse (g->got_entries, mips_elf_count_got_entries, &tga); return FALSE;
s->size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd); s->size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
s->size += g->global_gotno * MIPS_ELF_GOT_SIZE (output_bfd); s->size += g->global_gotno * MIPS_ELF_GOT_SIZE (output_bfd);