Force got and plt relocations.
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 5 Nov 2001 08:47:46 +0000 (08:47 +0000)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 5 Nov 2001 08:47:46 +0000 (08:47 +0000)
gas/ChangeLog
gas/config/tc-s390.c
gas/config/tc-s390.h

index f79ce0380b4a75c5be25796a515d9a581dc01164..3e43d3fe8cd091af1aa2c8de6043c7b9e4c2383c 100644 (file)
@@ -1,3 +1,13 @@
+2001-11-05  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+       * config/tc-s390.c (tc_s390_force_relocation): Force all relocations
+       that need the global offset table.
+       (md_apply_fix3): Add code to undo opertions done in fixup_segment
+       triggered by TC_FORCE_RELOCATION.
+       * config/tc-s390.h (TC_FORCE_RELOCATION): Replace macro code with
+       a call to function tc_s390_force_relocation.
+       (TC_FIX_ADJUSTABLE): Define.
+
 2001-11-04  Chris Demetriou  <cgd@broadcom.com>
 
        * configure.in (mips-*-netbsd*): Add support for target.
index dc3b16f2ea66880f4d5e1da670a07ea4c68e47f5..1f6f02c37844bb4f2b94c38a31b8ce5fadba0144 100644 (file)
@@ -1641,6 +1641,36 @@ tc_s390_fix_adjustable(fixP)
   return 1;
 }
 
+/* Return true if we must always emit a reloc for a type and false if
+   there is some hope of resolving it a assembly time.  */
+int
+tc_s390_force_relocation (fixp)
+     struct fix *fixp;
+{
+  /* Ensure we emit a relocation for every reference to the global
+     offset table or to the procedure link table.  */
+  switch (fixp->fx_r_type)
+    {
+    case BFD_RELOC_390_GOT12:
+    case BFD_RELOC_32_GOT_PCREL:
+    case BFD_RELOC_32_GOTOFF:
+    case BFD_RELOC_390_GOTPC:
+    case BFD_RELOC_390_GOT16:
+    case BFD_RELOC_390_GOTPCDBL:
+    case BFD_RELOC_390_GOT64:
+    case BFD_RELOC_390_GOTENT:
+    case BFD_RELOC_390_PLT32:
+    case BFD_RELOC_390_PLT16DBL:
+    case BFD_RELOC_390_PLT32DBL:
+    case BFD_RELOC_390_PLT64:
+    case BFD_RELOC_VTABLE_INHERIT:
+    case BFD_RELOC_VTABLE_ENTRY:
+      return 1;
+    default:
+      return 0;
+    }
+}
+
 /* Apply a fixup to the object code.  This is called for all the
    fixups we generated by the call to fix_new_exp, above.  In the call
    above we used a reloc code which was the largest legal reloc code
@@ -1654,7 +1684,7 @@ int
 md_apply_fix3 (fixp, valuep, seg)
      fixS *fixp;
      valueT *valuep;
-     segT seg ATTRIBUTE_UNUSED;
+     segT seg;
 {
   char *where;
   valueT value;
@@ -1662,22 +1692,34 @@ md_apply_fix3 (fixp, valuep, seg)
   value = *valuep;
   where = fixp->fx_frag->fr_literal + fixp->fx_where;
 
-  if (fixp->fx_subsy != NULL)
+  if (fixp->fx_subsy != NULL) 
     {
+      if ((fixp->fx_addsy != NULL
+          && S_GET_SEGMENT (fixp->fx_addsy) == S_GET_SEGMENT (fixp->fx_subsy)
+          && SEG_NORMAL (S_GET_SEGMENT (fixp->fx_addsy)))
+         || (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section))
+       value += S_GET_VALUE (fixp->fx_subsy);
       if (!S_IS_DEFINED (fixp->fx_subsy))
        as_bad_where (fixp->fx_file, fixp->fx_line,
                      _("unresolved fx_subsy symbol that must be resolved"));
       value -= S_GET_VALUE(fixp->fx_subsy);
-    }
 
-  if (fixp->fx_addsy != NULL)
+      if (S_GET_SEGMENT (fixp->fx_subsy) == seg && ! fixp->fx_pcrel)
+       value += MD_PCREL_FROM_SECTION (fixp, seg);
+    }
+  
+  if (fixp->fx_addsy != NULL) 
     {
-      /* `*valuep' may contain the value of the symbol on which the reloc
-        will be based; we have to remove it.  */
-      if (fixp->fx_addsy->sy_used_in_reloc
-         && S_GET_SEGMENT (fixp->fx_addsy) != absolute_section
-         && S_GET_SEGMENT (fixp->fx_addsy) != undefined_section
-         && ! bfd_is_com_section (S_GET_SEGMENT (fixp->fx_addsy)))
+      if ((fixp->fx_subsy != NULL
+          && S_GET_SEGMENT (fixp->fx_addsy) == S_GET_SEGMENT (fixp->fx_subsy)
+          && SEG_NORMAL (S_GET_SEGMENT(fixp->fx_addsy)))
+         || (S_GET_SEGMENT (fixp->fx_addsy) == seg
+             && fixp->fx_pcrel && TC_RELOC_RTSYM_LOC_FIXUP (fixp))
+         || (!fixp->fx_pcrel 
+             && S_GET_SEGMENT (fixp->fx_addsy) == absolute_section)
+         || (S_GET_SEGMENT (fixp->fx_addsy) != undefined_section
+             && !bfd_is_com_section (S_GET_SEGMENT (fixp->fx_addsy))
+             && TC_FIX_ADJUSTABLE(fixp)))
        value -= S_GET_VALUE (fixp->fx_addsy);
 
       if (fixp->fx_pcrel)
index ad201c38fb1bd164e9a24d3e789ff54619ba1ac4..67d9117534a043735ff62ed782fdb5c4f68eab25 100644 (file)
@@ -44,13 +44,15 @@ struct fix;
            && S_IS_DEFINED ((FIX)->fx_addsy)      \
            && ! S_IS_COMMON ((FIX)->fx_addsy))))
 
-#define TC_FORCE_RELOCATION(FIXP)       \
-  ((FIXP)->fx_r_type == BFD_RELOC_VTABLE_INHERIT       \
-   || (FIXP)->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+#define TC_FORCE_RELOCATION(FIXP) tc_s390_force_relocation(FIXP)
+extern int tc_s390_force_relocation PARAMS ((struct fix *));
 
 #define tc_fix_adjustable(X)  tc_s390_fix_adjustable(X)
 extern int tc_s390_fix_adjustable PARAMS ((struct fix *));
 
+#define TC_FIX_ADJUSTABLE(fixP) \
+  (! symbol_used_in_reloc_p ((fixP)->fx_addsy) && tc_fix_adjustable (fixP))
+
 /* The target BFD architecture.  */
 #define TARGET_ARCH bfd_arch_s390
 extern enum bfd_architecture s390_arch PARAMS ((void));