This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[PATCH] Fix thumb calls via PLT on ARM/SymbianOS
- From: Julian Brown <julian at codesourcery dot com>
- To: binutils at sources dot redhat dot com
- Cc: julian at codesourcery dot com
- Date: Wed, 16 Mar 2005 14:17:23 +0000
- Subject: [PATCH] Fix thumb calls via PLT on ARM/SymbianOS
Hi,
This patch fixes calls made from thumb mode via the PLT on SymbianOS.
PLT entries are written in ARM mode, but previously they were being
called in thumb mode, with their address incorrectly offset by -4
(PLT_THUMB_STUB_SIZE).
Now, the target address has been corrected and the thumb BL instruction
is rewritten as BLX to perform the mode switch before attempting to
execute the PLT entry. (BLX is an armv5t instruction, but as SymbianOS
is only targeted at armv5t+, this should always be OK.)
The hardwired "4" for the thumb stub size on non-SymbianOS targets has
also been rewritten as PLT_THUMB_STUB_SIZE.
OK to apply?
Julian
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.22
diff -c -p -r1.22 elf32-arm.c
*** bfd/elf32-arm.c 11 Feb 2005 16:41:09 -0000 1.22
--- bfd/elf32-arm.c 16 Mar 2005 12:38:29 -0000
*************** elf32_arm_final_link_relocate (reloc_how
*** 2692,2699 ****
value = (splt->output_section->vma
+ splt->output_offset
+ h->plt.offset);
! /* Target the Thumb stub before the ARM PLT entry. */
! value -= 4;
}
relocation = value + signed_addend;
--- 2692,2708 ----
value = (splt->output_section->vma
+ splt->output_offset
+ h->plt.offset);
! if (globals->symbian_p)
! {
! /* On SymbianOS, we are guaranteed to be using at least ARMv5t.
! Convert the BL to a BLX instruction to call the ARM-mode PLT
! entry. */
! if ((lower_insn & (0x3 << 11)) == 0x3 << 11)
! lower_insn = (lower_insn & ~(0x3 << 11)) | 0x1 << 11;
! }
! else
! /* Target the Thumb stub before the ARM PLT entry. */
! value -= PLT_THUMB_STUB_SIZE;
}
relocation = value + signed_addend;