gas: enable PC-relative diff relocations on sparc64
authorJames Clarke <jrtc27@jrtc27.com>
Wed, 23 Aug 2017 12:46:45 +0000 (05:46 -0700)
committerJose E. Marchesi <jose.marchesi@oracle.com>
Wed, 23 Aug 2017 12:46:45 +0000 (05:46 -0700)
gas/
* config/tc-sparc.c (tc_gen_reloc): Convert BFD_RELOC_8/16/32/64
into the corresponding BFD_RELOC_8/16/32/64_PCREL relocation
when requested.
* config/tc-sparc.h (DIFF_EXPR_OK): Define to enable PC-relative
diff relocations.
(TC_FORCE_RELOCATION_SUB_LOCAL): Define to ensure only supported
relocations are made PC-relative.
(CFI_DIFF_EXPR_OK): Define to 0 to force BFD_RELOC_32_PCREL to
be used directly, since otherwise BFD_RELOC_SPARC_UA32 will be
used for .eh_frame which cannot in general be converted to a
BFD_RELOC_32_PCREL due to alignment requirements.

gas/ChangeLog
gas/config/tc-sparc.c
gas/config/tc-sparc.h

index 27fba7240ff9cb6ce9e033bdc93705e9ec1847a0..328037e79d73829cd8409963f5cc633f54169911 100644 (file)
@@ -1,3 +1,17 @@
+2017-08-23  James Clarke  <jrtc27@jrtc27.com>
+
+       * config/tc-sparc.c (tc_gen_reloc): Convert BFD_RELOC_8/16/32/64
+       into the corresponding BFD_RELOC_8/16/32/64_PCREL relocation
+       when requested.
+       * config/tc-sparc.h (DIFF_EXPR_OK): Define to enable PC-relative
+       diff relocations.
+       (TC_FORCE_RELOCATION_SUB_LOCAL): Define to ensure only supported
+       relocations are made PC-relative.
+       (CFI_DIFF_EXPR_OK): Define to 0 to force BFD_RELOC_32_PCREL to
+       be used directly, since otherwise BFD_RELOC_SPARC_UA32 will be
+       used for .eh_frame which cannot in general be converted to a
+       BFD_RELOC_32_PCREL due to alignment requirements.
+
 2017-08-22  Alan Modra  <amodra@gmail.com>
 
        * testsuite/gas/ppc/lsp-checks.d: Assemble with -a32.
index 692a1873f41f2ac86a8fccd86694abcb7099adfa..6d1b038daa23c8cd1485871f7649c7c9e4bfe110 100644 (file)
@@ -3946,8 +3946,33 @@ tc_gen_reloc (asection *section, fixS *fixp)
 
   switch (fixp->fx_r_type)
     {
+    case BFD_RELOC_8:
     case BFD_RELOC_16:
     case BFD_RELOC_32:
+    case BFD_RELOC_64:
+      if (fixp->fx_pcrel)
+       {
+         switch (fixp->fx_size)
+           {
+           default:
+             as_bad_where (fixp->fx_file, fixp->fx_line,
+                           _("can not do %d byte pc-relative relocation"),
+                           fixp->fx_size);
+             code = fixp->fx_r_type;
+             fixp->fx_pcrel = 0;
+             break;
+           case 1: code = BFD_RELOC_8_PCREL;  break;
+           case 2: code = BFD_RELOC_16_PCREL; break;
+           case 4: code = BFD_RELOC_32_PCREL; break;
+#ifdef BFD64
+           case 8: code = BFD_RELOC_64_PCREL; break;
+#endif
+           }
+         if (fixp->fx_pcrel)
+           fixp->fx_addnumber = fixp->fx_offset;
+         break;
+       }
+      /* Fall through.  */
     case BFD_RELOC_HI22:
     case BFD_RELOC_LO10:
     case BFD_RELOC_32_PCREL_S2:
@@ -3960,7 +3985,6 @@ tc_gen_reloc (asection *section, fixS *fixp)
     case BFD_RELOC_SPARC_WDISP16:
     case BFD_RELOC_SPARC_WDISP19:
     case BFD_RELOC_SPARC_WDISP22:
-    case BFD_RELOC_64:
     case BFD_RELOC_SPARC_5:
     case BFD_RELOC_SPARC_6:
     case BFD_RELOC_SPARC_7:
index 3dd2483cd7183d4a838cfe895d86f1eec09b9c52..f24460cefd63d687f774cc4d78ff3c82fa953a9f 100644 (file)
@@ -77,6 +77,8 @@ extern void sparc_handle_align (struct frag *);
 
 #define MAX_MEM_FOR_RS_ALIGN_CODE  (3 + 4 + 4)
 
+#define DIFF_EXPR_OK    /* foo-. gets turned into PC relative relocs */
+
 /* I know that "call 0" fails in sparc-coff if this doesn't return 1.  I
    don't know about other relocation types, or other formats, yet.  */
 #ifdef OBJ_COFF
@@ -128,6 +130,15 @@ extern void sparc_handle_align (struct frag *);
 /* Finish up the entire symtab.  */
 #define tc_adjust_symtab() sparc_adjust_symtab ()
 extern void sparc_adjust_symtab (void);
+
+/* Don't allow the generic code to convert fixups involving the
+   subtraction of a label in the current section to pc-relative if we
+   don't have the necessary pc-relative relocation.  */
+#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG)                \
+  (!((FIX)->fx_r_type == BFD_RELOC_64                  \
+     || (FIX)->fx_r_type == BFD_RELOC_32               \
+     || (FIX)->fx_r_type == BFD_RELOC_16               \
+     || (FIX)->fx_r_type == BFD_RELOC_8))
 #endif
 
 #ifdef OBJ_AOUT
@@ -200,4 +211,10 @@ extern int sparc_cie_data_alignment;
 #define DWARF2_DEFAULT_RETURN_COLUMN    15
 #define DWARF2_CIE_DATA_ALIGNMENT       sparc_cie_data_alignment
 
+/* cons_fix_new_sparc will chooose BFD_RELOC_SPARC_UA32 for the difference
+   expressions, but there is no corresponding PC-relative relocation; as this
+   is for debugging info though, alignment does not matter, so by disabling
+   this, BFD_RELOC_32_PCREL will be emitted directly instead.  */
+#define CFI_DIFF_EXPR_OK 0
+
 /* end of tc-sparc.h */