aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2006-05-02 13:09:18 +0000
committerPaul Brook <paul@codesourcery.com>2006-05-02 13:09:18 +0000
commita8bc6c780e54b1dad7c356c815965f87df0314c7 (patch)
tree76bd0fd7da2825c7b9a1f69be8ac0e03935cb634 /gas
parent7cc27f03b90c3fad20b4fc535f448c4ee42932d0 (diff)
downloadfsf-binutils-gdb-a8bc6c780e54b1dad7c356c815965f87df0314c7.zip
fsf-binutils-gdb-a8bc6c780e54b1dad7c356c815965f87df0314c7.tar.gz
fsf-binutils-gdb-a8bc6c780e54b1dad7c356c815965f87df0314c7.tar.bz2
2006-05-02 Paul Brook <paul@codesourcery.com>
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. * 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-arm/thumb-rel32.d: New test. * ld-arm/thumb-rel32.s: New test.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog7
-rw-r--r--gas/config/tc-arm.c23
-rw-r--r--gas/config/tc-arm.h9
3 files changed, 39 insertions, 0 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 718197b..8ab4b75 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,10 @@
+2006-05-02 Paul Brook <paul@codesourcery.com>
+
+ * config/tc-arm.c (arm_optimize_expr): New function.
+ * config/tc-arm.h (md_optimize_expr): Define
+ (arm_optimize_expr): Add prototype.
+ (TC_FORCE_RELOCATION_SUB_SAME): Define.
+
2006-05-02 Ben Elliston <bje@au.ibm.com>
* config/obj-elf.h (ELF_TARGET_SYMBOL_FIELDS): Make single bit
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index ff66a1d..3b588ac 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -15811,6 +15811,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 3b33324..f261577 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