reloc overflows
Alan Modra
alan@linuxcare.com.au
Tue Apr 11 07:15:00 GMT 2000
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;
More information about the Binutils
mailing list