* config/tc-arm.c (symbol_preemptible): New function.
authorRichard Earnshaw <richard.earnshaw@arm.com>
Tue, 18 Jun 2013 14:41:09 +0000 (14:41 +0000)
committerRichard Earnshaw <richard.earnshaw@arm.com>
Tue, 18 Jun 2013 14:41:09 +0000 (14:41 +0000)
(relax_branch): Use it.

gas/ChangeLog
gas/config/tc-arm.c

index 9c0147f553d95c7c034908a338f602fef7bf2f2a..e3d3580031d830d39837839c23505fe3883ecf8b 100644 (file)
@@ -1,3 +1,8 @@
+2013-06-18  Richard Earnshaw  <rearnsha@arm.com>
+
+       * config/tc-arm.c (symbol_preemptible): New function.
+       (relax_branch): Use it.
+
 2013-06-17  Catherine Moore  <clm@codesourcery.com>
            Maciej W. Rozycki  <macro@codesourcery.com>
            Chao-Ying Fu  <fu@mips.com>
index 72eb0de60c27008ad8dcccd11bb4d4bf84ecd39e..3a34a5f872eb6385a13365500c399440444e6dbb 100644 (file)
@@ -20215,6 +20215,30 @@ relax_addsub (fragS *fragp, asection *sec)
     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 *sec, int bits, long stretch)
     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;