diff options
author | Mark Shinwell <shinwell@codesourcery.com> | 2006-10-18 15:34:50 +0000 |
---|---|---|
committer | Mark Shinwell <shinwell@codesourcery.com> | 2006-10-18 15:34:50 +0000 |
commit | 1299cfff6ebecfb61e8146297301a8eb99ed11b5 (patch) | |
tree | 4d5132727e3a066c21ab21daec919e74339c98b1 /bfd/elf32-arm.c | |
parent | 36935b8832d3b5b6b337f1ac5bcbc0cb798eee31 (diff) | |
download | gdb-1299cfff6ebecfb61e8146297301a8eb99ed11b5.tar.gz |
* elf32-arm.c (elf32_arm_final_link_relocate): Add support for
R_ARM_MOVW_BREL_NC, R_ARM_MOVW_BREL, R_ARM_MOVT_BREL,
R_ARM_THM_MOVW_BREL_NC, R_ARM_THM_MOVW_BREL and
R_ARM_THM_MOVT_BREL relocations.
Diffstat (limited to 'bfd/elf32-arm.c')
-rw-r--r-- | bfd/elf32-arm.c | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index c2e51c1976d..f9f668fa633 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -4832,6 +4832,13 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, case R_ARM_MOVT_ABS: case R_ARM_MOVW_PREL_NC: case R_ARM_MOVT_PREL: + /* Until we properly support segment-base-relative addressing then + we assume the segment base to be zero, as for the group relocations. + Thus R_ARM_MOVW_BREL_NC has the same semantics as R_ARM_MOVW_ABS_NC + and R_ARM_MOVT_BREL has the same semantics as R_ARM_MOVT_ABS. */ + case R_ARM_MOVW_BREL_NC: + case R_ARM_MOVW_BREL: + case R_ARM_MOVT_BREL: { bfd_vma insn = bfd_get_32 (input_bfd, hit_data); @@ -4840,15 +4847,21 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, addend = ((insn >> 4) & 0xf000) | (insn & 0xfff); signed_addend = (addend ^ 0x10000) - 0x10000; } + value += signed_addend; - if (sym_flags == STT_ARM_TFUNC) - value |= 1; if (r_type == R_ARM_MOVW_PREL_NC || r_type == R_ARM_MOVT_PREL) value -= (input_section->output_section->vma + input_section->output_offset + rel->r_offset); - if (r_type == R_ARM_MOVT_ABS || r_type == R_ARM_MOVT_PREL) + if (r_type == R_ARM_MOVW_BREL && value >= 0x10000) + return bfd_reloc_overflow; + + if (sym_flags == STT_ARM_TFUNC) + value |= 1; + + if (r_type == R_ARM_MOVT_ABS || r_type == R_ARM_MOVT_PREL + || r_type == R_ARM_MOVT_BREL) value >>= 16; insn &= 0xfff0f000; @@ -4862,6 +4875,14 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, case R_ARM_THM_MOVT_ABS: case R_ARM_THM_MOVW_PREL_NC: case R_ARM_THM_MOVT_PREL: + /* Until we properly support segment-base-relative addressing then + we assume the segment base to be zero, as for the above relocations. + Thus R_ARM_THM_MOVW_BREL_NC has the same semantics as + R_ARM_THM_MOVW_ABS_NC and R_ARM_THM_MOVT_BREL has the same semantics + as R_ARM_THM_MOVT_ABS. */ + case R_ARM_THM_MOVW_BREL_NC: + case R_ARM_THM_MOVW_BREL: + case R_ARM_THM_MOVT_BREL: { bfd_vma insn; @@ -4876,15 +4897,21 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, | (insn & 0x00ff); signed_addend = (addend ^ 0x10000) - 0x10000; } + value += signed_addend; - if (sym_flags == STT_ARM_TFUNC) - value |= 1; if (r_type == R_ARM_THM_MOVW_PREL_NC || r_type == R_ARM_THM_MOVT_PREL) value -= (input_section->output_section->vma + input_section->output_offset + rel->r_offset); - if (r_type == R_ARM_THM_MOVT_ABS || r_type == R_ARM_THM_MOVT_PREL) + if (r_type == R_ARM_THM_MOVW_BREL && value >= 0x10000) + return bfd_reloc_overflow; + + if (sym_flags == STT_ARM_TFUNC) + value |= 1; + + if (r_type == R_ARM_THM_MOVT_ABS || r_type == R_ARM_THM_MOVT_PREL + || r_type == R_ARM_THM_MOVT_BREL) value >>= 16; insn &= 0xfbf08f00; |