aboutsummaryrefslogtreecommitdiff
path: root/bfd/elfxx-mips.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elfxx-mips.c')
-rw-r--r--bfd/elfxx-mips.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 1b93a95..c184d2e 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -315,7 +315,10 @@ struct mips_elf_hash_sort_data
with a GOT entry that is not referenced (e.g., a dynamic symbol
with dynamic relocations pointing to it from non-primary GOTs). */
bfd_size_type max_unref_got_dynindx;
- /* The greatest dynamic symbol table index not corresponding to a
+ /* The greatest dynamic symbol table index corresponding to a local
+ symbol. */
+ bfd_size_type max_local_dynindx;
+ /* The greatest dynamic symbol table index corresponding to an external
symbol without a GOT entry. */
bfd_size_type max_non_got_dynindx;
};
@@ -3846,11 +3849,15 @@ mips_elf_sort_hash_table (bfd *abfd, struct bfd_link_info *info)
hsd.max_unref_got_dynindx
= hsd.min_got_dynindx
= (htab->root.dynsymcount - g->reloc_only_gotno);
- hsd.max_non_got_dynindx = count_section_dynsyms (abfd, info) + 1;
+ /* Add 1 to local symbol indices to account for the mandatory NULL entry
+ at the head of the table; see `_bfd_elf_link_renumber_dynsyms'. */
+ hsd.max_local_dynindx = count_section_dynsyms (abfd, info) + 1;
+ hsd.max_non_got_dynindx = htab->root.local_dynsymcount + 1;
mips_elf_link_hash_traverse (htab, mips_elf_sort_hash_table_f, &hsd);
/* There should have been enough room in the symbol table to
accommodate both the GOT and non-GOT symbols. */
+ BFD_ASSERT (hsd.max_local_dynindx <= htab->root.local_dynsymcount + 1);
BFD_ASSERT (hsd.max_non_got_dynindx <= hsd.min_got_dynindx);
BFD_ASSERT (hsd.max_unref_got_dynindx == htab->root.dynsymcount);
BFD_ASSERT (htab->root.dynsymcount - hsd.min_got_dynindx == g->global_gotno);
@@ -3879,7 +3886,10 @@ mips_elf_sort_hash_table_f (struct mips_elf_link_hash_entry *h, void *data)
switch (h->global_got_area)
{
case GGA_NONE:
- h->root.dynindx = hsd->max_non_got_dynindx++;
+ if (h->root.forced_local)
+ h->root.dynindx = hsd->max_local_dynindx++;
+ else
+ h->root.dynindx = hsd->max_non_got_dynindx++;
break;
case GGA_NORMAL: