This is the mail archive of the binutils@sourceware.cygnus.com 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]

Re: reloc overflows


On Sun, 12 Mar 2000, I wrote:

[part of a patch]
> -	  /* We explicitly permit wrap around if this relocation
> -	     covers the high bit of an address.  The Linux kernel
> -	     relies on it, and it is the only way to write assembler
> -	     code which can run when loaded at a location 0x80000000
> -	     away from the location at which it is linked.  */
> -	  if (howto->bitsize + rightshift
> -	      == bfd_arch_bits_per_address (input_bfd))
> -	    break;

Hi Ian,
   I goofed in removing this, causing problems such as
http://cgi.debian.org/cgi-bin/bugreport.cgi?bug=61719

Attached is a fairly simple fix, along with a couple of optimisations for
sign extension.

OK to apply?

-- 
Linuxcare.  Support for the Revolution.

bfd/ChangeLog
	* reloc.c (_bfd_relocate_contents): In complain_overflow_bitfield
	case, allow address wrap-around stupidly removed 2000-03-17.  Sign
	extend without an if statement.

Index: reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.19
diff -u -p -r1.19 reloc.c
--- reloc.c	2000/04/08 00:10:49	1.19
+++ reloc.c	2000/04/11 14:03:18
@@ -1498,12 +1498,10 @@ _bfd_relocate_contents (howto, input_bfd
              trouble; we would need to verify that B is in range, as
              we do for A above.  */
 	  signmask = ((~ howto->src_mask) >> 1) & howto->src_mask;
-	  if ((b & signmask) != 0)
-	    {
-	      /* Set all the bits above the sign bit.  */
-	      b -= signmask << 1;
-	    }
 
+	  /* Set all the bits above the sign bit.  */
+	  b = (b ^ signmask) - signmask;
+
 	  b = (b & addrmask) >> bitpos;
 
 	  /* Now we can do the addition.  */
@@ -1545,7 +1543,7 @@ _bfd_relocate_contents (howto, input_bfd
 
 	case complain_overflow_bitfield:
 	  /* Much like the signed check, but for a field one bit
-	     wider, and no trimming with addrmask.  We allow a
+	     wider, and no trimming inputs with addrmask.  We allow a
 	     bitfield to represent numbers in the range -2**n to
 	     2**n-1, where n is the number of bits in the field.
 	     Note that when bfd_vma is 32 bits, a 32-bit reloc can't
@@ -1558,15 +1556,19 @@ _bfd_relocate_contents (howto, input_bfd
 	    flag = bfd_reloc_overflow;
 
 	  signmask = ((~ howto->src_mask) >> 1) & howto->src_mask;
-	  if ((b & signmask) != 0)
-	    b -= signmask << 1;
+	  b = (b ^ signmask) - signmask;
 
 	  b >>= bitpos;
 
 	  sum = a + b;
 
+	  /* We mask with addrmask here to explicitly allow an address
+	     wrap-around.  The Linux kernel relies on it, and it is
+	     the only way to write assembler code which can run when
+	     loaded at a location 0x80000000 away from the location at
+	     which it is linked.  */
 	  signmask = fieldmask + 1;
-	  if (((~ (a ^ b)) & (a ^ sum)) & signmask)
+	  if (((~ (a ^ b)) & (a ^ sum)) & signmask & addrmask)
 	    flag = bfd_reloc_overflow;
 
 	  break;





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