From 8e41e2f8d96fa245f7d3d4b7c242faaf88e45930 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Mon, 1 May 2006 16:27:16 +0000 Subject: [PATCH] 2006-05-01 Paul Brook * bfd/elf32-arm.c (elf32_arm_final_link_relocate): Set thumb funciton bit for R_ARM_REL32. * gas/config/tc-arm.c (arm_optimize_expr): New function. * gas/config/tc-arm.h (md_optimize_expr): Define (arm_optimize_expr): Add prototype. (TC_FORCE_RELOCATION_SUB_SAME): Define. * ld/testsuite/ld-arm/arm-elf.exp: Add thumb-rel32. * ld/testsuite/ld-arm/thumb-rel32.d: New test. * ld/testsuite/ld-arm/thumb-rel32.s: New test. --- ChangeLog.csl | 12 ++++++++++++ bfd/elf32-arm.c | 4 +++- gas/config/tc-arm.c | 23 +++++++++++++++++++++++ gas/config/tc-arm.h | 9 +++++++++ ld/testsuite/ld-arm/arm-elf.exp | 3 +++ ld/testsuite/ld-arm/thumb-rel32.d | 7 +++++++ ld/testsuite/ld-arm/thumb-rel32.s | 18 ++++++++++++++++++ 7 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 ld/testsuite/ld-arm/thumb-rel32.d create mode 100644 ld/testsuite/ld-arm/thumb-rel32.s diff --git a/ChangeLog.csl b/ChangeLog.csl index 8200983079b..999bf93ffb3 100644 --- a/ChangeLog.csl +++ b/ChangeLog.csl @@ -1,3 +1,15 @@ +2006-05-01 Paul Brook + + * bfd/elf32-arm.c (elf32_arm_final_link_relocate): Set thumb funciton + bit for R_ARM_REL32. + * gas/config/tc-arm.c (arm_optimize_expr): New function. + * gas/config/tc-arm.h (md_optimize_expr): Define + (arm_optimize_expr): Add prototype. + (TC_FORCE_RELOCATION_SUB_SAME): Define. + * ld/testsuite/ld-arm/arm-elf.exp: Add thumb-rel32. + * ld/testsuite/ld-arm/thumb-rel32.d: New test. + * ld/testsuite/ld-arm/thumb-rel32.s: New test. + 2006-04-29 Paul Brook * opcodes/arm-dis.c (coprocessor_opcodes): Add %c to unconditional diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index ca33121708d..f64f5d6feee 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -3274,9 +3274,11 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, break; case R_ARM_REL32: + value += addend; + if (sym_flags == STT_ARM_TFUNC) + value |= 1; value -= (input_section->output_section->vma + input_section->output_offset + rel->r_offset); - value += addend; break; case R_ARM_PREL31: diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index e050bf43308..ea2ee5f3d49 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -15855,6 +15855,29 @@ get_thumb32_insn (char * buf) return insn; } + +/* We usually want to set the low bit on the address of thumb function + symbols. In particular .word foo - . should have the low bit set. + Generic code tries to fold the difference of two symbols to + a constant. Prevent this and force a relocation when the first symbols + is a thumb function. */ +int +arm_optimize_expr (expressionS *l, operatorT op, expressionS *r) +{ + if (op == O_subtract + && l->X_op == O_symbol + && r->X_op == O_symbol + && THUMB_IS_FUNC (l->X_add_symbol)) + { + l->X_op = O_subtract; + l->X_op_symbol = r->X_add_symbol; + l->X_add_number -= r->X_add_number; + return 1; + } + /* Process as normal. */ + return 0; +} + void md_apply_fix (fixS * fixP, valueT * valP, diff --git a/gas/config/tc-arm.h b/gas/config/tc-arm.h index 3b33324053d..f2615770c47 100644 --- a/gas/config/tc-arm.h +++ b/gas/config/tc-arm.h @@ -83,6 +83,9 @@ struct fix; arm_relax_frag(segment, fragp, stretch) extern int arm_relax_frag (asection *, struct frag *, long); +#define md_optimize_expr(l,o,r) arm_optimize_expr (l, o, r) +extern int arm_optimize_expr (expressionS *, operatorT, expressionS *); + #define md_cleanup() arm_cleanup () #define md_start_line_hook() arm_start_line_hook () @@ -148,6 +151,12 @@ extern void arm_md_end (void); || (FIX)->fx_r_type == BFD_RELOC_32 \ || TC_FORCE_RELOCATION (FIX)) +/* Force output of R_ARM_REL32 relocations against thumb function symbols. + This is needed to ensure the low bit is handled correctly. */ +#define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEG) \ + (THUMB_IS_FUNC ((FIX)->fx_addsy) \ + || !SEG_NORMAL (SEG)) + #define TC_CONS_FIX_NEW cons_fix_new_arm #define MAX_MEM_FOR_RS_ALIGN_CODE 31 diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index 1cb231faf14..1a9fc00aeb8 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -119,6 +119,9 @@ set armelftests { {"Thumb entry point" "-T arm.ld" "" {thumb-entry.s} {{readelf -h thumb-entry.d}} "thumb-entry"} + {"thumb-rel32" "-static -T arm.ld" "" {thumb-rel32.s} + {{objdump -s thumb-rel32.d}} + "thumb-rel32"} } run_ld_link_tests $armelftests diff --git a/ld/testsuite/ld-arm/thumb-rel32.d b/ld/testsuite/ld-arm/thumb-rel32.d new file mode 100644 index 00000000000..34cde4d729e --- /dev/null +++ b/ld/testsuite/ld-arm/thumb-rel32.d @@ -0,0 +1,7 @@ + +.*: file format.* + +Contents of section .text: + 8000 (00000011 fffffffd 00ffffff f8000000|11000000 fdffffff 00f8ffff ff000000) .* +# Ignore .ARM.attributes section +#... diff --git a/ld/testsuite/ld-arm/thumb-rel32.s b/ld/testsuite/ld-arm/thumb-rel32.s new file mode 100644 index 00000000000..83eb0e527d3 --- /dev/null +++ b/ld/testsuite/ld-arm/thumb-rel32.s @@ -0,0 +1,18 @@ + .text + .arch armv4t + .global _start + .type _start, %function + .thumb_func +_start: + .word bar - . + .word _start - . + .byte 0 + .4byte (_start - .) + 1 + .byte 0, 0, 0 + .section .after, "ax", %progbits + .global bar + .type bar, %function + .thumb_func +bar: + .word 0 + .ident "GCC: (GNU) 4.1.0 (CodeSourcery ARM)" -- 2.47.2