summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2000-04-11 23:02:50 +0000
committerAlan Modra <amodra@bigpond.net.au>2000-04-11 23:02:50 +0000
commitfd31a7e326949ef033e4ec42b10bee4b328eec4b (patch)
tree0ae3d7a75e8486a7610fa94dfc7b1bb0146ceed5
parentc12a62756e964933507447efbd5b4d0fcf379bb6 (diff)
downloadgdb-fd31a7e326949ef033e4ec42b10bee4b328eec4b.tar.gz
Allow address wrap for bitfields again.
-rw-r--r--bfd/ChangeLog6
-rw-r--r--bfd/reloc.c20
2 files changed, 17 insertions, 9 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index e1e1ec499a3..45c2b7b466b 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,9 @@
+2000-04-12 Alan Modra <alan@linuxcare.com.au>
+
+ * 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.
+
2000-04-04 Alan Modra <alan@linuxcare.com.au>
* po/bfd.pot: Regenerate.
diff --git a/bfd/reloc.c b/bfd/reloc.c
index a3318e6c09a..ef2375a0d79 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -1498,11 +1498,9 @@ _bfd_relocate_contents (howto, input_bfd, relocation, location)
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;
@@ -1545,7 +1543,7 @@ _bfd_relocate_contents (howto, input_bfd, relocation, location)
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, relocation, location)
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;