diff options
Diffstat (limited to 'bfd/elf32-m32r.c')
-rw-r--r-- | bfd/elf32-m32r.c | 546 |
1 files changed, 0 insertions, 546 deletions
diff --git a/bfd/elf32-m32r.c b/bfd/elf32-m32r.c index c74980b..a72da4a 100644 --- a/bfd/elf32-m32r.c +++ b/bfd/elf32-m32r.c @@ -56,10 +56,6 @@ static bfd_boolean m32r_elf_add_symbol_hook static bfd_boolean m32r_elf_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); -#if 0 /* not yet */ -static bfd_boolean m32r_elf_relax_delete_bytes - PARAMS ((bfd *, asection *, bfd_vma, int)); -#endif static bfd_reloc_status_type m32r_elf_final_sda_base PARAMS ((bfd *, struct bfd_link_info *, const char **, bfd_vma *)); static bfd_boolean m32r_elf_object_p @@ -3618,541 +3614,6 @@ printf("m32r_elf_finish_dynamic_sections()\n"); } -#if 0 /* relaxing not supported yet */ - -/* This function handles relaxing for the m32r. - Relaxing on the m32r is tricky because of instruction alignment - requirements (4 byte instructions must be aligned on 4 byte boundaries). - - The following relaxing opportunities are handled: - - seth/add3/jl -> bl24 or bl8 - seth/add3 -> ld24 - - It would be nice to handle bl24 -> bl8 but given: - - - 4 byte insns must be on 4 byte boundaries - - branch instructions only branch to insns on 4 byte boundaries - - this isn't much of a win because the insn in the 2 "deleted" bytes - must become a nop. With some complexity some real relaxation could be - done but the frequency just wouldn't make it worth it; it's better to - try to do all the code compaction one can elsewhere. - When the chip supports parallel 16 bit insns, things may change. -*/ - -static bfd_boolean -m32r_elf_relax_section (abfd, sec, link_info, again) - bfd *abfd; - asection *sec; - struct bfd_link_info *link_info; - bfd_boolean *again; -{ - Elf_Internal_Shdr *symtab_hdr; - /* The Rela structures are used here because that's what - _bfd_elf_link_read_relocs uses [for convenience - it sets the addend - field to 0]. */ - Elf_Internal_Rela *internal_relocs = NULL; - Elf_Internal_Rela *irel, *irelend; - bfd_byte *contents = NULL; - Elf_Internal_Sym *isymbuf = NULL; - - /* Assume nothing changes. */ - *again = FALSE; - - /* We don't have to do anything for a relocatable link, if - this section does not have relocs, or if this is not a - code section. */ - if (link_info->relocatable - || (sec->flags & SEC_RELOC) == 0 - || sec->reloc_count == 0 - || (sec->flags & SEC_CODE) == 0 - || 0 /* FIXME: check SHF_M32R_CAN_RELAX */) - return TRUE; - - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - - /* Get a copy of the native relocations. */ - internal_relocs = (_bfd_elf_link_read_relocs - (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, - link_info->keep_memory)); - if (internal_relocs == NULL) - goto error_return; - - /* Walk through them looking for relaxing opportunities. */ - irelend = internal_relocs + sec->reloc_count; - for (irel = internal_relocs; irel < irelend; irel++) - { - bfd_vma symval; - - /* If this isn't something that can be relaxed, then ignore - this reloc. */ - if (ELF32_R_TYPE (irel->r_info) != (int) R_M32R_HI16_SLO) - continue; - - /* Get the section contents if we haven't done so already. */ - if (contents == NULL) - { - /* Get cached copy if it exists. */ - if (elf_section_data (sec)->this_hdr.contents != NULL) - contents = elf_section_data (sec)->this_hdr.contents; - else - { - /* Go get them off disk. */ - if (!bfd_malloc_and_get_section (abfd, sec, &contents)) - goto error_return; - } - } - - /* Read this BFD's local symbols if we haven't done so already. */ - if (isymbuf == NULL && symtab_hdr->sh_info != 0) - { - isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; - if (isymbuf == NULL) - isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, - symtab_hdr->sh_info, 0, - NULL, NULL, NULL); - if (isymbuf == NULL) - goto error_return; - } - - /* Get the value of the symbol referred to by the reloc. */ - if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) - { - /* A local symbol. */ - Elf_Internal_Sym *isym; - asection *sym_sec; - - isym = isymbuf + ELF32_R_SYM (irel->r_info), - sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); - symval = (isym->st_value - + sym_sec->output_section->vma - + sym_sec->output_offset); - } - else - { - unsigned long indx; - struct elf_link_hash_entry *h; - - /* An external symbol. */ - indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; - h = elf_sym_hashes (abfd)[indx]; - BFD_ASSERT (h != NULL); - if (h->root.type != bfd_link_hash_defined - && h->root.type != bfd_link_hash_defweak) - { - /* This appears to be a reference to an undefined - symbol. Just ignore it--it will be caught by the - regular reloc processing. */ - continue; - } - - symval = (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset); - } - - /* For simplicity of coding, we are going to modify the section - contents, the section relocs, and the BFD symbol table. We - must tell the rest of the code not to free up this - information. It would be possible to instead create a table - of changes which have to be made, as is done in coff-mips.c; - that would be more work, but would require less memory when - the linker is run. */ - - /* Try to change a seth/add3/jl subroutine call to bl24 or bl8. - This sequence is generated by the compiler when compiling in - 32 bit mode. Also look for seth/add3 -> ld24. */ - - if (ELF32_R_TYPE (irel->r_info) == (int) R_M32R_HI16_SLO) - { - Elf_Internal_Rela *nrel; - bfd_vma pc = (sec->output_section->vma + sec->output_offset - + irel->r_offset); - bfd_signed_vma pcrel_value = symval - pc; - unsigned int code,reg; - int addend,nop_p,bl8_p,to_delete; - - /* The tests are ordered so that we get out as quickly as possible - if this isn't something we can relax, taking into account that - we are looking for two separate possibilities (jl/ld24). */ - - /* Do nothing if no room in the section for this to be what we're - looking for. */ - if (irel->r_offset > sec->size - 8) - continue; - - /* Make sure the next relocation applies to the next - instruction and that it's the add3's reloc. */ - nrel = irel + 1; - if (nrel == irelend - || irel->r_offset + 4 != nrel->r_offset - || ELF32_R_TYPE (nrel->r_info) != (int) R_M32R_LO16) - continue; - - /* See if the instructions are seth/add3. */ - /* FIXME: This is where macros from cgen can come in. */ - code = bfd_get_16 (abfd, contents + irel->r_offset + 0); - if ((code & 0xf0ff) != 0xd0c0) - continue; /* not seth rN,foo */ - reg = (code & 0x0f00) >> 8; - code = bfd_get_16 (abfd, contents + irel->r_offset + 4); - if (code != (0x80a0 | reg | (reg << 8))) - continue; /* not add3 rN,rN,foo */ - - /* At this point we've confirmed we have seth/add3. Now check - whether the next insn is a jl, in which case try to change this - to bl24 or bl8. */ - - /* Ensure the branch target is in range. - The bl24 instruction has a 24 bit operand which is the target - address right shifted by 2, giving a signed range of 26 bits. - Note that 4 bytes are added to the high value because the target - will be at least 4 bytes closer if we can relax. It'll actually - be 4 or 8 bytes closer, but we don't know which just yet and - the difference isn't significant enough to worry about. */ -#if !USE_REL /* put in for learning purposes */ - pcrel_value += irel->r_addend; -#else - addend = bfd_get_signed_16 (abfd, contents + irel->r_offset + 2); - pcrel_value += addend; -#endif - - if (pcrel_value >= -(1 << 25) && pcrel_value < (1 << 25) + 4 - /* Do nothing if no room in the section for this to be what we're - looking for. */ - && (irel->r_offset <= sec->size - 12) - /* Ensure the next insn is "jl rN". */ - && ((code = bfd_get_16 (abfd, contents + irel->r_offset + 8)), - code != (0x1ec0 | reg))) - { - /* We can relax to bl24/bl8. */ - - /* See if there's a nop following the jl. - Also see if we can use a bl8 insn. */ - code = bfd_get_16 (abfd, contents + irel->r_offset + 10); - nop_p = (code & 0x7fff) == NOP_INSN; - bl8_p = pcrel_value >= -0x200 && pcrel_value < 0x200; - - if (bl8_p) - { - /* Change "seth rN,foo" to "bl8 foo || nop". - We OR in CODE just in case it's not a nop (technically, - CODE currently must be a nop, but for cleanness we - allow it to be anything). */ -#if !USE_REL /* put in for learning purposes */ - code = 0x7e000000 | MAKE_PARALLEL (code); -#else - code = (0x7e000000 + (((addend >> 2) & 0xff) << 16)) | MAKE_PARALLEL (code); -#endif - to_delete = 8; - } - else - { - /* Change the seth rN,foo to a bl24 foo. */ -#if !USE_REL /* put in for learning purposes */ - code = 0xfe000000; -#else - code = 0xfe000000 + ((addend >> 2) & 0xffffff); -#endif - to_delete = nop_p ? 8 : 4; - } - - bfd_put_32 (abfd, code, contents + irel->r_offset); - - /* Set the new reloc type. */ - irel->r_info = ELF32_R_INFO (ELF32_R_SYM (nrel->r_info), - bl8_p ? R_M32R_10_PCREL : R_M32R_26_PCREL); - - /* Delete the add3 reloc by making it a null reloc. */ - nrel->r_info = ELF32_R_INFO (ELF32_R_SYM (nrel->r_info), - R_M32R_NONE); - } - else if (addend >= 0 - && symval + addend <= 0xffffff) - { - /* We can relax to ld24. */ - - code = 0xe0000000 | (reg << 24) | (addend & 0xffffff); - bfd_put_32 (abfd, code, contents + irel->r_offset); - to_delete = 4; - /* Tell the following code a nop filler isn't needed. */ - nop_p = 1; - } - else - { - /* Can't do anything here. */ - continue; - } - - /* Note that we've changed the relocs, section contents, etc. */ - elf_section_data (sec)->relocs = internal_relocs; - elf_section_data (sec)->this_hdr.contents = contents; - symtab_hdr->contents = (unsigned char *) isymbuf; - - /* Delete TO_DELETE bytes of data. */ - if (!m32r_elf_relax_delete_bytes (abfd, sec, - irel->r_offset + 4, to_delete)) - goto error_return; - - /* Now that the following bytes have been moved into place, see if - we need to replace the jl with a nop. This happens when we had - to use a bl24 insn and the insn following the jl isn't a nop. - Technically, this situation can't happen (since the insn can - never be executed) but to be clean we do this. When the chip - supports parallel 16 bit insns things may change. - We don't need to do this in the case of relaxing to ld24, - and the above code sets nop_p so this isn't done. */ - if (! nop_p && to_delete == 4) - bfd_put_16 (abfd, NOP_INSN, contents + irel->r_offset + 4); - - /* That will change things, so we should relax again. - Note that this is not required, and it may be slow. */ - *again = TRUE; - - continue; - } - - /* loop to try the next reloc */ - } - - if (isymbuf != NULL - && symtab_hdr->contents != (unsigned char *) isymbuf) - { - if (! link_info->keep_memory) - free (isymbuf); - else - { - /* Cache the symbols for elf_link_input_bfd. */ - symtab_hdr->contents = (unsigned char *) isymbuf; - } - } - - if (contents != NULL - && elf_section_data (sec)->this_hdr.contents != contents) - { - if (! link_info->keep_memory) - free (contents); - else - { - /* Cache the section contents for elf_link_input_bfd. */ - elf_section_data (sec)->this_hdr.contents = contents; - } - } - - if (internal_relocs != NULL - && elf_section_data (sec)->relocs != internal_relocs) - free (internal_relocs); - - return TRUE; - - error_return: - if (isymbuf != NULL - && symtab_hdr->contents != (unsigned char *) isymbuf) - free (isymbuf); - if (contents != NULL - && elf_section_data (sec)->this_hdr.contents != contents) - free (contents); - if (internal_relocs != NULL - && elf_section_data (sec)->relocs != internal_relocs) - free (internal_relocs); - - return FALSE; -} - -/* Delete some bytes from a section while relaxing. */ - -static bfd_boolean -m32r_elf_relax_delete_bytes (abfd, sec, addr, count) - bfd *abfd; - asection *sec; - bfd_vma addr; - int count; -{ - Elf_Internal_Shdr *symtab_hdr; - int shndx; - bfd_byte *contents; - Elf_Internal_Rela *irel, *irelend; - Elf_Internal_Rela *irelalign; - bfd_vma toaddr; - Elf_Internal_Sym *isym, *isymend; - struct elf_link_hash_entry **sym_hashes; - struct elf_link_hash_entry **end_hashes; - unsigned int symcount; - - shndx = _bfd_elf_section_from_bfd_section (abfd, sec); - - 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; - - /* Actually delete the bytes. */ - memmove (contents + addr, contents + addr + count, toaddr - addr - count); - sec->size -= count; - - /* Adjust all the relocs. */ - for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) - { - /* Get the new reloc address. */ - if ((irel->r_offset > addr - && irel->r_offset < toaddr)) - irel->r_offset -= count; - } - - /* Adjust the local symbols defined in this section. */ - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - isym = (Elf_Internal_Sym *) symtab_hdr->contents; - for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) - { - if (isym->st_shndx == shndx - && isym->st_value > addr - && isym->st_value < toaddr) - isym->st_value -= count; - } - - /* Now adjust the global symbols defined in this section. */ - symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) - - symtab_hdr->sh_info); - sym_hashes = elf_sym_hashes (abfd); - end_hashes = sym_hashes + symcount; - for (; sym_hashes < end_hashes; sym_hashes++) - { - struct elf_link_hash_entry *sym_hash = *sym_hashes; - - if ((sym_hash->root.type == bfd_link_hash_defined - || 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 -= count; - } - } - - return TRUE; -} - -/* This is a version of bfd_generic_get_relocated_section_contents - which uses m32r_elf_relocate_section. */ - -static bfd_byte * -m32r_elf_get_relocated_section_contents (output_bfd, link_info, link_order, - data, relocatable, symbols) - bfd *output_bfd; - struct bfd_link_info *link_info; - struct bfd_link_order *link_order; - bfd_byte *data; - bfd_boolean relocatable; - asymbol **symbols; -{ - Elf_Internal_Shdr *symtab_hdr; - asection *input_section = link_order->u.indirect.section; - bfd *input_bfd = input_section->owner; - asection **sections = NULL; - Elf_Internal_Rela *internal_relocs = NULL; - Elf_Internal_Sym *isymbuf = NULL; - bfd_size_type amt; - - /* We only need to handle the case of relaxing, or of having a - particular set of section contents, specially. */ - if (relocatable - || elf_section_data (input_section)->this_hdr.contents == NULL) - return bfd_generic_get_relocated_section_contents (output_bfd, link_info, - link_order, data, - relocatable, - symbols); - - symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; - - memcpy (data, elf_section_data (input_section)->this_hdr.contents, - input_section->size); - - if ((input_section->flags & SEC_RELOC) != 0 - && input_section->reloc_count > 0) - { - Elf_Internal_Sym *isymp; - asection **secpp; - Elf32_External_Sym *esym, *esymend; - - internal_relocs = (_bfd_elf_link_read_relocs - (input_bfd, input_section, (PTR) NULL, - (Elf_Internal_Rela *) NULL, FALSE)); - if (internal_relocs == NULL) - goto error_return; - - if (symtab_hdr->sh_info != 0) - { - isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; - if (isymbuf == NULL) - isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, - symtab_hdr->sh_info, 0, - NULL, NULL, NULL); - if (isymbuf == NULL) - goto error_return; - } - - amt = symtab_hdr->sh_info; - amt *= sizeof (asection *); - sections = (asection **) bfd_malloc (amt); - if (sections == NULL && symtab_hdr->sh_info > 0) - goto error_return; - - isymend = isymbuf + symtab_hdr->sh_info; - for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp) - { - asection *isec; - - if (isym->st_shndx == SHN_UNDEF) - isec = bfd_und_section_ptr; - else if (isym->st_shndx == SHN_ABS) - isec = bfd_abs_section_ptr; - else if (isym->st_shndx == SHN_COMMON) - isec = bfd_com_section_ptr; - else if (isym->st_shndx == SHN_M32R_SCOMMON) - isec = &m32r_elf_scom_section; - else - isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx); - - *secpp = isec; - } - - if (! m32r_elf_relocate_section (output_bfd, link_info, input_bfd, - input_section, data, internal_relocs, - isymbuf, sections)) - goto error_return; - - if (sections != NULL) - free (sections); - if (isymbuf != NULL - && symtab_hdr->contents != (unsigned char *) isymbuf) - free (isymbuf); - if (elf_section_data (input_section)->relocs != internal_relocs) - free (internal_relocs); - } - - return data; - - error_return: - if (sections != NULL) - free (sections); - if (isymbuf != NULL - && symtab_hdr->contents != (unsigned char *) isymbuf) - free (isymbuf); - if (internal_relocs != NULL - && elf_section_data (input_section)->relocs != internal_relocs) - free (internal_relocs); - return NULL; -} - -#endif /* #if 0 */ - /* Set the right machine number. */ static bfd_boolean m32r_elf_object_p (abfd) @@ -4832,13 +4293,6 @@ m32r_elf_reloc_type_class (rela) #define elf_backend_fake_sections m32r_elf_fake_sections #endif -#if 0 /* not yet */ -/* relax support */ -#define bfd_elf32_bfd_relax_section m32r_elf_relax_section -#define bfd_elf32_bfd_get_relocated_section_contents \ - m32r_elf_get_relocated_section_contents -#endif - #define elf_backend_object_p m32r_elf_object_p #define elf_backend_final_write_processing m32r_elf_final_write_processing #define bfd_elf32_bfd_merge_private_bfd_data m32r_elf_merge_private_bfd_data |