diff options
Diffstat (limited to 'bfd/elf32-m32r.c')
-rw-r--r-- | bfd/elf32-m32r.c | 372 |
1 files changed, 171 insertions, 201 deletions
diff --git a/bfd/elf32-m32r.c b/bfd/elf32-m32r.c index 6c42c2f5b60de..31151fc1a47fc 100644 --- a/bfd/elf32-m32r.c +++ b/bfd/elf32-m32r.c @@ -1,6 +1,6 @@ /* M32R-specific support for 32-bit ELF. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006 Free Software Foundation, Inc. + 2006, 2007 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -18,8 +18,8 @@ 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/m32r.h" @@ -1254,6 +1254,22 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 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 (m32r_elf_howto_table) / sizeof (m32r_elf_howto_table[0]); + i++) + if (m32r_elf_howto_table[i].name != NULL + && strcasecmp (m32r_elf_howto_table[i].name, r_name) == 0) + return &m32r_elf_howto_table[i]; + + return NULL; +} + /* Set the howto pointer for an M32R ELF reloc. */ static void @@ -1817,7 +1833,6 @@ m32r_elf_adjust_dynamic_symbol (struct bfd_link_info *info, struct elf_m32r_dyn_relocs *p; bfd *dynobj; asection *s; - unsigned int power_of_two; #ifdef DEBUG_PIC printf ("m32r_elf_adjust_dynamic_symbol()\n"); @@ -1945,28 +1960,7 @@ m32r_elf_adjust_dynamic_symbol (struct bfd_link_info *info, h->needs_copy = 1; } - /* We need to figure out the alignment required for this symbol. I - have no idea how ELF linkers handle this. */ - power_of_two = bfd_log2 (h->size); - if (power_of_two > 3) - power_of_two = 3; - - /* Apply the required alignment. */ - s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two)); - if (power_of_two > bfd_get_section_alignment (dynobj, s)) - { - if (! bfd_set_section_alignment (dynobj, s, power_of_two)) - return FALSE; - } - - /* Define the symbol as being at this point in the section. */ - h->root.u.def.section = s; - h->root.u.def.value = s->size; - - /* Increment the section size to make room for the symbol. */ - s->size += h->size; - - return TRUE; + return _bfd_elf_adjust_dynamic_copy (h, s); } /* Allocate space in .plt, .got and associated reloc sections for @@ -2309,7 +2303,7 @@ m32r_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, /* Strip this section if we don't need it; see the comment below. */ } - else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) + else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela")) { if (s->size != 0 && s != htab->srelplt) relocs = TRUE; @@ -2477,6 +2471,7 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, `r_addend'. */ bfd_vma addend = rel->r_addend; bfd_vma offset = rel->r_offset; + bfd_vma relocation; Elf_Internal_Sym *sym; asection *sec; const char *sym_name; @@ -2509,27 +2504,152 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, howto = m32r_elf_howto_table + r_type; r_symndx = ELF32_R_SYM (rel->r_info); - if (info->relocatable && use_rel) + sym = NULL; + sec = NULL; + h = NULL; + + if (r_symndx < symtab_hdr->sh_info) + { + /* Local symbol. */ + sym = local_syms + r_symndx; + sec = local_sections[r_symndx]; + sym_name = "<local symbol>"; + + if (!use_rel) + { + relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); + addend = rel->r_addend; + } + else + { + relocation = (sec->output_section->vma + + sec->output_offset + + sym->st_value); + } + } + else + { + /* External symbol. */ + relocation = 0; + + 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; + sym_name = h->root.root.string; + + if (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + { + bfd_boolean dyn; + sec = h->root.u.def.section; + + dyn = htab->root.dynamic_sections_created; + sec = h->root.u.def.section; + if (r_type == R_M32R_GOTPC24 + || (r_type == R_M32R_GOTPC_HI_ULO + || r_type == R_M32R_GOTPC_HI_SLO + || r_type == R_M32R_GOTPC_LO) + || (r_type == R_M32R_26_PLTREL + && h->plt.offset != (bfd_vma) -1) + || ((r_type == R_M32R_GOT24 + || r_type == R_M32R_GOT16_HI_ULO + || r_type == R_M32R_GOT16_HI_SLO + || r_type == R_M32R_GOT16_LO) + && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, + info->shared, h) + && (! info->shared + || (! info->symbolic && h->dynindx != -1) + || !h->def_regular)) + || (info->shared + && ((! info->symbolic && h->dynindx != -1) + || !h->def_regular) + && (((r_type == R_M32R_16_RELA + || r_type == R_M32R_32_RELA + || r_type == R_M32R_24_RELA + || r_type == R_M32R_HI16_ULO_RELA + || r_type == R_M32R_HI16_SLO_RELA + || r_type == R_M32R_LO16_RELA) + && !h->forced_local) + || r_type == R_M32R_REL32 + || r_type == R_M32R_10_PCREL_RELA + || r_type == R_M32R_18_PCREL_RELA + || r_type == R_M32R_26_PCREL_RELA) + && ((input_section->flags & SEC_ALLOC) != 0 + /* DWARF will emit R_M32R_16(24,32) relocations + in its sections against symbols defined + externally in shared libraries. We can't do + anything with them here. */ + || ((input_section->flags & SEC_DEBUGGING) != 0 + && h->def_dynamic)))) + { + /* In these cases, we don't need the relocation + value. We check specially because in some + obscure cases sec->output_section will be NULL. */ + } + else if (sec->output_section != NULL) + relocation = (h->root.u.def.value + + sec->output_section->vma + + sec->output_offset); + else if (!info->relocatable) + { + (*_bfd_error_handler) + (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), + input_bfd, + input_section, + (long) rel->r_offset, + howto->name, + h->root.root.string); + } + } + else if (h->root.type == bfd_link_hash_undefweak) + ; + else if (info->unresolved_syms_in_objects == RM_IGNORE + && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) + ; + else if (!info->relocatable) + { + if (! ((*info->callbacks->undefined_symbol) + (info, h->root.root.string, input_bfd, + input_section, offset, + (info->unresolved_syms_in_objects == RM_GENERATE_ERROR + || ELF_ST_VISIBILITY (h->other))))) + return FALSE; + } + } + + if (sec != NULL && elf_discarded_section (sec)) + { + /* For relocs against symbols from removed linkonce sections, + or sections discarded by a linker script, we just want the + section contents zeroed. Avoid any special processing. */ + _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); + rel->r_info = 0; + rel->r_addend = 0; + continue; + } + + if (info->relocatable && !use_rel) { /* This is a relocatable 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. */ - sec = NULL; - if (r_symndx >= symtab_hdr->sh_info) - /* External symbol. */ - continue; + if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION) + rel->r_addend += sec->output_offset; + continue; + } - /* Local symbol. */ - sym = local_syms + r_symndx; - sym_name = "<local symbol>"; - /* STT_SECTION: symbol is associated with a section. */ - if (ELF_ST_TYPE (sym->st_info) != STT_SECTION) - /* Symbol isn't associated with a section. Nothing to do. */ + if (info->relocatable && use_rel) + { + /* This is a relocatable 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 (sym == NULL || ELF_ST_TYPE (sym->st_info) != STT_SECTION) continue; - sec = local_sections[r_symndx]; - addend += sec->output_offset + sym->st_value; + addend += sec->output_offset; /* If partial_inplace, we need to store any additional addend back in the section. */ @@ -2567,140 +2687,6 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, } else { - bfd_vma relocation; - - /* This is a final link. */ - sym = NULL; - sec = NULL; - h = NULL; - - if (r_symndx < symtab_hdr->sh_info) - { - /* Local symbol. */ - sym = local_syms + r_symndx; - sec = local_sections[r_symndx]; - sym_name = "<local symbol>"; - - if (!use_rel) - { - relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); - addend = rel->r_addend; - - if (info->relocatable) - { - /* This is a relocatable 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 (ELF_ST_TYPE (sym->st_info) == STT_SECTION) - rel->r_addend += sec->output_offset + sym->st_value; - - continue; - } - } - else - { - relocation = (sec->output_section->vma - + sec->output_offset - + sym->st_value); - } - } - else - { - /* External symbol. */ - if (info->relocatable && !use_rel) - continue; - - 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; - sym_name = h->root.root.string; - - if (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - { - bfd_boolean dyn; - sec = h->root.u.def.section; - - dyn = htab->root.dynamic_sections_created; - sec = h->root.u.def.section; - if (r_type == R_M32R_GOTPC24 - || (r_type == R_M32R_GOTPC_HI_ULO - || r_type == R_M32R_GOTPC_HI_SLO - || r_type == R_M32R_GOTPC_LO) - || (r_type == R_M32R_26_PLTREL - && h->plt.offset != (bfd_vma) -1) - || ((r_type == R_M32R_GOT24 - || r_type == R_M32R_GOT16_HI_ULO - || r_type == R_M32R_GOT16_HI_SLO - || r_type == R_M32R_GOT16_LO) - && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, - info->shared, h) - && (! info->shared - || (! info->symbolic && h->dynindx != -1) - || !h->def_regular)) - || (info->shared - && ((! info->symbolic && h->dynindx != -1) - || !h->def_regular) - && (((r_type == R_M32R_16_RELA - || r_type == R_M32R_32_RELA - || r_type == R_M32R_24_RELA - || r_type == R_M32R_HI16_ULO_RELA - || r_type == R_M32R_HI16_SLO_RELA - || r_type == R_M32R_LO16_RELA) - && !h->forced_local) - || r_type == R_M32R_REL32 - || r_type == R_M32R_10_PCREL_RELA - || r_type == R_M32R_18_PCREL_RELA - || r_type == R_M32R_26_PCREL_RELA) - && ((input_section->flags & SEC_ALLOC) != 0 - /* DWARF will emit R_M32R_16(24,32) relocations - in its sections against symbols defined - externally in shared libraries. We can't do - anything with them here. */ - || ((input_section->flags & SEC_DEBUGGING) != 0 - && h->def_dynamic)))) - { - /* In these cases, we don't need the relocation - value. We check specially because in some - obscure cases sec->output_section will be NULL. */ - relocation = 0; - } - else if (sec->output_section == NULL) - { - (*_bfd_error_handler) - (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), - input_bfd, - input_section, - (long) rel->r_offset, - howto->name, - h->root.root.string); - - relocation = 0; - } - else - 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->unresolved_syms_in_objects == RM_IGNORE - && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) - relocation = 0; - else - { - if (! ((*info->callbacks->undefined_symbol) - (info, h->root.root.string, input_bfd, - input_section, offset, - (info->unresolved_syms_in_objects == RM_GENERATE_ERROR - || ELF_ST_VISIBILITY (h->other))))) - return FALSE; - relocation = 0; - } - } - /* Sanity check the address. */ if (offset > high_address) { @@ -2933,7 +2919,7 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, if (name == NULL) return FALSE; - BFD_ASSERT (strncmp (name, ".rela", 5) == 0 + BFD_ASSERT (CONST_STRNEQ (name, ".rela") && strcmp (bfd_get_section_name (input_bfd, input_section), name + 5) == 0); @@ -3637,40 +3623,22 @@ m32r_elf_print_private_bfd_data (bfd *abfd, void * ptr) static asection * m32r_elf_gc_mark_hook (asection *sec, - struct bfd_link_info *info ATTRIBUTE_UNUSED, + 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)) + switch (ELF32_R_TYPE (rel->r_info)) { case R_M32R_GNU_VTINHERIT: case R_M32R_GNU_VTENTRY: case R_M32R_RELA_GNU_VTINHERIT: case R_M32R_RELA_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; + } - return NULL; + return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } static bfd_boolean @@ -3990,7 +3958,7 @@ m32r_elf_check_relocs (bfd *abfd, if (name == NULL) return FALSE; - BFD_ASSERT (strncmp (name, ".rela", 5) == 0 + BFD_ASSERT (CONST_STRNEQ (name, ".rela") && strcmp (bfd_get_section_name (abfd, sec), name + 5) == 0); @@ -4082,9 +4050,9 @@ m32r_elf_check_relocs (bfd *abfd, static const struct bfd_elf_special_section m32r_elf_special_sections[] = { - { ".sbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, - { ".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, - { NULL, 0, 0, 0, 0 } + { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, + { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, + { NULL, 0, 0, 0, 0 } }; static bfd_boolean @@ -4159,6 +4127,8 @@ m32r_elf_reloc_type_class (const Elf_Internal_Rela *rela) #define elf_backend_create_dynamic_sections m32r_elf_create_dynamic_sections #define bfd_elf32_bfd_link_hash_table_create m32r_elf_link_hash_table_create #define elf_backend_size_dynamic_sections m32r_elf_size_dynamic_sections +#define elf_backend_omit_section_dynsym \ + ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true) #define elf_backend_finish_dynamic_sections m32r_elf_finish_dynamic_sections #define elf_backend_adjust_dynamic_symbol m32r_elf_adjust_dynamic_symbol #define elf_backend_finish_dynamic_symbol m32r_elf_finish_dynamic_symbol |