diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 6490fcf439..73c6a77c3b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2008-03-07 Paul Brook + + * elf32-arm.c (elf32_arm_howto_table_1): Fix bitmasks for MOVW and + MOVT relocations. + (elf32_arm_final_link_relocate): Fix off by one MOVW/MOVT sign + extension. + (elf32_arm_relocate_section): Handle MOVW and MOVT + relocations. Improve safety check for other weird relocations. + (elf32_arm_check_relocs): Only set h->needs_plt for branch/call + relocations. + 2008-03-03 Bob Wilson * xtensa-isa.c (xtensa_isa_num_pipe_stages): Make max_stage static and diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 6f66a7150d..687d9cd33a 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -696,8 +696,8 @@ static reloc_howto_type elf32_arm_howto_table_1[] = bfd_elf_generic_reloc, /* special_function */ "R_ARM_MOVW_ABS_NC", /* name */ FALSE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ + 0x000f0fff, /* src_mask */ + 0x000f0fff, /* dst_mask */ FALSE), /* pcrel_offset */ HOWTO (R_ARM_MOVT_ABS, /* type */ @@ -710,8 +710,8 @@ static reloc_howto_type elf32_arm_howto_table_1[] = bfd_elf_generic_reloc, /* special_function */ "R_ARM_MOVT_ABS", /* name */ FALSE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ + 0x000f0fff, /* src_mask */ + 0x000f0fff, /* dst_mask */ FALSE), /* pcrel_offset */ HOWTO (R_ARM_MOVW_PREL_NC, /* type */ @@ -724,8 +724,8 @@ static reloc_howto_type elf32_arm_howto_table_1[] = bfd_elf_generic_reloc, /* special_function */ "R_ARM_MOVW_PREL_NC", /* name */ FALSE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ + 0x000f0fff, /* src_mask */ + 0x000f0fff, /* dst_mask */ TRUE), /* pcrel_offset */ HOWTO (R_ARM_MOVT_PREL, /* type */ @@ -738,8 +738,8 @@ static reloc_howto_type elf32_arm_howto_table_1[] = bfd_elf_generic_reloc, /* special_function */ "R_ARM_MOVT_PREL", /* name */ FALSE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ + 0x000f0fff, /* src_mask */ + 0x000f0fff, /* dst_mask */ TRUE), /* pcrel_offset */ HOWTO (R_ARM_THM_MOVW_ABS_NC, /* type */ @@ -5916,7 +5916,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, if (globals->use_rel) { addend = ((insn >> 4) & 0xf000) | (insn & 0xfff); - signed_addend = (addend ^ 0x10000) - 0x10000; + signed_addend = (addend ^ 0x8000) - 0x8000; } value += signed_addend; @@ -5966,7 +5966,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, | ((insn >> 15) & 0x0800) | ((insn >> 4) & 0x0700) | (insn & 0x00ff); - signed_addend = (addend ^ 0x10000) - 0x10000; + signed_addend = (addend ^ 0x8000) - 0x8000; } value += signed_addend; @@ -6548,34 +6548,85 @@ elf32_arm_relocate_section (bfd * output_bfd, asection *msec; bfd_vma addend, value; - if (howto->rightshift) + switch (r_type) { - (*_bfd_error_handler) - (_("%B(%A+0x%lx): %s relocation against SEC_MERGE section"), - input_bfd, input_section, - (long) rel->r_offset, howto->name); - return FALSE; + case R_ARM_MOVW_ABS_NC: + case R_ARM_MOVT_ABS: + value = bfd_get_32 (input_bfd, contents + rel->r_offset); + addend = ((value & 0xf0000) >> 4) | (value & 0xfff); + addend = (addend ^ 0x8000) - 0x8000; + break; + + case R_ARM_THM_MOVW_ABS_NC: + case R_ARM_THM_MOVT_ABS: + value = bfd_get_16 (input_bfd, contents + rel->r_offset) + << 16; + value |= bfd_get_16 (input_bfd, + contents + rel->r_offset + 2); + addend = ((value & 0xf7000) >> 4) | (value & 0xff) + | ((value & 0x04000000) >> 15); + addend = (addend ^ 0x8000) - 0x8000; + break; + + default: + if (howto->rightshift + || (howto->src_mask & (howto->src_mask + 1))) + { + (*_bfd_error_handler) + (_("%B(%A+0x%lx): %s relocation against SEC_MERGE section"), + input_bfd, input_section, + (long) rel->r_offset, howto->name); + return FALSE; + } + + value = bfd_get_32 (input_bfd, contents + rel->r_offset); + + /* Get the (signed) value from the instruction. */ + addend = value & howto->src_mask; + if (addend & ((howto->src_mask + 1) >> 1)) + { + bfd_signed_vma mask; + + mask = -1; + mask &= ~ howto->src_mask; + addend |= mask; + } + break; } - value = bfd_get_32 (input_bfd, contents + rel->r_offset); - - /* Get the (signed) value from the instruction. */ - addend = value & howto->src_mask; - if (addend & ((howto->src_mask + 1) >> 1)) - { - bfd_signed_vma mask; - - mask = -1; - mask &= ~ howto->src_mask; - addend |= mask; - } msec = sec; addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation; addend += msec->output_section->vma + msec->output_offset; - value = (value & ~ howto->dst_mask) | (addend & howto->dst_mask); - bfd_put_32 (input_bfd, value, contents + rel->r_offset); + + /* Cases here must match those in the preceeding + switch statement. */ + switch (r_type) + { + case R_ARM_MOVW_ABS_NC: + case R_ARM_MOVT_ABS: + value = (value & 0xfff0f000) | ((addend & 0xf000) << 4) + | (addend & 0xfff); + bfd_put_32 (input_bfd, value, contents + rel->r_offset); + break; + + case R_ARM_THM_MOVW_ABS_NC: + case R_ARM_THM_MOVT_ABS: + value = (value & 0xfbf08f00) | ((addend & 0xf700) << 4) + | (addend & 0xff) | ((addend & 0x0800) << 15); + bfd_put_16 (input_bfd, value >> 16, + contents + rel->r_offset); + bfd_put_16 (input_bfd, value, + contents + rel->r_offset + 2); + break; + + default: + value = (value & ~ howto->dst_mask) + | (addend & howto->dst_mask); + bfd_put_32 (input_bfd, value, contents + rel->r_offset); + break; + } } } else @@ -7663,6 +7714,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sreloc; bfd_vma *local_got_offsets; struct elf32_arm_link_hash_table *htab; + bfd_boolean needs_plt; if (info->relocatable) return TRUE; @@ -7804,10 +7856,6 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, break; /* Fall through */ - case R_ARM_ABS32: - case R_ARM_ABS32_NOI: - case R_ARM_REL32: - case R_ARM_REL32_NOI: case R_ARM_PC24: case R_ARM_PLT32: case R_ARM_CALL: @@ -7816,6 +7864,13 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_ARM_THM_CALL: case R_ARM_THM_JUMP24: case R_ARM_THM_JUMP19: + needs_plt = 1; + goto normal_reloc; + + case R_ARM_ABS32: + case R_ARM_ABS32_NOI: + case R_ARM_REL32: + case R_ARM_REL32_NOI: case R_ARM_MOVW_ABS_NC: case R_ARM_MOVT_ABS: case R_ARM_MOVW_PREL_NC: @@ -7824,6 +7879,9 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_ARM_THM_MOVT_ABS: case R_ARM_THM_MOVW_PREL_NC: case R_ARM_THM_MOVT_PREL: + needs_plt = 0; + normal_reloc: + /* Should the interworking branches be listed here? */ if (h != NULL) { @@ -7840,11 +7898,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_ABS32 - && r_type != R_ARM_REL32 - && r_type != R_ARM_ABS32_NOI - && r_type != R_ARM_REL32_NOI - && r_type != R_ARM_ABS12) + if (needs_plt) h->needs_plt = 1; /* If we create a PLT entry, this relocation will reference diff --git a/gas/ChangeLog b/gas/ChangeLog index bb8a91eae0..b360a4b00a 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,7 @@ +2008-03-07 Paul Brook + + * config/tc-arm.c (md_apply_fix): Use correct offset range. + 2008-03-07 Alan Modra * config/tc-ppc.c (ppc_setup_opcodes): Tidy. Add code to test diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 48fb1522f8..161b644ccb 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -18804,7 +18804,7 @@ md_apply_fix (fixS * fixP, /* REL format relocations are limited to a 16-bit addend. */ if (!fixP->fx_done) { - if (value < -0x1000 || value > 0xffff) + if (value < -0x8000 || value > 0x7fff) as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range")); } diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 91eb52f99d..a30eba9433 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2008-03-07 Paul Brook + + * ld-arm/arm-elf.exp (armelftests): Add movw-merge and arm-app-movw. + * ld-arm/arm-app-movw.s: New test. + * ld-arm/arm-app.r: Update expected output. + * ld-arm/movw-merge.d: New test. + * ld-arm/movw-merge.s: New test. + 2008-03-01 Alan Modra * ld-powerpc/relbrlt.d: Update. Also check .branch_lt section. diff --git a/ld/testsuite/ld-arm/arm-app-movw.s b/ld/testsuite/ld-arm/arm-app-movw.s new file mode 100644 index 0000000000..55ced97b7b --- /dev/null +++ b/ld/testsuite/ld-arm/arm-app-movw.s @@ -0,0 +1,11 @@ + .text + .globl _start +_start: + movw r0, #:lower16:data_obj + movt r0, #:upper16:data_obj + movw r0, #:lower16:lib_func1 + movt r0, #:upper16:lib_func1 + + .globl app_func2 +app_func2: + bx lr diff --git a/ld/testsuite/ld-arm/arm-app.r b/ld/testsuite/ld-arm/arm-app.r index a24939281b..4b25e70c03 100644 --- a/ld/testsuite/ld-arm/arm-app.r +++ b/ld/testsuite/ld-arm/arm-app.r @@ -1,5 +1,5 @@ -tmpdir/arm-app: file format elf32-(little|big)arm +tmpdir/arm-app.*: file format elf32-(little|big)arm DYNAMIC RELOCATION RECORDS OFFSET TYPE VALUE diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index 3f2b69c1ac..7c6ee2134f 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -176,6 +176,12 @@ set armelftests { {"ARMv4 interworking" "-static -T arm.ld --fix-v4bx-interworking" "--fix-v4bx -meabi=4" {armv4-bx.s} {{objdump -d armv4-bx.d}} "armv4-bx"} + {"MOVW/MOVT and merged sections" "-T arm.ld" "" {movw-merge.s} + {{objdump -dw movw-merge.d}} + "movw-merge"} + {"MOVW/MOVT against shared libraries" "tmpdir/arm-lib.so" "" {arm-app-movw.s} + {{objdump -Rw arm-app.r}} + "arm-app-movw"} } run_ld_link_tests $armelftests diff --git a/ld/testsuite/ld-arm/movw-merge.d b/ld/testsuite/ld-arm/movw-merge.d new file mode 100644 index 0000000000..2df473780b --- /dev/null +++ b/ld/testsuite/ld-arm/movw-merge.d @@ -0,0 +1,13 @@ + +.*: file format.* + +Disassembly of section .text: + +00008000 <[^>]*>: + 8000: e3080013 movw r0, #32787 ; 0x8013 + 8004: e3400000 movt r0, #0 ; 0x0 + +00008008 <[^>]*>: + 8008: f248 0013 movw r0, #32787 ; 0x8013 + 800c: f2c0 0000 movt r0, #0 ; 0x0 + diff --git a/ld/testsuite/ld-arm/movw-merge.s b/ld/testsuite/ld-arm/movw-merge.s new file mode 100644 index 0000000000..17c70a5e90 --- /dev/null +++ b/ld/testsuite/ld-arm/movw-merge.s @@ -0,0 +1,20 @@ + .arch armv7-a + .syntax unified + .text + .global _start + .type _start, %function +_start: + movw r0, #:lower16:.LC0 + movt r0, #:upper16:.LC0 + .thumb + .global tfunc + .type tfunc, %function +tfunc: + movw r0, #:lower16:.LC0 + movt r0, #:upper16:.LC0 + + .section .rodata.str1.4,"aMS",%progbits,1 + .align 2 + .ascii "pad" +.LC0: + .ascii "inner: cont \000"