diff options
author | Ian Lance Taylor <ian@airs.com> | 1994-02-26 18:24:10 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1994-02-26 18:24:10 +0000 |
commit | 3d51f02f4c683aa29fb45e9083ddddd1a1b9ce97 (patch) | |
tree | d2d028084c44778ad33674931c612fa8d7885e7f /bfd/reloc.c | |
parent | a2961423ae6ad940625597be1c8f4103772987a9 (diff) | |
download | fsf-binutils-gdb-3d51f02f4c683aa29fb45e9083ddddd1a1b9ce97.zip fsf-binutils-gdb-3d51f02f4c683aa29fb45e9083ddddd1a1b9ce97.tar.gz fsf-binutils-gdb-3d51f02f4c683aa29fb45e9083ddddd1a1b9ce97.tar.bz2 |
* reloc.c (_bfd_relocate_contents): Adjust handling of overflow to
avoid depending upon right shifts of signed numbers, and to
correct handling of src_mask with lower bits zero.
Diffstat (limited to 'bfd/reloc.c')
-rw-r--r-- | bfd/reloc.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/bfd/reloc.c b/bfd/reloc.c index 675bb29..4323d9a 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -616,7 +616,8 @@ bfd_perform_relocation (abfd, reloc_entry, data, input_section, output_bfd, reloc_entry->address += input_section->output_offset; /* WTF?? */ - if (abfd->xvec->flavour == bfd_target_coff_flavour) + if (abfd->xvec->flavour == bfd_target_coff_flavour + && strcmp (abfd->xvec->name, "aixcoff-rs6000") != 0) { #if 1 /* For m68k-coff, the addend was being subtracted twice during @@ -1054,13 +1055,23 @@ _bfd_relocate_contents (howto, input_bfd, relocation, location) &~ ((bfd_vma) -1 >> howto->rightshift))); } - /* Add in the value from the object file, shifted down so that - it is a straight number. */ + /* Get the value from the object file. */ add = x & howto->src_mask; - if ((add & (((~ howto->src_mask) >> 1) & howto->src_mask)) == 0) - signed_add = add; - else - signed_add = add | ((bfd_vma) -1 &~ howto->src_mask); + + /* Get the value from the object file with an appropriate sign. + The expression involving howto->src_mask isolates the upper + bit of src_mask. If that bit is set in the value we are + adding, it is negative, and we subtract out that number times + two. If src_mask includes the highest possible bit, then we + can not get the upper bit, but that does not matter since + signed_add needs no adjustment to become negative in that + case. */ + signed_add = add; + if ((add & (((~ howto->src_mask) >> 1) & howto->src_mask)) != 0) + signed_add -= (((~ howto->src_mask) >> 1) & howto->src_mask) << 1; + + /* Add the value from the object file, shifted so that it is a + straight number. */ if (howto->bitpos == 0) { check += add; @@ -1069,10 +1080,14 @@ _bfd_relocate_contents (howto, input_bfd, relocation, location) else { check += add >> howto->bitpos; + + /* For the signed case we use ADD, rather than SIGNED_ADD, + to avoid warnings from SVR4 cc. This is OK since we + explictly handle the sign bits. */ if (signed_add >= 0) - signed_check += signed_add >> howto->bitpos; + signed_check += add >> howto->bitpos; else - signed_check += ((signed_add >> howto->bitpos) + signed_check += ((add >> howto->bitpos) | ((bfd_vma) -1 &~ ((bfd_vma) -1 >> howto->bitpos))); } @@ -1447,6 +1462,15 @@ CODE_FRAGMENT . BFD_RELOC_386_GOTOFF, . BFD_RELOC_386_GOTPC, . +. {* PowerPC/POWER (RS/6000) relocs. *} +. {* 26 bit relative branch. Low two bits must be zero. High 24 +. bits installed in bits 6 through 29 of instruction. *} +. BFD_RELOC_PPC_B26, +. {* 26 bit absolute branch, like BFD_RELOC_PPC_B26 but absolute. *} +. BFD_RELOC_PPC_BA26, +. {* 16 bit TOC relative reference. *} +. BFD_RELOC_PPC_TOC16, +. . {* this must be the highest numeric value *} . BFD_RELOC_UNUSED . } bfd_reloc_code_real_type; |