From f6a36b0c9e537e4525f3b0687a4f76b4f77bf173 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Wed, 23 Aug 2017 05:46:45 -0700 Subject: [PATCH] gas: enable PC-relative diff relocations on sparc64 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 | 14 ++++++++++++++ gas/config/tc-sparc.c | 26 +++++++++++++++++++++++++- gas/config/tc-sparc.h | 17 +++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 27fba72..328037e 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,17 @@ +2017-08-23 James Clarke + + * 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 * testsuite/gas/ppc/lsp-checks.d: Assemble with -a32. diff --git a/gas/config/tc-sparc.c b/gas/config/tc-sparc.c index 692a187..6d1b038 100644 --- a/gas/config/tc-sparc.c +++ b/gas/config/tc-sparc.c @@ -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: diff --git a/gas/config/tc-sparc.h b/gas/config/tc-sparc.h index 3dd2483..f24460c 100644 --- a/gas/config/tc-sparc.h +++ b/gas/config/tc-sparc.h @@ -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 */ -- 2.7.4