[GAS, ARM] Allow relaxation of all non-preemptible symbols
Richard Earnshaw
rearnsha@arm.com
Tue Jun 18 14:47:00 GMT 2013
Gas is currently being over conservative about which symbols in Thumb2
can be relaxed into shorter branches. In practice it is only unsafe to
relax a symbol which can be pre-empted. That means the symbols must be
global and (in the case of ELF) have default visibility.
This patch introduces a new support function symbol_preemptible and then
uses it in relax_branch to determine when relaxation is safe.
Tested on bare-metal and linux hosts. Installed on trunk.
R.
2013-06-18 Richard Earnshaw <rearnsha@arm.com>
* config/tc-arm.c (symbol_preemptible): New function.
(relax_branch): Use it.
-------------- next part --------------
Index: tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.569
diff -u -p -r1.569 tc-arm.c
--- tc-arm.c 28 May 2013 14:58:51 -0000 1.569
+++ tc-arm.c 18 Jun 2013 14:38:31 -0000
@@ -20215,6 +20215,30 @@ relax_addsub (fragS *fragp, asection *se
return relax_immediate (fragp, 3, 0);
}
+/* Return TRUE iff the definition of symbol S could be pre-empted
+ (overridden) at link or load time. */
+static bfd_boolean
+symbol_preemptible (symbolS *s)
+{
+ /* Weak symbols can always be pre-empted. */
+ if (S_IS_WEAK (s))
+ return TRUE;
+
+ /* Non-global symbols cannot be pre-empted. */
+ if (! S_IS_EXTERNAL (s))
+ return FALSE;
+
+#ifdef OBJ_ELF
+ /* In ELF, a global symbol can be marked protected, or private. In that
+ case it can't be pre-empted (other definitions in the same link unit
+ would violate the ODR). */
+ if (ELF_ST_VISIBILITY (S_GET_OTHER (s)) > STV_DEFAULT)
+ return FALSE;
+#endif
+
+ /* Other global symbols might be pre-empted. */
+ return TRUE;
+}
/* Return the size of a relaxable branch instruction. BITS is the
size of the offset field in the narrow instruction. */
@@ -20233,16 +20257,14 @@ relax_branch (fragS *fragp, asection *se
return 4;
#ifdef OBJ_ELF
+ /* A branch to a function in ARM state will require interworking. */
if (S_IS_DEFINED (fragp->fr_symbol)
&& ARM_IS_FUNC (fragp->fr_symbol))
return 4;
+#endif
- /* PR 12532. Global symbols with default visibility might
- be preempted, so do not relax relocations to them. */
- if ((ELF_ST_VISIBILITY (S_GET_OTHER (fragp->fr_symbol)) == STV_DEFAULT)
- && (! S_IS_LOCAL (fragp->fr_symbol)))
+ if (symbol_preemptible (fragp->fr_symbol))
return 4;
-#endif
val = relaxed_symbol_addr (fragp, stretch);
addr = fragp->fr_address + fragp->fr_fix + 4;
More information about the Binutils
mailing list