/* Meta support for 32-bit ELF
- Copyright (C) 2013 Free Software Foundation, Inc.
+ Copyright (C) 2013-2015 Free Software Foundation, Inc.
Contributed by Imagination Technologies Ltd.
This file is part of BFD, the Binary File Descriptor library.
/* No relocation. */
HOWTO (R_METAG_NONE, /* type */
0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 3, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
unsigned int r_type;
r_type = ELF32_R_TYPE (dst->r_info);
- BFD_ASSERT (r_type < (unsigned int) R_METAG_MAX);
+ if (r_type >= (unsigned int) R_METAG_MAX)
+ {
+ _bfd_error_handler (_("%B: invalid METAG reloc number: %d"), abfd, r_type);
+ r_type = 0;
+ }
cache_ptr->howto = & elf_metag_howto_table [r_type];
}
return entry;
}
+/* Free the derived linker hash table. */
+
+static void
+elf_metag_link_hash_table_free (bfd *obfd)
+{
+ struct elf_metag_link_hash_table *htab
+ = (struct elf_metag_link_hash_table *) obfd->link.hash;
+
+ bfd_hash_table_free (&htab->bstab);
+ _bfd_elf_link_hash_table_free (obfd);
+}
+
/* Create the derived linker hash table. The Meta ELF port uses the derived
hash table to keep information specific to the Meta ELF linker (without
using static variables). */
struct elf_metag_link_hash_table *htab;
bfd_size_type amt = sizeof (*htab);
- htab = bfd_malloc (amt);
+ htab = bfd_zmalloc (amt);
if (htab == NULL)
return NULL;
/* Init the stub hash table too. */
if (!bfd_hash_table_init (&htab->bstab, stub_hash_newfunc,
sizeof (struct elf_metag_stub_hash_entry)))
- return NULL;
-
- htab->stub_bfd = NULL;
- htab->add_stub_section = NULL;
- htab->layout_sections_again = NULL;
- htab->stub_group = NULL;
- htab->sgot = NULL;
- htab->sgotplt = NULL;
- htab->srelgot = NULL;
- htab->splt = NULL;
- htab->srelplt = NULL;
- htab->sdynbss = NULL;
- htab->srelbss = NULL;
- htab->sym_cache.abfd = NULL;
- htab->tls_ldm_got.refcount = 0;
+ {
+ _bfd_elf_link_hash_table_free (abfd);
+ return NULL;
+ }
+ htab->etab.root.hash_table_free = elf_metag_link_hash_table_free;
return &htab->etab.root;
}
-/* Free the derived linker hash table. */
-
-static void
-elf_metag_link_hash_table_free (struct bfd_link_hash_table *btab)
-{
- struct elf_metag_link_hash_table *htab
- = (struct elf_metag_link_hash_table *) btab;
-
- bfd_hash_table_free (&htab->bstab);
- _bfd_generic_link_hash_table_free (btab);
-}
-
/* Section name for stubs is the associated section name plus this
string. */
#define STUB_SUFFIX ".stub"
else
{
struct elf_link_hash_entry *eh;
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, eh_syms,
eh, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
name = eh->root.root.string;
hh = (struct elf_metag_link_hash_entry *) eh;
if (! _bfd_elf_create_dynamic_sections (abfd, info))
return FALSE;
- htab->sgot = bfd_get_section_by_name (abfd, ".got");
+ htab->sgot = bfd_get_linker_section (abfd, ".got");
if (! htab->sgot)
return FALSE;
elf_hash_table (info)->hgot = eh;
- htab->splt = bfd_get_section_by_name (abfd, ".plt");
- htab->srelplt = bfd_get_section_by_name (abfd, ".rela.plt");
+ htab->splt = bfd_get_linker_section (abfd, ".plt");
+ htab->srelplt = bfd_get_linker_section (abfd, ".rela.plt");
- htab->srelgot = bfd_get_section_by_name (abfd, ".rela.got");
+ htab->srelgot = bfd_get_linker_section (abfd, ".rela.got");
- htab->sdynbss = bfd_get_section_by_name (abfd, ".dynbss");
- htab->srelbss = bfd_get_section_by_name (abfd, ".rela.bss");
+ htab->sdynbss = bfd_get_linker_section (abfd, ".dynbss");
+ htab->srelbss = bfd_get_linker_section (abfd, ".rela.bss");
return TRUE;
}
{
int r_type;
struct elf_metag_link_hash_entry *hh;
+ Elf_Internal_Sym *isym;
unsigned long r_symndx;
r_symndx = ELF32_R_SYM (rel->r_info);
r_type = ELF32_R_TYPE (rel->r_info);
if (r_symndx < symtab_hdr->sh_info)
- hh = NULL;
+ {
+ /* A local symbol. */
+ isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+ abfd, r_symndx);
+ if (isym == NULL)
+ return FALSE;
+
+ hh = NULL;
+ }
else
{
+ isym = NULL;
+
hh = (struct elf_metag_link_hash_entry *)
eh_syms[r_symndx - symtab_hdr->sh_info];
while (hh->eh.root.type == bfd_link_hash_indirect
|| hh->eh.root.type == bfd_link_hash_warning)
hh = (struct elf_metag_link_hash_entry *) hh->eh.root.u.i.link;
+
+ /* PR15323, ref flags aren't set for references in the same
+ object. */
+ hh->eh.root.non_ir_ref = 1;
}
/* Some relocs require a global offset table. */
hh->eh.plt.refcount += 1;
break;
- case R_METAG_ADDR32:
case R_METAG_HIADDR16:
case R_METAG_LOADDR16:
+ /* Let's help debug shared library creation. These relocs
+ cannot be used in shared libs. Don't error out for
+ sections we don't care about, such as debug sections or
+ non-constant sections. */
+ if (info->shared
+ && (sec->flags & SEC_ALLOC) != 0
+ && (sec->flags & SEC_READONLY) != 0)
+ {
+ const char *name;
+
+ if (hh)
+ name = hh->eh.root.root.string;
+ else
+ name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
+ (*_bfd_error_handler)
+ (_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"),
+ abfd, elf_metag_howto_table[r_type].name, name);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
+ /* Fall through. */
+ case R_METAG_ADDR32:
case R_METAG_RELBRANCH:
case R_METAG_GETSETOFF:
if (hh != NULL && !info->shared)
/* Track dynamic relocs needed for local syms too. */
asection *sr;
void *vpp;
- Elf_Internal_Sym *isym;
-
- isym = bfd_sym_from_r_symndx (&htab->sym_cache,
- abfd, r_symndx);
- if (isym == NULL)
- return FALSE;
sr = bfd_section_from_elf_index (abfd, isym->st_shndx);
if (sr == NULL)
return TRUE;
}
- if (eh->size == 0)
- {
- (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
- hh->eh.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
/* We must generate a COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
- if ((eh->root.u.def.section->flags & SEC_ALLOC) != 0)
+ if ((eh->root.u.def.section->flags & SEC_ALLOC) != 0 && eh->size != 0)
{
htab->srelbss->size += sizeof (Elf32_External_Rela);
eh->needs_copy = 1;
s = htab->sdynbss;
- return _bfd_elf_adjust_dynamic_copy (eh, s);
+ return _bfd_elf_adjust_dynamic_copy (info, eh, s);
}
/* Allocate space in .plt, .got and associated reloc sections for
/* 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");
if (s == NULL)
abort ();
s->size = sizeof ELF_DYNAMIC_INTERPRETER;
/* Set up .got offsets for local syms, and space for local dynamic
relocs. */
- for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
{
bfd_signed_vma *local_got;
bfd_signed_vma *end_local_got;
/* Set the Meta ELF ABI version. */
static void
-elf_metag_post_process_headers (bfd * abfd, struct bfd_link_info * link_info ATTRIBUTE_UNUSED)
+elf_metag_post_process_headers (bfd * abfd, struct bfd_link_info * link_info)
{
Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */
+ _bfd_elf_post_process_headers (abfd, link_info);
i_ehdrp = elf_elfheader (abfd);
i_ehdrp->e_ident[EI_ABIVERSION] = METAG_ELF_ABI_VERSION;
}
dynamic linker, before writing them out. */
static enum elf_reloc_type_class
-elf_metag_reloc_type_class (const Elf_Internal_Rela *rela)
+elf_metag_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))
{
htab = metag_link_hash_table (info);
dynobj = htab->etab.dynobj;
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+ sdyn = bfd_get_linker_section (dynobj, ".dynamic");
if (htab->etab.dynamic_sections_created)
{
/* Count the number of input BFDs and find the top input section id. */
for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0;
input_bfd != NULL;
- input_bfd = input_bfd->link_next)
+ input_bfd = input_bfd->link.next)
{
bfd_count += 1;
for (section = input_bfd->sections;
/* Walk over all the input BFDs, swapping in local symbols. */
for (bfd_indx = 0;
input_bfd != NULL;
- input_bfd = input_bfd->link_next, bfd_indx++)
+ input_bfd = input_bfd->link.next, bfd_indx++)
{
Elf_Internal_Shdr *symtab_hdr;
for (input_bfd = info->input_bfds, bfd_indx = 0;
input_bfd != NULL;
- input_bfd = input_bfd->link_next, bfd_indx++)
+ input_bfd = input_bfd->link.next, bfd_indx++)
{
Elf_Internal_Shdr *symtab_hdr;
asection *section;
#define ELF_MAXPAGESIZE 0x4000
#define ELF_COMMONPAGESIZE 0x1000
-#define TARGET_LITTLE_SYM bfd_elf32_metag_vec
+#define TARGET_LITTLE_SYM metag_elf32_vec
#define TARGET_LITTLE_NAME "elf32-metag"
#define elf_symbol_leading_char '_'
#define bfd_elf32_bfd_is_local_label_name elf_metag_is_local_label_name
#define bfd_elf32_bfd_link_hash_table_create \
elf_metag_link_hash_table_create
-#define bfd_elf32_bfd_link_hash_table_free elf_metag_link_hash_table_free
#define elf_backend_relocate_section elf_metag_relocate_section
#define elf_backend_gc_mark_hook elf_metag_gc_mark_hook
#define elf_backend_gc_sweep_hook elf_metag_gc_sweep_hook