/* 32-bit ELF support for Nios II.
- Copyright (C) 2012-2017 Free Software Foundation, Inc.
+ Copyright (C) 2012-2019 Free Software Foundation, Inc.
Contributed by Nigel Gray (ngray@altera.com).
Contributed by Mentor Graphics, Inc.
#include "elf/nios2.h"
#include "opcode/nios2.h"
#include "elf32-nios2.h"
+#include "libiberty.h"
/* Use RELA relocations. */
#ifndef USE_RELA
TRUE,
6,
complain_overflow_signed,
- bfd_elf_generic_reloc, /* FIXME? */
+ bfd_elf_generic_reloc, /* FIXME? */
"R_NIOS2_R2_I10_1_PCREL",
FALSE,
0xffc0,
int i;
/* R2 relocations are a superset of R1, so use that for the lookup
table. */
- int r1_howto_tbl_size = (int) (sizeof (elf_nios2_r1_howto_table_rel)
- / sizeof (elf_nios2_r1_howto_table_rel[0]));
- int r2_howto_tbl_size = (int) (sizeof (elf_nios2_r2_howto_table_rel)
- / sizeof (elf_nios2_r2_howto_table_rel[0]));
+ int r1_howto_tbl_size = (int) ARRAY_SIZE (elf_nios2_r1_howto_table_rel);
+ int r2_howto_tbl_size = (int) ARRAY_SIZE (elf_nios2_r2_howto_table_rel);
if (!initialized)
{
}
}
- BFD_ASSERT (rtype <= R_NIOS2_ILLEGAL);
+ if (rtype > R_NIOS2_ILLEGAL)
+ return NULL;
i = elf_code_to_howto_index[rtype];
if (BFD_IS_R2 (abfd))
{
if (i >= r2_howto_tbl_size)
- return 0;
+ return NULL;
return elf_nios2_r2_howto_table_rel + i;
}
else
{
if (i >= r1_howto_tbl_size)
- return 0;
+ return NULL;
return elf_nios2_r1_howto_table_rel + i;
}
}
enum elf_nios2_reloc_type elf_val;
};
-static const struct elf_reloc_map nios2_reloc_map[] = {
+static const struct elf_reloc_map nios2_reloc_map[] =
+{
{BFD_RELOC_NONE, R_NIOS2_NONE},
{BFD_RELOC_NIOS2_S16, R_NIOS2_S16},
{BFD_RELOC_NIOS2_U16, R_NIOS2_U16},
bfd_hash_lookup ((table), (string), (create), (copy)))
-/* The Nios II linker needs to keep track of the number of relocs that it
- decides to copy as dynamic relocs in check_relocs for each symbol.
- This is so that it can later discard them if they are found to be
- unnecessary. We store the information in a field extending the
- regular ELF linker hash table. */
-
-struct elf32_nios2_dyn_relocs
-{
- struct elf32_nios2_dyn_relocs *next;
-
- /* The input section of the reloc. */
- asection *sec;
-
- /* Total number of relocs copied for the input section. */
- bfd_size_type count;
-
- /* Number of pc-relative relocs copied for the input section. */
- bfd_size_type pc_count;
-};
-
/* Nios II ELF linker hash entry. */
struct elf32_nios2_link_hash_entry
struct elf32_nios2_stub_hash_entry *hsh_cache;
/* Track dynamic relocs copied for this symbol. */
- struct elf32_nios2_dyn_relocs *dyn_relocs;
+ struct elf_dyn_relocs *dyn_relocs;
#define GOT_UNKNOWN 0
#define GOT_NORMAL 1
if (hsh == NULL)
{
/* xgettext:c-format */
- _bfd_error_handler (_("%B: cannot create stub entry %s"),
+ _bfd_error_handler (_("%pB: cannot create stub entry %s"),
section->owner,
stub_name);
return NULL;
if (bfd_big_endian (ibfd))
{
_bfd_error_handler
- (_("error: %B: Big-endian R2 is not supported."), ibfd);
+ (_("error: %pB: big-endian R2 is not supported"), ibfd);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
architectures. */
_bfd_error_handler
/* xgettext:c-format */
- (_("error: %B: Conflicting CPU architectures %d/%d"),
+ (_("error: %pB: conflicting CPU architectures %d/%d"),
ibfd, new_flags, old_flags);
bfd_set_error (bfd_error_bad_value);
return FALSE;
return TRUE;
}
-
/* Implement bfd_elf32_bfd_reloc_type_lookup:
Given a BFD reloc type, return a howto structure. */
+
static reloc_howto_type *
nios2_elf32_bfd_reloc_type_lookup (bfd *abfd,
bfd_reloc_code_real_type code)
{
int i;
- for (i = 0;
- i < (int) (sizeof (nios2_reloc_map) / sizeof (struct elf_reloc_map));
- ++i)
+ for (i = 0; i < (int) ARRAY_SIZE (nios2_reloc_map); ++i)
if (nios2_reloc_map[i].bfd_val == code)
return lookup_howto (nios2_reloc_map[i].elf_val, abfd);
return NULL;
/* Implement bfd_elf32_bfd_reloc_name_lookup:
Given a reloc name, return a howto structure. */
+
static reloc_howto_type *
nios2_elf32_bfd_reloc_name_lookup (bfd *abfd,
const char *r_name)
if (BFD_IS_R2 (abfd))
{
howto_tbl = elf_nios2_r2_howto_table_rel;
- howto_tbl_size = (int) (sizeof (elf_nios2_r2_howto_table_rel)
- / sizeof (elf_nios2_r2_howto_table_rel[0]));
+ howto_tbl_size = (int) ARRAY_SIZE (elf_nios2_r2_howto_table_rel);
}
else
{
howto_tbl = elf_nios2_r1_howto_table_rel;
- howto_tbl_size = (int) (sizeof (elf_nios2_r1_howto_table_rel)
- / sizeof (elf_nios2_r1_howto_table_rel[0]));
+ howto_tbl_size = (int) ARRAY_SIZE (elf_nios2_r1_howto_table_rel);
}
for (i = 0; i < howto_tbl_size; i++)
if (howto_tbl[i].name && strcasecmp (howto_tbl[i].name, r_name) == 0)
return howto_tbl + i;
+
return NULL;
}
/* Implement elf_info_to_howto:
Given a ELF32 relocation, fill in a arelent structure. */
-static void
+
+static bfd_boolean
nios2_elf32_info_to_howto (bfd *abfd, arelent *cache_ptr,
Elf_Internal_Rela *dst)
{
unsigned int r_type;
r_type = ELF32_R_TYPE (dst->r_info);
- cache_ptr->howto = lookup_howto (r_type, abfd);
+ if ((cache_ptr->howto = lookup_howto (r_type, abfd)) == NULL)
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+ abfd, r_type);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ return TRUE;
}
/* Return the base VMA address which should be subtracted from real addresses
const char *name = NULL;
int r_type;
const char *format;
- char msgbuf[256];
- const char* msg = (const char*) NULL;
+ char *msgbuf = NULL;
+ char *msg = NULL;
bfd_boolean unresolved_reloc;
bfd_vma off;
int use_plt;
if (howto)
{
+ bfd_boolean resolved_to_zero;
+
+ resolved_to_zero = (h != NULL
+ && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
switch (howto->type)
{
case R_NIOS2_HI16:
reloc_address = 0;
format = _("global pointer relative relocation at address "
- "0x%08x when _gp not defined\n");
- sprintf (msgbuf, format, reloc_address);
+ "%#" PRIx64 " when _gp not defined\n");
+ if (asprintf (&msgbuf, format,
+ (uint64_t) reloc_address) == -1)
+ msgbuf = NULL;
msg = msgbuf;
r = bfd_reloc_dangerous;
}
{
if (h)
name = h->root.root.string;
+ else
+ {
+ name = (bfd_elf_string_from_elf_section
+ (input_bfd, symtab_hdr->sh_link,
+ sym->st_name));
+ if (name == NULL || *name == '\0')
+ name = bfd_section_name (sec);
+ }
/* xgettext:c-format */
- format = _("Unable to reach %s (at 0x%08x) from the "
- "global pointer (at 0x%08x) because the "
- "offset (%d) is out of the allowed range, "
- "-32678 to 32767.\n" );
- sprintf (msgbuf, format, name, symbol_address, gp,
- (signed)relocation);
+ format = _("unable to reach %s (at %#" PRIx64 ") from "
+ "the global pointer (at %#" PRIx64 ") "
+ "because the offset (%" PRId64 ") is out of "
+ "the allowed range, -32678 to 32767\n" );
+ if (asprintf (&msgbuf, format, name,
+ (uint64_t) symbol_address, (uint64_t) gp,
+ (int64_t) relocation) == -1)
+ msgbuf = NULL;
msg = msgbuf;
r = bfd_reloc_outofrange;
}
h)
|| (bfd_link_pic (info)
&& SYMBOL_REFERENCES_LOCAL (info, h))
- || (ELF_ST_VISIBILITY (h->other)
+ || ((ELF_ST_VISIBILITY (h->other)
+ || resolved_to_zero)
&& h->root.type == bfd_link_hash_undefweak))
{
/* This is actually a static link, or it is a -Bsymbolic
if ((bfd_link_pic (info) || indx != 0)
&& (h == NULL
- || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ && !resolved_to_zero)
|| h->root.type != bfd_link_hash_undefweak))
{
need_relocs = TRUE;
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B(%A+0x%lx): R_NIOS2_TLS_LE16 relocation not "
+ (_("%pB(%pA+%#" PRIx64 "): %s relocation not "
"permitted in shared object"),
input_bfd, input_section,
- (long) rel->r_offset, howto->name);
+ (uint64_t) rel->r_offset, howto->name);
return FALSE;
}
else
if (bfd_link_pic (info)
&& (input_section->flags & SEC_ALLOC) != 0
&& (h == NULL
- || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ && !resolved_to_zero)
|| h->root.type != bfd_link_hash_undefweak))
{
Elf_Internal_Rela outrel;
symtab_hdr->sh_link,
sym->st_name);
if (name == NULL || *name == '\0')
- name = bfd_section_name (input_bfd, sec);
+ name = bfd_section_name (sec);
}
switch (r)
{
(*info->callbacks->warning) (info, msg, name, input_bfd,
input_section, rel->r_offset);
+ if (msgbuf)
+ free (msgbuf);
return FALSE;
}
}
nios2_elf32_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
Elf_Internal_Shdr *hdr, asection *sec)
{
- register const char *name = bfd_get_section_name (abfd, sec);
+ const char *name = bfd_section_name (sec);
if ((sec->flags & SEC_SMALL_DATA)
|| strcmp (name, ".sdata") == 0
/* In order for the two loads in .PLTresolve to share the same %hiadj,
_GLOBAL_OFFSET_TABLE_ must be aligned to a 16-byte boundary. */
- if (!bfd_set_section_alignment (dynobj, htab->root.sgotplt, 4))
+ if (!bfd_set_section_alignment (htab->root.sgotplt, 4))
return FALSE;
/* The Nios II ABI specifies that GOT-relative relocations are relative
same %hiadj, the start of the PLT (as well as the GOT) must be aligned
to a 16-byte boundary. This is because the addresses for these loads
include the -(.plt+4) PIC correction. */
- return bfd_set_section_alignment (dynobj, htab->root.splt, 4);
+ return bfd_set_section_alignment (htab->root.splt, 4);
}
/* Implement elf_backend_copy_indirect_symbol:
{
if (edir->dyn_relocs != NULL)
{
- struct elf32_nios2_dyn_relocs **pp;
- struct elf32_nios2_dyn_relocs *p;
+ struct elf_dyn_relocs **pp;
+ struct elf_dyn_relocs *p;
/* Add reloc counts against the indirect sym to the direct sym
list. Merge any entries against the same section. */
for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
{
- struct elf32_nios2_dyn_relocs *q;
+ struct elf_dyn_relocs *q;
for (q = edir->dyn_relocs; q != NULL; q = q->next)
if (q->sec == p->sec)
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;
-
- /* PR15323, ref flags aren't set for references in the same
- object. */
- h->root.non_ir_ref_regular = 1;
}
r_type = ELF32_R_TYPE (rel->r_info);
|| (h != NULL && ! h->needs_plt
&& (! SYMBOLIC_BIND (info, h) || ! h->def_regular))))
{
- struct elf32_nios2_dyn_relocs *p;
- struct elf32_nios2_dyn_relocs **head;
+ struct elf_dyn_relocs *p;
+ struct elf_dyn_relocs **head;
/* When creating a shared object, we must copy these
reloc types into the output file. We create a reloc
s = sec;
vpp = &elf_section_data (s)->local_dynrel;
- head = (struct elf32_nios2_dyn_relocs **) vpp;
+ head = (struct elf_dyn_relocs **) vpp;
}
p = *head;
if (p == NULL || p->sec != sec)
{
bfd_size_type amt = sizeof *p;
- p = ((struct elf32_nios2_dyn_relocs *)
+ p = ((struct elf_dyn_relocs *)
bfd_alloc (htab->root.dynobj, amt));
if (p == NULL)
return FALSE;
return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}
-/* Implement elf_backend_gc_sweep_hook:
- Update the got entry reference counts for the section being removed. */
-static bfd_boolean
-nios2_elf32_gc_sweep_hook (bfd *abfd,
- struct bfd_link_info *info,
- asection *sec,
- const Elf_Internal_Rela *relocs)
-{
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- bfd_signed_vma *local_got_refcounts;
- const Elf_Internal_Rela *rel, *relend;
- bfd *dynobj;
-
- if (bfd_link_relocatable (info))
- return TRUE;
-
- elf_section_data (sec)->local_dynrel = NULL;
-
- dynobj = elf_hash_table (info)->dynobj;
- if (dynobj == NULL)
- return TRUE;
-
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (abfd);
- local_got_refcounts = elf_local_got_refcounts (abfd);
-
- relend = relocs + sec->reloc_count;
- for (rel = relocs; rel < relend; rel++)
- {
- unsigned long r_symndx;
- struct elf_link_hash_entry *h = NULL;
- int r_type;
-
- r_symndx = ELF32_R_SYM (rel->r_info);
- if (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;
- }
-
- r_type = ELF32_R_TYPE (rel->r_info);
- switch (r_type)
- {
- case R_NIOS2_GOT16:
- case R_NIOS2_GOT_LO:
- case R_NIOS2_GOT_HA:
- case R_NIOS2_CALL16:
- case R_NIOS2_CALL_LO:
- case R_NIOS2_CALL_HA:
- if (h != NULL)
- {
- if (h->got.refcount > 0)
- --h->got.refcount;
- }
- else if (local_got_refcounts != NULL)
- {
- if (local_got_refcounts[r_symndx] > 0)
- --local_got_refcounts[r_symndx];
- }
- break;
-
- case R_NIOS2_PCREL_LO:
- case R_NIOS2_PCREL_HA:
- case R_NIOS2_BFD_RELOC_32:
- case R_NIOS2_CALL26:
- case R_NIOS2_CALL26_NOAT:
- if (h != NULL)
- {
- struct elf32_nios2_link_hash_entry *eh;
- struct elf32_nios2_dyn_relocs **pp;
- struct elf32_nios2_dyn_relocs *p;
-
- eh = (struct elf32_nios2_link_hash_entry *) h;
-
- if (h->plt.refcount > 0)
- --h->plt.refcount;
-
- if (r_type == R_NIOS2_PCREL_LO || r_type == R_NIOS2_PCREL_HA
- || r_type == R_NIOS2_BFD_RELOC_32)
- {
- for (pp = &eh->dyn_relocs; (p = *pp) != NULL;
- pp = &p->next)
- if (p->sec == sec)
- {
- p->count -= 1;
- if (p->count == 0)
- *pp = p->next;
- break;
- }
- }
- }
- break;
-
- default:
- break;
- }
- }
-
- return TRUE;
-}
-
/* Implement elf_backend_finish_dynamic_symbols:
Finish up dynamic symbol handling. We set the contents of various
dynamic sections here. */
/* Make sure we know what is going on here. */
BFD_ASSERT (dynobj != NULL
&& (h->needs_plt
- || h->u.weakdef != NULL
+ || h->is_weakalias
|| (h->def_dynamic
&& h->ref_regular
&& !h->def_regular)));
/* If this is a weak symbol, and there is a real definition, the
processor independent code will have arranged for us to see the
real definition first, and we can just use the same value. */
- if (h->u.weakdef != NULL)
+ if (h->is_weakalias)
{
- BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
- || h->u.weakdef->root.type == bfd_link_hash_defweak);
- h->root.u.def.section = h->u.weakdef->root.u.def.section;
- h->root.u.def.value = h->u.weakdef->root.u.def.value;
+ struct elf_link_hash_entry *def = weakdef (h);
+ BFD_ASSERT (def->root.type == bfd_link_hash_defined);
+ h->root.u.def.section = def->root.u.def.section;
+ h->root.u.def.value = def->root.u.def.value;
return TRUE;
}
/* Align dynbss. */
s->size = BFD_ALIGN (s->size, (bfd_size_type)1 << align2);
- if (align2 > bfd_get_section_alignment (dynobj, s)
- && !bfd_set_section_alignment (dynobj, s, align2))
+ if (align2 > bfd_section_alignment (s)
+ && !bfd_set_section_alignment (s, align2))
return FALSE;
/* Define the symbol as being at this point in the section. */
struct bfd_link_info *info;
struct elf32_nios2_link_hash_table *htab;
struct elf32_nios2_link_hash_entry *eh;
- struct elf32_nios2_dyn_relocs *p;
+ struct elf_dyn_relocs *p;
int use_plt;
if (h->root.type == bfd_link_hash_indirect)
if (h->def_regular
&& (h->forced_local || SYMBOLIC_BIND (info, h)))
{
- struct elf32_nios2_dyn_relocs **pp;
+ struct elf_dyn_relocs **pp;
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
{
if (eh->dyn_relocs != NULL
&& h->root.type == bfd_link_hash_undefweak)
{
- if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+ if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
eh->dyn_relocs = NULL;
/* Make sure undefined weak symbols are output as a dynamic
for (s = ibfd->sections; s != NULL; s = s->next)
{
- struct elf32_nios2_dyn_relocs *p;
+ struct elf_dyn_relocs *p;
for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
{
/* It's OK to base decisions on the section name, because none
of the dynobj section names depend upon the input files. */
- name = bfd_get_section_name (dynobj, s);
+ name = bfd_section_name (s);
if (CONST_STRNEQ (name, ".rela"))
{
#define elf_backend_check_relocs nios2_elf32_check_relocs
#define elf_backend_gc_mark_hook nios2_elf32_gc_mark_hook
-#define elf_backend_gc_sweep_hook nios2_elf32_gc_sweep_hook
#define elf_backend_create_dynamic_sections \
nios2_elf32_create_dynamic_sections
#define elf_backend_finish_dynamic_symbol nios2_elf32_finish_dynamic_symbol