/* Renesas / SuperH SH specific support for 32-bit ELF
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Ian Lance Taylor, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
/* Do the inverse operation. */
static bfd_vma
-get_plt_offset (const struct elf_sh_plt_info *info, bfd_vma index)
+get_plt_offset (const struct elf_sh_plt_info *info, bfd_vma plt_index)
{
- return info->plt0_entry_size + (index * info->symbol_entry_size);
+ return info->plt0_entry_size + (plt_index * info->symbol_entry_size);
}
/* The sh linker needs to keep track of the number of relocs that it
/* The (unloaded but important) VxWorks .rela.plt.unloaded section. */
asection *srelplt2;
- /* Small local sym to section mapping cache. */
- struct sym_sec_cache sym_sec;
+ /* Small local sym cache. */
+ struct sym_cache sym_cache;
/* A counter or offset to track a TLS got entry. */
union
ret->sdynbss = NULL;
ret->srelbss = NULL;
ret->srelplt2 = NULL;
- ret->sym_sec.abfd = NULL;
+ ret->sym_cache.abfd = NULL;
ret->tls_ldm_got.refcount = 0;
ret->plt_info = NULL;
ret->vxworks_p = vxworks_object_p (abfd);
htab = sh_elf_hash_table (info);
htab->sgot = bfd_get_section_by_name (dynobj, ".got");
htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
- if (! htab->sgot || ! htab->sgotplt)
+ htab->srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ if (! htab->sgot || ! htab->sgotplt || ! htab->srelgot)
abort ();
-
- htab->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 (htab->srelgot == NULL
- || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
- return FALSE;
return TRUE;
}
{
struct elf_sh_link_hash_table *htab;
flagword flags, pltflags;
- register asection *s;
+ asection *s;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
int ptralign = 0;
}
}
+ if (htab->vxworks_p)
+ {
+ struct elf_sh_dyn_relocs **pp;
+
+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+ {
+ if (strcmp (p->sec->output_section->name, ".tls_vars") == 0)
+ *pp = p->next;
+ else
+ pp = &p->next;
+ }
+ }
+
/* Also discard relocs on undefined weak syms with non-default
visibility. */
if (eh->dyn_relocs != NULL
linker script /DISCARD/, so we'll be discarding
the relocs too. */
}
+ else if (htab->vxworks_p
+ && strcmp (p->sec->output_section->name,
+ ".tls_vars") == 0)
+ {
+ /* Relocations in vxworks .tls_vars sections are
+ handled specially by the loader. */
+ }
else if (p->count != 0)
{
srel = elf_section_data (p->sec)->sreloc;
asection *splt;
asection *sreloc;
asection *srelgot;
+ bfd_boolean is_vxworks_tls;
BFD_ASSERT (is_sh_elf (input_bfd));
splt = htab->splt;
sreloc = NULL;
srelgot = NULL;
+ /* We have to handle relocations in vxworks .tls_vars sections
+ specially, because the dynamic loader is 'weird'. */
+ is_vxworks_tls = (htab->vxworks_p && info->shared
+ && !strcmp (input_section->output_section->name,
+ ".tls_vars"));
rel = relocs;
relend = relocs + input_section->reloc_count;
|| h->root.type != bfd_link_hash_undefweak)
&& r_symndx != 0
&& (input_section->flags & SEC_ALLOC) != 0
+ && !is_vxworks_tls
&& (r_type == R_SH_DIR32
|| !SYMBOL_CALLS_LOCAL (info, h)))
{
if (sreloc == NULL)
{
- const char *name;
-
- name = (bfd_elf_string_from_elf_section
- (input_bfd,
- elf_elfheader (input_bfd)->e_shstrndx,
- elf_section_data (input_section)->rel_hdr.sh_name));
- if (name == NULL)
+ sreloc = _bfd_elf_get_dynamic_reloc_section
+ (input_bfd, input_section, /*rela?*/ TRUE);
+ if (sreloc == NULL)
return FALSE;
-
- BFD_ASSERT (CONST_STRNEQ (name, ".rela")
- && strcmp (bfd_get_section_name (input_bfd,
- input_section),
- name + 5) == 0);
-
- sreloc = bfd_get_section_by_name (dynobj, name);
- BFD_ASSERT (sreloc != NULL);
}
skip = FALSE;
}
else
{
- int index;
+ int target;
/* IE->LE transition:
mov.l 1f,r0; stc gbr,rN; mov.l @(r0,r12),rM;
}
BFD_ASSERT ((insn & 0xff00) == 0xd000);
- index = insn & 0x00ff;
+ target = insn & 0x00ff;
insn = bfd_get_16 (input_bfd, contents + offset + 2);
BFD_ASSERT ((insn & 0xf0ff) == 0x0012);
insn = bfd_get_16 (input_bfd, contents + offset + 4);
BFD_ASSERT ((insn & 0xf0ff) == 0x00ce);
- insn = 0xd000 | (insn & 0x0f00) | index;
+ insn = 0xd000 | (insn & 0x0f00) | target;
bfd_put_16 (output_bfd, insn, contents + offset + 0);
bfd_put_16 (output_bfd, 0x0009, contents + offset + 4);
}
if (sreloc == NULL)
{
- const char *name;
-
- name = (bfd_elf_string_from_elf_section
- (input_bfd,
- elf_elfheader (input_bfd)->e_shstrndx,
- elf_section_data (input_section)->rel_hdr.sh_name));
- if (name == NULL)
+ sreloc = _bfd_elf_get_dynamic_reloc_section
+ (input_bfd, input_section, /*rela?*/ TRUE);
+ if (sreloc == NULL)
return FALSE;
-
- BFD_ASSERT (CONST_STRNEQ (name, ".rela")
- && strcmp (bfd_get_section_name (input_bfd,
- input_section),
- name + 5) == 0);
-
- sreloc = bfd_get_section_by_name (dynobj, name);
- BFD_ASSERT (sreloc != NULL);
}
if (h == NULL || h->dynindx == -1)
section in dynobj and make room for this reloc. */
if (sreloc == NULL)
{
- const char *name;
-
- name = (bfd_elf_string_from_elf_section
- (abfd,
- elf_elfheader (abfd)->e_shstrndx,
- elf_section_data (sec)->rel_hdr.sh_name));
- if (name == NULL)
- return FALSE;
-
- BFD_ASSERT (CONST_STRNEQ (name, ".rela")
- && strcmp (bfd_get_section_name (abfd, sec),
- name + 5) == 0);
+ sreloc = _bfd_elf_make_dynamic_reloc_section
+ (sec, htab->root.dynobj, 2, abfd, /*rela?*/ TRUE);
- sreloc = bfd_get_section_by_name (htab->root.dynobj, name);
if (sreloc == NULL)
- {
- flagword flags;
-
- 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 (htab->root.dynobj,
- name,
- flags);
- if (sreloc == NULL
- || ! bfd_set_section_alignment (htab->root.dynobj,
- sreloc, 2))
- return FALSE;
- }
- elf_section_data (sec)->sreloc = sreloc;
+ return FALSE;
}
/* If this is a global symbol, we count the number of
head = &((struct elf_sh_link_hash_entry *) h)->dyn_relocs;
else
{
+ /* Track dynamic relocs needed for local syms too. */
asection *s;
void *vpp;
+ Elf_Internal_Sym *isym;
- /* Track dynamic relocs needed for local syms too. */
- s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
- sec, r_symndx);
- if (s == NULL)
+ isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+ abfd, r_symndx);
+ if (isym == NULL)
return FALSE;
+ s = bfd_section_from_elf_index (abfd, isym->st_shndx);
+ if (s == NULL)
+ s = sec;
+
vpp = &elf_section_data (s)->local_dynrel;
head = (struct elf_sh_dyn_relocs **) vpp;
}