diff options
author | Cl?ment Chigot <clement.chigot@atos.net> | 2021-04-20 14:40:43 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2021-04-20 14:40:43 +0100 |
commit | c5df7e442e6cdc9303b7373842370d6ee8f67ea5 (patch) | |
tree | 28e1442062fdbb13b5c46d98ceeba9c556e6f3b0 /gas | |
parent | d549b029d6d622af531211ef4c7bc48cb5011d93 (diff) | |
download | gdb-c5df7e442e6cdc9303b7373842370d6ee8f67ea5.zip gdb-c5df7e442e6cdc9303b7373842370d6ee8f67ea5.tar.gz gdb-c5df7e442e6cdc9303b7373842370d6ee8f67ea5.tar.bz2 |
Rework the R_NEG support on both gas and ld for the PowerPC AIX targets, in order to manage C++ exceptions built with GCC.
bfd PR binutils/21700
* reloc.c (BFD_RELOC_PPC_NEG): New relocation.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* coff-rs6000.c (_bfd_xcoff_reloc_type_lookup): Add
BFD_RELOC_PPC_NEG handler.
(xcoff_reloc_type_neg): Correctly substract addend.
* coff64-rs6000.c (xcoff64_howto_table): Add R_NEG_32
howto.
(xcoff64_rtype2howto): Add handler for R_NEG_32.
(xcoff64_reloc_type_lookup): Add BFD_RELOC_PPC_NEG handler.
* xcofflink.c (xcoff_need_ldrel_p): Check output section
for R_POS-like relocations. New argument added.
(xcoff_mark): Adapt to new xcoff_need_ldrel_p argument.
(xcoff_link_input_bfd): Likewise.
gas * config/tc-ppc.c (ppc_get_csect_to_adjust): New function.
(ppc_fix_adjustable): Manage fx_subsy part.
(tc_gen_reloc): Create second relocation when both
fx_addsy and fx_subsy are provided.
* config/tc-ppc.h (RELOC_EXPANSION_POSSIBLE): New define.
(MAX_RELOC_EXPANSION): Likewise.
(TC_FORCE_RELOCATION_SUB_SAME): Likewise
(UNDEFINED_DIFFERENCE_OK): Likewise
* testsuite/gas/all/gas.exp: Skip difference between two
undefined symbols test.
ld * testsuite/ld-powerpc/aix52.exp: Add new test.
* testsuite/ld-powerpc/aix-neg-reloc-32.d: New test.
* testsuite/ld-powerpc/aix-neg-reloc-64.d: New test.
* testsuite/ld-powerpc/aix-neg-reloc.ex: New test.
* testsuite/ld-powerpc/aix-neg-reloc.s: New test.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 14 | ||||
-rw-r--r-- | gas/config/tc-ppc.c | 102 | ||||
-rw-r--r-- | gas/config/tc-ppc.h | 19 |
3 files changed, 107 insertions, 28 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 5111ace..c8ef5f3 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,17 @@ +2021-04-20 Clément Chigot <clement.chigot@atos.net> + + PR binutils/21700 + * config/tc-ppc.c (ppc_get_csect_to_adjust): New function. + (ppc_fix_adjustable): Manage fx_subsy part. + (tc_gen_reloc): Create second relocation when both + fx_addsy and fx_subsy are provided. + * config/tc-ppc.h (RELOC_EXPANSION_POSSIBLE): New define. + (MAX_RELOC_EXPANSION): Likewise. + (TC_FORCE_RELOCATION_SUB_SAME): Likewise + (UNDEFINED_DIFFERENCE_OK): Likewise + * testsuite/gas/all/gas.exp: Skip difference between two + undefined symbols test. + 2021-04-19 Nick Clifton <nickc@redhat.com> * testsuite/gas/all/gas.exp: Add rs6000*-*-aix* to the list of diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index c719b40..7715fc5 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -6264,6 +6264,45 @@ md_pcrel_from_section (fixS *fixp, segT sec ATTRIBUTE_UNUSED) #ifdef OBJ_XCOFF +/* Return the surrending csect for sym when possible. */ + +static symbolS* +ppc_get_csect_to_adjust (symbolS *sym) +{ + if (sym == NULL) + return NULL; + + valueT val = resolve_symbol_value (sym); + TC_SYMFIELD_TYPE *tc = symbol_get_tc (sym); + segT symseg = S_GET_SEGMENT (sym); + + if (tc->subseg == 0 + && tc->symbol_class != XMC_TC0 + && tc->symbol_class != XMC_TC + && tc->symbol_class != XMC_TE + && symseg != bss_section + && symseg != ppc_xcoff_tbss_section.segment + /* Don't adjust if this is a reloc in the toc section. */ + && (symseg != data_section + || ppc_toc_csect == NULL + || val < ppc_toc_frag->fr_address + || (ppc_after_toc_frag != NULL + && val >= ppc_after_toc_frag->fr_address))) + { + symbolS* csect = tc->within; + + /* If the symbol was not declared by a label (eg: a section symbol), + use the section instead of the csect. This doesn't happen in + normal AIX assembly code. */ + if (csect == NULL) + csect = seg_info (symseg)->sym; + + return csect; + } + + return NULL; +} + /* This is called to see whether a fixup should be adjusted to use a section symbol. We take the opportunity to change a fixup against a symbol in the TOC subsegment into a reloc against the @@ -6274,7 +6313,7 @@ ppc_fix_adjustable (fixS *fix) { valueT val = resolve_symbol_value (fix->fx_addsy); segT symseg = S_GET_SEGMENT (fix->fx_addsy); - TC_SYMFIELD_TYPE *tc; + symbolS* csect; if (symseg == absolute_section) return 0; @@ -6316,32 +6355,17 @@ ppc_fix_adjustable (fixS *fix) } /* Possibly adjust the reloc to be against the csect. */ - tc = symbol_get_tc (fix->fx_addsy); - if (tc->subseg == 0 - && tc->symbol_class != XMC_TC0 - && tc->symbol_class != XMC_TC - && tc->symbol_class != XMC_TE - && symseg != bss_section - && symseg != ppc_xcoff_tbss_section.segment - /* Don't adjust if this is a reloc in the toc section. */ - && (symseg != data_section - || ppc_toc_csect == NULL - || val < ppc_toc_frag->fr_address - || (ppc_after_toc_frag != NULL - && val >= ppc_after_toc_frag->fr_address))) + if ((csect = ppc_get_csect_to_adjust (fix->fx_addsy)) != NULL) { - symbolS *csect = tc->within; - - /* If the symbol was not declared by a label (eg: a section symbol), - use the section instead of the csect. This doesn't happen in - normal AIX assembly code. */ - if (csect == NULL) - csect = seg_info (symseg)->sym; - fix->fx_offset += val - symbol_get_frag (csect)->fr_address; fix->fx_addsy = csect; + } - return 0; + if ((csect = ppc_get_csect_to_adjust (fix->fx_subsy)) != NULL) + { + fix->fx_offset -= resolve_symbol_value (fix->fx_subsy) + - symbol_get_frag (csect)->fr_address; + fix->fx_subsy = csect; } /* Adjust a reloc against a .lcomm symbol to be against the base @@ -7367,12 +7391,14 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) /* Generate a reloc for a fixup. */ -arelent * +arelent ** tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) { + static arelent *relocs[3]; arelent *reloc; - reloc = XNEW (arelent); + relocs[0] = reloc = XNEW (arelent); + relocs[1] = NULL; reloc->sym_ptr_ptr = XNEW (asymbol *); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); @@ -7386,11 +7412,33 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) as_bad_where (fixp->fx_file, fixp->fx_line, _("reloc %d not supported by object file format"), (int) fixp->fx_r_type); - return NULL; + relocs[0] = NULL; } reloc->addend = fixp->fx_addnumber; - return reloc; + if (fixp->fx_subsy && fixp->fx_addsy) + { + relocs[1] = reloc = XNEW (arelent); + relocs[2] = NULL; + + reloc->sym_ptr_ptr = XNEW (asymbol *); + *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy); + reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; + + reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_PPC_NEG); + reloc->addend = fixp->fx_addnumber; + + if (reloc->howto == (reloc_howto_type *) NULL) + { + as_bad_where (fixp->fx_file, fixp->fx_line, + _("reloc %d not supported by object file format"), + BFD_RELOC_PPC_NEG); + relocs[0] = NULL; + } + } + + + return relocs; } void diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h index d38c7d4..790994e 100644 --- a/gas/config/tc-ppc.h +++ b/gas/config/tc-ppc.h @@ -284,10 +284,27 @@ extern int ppc_force_relocation (struct fix *); || (FIX)->fx_r_type == BFD_RELOC_PPC_16DX_HA \ || (FIX)->fx_r_type == BFD_RELOC_PPC64_D34 \ || (FIX)->fx_r_type == BFD_RELOC_PPC64_D28)) -#endif #define TC_VALIDATE_FIX_SUB(FIX, SEG) 0 +#endif /* OBJ_ELF */ + +#define RELOC_EXPANSION_POSSIBLE +#define MAX_RELOC_EXPANSION 2 + +#if defined (OBJ_XCOFF) +/* Force a relocation when the fix is negative. */ +#define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEG) \ + (GENERIC_FORCE_RELOCATION_SUB_SAME(FIX, SEG) \ + || (((SEG)->flags & SEC_DEBUGGING) == 0 \ + && (FIX)->fx_addsy && (FIX)->fx_subsy \ + && (S_GET_VALUE (fixP->fx_addsy) < S_GET_VALUE (fixP->fx_subsy)))) + +/* XCOFF allows undefined differences which will be encoded with + R_NEG relocations. */ +#define UNDEFINED_DIFFERENCE_OK +#endif /* OBJ_XCOFF */ + /* Various frobbings of labels and their addresses. */ #define md_start_line_hook() ppc_start_line_hook () extern void ppc_start_line_hook (void); |