For the Thumb BLX reloc round the relocation up rather than down.

This commit is contained in:
Nick Clifton 2002-05-23 12:37:57 +00:00
parent 6ff96af674
commit c62e1cc30f
5 changed files with 46 additions and 38 deletions

View file

@ -1,3 +1,9 @@
2002-05-23 Nick Clifton <nickc@cambridge.redhat.com>
* elf32-arm.h (elf32_arm_final_link_relocate): For the Thumb
BLX reloc round the relocation up rather than down.
* coff-arm.c (coff_arm_relocate_section): Likewise.
2002-05-21 H.J. Lu (hjl@gnu.org) 2002-05-21 H.J. Lu (hjl@gnu.org)
* linker.c (_bfd_generic_link_add_one_symbol): Allow multiple * linker.c (_bfd_generic_link_add_one_symbol): Allow multiple

View file

@ -1701,21 +1701,23 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
|| signed_check < reloc_signed_min) || signed_check < reloc_signed_min)
overflow = true; overflow = true;
/* For the BLX(1) instruction remove bit 0 of the adjusted offset. /* Put the relocation into the correct bits.
Bit 0 can only be set if the upper insn is at a half-word boundary, For a BLX instruction, make sure that the relocation is rounded up
since the destination address, an ARM instruction, must always be to a word boundary. This follows the semantics of the instruction
on a word boundary. The semantics of the BLX (1) instruction, which specifies that bit 1 of the target address will come from bit
however, are that bit 0 in the offset must always be 0, and the 1 of the base address. */
corresponding bit 1 in the target address will be set from bit
1 of the source address. */
if ((x & 0x18000000) == 0x08000000)
relocation &= ~0x2;
/* Put the relocation into the correct bits. */
if (bfd_big_endian (input_bfd)) if (bfd_big_endian (input_bfd))
relocation = (((relocation & 0xffe) >> 1) | ((relocation << 4) & 0x07ff0000)); {
if ((x & 0x1800) == 0x0800 && (relocation & 0x02))
relocation += 2;
relocation = (((relocation & 0xffe) >> 1) | ((relocation << 4) & 0x07ff0000));
}
else else
relocation = (((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff)); {
if ((x & 0x18000000) == 0x08000000 && (relocation & 0x02))
relocation += 2;
relocation = (((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff));
}
/* Add the relocation to the correct bits of X. */ /* Add the relocation to the correct bits of X. */
x = ((x & ~howto->dst_mask) | relocation); x = ((x & ~howto->dst_mask) | relocation);

View file

@ -1471,22 +1471,19 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
if (signed_check > reloc_signed_max || signed_check < reloc_signed_min) if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
overflow = true; overflow = true;
#ifndef OLD_ARM_ABI
if (r_type == R_ARM_THM_XPC22
&& ((lower_insn & 0x1800) == 0x0800))
/* For a BLX instruction, make sure that the relocation is rounded up
to a word boundary. This follows the semantics of the instruction
which specifies that bit 1 of the target address will come from bit
1 of the base address. */
relocation = (relocation + 2) & ~ 3;
#endif
/* Put RELOCATION back into the insn. */ /* Put RELOCATION back into the insn. */
upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 12) & 0x7ff); upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 12) & 0x7ff);
lower_insn = (lower_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 1) & 0x7ff); lower_insn = (lower_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 1) & 0x7ff);
#ifndef OLD_ARM_ABI
if (r_type == R_ARM_THM_XPC22
&& ((lower_insn & 0x1800) == 0x0800))
/* Remove bit zero of the adjusted offset. Bit zero can only be
set if the upper insn is at a half-word boundary, since the
destination address, an ARM instruction, must always be on a
word boundary. The semantics of the BLX (1) instruction, however,
are that bit zero in the offset must always be zero, and the
corresponding bit one in the target address will be set from bit
one of the source address. */
lower_insn &= ~1;
#endif
/* Put the relocated value back in the object file: */ /* Put the relocated value back in the object file: */
bfd_put_16 (input_bfd, upper_insn, hit_data); bfd_put_16 (input_bfd, upper_insn, hit_data);
bfd_put_16 (input_bfd, lower_insn, hit_data + 2); bfd_put_16 (input_bfd, lower_insn, hit_data + 2);

View file

@ -1,3 +1,8 @@
2002-05-23 Nick Clifton <nickc@cambridge.redhat.com>
* config/tc-arm.c (md_apply_fix3): For the Thumb BLX reloc
round the relocation up rather than down.
2002-05-23 Nick Clifton <nickc@cambridge.redhat.com> 2002-05-23 Nick Clifton <nickc@cambridge.redhat.com>
* config/obj-coff.c (obj_coff_section): Silently ignore an 'a' * config/obj-coff.c (obj_coff_section): Silently ignore an 'a'

View file

@ -2227,7 +2227,7 @@ symbol_locate (symbolP, name, segment, valu, frag)
S_SET_SEGMENT (symbolP, segment); S_SET_SEGMENT (symbolP, segment);
S_SET_VALUE (symbolP, valu); S_SET_VALUE (symbolP, valu);
symbol_clear_list_pointers(symbolP); symbol_clear_list_pointers (symbolP);
symbol_set_frag (symbolP, frag); symbol_set_frag (symbolP, frag);
@ -6963,7 +6963,7 @@ vfp_sp_reg_list (str, pos)
/* Sanity check -- should have raised a parse error above. */ /* Sanity check -- should have raised a parse error above. */
if (count == 0 || count > 32) if (count == 0 || count > 32)
abort(); abort ();
/* Final test -- the registers must be consecutive. */ /* Final test -- the registers must be consecutive. */
while (count--) while (count--)
@ -7076,7 +7076,7 @@ vfp_dp_reg_list (str)
/* Sanity check -- should have raised a parse error above. */ /* Sanity check -- should have raised a parse error above. */
if (count == 0 || count > 16) if (count == 0 || count > 16)
abort(); abort ();
/* Final test -- the registers must be consecutive. */ /* Final test -- the registers must be consecutive. */
while (count--) while (count--)
@ -7093,7 +7093,7 @@ vfp_dp_reg_list (str)
} }
static void static void
vfp_sp_ldstm(str, ldstm_type) vfp_sp_ldstm (str, ldstm_type)
char *str; char *str;
enum vfp_ldstm_type ldstm_type; enum vfp_ldstm_type ldstm_type;
{ {
@ -7130,7 +7130,7 @@ vfp_sp_ldstm(str, ldstm_type)
} }
static void static void
vfp_dp_ldstm(str, ldstm_type) vfp_dp_ldstm (str, ldstm_type)
char *str; char *str;
enum vfp_ldstm_type ldstm_type; enum vfp_ldstm_type ldstm_type;
{ {
@ -9939,6 +9939,7 @@ md_apply_fix3 (fixP, valP, seg)
value = fixP->fx_offset; value = fixP->fx_offset;
#endif #endif
value += diff; value += diff;
if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff)) if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
as_bad_where (fixP->fx_file, fixP->fx_line, as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch with link out of range")); _("branch with link out of range"));
@ -9946,14 +9947,11 @@ md_apply_fix3 (fixP, valP, seg)
newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12); newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1); newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX) if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
/* Remove bit zero of the adjusted offset. Bit zero can only be /* For a BLX instruction, make sure that the relocation is rounded up
set if the upper insn is at a half-word boundary, since the to a word boundary. This follows the semantics of the instruction
destination address, an ARM instruction, must always be on a which specifies that bit 1 of the target address will come from bit
word boundary. The semantics of the BLX (1) instruction, however, 1 of the base address. */
are that bit zero in the offset must always be zero, and the newval2 = (newval2 + 1) & ~ 1;
corresponding bit one in the target address will be set from bit
one of the source address. */
newval2 &= ~1;
md_number_to_chars (buf, newval, THUMB_SIZE); md_number_to_chars (buf, newval, THUMB_SIZE);
md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE); md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
} }