This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
powerpc ld -relax fix
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: binutils at sources dot redhat dot com
- Cc: Suriyan Ramasami <suram at us dot ibm dot com>
- Date: Wed, 12 Jan 2005 21:58:34 +1030
- Subject: powerpc ld -relax fix
ld -relax on powerpc supports insertion of branch trampolines to reach
locations that would otherwise cause reloc overflows. However, there
was a problem with trampolines to reach the PLT: The calculation in
relocate_section for such trampolines didn't use the proper destination
value, resulting in branches to zero.
I've also removed the howto entries for R_PPC_RELAX* relocs since they
aren't used anywhere.
include/elf/
* ppc.h (R_PPC_RELAX32_PLT, R_PPC_RELAX32PC_PLT): Define.
(R_PPC_RELAX32, R_PPC_RELAX32PC): Adjust value.
bfd/
* elf32-ppc.c (ppc_elf_howto_raw): Delete RELAX32* entries.
(ppc_elf_relax_section): Use PLT variants of RELAX32 relocs for
reaching PLT.
(ppc_elf_relocate_section): Handle R_PPC_RELAX32_PLT and
R_PPC_RELAX32PC_PLT.
Index: include/elf/ppc.h
===================================================================
RCS file: /cvs/src/src/include/elf/ppc.h,v
retrieving revision 1.13
diff -u -p -r1.13 ppc.h
--- include/elf/ppc.h 6 Nov 2003 02:57:08 -0000 1.13
+++ include/elf/ppc.h 12 Jan 2005 11:09:46 -0000
@@ -122,8 +122,10 @@ START_RELOC_NUMBERS (elf_ppc_reloc_type)
/* Fake relocations for branch stubs. This will keep them
together. */
-#define R_PPC_RELAX32 251
-#define R_PPC_RELAX32PC 252
+#define R_PPC_RELAX32 249
+#define R_PPC_RELAX32PC 250
+#define R_PPC_RELAX32_PLT 251
+#define R_PPC_RELAX32PC_PLT 252
/* These are GNU extensions to enable C++ vtable garbage collection. */
RELOC_NUMBER (R_PPC_GNU_VTINHERIT, 253)
Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.133
diff -u -p -r1.133 elf32-ppc.c
--- bfd/elf32-ppc.c 11 Jan 2005 09:32:49 -0000 1.133
+++ bfd/elf32-ppc.c 12 Jan 2005 11:09:49 -0000
@@ -1533,35 +1533,6 @@ static reloc_howto_type ppc_elf_howto_ra
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
- /* Phony relocs to handle branch stubs. */
- HOWTO (R_PPC_RELAX32, /* type */
- 0, /* rightshift */
- 0, /* size */
- 0, /* bitsize */
- FALSE, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_PPC_RELAX32", /* name */
- FALSE, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- FALSE), /* pcrel_offset */
-
- HOWTO (R_PPC_RELAX32PC, /* type */
- 0, /* rightshift */
- 0, /* size */
- 0, /* bitsize */
- FALSE, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_PPC_RELAX32PC", /* name */
- FALSE, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- FALSE), /* pcrel_offset */
-
/* GNU extension to record C++ vtable hierarchy. */
HOWTO (R_PPC_GNU_VTINHERIT, /* type */
0, /* rightshift */
@@ -1867,6 +1838,12 @@ ppc_elf_relax_section (bfd *abfd,
stub_rtype = R_PPC_RELAX32;
}
+ if (R_PPC_RELAX32_PLT - R_PPC_RELAX32
+ != R_PPC_RELAX32PC_PLT - R_PPC_RELAX32PC)
+ abort ();
+ if (tsec == ppc_info->plt)
+ stub_rtype += R_PPC_RELAX32_PLT - R_PPC_RELAX32;
+
/* Hijack the old relocation. Since we need two
relocations for this use a "composite" reloc. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
@@ -5422,12 +5399,27 @@ ppc_elf_relocate_section (bfd *output_bf
}
break;
+ case R_PPC_RELAX32PC_PLT:
+ case R_PPC_RELAX32_PLT:
+ BFD_ASSERT (h != NULL
+ && h->plt.offset != (bfd_vma) -1
+ && htab->plt != NULL);
+
+ relocation = (htab->plt->output_section->vma
+ + htab->plt->output_offset
+ + h->plt.offset);
+ if (r_type == R_PPC_RELAX32_PLT)
+ goto relax32;
+ /* Fall thru */
+
case R_PPC_RELAX32PC:
relocation -= (input_section->output_section->vma
+ input_section->output_offset
+ rel->r_offset - 4);
/* Fall thru */
+
case R_PPC_RELAX32:
+ relax32:
{
unsigned long t0;
unsigned long t1;
--
Alan Modra
IBM OzLabs - Linux Technology Centre