diff options
author | Paul Brook <paul@codesourcery.com> | 2006-05-11 15:17:34 +0000 |
---|---|---|
committer | Paul Brook <paul@codesourcery.com> | 2006-05-11 15:17:34 +0000 |
commit | b6895b4f375bfb1de5a8d33b3af600c5d92314d8 (patch) | |
tree | 270b1929d939066a8b43f6cabfa3d6282c7dacdd /bfd | |
parent | e28387c3bf6b1358d3a438443fc790c8e0fefa22 (diff) | |
download | gdb-b6895b4f375bfb1de5a8d33b3af600c5d92314d8.zip gdb-b6895b4f375bfb1de5a8d33b3af600c5d92314d8.tar.gz gdb-b6895b4f375bfb1de5a8d33b3af600c5d92314d8.tar.bz2 |
2006-05-11 Paul Brook <paul@codesourcery.com>
bfd/
* elf32-arm.c (elf32_arm_reloc_map): Add MOVW and MOVT relocs.
(elf32_arm_final_link_relocate): Handle MOVW and MOVT relocs.
(elf32_arm_gc_sweep_hook, elf32_arm_check_relocs): Ditto.
* reloc.c: Ditto.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* libcoff.h: Regenerate.
gas/
* config/tc-arm.c (parse_half): New function.
(operand_parse_code): Remove OP_Iffff. Add OP_HALF.
(parse_operands): Ditto.
(do_mov16): Reject invalid relocations.
(do_t_mov16): Ditto. Use Thumb reloc numbers.
(insns): Replace Iffff with HALF.
(md_apply_fix): Add MOVW and MOVT relocs.
(tc_gen_reloc): Ditto.
* doc/c-arm.texi: Document relocation operators
ld/testsuite/
* ld-arm/arm-elf.exp: Add arm-movwt.
* ld-arm/arm-movwt.d: New test.
* ld-arm/arm-movwt.s: New test.
* ld-arm/arm.ld: Add .far.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 10 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 10 | ||||
-rw-r--r-- | bfd/elf32-arm.c | 101 | ||||
-rw-r--r-- | bfd/libbfd.h | 8 | ||||
-rw-r--r-- | bfd/reloc.c | 18 |
5 files changed, 141 insertions, 6 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a95fd4f..9f9ba30 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2006-05-11 Paul Brook <paul@codesourcery.com> + + * elf32-arm.c (elf32_arm_reloc_map): Add MOVW and MOVT relocs. + (elf32_arm_final_link_relocate): Handle MOVW and MOVT relocs. + (elf32_arm_gc_sweep_hook, elf32_arm_check_relocs): Ditto. + * reloc.c: Ditto. + * bfd-in2.h: Regenerate. + * libbfd.h: Regenerate. + * libcoff.h: Regenerate. + 2006-05-11 Mike Bland <mbland@google.com> * elf.c (_bfd_elf_init_private_section_data): Don't change diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 94118cc..5ba74d2 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -2897,6 +2897,16 @@ pc-relative or some form of GOT-indirect relocation. */ /* 31-bit PC relative address. */ BFD_RELOC_ARM_PREL31, +/* Low and High halfword relocations for MOVW and MOVT instructions. */ + BFD_RELOC_ARM_MOVW, + BFD_RELOC_ARM_MOVT, + BFD_RELOC_ARM_MOVW_PCREL, + BFD_RELOC_ARM_MOVT_PCREL, + BFD_RELOC_ARM_THUMB_MOVW, + BFD_RELOC_ARM_THUMB_MOVT, + BFD_RELOC_ARM_THUMB_MOVW_PCREL, + BFD_RELOC_ARM_THUMB_MOVT_PCREL, + /* Relocations for setting up GOTs and PLTs for shared libraries. */ BFD_RELOC_ARM_JUMP_SLOT, BFD_RELOC_ARM_GLOB_DAT, diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 3b4152a..e0a5abe 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -1366,6 +1366,14 @@ static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] = {BFD_RELOC_ARM_TLS_LE32, R_ARM_TLS_LE32}, {BFD_RELOC_VTABLE_INHERIT, R_ARM_GNU_VTINHERIT}, {BFD_RELOC_VTABLE_ENTRY, R_ARM_GNU_VTENTRY}, + {BFD_RELOC_ARM_MOVW, R_ARM_MOVW_ABS_NC}, + {BFD_RELOC_ARM_MOVT, R_ARM_MOVT_ABS}, + {BFD_RELOC_ARM_MOVW_PCREL, R_ARM_MOVW_PREL_NC}, + {BFD_RELOC_ARM_MOVT_PCREL, R_ARM_MOVT_PREL}, + {BFD_RELOC_ARM_THUMB_MOVW, R_ARM_THM_MOVW_ABS_NC}, + {BFD_RELOC_ARM_THUMB_MOVT, R_ARM_THM_MOVT_ABS}, + {BFD_RELOC_ARM_THUMB_MOVW_PCREL, R_ARM_THM_MOVW_PREL_NC}, + {BFD_RELOC_ARM_THUMB_MOVT_PCREL, R_ARM_THM_MOVT_PREL}, }; static reloc_howto_type * @@ -4080,6 +4088,76 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, } return bfd_reloc_ok; + case R_ARM_MOVW_ABS_NC: + case R_ARM_MOVT_ABS: + case R_ARM_MOVW_PREL_NC: + case R_ARM_MOVT_PREL: + { + bfd_vma insn = bfd_get_32 (input_bfd, hit_data); + + if (globals->use_rel) + { + 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) + value >>= 16; + + insn &= 0xfff0f000; + insn |= value & 0xfff; + insn |= (value & 0xf000) << 4; + bfd_put_32 (input_bfd, insn, hit_data); + } + return bfd_reloc_ok; + + case R_ARM_THM_MOVW_ABS_NC: + case R_ARM_THM_MOVT_ABS: + case R_ARM_THM_MOVW_PREL_NC: + case R_ARM_THM_MOVT_PREL: + { + bfd_vma insn; + + insn = bfd_get_16 (input_bfd, hit_data) << 16; + insn |= bfd_get_16 (input_bfd, hit_data + 2); + + if (globals->use_rel) + { + addend = ((insn >> 4) & 0xf000) + | ((insn >> 15) & 0x0800) + | ((insn >> 4) & 0x0700) + | (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) + value >>= 16; + + insn &= 0xfbf08f00; + insn |= (value & 0xf000) << 4; + insn |= (value & 0x0800) << 15; + insn |= (value & 0x0700) << 4; + insn |= (value & 0x00ff); + + bfd_put_16 (input_bfd, insn >> 16, hit_data); + bfd_put_16 (input_bfd, insn & 0xffff, hit_data + 2); + } + return bfd_reloc_ok; + default: return bfd_reloc_notsupported; } @@ -5651,6 +5729,14 @@ elf32_arm_gc_sweep_hook (bfd * abfd, case R_ARM_JUMP24: case R_ARM_PREL31: case R_ARM_THM_CALL: + case R_ARM_MOVW_ABS_NC: + case R_ARM_MOVT_ABS: + case R_ARM_MOVW_PREL_NC: + case R_ARM_MOVT_PREL: + case R_ARM_THM_MOVW_ABS_NC: + case R_ARM_THM_MOVT_ABS: + case R_ARM_THM_MOVW_PREL_NC: + case R_ARM_THM_MOVT_PREL: /* Should the interworking branches be here also? */ if (h != NULL) @@ -5861,6 +5947,14 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_ARM_JUMP24: case R_ARM_PREL31: case R_ARM_THM_CALL: + case R_ARM_MOVW_ABS_NC: + case R_ARM_MOVT_ABS: + case R_ARM_MOVW_PREL_NC: + case R_ARM_MOVT_PREL: + case R_ARM_THM_MOVW_ABS_NC: + case R_ARM_THM_MOVT_ABS: + case R_ARM_THM_MOVW_PREL_NC: + case R_ARM_THM_MOVT_PREL: /* Should the interworking branches be listed here? */ if (h != NULL) { @@ -5877,12 +5971,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, refers to is in a different object. We can't tell for sure yet, because something later might force the symbol local. */ - if (r_type == R_ARM_PC24 - || r_type == R_ARM_CALL - || r_type == R_ARM_JUMP24 - || r_type == R_ARM_PREL31 - || r_type == R_ARM_PLT32 - || r_type == R_ARM_THM_CALL) + if (r_type != R_ARM_ABS32 && r_type != R_ARM_REL32) h->needs_plt = 1; /* If we create a PLT entry, this relocation will reference diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 6cbef48..34b0f4f 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1208,6 +1208,14 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_ARM_SBREL32", "BFD_RELOC_ARM_TARGET2", "BFD_RELOC_ARM_PREL31", + "BFD_RELOC_ARM_MOVW", + "BFD_RELOC_ARM_MOVT", + "BFD_RELOC_ARM_MOVW_PCREL", + "BFD_RELOC_ARM_MOVT_PCREL", + "BFD_RELOC_ARM_THUMB_MOVW", + "BFD_RELOC_ARM_THUMB_MOVT", + "BFD_RELOC_ARM_THUMB_MOVW_PCREL", + "BFD_RELOC_ARM_THUMB_MOVT_PCREL", "BFD_RELOC_ARM_JUMP_SLOT", "BFD_RELOC_ARM_GLOB_DAT", "BFD_RELOC_ARM_GOT32", diff --git a/bfd/reloc.c b/bfd/reloc.c index f1d09a5..6adc7fb 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2701,6 +2701,24 @@ ENUM BFD_RELOC_ARM_PREL31 ENUMDOC 31-bit PC relative address. +ENUM + BFD_RELOC_ARM_MOVW +ENUMX + BFD_RELOC_ARM_MOVT +ENUMX + BFD_RELOC_ARM_MOVW_PCREL +ENUMX + BFD_RELOC_ARM_MOVT_PCREL +ENUMX + BFD_RELOC_ARM_THUMB_MOVW +ENUMX + BFD_RELOC_ARM_THUMB_MOVT +ENUMX + BFD_RELOC_ARM_THUMB_MOVW_PCREL +ENUMX + BFD_RELOC_ARM_THUMB_MOVT_PCREL +ENUMDOC + Low and High halfword relocations for MOVW and MOVT instructions. ENUM BFD_RELOC_ARM_JUMP_SLOT |