This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch] R_ARM_REL32 and Thumb functions.


On Thu, 2006-04-20 at 19:29, Paul Brook wrote:
> The attached patch makes the R_ARM_REL32 relocation set the low bit of the 
> value when the relocated symbol is a Thumb function, as required by the ARM 
> EABI.
> 
> I don't know if the current behavior is considered a bug or a feature for 
> pre-EABI objects. For now I'm assuming bug, and making the change 
> unconditionally. I can preserver the old behavior if anything depends on it.
> 
> A slight complication is that gas will try and fold relative expressions at 
> assembly time. This folding is done in generic code, so gets the value wrong. 
> e.g.
> 
> .thumb_func
> foo:
> .word foo - .
> 
> Will be folded to zero by gas/expr.c:expr.  I've [ab]used md_optimize_expr to 
> prevent this happening.
> 
> Initially I disabled the folding if either symbol was a Thumb function. 
> However this ends up breaking the explicit cfi directives in libgcc, so I've 
> only disabled the folding when the first symbol is a Thumb function.
> 
> Tested with cross to arm-eabi.
> Ok?
> 
> Paul
> 
> 2006-04-20  Paul Brook  <paul@codesourcery.com>
> 
> bfd/
> 	* elf32-arm.c (elf32_arm_final_link_relocate): Set thumb funciton bit
> 	for R_ARM_REL32.
> gas/
> 	* config/tc-arm.c (arm_optimize_expr): New function.
> 	(md_apply_fix): Set thumb funciton bit for PC-relative relocations.
> 	* config/tc-arm.c (md_optimize_expr): Define
> 	(arm_optimize_expr): Add prototype.
> 	(TC_FORCE_RELOCATION_SUB_SAME): Define.
> ld/testsuite/
> 	* ld-arm/arm-elf.exp: Add thumb-rel32.
> 	* ld-arm/thumb-rel32.d: New test.
> 	* ld-arm/thumb-rel32.s: New test.
> 
> ______________________________________________________________________
> Index: bfd/elf32-arm.c
> ===================================================================
> RCS file: /var/cvsroot/src-cvs/src/bfd/elf32-arm.c,v
> retrieving revision 1.70
> diff -u -p -r1.70 elf32-arm.c
> --- bfd/elf32-arm.c	16 Mar 2006 12:20:15 -0000	1.70
> +++ bfd/elf32-arm.c	20 Apr 2006 14:39:04 -0000
> @@ -3277,6 +3277,8 @@ elf32_arm_final_link_relocate (reloc_how
>  	  value -= (input_section->output_section->vma
>  		    + input_section->output_offset + rel->r_offset);
>  	  value += addend;
> +	  if (sym_flags == STT_ARM_TFUNC)
> +	    value |= 1;
>  	  break;
>  
>  	case R_ARM_PREL31:
> Index: gas/config/tc-arm.c
> ===================================================================
> RCS file: /var/cvsroot/src-cvs/src/gas/config/tc-arm.c,v
> retrieving revision 1.256
> diff -u -p -r1.256 tc-arm.c
> --- gas/config/tc-arm.c	7 Apr 2006 15:11:19 -0000	1.256
> +++ gas/config/tc-arm.c	20 Apr 2006 17:31:47 -0000
> @@ -11491,6 +11491,29 @@ get_thumb32_insn (char * buf)
>    return insn;
>  }
>  
> +
> +/* We usually want to set the low bit on the address of thumb function
> +   symbols.  In particular .word foo - . should have the low bit set.
> +   Generic code tries to fold the difference of two symbols to
> +   a constant.  Prevent this and force a relocation when the first symbols
> +   is a thumb function.  */
> +int
> +arm_optimize_expr (expressionS *l, operatorT op, expressionS *r)
> +{
> +  if (op == O_subtract
> +      && l->X_op == O_symbol
> +      && r->X_op == O_symbol
> +      && THUMB_IS_FUNC (l->X_add_symbol))
> +    {
> +      l->X_op = O_subtract;
> +      l->X_op_symbol = r->X_add_symbol;
> +      l->X_add_number -= r->X_add_number;
> +      return 1;
> +    }
> +  /* Process as normal.  */
> +  return 0;
> +}
> +
>  void
>  md_apply_fix (fixS *	fixP,
>  	       valueT * valP,
> @@ -12106,7 +12129,14 @@ md_apply_fix (fixS *	fixP,
>      case BFD_RELOC_ARM_TARGET1:
>      case BFD_RELOC_ARM_ROSEGREL32:
>      case BFD_RELOC_ARM_SBREL32:
> +      if (fixP->fx_done || !seg->use_rela_p)
> +	md_number_to_chars (buf, value, 4);
> +      break;
> +
>      case BFD_RELOC_32_PCREL:
> +      /* Set the low bit of the value if the target is a thumb function.  */
> +      if (fixP->fx_done && fixP->fx_addsy && THUMB_IS_FUNC(fixP->fx_addsy))
> +	value |= 1;

AFAICT, this is close, but not quite what AAELF says.  The relocation
expression is

	((S + A) | T) - .

That is, the T bit is orred in before the address of the place is
subtracted. 

Normally, this doesn't change anything since the relocation is used with
.word which has 4-byte alignment.  However, if a .4byte directive is
used, then there are no alignment constraints and the order of
processing becomes significant.

R.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]