Add --no-use-blx switch to force disabling of BLX instructions for thumb interworking. This allows ld to emit code that is armv4t safe even if configured for armv5 or later. --- bfd/bfd-in.h | 4 ++-- bfd/bfd-in2.h | 4 ++-- bfd/elf32-arm.c | 10 +++++++++- ld/emultempl/armelf.em | 11 +++++++++-- 4 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index a477b49..0a81327 100644 --- a/bfd/bfd-in.h +++ b/bfd/bfd-in.h @@ -872,8 +872,8 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation (bfd *, struct bfd_link_info *);
void bfd_elf32_arm_set_target_relocs - (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix, - int, int, int, int, int); + (bfd *, struct bfd_link_info *, int, char *, int, int, int, + bfd_arm_vfp11_fix, int, int, int, int, int);
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking (bfd *, struct bfd_link_info *); diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 22fcdf6..45c5376 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -879,8 +879,8 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation (bfd *, struct bfd_link_info *);
void bfd_elf32_arm_set_target_relocs - (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix, - int, int, int, int, int); + (bfd *, struct bfd_link_info *, int, char *, int, int, int, + bfd_arm_vfp11_fix, int, int, int, int, int);
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking (bfd *, struct bfd_link_info *); diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 1f6c1a0..7cbb5f8 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -2782,6 +2782,9 @@ struct elf32_arm_link_hash_table /* Nonzero if the ARM/Thumb BLX instructions are available for use. */ int use_blx;
+ /* Nonzero to prevent BLX instructions from being used. */ + int no_use_blx; + /* What sort of code sequences we should look for which may trigger the VFP11 denorm erratum. */ bfd_arm_vfp11_fix vfp11_fix; @@ -3332,6 +3335,7 @@ elf32_arm_link_hash_table_create (bfd *abfd) #endif ret->fix_v4bx = 0; ret->use_blx = 0; + ret->no_use_blx = 0; ret->vxworks_p = 0; ret->symbian_p = 0; ret->use_rel = 1; @@ -5939,7 +5943,9 @@ check_use_blx (struct elf32_arm_link_hash_table *globals) cpu_arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC, Tag_CPU_arch);
- if (globals->fix_arm1176) + if (globals->no_use_blx) + globals->use_blx = 0; + else if (globals->fix_arm1176) { if (cpu_arch == TAG_CPU_ARCH_V6T2 || cpu_arch > TAG_CPU_ARCH_V6K) globals->use_blx = 1; @@ -6800,6 +6806,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd, char * target2_type, int fix_v4bx, int use_blx, + int no_use_blx, bfd_arm_vfp11_fix vfp11_fix, int no_enum_warn, int no_wchar_warn, int pic_veneer, int fix_cortex_a8, @@ -6825,6 +6832,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd, } globals->fix_v4bx = fix_v4bx; globals->use_blx |= use_blx; + globals->no_use_blx = no_use_blx; globals->vfp11_fix = vfp11_fix; globals->pic_veneer = pic_veneer; globals->fix_cortex_a8 = fix_cortex_a8; diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em index d29da59..14a0dcf 100644 --- a/ld/emultempl/armelf.em +++ b/ld/emultempl/armelf.em @@ -36,6 +36,7 @@ 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 int no_use_blx = 0; static bfd_arm_vfp11_fix vfp11_denorm_fix = BFD_ARM_VFP11_FIX_DEFAULT; static int fix_cortex_a8 = -1; static int no_enum_size_warning = 0; @@ -462,7 +463,7 @@ arm_elf_create_output_section_statements (void)
bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info, target1_is_rel, - target2_type, fix_v4bx, use_blx, + target2_type, fix_v4bx, use_blx, no_use_blx, vfp11_denorm_fix, no_enum_size_warning, no_wchar_size_warning, pic_veneer, fix_cortex_a8, @@ -533,6 +534,7 @@ PARSE_AND_LIST_PROLOGUE=' #define OPTION_NO_MERGE_EXIDX_ENTRIES 316 #define OPTION_FIX_ARM1176 317 #define OPTION_NO_FIX_ARM1176 318 +#define OPTION_NO_USE_BLX 319 '
PARSE_AND_LIST_SHORTOPTS=p @@ -547,6 +549,7 @@ PARSE_AND_LIST_LONGOPTS=' { "fix-v4bx", no_argument, NULL, OPTION_FIX_V4BX}, { "fix-v4bx-interworking", no_argument, NULL, OPTION_FIX_V4BX_INTERWORKING}, { "use-blx", no_argument, NULL, OPTION_USE_BLX}, + { "no-use-blx", no_argument, NULL, OPTION_NO_USE_BLX}, { "vfp11-denorm-fix", required_argument, NULL, OPTION_VFP11_DENORM_FIX}, { "no-enum-size-warning", no_argument, NULL, OPTION_NO_ENUM_SIZE_WARNING}, { "pic-veneer", no_argument, NULL, OPTION_PIC_VENEER}, @@ -567,7 +570,7 @@ PARSE_AND_LIST_OPTIONS=' 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, _(" --fix-v4bx-interworking Rewrite BX rn branch to ARMv4 interworking veneer\n")); - fprintf (file, _(" --use-blx Enable use of BLX instructions\n")); + fprintf (file, _(" --[no-]use-blx Disable/enable use of BLX instructions\n")); fprintf (file, _(" --vfp11-denorm-fix Specify how to fix VFP11 denorm erratum\n")); fprintf (file, _(" --no-enum-size-warning Don'''t warn about objects with incompatible\n" " enum sizes\n")); @@ -625,6 +628,10 @@ PARSE_AND_LIST_ARGS_CASES=' use_blx = 1; break;
+ case OPTION_NO_USE_BLX: + no_use_blx = 1; + break; + case OPTION_VFP11_DENORM_FIX: if (strcmp (optarg, "none") == 0) vfp11_denorm_fix = BFD_ARM_VFP11_FIX_NONE;