diff options
author | Nathan Sidwell <nathan@codesourcery.com> | 2009-05-27 13:31:24 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@codesourcery.com> | 2009-05-27 13:31:24 +0000 |
commit | c8a1f2548b56bc210c8bcb067e91de8132f56d67 (patch) | |
tree | d765705e9894e818c3ef4e0895ecd402ced6541c /bfd/elf32-ppc.c | |
parent | 07fc31c9c913c27ac64af66c32689db4a63827e2 (diff) | |
download | gdb-c8a1f2548b56bc210c8bcb067e91de8132f56d67.zip gdb-c8a1f2548b56bc210c8bcb067e91de8132f56d67.tar.gz gdb-c8a1f2548b56bc210c8bcb067e91de8132f56d67.tar.bz2 |
bfd/
* elf32-ppc.c (ppc_elf_relax_section): Work with a partial
link.
* bout.c (b_out_bfd_relax_section): Reject relocatable links.
* elf32-m10300.c (mn10300_elf_relax_section): Likewise.
* elf32-avr.c (elf32_avr_relax_section): Likewise.
* elf32-frv.c (elf32_avr_relax_section): Likewise.
* elf32-xtensa.c (elf_xtensa_relax_section): Likewise.
* elf64-mmix.c (mmix_elf_relax_section): Likewise.
* elfxx-ia64.c (elfNN_ia64_relax_section): Likewise.
* elfxx-sparc.c (_bfd_sparc_elf_relax_section): Likewise.
* reloc.c (bfd_generic_relax_section): Likewise.
* reloc16.c (bfd_coff_reloc16_relax_section): Likewise.
* vms.c (vms_bfd_relax_section): Likewise.
ld/
* ldmain.c (main): Don't reject --relax -r.
* ld.texinfo (PowerPC ELF32): Document behaviour of relaxing
partial links.
ld/testsuite/
* ld-powerpc/vxworks-relax-2.s: New.
* ld-powerpc/vxworks-relax-2.rd: New.
* ld-powerpc/powerpc.exp: Add it.
Diffstat (limited to 'bfd/elf32-ppc.c')
-rw-r--r-- | bfd/elf32-ppc.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index e15f88e..dcf33cc 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -5661,6 +5661,12 @@ ppc_elf_relax_section (bfd *abfd, || isec->reloc_count == 0) return TRUE; + /* We cannot represent the required PIC relocs in the output, so don't + do anything. The linker doesn't support mixing -shared and -r + anyway. */ + if (link_info->relocatable && link_info->shared) + return TRUE; + trampoff = (isec->size + 3) & (bfd_vma) -4; /* Space for a branch around any trampolines. */ trampoff += 4; @@ -5726,7 +5732,7 @@ ppc_elf_relax_section (bfd *abfd, } isym = isymbuf + ELF32_R_SYM (irel->r_info); if (isym->st_shndx == SHN_UNDEF) - continue; /* We can't do anything with undefined symbols. */ + tsec = bfd_und_section_ptr; else if (isym->st_shndx == SHN_ABS) tsec = bfd_abs_section_ptr; else if (isym->st_shndx == SHN_COMMON) @@ -5779,6 +5785,12 @@ ppc_elf_relax_section (bfd *abfd, tsec = h->root.u.def.section; toff = h->root.u.def.value; } + else if (h->root.type == bfd_link_hash_undefined + || h->root.type == bfd_link_hash_undefweak) + { + tsec = bfd_und_section_ptr; + toff = 0; + } else continue; @@ -5838,7 +5850,12 @@ ppc_elf_relax_section (bfd *abfd, reladdr = isec->output_section->vma + isec->output_offset + roff; /* If the branch is in range, no need to do anything. */ - if (symaddr - reladdr + max_branch_offset < 2 * max_branch_offset) + if (tsec != bfd_und_section_ptr + && (!link_info->relocatable + /* A relocatable link may have sections moved during + final link, so do not presume they remain in range. */ + || tsec->output_section == isec->output_section) + && symaddr - reladdr + max_branch_offset < 2 * max_branch_offset) continue; /* Look for an existing fixup to this address. */ @@ -6048,6 +6065,27 @@ ppc_elf_relax_section (bfd *abfd, free (internal_relocs); *again = changes != 0; + if (!*again && link_info->relocatable) + { + /* Convert the internal relax relocs to external form. */ + for (irel = internal_relocs; irel < irelend; irel++) + if (ELF32_R_TYPE (irel->r_info) == R_PPC_RELAX32) + { + unsigned long r_symndx = ELF32_R_SYM (irel->r_info); + + /* Rewrite the reloc and convert one of the trailing nop + relocs to describe this relocation. */ + BFD_ASSERT (ELF32_R_TYPE (irelend[-1].r_info) == R_PPC_NONE); + /* The relocs are at the bottom 2 bytes */ + irel[0].r_offset += 2; + memmove (irel + 1, irel, (irelend - irel - 1) * sizeof (*irel)); + irel[0].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_HA); + irel[1].r_offset += 4; + irel[1].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_LO); + irel++; + } + } + return TRUE; error_return: |