diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2008-08-07 20:01:14 +0000 |
---|---|---|
committer | Richard Sandiford <rdsandiford@googlemail.com> | 2008-08-07 20:01:14 +0000 |
commit | 23cc69b6636ef7c99fd9b1e076d683e1a96283df (patch) | |
tree | 340efdd865bb90a3d8334af47651ded197ef859e /bfd/elfxx-mips.c | |
parent | bd8aab1c2944a603af1182db1d81cfbd832d162a (diff) | |
download | gdb-23cc69b6636ef7c99fd9b1e076d683e1a96283df.zip gdb-23cc69b6636ef7c99fd9b1e076d683e1a96283df.tar.gz gdb-23cc69b6636ef7c99fd9b1e076d683e1a96283df.tar.bz2 |
bfd/
* elfxx-mips.c (mips_got_info): Add a "reloc_only_gotno" field.
(mips_elf_got_section): Delete.
(mips_elf_sort_hash_table): Use g->reloc_only_gotno to decide
how many reloc-only entries there are.
(mips_elf_count_got_symbols): Adjust g->reloc_only_gotno as
well as g->global_gotno.
(mips_elf_make_got_per_bfd): Initialize reloc_only_gotno.
(mips_elf_multi_got): Likewise. Use gg->reloc_only_gotno
rather than gg->assigned_gotno to store the number of
reloc-only GOT entries.
(mips_elf_create_got_section): Remove the MAYBE_EXCLUDE parameter.
Initialize reloc_only_gotno.
(mips_elf_calculate_relocation): Check htab->got_info instead of
dynobj when deciding whether to call mips_elf_adjust_gp,
(_bfd_mips_elf_create_dynamic_sections): Adjust the call
to mips_elf_create_got_section.
(mips_elf_record_relocs): Likewise. Remove redundant
"dynobj == NULL" code. Do not use mips_elf_create_got_section
or mips_elf_record_global_got_symbol for R_MIPS_32, R_MIPS_REL32
and R_MIPS_64; limit global_got_area to GGA_RELOC_ONLY instead.
(_bfd_mips_elf_finish_dynamic_symbol): Use htab->sgot instead
of mips_elf_got_section.
(_bfd_mips_vxworks_finish_dynamic_symbol): Likewise.
(_bfd_mips_elf_finish_dynamic_sections): Likewise.
Move the initial assignment of G to the block that uses it;
it is used for an unrelated purpose later.
ld/testsuite/
* ld-mips-elf/tls-hidden4.got, ld-mips-elf/tls-hidden4.r: We have
removed an unused GOT entry that was allocated for the R_MIPS_32
relocation against "undef", so adjust addresses down by 4 bytes.
* ld-mips-elf/got-dump-1.d, ld-mips-elf/got-dump-2.d: We have
changed the order of the GOT entries so that reloc-only ones
come last. "undef" is only referred to by dynamic relocations,
so it now comes after "glob".
* ld-mips-elf/mips16-pic-2.dd, ld-mips-elf/mips16-pic-2.gd,
ld-mips-elf/mips16-pic-2.nd, ld-mips-elf/mips16-pic-2.rd: We have
removed two unused local GOT entries that were originally created
as global entries for the hidden symbols "used2" and "used3".
"used4" and "used5" are only referred to by relocations, so they
now come after "used6" and "used7".
Diffstat (limited to 'bfd/elfxx-mips.c')
-rw-r--r-- | bfd/elfxx-mips.c | 95 |
1 files changed, 35 insertions, 60 deletions
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 297c361..36c94d5 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -145,6 +145,8 @@ struct mips_got_info struct elf_link_hash_entry *global_gotsym; /* The number of global .got entries. */ unsigned int global_gotno; + /* The number of global .got entries that are in the GGA_RELOC_ONLY area. */ + unsigned int reloc_only_gotno; /* The number of .got slots used for TLS. */ unsigned int tls_gotno; /* The first unused TLS .got entry. Used only during @@ -2280,19 +2282,6 @@ mips_elf_rel_dyn_section (struct bfd_link_info *info, bfd_boolean create_p) return sreloc; } -/* Returns the GOT section, if it hasn't been excluded. */ - -static asection * -mips_elf_got_section (struct bfd_link_info *info) -{ - struct mips_elf_link_hash_table *htab; - - htab = mips_elf_hash_table (info); - if (htab->sgot == NULL || (htab->sgot->flags & SEC_EXCLUDE) != 0) - return NULL; - return htab->sgot; -} - /* Count the number of relocations needed for a TLS GOT entry, with access types from TLS_TYPE, and symbol H (or a local symbol if H is NULL). */ @@ -2423,12 +2412,14 @@ mips_elf_initialize_tls_slots (bfd *abfd, bfd_vma got_offset, struct mips_elf_link_hash_entry *h, bfd_vma value) { + struct mips_elf_link_hash_table *htab; int indx; asection *sreloc, *sgot; bfd_vma offset, offset2; bfd_boolean need_relocs = FALSE; - sgot = mips_elf_got_section (info); + htab = mips_elf_hash_table (info); + sgot = htab->sgot; indx = 0; if (h != NULL) @@ -2954,16 +2945,9 @@ mips_elf_sort_hash_table (bfd *abfd, struct bfd_link_info *info) return TRUE; hsd.low = NULL; - hsd.max_unref_got_dynindx = - hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount - /* In the multi-got case, assigned_gotno of the master got_info - indicate the number of entries that aren't referenced in the - primary GOT, but that must have entries because there are - dynamic relocations that reference it. Since they aren't - referenced, we move them to the end of the GOT, so that they - don't prevent other entries that are referenced from getting - too large offsets. */ - - (g->next ? g->assigned_gotno : 0); + hsd.max_unref_got_dynindx + = hsd.min_got_dynindx + = (elf_hash_table (info)->dynsymcount - g->reloc_only_gotno); hsd.max_non_got_dynindx = count_section_dynsyms (abfd, info) + 1; mips_elf_link_hash_traverse (((struct mips_elf_link_hash_table *) elf_hash_table (info)), @@ -3413,7 +3397,11 @@ mips_elf_count_got_symbols (struct mips_elf_link_hash_entry *h, void *data) h->global_got_area = GGA_NONE; } else - g->global_gotno++; + { + g->global_gotno++; + if (h->global_got_area == GGA_RELOC_ONLY) + g->reloc_only_gotno++; + } } return 1; } @@ -3492,6 +3480,7 @@ mips_elf_get_got_for_bfd (struct htab *bfd2got, bfd *output_bfd, g->global_gotsym = NULL; g->global_gotno = 0; + g->reloc_only_gotno = 0; g->local_gotno = 0; g->page_gotno = 0; g->assigned_gotno = -1; @@ -3912,6 +3901,7 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info, g->next->global_gotsym = NULL; g->next->global_gotno = 0; + g->next->reloc_only_gotno = 0; g->next->local_gotno = 0; g->next->page_gotno = 0; g->next->tls_gotno = 0; @@ -3964,7 +3954,7 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info, /* Every symbol that is referenced in a dynamic relocation must be present in the primary GOT, so arrange for them to appear after those that are actually referenced. */ - gg->assigned_gotno = gg->global_gotno - g->global_gotno; + gg->reloc_only_gotno = gg->global_gotno - g->global_gotno; g->global_gotno = gg->global_gotno; set_got_offset_arg.g = NULL; @@ -4224,8 +4214,7 @@ mips_elf_create_compact_rel_section /* Create the .got section to hold the global offset table. */ static bfd_boolean -mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info, - bfd_boolean maybe_exclude) +mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) { flagword flags; register asection *s; @@ -4238,20 +4227,12 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info, htab = mips_elf_hash_table (info); /* This function may be called more than once. */ - s = htab->sgot; - if (s) - { - if (! maybe_exclude) - s->flags &= ~SEC_EXCLUDE; - return TRUE; - } + if (htab->sgot) + return TRUE; flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); - if (maybe_exclude) - flags |= SEC_EXCLUDE; - /* We have to use an alignment of 2**4 here because this is hardcoded in the function stub generation and in the linker script. */ s = bfd_make_section_with_flags (abfd, ".got", flags); @@ -4285,6 +4266,7 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info, return FALSE; g->global_gotsym = NULL; g->global_gotno = 0; + g->reloc_only_gotno = 0; g->tls_gotno = 0; g->local_gotno = MIPS_RESERVED_GOTNO (info); g->page_gotno = 0; @@ -4642,7 +4624,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, gp0 = _bfd_get_gp_value (input_bfd); gp = _bfd_get_gp_value (abfd); - if (dynobj) + if (htab->got_info) gp += mips_elf_adjust_gp (abfd, htab->got_info, input_bfd); if (gnu_local_gp_p) @@ -6417,7 +6399,7 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) } /* We need to create .got section. */ - if (! mips_elf_create_got_section (abfd, info, FALSE)) + if (!mips_elf_create_got_section (abfd, info)) return FALSE; if (! mips_elf_rel_dyn_section (info, TRUE)) @@ -7039,7 +7021,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_MIPS_TLS_LDM: if (dynobj == NULL) elf_hash_table (info)->dynobj = dynobj = abfd; - if (! mips_elf_create_got_section (dynobj, info, FALSE)) + if (!mips_elf_create_got_section (dynobj, info)) return FALSE; if (htab->is_vxworks && !info->shared) { @@ -7301,12 +7283,11 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, between global GOT entries and .dynsym entries. */ if (h != NULL && !htab->is_vxworks) { - if (dynobj == NULL) - elf_hash_table (info)->dynobj = dynobj = abfd; - if (! mips_elf_create_got_section (dynobj, info, TRUE)) - return FALSE; - if (!mips_elf_record_global_got_symbol (h, abfd, info, 0)) - return FALSE; + struct mips_elf_link_hash_entry *hmips; + + hmips = (struct mips_elf_link_hash_entry *) h; + if (hmips->global_got_area > GGA_RELOC_ONLY) + hmips->global_got_area = GGA_RELOC_ONLY; } } @@ -8818,8 +8799,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, BFD_ASSERT (h->dynindx != -1 || h->forced_local); - sgot = mips_elf_got_section (info); - BFD_ASSERT (sgot != NULL); + sgot = htab->sgot; g = htab->got_info; BFD_ASSERT (g != NULL); @@ -9089,8 +9069,7 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd, BFD_ASSERT (h->dynindx != -1 || h->forced_local); - sgot = mips_elf_got_section (info); - BFD_ASSERT (sgot != NULL); + sgot = htab->sgot; g = htab->got_info; BFD_ASSERT (g != NULL); @@ -9252,15 +9231,8 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); - sgot = mips_elf_got_section (info); - if (sgot == NULL) - gg = g = NULL; - else - { - gg = htab->got_info; - g = mips_elf_got_for_ibfd (gg, output_bfd); - BFD_ASSERT (g != NULL); - } + sgot = htab->sgot; + gg = htab->got_info; if (elf_hash_table (info)->dynamic_sections_created) { @@ -9268,6 +9240,9 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, int dyn_to_skip = 0, dyn_skipped = 0; BFD_ASSERT (sdyn != NULL); + BFD_ASSERT (gg != NULL); + + g = mips_elf_got_for_ibfd (gg, output_bfd); BFD_ASSERT (g != NULL); for (b = sdyn->contents; |