X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf-m10200.c;h=b234c168c8f1b5ec666f04a95f45bd1f7d9b0fb4;hb=cf950fd4dd4581849a445a76b57514d72074927d;hp=6f3e64f86e79c27400bc86a96c447f3dd9fb0269;hpb=fa803dc60f0bf01297674c41d001798e18ade4dc;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf-m10200.c b/bfd/elf-m10200.c index 6f3e64f86e..b234c168c8 100644 --- a/bfd/elf-m10200.c +++ b/bfd/elf-m10200.c @@ -1,39 +1,32 @@ /* Matsushita 10200 specific support for 32-bit ELF - Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1996-2019 Free Software Foundation, Inc. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "libbfd.h" #include "elf-bfd.h" -static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup - PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); -static void mn10200_info_to_howto - PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *)); -static boolean mn10200_elf_relax_delete_bytes - PARAMS ((bfd *, asection *, bfd_vma, int)); -static boolean mn10200_elf_symbol_address_p - PARAMS ((bfd *, asection *, Elf32_External_Sym *, bfd_vma)); - -/* We have to use RELA instructions since md_apply_fix3 in the assembler - does absolutely nothing. */ -#define USE_RELA +static bfd_boolean +mn10200_elf_relax_delete_bytes (bfd *, asection *, bfd_vma, int); +static bfd_boolean +mn10200_elf_symbol_address_p (bfd *, asection *, Elf_Internal_Sym *, bfd_vma); enum reloc_type { @@ -53,140 +46,139 @@ static reloc_howto_type elf_mn10200_howto_table[] = /* Dummy relocation. Does nothing. */ HOWTO (R_MN10200_NONE, 0, - 2, - 16, - false, + 3, 0, - complain_overflow_bitfield, + FALSE, + 0, + complain_overflow_dont, bfd_elf_generic_reloc, "R_MN10200_NONE", - false, + FALSE, 0, 0, - false), + FALSE), /* Standard 32 bit reloc. */ HOWTO (R_MN10200_32, 0, 2, 32, - false, + FALSE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_MN10200_32", - false, + FALSE, 0xffffffff, 0xffffffff, - false), + FALSE), /* Standard 16 bit reloc. */ HOWTO (R_MN10200_16, 0, 1, 16, - false, + FALSE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_MN10200_16", - false, + FALSE, 0xffff, 0xffff, - false), + FALSE), /* Standard 8 bit reloc. */ HOWTO (R_MN10200_8, 0, 0, 8, - false, + FALSE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_MN10200_8", - false, + FALSE, 0xff, 0xff, - false), + FALSE), /* Standard 24 bit reloc. */ HOWTO (R_MN10200_24, 0, 2, 24, - false, + FALSE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_MN10200_24", - false, + FALSE, 0xffffff, 0xffffff, - false), + FALSE), /* Simple 8 pc-relative reloc. */ HOWTO (R_MN10200_PCREL8, 0, 0, 8, - true, + TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_MN10200_PCREL8", - false, + FALSE, 0xff, 0xff, - true), + TRUE), /* Simple 16 pc-relative reloc. */ HOWTO (R_MN10200_PCREL16, 0, 1, 16, - true, + TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_MN10200_PCREL16", - false, + FALSE, 0xffff, 0xffff, - true), + TRUE), /* Simple 32bit pc-relative reloc with a 1 byte adjustment to get the pc-relative offset correct. */ HOWTO (R_MN10200_PCREL24, 0, 2, 24, - true, + TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_MN10200_PCREL24", - false, + FALSE, 0xffffff, 0xffffff, - true), + TRUE), }; struct mn10200_reloc_map { - unsigned char bfd_reloc_val; + bfd_reloc_code_real_type bfd_reloc_val; unsigned char elf_reloc_val; }; static const struct mn10200_reloc_map mn10200_reloc_map[] = { - { BFD_RELOC_NONE, R_MN10200_NONE, }, - { BFD_RELOC_32, R_MN10200_32, }, - { BFD_RELOC_16, R_MN10200_16, }, - { BFD_RELOC_8, R_MN10200_8, }, - { BFD_RELOC_24, R_MN10200_24, }, - { BFD_RELOC_8_PCREL, R_MN10200_PCREL8, }, + { BFD_RELOC_NONE , R_MN10200_NONE , }, + { BFD_RELOC_32 , R_MN10200_32 , }, + { BFD_RELOC_16 , R_MN10200_16 , }, + { BFD_RELOC_8 , R_MN10200_8 , }, + { BFD_RELOC_24 , R_MN10200_24 , }, + { BFD_RELOC_8_PCREL , R_MN10200_PCREL8 , }, { BFD_RELOC_16_PCREL, R_MN10200_PCREL16, }, { BFD_RELOC_24_PCREL, R_MN10200_PCREL24, }, }; static reloc_howto_type * -bfd_elf32_bfd_reloc_type_lookup (abfd, code) - bfd *abfd; - bfd_reloc_code_real_type code; +bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type code) { unsigned int i; @@ -201,37 +193,60 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code) return NULL; } +static reloc_howto_type * +bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *r_name) +{ + unsigned int i; + + for (i = 0; + i < (sizeof (elf_mn10200_howto_table) + / sizeof (elf_mn10200_howto_table[0])); + i++) + if (elf_mn10200_howto_table[i].name != NULL + && strcasecmp (elf_mn10200_howto_table[i].name, r_name) == 0) + return &elf_mn10200_howto_table[i]; + + return NULL; +} + /* Set the howto pointer for an MN10200 ELF reloc. */ -static void -mn10200_info_to_howto (abfd, cache_ptr, dst) - bfd *abfd; - arelent *cache_ptr; - Elf32_Internal_Rela *dst; +static bfd_boolean +mn10200_info_to_howto (bfd *abfd, + arelent *cache_ptr, + Elf_Internal_Rela *dst) { unsigned int r_type; r_type = ELF32_R_TYPE (dst->r_info); - BFD_ASSERT (r_type < (unsigned int) R_MN10200_MAX); + if (r_type >= (unsigned int) R_MN10200_MAX) + { + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: unsupported relocation type %#x"), + abfd, r_type); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + cache_ptr->howto = &elf_mn10200_howto_table[r_type]; + return cache_ptr->howto != NULL; } /* Perform a relocation as part of a final link. */ + static bfd_reloc_status_type -mn10200_elf_final_link_relocate (howto, input_bfd, output_bfd, - input_section, contents, offset, value, - addend, info, sym_sec, is_local) - reloc_howto_type *howto; - bfd *input_bfd; - bfd *output_bfd; - asection *input_section; - bfd_byte *contents; - bfd_vma offset; - bfd_vma value; - bfd_vma addend; - struct bfd_link_info *info; - asection *sym_sec; - int is_local; +mn10200_elf_final_link_relocate (reloc_howto_type *howto, + bfd *input_bfd, + bfd *output_bfd ATTRIBUTE_UNUSED, + asection *input_section, + bfd_byte *contents, + bfd_vma offset, + bfd_vma value, + bfd_vma addend, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + asection *sym_sec ATTRIBUTE_UNUSED, + int is_local ATTRIBUTE_UNUSED) { unsigned long r_type = howto->type; bfd_byte *hit_data = contents + offset; @@ -250,7 +265,7 @@ mn10200_elf_final_link_relocate (howto, input_bfd, output_bfd, case R_MN10200_16: value += addend; - if ((long)value > 0x7fff || (long)value < -0x8000) + if ((long) value > 0x7fff || (long) value < -0x8000) return bfd_reloc_overflow; bfd_put_16 (input_bfd, value, hit_data); @@ -259,7 +274,7 @@ mn10200_elf_final_link_relocate (howto, input_bfd, output_bfd, case R_MN10200_8: value += addend; - if ((long)value > 0x7fff || (long)value < -0x8000) + if ((long) value > 0x7f || (long) value < -0x80) return bfd_reloc_overflow; bfd_put_8 (input_bfd, value, hit_data); @@ -268,7 +283,7 @@ mn10200_elf_final_link_relocate (howto, input_bfd, output_bfd, case R_MN10200_24: value += addend; - if ((long)value > 0x7fffff || (long)value < -0x800000) + if ((long) value > 0x7fffff || (long) value < -0x800000) return bfd_reloc_overflow; value &= 0xffffff; @@ -279,11 +294,11 @@ mn10200_elf_final_link_relocate (howto, input_bfd, output_bfd, case R_MN10200_PCREL8: value -= (input_section->output_section->vma + input_section->output_offset); - value -= offset; + value -= (offset + 1); value += addend; - if ((long)value > 0xff || (long)value < -0x100) - return bfd_reloc_overflow; + if ((long) value > 0xff || (long) value < -0x100) + return bfd_reloc_overflow; bfd_put_8 (input_bfd, value, hit_data); return bfd_reloc_ok; @@ -291,11 +306,11 @@ mn10200_elf_final_link_relocate (howto, input_bfd, output_bfd, case R_MN10200_PCREL16: value -= (input_section->output_section->vma + input_section->output_offset); - value -= offset; + value -= (offset + 2); value += addend; - if ((long)value > 0xffff || (long)value < -0x10000) - return bfd_reloc_overflow; + if ((long) value > 0xffff || (long) value < -0x10000) + return bfd_reloc_overflow; bfd_put_16 (input_bfd, value, hit_data); return bfd_reloc_ok; @@ -303,11 +318,11 @@ mn10200_elf_final_link_relocate (howto, input_bfd, output_bfd, case R_MN10200_PCREL24: value -= (input_section->output_section->vma + input_section->output_offset); - value -= offset; + value -= (offset + 3); value += addend; - if ((long)value > 0xffffff || (long)value < -0x1000000) - return bfd_reloc_overflow; + if ((long) value > 0xffffff || (long) value < -0x1000000) + return bfd_reloc_overflow; value &= 0xffffff; value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000); @@ -318,20 +333,17 @@ mn10200_elf_final_link_relocate (howto, input_bfd, output_bfd, return bfd_reloc_notsupported; } } - /* Relocate an MN10200 ELF section. */ -static boolean -mn10200_elf_relocate_section (output_bfd, info, input_bfd, input_section, - contents, relocs, local_syms, local_sections) - bfd *output_bfd; - struct bfd_link_info *info; - bfd *input_bfd; - asection *input_section; - bfd_byte *contents; - Elf_Internal_Rela *relocs; - Elf_Internal_Sym *local_syms; - asection **local_sections; +static bfd_boolean +mn10200_elf_relocate_section (bfd *output_bfd, + struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + bfd_byte *contents, + Elf_Internal_Rela *relocs, + Elf_Internal_Sym *local_syms, + asection **local_sections) { Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; @@ -357,26 +369,6 @@ mn10200_elf_relocate_section (output_bfd, info, input_bfd, input_section, r_type = ELF32_R_TYPE (rel->r_info); howto = elf_mn10200_howto_table + r_type; - if (info->relocateable) - { - /* This is a relocateable link. We don't have to change - anything, unless the reloc is against a section symbol, - in which case we have to adjust according to where the - section symbol winds up in the output section. */ - if (r_symndx < symtab_hdr->sh_info) - { - sym = local_syms + r_symndx; - if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) - { - sec = local_sections[r_symndx]; - rel->r_addend += sec->output_offset + sym->st_value; - } - } - - continue; - } - - /* This is a final link. */ h = NULL; sym = NULL; sec = NULL; @@ -384,36 +376,25 @@ mn10200_elf_relocate_section (output_bfd, info, input_bfd, input_section, { sym = local_syms + r_symndx; sec = local_sections[r_symndx]; - relocation = (sec->output_section->vma - + sec->output_offset - + sym->st_value); + relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); } else { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - { - sec = h->root.u.def.section; - relocation = (h->root.u.def.value - + sec->output_section->vma - + sec->output_offset); - } - else if (h->root.type == bfd_link_hash_undefweak) - relocation = 0; - else - { - if (! ((*info->callbacks->undefined_symbol) - (info, h->root.root.string, input_bfd, - input_section, rel->r_offset))) - return false; - relocation = 0; - } + bfd_boolean unresolved_reloc, warned, ignored; + + RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, + r_symndx, symtab_hdr, sym_hashes, + h, sec, relocation, + unresolved_reloc, warned, ignored); } + if (sec != NULL && discarded_section (sec)) + RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, + rel, 1, relend, howto, 0, contents); + + if (bfd_link_relocatable (info)) + continue; + r = mn10200_elf_final_link_relocate (howto, input_bfd, output_bfd, input_section, contents, rel->r_offset, @@ -423,7 +404,7 @@ mn10200_elf_relocate_section (output_bfd, info, input_bfd, input_section, if (r != bfd_reloc_ok) { const char *name; - const char *msg = (const char *)0; + const char *msg = (const char *) 0; if (h != NULL) name = h->root.root.string; @@ -432,59 +413,127 @@ mn10200_elf_relocate_section (output_bfd, info, input_bfd, input_section, name = (bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name)); if (name == NULL || *name == '\0') - name = bfd_section_name (input_bfd, sec); + name = bfd_section_name (sec); } switch (r) { case bfd_reloc_overflow: - if (! ((*info->callbacks->reloc_overflow) - (info, name, howto->name, (bfd_vma) 0, - input_bfd, input_section, rel->r_offset))) - return false; + (*info->callbacks->reloc_overflow) + (info, (h ? &h->root : NULL), name, howto->name, + (bfd_vma) 0, input_bfd, input_section, rel->r_offset); break; case bfd_reloc_undefined: - if (! ((*info->callbacks->undefined_symbol) - (info, name, input_bfd, input_section, - rel->r_offset))) - return false; + (*info->callbacks->undefined_symbol) (info, name, input_bfd, + input_section, + rel->r_offset, TRUE); break; case bfd_reloc_outofrange: - msg = "internal error: out of range error"; + msg = _("internal error: out of range error"); goto common_error; case bfd_reloc_notsupported: - msg = "internal error: unsupported relocation error"; + msg = _("internal error: unsupported relocation error"); goto common_error; case bfd_reloc_dangerous: - msg = "internal error: dangerous error"; + msg = _("internal error: dangerous error"); goto common_error; default: - msg = "internal error: unknown error"; + msg = _("internal error: unknown error"); /* fall through */ common_error: - if (!((*info->callbacks->warning) - (info, msg, name, input_bfd, input_section, - rel->r_offset))) - return false; + (*info->callbacks->warning) (info, msg, name, input_bfd, + input_section, rel->r_offset); break; } } } - return true; + return TRUE; +} + +/* Delete some bytes from a section while relaxing. */ + +static bfd_boolean +mn10200_elf_relax_delete_bytes (bfd *abfd, asection *sec, + bfd_vma addr, int count) +{ + Elf_Internal_Shdr *symtab_hdr; + unsigned int sec_shndx; + bfd_byte *contents; + Elf_Internal_Rela *irel, *irelend; + bfd_vma toaddr; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; + struct elf_link_hash_entry **sym_hashes; + struct elf_link_hash_entry **end_hashes; + unsigned int symcount; + + sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); + + contents = elf_section_data (sec)->this_hdr.contents; + + toaddr = sec->size; + + irel = elf_section_data (sec)->relocs; + irelend = irel + sec->reloc_count; + + /* Actually delete the bytes. */ + memmove (contents + addr, contents + addr + count, + (size_t) (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 == sec_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 function handles relaxing for the mn10200. - There's quite a few relaxing opportunites available on the mn10200: + There are quite a few relaxing opportunities available on the mn10200: - * jsr:24 -> jsr:16 2 bytes + * jsr:24 -> jsr:16 2 bytes * jmp:24 -> jmp:16 2 bytes * jmp:16 -> bra:8 1 byte @@ -505,53 +554,42 @@ mn10200_elf_relocate_section (output_bfd, info, input_bfd, input_section, abs24, imm24, d24 all look the same at the reloc level. It might make the code simpler if we had different relocs for the various relaxable operand types. - + We don't handle imm16->imm8 or d16->d8 as they're very rare and somewhat more difficult to support. */ -static boolean -mn10200_elf_relax_section (abfd, sec, link_info, again) - bfd *abfd; - asection *sec; - struct bfd_link_info *link_info; - boolean *again; +static bfd_boolean +mn10200_elf_relax_section (bfd *abfd, + asection *sec, + struct bfd_link_info *link_info, + bfd_boolean *again) { Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *free_relocs = NULL; Elf_Internal_Rela *irel, *irelend; bfd_byte *contents = NULL; - bfd_byte *free_contents = NULL; - Elf32_External_Sym *extsyms = NULL; - Elf32_External_Sym *free_extsyms = NULL; + Elf_Internal_Sym *isymbuf = NULL; /* Assume nothing changes. */ - *again = false; + *again = FALSE; - /* We don't have to do anything for a relocateable link, if + /* 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->relocateable + if (bfd_link_relocatable (link_info) || (sec->flags & SEC_RELOC) == 0 || sec->reloc_count == 0 || (sec->flags & SEC_CODE) == 0) - return true; - - /* If this is the first time we have been called for this section, - initialize the cooked size. */ - if (sec->_cooked_size == 0) - sec->_cooked_size = sec->_raw_size; + return TRUE; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; /* Get a copy of the native relocations. */ - internal_relocs = (_bfd_elf32_link_read_relocs - (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, + internal_relocs = (_bfd_elf_link_read_relocs + (abfd, sec, NULL, (Elf_Internal_Rela *) NULL, link_info->keep_memory)); if (internal_relocs == NULL) goto error_return; - if (! link_info->keep_memory) - free_relocs = internal_relocs; /* Walk through them looking for relaxing opportunities. */ irelend = internal_relocs + sec->reloc_count; @@ -575,53 +613,40 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) else { /* Go get them off disk. */ - contents = (bfd_byte *) bfd_malloc (sec->_raw_size); - if (contents == NULL) - goto error_return; - free_contents = contents; - - if (! bfd_get_section_contents (abfd, sec, contents, - (file_ptr) 0, sec->_raw_size)) + if (!bfd_malloc_and_get_section (abfd, sec, &contents)) goto error_return; } } - /* Read the local symbols if we haven't done so already. */ - if (extsyms == NULL) + /* Read this BFD's local symbols if we haven't done so already. */ + if (isymbuf == NULL && symtab_hdr->sh_info != 0) { - /* Get cached copy if it exists. */ - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else - { - /* Go get them off disk. */ - extsyms = ((Elf32_External_Sym *) - bfd_malloc (symtab_hdr->sh_info - * sizeof (Elf32_External_Sym))); - if (extsyms == NULL) - goto error_return; - free_extsyms = extsyms; - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || (bfd_read (extsyms, sizeof (Elf32_External_Sym), - symtab_hdr->sh_info, abfd) - != (symtab_hdr->sh_info * sizeof (Elf32_External_Sym)))) - goto error_return; - } + 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) { - Elf_Internal_Sym isym; - asection *sym_sec; - /* A local symbol. */ - bfd_elf32_swap_symbol_in (abfd, - extsyms + ELF32_R_SYM (irel->r_info), - &isym); + Elf_Internal_Sym *isym; + asection *sym_sec; - sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx); - symval = (isym.st_value + isym = isymbuf + ELF32_R_SYM (irel->r_info); + if (isym->st_shndx == SHN_UNDEF) + sym_sec = bfd_und_section_ptr; + else if (isym->st_shndx == SHN_ABS) + sym_sec = bfd_abs_section_ptr; + else if (isym->st_shndx == SHN_COMMON) + sym_sec = bfd_com_section_ptr; + else + sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); + symval = (isym->st_value + sym_sec->output_section->vma + sym_sec->output_offset); } @@ -638,8 +663,8 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) && 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. */ + symbol. Just ignore it--it will be caught by the + regular reloc processing. */ continue; } @@ -656,7 +681,6 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) that would be more work, but would require less memory when the linker is run. */ - /* Try to turn a 24bit pc-relative branch/call into a 16bit pc-relative branch/call. */ if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10200_PCREL24) @@ -665,13 +689,13 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* Deal with pc-relative gunk. */ value -= (sec->output_section->vma + sec->output_offset); - value -= irel->r_offset; + value -= (irel->r_offset + 3); value += irel->r_addend; /* See if the value will fit in 16 bits, note the high value is 0x7fff + 2 as the target will be two bytes closer if we are able to relax. */ - if ((long)value < 0x8001 && (long)value > -0x8000) + if ((long) value < 0x8001 && (long) value > -0x8000) { unsigned char code; @@ -683,13 +707,8 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - symtab_hdr->contents = (bfd_byte *) extsyms; - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ if (code == 0xe0) @@ -701,9 +720,7 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_MN10200_PCREL16); - /* The opcode got shorter too, so we have to fix the - addend and offset too! */ - irel->r_addend -= 1; + /* The opcode got shorter too, so we have to fix the offset. */ irel->r_offset -= 1; /* Delete two bytes of data. */ @@ -713,7 +730,7 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* That will change things, so, we should relax again. Note that this is not required, and it may be slow. */ - *again = true; + *again = TRUE; } } @@ -725,13 +742,13 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* Deal with pc-relative gunk. */ value -= (sec->output_section->vma + sec->output_offset); - value -= irel->r_offset; + value -= (irel->r_offset + 2); value += irel->r_addend; /* See if the value will fit in 8 bits, note the high value is 0x7f + 1 as the target will be one bytes closer if we are able to relax. */ - if ((long)value < 0x80 && (long)value > -0x80) + if ((long) value < 0x80 && (long) value > -0x80) { unsigned char code; @@ -743,13 +760,8 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - symtab_hdr->contents = (bfd_byte *) extsyms; - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ bfd_put_8 (abfd, 0xea, contents + irel->r_offset - 1); @@ -765,7 +777,7 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* That will change things, so, we should relax again. Note that this is not required, and it may be slow. */ - *again = true; + *again = TRUE; } } @@ -778,7 +790,6 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) bra lab2 lab1: lab1: - This happens when the bCC can't reach lab2 at assembly time, but due to other relaxations it can reach at link time. */ if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10200_PCREL8) @@ -789,11 +800,11 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* Deal with pc-relative gunk. */ value -= (sec->output_section->vma + sec->output_offset); - value -= irel->r_offset; + value -= (irel->r_offset + 1); value += irel->r_addend; /* Do nothing if this reloc is the last byte in the section. */ - if (irel->r_offset == sec->_cooked_size) + if (irel->r_offset == sec->size) continue; /* See if the next instruction is an unconditional pc-relative @@ -818,7 +829,7 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) continue; /* Now make sure we are a conditional branch. This may not - be necessary, but why take the chance. + be necessary, but why take the chance. Note these checks assume that R_MN10200_PCREL8 relocs only occur on bCC and bCCx insns. If they occured @@ -835,80 +846,75 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* We also have to be sure there is no symbol/label at the unconditional branch. */ - if (mn10200_elf_symbol_address_p (abfd, sec, extsyms, + if (mn10200_elf_symbol_address_p (abfd, sec, isymbuf, irel->r_offset + 1)) continue; /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - symtab_hdr->contents = (bfd_byte *) extsyms; - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Reverse the condition of the first branch. */ switch (code) { - case 0xfc: - code = 0xfd; - break; - case 0xfd: - code = 0xfc; - break; - case 0xfe: - code = 0xff; - break; - case 0xff: - code = 0xfe; - break; - case 0xe8: - code = 0xe9; - break; - case 0xe9: - code = 0xe8; - break; - case 0xe0: - code = 0xe2; - break; - case 0xe2: - code = 0xe0; - break; - case 0xe3: - code = 0xe1; - break; - case 0xe1: - code = 0xe3; - break; - case 0xe4: - code = 0xe6; - break; - case 0xe6: - code = 0xe4; - break; - case 0xe7: - code = 0xe5; - break; - case 0xe5: - code = 0xe7; - break; - case 0xec: - code = 0xed; - break; - case 0xed: - code = 0xec; - break; - case 0xee: - code = 0xef; - break; - case 0xef: - code = 0xee; - break; + case 0xfc: + code = 0xfd; + break; + case 0xfd: + code = 0xfc; + break; + case 0xfe: + code = 0xff; + break; + case 0xff: + code = 0xfe; + break; + case 0xe8: + code = 0xe9; + break; + case 0xe9: + code = 0xe8; + break; + case 0xe0: + code = 0xe2; + break; + case 0xe2: + code = 0xe0; + break; + case 0xe3: + code = 0xe1; + break; + case 0xe1: + code = 0xe3; + break; + case 0xe4: + code = 0xe6; + break; + case 0xe6: + code = 0xe4; + break; + case 0xe7: + code = 0xe5; + break; + case 0xe5: + code = 0xe7; + break; + case 0xec: + code = 0xed; + break; + case 0xed: + code = 0xec; + break; + case 0xee: + code = 0xef; + break; + case 0xef: + code = 0xee; + break; } bfd_put_8 (abfd, code, contents + irel->r_offset - 1); - + /* Set the reloc type and symbol for the first branch from the second branch. */ irel->r_info = nrel->r_info; @@ -924,7 +930,7 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* That will change things, so, we should relax again. Note that this is not required, and it may be slow. */ - *again = true; + *again = TRUE; } /* Try to turn a 24bit immediate, displacement or absolute address @@ -933,10 +939,10 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) { bfd_vma value = symval; - /* See if the value will fit in 16 bits. + /* See if the value will fit in 16 bits. We allow any 16bit match here. We prune those we can't handle below. */ - if ((long)value < 0x7fff && (long)value > -0x8000) + if ((long) value < 0x7fff && (long) value > -0x8000) { unsigned char code; @@ -963,15 +969,10 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) if (value & 0x8000) continue; - /* Note that we've changed the reldection contents, etc. */ + /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - symtab_hdr->contents = (bfd_byte *) extsyms; - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ bfd_put_8 (abfd, 0xf8 + (code & 0x03), @@ -982,7 +983,7 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) R_MN10200_16); /* The opcode got shorter too, so we have to fix the - addend and offset too! */ + offset. */ irel->r_offset -= 1; /* Delete two bytes of data. */ @@ -992,10 +993,10 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* That will change things, so, we should relax again. Note that this is not required, and it may be slow. */ - *again = true; + *again = TRUE; break; - /* mov imm24,an -> mov imm16,an + /* mov imm24,an -> mov imm16,an cmp imm24,an -> cmp imm16,an mov (abs24),dn -> mov (abs16),dn mov dn,(abs24) -> mov dn,(abs16) @@ -1007,15 +1008,10 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) case 0x40: case 0x44: case 0xc8: - /* Note that we've changed the reldection contents, etc. */ + /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - symtab_hdr->contents = (bfd_byte *) extsyms; - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; if ((code & 0xfc) == 0x74) code = 0xdc + (code & 0x03); @@ -1038,7 +1034,7 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) R_MN10200_16); /* The opcode got shorter too, so we have to fix the - addend and offset too! */ + offset. */ irel->r_offset -= 1; /* Delete two bytes of data. */ @@ -1048,7 +1044,7 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* That will change things, so, we should relax again. Note that this is not required, and it may be slow. */ - *again = true; + *again = TRUE; break; /* cmp imm24,dn -> cmp imm16,dn @@ -1057,7 +1053,7 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) add imm24,dn -> add imm16,dn add imm24,an -> add imm16,an sub imm24,dn -> sub imm16,dn - sub imm24,an -> sub imm16,an + sub imm24,an -> sub imm16,an And all d24->d16 in memory ops. */ case 0x78: case 0xd0: @@ -1079,31 +1075,26 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) move the value out of high mem and thus not fit in a signed 16bit value. */ if (((code & 0xfc) == 0x78 - || (code & 0xfc) == 0x60 - || (code & 0xfc) == 0x64 - || (code & 0xfc) == 0x68 - || (code & 0xfc) == 0x6c - || (code & 0xfc) == 0x80 - || (code & 0xfc) == 0xf0 - || (code & 0xfc) == 0x00 - || (code & 0xfc) == 0x10 - || (code & 0xfc) == 0xb0 - || (code & 0xfc) == 0x30 - || (code & 0xfc) == 0xa0 - || (code & 0xfc) == 0x20 - || (code & 0xfc) == 0x90) - && (value & 0x8000) != 0) + || (code & 0xfc) == 0x60 + || (code & 0xfc) == 0x64 + || (code & 0xfc) == 0x68 + || (code & 0xfc) == 0x6c + || (code & 0xfc) == 0x80 + || (code & 0xfc) == 0xf0 + || (code & 0xfc) == 0x00 + || (code & 0xfc) == 0x10 + || (code & 0xfc) == 0xb0 + || (code & 0xfc) == 0x30 + || (code & 0xfc) == 0xa0 + || (code & 0xfc) == 0x20 + || (code & 0xfc) == 0x90) + && (value & 0x8000) != 0) continue; - /* Note that we've changed the reldection contents, etc. */ + /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - symtab_hdr->contents = (bfd_byte *) extsyms; - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; /* Fix the opcode. */ bfd_put_8 (abfd, 0xf7, contents + irel->r_offset - 2); @@ -1154,20 +1145,15 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* That will change things, so, we should relax again. Note that this is not required, and it may be slow. */ - *again = true; + *again = TRUE; break; /* movb (abs24),dn ->movbu (abs16),dn extxb bn */ case 0xc4: /* Note that we've changed the reldection contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; - free_relocs = NULL; - elf_section_data (sec)->this_hdr.contents = contents; - free_contents = NULL; - - symtab_hdr->contents = (bfd_byte *) extsyms; - free_extsyms = NULL; + symtab_hdr->contents = (unsigned char *) isymbuf; bfd_put_8 (abfd, 0xcc + (code & 0x03), contents + irel->r_offset - 2); @@ -1190,331 +1176,218 @@ mn10200_elf_relax_section (abfd, sec, link_info, again) /* That will change things, so, we should relax again. Note that this is not required, and it may be slow. */ - *again = true; + *again = TRUE; break; } } } } - if (free_relocs != NULL) - { - free (free_relocs); - free_relocs = NULL; - } - - if (free_contents != NULL) + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) { if (! link_info->keep_memory) - free (free_contents); + free (isymbuf); else { - /* Cache the section contents for elf_link_input_bfd. */ - elf_section_data (sec)->this_hdr.contents = contents; + /* Cache the symbols for elf_link_input_bfd. */ + symtab_hdr->contents = (unsigned char *) isymbuf; } - free_contents = NULL; } - if (free_extsyms != NULL) + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) { if (! link_info->keep_memory) - free (free_extsyms); + free (contents); else { - /* Cache the symbols for elf_link_input_bfd. */ - symtab_hdr->contents = extsyms; + /* Cache the section contents for elf_link_input_bfd. */ + elf_section_data (sec)->this_hdr.contents = contents; } - free_extsyms = NULL; } - return true; - - error_return: - if (free_relocs != NULL) - free (free_relocs); - if (free_contents != NULL) - free (free_contents); - if (free_extsyms != NULL) - free (free_extsyms); - return false; -} - -/* Delete some bytes from a section while relaxing. */ - -static boolean -mn10200_elf_relax_delete_bytes (abfd, sec, addr, count) - bfd *abfd; - asection *sec; - bfd_vma addr; - int count; -{ - Elf_Internal_Shdr *symtab_hdr; - Elf32_External_Sym *extsyms; - int shndx; - bfd_byte *contents; - Elf_Internal_Rela *irel, *irelend; - Elf_Internal_Rela *irelalign; - bfd_vma toaddr; - Elf32_External_Sym *esym, *esymend; - struct elf_link_hash_entry **sym_hash, **sym_hash_end; - - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - - 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->_cooked_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->_cooked_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 all the symbols. */ - esym = extsyms; - esymend = esym + symtab_hdr->sh_info; - for (; esym < esymend; esym++) - { - Elf_Internal_Sym isym; + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); - bfd_elf32_swap_symbol_in (abfd, esym, &isym); + return TRUE; - if (isym.st_shndx == shndx - && isym.st_value > addr - && isym.st_value < toaddr) - { - isym.st_value -= count; - bfd_elf32_swap_symbol_out (abfd, &isym, esym); - } - } - - sym_hash = elf_sym_hashes (abfd); - sym_hash_end = (sym_hash - + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) - - symtab_hdr->sh_info)); - for (; sym_hash < sym_hash_end; sym_hash++) - { - 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; - } - } + 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 true; + return FALSE; } -/* Return true if a symbol exists at the given address, else return - false. */ -static boolean -mn10200_elf_symbol_address_p (abfd, sec, extsyms, addr) - bfd *abfd; - asection *sec; - Elf32_External_Sym *extsyms; - bfd_vma addr; +/* Return TRUE if a symbol exists at the given address, else return + FALSE. */ +static bfd_boolean +mn10200_elf_symbol_address_p (bfd *abfd, + asection *sec, + Elf_Internal_Sym *isym, + bfd_vma addr) { Elf_Internal_Shdr *symtab_hdr; - int shndx; - Elf32_External_Sym *esym, *esymend; - struct elf_link_hash_entry **sym_hash, **sym_hash_end; + unsigned int sec_shndx; + Elf_Internal_Sym *isymend; + struct elf_link_hash_entry **sym_hashes; + struct elf_link_hash_entry **end_hashes; + unsigned int symcount; - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - shndx = _bfd_elf_section_from_bfd_section (abfd, sec); + sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); - /* Examine all the symbols. */ - esym = extsyms; - esymend = esym + symtab_hdr->sh_info; - for (; esym < esymend; esym++) + /* Examine all the local symbols. */ + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) { - Elf_Internal_Sym isym; - - bfd_elf32_swap_symbol_in (abfd, esym, &isym); - - if (isym.st_shndx == shndx - && isym.st_value == addr) - return true; + if (isym->st_shndx == sec_shndx + && isym->st_value == addr) + return TRUE; } - sym_hash = elf_sym_hashes (abfd); - sym_hash_end = (sym_hash - + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) - - symtab_hdr->sh_info)); - for (; sym_hash < sym_hash_end; sym_hash++) + 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++) { - 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) - return true; + 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) + return TRUE; } - return false; + + return FALSE; } /* This is a version of bfd_generic_get_relocated_section_contents which uses mn10200_elf_relocate_section. */ static bfd_byte * -mn10200_elf_get_relocated_section_contents (output_bfd, link_info, link_order, - data, relocateable, symbols) - bfd *output_bfd; - struct bfd_link_info *link_info; - struct bfd_link_order *link_order; - bfd_byte *data; - boolean relocateable; - asymbol **symbols; +mn10200_elf_get_relocated_section_contents (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; - Elf32_External_Sym *external_syms = NULL; - Elf_Internal_Sym *internal_syms = NULL; + Elf_Internal_Sym *isymbuf = NULL; /* We only need to handle the case of relaxing, or of having a particular set of section contents, specially. */ - if (relocateable + 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, - relocateable, + relocatable, symbols); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; memcpy (data, elf_section_data (input_section)->this_hdr.contents, - input_section->_raw_size); + (size_t) input_section->size); if ((input_section->flags & SEC_RELOC) != 0 && input_section->reloc_count > 0) { - Elf_Internal_Sym *isymp; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; asection **secpp; - Elf32_External_Sym *esym, *esymend; - - if (symtab_hdr->contents != NULL) - external_syms = (Elf32_External_Sym *) symtab_hdr->contents; - else - { - external_syms = ((Elf32_External_Sym *) - bfd_malloc (symtab_hdr->sh_info - * sizeof (Elf32_External_Sym))); - if (external_syms == NULL && symtab_hdr->sh_info > 0) - goto error_return; - if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || (bfd_read (external_syms, sizeof (Elf32_External_Sym), - symtab_hdr->sh_info, input_bfd) - != (symtab_hdr->sh_info * sizeof (Elf32_External_Sym)))) - goto error_return; - } + bfd_size_type amt; - internal_relocs = (_bfd_elf32_link_read_relocs - (input_bfd, input_section, (PTR) NULL, - (Elf_Internal_Rela *) NULL, false)); + internal_relocs = (_bfd_elf_link_read_relocs + (input_bfd, input_section, NULL, + (Elf_Internal_Rela *) NULL, FALSE)); if (internal_relocs == NULL) goto error_return; - internal_syms = ((Elf_Internal_Sym *) - bfd_malloc (symtab_hdr->sh_info - * sizeof (Elf_Internal_Sym))); - if (internal_syms == NULL && symtab_hdr->sh_info > 0) - 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; + } - sections = (asection **) bfd_malloc (symtab_hdr->sh_info - * sizeof (asection *)); - if (sections == NULL && symtab_hdr->sh_info > 0) + amt = symtab_hdr->sh_info; + amt *= sizeof (asection *); + sections = (asection **) bfd_malloc (amt); + if (sections == NULL && amt != 0) goto error_return; - isymp = internal_syms; - secpp = sections; - esym = external_syms; - esymend = esym + symtab_hdr->sh_info; - for (; esym < esymend; ++esym, ++isymp, ++secpp) + isymend = isymbuf + symtab_hdr->sh_info; + for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp) { asection *isec; - bfd_elf32_swap_symbol_in (input_bfd, esym, isymp); - - if (isymp->st_shndx == SHN_UNDEF) + if (isym->st_shndx == SHN_UNDEF) isec = bfd_und_section_ptr; - else if (isymp->st_shndx > 0 && isymp->st_shndx < SHN_LORESERVE) - isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx); - else if (isymp->st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) isec = bfd_abs_section_ptr; - else if (isymp->st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) isec = bfd_com_section_ptr; else - { - /* Who knows? */ - isec = NULL; - } + isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx); *secpp = isec; } if (! mn10200_elf_relocate_section (output_bfd, link_info, input_bfd, input_section, data, internal_relocs, - internal_syms, sections)) + isymbuf, sections)) goto error_return; if (sections != NULL) free (sections); - sections = NULL; - if (internal_syms != NULL) - free (internal_syms); - internal_syms = NULL; - if (external_syms != NULL && symtab_hdr->contents == NULL) - free (external_syms); - external_syms = NULL; - if (internal_relocs != elf_section_data (input_section)->relocs) + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (elf_section_data (input_section)->relocs != internal_relocs) free (internal_relocs); - internal_relocs = NULL; } return data; error_return: - if (internal_relocs != NULL - && internal_relocs != elf_section_data (input_section)->relocs) - free (internal_relocs); - if (external_syms != NULL && symtab_hdr->contents == NULL) - free (external_syms); - if (internal_syms != NULL) - free (internal_syms); 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; } - -#define TARGET_LITTLE_SYM bfd_elf32_mn10200_vec +#define TARGET_LITTLE_SYM mn10200_elf32_vec #define TARGET_LITTLE_NAME "elf32-mn10200" #define ELF_ARCH bfd_arch_mn10200 -#define ELF_MACHINE_CODE EM_CYGNUS_MN10200 +#define ELF_MACHINE_CODE EM_MN10200 +#define ELF_MACHINE_ALT1 EM_CYGNUS_MN10200 #define ELF_MAXPAGESIZE 0x1000 +#define elf_backend_rela_normal 1 #define elf_info_to_howto mn10200_info_to_howto -#define elf_info_to_howto_rel 0 +#define elf_info_to_howto_rel NULL #define elf_backend_relocate_section mn10200_elf_relocate_section #define bfd_elf32_bfd_relax_section mn10200_elf_relax_section #define bfd_elf32_bfd_get_relocated_section_contents \