This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: [PATCH] Enable use of ARMv5t BLX for Thumb-mode calls via PLT
- From: Julian Brown <julian at codesourcery dot com>
- To: binutils at sources dot redhat dot com
- Cc: Julian Brown <julian at codesourcery dot com>, Daniel Jacobowitz <dan at codesourcery dot com>,Paul Brook <paul at codesourcery dot com>
- Date: Tue, 12 Apr 2005 22:13:54 +0100
- Subject: Re: [PATCH] Enable use of ARMv5t BLX for Thumb-mode calls via PLT
- References: <425AC810.5040408@codesourcery.com> <20050411190012.GA3003@nevyn.them.org>
Daniel Jacobowitz wrote:
On Mon, Apr 11, 2005 at 07:55:12PM +0100, Julian Brown wrote:
With this patch, the option "--use-thumb-blx" can be passed to the
linker to enable the use of the BLX instruction when the target supports
it. The format of the PLT itself isn't changed by this patch: there is
still a Thumb stub before each ARM PLT entry, but it is now unused. The
ARM mode entry is called directly instead.
The Thumb stub is never referenced from outside of the object. So, if
we aren't going to branch to it, no point in emitting it either. Patch
looks plausible to me...
This is a new version of the patch which doesn't emit Thumb stubs before
PLT entries if BLX is being used to call them, and also renames the
switch to --use-blx as per Paul's suggestion.
Re-tested on arm-none-eabi and arm-none-symbianelf.
OK to apply?
ChangeLog:
bfd:
* bfd-in.h (bfd_elf32_arm_set_target_relocs): Update prototype.
* bfd-in2.h: Regenerate.
* elf32-arm.c (elf32_arm_link_hash_table): New field, 'use_blx'.
(elf32_arm_link_hash_table_create): Initialise fix_v4bx, use_blx.
(bfd_elf32_arm_set_target_relocs): Handle use_blx.
(elf32_arm_final_link_relocate): Use Thumb BLX for R_ARM_THM_PC22
relocations if requested to.
(allocate_dynrelocs): Don't count size of omitted Thumb stubs based on
use_blx rather than symbian_p.
(elf32_arm_finish_dynamic_symbol): Don't output Thumb PLT stubs if
use_blx is in effect.
(elf32_arm_symbian_link_hash_table_create): Enable use_blx by default
for SymbianOS.
ld:
* ld.texinfo: Document --use-blx.
* emultempl/armelf.em (use_blx): New variable.
(arm_elf_create_output_section_statements): Communicate value of
use_blx to bfd.
(PARSE_AND_LIST_PROLOGUE): Add OPTION_USE_BLX.
(PARSE_AND_LIST_OPTIONS): Add --use-blx option.
(PARSE_AND_LIST_ARGS_CASES): Add OPTION_USE_BLX case.
Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.97
diff -c -p -r1.97 bfd-in.h
*** bfd/bfd-in.h 30 Mar 2005 17:19:27 -0000 1.97
--- bfd/bfd-in.h 12 Apr 2005 20:57:45 -0000
*************** extern bfd_boolean bfd_elf32_arm_process
*** 816,822 ****
(bfd *, struct bfd_link_info *, int);
void bfd_elf32_arm_set_target_relocs
! (struct bfd_link_info *, int, char *, int);
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
(bfd *, struct bfd_link_info *);
--- 816,822 ----
(bfd *, struct bfd_link_info *, int);
void bfd_elf32_arm_set_target_relocs
! (struct bfd_link_info *, int, char *, int, int);
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
(bfd *, struct bfd_link_info *);
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.31
diff -c -p -r1.31 elf32-arm.c
*** bfd/elf32-arm.c 8 Apr 2005 11:47:59 -0000 1.31
--- bfd/elf32-arm.c 12 Apr 2005 20:57:45 -0000
*************** struct elf32_arm_link_hash_table
*** 1324,1329 ****
--- 1324,1332 ----
/* Nonzero to fix BX instructions for ARMv4 targets. */
int fix_v4bx;
+ /* Nonzero if the ARM/Thumb BLX instructions are available for use. */
+ int use_blx;
+
/* The number of bytes in the initial entry in the PLT. */
bfd_size_type plt_header_size;
*************** elf32_arm_link_hash_table_create (bfd *a
*** 1559,1564 ****
--- 1562,1569 ----
ret->plt_header_size = 20;
ret->plt_entry_size = 12;
#endif
+ ret->fix_v4bx = 0;
+ ret->use_blx = 0;
ret->symbian_p = 0;
ret->use_rel = 1;
ret->sym_sec.abfd = NULL;
*************** void
*** 2125,2131 ****
bfd_elf32_arm_set_target_relocs (struct bfd_link_info *link_info,
int target1_is_rel,
char * target2_type,
! int fix_v4bx)
{
struct elf32_arm_link_hash_table *globals;
--- 2130,2137 ----
bfd_elf32_arm_set_target_relocs (struct bfd_link_info *link_info,
int target1_is_rel,
char * target2_type,
! int fix_v4bx,
! int use_blx)
{
struct elf32_arm_link_hash_table *globals;
*************** bfd_elf32_arm_set_target_relocs (struct
*** 2144,2149 ****
--- 2150,2156 ----
target2_type);
}
globals->fix_v4bx = fix_v4bx;
+ globals->use_blx |= use_blx;
}
#endif
*************** elf32_arm_final_link_relocate (reloc_how
*** 2893,2898 ****
--- 2900,2906 ----
bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
bfd_vma check;
bfd_signed_vma signed_check;
+ bfd_boolean thumb_plt_call = FALSE;
/* Need to refetch the addend and squish the two 11 bit pieces
together. */
*************** elf32_arm_final_link_relocate (reloc_how
*** 2942,2949 ****
value = (splt->output_section->vma
+ splt->output_offset
+ h->plt.offset);
! /* Target the Thumb stub before the ARM PLT entry. */
! value -= 4;
*unresolved_reloc_p = FALSE;
}
--- 2950,2968 ----
value = (splt->output_section->vma
+ splt->output_offset
+ h->plt.offset);
! if (globals->use_blx)
! {
! /* If the Thumb BLX instruction is available, 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;
! thumb_plt_call = TRUE;
! }
! }
! else
! /* Target the Thumb stub before the ARM PLT entry. */
! value -= PLT_THUMB_STUB_SIZE;
*unresolved_reloc_p = FALSE;
}
*************** elf32_arm_final_link_relocate (reloc_how
*** 2967,2974 ****
overflow = TRUE;
#ifndef OLD_ARM_ABI
! if (r_type == R_ARM_THM_XPC22
! && ((lower_insn & 0x1800) == 0x0800))
/* For a BLX instruction, make sure that the relocation is rounded up
to a word boundary. This follows the semantics of the instruction
which specifies that bit 1 of the target address will come from bit
--- 2986,2994 ----
overflow = TRUE;
#ifndef OLD_ARM_ABI
! if ((r_type == R_ARM_THM_XPC22
! && ((lower_insn & 0x1800) == 0x0800))
! || thumb_plt_call)
/* For a BLX instruction, make sure that the relocation is rounded up
to a word boundary. This follows the semantics of the instruction
which specifies that bit 1 of the target address will come from bit
*************** allocate_dynrelocs (struct elf_link_hash
*** 5059,5065 ****
/* If we will insert a Thumb trampoline before this PLT, leave room
for it. */
! if (!htab->symbian_p && eh->plt_thumb_refcount > 0)
{
h->plt.offset += PLT_THUMB_STUB_SIZE;
s->size += PLT_THUMB_STUB_SIZE;
--- 5079,5085 ----
/* If we will insert a Thumb trampoline before this PLT, leave room
for it. */
! if (!htab->use_blx && eh->plt_thumb_refcount > 0)
{
h->plt.offset += PLT_THUMB_STUB_SIZE;
s->size += PLT_THUMB_STUB_SIZE;
*************** elf32_arm_finish_dynamic_symbol (bfd * o
*** 5632,5638 ****
BFD_ASSERT ((got_displacement & 0xf0000000) == 0);
! if (eh->plt_thumb_refcount > 0)
{
bfd_put_16 (output_bfd, elf32_arm_plt_thumb_stub[0],
splt->contents + h->plt.offset - 4);
--- 5652,5658 ----
BFD_ASSERT ((got_displacement & 0xf0000000) == 0);
! if (!htab->use_blx && eh->plt_thumb_refcount > 0)
{
bfd_put_16 (output_bfd, elf32_arm_plt_thumb_stub[0],
splt->contents + h->plt.offset - 4);
*************** elf32_arm_symbian_link_hash_table_create
*** 6505,6510 ****
--- 6525,6532 ----
/* The PLT entries are each three instructions. */
htab->plt_entry_size = 4 * NUM_ELEM (elf32_arm_symbian_plt_entry);
htab->symbian_p = 1;
+ /* Symbian uses armv5t or above, so use_blx is always true. */
+ htab->use_blx = 1;
htab->root.is_relocatable_executable = 1;
}
return ret;
Index: ld/ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.140
diff -c -p -r1.140 ld.texinfo
*** ld/ld.texinfo 1 Feb 2005 17:31:01 -0000 1.140
--- ld/ld.texinfo 12 Apr 2005 20:57:45 -0000
*************** linker, which causes v4t @code{BX rM} in
*** 5262,5267 ****
--- 5262,5278 ----
In the former case, the switch should not be used, and @samp{R_ARM_V4BX}
relocations are ignored.
+ @cindex USE_BLX
+ @kindex --use-blx
+ The @samp{--use-blx} switch enables the linker to use ARM/Thumb
+ BLX instructions (available on ARMv5t and above) in various
+ situations. Currently it is used to perform calls via the PLT from
+ Thumb code rather than using BX and a mode-switching stub before each
+ PLT entry. This should lead to such calls executing slightly faster.
+
+ This option is enabled implicitly for SymbianOS, so there is no need to
+ specify it if you are using that target.
+
@ifclear GENERIC
@lowersections
@end ifclear
Index: ld/emultempl/armelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/armelf.em,v
retrieving revision 1.44
diff -c -p -r1.44 armelf.em
*** ld/emultempl/armelf.em 3 Mar 2005 11:52:04 -0000 1.44
--- ld/emultempl/armelf.em 12 Apr 2005 20:57:45 -0000
*************** static int byteswap_code = 0;
*** 32,37 ****
--- 32,38 ----
static int target1_is_rel = 0${TARGET1_IS_REL};
static char *target2_type = "${TARGET2_TYPE}";
static int fix_v4bx = 0;
+ static int use_blx = 0;
static void
gld${EMULATION_NAME}_before_parse (void)
*************** static void
*** 192,198 ****
arm_elf_create_output_section_statements (void)
{
bfd_elf32_arm_set_target_relocs (&link_info, target1_is_rel, target2_type,
! fix_v4bx);
}
EOF
--- 193,199 ----
arm_elf_create_output_section_statements (void)
{
bfd_elf32_arm_set_target_relocs (&link_info, target1_is_rel, target2_type,
! fix_v4bx, use_blx);
}
EOF
*************** PARSE_AND_LIST_PROLOGUE='
*** 206,212 ****
#define OPTION_TARGET1_REL 303
#define OPTION_TARGET1_ABS 304
#define OPTION_TARGET2 305
! #define OPTION_FIX_V4BX 306
'
PARSE_AND_LIST_SHORTOPTS=p
--- 207,214 ----
#define OPTION_TARGET1_REL 303
#define OPTION_TARGET1_ABS 304
#define OPTION_TARGET2 305
! #define OPTION_FIX_V4BX 306
! #define OPTION_USE_BLX 307
'
PARSE_AND_LIST_SHORTOPTS=p
*************** PARSE_AND_LIST_LONGOPTS='
*** 219,224 ****
--- 221,227 ----
{ "target1-abs", no_argument, NULL, OPTION_TARGET1_ABS},
{ "target2", required_argument, NULL, OPTION_TARGET2},
{ "fix-v4bx", no_argument, NULL, OPTION_FIX_V4BX},
+ { "use-blx", no_argument, NULL, OPTION_USE_BLX},
'
PARSE_AND_LIST_OPTIONS='
*************** PARSE_AND_LIST_OPTIONS='
*** 228,233 ****
--- 231,237 ----
fprintf (file, _(" --target1=abs Interpret R_ARM_TARGET1 as R_ARM_ABS32\n"));
fprintf (file, _(" --target2=<type> Specify definition of R_ARM_TARGET2\n"));
fprintf (file, _(" --fix-v4bx Rewrite BX rn as MOV pc, rn for ARMv4\n"));
+ fprintf (file, _(" --use-blx Enable use of BLX instructions\n"));
'
PARSE_AND_LIST_ARGS_CASES='
*************** PARSE_AND_LIST_ARGS_CASES='
*** 258,263 ****
--- 262,271 ----
case OPTION_FIX_V4BX:
fix_v4bx = 1;
break;
+
+ case OPTION_USE_BLX:
+ use_blx = 1;
+ break;
'
# We have our own after_open and before_allocation functions, but they call