/* SuperH SH64-specific support for 64-bit ELF
- Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
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. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
#define SH64_ELF64
#define sh64_elf64_hash_table(p) \
((struct elf_sh64_link_hash_table *) ((p)->hash))
-static bfd_boolean sh_elf64_copy_private_data
- (bfd *, bfd *);
-static bfd_boolean sh_elf64_copy_private_data_internal
- (bfd *, bfd *);
-static bfd_boolean sh_elf64_merge_private_data
- (bfd *, bfd *);
static bfd_reloc_status_type sh_elf64_ignore_reloc
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
static bfd_reloc_status_type sh_elf64_reloc
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
-static reloc_howto_type *sh_elf64_reloc_type_lookup
- (bfd *, bfd_reloc_code_real_type);
-static void sh_elf64_info_to_howto
- (bfd *, arelent *, Elf_Internal_Rela *);
-static bfd_boolean sh_elf64_relocate_section
- (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
- Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
-static bfd_byte *sh_elf64_get_relocated_section_contents
- (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *,
- bfd_boolean, asymbol **);
-static bfd_boolean sh_elf64_set_mach_from_flags
- (bfd *);
-static bfd_boolean sh_elf64_set_private_flags
- (bfd *, flagword);
-static asection *sh_elf64_gc_mark_hook
- (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
- struct elf_link_hash_entry *, Elf_Internal_Sym *);
-static bfd_boolean sh_elf64_gc_sweep_hook
- (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
-static bfd_boolean sh_elf64_check_relocs
- (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
-static int sh64_elf64_get_symbol_type
- (Elf_Internal_Sym *, int);
-static bfd_boolean sh64_elf64_add_symbol_hook
- (bfd *, struct bfd_link_info *, Elf_Internal_Sym *, const char **,
- flagword *, asection **, bfd_vma *);
-static bfd_boolean sh64_elf64_link_output_symbol_hook
- (struct bfd_link_info *, const char *, Elf_Internal_Sym *, asection *,
- struct elf_link_hash_entry *);
-static bfd_boolean sh64_elf64_fake_sections
- (bfd *, Elf_Internal_Shdr *, asection *);
-static void sh64_elf64_final_write_processing
- (bfd *, bfd_boolean);
-static struct bfd_hash_entry *sh64_elf64_link_hash_newfunc
- (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
-static struct bfd_link_hash_table *sh64_elf64_link_hash_table_create
- (bfd *);
-inline static void movi_shori_putval
- (bfd *, unsigned long, char *);
-inline static void movi_3shori_putval
- (bfd *, bfd_vma, char *);
-static bfd_boolean sh64_elf64_create_dynamic_sections
- (bfd *, struct bfd_link_info *);
-static bfd_boolean sh64_elf64_adjust_dynamic_symbol
- (struct bfd_link_info *info, struct elf_link_hash_entry *);
-static bfd_boolean sh64_elf64_discard_copies
- (struct elf_sh64_link_hash_entry *, void *);
-static bfd_boolean sh64_elf64_size_dynamic_sections
- (bfd *, struct bfd_link_info *);
-static bfd_boolean sh64_elf64_finish_dynamic_symbol
- (bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
- Elf_Internal_Sym *);
-static bfd_boolean sh64_elf64_finish_dynamic_sections
- (bfd *, struct bfd_link_info *);
static reloc_howto_type sh_elf64_howto_table[] = {
/* No relocation. */
else if (sec->output_section == NULL)
{
(*_bfd_error_handler)
- (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"),
- bfd_get_filename (input_bfd), h->root.root.string,
- bfd_get_section_name (input_bfd, input_section));
+ (_("%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
const char *name;
if (h != NULL)
- name = h->root.root.string;
+ name = NULL;
else
{
name = (bfd_elf_string_from_elf_section
name = bfd_section_name (input_bfd, sec);
}
if (! ((*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)))
return FALSE;
}
break;
/* Set the SHF_SH5_ISA32 flag for ISA SHmedia code sections. */
-bfd_boolean
+static bfd_boolean
sh64_elf64_fake_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
Elf_Internal_Shdr *elf_section_hdr,
asection *asect)
if (r_symndx < symtab_hdr->sh_info)
h = NULL;
else
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ {
+ 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;
+ }
/* Some relocs require a global offset table. */
if (dynobj == NULL)
srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
if (srelgot == NULL)
{
- srelgot = bfd_make_section (dynobj, ".rela.got");
+ srelgot = bfd_make_section_with_flags (dynobj,
+ ".rela.got",
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED
+ | SEC_READONLY));
if (srelgot == NULL
- || ! bfd_set_section_flags (dynobj, srelgot,
- (SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED
- | SEC_READONLY))
|| ! bfd_set_section_alignment (dynobj, srelgot, 2))
return FALSE;
}
{
flagword flags;
- sreloc = bfd_make_section (dynobj, name);
flags = (SEC_HAS_CONTENTS | SEC_READONLY
| SEC_IN_MEMORY | SEC_LINKER_CREATED);
if ((sec->flags & SEC_ALLOC) != 0)
flags |= SEC_ALLOC | SEC_LOAD;
+ sreloc = bfd_make_section_with_flags (dynobj,
+ name,
+ flags);
if (sreloc == NULL
- || ! bfd_set_section_flags (dynobj, sreloc, flags)
|| ! bfd_set_section_alignment (dynobj, sreloc, 2))
return FALSE;
}
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;
}
inline static void
-movi_shori_putval (bfd *output_bfd, unsigned long value, char *addr)
+movi_shori_putval (bfd *output_bfd, unsigned long value, bfd_byte *addr)
{
bfd_put_32 (output_bfd,
bfd_get_32 (output_bfd, addr)
}
inline static void
-movi_3shori_putval (bfd *output_bfd, bfd_vma value, char *addr)
+movi_3shori_putval (bfd *output_bfd, bfd_vma value, bfd_byte *addr)
{
bfd_put_32 (output_bfd,
bfd_get_32 (output_bfd, addr)
if (bed->plt_readonly)
pltflags |= SEC_READONLY;
- s = bfd_make_section (abfd, ".plt");
+ s = bfd_make_section_with_flags (abfd, ".plt", pltflags);
if (s == NULL
- || ! bfd_set_section_flags (abfd, s, pltflags)
|| ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
return FALSE;
h = (struct elf_link_hash_entry *) bh;
h->def_regular = 1;
h->type = STT_OBJECT;
+ elf_hash_table (info)->hplt = h;
if (info->shared
&& ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
- s = bfd_make_section (abfd,
- bed->default_use_rela_p ? ".rela.plt" : ".rel.plt");
+ s = bfd_make_section_with_flags (abfd,
+ bed->default_use_rela_p ? ".rela.plt" : ".rel.plt",
+ flags | SEC_READONLY);
if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
|| ! bfd_set_section_alignment (abfd, s, ptralign))
return FALSE;
relname = (char *) bfd_malloc (strlen (secname) + 6);
strcpy (relname, ".rela");
strcat (relname, secname);
- s = bfd_make_section (abfd, relname);
+ s = bfd_make_section_with_flags (abfd, relname,
+ flags | SEC_READONLY);
if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
|| ! bfd_set_section_alignment (abfd, s, ptralign))
return FALSE;
}
image and use a R_*_COPY reloc to tell the dynamic linker to
initialize them at run time. The linker script puts the .dynbss
section into the .bss section of the final image. */
- s = bfd_make_section (abfd, ".dynbss");
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, SEC_ALLOC))
+ s = bfd_make_section_with_flags (abfd, ".dynbss",
+ SEC_ALLOC | SEC_LINKER_CREATED);
+ if (s == NULL)
return FALSE;
/* The .rel[a].bss section holds copy relocs. This section is not
copy relocs. */
if (! info->shared)
{
- s = bfd_make_section (abfd,
- (bed->default_use_rela_p
- ? ".rela.bss" : ".rel.bss"));
+ s = bfd_make_section_with_flags (abfd,
+ (bed->default_use_rela_p
+ ? ".rela.bss" : ".rel.bss"),
+ flags | SEC_READONLY);
if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
|| ! bfd_set_section_alignment (abfd, s, ptralign))
return FALSE;
}
if (!h->non_got_ref)
return TRUE;
+ if (h->size == 0)
+ {
+ (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
+ h->root.root.string);
+ return TRUE;
+ }
+
/* We must allocate the symbol in our .dynbss section, which will
become part of the .bss section of the executable. There will be
an entry for this symbol in the .dynsym section. The dynamic
for (s = dynobj->sections; s != NULL; s = s->next)
{
const char *name;
- bfd_boolean strip;
if ((s->flags & SEC_LINKER_CREATED) == 0)
continue;
of the dynobj section names depend upon the input files. */
name = bfd_get_section_name (dynobj, s);
- strip = FALSE;
-
if (strcmp (name, ".plt") == 0)
{
- if (s->size == 0)
- {
- /* Strip this section if we don't need it; see the
- comment below. */
- strip = TRUE;
- }
- else
- {
- /* Remember whether there is a PLT. */
- plt = TRUE;
- }
+ /* Remember whether there is a PLT. */
+ plt = s->size != 0;
}
else if (strncmp (name, ".rela", 5) == 0)
{
- if (s->size == 0)
- {
- /* If we don't need this section, strip it from the
- output file. This is mostly to handle .rela.bss and
- .rela.plt. We must create both sections in
- create_dynamic_sections, because they must be created
- before the linker maps input sections to output
- sections. The linker does that before
- adjust_dynamic_symbol is called, and it is that
- function which decides whether anything needs to go
- into these sections. */
- strip = TRUE;
- }
- else
+ if (s->size != 0)
{
asection *target;
s->reloc_count = 0;
}
}
- else if (strncmp (name, ".got", 4) != 0)
+ else if (strncmp (name, ".got", 4) != 0
+ && strcmp (name, ".dynbss") != 0)
{
/* It's not one of our sections, so don't allocate space. */
continue;
}
- if (strip)
+ if (s->size == 0)
{
- _bfd_strip_section_from_output (info, s);
+ /* If we don't need this section, strip it from the
+ output file. This is mostly to handle .rela.bss and
+ .rela.plt. We must create both sections in
+ create_dynamic_sections, because they must be created
+ before the linker maps input sections to output
+ sections. The linker does that before
+ adjust_dynamic_symbol is called, and it is that
+ function which decides whether anything needs to go
+ into these sections. */
+ s->flags |= SEC_EXCLUDE;
continue;
}
+ if ((s->flags & SEC_HAS_CONTENTS) == 0)
+ continue;
+
/* Allocate memory for the section contents. */
s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
- if (s->contents == NULL && s->size != 0)
+ if (s->contents == NULL)
return FALSE;
}
/* 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;
return;
}
-static struct bfd_elf_special_section const sh64_elf64_special_sections[]=
+static const struct bfd_elf_special_section sh64_elf64_special_sections[]=
{
{ ".cranges", 8, 0, SHT_PROGBITS, 0 },
{ NULL, 0, 0, 0, 0 }