diff options
-rw-r--r-- | bfd/ChangeLog | 12 | ||||
-rw-r--r-- | bfd/elf-m10300.c | 81 | ||||
-rw-r--r-- | gas/ChangeLog | 7 | ||||
-rw-r--r-- | gas/config/tc-mn10300.c | 19 | ||||
-rw-r--r-- | gas/config/tc-mn10300.h | 13 | ||||
-rw-r--r-- | ld/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | ld/testsuite/ld-mn10300/i127740.d | 17 | ||||
-rw-r--r-- | ld/testsuite/ld-mn10300/i127740.s | 12 | ||||
-rw-r--r-- | ld/testsuite/ld-mn10300/i135409-3.d | 16 | ||||
-rw-r--r-- | ld/testsuite/ld-mn10300/i135409-3.s | 16 | ||||
-rw-r--r-- | ld/testsuite/ld-mn10300/mn10300.exp | 16 |
11 files changed, 191 insertions, 26 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index be08948..6a7fe8d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +2007-11-13 Nick Clifton <nickc@redhat.com> + + * elf-m10300.c (mn10300_elf_final_link_relocate): Prevent the + accidental termination of DWARF location list entries. + (mn10300_elf_relax_delete_bytes): Stop deletion if an align reloc + is encountered that is larger than or not a mutliple of the number + of bytes being deleted. + When adjusting symbols, any symbols inside the region being + deleted must be moved to the end of the region. + Move align relocs forward if there is room for them after the + deletion of the region. + 2007-11-13 Alan Modra <amodra@bigpond.net.au> PR 5233 diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c index 7c51498..9a75b7c 100644 --- a/bfd/elf-m10300.c +++ b/bfd/elf-m10300.c @@ -1039,6 +1039,17 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto, case R_MN10300_16: case R_MN10300_8: value -= sym_diff_value; + /* If we are computing a 32-bit value for the location lists + and the result is 0 then we add one to the value. A zero + value can result because of linker relaxation deleteing + prologue instructions and using a value of 1 (for the begin + and end offsets in the location list entry) results in a + nul entry which does not prevent the following entries from + being parsed. */ + if (r_type == R_MN10300_32 + && value == 0 + && strcmp (input_section->name, ".debug_loc") == 0) + value = 1; sym_diff_section = NULL; is_sym_diff_reloc = TRUE; break; @@ -1856,17 +1867,23 @@ mn10300_elf_relax_delete_bytes (bfd *abfd, --irelend; /* The deletion must stop at the next ALIGN reloc for an aligment - power larger than the number of bytes we are deleting. */ + power larger than, or not a multiple of, the number of bytes we + are deleting. */ for (; irel < irelend; irel++) - if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_ALIGN - && irel->r_offset > addr - && irel->r_offset < toaddr - && count < (1 << irel->r_addend)) - { - irelalign = irel; - toaddr = irel->r_offset; - break; - } + { + int alignment = 1 << irel->r_addend; + + if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_ALIGN + && irel->r_offset > addr + && irel->r_offset < toaddr + && (count < alignment + || alignment % count != 0)) + { + irelalign = irel; + toaddr = irel->r_offset; + break; + } + } } /* Actually delete the bytes. */ @@ -1898,11 +1915,17 @@ mn10300_elf_relax_delete_bytes (bfd *abfd, { /* Get the new reloc address. */ if ((irel->r_offset > addr - && irel->r_offset < toaddr)) + && irel->r_offset < toaddr) + || (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_ALIGN + && irel->r_offset == toaddr)) irel->r_offset -= count; } - /* Adjust the local symbols defined in this section. */ + /* Adjust the local symbols in the section, reducing their value + by the number of bytes deleted. Note - symbols within the deleted + region are moved to the address of the start of the region, which + actually means that they will address the byte beyond the end of + the region once the deletion has been completed. */ symtab_hdr = &elf_tdata (abfd)->symtab_hdr; isym = (Elf_Internal_Sym *) symtab_hdr->contents; for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) @@ -1910,7 +1933,12 @@ mn10300_elf_relax_delete_bytes (bfd *abfd, if (isym->st_shndx == sec_shndx && isym->st_value > addr && isym->st_value < toaddr) - isym->st_value -= count; + { + if (isym->st_value < addr + count) + isym->st_value = addr; + else + isym->st_value -= count; + } /* Adjust the function symbol's size as well. */ else if (isym->st_shndx == sec_shndx && ELF_ST_TYPE (isym->st_info) == STT_FUNC @@ -1933,7 +1961,12 @@ mn10300_elf_relax_delete_bytes (bfd *abfd, && sym_hash->root.u.def.section == sec && sym_hash->root.u.def.value > addr && sym_hash->root.u.def.value < toaddr) - sym_hash->root.u.def.value -= count; + { + if (sym_hash->root.u.def.value < addr + count) + sym_hash->root.u.def.value = addr; + else + sym_hash->root.u.def.value -= count; + } /* Adjust the function symbol's size as well. */ else if (sym_hash->root.type == bfd_link_hash_defined && sym_hash->root.u.def.section == sec @@ -1943,6 +1976,26 @@ mn10300_elf_relax_delete_bytes (bfd *abfd, sym_hash->size -= count; } + /* See if we can move the ALIGN reloc forward. + We have adjusted r_offset for it already. */ + if (irelalign != NULL) + { + bfd_vma alignto, alignaddr; + + if ((int) irelalign->r_addend > 0) + { + /* This is the old address. */ + alignto = BFD_ALIGN (toaddr, 1 << irelalign->r_addend); + /* This is where the align points to now. */ + alignaddr = BFD_ALIGN (irelalign->r_offset, + 1 << irelalign->r_addend); + if (alignaddr < alignto) + /* Tail recursion. */ + return mn10300_elf_relax_delete_bytes (abfd, sec, alignaddr, + (int) (alignto - alignaddr)); + } + } + return TRUE; } diff --git a/gas/ChangeLog b/gas/ChangeLog index 3b640e7..06fd9d1 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2007-11-13 Nick Clifton <nickc@redhat.com> + + * config/tc-mn10300.c (mn10300_force_relocation): Force a reloc to + be generated for alignment fixups. + * config/tc-mn10300.h (TC_FORCE_RELOCATION): Call + mn10300_force_relocation. + 2007-11-12 Nick Clifton <nickc@redhat.com> PR gas/5269 diff --git a/gas/config/tc-mn10300.c b/gas/config/tc-mn10300.c index e16a764..5d21cb5 100644 --- a/gas/config/tc-mn10300.c +++ b/gas/config/tc-mn10300.c @@ -2571,11 +2571,9 @@ mn10300_allow_local_subtract (expressionS * left, expressionS * right, segT sect void mn10300_handle_align (fragS *frag) { - if (! linkrelax) - return; - - if ((frag->fr_type == rs_align - || frag->fr_type == rs_align_code) + if (linkrelax + && (frag->fr_type == rs_align + || frag->fr_type == rs_align_code) && frag->fr_address + frag->fr_fix > 0 && frag->fr_offset > 1 && now_seg != bss_section @@ -2590,3 +2588,14 @@ mn10300_handle_align (fragS *frag) fix_new (frag, frag->fr_fix, 0, & abs_symbol, frag->fr_offset, FALSE, BFD_RELOC_MN10300_ALIGN); } + +bfd_boolean +mn10300_force_relocation (struct fix * fixp) +{ + if (linkrelax + && (fixp->fx_pcrel + || fixp->fx_r_type == BFD_RELOC_MN10300_ALIGN)) + return TRUE; + + return generic_force_reloc (fixp); +} diff --git a/gas/config/tc-mn10300.h b/gas/config/tc-mn10300.h index ca51eda..63ca74a 100644 --- a/gas/config/tc-mn10300.h +++ b/gas/config/tc-mn10300.h @@ -26,8 +26,8 @@ #define DIFF_EXPR_OK #define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_" -#define TC_FORCE_RELOCATION(FIX) \ - (generic_force_reloc (FIX)) +#define TC_FORCE_RELOCATION(FIX) mn10300_force_relocation (FIX) +extern bfd_boolean mn10300_force_relocation (struct fix *); #define TC_FORCE_RELOCATION_LOCAL(FIX) \ (!(FIX)->fx_pcrel \ @@ -36,14 +36,13 @@ || (FIX)->fx_r_type == BFD_RELOC_32_GOT_PCREL \ || TC_FORCE_RELOCATION (FIX)) -#define md_parse_name(name, exprP, mode, nextcharP) \ - mn10300_parse_name ((name), (exprP), (mode), (nextcharP)) -int mn10300_parse_name PARAMS ((char const *, expressionS *, - enum expr_mode, char *)); +#define md_parse_name(NAME, EXPRP, MODE, NEXTCHARP) \ + mn10300_parse_name ((NAME), (EXPRP), (MODE), (NEXTCHARP)) +int mn10300_parse_name (char const *, expressionS *, enum expr_mode, char *); #define TC_CONS_FIX_NEW(FRAG, OFF, LEN, EXP) \ mn10300_cons_fix_new ((FRAG), (OFF), (LEN), (EXP)) -void mn10300_cons_fix_new PARAMS ((fragS *, int, int, expressionS *)); +void mn10300_cons_fix_new (fragS *, int, int, expressionS *); /* This is used to construct expressions out of @GOTOFF, @PLT and @GOT symbols. The relocation type is stored in X_md. */ diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 0805299..83fce11 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2007-11-13 Nick Clifton <nickc@redhat.com> + + * ld-mn10300/i127740.s: New test: Checks relaxation and alignment. + * ld-mn10300/i127740.d: New file: Expected disassembly. + * ld-mn10300/i135409-3.s: New test: Check symbols inside a relaxed region. + * ld-mn10300/i135409-3.d: New file: Expected disassembly. + * ld-mn10300/mn10300.exp: Run new tests. + 2007-11-08 Nathan Sidwell <nathan@codesourcery.com> * ld-vxworks/tls-2.d: New. diff --git a/ld/testsuite/ld-mn10300/i127740.d b/ld/testsuite/ld-mn10300/i127740.d new file mode 100644 index 0000000..456a75b --- /dev/null +++ b/ld/testsuite/ld-mn10300/i127740.d @@ -0,0 +1,17 @@ + +tmpdir/i127740.x: file format elf32-.* + +Disassembly of section .text: + +0+0100 <_main>: + 100: 2d 00 03[ ]+mov 768,d1 + 103: cb[ ]+nop + 104: cb[ ]+nop + 105: cb[ ]+nop + ... + +0+0200 <_dummy>: + 200: 00[ ]+clr d0 + 201: 02 00 00[ ]+movbu d0,\(0 <_main-0x100>\) + 204: df 00 00[ ]+ret \[\],0 + ... diff --git a/ld/testsuite/ld-mn10300/i127740.s b/ld/testsuite/ld-mn10300/i127740.s new file mode 100644 index 0000000..358266b --- /dev/null +++ b/ld/testsuite/ld-mn10300/i127740.s @@ -0,0 +1,12 @@ + .section .text + .global _main + .global _dummy +_main: + mov _g_label,d1 # instruction is changed by relaxations + + .balign 0x100 +_dummy: + .long _dummy + ret [],0 + .size _main, .-_main + .comm _g_label,4,4 diff --git a/ld/testsuite/ld-mn10300/i135409-3.d b/ld/testsuite/ld-mn10300/i135409-3.d new file mode 100644 index 0000000..1ea91ba --- /dev/null +++ b/ld/testsuite/ld-mn10300/i135409-3.d @@ -0,0 +1,16 @@ + +tmpdir/i135409-3.x: file format elf32-.* + +Disassembly of section .text: + +0+0 <_func>: + 0: 25 1f 00[ ]+mov 31,a1 + 3: cb[ ]+nop + +0+04 <A>: + 4: 25 1f 00[ ]+mov 31,a1 + 7: cb[ ]+nop + +0+08 <BOTTOM>: + 8: e1[ ]+add d0,d1 +#pass diff --git a/ld/testsuite/ld-mn10300/i135409-3.s b/ld/testsuite/ld-mn10300/i135409-3.s new file mode 100644 index 0000000..e83ad96 --- /dev/null +++ b/ld/testsuite/ld-mn10300/i135409-3.s @@ -0,0 +1,16 @@ + .text + .global _start +_start: + .type _func, @function +_func: + mov L001,A1 + nop +A: + mov L001,A1 +BOTTOM: + .balign 0x8 + add D0,D1 + .size _func, .-func + + .data +L001: diff --git a/ld/testsuite/ld-mn10300/mn10300.exp b/ld/testsuite/ld-mn10300/mn10300.exp index 18bbad3..232a5fb 100644 --- a/ld/testsuite/ld-mn10300/mn10300.exp +++ b/ld/testsuite/ld-mn10300/mn10300.exp @@ -48,6 +48,14 @@ set mn10300_tests { "i112045-3.x" } { + "relaxation and alignment directives" + "-relax -Ttext 100" + "" + { "i127740.s" } + { {objdump -d i127740.d} } + "i127740.x" + } + { "adjustment of symbols due to relaxation" "-Tdata 1f -Ttext 0 -relax" "" @@ -63,6 +71,14 @@ set mn10300_tests { { {readelf --syms i135409-2.d} } "i135409-2.x" } + { + "adjustment of symbols due to relaxation (with a symbol in the deleted region)" + "-Tdata 1f -Ttext 0 -relax" + "" + { "i135409-3.s" } + { {objdump -d i135409-3.d} } + "i135409-3.x" + } } run_ld_link_tests $mn10300_tests |