/* SuperH SH64-specific support for 64-bit ELF
- Copyright 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright 2000, 2001, 2002, 2003, 2004, 2005, 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. */
#define SH64_ELF64
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
return NULL;
}
+static reloc_howto_type *
+sh_elf64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < sizeof (sh_elf64_howto_table) / sizeof (sh_elf64_howto_table[0]);
+ i++)
+ if (sh_elf64_howto_table[i].name != NULL
+ && strcasecmp (sh_elf64_howto_table[i].name, r_name) == 0)
+ return &sh_elf64_howto_table[i];
+
+ return NULL;
+}
+
/* Given an ELF reloc, fill in the howto field of a relent.
See sh_elf_info_to_howto in elf32-sh.c for the original. */
howto = sh_elf64_howto_table + r_type;
- /* This is a final link. */
h = NULL;
sym = NULL;
sec = NULL;
+ relocation = 0;
if (r_symndx < symtab_hdr->sh_info)
{
sym = local_syms + r_symndx;
_("Unexpected STO_SH5_ISA32 on local symbol is not handled"),
input_bfd, input_section, rel->r_offset));
- if (info->relocatable)
+ if (sec != NULL && elf_discarded_section (sec))
+ /* Handled below. */
+ ;
+ else 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. */
- sym = local_syms + r_symndx;
if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
goto final_link_relocate;
{
/* ??? Could we use the RELOC_FOR_GLOBAL_SYMBOL macro here ? */
- /* Section symbols are never (?) placed in the hash table, so
- we can just ignore hash relocations when creating a
- relocatable object file. */
- if (info->relocatable)
- 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)
|| (sec->output_section == NULL
&& ((input_section->flags & SEC_DEBUGGING) != 0
&& h->def_dynamic)))
- relocation = 0;
- else if (sec->output_section == NULL)
+ ;
+ else if (sec->output_section != NULL)
+ relocation = ((h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset)
+ /* A STO_SH5_ISA32 causes a "bitor 1" to the
+ symbol value, unless we've seen
+ STT_DATALABEL on the way to it. */
+ | ((h->other & STO_SH5_ISA32) != 0
+ && ! seen_stt_datalabel));
+ else if (!info->relocatable)
{
(*_bfd_error_handler)
(_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
(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)
- /* A STO_SH5_ISA32 causes a "bitor 1" to the
- symbol value, unless we've seen
- STT_DATALABEL on the way to it. */
- | ((h->other & STO_SH5_ISA32) != 0
- && ! seen_stt_datalabel));
}
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
+ ;
+ else if (!info->relocatable)
{
if (! ((*info->callbacks->undefined_symbol)
(info, h->root.root.string, input_bfd,
(info->unresolved_syms_in_objects == RM_GENERATE_ERROR
|| ELF_ST_VISIBILITY (h->other)))))
return FALSE;
- relocation = 0;
}
}
+ 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)
+ continue;
+
disp = (relocation
- input_section->output_section->vma
- input_section->output_offset
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);
}
}
+ /* Copy object attributes. */
+ _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
return sh_elf64_set_private_flags (obfd, elf_elfheader (ibfd)->e_flags);
}
static asection *
sh_elf64_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 (ELF64_R_TYPE (rel->r_info))
- {
- case R_SH_GNU_VTINHERIT:
- case R_SH_GNU_VTENTRY:
- break;
-
- default:
- while (h->root.type == bfd_link_hash_indirect
- && h->root.u.i.link)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
- 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. */
+ switch (ELF64_R_TYPE (rel->r_info))
+ {
+ case R_SH_GNU_VTINHERIT:
+ case R_SH_GNU_VTENTRY:
+ return NULL;
+ }
-static bfd_boolean
-sh_elf64_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
- struct bfd_link_info *info ATTRIBUTE_UNUSED,
- asection *sec ATTRIBUTE_UNUSED,
- const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
-{
- /* No got and plt entries for 64-bit SH at present. */
- return TRUE;
+ return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}
/* Look through the relocs for a section during the first phase.
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);
if (ret == (struct elf_sh64_link_hash_table *) NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
- sh64_elf64_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ sh64_elf64_link_hash_newfunc,
+ sizeof (struct elf_sh64_link_hash_entry)))
{
free (ret);
return NULL;
{
bfd *dynobj;
asection *s;
- unsigned int power_of_two;
dynobj = elf_hash_table (info)->dynobj;
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);
}
/* This function is called via sh_elf_link_hash_traverse if we are
/* Remember whether there is a PLT. */
plt = s->size != 0;
}
- else if (strncmp (name, ".rela", 5) == 0)
+ else if (CONST_STRNEQ (name, ".rela"))
{
if (s->size != 0)
{
s->reloc_count = 0;
}
}
- else if (strncmp (name, ".got", 4) != 0
+ else if (! CONST_STRNEQ (name, ".got")
&& strcmp (name, ".dynbss") != 0)
{
/* It's not one of our sections, so don't allocate space. */
/* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
if (strcmp (h->root.root.string, "_DYNAMIC") == 0
- || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+ || h == elf_hash_table (info)->hgot)
sym->st_shndx = SHN_ABS;
return TRUE;
sh64_elf64_merge_symbol_attribute (struct elf_link_hash_entry *h,
const Elf_Internal_Sym *isym,
bfd_boolean definition,
- bfd_boolean dynamic)
+ bfd_boolean dynamic ATTRIBUTE_UNUSED)
{
- if (isym->st_other != 0 && dynamic)
+ if ((isym->st_other & ~ELF_ST_VISIBILITY (-1)) != 0)
{
unsigned char other;
static const struct bfd_elf_special_section sh64_elf64_special_sections[]=
{
- { ".cranges", 8, 0, SHT_PROGBITS, 0 },
- { NULL, 0, 0, 0, 0 }
+ { STRING_COMMA_LEN (".cranges"), 0, SHT_PROGBITS, 0 },
+ { NULL, 0, 0, 0, 0 }
};
#define TARGET_BIG_SYM bfd_elf64_sh64_vec
#define elf_symbol_leading_char '_'
#define bfd_elf64_bfd_reloc_type_lookup sh_elf64_reloc_type_lookup
+#define bfd_elf64_bfd_reloc_name_lookup \
+ sh_elf64_reloc_name_lookup
#define elf_info_to_howto sh_elf64_info_to_howto
/* Note: there's no relaxation at present. */
#define elf_backend_fake_sections sh64_elf64_fake_sections
#define elf_backend_gc_mark_hook sh_elf64_gc_mark_hook
-#define elf_backend_gc_sweep_hook sh_elf64_gc_sweep_hook
#define elf_backend_check_relocs sh_elf64_check_relocs
#define elf_backend_can_gc_sections 1
sh64_elf64_adjust_dynamic_symbol
#define elf_backend_size_dynamic_sections \
sh64_elf64_size_dynamic_sections
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_finish_dynamic_symbol \
sh64_elf64_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections \
#define TARGET_LITTLE_SYM bfd_elf64_sh64lin_vec
#undef TARGET_LITTLE_NAME
#define TARGET_LITTLE_NAME "elf64-sh64-linux"
+#undef elf64_bed
+#define elf64_bed elf64_sh64_linux_bed
-#define INCLUDED_TARGET_FILE
#include "elf64-target.h"