diff --git a/bfd/ChangeLog b/bfd/ChangeLog index d3b2d8a129..99e5e28c84 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2013-02-11 Richard Sandiford + + * 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 * elfxx-mips.c (mips_got_tls_type): New enum. diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index e4ba822849..00757ff676 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -2979,23 +2979,6 @@ mips_elf_count_got_entry (struct bfd_link_info *info, 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. */ 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 - if the GOT entry is for an indirect or warning symbol. */ +/* A htab_traverse callback for GOT entries, with DATA pointing to a + 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 mips_elf_check_recreate_got (void **entryp, void *data) { struct mips_got_entry *entry; - bfd_boolean *must_recreate; + struct mips_elf_traverse_got_arg *arg; 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) { 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 || h->root.root.type == bfd_link_hash_warning) { - *must_recreate = TRUE; + arg->value = TRUE; return 0; } } + mips_elf_count_got_entry (arg->info, arg->g, entry); return 1; } -/* A htab_traverse callback for GOT entries. Add all entries to - hash table *DATA, converting entries for indirect and warning - symbols into entries for the target symbol. Set *DATA to null - on error. */ +/* A htab_traverse callback for GOT entries, with DATA pointing to a + mips_elf_traverse_got_arg structure. Add all entries to DATA->g, + converting entries for indirect and warning symbols into entries + for the target symbol. Set DATA->g to null on error. */ static int mips_elf_recreate_got (void **entryp, void *data) { - htab_t *new_got; struct mips_got_entry new_entry, *entry; + struct mips_elf_traverse_got_arg *arg; void **slot; - new_got = (htab_t *) data; entry = (struct mips_got_entry *) *entryp; + arg = (struct mips_elf_traverse_got_arg *) data; if (entry->abfd != NULL && entry->symndx == -1 && (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); 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) { - *new_got = NULL; + arg->g = NULL; return 0; } if (*slot == NULL) @@ -3933,12 +3919,13 @@ mips_elf_recreate_got (void **entryp, void *data) entry = bfd_alloc (entry->abfd, sizeof (*entry)); if (!entry) { - *new_got = NULL; + arg->g = NULL; return 0; } *entry = new_entry; } *slot = entry; + mips_elf_count_got_entry (arg->info, arg->g, entry); } return 1; } @@ -3947,24 +3934,32 @@ mips_elf_recreate_got (void **entryp, void *data) replace them with entries for the target symbol. */ 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; - htab_t new_got; + struct mips_elf_traverse_got_arg tga; + struct mips_got_info oldg; - must_recreate = FALSE; - htab_traverse (g->got_entries, mips_elf_check_recreate_got, &must_recreate); - if (must_recreate) + oldg = *g; + + 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), - mips_elf_got_entry_hash, - mips_elf_got_entry_eq, NULL); - htab_traverse (g->got_entries, mips_elf_recreate_got, &new_got); - if (new_got == NULL) + *g = oldg; + g->got_entries = htab_create (htab_size (oldg.got_entries), + mips_elf_got_entry_hash, + mips_elf_got_entry_eq, NULL); + if (!g->got_entries) return FALSE; - htab_delete (g->got_entries); - g->got_entries = new_got; + htab_traverse (oldg.got_entries, mips_elf_recreate_got, &tga); + if (!tga.g) + return FALSE; + + htab_delete (oldg.got_entries); } return TRUE; } @@ -4134,17 +4129,12 @@ static bfd_boolean mips_elf_merge_got (bfd *abfd, struct mips_got_info *g, struct mips_elf_got_per_bfd_arg *arg) { - struct mips_elf_traverse_got_arg tga; unsigned int estimate; int result; - if (!mips_elf_resolve_final_got_entries (g)) + if (!mips_elf_resolve_final_got_entries (arg->info, g)) 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. */ estimate = arg->max_pages; 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->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 count the number of reloc-only GOT symbols. */ 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; - /* Count the number of GOT entries and TLS relocs. */ - tga.info = info; - tga.g = g; - htab_traverse (g->got_entries, mips_elf_count_got_entries, &tga); + /* Replace entries for indirect and warning symbols with entries for + the target symbol. Count the number of GOT entries and TLS relocs. */ + if (!mips_elf_resolve_final_got_entries (info, g)) + return FALSE; s->size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd); s->size += g->global_gotno * MIPS_ELF_GOT_SIZE (output_bfd);