* symbols.c (S_FORCE_RELOC): Return true for indirect functions
	even if !strict.
	* expr.c (operand): Don't convert absolute symbols to constants
	if S_FORCE_RELOC is true.
	(expr): Only reduce subtractions between different symbols if
	S_FORCE_RELOC is false for both of them.
	* write.c (fixup_segment): Don't remove symbols if S_FORCE_RELOC
	is true for them, regardless of their segment.

gas/testsuite/
	* gas/i386/ifunc-2.s, gas/i386/ifunc-2.l: New test.
	* gas/i386/ifunc-3.s, gas/i386/ifunc-3.d: Likeise.
	* gas/i386/i386.exp: Run them.
This commit is contained in:
Richard Sandiford 2010-12-02 13:25:13 +00:00
parent 0c98115d15
commit c969da6473
10 changed files with 308 additions and 4 deletions

View file

@ -1325,7 +1325,9 @@ operand (expressionS *expressionP, enum expr_mode mode)
/* If we have an absolute symbol or a reg, then we know its
value now. */
segment = S_GET_SEGMENT (symbolP);
if (mode != expr_defer && segment == absolute_section)
if (mode != expr_defer
&& segment == absolute_section
&& !S_FORCE_RELOC (symbolP, 0))
{
expressionP->X_op = O_constant;
expressionP->X_add_number = S_GET_VALUE (symbolP);
@ -1840,7 +1842,9 @@ expr (int rankarg, /* Larger # is higher rank. */
#ifdef md_allow_local_subtract
&& md_allow_local_subtract (resultP, & right, rightseg)
#endif
&& (SEG_NORMAL (rightseg)
&& ((SEG_NORMAL (rightseg)
&& !S_FORCE_RELOC (resultP->X_add_symbol, 0)
&& !S_FORCE_RELOC (right.X_add_symbol, 0))
|| right.X_add_symbol == resultP->X_add_symbol)
&& frag_offset_fixed_p (symbol_get_frag (resultP->X_add_symbol),
symbol_get_frag (right.X_add_symbol),
@ -1954,7 +1958,10 @@ expr (int rankarg, /* Larger # is higher rank. */
else if (op_left == O_subtract)
{
resultP->X_add_number -= right.X_add_number;
if (retval == rightseg && SEG_NORMAL (retval))
if (retval == rightseg
&& SEG_NORMAL (retval)
&& !S_FORCE_RELOC (resultP->X_add_symbol, 0)
&& !S_FORCE_RELOC (right.X_add_symbol, 0))
{
retval = absolute_section;
rightseg = absolute_section;