diff --git a/gas/ChangeLog b/gas/ChangeLog index f79ce0380b..3e43d3fe8c 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2001-11-05 Martin Schwidefsky + + * 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 * configure.in (mips-*-netbsd*): Add support for target. diff --git a/gas/config/tc-s390.c b/gas/config/tc-s390.c index dc3b16f2ea..1f6f02c378 100644 --- a/gas/config/tc-s390.c +++ b/gas/config/tc-s390.c @@ -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) diff --git a/gas/config/tc-s390.h b/gas/config/tc-s390.h index ad201c38fb..67d9117534 100644 --- a/gas/config/tc-s390.h +++ b/gas/config/tc-s390.h @@ -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));