From: Ken Raeburn Date: Mon, 26 Jul 1993 18:42:09 +0000 (+0000) Subject: (bfd_perform_relocation): Handle 64-bit relocs. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=109a640b465a0fc5f8fdb567035fa04008983e16;p=binutils-gdb.git (bfd_perform_relocation): Handle 64-bit relocs. --- diff --git a/bfd/reloc.c b/bfd/reloc.c index 890cb6f3d62..c2df4b722b0 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; }