/* Renesas / SuperH SH specific support for 32-bit ELF
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
+ Free Software Foundation, Inc.
Contributed by Ian Lance Taylor, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
and thus require fixups or relocations. */
bfd_signed_vma abs_funcdesc_refcount;
- enum {
+ enum got_type {
GOT_UNKNOWN = 0, GOT_NORMAL, GOT_TLS_GD, GOT_TLS_IE, GOT_FUNCDESC
} got_type;
};
struct elf_sh_link_hash_table *ret;
bfd_size_type amt = sizeof (struct elf_sh_link_hash_table);
- ret = (struct elf_sh_link_hash_table *) bfd_malloc (amt);
+ ret = (struct elf_sh_link_hash_table *) bfd_zmalloc (amt);
if (ret == (struct elf_sh_link_hash_table *) NULL)
return NULL;
return NULL;
}
- ret->sgot = NULL;
- ret->sgotplt = NULL;
- ret->srelgot = NULL;
- ret->splt = NULL;
- ret->srelplt = NULL;
- ret->sdynbss = NULL;
- ret->srelbss = NULL;
- ret->srelplt2 = NULL;
- ret->sym_cache.abfd = NULL;
- ret->tls_ldm_got.refcount = 0;
- ret->plt_info = NULL;
ret->vxworks_p = vxworks_object_p (abfd);
ret->fdpic_p = fdpic_object_p (abfd);
if (htab == NULL)
return FALSE;
- htab->sgot = bfd_get_section_by_name (dynobj, ".got");
- htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
- htab->srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ htab->sgot = bfd_get_linker_section (dynobj, ".got");
+ htab->sgotplt = bfd_get_linker_section (dynobj, ".got.plt");
+ htab->srelgot = bfd_get_linker_section (dynobj, ".rela.got");
if (! htab->sgot || ! htab->sgotplt || ! htab->srelgot)
abort ();
- htab->sfuncdesc = bfd_make_section_with_flags (dynobj, ".got.funcdesc",
- (SEC_ALLOC | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED));
+ htab->sfuncdesc = bfd_make_section_anyway_with_flags (dynobj, ".got.funcdesc",
+ (SEC_ALLOC | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED));
if (htab->sfuncdesc == NULL
|| ! bfd_set_section_alignment (dynobj, htab->sfuncdesc, 2))
return FALSE;
- htab->srelfuncdesc = bfd_make_section_with_flags (dynobj,
- ".rela.got.funcdesc",
- (SEC_ALLOC | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED
- | SEC_READONLY));
+ htab->srelfuncdesc = bfd_make_section_anyway_with_flags (dynobj,
+ ".rela.got.funcdesc",
+ (SEC_ALLOC | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED
+ | SEC_READONLY));
if (htab->srelfuncdesc == NULL
|| ! bfd_set_section_alignment (dynobj, htab->srelfuncdesc, 2))
return FALSE;
/* Also create .rofixup. */
- htab->srofixup = bfd_make_section_with_flags (dynobj, ".rofixup",
- (SEC_ALLOC | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED
- | SEC_READONLY));
+ htab->srofixup = bfd_make_section_anyway_with_flags (dynobj, ".rofixup",
+ (SEC_ALLOC | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED
+ | SEC_READONLY));
if (htab->srofixup == NULL
|| ! bfd_set_section_alignment (dynobj, htab->srofixup, 2))
return FALSE;
if (bed->plt_readonly)
pltflags |= SEC_READONLY;
- s = bfd_make_section_with_flags (abfd, ".plt", pltflags);
+ s = bfd_make_section_anyway_with_flags (abfd, ".plt", pltflags);
htab->splt = s;
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
return FALSE;
}
- s = bfd_make_section_with_flags (abfd,
- bed->default_use_rela_p ? ".rela.plt" : ".rel.plt",
- flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd,
+ bed->default_use_rela_p
+ ? ".rela.plt" : ".rel.plt",
+ flags | SEC_READONLY);
htab->srelplt = s;
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, ptralign))
&& !create_got_section (abfd, info))
return FALSE;
- {
- const char *secname;
- char *relname;
- flagword secflags;
- asection *sec;
-
- for (sec = abfd->sections; sec; sec = sec->next)
- {
- secflags = bfd_get_section_flags (abfd, sec);
- if ((secflags & (SEC_DATA | SEC_LINKER_CREATED))
- || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS))
- continue;
- secname = bfd_get_section_name (abfd, sec);
- relname = (char *) bfd_malloc ((bfd_size_type) strlen (secname) + 6);
- strcpy (relname, ".rela");
- strcat (relname, secname);
- if (bfd_get_section_by_name (abfd, secname))
- continue;
- s = bfd_make_section_with_flags (abfd, relname,
- flags | SEC_READONLY);
- if (s == NULL
- || ! bfd_set_section_alignment (abfd, s, ptralign))
- return FALSE;
- }
- }
-
if (bed->want_dynbss)
{
/* The .dynbss section is a place to put symbols which are defined
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_with_flags (abfd, ".dynbss",
- SEC_ALLOC | SEC_LINKER_CREATED);
+ s = bfd_make_section_anyway_with_flags (abfd, ".dynbss",
+ SEC_ALLOC | SEC_LINKER_CREATED);
htab->sdynbss = s;
if (s == NULL)
return FALSE;
copy relocs. */
if (! info->shared)
{
- s = bfd_make_section_with_flags (abfd,
- (bed->default_use_rela_p
- ? ".rela.bss" : ".rel.bss"),
- flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd,
+ (bed->default_use_rela_p
+ ? ".rela.bss" : ".rel.bss"),
+ flags | SEC_READONLY);
htab->srelbss = s;
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, ptralign))
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
copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rela.bss section we are going to use. */
- if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
asection *srel;
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
- if (h->root.type == bfd_link_hash_warning)
- /* When warning symbols are created, they **replace** the "real"
- entry in the hash table, thus we never get to see the real
- symbol in a hash traversal. So look at it now. */
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
info = (struct bfd_link_info *) inf;
htab = sh_elf_hash_table (info);
if (htab == NULL)
{
asection *s;
bfd_boolean dyn;
- int got_type = sh_elf_hash_entry (h)->got_type;
+ enum got_type got_type = sh_elf_hash_entry (h)->got_type;
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
&& (got_type == GOT_NORMAL || got_type == GOT_FUNCDESC))
htab->srofixup->size += 4;
}
+ /* No dynamic relocations required when IE->LE conversion happens. */
+ else if (got_type == GOT_TLS_IE && !h->def_dynamic && !info->shared)
+ ;
/* R_SH_TLS_IE_32 needs one dynamic relocation if dynamic,
R_SH_TLS_GD needs one if local symbol and two if global. */
else if ((got_type == GOT_TLS_GD && h->dynindx == -1)
struct elf_sh_link_hash_entry *eh;
struct elf_sh_dyn_relocs *p;
- if (h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
eh = (struct elf_sh_link_hash_entry *) h;
for (p = eh->dyn_relocs; p != NULL; p = p->next)
{
{
sh_elf_hash_table (info)->plt_info = get_plt_info (output_bfd, info->shared);
- if (sh_elf_hash_table (info)->fdpic_p && !info->relocatable)
- {
- struct elf_link_hash_entry *h;
-
- /* Force a PT_GNU_STACK segment to be created. */
- if (! elf_tdata (output_bfd)->stack_flags)
- elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
-
- /* Define __stacksize if it's not defined yet. */
- h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
- FALSE, FALSE, FALSE);
- if (! h || h->root.type != bfd_link_hash_defined
- || h->type != STT_OBJECT
- || !h->def_regular)
- {
- struct bfd_link_hash_entry *bh = NULL;
-
- if (!(_bfd_generic_link_add_one_symbol
- (info, output_bfd, "__stacksize",
- BSF_GLOBAL, bfd_abs_section_ptr, DEFAULT_STACK_SIZE,
- (const char *) NULL, FALSE,
- get_elf_backend_data (output_bfd)->collect, &bh)))
- return FALSE;
-
- h = (struct elf_link_hash_entry *) bh;
- h->def_regular = 1;
- h->type = STT_OBJECT;
- }
- }
- return TRUE;
-}
-
-#if !defined INCLUDE_SHMEDIA && !defined SH_TARGET_ALREADY_DEFINED
-
-static bfd_boolean
-sh_elf_modify_program_headers (bfd *output_bfd, struct bfd_link_info *info)
-{
- struct elf_obj_tdata *tdata = elf_tdata (output_bfd);
- struct elf_segment_map *m;
- Elf_Internal_Phdr *p;
-
- /* objcopy and strip preserve what's already there using
- sh_elf_copy_private_bfd_data (). */
- if (! info)
- return TRUE;
-
- for (p = tdata->phdr, m = tdata->segment_map; m != NULL; m = m->next, p++)
- if (m->p_type == PT_GNU_STACK)
- break;
-
- if (m)
- {
- struct elf_link_hash_entry *h;
-
- /* Obtain the pointer to the __stacksize symbol. */
- h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
- FALSE, FALSE, FALSE);
- if (h)
- {
- 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;
- BFD_ASSERT (h->root.type == bfd_link_hash_defined);
- }
-
- /* Set the header p_memsz from the symbol value. We
- intentionally ignore the symbol section. */
- if (h && h->root.type == bfd_link_hash_defined)
- p->p_memsz = h->root.u.def.value;
- else
- p->p_memsz = DEFAULT_STACK_SIZE;
-
- p->p_align = 8;
- }
-
+ if (sh_elf_hash_table (info)->fdpic_p && !info->relocatable
+ && !bfd_elf_stack_segment_size (output_bfd, info,
+ "__stacksize", DEFAULT_STACK_SIZE))
+ return FALSE;
return TRUE;
}
-#endif
-
/* Set the sizes of the dynamic sections. */
static bfd_boolean
/* Set the contents of the .interp section to the interpreter. */
if (info->executable)
{
- s = bfd_get_section_by_name (dynobj, ".interp");
+ s = bfd_get_linker_section (dynobj, ".interp");
BFD_ASSERT (s != NULL);
s->size = sizeof ELF_DYNAMIC_INTERPRETER;
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
static unsigned
sh_elf_osec_to_segment (bfd *output_bfd, asection *osec)
{
- Elf_Internal_Phdr *p = _bfd_elf_find_segment_containing_section (output_bfd,
- osec);
+ Elf_Internal_Phdr *p = NULL;
+
+ if (output_bfd->xvec->flavour == bfd_target_elf_flavour)
+ p = _bfd_elf_find_segment_containing_section (output_bfd, osec);
/* FIXME: Nothing ever says what this index is relative to. The kernel
supplies data in terms of the number of load segments but this is
{
unsigned seg = sh_elf_osec_to_segment (output_bfd, osec);
- return ! (elf_tdata (output_bfd)->phdr[seg].p_flags & PF_W);
+ return (seg != (unsigned) -1
+ && ! (elf_tdata (output_bfd)->phdr[seg].p_flags & PF_W));
}
/* Generate the initial contents of a local function descriptor, along
bfd_reloc_status_type r;
int seen_stt_datalabel = 0;
bfd_vma off;
- int got_type;
+ enum got_type got_type;
const char *symname = NULL;
r_symndx = ELF32_R_SYM (rel->r_info);
_("Unexpected STO_SH5_ISA32 on local symbol is not handled"),
input_bfd, input_section, rel->r_offset));
- if (sec != NULL && elf_discarded_section (sec))
+ if (sec != NULL && discarded_section (sec))
/* Handled below. */
;
else if (info->relocatable)
STT_DATALABEL on the way to it. */
| ((h->other & STO_SH5_ISA32) != 0
&& ! seen_stt_datalabel));
- else if (!info->relocatable)
+ else if (!info->relocatable
+ && (_bfd_elf_section_offset (output_bfd, info,
+ input_section,
+ rel->r_offset)
+ != (bfd_vma) -1))
{
(*_bfd_error_handler)
(_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
}
}
- 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 (sec != NULL && discarded_section (sec))
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, 1, relend, howto, 0, contents);
if (info->relocatable)
continue;
((*_bfd_error_handler)
(_("%B: 0x%lx: fatal: unaligned %s relocation 0x%lx"),
input_section->owner,
- (unsigned long) rel->r_offset, howto->name,
+ (unsigned long) rel->r_offset, howto->name,
(unsigned long) relocation));
bfd_set_error (bfd_error_bad_value);
return FALSE;
((*_bfd_error_handler)
(_("%B: 0x%lx: fatal: unaligned %s relocation 0x%lx"),
input_section->owner,
- (unsigned long) rel->r_offset, howto->name,
+ (unsigned long) rel->r_offset, howto->name,
(unsigned long) relocation));
bfd_set_error (bfd_error_bad_value);
return FALSE;
check_segment[0] = check_segment[1] = -1;
}
+ /* We don't want warnings for non-NULL tests on undefined weak
+ symbols. */
+ else if (r_type == R_SH_REL32
+ && h
+ && h->root.type == bfd_link_hash_undefweak)
+ check_segment[0] = check_segment[1] = -1;
goto final_link_relocate;
case R_SH_GOTPLT32:
if (srelgot == NULL)
{
- srelgot = bfd_get_section_by_name (dynobj,
- ".rela.got");
+ srelgot = bfd_get_linker_section (dynobj,
+ ".rela.got");
BFD_ASSERT (srelgot != NULL);
}
if (srelgot == NULL)
{
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ srelgot = bfd_get_linker_section (dynobj, ".rela.got");
BFD_ASSERT (srelgot != NULL);
}
if (srelgot == NULL)
{
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ srelgot = bfd_get_linker_section (dynobj, ".rela.got");
BFD_ASSERT (srelgot != NULL);
}
check_segment[0] = check_segment[1] = -1;
- if (! info->shared)
+ if (! info->shared || info->pie)
{
relocation = tpoff (info, relocation);
addend = rel->r_addend;
eind->datalabel_got.refcount = 0;
#endif
edir->funcdesc.refcount += eind->funcdesc.refcount;
- eind->funcdesc.refcount = 0;
+ eind->funcdesc.refcount = 0;
edir->abs_funcdesc_refcount += eind->abs_funcdesc_refcount;
- eind->abs_funcdesc_refcount = 0;
+ eind->abs_funcdesc_refcount = 0;
if (ind->root.type == bfd_link_hash_indirect
&& dir->got.refcount <= 0)
const Elf_Internal_Rela *rel_end;
asection *sreloc;
unsigned int r_type;
- int got_type, old_got_type;
+ enum got_type got_type, old_got_type;
sreloc = NULL;
#endif
h = (struct elf_link_hash_entry *) h->root.u.i.link;
}
+
+ /* PR15323, ref flags aren't set for references in the same
+ object. */
+ h->root.non_ir_ref = 1;
}
r_type = sh_elf_optimized_tls_reloc (info, r_type, h == NULL);
break;
case R_SH_TLS_LE_32:
- if (info->shared)
+ if (info->shared && !info->pie)
{
(*_bfd_error_handler)
(_("%B: TLS local exec code cannot be linked into shared objects"),
if (sh_ef_bfd_table[flags] == 0)
return FALSE;
-
+
bfd_default_set_arch_mach (abfd, bfd_arch_sh, sh_ef_bfd_table[flags]);
return TRUE;
sh_elf_get_flags_from_mach (unsigned long mach)
{
int i = ARRAY_SIZE (sh_ef_bfd_table) - 1;
-
+
for (; i>0; i--)
if (sh_ef_bfd_table[i] == mach)
return i;
-
+
/* shouldn't get here */
BFD_FAIL();
if (! is_sh_elf (ibfd) || ! is_sh_elf (obfd))
return TRUE;
- /* Copy the stack size. */
- if (elf_tdata (ibfd)->phdr && elf_tdata (obfd)->phdr
- && fdpic_object_p (ibfd) && fdpic_object_p (obfd))
- {
- unsigned i;
-
- for (i = 0; i < elf_elfheader (ibfd)->e_phnum; i++)
- if (elf_tdata (ibfd)->phdr[i].p_type == PT_GNU_STACK)
- {
- Elf_Internal_Phdr *iphdr = &elf_tdata (ibfd)->phdr[i];
-
- for (i = 0; i < elf_elfheader (obfd)->e_phnum; i++)
- if (elf_tdata (obfd)->phdr[i].p_type == PT_GNU_STACK)
- {
- memcpy (&elf_tdata (obfd)->phdr[i], iphdr, sizeof (*iphdr));
-
- /* Rewrite the phdrs, since we're only called after they
- were first written. */
- if (bfd_seek (obfd,
- (bfd_signed_vma) get_elf_backend_data (obfd)
- ->s->sizeof_ehdr, SEEK_SET) != 0
- || get_elf_backend_data (obfd)->s
- ->write_out_phdrs (obfd, elf_tdata (obfd)->phdr,
- elf_elfheader (obfd)->e_phnum) != 0)
- return FALSE;
- break;
- }
-
- break;
- }
- }
-
return sh_elf_set_private_flags (obfd, elf_elfheader (ibfd)->e_flags);
}
#endif /* not sh_elf_copy_private_data */
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak));
- s = bfd_get_section_by_name (h->root.u.def.section->owner,
- ".rela.bss");
+ s = bfd_get_linker_section (htab->root.dynobj, ".rela.bss");
BFD_ASSERT (s != NULL);
rel.r_offset = (h->root.u.def.value
/* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. On VxWorks,
_GLOBAL_OFFSET_TABLE_ is not absolute: it is relative to the
".got" section. */
- if (strcmp (h->root.root.string, "_DYNAMIC") == 0
+ if (h == htab->root.hdynamic
|| (!htab->vxworks_p && h == htab->root.hgot))
sym->st_shndx = SHN_ABS;
return FALSE;
sgotplt = htab->sgotplt;
- sdyn = bfd_get_section_by_name (htab->root.dynobj, ".dynamic");
+ sdyn = bfd_get_linker_section (htab->root.dynobj, ".dynamic");
if (htab->root.dynamic_sections_created)
{
if (sgotplt && sgotplt->size > 0)
elf_section_data (sgotplt->output_section)->this_hdr.sh_entsize = 4;
-
+
/* At the very end of the .rofixup section is a pointer to the GOT. */
if (htab->fdpic_p && htab->srofixup != NULL)
{
}
static enum elf_reloc_type_class
-sh_elf_reloc_type_class (const Elf_Internal_Rela *rela)
+sh_elf_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ const asection *rel_sec ATTRIBUTE_UNUSED,
+ const Elf_Internal_Rela *rela)
{
switch ((int) ELF32_R_TYPE (rela->r_info))
{
case 168: /* Linux/SH */
/* pr_cursig */
- elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+ elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12);
/* pr_pid */
- elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24);
+ elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 24);
/* pr_reg */
offset = 72;
return FALSE;
case 124: /* Linux/SH elf_prpsinfo */
- elf_tdata (abfd)->core_program
+ elf_tdata (abfd)->core->program
= _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
- elf_tdata (abfd)->core_command
+ elf_tdata (abfd)->core->command
= _bfd_elfcore_strndup (abfd, note->descdata + 44, 80);
}
implementations, so strip it off if it exists. */
{
- char *command = elf_tdata (abfd)->core_command;
+ char *command = elf_tdata (abfd)->core->command;
int n = strlen (command);
if (0 < n && command[n - 1] == ' ')
}
#endif /* not SH_TARGET_ALREADY_DEFINED */
-
+
/* Return address for Ith PLT stub in section PLT, for relocation REL
or (bfd_vma) -1 if it should not be included. */
#define elf_backend_encode_eh_address \
sh_elf_encode_eh_address
+#define elf_backend_stack_align 8
#define elf_backend_can_gc_sections 1
#define elf_backend_can_refcount 1
#define elf_backend_want_got_plt 1
#define TARGET_LITTLE_SYM bfd_elf32_shfd_vec
#undef TARGET_LITTLE_NAME
#define TARGET_LITTLE_NAME "elf32-sh-fdpic"
-#undef elf_backend_modify_program_headers
-#define elf_backend_modify_program_headers \
- sh_elf_modify_program_headers
#undef elf32_bed
#define elf32_bed elf32_sh_fd_bed