aboutsummaryrefslogtreecommitdiff
path: root/bfd/reloc.c
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@cygnus>1993-07-26 18:42:09 +0000
committerKen Raeburn <raeburn@cygnus>1993-07-26 18:42:09 +0000
commit109a640b465a0fc5f8fdb567035fa04008983e16 (patch)
tree804f3cb249db28f0068ad5db5e041c37f955be5e /bfd/reloc.c
parent91ab5674f825baa3c3b56e800e40b92526895346 (diff)
downloadfsf-binutils-gdb-109a640b465a0fc5f8fdb567035fa04008983e16.zip
fsf-binutils-gdb-109a640b465a0fc5f8fdb567035fa04008983e16.tar.gz
fsf-binutils-gdb-109a640b465a0fc5f8fdb567035fa04008983e16.tar.bz2
(bfd_perform_relocation): Handle 64-bit relocs.
Diffstat (limited to 'bfd/reloc.c')
-rw-r--r--bfd/reloc.c107
1 files changed, 68 insertions, 39 deletions
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 890cb6f..c2df4b7 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -575,51 +575,68 @@ DEFUN(bfd_perform_relocation,(abfd,
reloc_entry->addend = 0;
}
-
/* FIXME: This overflow checking is incomplete, because the value
might have overflowed before we get here. For a correct check we
need to compute the value in a size larger than bitsize, but we
can't reasonably do that for a reloc the same size as a host
machine word. */
- switch (howto->complain_on_overflow)
+ if (howto->complain_on_overflow != complain_overflow_dont)
{
- case complain_overflow_dont:
- break;
- case complain_overflow_signed:
- {
- /* Assumes two's complement. */
- bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
- bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
-
- if ((bfd_signed_vma) relocation > reloc_signed_max
- || (bfd_signed_vma) relocation < reloc_signed_min)
- flag = bfd_reloc_overflow;
- }
- break;
- case complain_overflow_unsigned:
- {
- /* Assumes two's complement. This expression avoids overflow
- if howto->bitsize is the number of bits in bfd_vma. */
- bfd_vma reloc_unsigned_max =
- (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
-
- if ((bfd_vma) relocation > reloc_unsigned_max)
- flag = bfd_reloc_overflow;
- }
- break;
- case complain_overflow_bitfield:
- {
- /* Assumes two's complement. This expression avoids overflow
- if howto->bitsize is the number of bits in bfd_vma. */
- bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
+ bfd_vma check;
- if (((bfd_vma) relocation &~ reloc_bits) != 0
- && ((bfd_vma) relocation &~ reloc_bits) != (-1 &~ reloc_bits))
- flag = bfd_reloc_overflow;
- }
- break;
- default:
- abort ();
+ /* Get the value that will be used for the relocation, but
+ starting at bit position zero. */
+ if (howto->rightshift > howto->bitpos)
+ check = relocation >> (howto->rightshift - howto->bitpos);
+ else
+ check = relocation << (howto->bitpos - howto->rightshift);
+ switch (howto->complain_on_overflow)
+ {
+ case complain_overflow_signed:
+ {
+ /* Assumes two's complement. */
+ bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
+ bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
+
+ /* The above right shift is incorrect for a signed value.
+ Fix it up by forcing on the upper bits. */
+ if (howto->rightshift > howto->bitpos
+ && (bfd_signed_vma) relocation < 0)
+ check |= ((bfd_vma) -1
+ &~ ((bfd_vma) -1
+ >> (howto->rightshift - howto->bitpos)));
+ if ((bfd_signed_vma) check > reloc_signed_max
+ || (bfd_signed_vma) check < reloc_signed_min)
+ flag = bfd_reloc_overflow;
+ }
+ break;
+ case complain_overflow_unsigned:
+ {
+ /* Assumes two's complement. This expression avoids
+ overflow if howto->bitsize is the number of bits in
+ bfd_vma. */
+ bfd_vma reloc_unsigned_max =
+ (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
+
+ if ((bfd_vma) check > reloc_unsigned_max)
+ flag = bfd_reloc_overflow;
+ }
+ break;
+ case complain_overflow_bitfield:
+ {
+ /* Assumes two's complement. This expression avoids
+ overflow if howto->bitsize is the number of bits in
+ bfd_vma. */
+ bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
+
+ if (((bfd_vma) check &~ reloc_bits) != 0
+ && ((bfd_vma) check &~ reloc_bits) != (-1 &~ reloc_bits))
+ flag = bfd_reloc_overflow;
+ }
+ break;
+ default:
+ abort ();
+ }
}
/*
@@ -705,9 +722,21 @@ DEFUN(bfd_perform_relocation,(abfd,
break;
case 3:
-
/* Do nothing */
break;
+
+ case 4:
+#ifdef BFD64
+ if (relocation)
+ {
+ bfd_vma x = bfd_get_64 (abfd, (bfd_byte *) data + addr);
+ DOIT (x);
+ bfd_put_64 (abfd, x, (bfd_byte *) data + addr);
+ }
+#else
+ abort ();
+#endif
+ break;
default:
return bfd_reloc_other;
}