X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf32-xstormy16.c;h=d6a48bf7bbe9a988e87d20a91a69ad8eef416dc3;hb=545fd46b6bb24535905e4bc69b91537fee065bf3;hp=af9a04882fed9bd61a199c702b501768537f3731;hpb=1049f94e8e1a9eae86a694d2dca94a6194f763b1;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-xstormy16.c b/bfd/elf32-xstormy16.c index af9a04882f..d6a48bf7bb 100644 --- a/bfd/elf32-xstormy16.c +++ b/bfd/elf32-xstormy16.c @@ -1,61 +1,73 @@ -/* XSTORMY16-specific support for 32-bit ELF. - Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +/* Xstormy16-specific support for 32-bit ELF. + Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2010, 2011, 2012 + 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" #include "elf/xstormy16.h" #include "libiberty.h" -/* Forward declarations. */ -static reloc_howto_type * xstormy16_reloc_type_lookup - PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); -static void xstormy16_info_to_howto_rela - PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); -static bfd_reloc_status_type xstormy16_elf_24_reloc - PARAMS ((bfd *abfd, arelent *reloc_entry, asymbol *symbol, - PTR data, asection *input_section, bfd *output_bfd, - char **error_message)); -static bfd_boolean xstormy16_elf_check_relocs - PARAMS ((bfd *, struct bfd_link_info *, asection *, - const Elf_Internal_Rela *)); -static bfd_boolean xstormy16_relax_plt_check - PARAMS ((struct elf_link_hash_entry *, PTR)); -static bfd_boolean xstormy16_relax_plt_realloc - PARAMS ((struct elf_link_hash_entry *, PTR)); -static bfd_boolean xstormy16_elf_relax_section - PARAMS ((bfd *abfd, asection *sec, struct bfd_link_info *link_info, - bfd_boolean *again)); -static bfd_boolean xstormy16_elf_always_size_sections - PARAMS ((bfd *, struct bfd_link_info *)); -static bfd_boolean xstormy16_elf_relocate_section - PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, - Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); -static bfd_boolean xstormy16_elf_finish_dynamic_sections - PARAMS((bfd *, struct bfd_link_info *)); -static bfd_boolean xstormy16_elf_gc_sweep_hook - PARAMS ((bfd *, struct bfd_link_info *, asection *, - const Elf_Internal_Rela *)); -static asection * xstormy16_elf_gc_mark_hook - PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, - struct elf_link_hash_entry *, Elf_Internal_Sym *)); +/* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement. */ + +static bfd_reloc_status_type +xstormy16_elf_24_reloc (bfd *abfd, + arelent *reloc_entry, + asymbol *symbol, + void * data, + asection *input_section, + bfd *output_bfd, + char **error_message ATTRIBUTE_UNUSED) +{ + bfd_vma relocation, x; + + if (output_bfd != NULL) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + + if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) + return bfd_reloc_outofrange; + + if (bfd_is_com_section (symbol->section)) + relocation = 0; + else + relocation = symbol->value; + + relocation += symbol->section->output_section->vma; + relocation += symbol->section->output_offset; + relocation += reloc_entry->addend; + + x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); + x &= 0x0000ff00; + x |= relocation & 0xff; + x |= (relocation << 8) & 0xffff0000; + bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address); + + if (relocation & ~ (bfd_vma) 0xffffff) + return bfd_reloc_overflow; + + return bfd_reloc_ok; +} static reloc_howto_type xstormy16_elf_howto_table [] = { @@ -238,7 +250,7 @@ static reloc_howto_type xstormy16_elf_howto_table [] = 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - + /* A 12 bit absolute relocation. */ HOWTO (R_XSTORMY16_12, /* type */ 0, /* rightshift */ @@ -318,9 +330,8 @@ static const reloc_map xstormy16_reloc_map [] = }; static reloc_howto_type * -xstormy16_reloc_type_lookup (abfd, code) - bfd * abfd ATTRIBUTE_UNUSED; - bfd_reloc_code_real_type code; +xstormy16_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type code) { unsigned int i; @@ -338,13 +349,37 @@ xstormy16_reloc_type_lookup (abfd, code) return NULL; } +static reloc_howto_type * +xstormy16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *r_name) +{ + unsigned int i; + + for (i = 0; + i < (sizeof (xstormy16_elf_howto_table) + / sizeof (xstormy16_elf_howto_table[0])); + i++) + if (xstormy16_elf_howto_table[i].name != NULL + && strcasecmp (xstormy16_elf_howto_table[i].name, r_name) == 0) + return &xstormy16_elf_howto_table[i]; + + for (i = 0; + i < (sizeof (xstormy16_elf_howto_table2) + / sizeof (xstormy16_elf_howto_table2[0])); + i++) + if (xstormy16_elf_howto_table2[i].name != NULL + && strcasecmp (xstormy16_elf_howto_table2[i].name, r_name) == 0) + return &xstormy16_elf_howto_table2[i]; + + return NULL; +} + /* Set the howto pointer for an XSTORMY16 ELF reloc. */ static void -xstormy16_info_to_howto_rela (abfd, cache_ptr, dst) - bfd * abfd ATTRIBUTE_UNUSED; - arelent * cache_ptr; - Elf_Internal_Rela * dst; +xstormy16_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED, + arelent * cache_ptr, + Elf_Internal_Rela * dst) { unsigned int r_type = ELF32_R_TYPE (dst->r_info); @@ -357,51 +392,6 @@ xstormy16_info_to_howto_rela (abfd, cache_ptr, dst) else abort (); } - -/* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement. */ - -static bfd_reloc_status_type -xstormy16_elf_24_reloc (abfd, reloc_entry, symbol, data, input_section, - output_bfd, error_message) - bfd *abfd; - arelent *reloc_entry; - asymbol *symbol; - PTR data; - asection *input_section; - bfd *output_bfd; - char **error_message ATTRIBUTE_UNUSED; -{ - bfd_vma relocation, x; - - if (output_bfd != NULL) - { - reloc_entry->address += input_section->output_offset; - return bfd_reloc_ok; - } - - if (reloc_entry->address > input_section->_cooked_size) - return bfd_reloc_outofrange; - - if (bfd_is_com_section (symbol->section)) - relocation = 0; - else - relocation = symbol->value; - - relocation += symbol->section->output_section->vma; - relocation += symbol->section->output_offset; - relocation += reloc_entry->addend; - - x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); - x &= 0x0000ff00; - x |= relocation & 0xff; - x |= (relocation << 8) & 0xffff0000; - bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address); - - if (relocation & ~ (bfd_vma) 0xffffff) - return bfd_reloc_overflow; - - return bfd_reloc_ok; -} /* We support 16-bit pointers to code above 64k by generating a thunk below 64k containing a JMPF instruction to the final address. We @@ -410,11 +400,10 @@ xstormy16_elf_24_reloc (abfd, reloc_entry, symbol, data, input_section, sections will fall in the address space. */ static bfd_boolean -xstormy16_elf_check_relocs (abfd, info, sec, relocs) - bfd *abfd; - struct bfd_link_info *info; - asection *sec; - const Elf_Internal_Rela *relocs; +xstormy16_elf_check_relocs (bfd *abfd, + struct bfd_link_info *info, + asection *sec, + const Elf_Internal_Rela *relocs) { const Elf_Internal_Rela *rel, *relend; struct elf_link_hash_entry **sym_hashes; @@ -470,16 +459,16 @@ xstormy16_elf_check_relocs (abfd, info, sec, relocs) splt = bfd_get_section_by_name (dynobj, ".plt"); if (splt == NULL) { - splt = bfd_make_section (dynobj, ".plt"); + splt = bfd_make_section_with_flags (dynobj, ".plt", + (SEC_ALLOC + | SEC_LOAD + | SEC_HAS_CONTENTS + | SEC_IN_MEMORY + | SEC_LINKER_CREATED + | SEC_READONLY + | SEC_CODE)); + if (splt == NULL - || ! bfd_set_section_flags (dynobj, splt, - (SEC_ALLOC - | SEC_LOAD - | SEC_HAS_CONTENTS - | SEC_IN_MEMORY - | SEC_LINKER_CREATED - | SEC_READONLY - | SEC_CODE)) || ! bfd_set_section_alignment (dynobj, splt, 1)) return FALSE; } @@ -495,7 +484,7 @@ xstormy16_elf_check_relocs (abfd, info, sec, relocs) unsigned int i; size = symtab_hdr->sh_info * sizeof (bfd_vma); - local_plt_offsets = (bfd_vma *) bfd_alloc (abfd, size); + local_plt_offsets = bfd_alloc (abfd, size); if (local_plt_offsets == NULL) return FALSE; elf_local_got_offsets (abfd) = local_plt_offsets; @@ -508,22 +497,24 @@ xstormy16_elf_check_relocs (abfd, info, sec, relocs) if (*offset == (bfd_vma) -1) { - *offset = splt->_raw_size; - splt->_raw_size += 4; + *offset = splt->size; + splt->size += 4; } break; /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_XSTORMY16_GNU_VTINHERIT: - if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) + if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) return FALSE; break; /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_XSTORMY16_GNU_VTENTRY: - if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) + BFD_ASSERT (h != NULL); + if (h != NULL + && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) return FALSE; break; } @@ -542,15 +533,10 @@ struct relax_plt_data }; static bfd_boolean -xstormy16_relax_plt_check (h, xdata) - struct elf_link_hash_entry *h; - PTR xdata; +xstormy16_relax_plt_check (struct elf_link_hash_entry *h, void * xdata) { struct relax_plt_data *data = (struct relax_plt_data *) xdata; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (h->plt.offset != (bfd_vma) -1) { bfd_vma address; @@ -566,7 +552,7 @@ xstormy16_relax_plt_check (h, xdata) if (address <= 0xffff) { h->plt.offset = -1; - data->splt->_cooked_size -= 4; + data->splt->size -= 4; *data->again = TRUE; } } @@ -578,15 +564,10 @@ xstormy16_relax_plt_check (h, xdata) previously had a plt entry, give it a new entry offset. */ static bfd_boolean -xstormy16_relax_plt_realloc (h, xdata) - struct elf_link_hash_entry *h; - PTR xdata; +xstormy16_relax_plt_realloc (struct elf_link_hash_entry *h, void * xdata) { bfd_vma *entry = (bfd_vma *) xdata; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (h->plt.offset != (bfd_vma) -1) { h->plt.offset = *entry; @@ -597,11 +578,10 @@ xstormy16_relax_plt_realloc (h, xdata) } static bfd_boolean -xstormy16_elf_relax_section (dynobj, splt, info, again) - bfd *dynobj; - asection *splt; - struct bfd_link_info *info; - bfd_boolean *again; +xstormy16_elf_relax_section (bfd *dynobj, + asection *splt, + struct bfd_link_info *info, + bfd_boolean *again) { struct relax_plt_data relax_plt_data; bfd *ibfd; @@ -618,14 +598,9 @@ xstormy16_elf_relax_section (dynobj, splt, info, again) return TRUE; /* Quick check for an empty plt. */ - if (splt->_raw_size == 0) + if (splt->size == 0) return TRUE; - /* If this is the first time we have been called for this section, - initialize the cooked size. */ - if (splt->_cooked_size == 0) - splt->_cooked_size = splt->_raw_size; - /* Map across all global symbols; see which ones happen to fall in the low 64k. */ relax_plt_data.splt = splt; @@ -682,7 +657,7 @@ xstormy16_elf_relax_section (dynobj, splt, info, again) if (address <= 0xffff) { local_plt_offsets[idx] = -1; - splt->_cooked_size -= 4; + splt->size -= 4; *again = TRUE; } } @@ -702,7 +677,7 @@ xstormy16_elf_relax_section (dynobj, splt, info, again) /* If we changed anything, walk the symbols again to reallocate .plt entry addresses. */ - if (*again && splt->_cooked_size > 0) + if (*again && splt->size > 0) { bfd_vma entry = 0; @@ -727,14 +702,12 @@ xstormy16_elf_relax_section (dynobj, splt, info, again) } } - splt->_raw_size = splt->_cooked_size; return TRUE; } static bfd_boolean -xstormy16_elf_always_size_sections (output_bfd, info) - bfd *output_bfd ATTRIBUTE_UNUSED; - struct bfd_link_info *info; +xstormy16_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info) { bfd *dynobj; asection *splt; @@ -749,7 +722,7 @@ xstormy16_elf_always_size_sections (output_bfd, info) splt = bfd_get_section_by_name (dynobj, ".plt"); BFD_ASSERT (splt != NULL); - splt->contents = (bfd_byte *) bfd_zalloc (dynobj, splt->_raw_size); + splt->contents = bfd_zalloc (dynobj, splt->size); if (splt->contents == NULL) return FALSE; @@ -787,16 +760,14 @@ xstormy16_elf_always_size_sections (output_bfd, info) accordingly. */ static bfd_boolean -xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section, - contents, relocs, local_syms, local_sections) - bfd * output_bfd ATTRIBUTE_UNUSED; - 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; +xstormy16_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, + 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; @@ -805,9 +776,6 @@ xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section, bfd *dynobj; asection *splt; - if (info->relocatable) - return TRUE; - symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); relend = relocs + input_section->reloc_count; @@ -845,42 +813,33 @@ xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section, { sym = local_syms + r_symndx; sec = local_sections [r_symndx]; - relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); - - name = bfd_elf_string_from_elf_section - (input_bfd, symtab_hdr->sh_link, sym->st_name); - name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; + relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); } else { - h = sym_hashes [r_symndx - symtab_hdr->sh_info]; + bfd_boolean unresolved_reloc, warned; - 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; + RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, + r_symndx, symtab_hdr, sym_hashes, + h, sec, relocation, + unresolved_reloc, warned); + } - name = h->root.root.string; + if (sec != NULL && discarded_section (sec)) + RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, + rel, 1, relend, howto, 0, contents); - 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, TRUE))) - return FALSE; - relocation = 0; - } + if (info->relocatable) + continue; + + if (h != NULL) + name = h->root.root.string; + else + { + 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); } switch (ELF32_R_TYPE (rel->r_info)) @@ -956,14 +915,14 @@ xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section, if (r != bfd_reloc_ok) { - const char * msg = (const char *) NULL; + const char * msg = NULL; switch (r) { case bfd_reloc_overflow: r = info->callbacks->reloc_overflow - (info, name, howto->name, (bfd_vma) 0, - input_bfd, input_section, rel->r_offset); + (info, (h ? &h->root : NULL), name, howto->name, + (bfd_vma) 0, input_bfd, input_section, rel->r_offset); break; case bfd_reloc_undefined: @@ -1004,9 +963,8 @@ xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* This must exist if dynobj is ever set. */ static bfd_boolean -xstormy16_elf_finish_dynamic_sections (abfd, info) - bfd *abfd ATTRIBUTE_UNUSED; - struct bfd_link_info *info; +xstormy16_elf_finish_dynamic_sections (bfd *abfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info) { bfd *dynobj; asection *splt; @@ -1018,10 +976,12 @@ xstormy16_elf_finish_dynamic_sections (abfd, info) && (splt = bfd_get_section_by_name (dynobj, ".plt")) != NULL) { bfd_byte *contents = splt->contents; - unsigned int i, size = splt->_raw_size; + unsigned int i, size = splt->size; + for (i = 0; i < size; i += 4) { unsigned int x = bfd_get_32 (dynobj, contents + i); + BFD_ASSERT (x != 0); } } @@ -1033,52 +993,21 @@ xstormy16_elf_finish_dynamic_sections (abfd, info) relocation. */ static asection * -xstormy16_elf_gc_mark_hook (sec, info, rel, h, sym) - asection * sec; - struct bfd_link_info * info ATTRIBUTE_UNUSED; - Elf_Internal_Rela * rel; - struct elf_link_hash_entry * h; - Elf_Internal_Sym * sym; +xstormy16_elf_gc_mark_hook (asection *sec, + struct bfd_link_info *info, + Elf_Internal_Rela *rel, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) { if (h != NULL) - { - switch (ELF32_R_TYPE (rel->r_info)) - { - case R_XSTORMY16_GNU_VTINHERIT: - case R_XSTORMY16_GNU_VTENTRY: - break; - - default: - switch (h->root.type) - { - case bfd_link_hash_defined: - case bfd_link_hash_defweak: - return h->root.u.def.section; - - case bfd_link_hash_common: - return h->root.u.c.p->section; - - default: - break; - } - } - } - else - return bfd_section_from_elf_index (sec->owner, sym->st_shndx); - - return NULL; -} - -/* Update the got entry reference counts for the section being removed. */ - -static bfd_boolean -xstormy16_elf_gc_sweep_hook (abfd, info, sec, relocs) - bfd * abfd ATTRIBUTE_UNUSED; - struct bfd_link_info * info ATTRIBUTE_UNUSED; - asection * sec ATTRIBUTE_UNUSED; - const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED; -{ - return TRUE; + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_XSTORMY16_GNU_VTINHERIT: + case R_XSTORMY16_GNU_VTENTRY: + return NULL; + } + + return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } #define ELF_ARCH bfd_arch_xstormy16 @@ -1092,10 +1021,11 @@ xstormy16_elf_gc_sweep_hook (abfd, info, sec, relocs) #define elf_info_to_howto xstormy16_info_to_howto_rela #define elf_backend_relocate_section xstormy16_elf_relocate_section #define elf_backend_gc_mark_hook xstormy16_elf_gc_mark_hook -#define elf_backend_gc_sweep_hook xstormy16_elf_gc_sweep_hook #define elf_backend_check_relocs xstormy16_elf_check_relocs #define elf_backend_always_size_sections \ xstormy16_elf_always_size_sections +#define elf_backend_omit_section_dynsym \ + ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true) #define elf_backend_finish_dynamic_sections \ xstormy16_elf_finish_dynamic_sections @@ -1103,6 +1033,8 @@ xstormy16_elf_gc_sweep_hook (abfd, info, sec, relocs) #define elf_backend_rela_normal 1 #define bfd_elf32_bfd_reloc_type_lookup xstormy16_reloc_type_lookup +#define bfd_elf32_bfd_reloc_name_lookup \ + xstormy16_reloc_name_lookup #define bfd_elf32_bfd_relax_section xstormy16_elf_relax_section #include "elf32-target.h"