diff options
author | Ken Raeburn <raeburn@cygnus> | 1993-07-26 18:42:09 +0000 |
---|---|---|
committer | Ken Raeburn <raeburn@cygnus> | 1993-07-26 18:42:09 +0000 |
commit | 109a640b465a0fc5f8fdb567035fa04008983e16 (patch) | |
tree | 804f3cb249db28f0068ad5db5e041c37f955be5e /bfd/reloc.c | |
parent | 91ab5674f825baa3c3b56e800e40b92526895346 (diff) | |
download | gdb-109a640b465a0fc5f8fdb567035fa04008983e16.zip gdb-109a640b465a0fc5f8fdb567035fa04008983e16.tar.gz gdb-109a640b465a0fc5f8fdb567035fa04008983e16.tar.bz2 |
(bfd_perform_relocation): Handle 64-bit relocs.
Diffstat (limited to 'bfd/reloc.c')
-rw-r--r-- | bfd/reloc.c | 107 |
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; } |