/* 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.
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
+ 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,
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. */
+ 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"
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
if (ret == NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
- m32r_elf_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ m32r_elf_link_hash_newfunc,
+ sizeof (struct elf_m32r_link_hash_entry)))
{
free (ret);
return NULL;
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");
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
/* 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;
`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;
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. */
}
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)
{
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);
/* Mark some specially defined symbols as absolute. */
if (strcmp (h->root.root.string, "_DYNAMIC") == 0
- || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+ || h == htab->root.hgot)
sym->st_shndx = SHN_ABS;
return TRUE;
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
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);
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
#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