public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH]: v850 pseudo-relocs can corrupt opcodes
@ 2005-05-17 12:32 Nick Clifton
  0 siblings, 0 replies; only message in thread
From: Nick Clifton @ 2005-05-17 12:32 UTC (permalink / raw)
  To: binutils

Hi Guys,

  A user recently reported a problem with the v850 toolchain whereby
  the pseudo relocs (lo(), hi(), etc) can result in the generation of
  corrupt instructions.  The cause was the fact that when the pseudo
  reloc was resolved to a value it was just plonked into the
  instruction's binary without following the correct insertion
  procedure for the corresponding operand.

  I am therefore applying the patch below to fix this problem and to
  add a test to the v850 testsuite to make sure that it does not
  happen again.

Cheers
  Nick

gas/ChangeLog
2005-05-17  Nick Clifton  <nickc@redhat.com>

	* config/tc-v850,h (TC_FIX_TYPE): Define.
	(TC_INIT_FIX_TYPE): Define.
	* config/tc-v850.c (md_assemble): When creating a fix record the
	operand in the tc_fix_data field.
	(md_apply_fix3): When applying a resolved fix use the operand's
	insertion procedure to store the value, if the operand has been
	recorded.

gas/testsuite/ChangeLog
2005-05-17  Nick Clifton  <nickc@redhat.com>

	* gas/v850/split-lo16.s: Add test for a lo() pseudo reloc
	corrupting an ld.w instruction.
	* gas/v850/split-lo16.d: Add expected, correct (ie not corrupt)
	output.

Index: gas/config/tc-v850.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-v850.c,v
retrieving revision 1.45
diff -c -3 -p -r1.45 tc-v850.c
*** gas/config/tc-v850.c	5 May 2005 09:13:04 -0000	1.45
--- gas/config/tc-v850.c	17 May 2005 11:48:05 -0000
*************** md_assemble (char *str)
*** 2125,2130 ****
--- 2125,2132 ----
  			      reloc_howto->pc_relative,
  			      reloc);
  
+ 	  fixP->tc_fix_data = (void *) operand;
+ 
  	  switch (reloc)
  	    {
  	    case BFD_RELOC_LO16:
*************** md_apply_fix3 (fixS *fixP, valueT *value
*** 2319,2334 ****
        /* We still have to insert the value into memory!  */
        where = fixP->fx_frag->fr_literal + fixP->fx_where;
  
!       if (fixP->fx_r_type == BFD_RELOC_V850_LO16_SPLIT_OFFSET)
! 	bfd_putl32 (((value << 16) & 0xfffe0000)
! 		    | ((value << 5) & 0x20)
! 		    | (bfd_getl32 (where) & ~0xfffe0020), where);
!       else if (fixP->fx_size == 1)
! 	*where = value & 0xff;
!       else if (fixP->fx_size == 2)
! 	bfd_putl16 (value & 0xffff, (unsigned char *) where);
!       else if (fixP->fx_size == 4)
! 	bfd_putl32 (value, (unsigned char *) where);
      }
  }
  \f
--- 2321,2362 ----
        /* We still have to insert the value into memory!  */
        where = fixP->fx_frag->fr_literal + fixP->fx_where;
  
!       if (fixP->tc_fix_data != NULL)
! 	{
! 	  struct v850_operand * operand = (struct v850_operand *) fixP->tc_fix_data;
! 	  unsigned long insn;
! 
! 	  /* The variable "where" currently points at the exact point inside
! 	     the insn where we need to insert the value.  But we need to
! 	     extract the entire insn so we probably need to move "where"
! 	     back a few bytes.  */
! 	  if (fixP->fx_size == 2)
! 	    where -= 2;
! 	  else if (fixP->fx_size == 1)
! 	    where -= 3;
! 
! 	  insn = bfd_getl32 ((unsigned char *) where);
! 
! 	  /* Use the operand's insertion procedure, if present, in order to
! 	     make sure that the value is correctly stored in the insn.  */
! 	  insn = v850_insert_operand (insn, operand, (offsetT) value,
! 				      fixP->fx_file, fixP->fx_line, NULL);
! 
! 	  bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
! 	}
!       else
! 	{
! 	  if (fixP->fx_r_type == BFD_RELOC_V850_LO16_SPLIT_OFFSET)
! 	    bfd_putl32 (((value << 16) & 0xfffe0000)
! 			| ((value << 5) & 0x20)
! 			| (bfd_getl32 (where) & ~0xfffe0020), where);
! 	  else if (fixP->fx_size == 1)
! 	    *where = value & 0xff;
! 	  else if (fixP->fx_size == 2)
! 	    bfd_putl16 (value & 0xffff, (unsigned char *) where);
! 	  else if (fixP->fx_size == 4)
! 	    bfd_putl32 (value, (unsigned char *) where);
! 	}
      }
  }
  \f
Index: gas/config/tc-v850.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-v850.h,v
retrieving revision 1.18
diff -c -3 -p -r1.18 tc-v850.h
*** gas/config/tc-v850.h	5 May 2005 09:13:04 -0000	1.18
--- gas/config/tc-v850.h	17 May 2005 11:48:05 -0000
*************** extern void v850_handle_align (fragS *);
*** 78,80 ****
--- 78,85 ----
  extern long v850_pcrel_from_section (struct fix *, asection *);
  
  #define DWARF2_LINE_MIN_INSN_LENGTH 2
+ 
+ /* We need to record the operand involved when a pseudo-reloc is
+    processed so that the resulting value can be inserted correctly.  */
+ #define TC_FIX_TYPE             void *
+ #define TC_INIT_FIX_DATA(fixP)  (fixP)->tc_fix_data = NULL
Index: gas/testsuite/gas/v850/split-lo16.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/v850/split-lo16.d,v
retrieving revision 1.1
diff -c -3 -p -r1.1 split-lo16.d
*** gas/testsuite/gas/v850/split-lo16.d	16 Dec 2004 16:56:04 -0000	1.1
--- gas/testsuite/gas/v850/split-lo16.d	17 May 2005 11:49:37 -0000
***************
*** 13,16 ****
--- 13,18 ----
  			c: R_V850_LO16_SPLIT_OFFSET	foo
    10:	a1 17 45 23 	ld\.bu	9029\[r1\],r2
    14:	81 17 57 34 	ld\.bu	13398\[r1\],r2
+   18:	20 57 01 00 	ld.w	0\[r0\],r10
+   1c:	20 57 79 56 	ld.w	22136\[r0\],r10
  #pass
Index: gas/testsuite/gas/v850/split-lo16.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/v850/split-lo16.s,v
retrieving revision 1.1
diff -c -3 -p -r1.1 split-lo16.s
*** gas/testsuite/gas/v850/split-lo16.s	16 Dec 2004 16:56:04 -0000	1.1
--- gas/testsuite/gas/v850/split-lo16.s	17 May 2005 11:49:37 -0000
***************
*** 5,7 ****
--- 5,11 ----
  
  	ld.bu	lo(0x12345),r1,r2
  	ld.bu	lo(0x123456),r1,r2
+ 
+ 	ld.w lo(0)[r0], r10
+ 	ld.w lo(0x12345678)[r0], r10
+ 

  

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-05-17 11:55 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-05-17 12:32 [PATCH]: v850 pseudo-relocs can corrupt opcodes Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).