aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elf64-ppc.c98
2 files changed, 60 insertions, 45 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 55cfb10..4499f79 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,10 @@
+2007-10-23 Alan Modra <amodra@bigpond.net.au>
+
+ * elf64-ppc.c (ppc_build_one_stub): Don't duplicate relocs
+ emitted for ".brlt" entries.
+ (toc_adjusting_stub_needed): Don't treat ".fixup" specially here..
+ (ppc64_elf_next_input_section): ..instead do so here.
+
2007-10-19 Nick Clifton <nickc@redhat.com>
* config.bfd: Recognise am34-linux-gnu target.
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index a1c7d9b..b25ca3a 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -8387,49 +8387,57 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
bfd_put_64 (htab->brlt->owner, off,
htab->brlt->contents + br_entry->offset);
- if (htab->relbrlt != NULL)
- {
- /* Create a reloc for the branch lookup table entry. */
- Elf_Internal_Rela rela;
- bfd_byte *rl;
-
- rela.r_offset = (br_entry->offset
- + htab->brlt->output_offset
- + htab->brlt->output_section->vma);
- rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
- rela.r_addend = off;
-
- rl = htab->relbrlt->contents;
- rl += htab->relbrlt->reloc_count++ * sizeof (Elf64_External_Rela);
- bfd_elf64_swap_reloca_out (htab->relbrlt->owner, &rela, rl);
- }
- else if (info->emitrelocations)
+ if (br_entry->iter == htab->stub_iteration)
{
- Elf_Internal_Rela *relocs, *r;
- struct bfd_elf_section_data *elfsec_data;
+ br_entry->iter = 0;
- elfsec_data = elf_section_data (htab->brlt);
- relocs = elfsec_data->relocs;
- if (relocs == NULL)
+ if (htab->relbrlt != NULL)
{
- bfd_size_type relsize;
- relsize = htab->brlt->reloc_count * sizeof (*relocs);
- relocs = bfd_alloc (htab->brlt->owner, relsize);
+ /* Create a reloc for the branch lookup table entry. */
+ Elf_Internal_Rela rela;
+ bfd_byte *rl;
+
+ rela.r_offset = (br_entry->offset
+ + htab->brlt->output_offset
+ + htab->brlt->output_section->vma);
+ rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
+ rela.r_addend = off;
+
+ rl = htab->relbrlt->contents;
+ rl += (htab->relbrlt->reloc_count++
+ * sizeof (Elf64_External_Rela));
+ bfd_elf64_swap_reloca_out (htab->relbrlt->owner, &rela, rl);
+ }
+ else if (info->emitrelocations)
+ {
+ Elf_Internal_Rela *relocs, *r;
+ struct bfd_elf_section_data *elfsec_data;
+
+ elfsec_data = elf_section_data (htab->brlt);
+ relocs = elfsec_data->relocs;
if (relocs == NULL)
- return FALSE;
- elfsec_data->relocs = relocs;
- elfsec_data->rel_hdr.sh_size = (stub_entry->stub_sec->reloc_count
- * sizeof (Elf64_External_Rela));
- elfsec_data->rel_hdr.sh_entsize = sizeof (Elf64_External_Rela);
- htab->brlt->reloc_count = 0;
+ {
+ bfd_size_type relsize;
+ relsize = htab->brlt->reloc_count * sizeof (*relocs);
+ relocs = bfd_alloc (htab->brlt->owner, relsize);
+ if (relocs == NULL)
+ return FALSE;
+ elfsec_data->relocs = relocs;
+ elfsec_data->rel_hdr.sh_size
+ = (stub_entry->stub_sec->reloc_count
+ * sizeof (Elf64_External_Rela));
+ elfsec_data->rel_hdr.sh_entsize
+ = sizeof (Elf64_External_Rela);
+ htab->brlt->reloc_count = 0;
+ }
+ r = relocs + htab->brlt->reloc_count;
+ htab->brlt->reloc_count += 1;
+ r->r_offset = (br_entry->offset
+ + htab->brlt->output_offset
+ + htab->brlt->output_section->vma);
+ r->r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
+ r->r_addend = off;
}
- r = relocs + htab->brlt->reloc_count;
- htab->brlt->reloc_count += 1;
- r->r_offset = (br_entry->offset
- + htab->brlt->output_offset
- + htab->brlt->output_section->vma);
- r->r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
- r->r_addend = off;
}
off = (br_entry->offset
@@ -8865,11 +8873,6 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
if (isec->output_section == NULL)
return 0;
- /* Hack for linux kernel. .fixup contains branches, but only back to
- the function that hit an exception. */
- if (strcmp (isec->name, ".fixup") == 0)
- return 0;
-
if (isec->reloc_count == 0)
return 0;
@@ -9074,8 +9077,13 @@ ppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec)
/* If a code section has a function that uses the TOC then we need
to use the right TOC (obviously). Also, make sure that .opd gets
the correct TOC value for R_PPC64_TOC relocs that don't have or
- can't find their function symbol (shouldn't ever happen now). */
- if (isec->has_toc_reloc || (isec->flags & SEC_CODE) == 0)
+ can't find their function symbol (shouldn't ever happen now).
+ Also specially treat .fixup for the linux kernel. .fixup
+ contains branches, but only back to the function that hit an
+ exception. */
+ if (isec->has_toc_reloc
+ || (isec->flags & SEC_CODE) == 0
+ || strcmp (isec->name, ".fixup") == 0)
{
if (elf_gp (isec->owner) != 0)
htab->toc_curr = elf_gp (isec->owner);