summaryrefslogtreecommitdiff
path: root/bfd/elf64-alpha.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2007-04-10 18:00:26 +0000
committerRichard Henderson <rth@redhat.com>2007-04-10 18:00:26 +0000
commit4a828aab99fb02f80d97ebf005eb3daf933a37a3 (patch)
treeff1af32241e40480fd52822c3bee44185264d9e5 /bfd/elf64-alpha.c
parenta489f7899482002eac7956dfcd923dc0688b6ac0 (diff)
downloadbinutils-4a828aab99fb02f80d97ebf005eb3daf933a37a3.tar.gz
binutils-4a828aab99fb02f80d97ebf005eb3daf933a37a3.tar.bz2
binutils-4a828aab99fb02f80d97ebf005eb3daf933a37a3.zip
bfd/
* elf64-alpha.c (struct alpha_elf_link_hash_table): Add relax_trip. (elf64_alpha_size_got_sections): Remove unused something_changed local. (elf64_alpha_size_plt_section): Return void. (elf64_alpha_size_rela_got_section): Likewise. (elf64_alpha_relax_section): Only regenerate got+plt if the relax_trip counter has changed. include/ * bfdlink.h (struct bfd_link_info): Add relax_trip. ld/ * ldlang.c (relax_sections): Initialize and increment link_info.relax_trip.
Diffstat (limited to 'bfd/elf64-alpha.c')
-rw-r--r--bfd/elf64-alpha.c57
1 files changed, 29 insertions, 28 deletions
diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index 89475793886..76535623536 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -184,6 +184,10 @@ struct alpha_elf_link_hash_table
/* The head of a list of .got subsections linked through
alpha_elf_tdata(abfd)->got_link_next. */
bfd *got_list;
+
+ /* The most recent relax pass that we've seen. The GOTs
+ should be regenerated if this doesn't match. */
+ int relax_trip;
};
/* Look up an entry in a Alpha ELF linker hash table. */
@@ -2375,7 +2379,6 @@ static bfd_boolean
elf64_alpha_size_got_sections (struct bfd_link_info *info)
{
bfd *i, *got_list, *cur_got_obj = NULL;
- int something_changed = 0;
got_list = alpha_elf_hash_table (info)->got_list;
@@ -2413,9 +2416,6 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info)
return TRUE;
alpha_elf_hash_table (info)->got_list = got_list;
-
- /* Force got offsets to be recalculated. */
- something_changed = 1;
}
cur_got_obj = got_list;
@@ -2429,8 +2429,6 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info)
alpha_elf_tdata(i)->got->size = 0;
i = alpha_elf_tdata(i)->got_link_next;
alpha_elf_tdata(cur_got_obj)->got_link_next = i;
-
- something_changed = 1;
}
else
{
@@ -2441,8 +2439,7 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info)
/* Once the gots have been merged, fill in the got offsets for
everything therein. */
- if (1 || something_changed)
- elf64_alpha_calc_got_offsets (info);
+ elf64_alpha_calc_got_offsets (info);
return TRUE;
}
@@ -2477,10 +2474,10 @@ elf64_alpha_size_plt_section_1 (struct alpha_elf_link_hash_entry *h, PTR data)
return TRUE;
}
-/* Called from relax_section to rebuild the PLT in light of
- potential changes in the function's status. */
+/* Called from relax_section to rebuild the PLT in light of potential changes
+ in the function's status. */
-static bfd_boolean
+static void
elf64_alpha_size_plt_section (struct bfd_link_info *info)
{
asection *splt, *spltrel, *sgotplt;
@@ -2490,7 +2487,7 @@ elf64_alpha_size_plt_section (struct bfd_link_info *info)
dynobj = elf_hash_table(info)->dynobj;
splt = bfd_get_section_by_name (dynobj, ".plt");
if (splt == NULL)
- return TRUE;
+ return;
splt->size = 0;
@@ -2499,6 +2496,7 @@ elf64_alpha_size_plt_section (struct bfd_link_info *info)
/* Every plt entry requires a JMP_SLOT relocation. */
spltrel = bfd_get_section_by_name (dynobj, ".rela.plt");
+ entries = 0;
if (splt->size)
{
if (elf64_alpha_use_secureplt)
@@ -2506,8 +2504,6 @@ elf64_alpha_size_plt_section (struct bfd_link_info *info)
else
entries = (splt->size - OLD_PLT_HEADER_SIZE) / OLD_PLT_ENTRY_SIZE;
}
- else
- entries = 0;
spltrel->size = entries * sizeof (Elf64_External_Rela);
/* When using the secureplt, we need two words somewhere in the data
@@ -2518,8 +2514,6 @@ elf64_alpha_size_plt_section (struct bfd_link_info *info)
sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
sgotplt->size = entries ? 16 : 0;
}
-
- return TRUE;
}
static bfd_boolean
@@ -2690,7 +2684,7 @@ elf64_alpha_size_rela_got_1 (struct alpha_elf_link_hash_entry *h,
/* Set the sizes of the dynamic relocation sections. */
-static bfd_boolean
+static void
elf64_alpha_size_rela_got_section (struct bfd_link_info *info)
{
unsigned long entries;
@@ -2729,15 +2723,13 @@ elf64_alpha_size_rela_got_section (struct bfd_link_info *info)
if (!srel)
{
BFD_ASSERT (entries == 0);
- return TRUE;
+ return;
}
srel->size = sizeof (Elf64_External_Rela) * entries;
/* Now do the non-local symbols. */
alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
elf64_alpha_size_rela_got_1, info);
-
- return TRUE;
}
/* Set the sizes of the dynamic sections. */
@@ -3609,7 +3601,7 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
struct alpha_elf_got_entry **local_got_entries;
struct alpha_relax_info info;
- /* We are not currently changing any sizes, so only one pass. */
+ /* There's nothing to change, yet. */
*again = FALSE;
if (link_info->relocatable
@@ -3618,6 +3610,22 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
|| sec->reloc_count == 0)
return TRUE;
+ /* Make sure our GOT and PLT tables are up-to-date. */
+ if (alpha_elf_hash_table(link_info)->relax_trip != link_info->relax_trip)
+ {
+ alpha_elf_hash_table(link_info)->relax_trip = link_info->relax_trip;
+
+ /* This should never fail after the initial round, since the only
+ error is GOT overflow, and relaxation only shrinks the table. */
+ if (!elf64_alpha_size_got_sections (link_info))
+ abort ();
+ if (elf_hash_table (link_info)->dynamic_sections_created)
+ {
+ elf64_alpha_size_plt_section (link_info);
+ elf64_alpha_size_rela_got_section (link_info);
+ }
+ }
+
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
@@ -3827,13 +3835,6 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
}
}
- if (!elf64_alpha_size_plt_section (link_info))
- return FALSE;
- if (!elf64_alpha_size_got_sections (link_info))
- return FALSE;
- if (!elf64_alpha_size_rela_got_section (link_info))
- return FALSE;
-
if (isymbuf != NULL
&& symtab_hdr->contents != (unsigned char *) isymbuf)
{