This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
Add relocations for Arm and Thumb BLX instructions
- To: binutils at sourceware dot cygnus dot com
- Subject: Add relocations for Arm and Thumb BLX instructions
- From: Nick Clifton <nickc at cygnus dot com>
- Date: Fri, 7 Apr 2000 17:08:27 -0700
Hi Guys,
The latest versions of the ARM ELF specification define relocations
for the new BLX instruction in version 5 of the Arm Architecture
Specification. This patch adds support for these relocations.
As a side effect of this patch the header file
include/elf/arm-oabi.h is going away. Its contents have been merged
into the include/elf/arm.h which simplifies things, and helps to
make clear the exact difference between the old ABI and the new
ABI. (Actually "old" and "new" are misnomers. They should be
"prior to the release of the ARM ELF spec" and "after the release of
the ARM ELF spec").
Cheers
Nick
[ChangeLog for include/elf]
* arm-oabi.h: Delete.
* arm.h: Merge in definitions of old reloc numbers from
arm-oabi.h.
[ChangeLog for bfd]
* reloc.c: Add BFD_RELOC_ARM_PCREL_BLX and
BFD_RELOC_THUMB_PCREL_BLX.
* elf32-arm.h (elf32_arm_final_link_relocate): Handle
R_ARM_XPC25 and R_ARM_THM_PC22.
* elfarm-nabi.c (elf32_arm_howto_): Fix definitions of
R_ARM_XPC25 and R_ARM_THM_XPC22.
(elf32_arm_reloc_map): Make BFD_RELOC_{ARM|THUMB}_PCREL_BLX to
R_ARM_[XPC25|THM_XPC22].
* elfarm-oabi.c: Define OLD_ARM_ABI and change include from
elf/arm-oabi.h to elf/arm.h
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
[ChangeLog for gas]
* config/tc-arm.c (md_apply_fix3): Treat BFD_RELOC_ARM_PCREL_BLX
in the same way as BFD_RELOC_ARM_PCREL_BRANCH, and
BFD_RELOC_THUMB_PCREL_BLX lie BFD_RELOC_THUMB_PCREL_BRANCH.
(tc_gen_reloc): Accept BFD_RELOC_{ARM|THUMB}_PCREL_BLX.
(arm_force_relocation): Force relocations for
BFD_RELOC_{ARM|THUMB}_PCREL_BLX as well.
Index: include//elf/arm.h
===================================================================
RCS file: /cvs/src//src/include/elf/arm.h,v
retrieving revision 1.4
diff -p -w -r1.4 arm.h
*** arm.h 2000/04/06 23:18:18 1.4
--- arm.h 2000/04/07 23:50:02
***************
*** 63,73 ****
--- 63,87 ----
#define PF_ARM_ABS 0x40000000 /* Segment must be loaded at its base address. */
/* Relocation types. */
+
START_RELOC_NUMBERS (elf_arm_reloc_type)
RELOC_NUMBER (R_ARM_NONE, 0)
RELOC_NUMBER (R_ARM_PC24, 1)
RELOC_NUMBER (R_ARM_ABS32, 2)
RELOC_NUMBER (R_ARM_REL32, 3)
+ #ifdef OLD_ARM_ABI
+ RELOC_NUMBER (R_ARM_ABS8, 4)
+ RELOC_NUMBER (R_ARM_ABS16, 5)
+ RELOC_NUMBER (R_ARM_ABS12, 6)
+ RELOC_NUMBER (R_ARM_THM_ABS5, 7)
+ RELOC_NUMBER (R_ARM_THM_PC22, 8)
+ RELOC_NUMBER (R_ARM_SBREL32, 9)
+ RELOC_NUMBER (R_ARM_AMP_VCALL9, 10)
+ RELOC_NUMBER (R_ARM_THM_PC11, 11) /* Cygnus extension to abi: Thumb unconditional branch. */
+ RELOC_NUMBER (R_ARM_THM_PC9, 12) /* Cygnus extension to abi: Thumb conditional branch. */
+ RELOC_NUMBER (R_ARM_GNU_VTINHERIT, 13)
+ RELOC_NUMBER (R_ARM_GNU_VTENTRY, 14)
+ #else /* not OLD_ARM_ABI */
RELOC_NUMBER (R_ARM_PC13, 4)
RELOC_NUMBER (R_ARM_ABS16, 5)
RELOC_NUMBER (R_ARM_ABS12, 6)
*************** START_RELOC_NUMBERS (elf_arm_reloc_type)
*** 81,103 ****
RELOC_NUMBER (R_ARM_THM_SWI8, 14)
RELOC_NUMBER (R_ARM_XPC25, 15)
RELOC_NUMBER (R_ARM_THM_XPC22, 16)
! RELOC_NUMBER (R_ARM_COPY, 20) /* copy symbol at runtime */
! RELOC_NUMBER (R_ARM_GLOB_DAT, 21) /* create GOT entry */
! RELOC_NUMBER (R_ARM_JUMP_SLOT, 22) /* create PLT entry */
! RELOC_NUMBER (R_ARM_RELATIVE, 23) /* adjust by program base */
! RELOC_NUMBER (R_ARM_GOTOFF, 24) /* 32 bit offset to GOT */
! RELOC_NUMBER (R_ARM_GOTPC, 25) /* 32 bit PC relative offset to GOT */
! RELOC_NUMBER (R_ARM_GOT32, 26) /* 32 bit GOT entry */
! RELOC_NUMBER (R_ARM_PLT32, 27) /* 32 bit PLT address */
FAKE_RELOC (FIRST_INVALID_RELOC1, 28)
FAKE_RELOC (LAST_INVALID_RELOC1, 99)
RELOC_NUMBER (R_ARM_GNU_VTENTRY, 100)
RELOC_NUMBER (R_ARM_GNU_VTINHERIT, 101)
! RELOC_NUMBER (R_ARM_THM_PC11, 102) /* Cygnus extension to abi: Thumb unconditional branch */
! RELOC_NUMBER (R_ARM_THM_PC9, 103) /* Cygnus extension to abi: Thumb conditional branch */
FAKE_RELOC (FIRST_INVALID_RELOC2, 104)
FAKE_RELOC (LAST_INVALID_RELOC2, 248)
RELOC_NUMBER (R_ARM_RXPC25, 249)
RELOC_NUMBER (R_ARM_RSBREL32, 250)
RELOC_NUMBER (R_ARM_THM_RPC22, 251)
RELOC_NUMBER (R_ARM_RREL32, 252)
--- 95,123 ----
RELOC_NUMBER (R_ARM_THM_SWI8, 14)
RELOC_NUMBER (R_ARM_XPC25, 15)
RELOC_NUMBER (R_ARM_THM_XPC22, 16)
! #endif /* not OLD_ARM_ABI */
! RELOC_NUMBER (R_ARM_COPY, 20) /* Copy symbol at runtime. */
! RELOC_NUMBER (R_ARM_GLOB_DAT, 21) /* Create GOT entry. */
! RELOC_NUMBER (R_ARM_JUMP_SLOT, 22) /* Create PLT entry. */
! RELOC_NUMBER (R_ARM_RELATIVE, 23) /* Adjust by program base. */
! RELOC_NUMBER (R_ARM_GOTOFF, 24) /* 32 bit offset to GOT. */
! RELOC_NUMBER (R_ARM_GOTPC, 25) /* 32 bit PC relative offset to GOT. */
! RELOC_NUMBER (R_ARM_GOT32, 26) /* 32 bit GOT entry. */
! RELOC_NUMBER (R_ARM_PLT32, 27) /* 32 bit PLT address. */
! #ifdef OLD_ARM_ABI
! FAKE_RELOC (FIRST_INVALID_RELOC, 28)
! FAKE_RELOC (LAST_INVALID_RELOC, 249)
! #else /* not OLD_ARM_ABI */
FAKE_RELOC (FIRST_INVALID_RELOC1, 28)
FAKE_RELOC (LAST_INVALID_RELOC1, 99)
RELOC_NUMBER (R_ARM_GNU_VTENTRY, 100)
RELOC_NUMBER (R_ARM_GNU_VTINHERIT, 101)
! RELOC_NUMBER (R_ARM_THM_PC11, 102) /* Cygnus extension to abi: Thumb unconditional branch. */
! RELOC_NUMBER (R_ARM_THM_PC9, 103) /* Cygnus extension to abi: Thumb conditional branch. */
FAKE_RELOC (FIRST_INVALID_RELOC2, 104)
FAKE_RELOC (LAST_INVALID_RELOC2, 248)
RELOC_NUMBER (R_ARM_RXPC25, 249)
+ #endif /* not OLD_ARM_ABI */
RELOC_NUMBER (R_ARM_RSBREL32, 250)
RELOC_NUMBER (R_ARM_THM_RPC22, 251)
RELOC_NUMBER (R_ARM_RREL32, 252)
*************** START_RELOC_NUMBERS (elf_arm_reloc_type)
*** 106,109 ****
RELOC_NUMBER (R_ARM_RBASE, 255)
END_RELOC_NUMBERS
! #endif
--- 126,129 ----
RELOC_NUMBER (R_ARM_RBASE, 255)
END_RELOC_NUMBERS
! #endif /* _ELF_ARM_H */
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src//src/bfd/reloc.c,v
retrieving revision 1.18
diff -p -w -r1.18 reloc.c
*** reloc.c 2000/04/07 17:06:58 1.18
--- reloc.c 2000/04/07 23:50:03
*************** ENUMDOC
*** 2202,2207 ****
--- 2202,2219 ----
ARM 26 bit pc-relative branch. The lowest two bits must be zero and are
not stored in the instruction.
ENUM
+ BFD_RELOC_ARM_PCREL_BLX
+ ENUMDOC
+ ARM 26 bit pc-relative branch. The lowest bit must be zero and is
+ not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+ field in the instruction.
+ ENUM
+ BFD_RELOC_THUMB_PCREL_BLX
+ ENUMDOC
+ Thumb 22 bit pc-relative branch. The lowest bit must be zero and is
+ not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+ field in the instruction.
+ ENUM
BFD_RELOC_ARM_IMMEDIATE
ENUMX
BFD_RELOC_ARM_ADRL_IMMEDIATE
Index: bfd/elf32-arm.h
===================================================================
RCS file: /cvs/src//src/bfd/elf32-arm.h,v
retrieving revision 1.27
diff -p -w -r1.27 elf32-arm.h
*** elf32-arm.h 2000/04/06 23:38:47 1.27
--- elf32-arm.h 2000/04/07 23:59:15
*************** elf32_arm_final_link_relocate (howto, in
*** 1062,1067 ****
--- 1062,1070 ----
case R_ARM_PC24:
case R_ARM_ABS32:
case R_ARM_REL32:
+ #ifndef OLD_ARM_ABI
+ case R_ARM_XPC25:
+ #endif
/* When generating a shared object, these relocations are copied
into the output file to be resolved at run time. */
*************** elf32_arm_final_link_relocate (howto, in
*** 1171,1180 ****
}
else switch (r_type)
{
! case R_ARM_PC24:
! /* Arm B/BL instruction */
!
! /* Check for arm calling thumb function. */
if (sym_flags == STT_ARM_TFUNC)
{
elf32_arm_to_thumb_stub (info, sym_name, input_bfd, output_bfd,
--- 1174,1199 ----
}
else switch (r_type)
{
! #ifndef OLD_ARM_ABI
! case R_ARM_XPC25: /* Arm BLX instruction. */
! #endif
! case R_ARM_PC24: /* Arm B/BL instruction */
! #ifndef OLD_ARM_ABI
! if (r_type == R_ARM_XPC25)
! {
! /* Check for Arm calling Arm function. */
! /* FIXME: Should we translate the instruction into a BL
! instruction instead ? */
! if (sym_flags != STT_ARM_TFUNC)
! _bfd_error_handler (_("\
! %s: Warning: Arm BLX instruction targets Arm function '%s'."),
! bfd_get_filename (input_bfd),
! h->root.root.string);
! }
! else
! #endif
! {
! /* Check for Arm calling Thumb function. */
if (sym_flags == STT_ARM_TFUNC)
{
elf32_arm_to_thumb_stub (info, sym_name, input_bfd, output_bfd,
*************** elf32_arm_final_link_relocate (howto, in
*** 1321,1326 ****
--- 1341,1349 ----
bfd_put_16 (input_bfd, value, hit_data);
return bfd_reloc_ok;
+ #ifndef OLD_ARM_ABI
+ case R_ARM_THM_XPC22:
+ #endif
case R_ARM_THM_PC22:
/* Thumb BL (branch long instruction). */
{
*************** elf32_arm_final_link_relocate (howto, in
*** 1344,1351 ****
signed_addend = addend;
}
#endif
!
! /* If it is not a call to thumb, assume call to arm.
If it is a call relative to a section name, then it is not a
function call at all, but rather a long jump. */
if (sym_flags != STT_ARM_TFUNC && sym_flags != STT_SECTION)
--- 1367,1388 ----
signed_addend = addend;
}
#endif
! #ifndef OLD_ARM_ABI
! if (r_type == R_ARM_THM_XPC22)
! {
! /* Check for Thumb to Thumb call. */
! /* FIXME: Should we translate the instruction into a BL
! instruction instead ? */
! if (sym_flags == STT_ARM_TFUNC)
! _bfd_error_handler (_("\
! %s: Warning: Thumb BLX instruction targets thumb function '%s'."),
! bfd_get_filename (input_bfd),
! h->root.root.string);
! }
! else
! #endif
! {
! /* If it is not a call to Thumb, assume call to Arm.
If it is a call relative to a section name, then it is not a
function call at all, but rather a long jump. */
if (sym_flags != STT_ARM_TFUNC && sym_flags != STT_SECTION)
Index: bfd/elfarm-nabi.c
===================================================================
RCS file: /cvs/src//src/bfd/elfarm-nabi.c,v
retrieving revision 1.3
diff -p -w -r1.3 elfarm-nabi.c
*** elfarm-nabi.c 1999/07/12 10:29:36 1.3
--- elfarm-nabi.c 2000/04/07 23:50:03
*************** static reloc_howto_type elf32_arm_howto_
*** 261,296 ****
0x00000000, /* src_mask */
0x00000000, /* dst_mask */
false), /* pcrel_offset */
-
- /* These next two relocs are defined, but I do not know what they do. */
HOWTO (R_ARM_XPC25, /* type */
! 0, /* rightshift */
! 0, /* size (0 = byte, 1 = short, 2 = long) */
! 0, /* bitsize */
! false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_XPC25", /* name */
false, /* partial_inplace */
! 0x00000000, /* src_mask */
! 0x00000000, /* dst_mask */
! false), /* pcrel_offset */
HOWTO (R_ARM_THM_XPC22, /* type */
! 0, /* rightshift */
! 0, /* size (0 = byte, 1 = short, 2 = long) */
! 0, /* bitsize */
! false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_XPC22", /* name */
false, /* partial_inplace */
! 0x00000000, /* src_mask */
! 0x00000000, /* dst_mask */
! false), /* pcrel_offset */
/* These next three relocs are not defined, but we need to fill the space. */
--- 265,300 ----
0x00000000, /* src_mask */
0x00000000, /* dst_mask */
false), /* pcrel_offset */
+ /* BLX instruction for the ARM. */
HOWTO (R_ARM_XPC25, /* type */
! 2, /* rightshift */
! 2, /* size (0 = byte, 1 = short, 2 = long) */
! 25, /* bitsize */
! true, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_XPC25", /* name */
false, /* partial_inplace */
! 0x00ffffff, /* src_mask */
! 0x00ffffff, /* dst_mask */
! true), /* pcrel_offset */
+ /* BLX instruction for the Thumb. */
HOWTO (R_ARM_THM_XPC22, /* type */
! 2, /* rightshift */
! 2, /* size (0 = byte, 1 = short, 2 = long) */
! 22, /* bitsize */
! true, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_XPC22", /* name */
false, /* partial_inplace */
! 0x07ff07ff, /* src_mask */
! 0x07ff07ff, /* dst_mask */
! true), /* pcrel_offset */
/* These next three relocs are not defined, but we need to fill the space. */
*************** static const struct elf32_arm_reloc_map
*** 622,627 ****
--- 626,633 ----
{
{BFD_RELOC_NONE, R_ARM_NONE},
{BFD_RELOC_ARM_PCREL_BRANCH, R_ARM_PC24},
+ {BFD_RELOC_ARM_PCREL_BLX, R_ARM_XPC25},
+ {BFD_RELOC_THUMB_PCREL_BLX, R_ARM_THM_XPC22},
{BFD_RELOC_32, R_ARM_ABS32},
{BFD_RELOC_32_PCREL, R_ARM_REL32},
{BFD_RELOC_8, R_ARM_ABS8},
Index: bfd/elfarm-oabi.c
===================================================================
RCS file: /cvs/src//src/bfd/elfarm-oabi.c,v
retrieving revision 1.4
diff -p -w -r1.4 elfarm-oabi.c
*** elfarm-oabi.c 1999/07/12 10:29:38 1.4
--- elfarm-oabi.c 2000/04/07 23:50:03
***************
*** 17,23 ****
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
! #include "elf/arm-oabi.h"
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
--- 17,25 ----
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
! #define OLD_ARM_ABI
!
! #include "elf/arm.h"
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src//src/bfd/bfd-in2.h,v
retrieving revision 1.39
diff -p -w -r1.39 bfd-in2.h
*** bfd-in2.h 2000/04/07 17:06:57 1.39
--- bfd-in2.h 2000/04/07 23:50:02
*************** It generally does map to one of the othe
*** 2049,2054 ****
--- 2049,2064 ----
not stored in the instruction. */
BFD_RELOC_ARM_PCREL_BRANCH,
+ /* ARM 26 bit pc-relative branch. The lowest bit must be zero and is
+ not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+ field in the instruction. */
+ BFD_RELOC_ARM_PCREL_BLX,
+
+ /* Thumb 22 bit pc-relative branch. The lowest bit must be zero and is
+ not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+ field in the instruction. */
+ BFD_RELOC_THUMB_PCREL_BLX,
+
/* These relocs are only used within the ARM assembler. They are not
(at present) written to any object files. */
BFD_RELOC_ARM_IMMEDIATE,
Index: bfd/libbfd.h
===================================================================
RCS file: /cvs/src//src/bfd/libbfd.h,v
retrieving revision 1.16
diff -p -w -r1.16 libbfd.h
*** libbfd.h 2000/04/07 17:06:58 1.16
--- libbfd.h 2000/04/07 23:50:03
*************** static const char *const bfd_reloc_code_
*** 765,770 ****
--- 765,772 ----
"BFD_RELOC_I370_D12",
"BFD_RELOC_CTOR",
"BFD_RELOC_ARM_PCREL_BRANCH",
+ "BFD_RELOC_ARM_PCREL_BLX",
+ "BFD_RELOC_THUMB_PCREL_BLX",
"BFD_RELOC_ARM_IMMEDIATE",
"BFD_RELOC_ARM_ADRL_IMMEDIATE",
"BFD_RELOC_ARM_OFFSET_IMM",
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src//src/gas/config/tc-arm.c,v
retrieving revision 1.39
diff -p -w -r1.39 tc-arm.c
*** tc-arm.c 2000/03/29 18:25:37 1.39
--- tc-arm.c 2000/04/07 23:50:03
*************** md_apply_fix3 (fixP, val, seg)
*** 5370,5375 ****
--- 5370,5376 ----
{
if (target_oabi
&& (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
+ || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
))
value = 0;
else
*************** md_apply_fix3 (fixP, val, seg)
*** 5617,5622 ****
--- 5618,5639 ----
md_number_to_chars (buf, newval, INSN_SIZE);
break;
+ case BFD_RELOC_ARM_PCREL_BLX:
+ {
+ offsetT hbit;
+ newval = md_chars_to_number (buf, INSN_SIZE);
+
+ #ifdef OBJ_ELF
+ if (! target_oabi)
+ value = fixP->fx_offset;
+ #endif
+ hbit = (value >> 1) & 1;
+ value = (value >> 2) & 0x00ffffff;
+ value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
+ newval = value | (newval & 0xfe000000) | (hbit << 24);
+ md_number_to_chars (buf, newval, INSN_SIZE);
+ }
+ break;
case BFD_RELOC_THUMB_PCREL_BRANCH9: /* conditional branch */
newval = md_chars_to_number (buf, THUMB_SIZE);
*************** md_apply_fix3 (fixP, val, seg)
*** 5650,5655 ****
--- 5667,5673 ----
md_number_to_chars (buf, newval, THUMB_SIZE);
break;
+ case BFD_RELOC_THUMB_PCREL_BLX:
case BFD_RELOC_THUMB_PCREL_BRANCH23:
{
offsetT newval2;
*************** tc_gen_reloc (section, fixp)
*** 5956,5965 ****
--- 5974,5985 ----
}
case BFD_RELOC_ARM_PCREL_BRANCH:
+ case BFD_RELOC_ARM_PCREL_BLX:
case BFD_RELOC_RVA:
case BFD_RELOC_THUMB_PCREL_BRANCH9:
case BFD_RELOC_THUMB_PCREL_BRANCH12:
case BFD_RELOC_THUMB_PCREL_BRANCH23:
+ case BFD_RELOC_THUMB_PCREL_BLX:
case BFD_RELOC_VTABLE_ENTRY:
case BFD_RELOC_VTABLE_INHERIT:
code = fixp->fx_r_type;
*************** arm_force_relocation (fixp)
*** 7102,7107 ****
--- 7124,7131 ----
if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
|| fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
+ || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
+ || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
|| fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
return 1;