aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-ppc.c
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2009-01-26 15:27:04 +0000
committerNathan Sidwell <nathan@codesourcery.com>2009-01-26 15:27:04 +0000
commit9bc4e62bdc0fdb16a98730b9bc038b2cea6b39e4 (patch)
treeacc48d95e222d78831fdf4341e6e213f035ea85c /bfd/elf32-ppc.c
parent02b0b1aa7702634955c7972e33403e1d37ed6602 (diff)
downloadfsf-binutils-gdb-9bc4e62bdc0fdb16a98730b9bc038b2cea6b39e4.zip
fsf-binutils-gdb-9bc4e62bdc0fdb16a98730b9bc038b2cea6b39e4.tar.gz
fsf-binutils-gdb-9bc4e62bdc0fdb16a98730b9bc038b2cea6b39e4.tar.bz2
* ld-powerpc/powerpc.exp: Add vxworks relax testcase.
* ld-powerpc/vxworks-relax.s, ld-powerpc/vxworks-relax.rd: New. * ld-powerpc/vxworks1.ld: Add .pad and .far input sections. * ld-powerpc/vxworks1.rd: Correct regexp for undefined symbols.
Diffstat (limited to 'bfd/elf32-ppc.c')
-rw-r--r--bfd/elf32-ppc.c47
1 files changed, 39 insertions, 8 deletions
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 432605b..b04bea4 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -5576,7 +5576,7 @@ ppc_elf_relax_section (bfd *abfd,
Elf_Internal_Rela *internal_relocs = NULL;
Elf_Internal_Rela *irel, *irelend;
struct one_fixup *fixups = NULL;
- bfd_boolean changed;
+ unsigned changes = 0;
struct ppc_elf_link_hash_table *htab;
bfd_size_type trampoff;
asection *got2;
@@ -5823,6 +5823,7 @@ ppc_elf_relax_section (bfd *abfd,
fixups = f;
trampoff += size;
+ changes++;
}
else
{
@@ -5873,7 +5874,6 @@ ppc_elf_relax_section (bfd *abfd,
}
/* Write out the trampolines. */
- changed = fixups != NULL;
if (fixups != NULL)
{
const int *stub;
@@ -5939,7 +5939,7 @@ ppc_elf_relax_section (bfd *abfd,
if (contents != NULL
&& elf_section_data (isec)->this_hdr.contents != contents)
{
- if (!changed && !link_info->keep_memory)
+ if (!changes && !link_info->keep_memory)
free (contents);
else
{
@@ -5948,15 +5948,35 @@ ppc_elf_relax_section (bfd *abfd,
}
}
- if (elf_section_data (isec)->relocs != internal_relocs)
+ if (changes != 0)
{
- if (!changed)
+ /* Append sufficient NOP relocs so we can write out relocation
+ information for the trampolines. */
+ Elf_Internal_Rela *new_relocs = bfd_malloc ((changes + isec->reloc_count)
+ * sizeof (*new_relocs));
+ unsigned ix;
+
+ if (!new_relocs)
+ goto error_return;
+ memcpy (new_relocs, internal_relocs,
+ isec->reloc_count * sizeof (*new_relocs));
+ for (ix = changes; ix--;)
+ {
+ irel = new_relocs + ix + isec->reloc_count;
+
+ irel->r_info = ELF32_R_INFO (0, R_PPC_NONE);
+ }
+ if (internal_relocs != elf_section_data (isec)->relocs)
free (internal_relocs);
- else
- elf_section_data (isec)->relocs = internal_relocs;
+ elf_section_data (isec)->relocs = new_relocs;
+ isec->reloc_count += changes;
+ elf_section_data (isec)->rel_hdr.sh_size
+ += changes * elf_section_data (isec)->rel_hdr.sh_entsize;
}
+ else if (elf_section_data (isec)->relocs != internal_relocs)
+ free (internal_relocs);
- *again = changed;
+ *again = changes != 0;
return TRUE;
error_return:
@@ -6950,6 +6970,17 @@ ppc_elf_relocate_section (bfd *output_bfd,
bfd_put_32 (output_bfd, t0, contents + rel->r_offset);
bfd_put_32 (output_bfd, t1, contents + rel->r_offset + 4);
+
+ /* Rewrite the reloc and convert one of the trailing nop
+ relocs to describe this relocation. */
+ BFD_ASSERT (ELF32_R_TYPE (relend[-1].r_info) == R_PPC_NONE);
+ /* The relocs are at the bottom 2 bytes */
+ rel[0].r_offset += 2;
+ memmove (rel + 1, rel, (relend - rel - 1) * sizeof (*rel));
+ rel[0].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_HA);
+ rel[1].r_offset += 4;
+ rel[1].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_LO);
+ rel++;
}
continue;