This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
Re: reloc overflows
- To: Ian Lance Taylor <ian at zembu dot com>
- Subject: Re: reloc overflows
- From: Alan Modra <alan at linuxcare dot com dot au>
- Date: Wed, 12 Apr 2000 00:14:58 +1000 (EST)
- cc: binutils at sourceware dot cygnus dot com, hjl at gnu dot org, chris at beezer dot med dot miami dot edu, VANDROVE at vc dot cvut dot cz, kruus at on2 dot com, sama at prosa dot it
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;