From 569006e5824adcb39d114e815712b7aa3f5e136c Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 30 Oct 2007 15:18:29 +0000 Subject: * mn10300.h (R_MN10300_ALIGN): Define. * reloc.c (BFD_RELOC_MN10300_ALIGN): Add. * bfd-in2.h: Regenerate. * libbfd.h: Regenerate. * elf-m10300.h: Handle R_MN10300_ALIGN relocs. * mn10300_elf_relax_delete_bytes): Honour R_MN10300_ALIGN relocs. Re-fix off by one error in comparisons. * config/tc-mn10300.c (tc_gen_reloc): Fix test that decides when sym_diff relocs should be generated. (md_apply_fix): Skip R_MN10300_ALIGN relocs. (mn10300_fix_adjustable): Do not adjust R_MN10300_ALIGN relocs. (mn10300_handle_align): New function. Generate R_MN10300_ALIGN relocs to record alignment requests. * config/tc-mn10300.h (TC_FORCE_RELOCATION_SUB_SAME): Also force R_MN10300_ALIGN relocs. (HANDLE_ALIGN): Define. Call mn10300_handle_align. * gas/all/gas.exp: Do not run diff1.s test for mn10300. * ld-mn10300/mn10300.exp: Run new tests. Skip i126256 test if a compiler is not available. * ld-mn10300/i112045-3.s: New test. * ld-mn10300/i112045-3.d: Expected disassembly. * ld-mn10300/i135409.s: Rename to i135409-1.s. * ld-mn10300/i135409.d: Rename to i135409-1.d * ld-mn10300/i135409-2.s: New test. * ld-mn10300/i135409-2.d: Expected symbol table. * ld-mn10300/i36434.d: Adjust expected disassembly. --- bfd/ChangeLog | 9 ++++++++ bfd/bfd-in2.h | 5 ++++ bfd/elf-m10300.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++-------- bfd/libbfd.h | 1 + bfd/reloc.c | 6 +++++ 5 files changed, 81 insertions(+), 9 deletions(-) (limited to 'bfd') diff --git a/bfd/ChangeLog b/bfd/ChangeLog index d9d5330..5484c4b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2007-10-30 Nick Clifton + + * reloc.c (BFD_RELOC_MN10300_ALIGN): Add. + * bfd-in2.h: Regenerate. + * libbfd.h: Regnerate. + * elf-m10300.h: Handle R_MN10300_ALIGN relocs. + (mn10300_elf_relax_delete_bytes): Honour R_MN10300_ALIGN relocs. + Re-fix off by one error in comparisons. + 2007-10-25 Pedro Alves * bfd-in.h (STRING_COMMA_LEN): Don't handle NULL STR case. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 5e54867..842a536 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -2778,6 +2778,11 @@ allows for a value that is the difference of two symbols in the same section. */ BFD_RELOC_MN10300_SYM_DIFF, +/* The addend of this reloc is an alignment power that must +be honoured at the offset's location, regardless of linker +relaxation. */ + BFD_RELOC_MN10300_ALIGN, + /* i386/elf relocations */ BFD_RELOC_386_GOT32, diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c index 6c688bd..db8114e 100644 --- a/bfd/elf-m10300.c +++ b/bfd/elf-m10300.c @@ -469,6 +469,20 @@ static reloc_howto_type elf_mn10300_howto_table[] = FALSE, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_MN10300_ALIGN, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + NULL, /* special handler. */ + "R_MN10300_ALIGN", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ FALSE) /* pcrel_offset */ }; @@ -504,7 +518,8 @@ static const struct mn10300_reloc_map mn10300_reloc_map[] = { BFD_RELOC_MN10300_GLOB_DAT, R_MN10300_GLOB_DAT }, { BFD_RELOC_MN10300_JMP_SLOT, R_MN10300_JMP_SLOT }, { BFD_RELOC_MN10300_RELATIVE, R_MN10300_RELATIVE }, - { BFD_RELOC_MN10300_SYM_DIFF, R_MN10300_SYM_DIFF } + { BFD_RELOC_MN10300_SYM_DIFF, R_MN10300_SYM_DIFF }, + { BFD_RELOC_MN10300_ALIGN, R_MN10300_ALIGN } }; /* Create the GOT section. */ @@ -1045,6 +1060,7 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto, sym_diff_value = value; return bfd_reloc_ok; + case R_MN10300_ALIGN: case R_MN10300_NONE: return bfd_reloc_ok; @@ -1825,19 +1841,54 @@ mn10300_elf_relax_delete_bytes (bfd *abfd, contents = elf_section_data (sec)->this_hdr.contents; - /* The deletion must stop at the next ALIGN reloc for an aligment - power larger than the number of bytes we are deleting. */ - irelalign = NULL; toaddr = sec->size; irel = elf_section_data (sec)->relocs; irelend = irel + sec->reloc_count; + /* If there is an align reloc at the end of the section ignore it. + GAS creates these relocs for reasons of its own, and they just + serve to keep the section artifically inflated. */ + if (ELF32_R_TYPE ((irelend - 1)->r_info) == (int) R_MN10300_ALIGN) + --irelend; + + /* The deletion must stop at the next ALIGN reloc for an aligment + power larger than 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; + } + /* Actually delete the bytes. */ memmove (contents + addr, contents + addr + count, (size_t) (toaddr - addr - count)); - sec->size -= count; + + /* Adjust the section's size if we are shrinking it, or else + pad the bytes between the end of the shrunken region and + the start of the next region with NOP codes. */ + if (irelalign == NULL) + { + sec->size -= count; + /* Include symbols at the end of the section, but + not at the end of a sub-region of the section. */ + toaddr ++; + } + else + { + int i; + +#define NOP_OPCODE 0xcb + + for (i = 0; i < count; i ++) + bfd_put_8 (abfd, (bfd_vma) NOP_OPCODE, contents + toaddr - count + i); + } /* Adjust all the relocs. */ for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) @@ -1855,13 +1906,13 @@ mn10300_elf_relax_delete_bytes (bfd *abfd, { if (isym->st_shndx == sec_shndx && isym->st_value > addr - && isym->st_value <= toaddr) + && isym->st_value < toaddr) 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 && isym->st_value + isym->st_size > addr - && isym->st_value + isym->st_size <= toaddr) + && isym->st_value + isym->st_size < toaddr) isym->st_size -= count; } @@ -1878,14 +1929,14 @@ mn10300_elf_relax_delete_bytes (bfd *abfd, || sym_hash->root.type == bfd_link_hash_defweak) && 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 < toaddr) 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 && sym_hash->type == STT_FUNC && sym_hash->root.u.def.value + sym_hash->size > addr - && sym_hash->root.u.def.value + sym_hash->size <= toaddr) + && sym_hash->root.u.def.value + sym_hash->size < toaddr) sym_hash->size -= count; } diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 18d01ca..4d83a4c 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1047,6 +1047,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_MN10300_JMP_SLOT", "BFD_RELOC_MN10300_RELATIVE", "BFD_RELOC_MN10300_SYM_DIFF", + "BFD_RELOC_MN10300_ALIGN", "BFD_RELOC_386_GOT32", "BFD_RELOC_386_PLT32", diff --git a/bfd/reloc.c b/bfd/reloc.c index aa21875..f413ced 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2367,6 +2367,12 @@ ENUMDOC Together with another reloc targeted at the same location, allows for a value that is the difference of two symbols in the same section. +ENUM + BFD_RELOC_MN10300_ALIGN +ENUMDOC + The addend of this reloc is an alignment power that must + be honoured at the offset's location, regardless of linker + relaxation. COMMENT ENUM -- cgit v1.1