/* NDS32-specific support for 32-bit ELF.
- Copyright (C) 2012-2019 Free Software Foundation, Inc.
+ Copyright (C) 2012-2020 Free Software Foundation, Inc.
Contributed by Andes Technology Corporation.
This file is part of BFD, the Binary File Descriptor library.
{
struct elf_link_hash_entry root;
- /* Track dynamic relocs copied for this symbol. */
- struct elf_dyn_relocs *dyn_relocs;
-
/* For checking relocation type. */
enum elf_nds32_tls_type tls_type;
|| ELF_ST_TYPE (sym->st_info) == STT_TLS)
break;
- /* st_value is the alignemnt constraint.
+ /* st_value is the alignment constraint.
That might be its actual size if it is an array or structure. */
switch (sym->st_value)
{
return TRUE;
}
- (*secp)->flags |= SEC_IS_COMMON;
+ (*secp)->flags |= SEC_IS_COMMON | SEC_SMALL_DATA;
*valp = sym->st_size;
break;
}
struct elf_nds32_link_hash_entry *eh;
eh = (struct elf_nds32_link_hash_entry *) ret;
- eh->dyn_relocs = NULL;
eh->tls_type = GOT_UNKNOWN;
eh->offset_to_gp = 0;
}
{
struct elf_nds32_link_hash_table *ret;
- bfd_size_type amt = sizeof (struct elf_nds32_link_hash_table);
+ size_t amt = sizeof (struct elf_nds32_link_hash_table);
ret = (struct elf_nds32_link_hash_table *) bfd_zmalloc (amt);
if (ret == NULL)
return NULL;
}
- ret->sdynbss = NULL;
- ret->srelbss = NULL;
ret->sym_ld_script = NULL;
return &ret->root.root;
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");
- htab->sdynbss = s;
+ htab->root.sdynbss = s;
if (s == NULL
|| !bfd_set_section_flags (s, SEC_ALLOC | SEC_LINKER_CREATED))
return FALSE;
{
s = bfd_make_section (abfd, (bed->default_use_rela_p
? ".rela.bss" : ".rel.bss"));
- htab->srelbss = s;
+ htab->root.srelbss = s;
if (s == NULL
|| !bfd_set_section_flags (s, flags | SEC_READONLY)
|| !bfd_set_section_alignment (s, ptralign))
edir = (struct elf_nds32_link_hash_entry *) dir;
eind = (struct elf_nds32_link_hash_entry *) ind;
- if (eind->dyn_relocs != NULL)
- {
- if (edir->dyn_relocs != NULL)
- {
- struct elf_dyn_relocs **pp;
- struct elf_dyn_relocs *p;
-
- if (ind->root.type == bfd_link_hash_indirect)
- abort ();
-
- /* Add reloc counts against the weak sym to the strong sym
- list. Merge any entries against the same section. */
- for (pp = &eind->dyn_relocs; (p = *pp) != NULL;)
- {
- struct elf_dyn_relocs *q;
-
- for (q = edir->dyn_relocs; q != NULL; q = q->next)
- if (q->sec == p->sec)
- {
- q->pc_count += p->pc_count;
- q->count += p->count;
- *pp = p->next;
- break;
- }
- if (q == NULL)
- pp = &p->next;
- }
- *pp = edir->dyn_relocs;
- }
-
- edir->dyn_relocs = eind->dyn_relocs;
- eind->dyn_relocs = NULL;
- }
-
if (ind->root.type == bfd_link_hash_indirect)
{
if (dir->got.refcount <= 0)
_bfd_elf_link_hash_copy_indirect (info, dir, ind);
}
\f
-
-/* Find dynamic relocs for H that apply to read-only sections. */
-
-static asection *
-readonly_dynrelocs (struct elf_link_hash_entry *h)
-{
- struct elf_dyn_relocs *p;
-
- for (p = elf32_nds32_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
- {
- asection *s = p->sec->output_section;
-
- if (s != NULL && (s->flags & SEC_READONLY) != 0)
- return p->sec;
- }
- return NULL;
-}
-
/* Adjust a symbol defined by a dynamic object and referenced by a
regular object. The current definition is in some section of the
dynamic object, but we're not including those sections. We have to
/* If we don't find any dynamic relocs in read-only sections, then
we'll be keeping the dynamic relocs and avoiding the copy reloc. */
- if (!readonly_dynrelocs (h))
+ if (!_bfd_elf_readonly_dynrelocs (h))
{
h->non_got_ref = 0;
return TRUE;
same memory location for the variable. */
htab = nds32_elf_hash_table (info);
- s = htab->sdynbss;
+ s = htab->root.sdynbss;
BFD_ASSERT (s != NULL);
/* We must generate a R_NDS32_COPY reloc to tell the dynamic linker
{
asection *srel;
- srel = htab->srelbss;
+ srel = htab->root.srelbss;
BFD_ASSERT (srel != NULL);
srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
struct bfd_link_info *info;
struct elf_link_hash_table *ehtab;
struct elf_nds32_link_hash_table *htab;
- struct elf_nds32_link_hash_entry *eh;
struct elf_dyn_relocs *p;
if (h->root.type == bfd_link_hash_indirect)
if (h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
- eh = (struct elf_nds32_link_hash_entry *) h;
-
info = (struct bfd_link_info *) inf;
ehtab = elf_hash_table (info);
htab = nds32_elf_hash_table (info);
if (htab == NULL)
return FALSE;
- eh = (struct elf_nds32_link_hash_entry *) h;
-
if ((htab->root.dynamic_sections_created || h->type == STT_GNU_IFUNC)
&& h->plt.refcount > 0
&& !(bfd_link_pie (info) && h->def_regular))
else
h->got.offset = (bfd_vma)-1;
- if (eh->dyn_relocs == NULL)
+ if (h->dyn_relocs == NULL)
return TRUE;
/* In the shared -Bsymbolic case, discard space allocated for
{
struct elf_dyn_relocs **pp;
- for (pp = &eh->dyn_relocs; (p = *pp) != NULL;)
+ for (pp = &h->dyn_relocs; (p = *pp) != NULL;)
{
p->count -= p->pc_count;
p->pc_count = 0;
goto keep;
}
- eh->dyn_relocs = NULL;
+ h->dyn_relocs = NULL;
-keep:;
+ keep:;
}
/* Finally, allocate space. */
- for (p = eh->dyn_relocs; p != NULL; p = p->next)
+ for (p = h->dyn_relocs; p != NULL; p = p->next)
{
asection *sreloc = elf_section_data (p->sec)->sreloc;
sreloc->size += p->count * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, rel, loc);
}
-/* Set DF_TEXTREL if we find any dynamic relocs that apply to
- read-only sections. */
-
-static bfd_boolean
-maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p)
-{
- asection *sec;
-
- if (h->root.type == bfd_link_hash_indirect)
- return TRUE;
-
- sec = readonly_dynrelocs (h);
- if (sec != NULL)
- {
- struct bfd_link_info *info = (struct bfd_link_info *) info_p;
-
- info->flags |= DF_TEXTREL;
- info->callbacks->minfo
- (_("%pB: dynamic relocation against `%pT' in read-only section `%pA'\n"),
- sec->owner, h->root.root.string, sec);
-
- /* Not an error, just cut short the traversal. */
- return FALSE;
- }
- return TRUE;
-}
-
/* Set the sizes of the dynamic sections. */
static bfd_boolean
bfd *dynobj;
asection *s;
bfd_boolean relocs;
- bfd_boolean plt;
bfd *ibfd;
htab = nds32_elf_hash_table (info);
/* If we're not using lazy TLS relocations, don't generate the
PLT and GOT entries they require. */
- if (!(info->flags & DF_BIND_NOW))
+ if ((info->flags & DF_BIND_NOW))
+ htab->root.tlsdesc_plt = 0;
+ else
{
- htab->dt_tlsdesc_got = htab->root.sgot->size;
+ htab->root.tlsdesc_got = htab->root.sgot->size;
htab->root.sgot->size += 4;
- htab->dt_tlsdesc_plt = htab->root.splt->size;
+ htab->root.tlsdesc_plt = htab->root.splt->size;
htab->root.splt->size += 4 * ARRAY_SIZE (dl_tlsdesc_lazy_trampoline);
}
}
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
memory for them. */
- plt = FALSE;
relocs = FALSE;
for (s = dynobj->sections; s != NULL; s = s->next)
{
{
/* Strip this section if we don't need it; see the
comment below. */
- plt = s->size != 0;
+ ;
}
else if (s == elf_hash_table (info)->sgot)
{
return FALSE;
}
-
- if (htab->root.dynamic_sections_created)
- {
- /* Add some entries to the .dynamic section. We fill in the
- values later, in nds32_elf_finish_dynamic_sections, but we
- must add the entries now so that we get the correct size for
- the .dynamic section. The DT_DEBUG entry is filled in by the
- dynamic linker and used by the debugger. */
-#define add_dynamic_entry(TAG, VAL) \
- _bfd_elf_add_dynamic_entry (info, TAG, VAL)
-
- if (bfd_link_executable (info))
- {
- if (!add_dynamic_entry (DT_DEBUG, 0))
- return FALSE;
- }
-
- if (elf_hash_table (info)->splt->size != 0)
- {
- if (!add_dynamic_entry (DT_PLTGOT, 0)
- || !add_dynamic_entry (DT_PLTRELSZ, 0)
- || !add_dynamic_entry (DT_PLTREL, DT_RELA)
- || !add_dynamic_entry (DT_JMPREL, 0))
- return FALSE;
- }
-
- if (htab->tls_desc_trampoline && plt)
- {
- if (htab->dt_tlsdesc_plt
- && (!add_dynamic_entry (DT_TLSDESC_PLT, 0)
- || !add_dynamic_entry (DT_TLSDESC_GOT, 0)))
- return FALSE;
- }
-
- if (relocs)
- {
- if (!add_dynamic_entry (DT_RELA, 0)
- || !add_dynamic_entry (DT_RELASZ, 0)
- || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
- return FALSE;
-
- /* If any dynamic relocs apply to a read-only section,
- then we need a DT_TEXTREL entry. */
- if ((info->flags & DF_TEXTREL) == 0)
- elf_link_hash_traverse (&htab->root, maybe_set_textrel,
- (void *) info);
-
- if ((info->flags & DF_TEXTREL) != 0)
- {
- if (!add_dynamic_entry (DT_TEXTREL, 0))
- return FALSE;
- }
- }
- }
-#undef add_dynamic_entry
-
- return TRUE;
+ return _bfd_elf_add_dynamic_tags (output_bfd, info, relocs);
}
static bfd_reloc_status_type
if (bfd_is_const_section (input_sec))
source = input_sec->name;
else
- source = input_sec->owner->filename;
+ source = bfd_get_filename (input_sec->owner);
fprintf (sym_ld_script, "\t%s = 0x%08lx;\t /* %s */\n",
h->root.root.string,
if (!rz)
{
- printf ("%s: %s @ 0x%08x\n", __func__, ibfd->filename,
+ printf ("%s: %s @ 0x%08x\n", __func__, bfd_get_filename (ibfd),
(int) rel->r_offset);
BFD_ASSERT(0); /* Unsupported pattern. */
}
case R_NDS32_SDA15S0_RELA:
case R_NDS32_SDA15S0:
align = 0x0;
-handle_sda:
+ handle_sda:
BFD_ASSERT (sec != NULL);
/* If the symbol is in the abs section, the out_bfd will be null.
break;
}
-check_reloc:
+ check_reloc:
if (r != bfd_reloc_ok)
{
errmsg = _("internal error: unknown error");
/* Fall through. */
-common_error:
+ common_error:
(*info->callbacks->warning) (info, errmsg, name, input_bfd,
input_section, offset);
break;
goto get_vma;
case DT_JMPREL:
s = ehtab->srelplt->output_section;
-get_vma:
+ get_vma:
BFD_ASSERT (s != NULL);
dyn.d_un.d_ptr = s->vma;
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
case DT_TLSDESC_PLT:
s = htab->root.splt;
dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset
- + htab->dt_tlsdesc_plt);
+ + htab->root.tlsdesc_plt);
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
case DT_TLSDESC_GOT:
s = htab->root.sgot;
dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset
- + htab->dt_tlsdesc_got);
+ + htab->root.tlsdesc_got);
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
}
PLT_ENTRY_SIZE;
}
- if (htab->dt_tlsdesc_plt)
+ if (htab->root.tlsdesc_plt)
{
/* Calculate addresses. */
asection *sgot = sgot = ehtab->sgot;
bfd_vma pltgot = sgotplt->output_section->vma
+ sgotplt->output_offset;
bfd_vma tlsdesc_got = sgot->output_section->vma + sgot->output_offset
- + htab->dt_tlsdesc_got;
+ + htab->root.tlsdesc_got;
/* Get GP offset. */
pltgot -= elf_gp (output_bfd) - 4; /* PLTGOT[1] */
dl_tlsdesc_lazy_trampoline[5] += 0xfff & pltgot;
/* Insert .plt. */
- nds32_put_trampoline (splt->contents + htab->dt_tlsdesc_plt,
+ nds32_put_trampoline (splt->contents + htab->root.tlsdesc_plt,
dl_tlsdesc_lazy_trampoline,
ARRAY_SIZE (dl_tlsdesc_lazy_trampoline));
}
flagword out_fpu_config;
flagword in_fpu_config;
+ /* FIXME: What should be checked when linking shared libraries? */
+ if ((ibfd->flags & DYNAMIC) != 0)
+ return TRUE;
+
/* TODO: Revise to use object-attributes instead. */
if (!nds32_check_vec_size (ibfd))
return FALSE;
return TRUE;
}
- /* Don't do anything special with non-loaded, non-alloced sections.
- In particular, any relocs in such sections should not affect GOT
- and PLT reference counting (ie. we don't allow them to create GOT
- or PLT entries), there's no possibility or desire to optimize TLS
- relocs, and there's not much point in propagating relocs to shared
- libs that the dynamic linker won't relocate. */
- if ((sec->flags & SEC_ALLOC) == 0)
- return TRUE;
-
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
sym_hashes_end =
/* If this is a global symbol, we count the number of
relocations we need for this symbol. */
if (h != NULL)
- head = &((struct elf_nds32_link_hash_entry *) h)->dyn_relocs;
+ head = &h->dyn_relocs;
else
{
asection *s;
void *vpp;
Elf_Internal_Sym *isym;
- isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, r_symndx);
+ isym = bfd_sym_from_r_symndx (&htab->root.sym_cache,
+ abfd, r_symndx);
if (isym == NULL)
return FALSE;
p = *head;
if (p == NULL || p->sec != sec)
{
- bfd_size_type amt = sizeof (*p);
+ size_t amt = sizeof (*p);
p = (struct elf_dyn_relocs *) bfd_alloc (dynobj, amt);
if (p == NULL)
return FALSE;
goto done;
}
-done:
+ done:
/* Bit-15 of insn16 should be set for a valid instruction. */
if ((insn16 & 0x8000) == 0)
return 0;
goto done;
}
-done:
+ done:
if (insn & 0x80000000)
return 0;
if (p < endp)
*p |= 0x80;
}
-done_adjust_diff:
+ done_adjust_diff:
if (sec == sect)
{
clean_nds32_elf_blank ();
}
-finish:
- if (internal_relocs != NULL
- && elf_section_data (sec)->relocs != internal_relocs)
+ finish:
+ if (elf_section_data (sec)->relocs != internal_relocs)
free (internal_relocs);
- if (contents != NULL
- && elf_section_data (sec)->this_hdr.contents != contents)
+ if (elf_section_data (sec)->this_hdr.contents != contents)
free (contents);
- if (isymbuf != NULL && symtab_hdr->contents != (bfd_byte *) isymbuf)
+ if (symtab_hdr->contents != (bfd_byte *) isymbuf)
free (isymbuf);
return result;
-error_return:
+ error_return:
result = FALSE;
goto finish;
}
{NULL, 0, 0, 0, 0}
};
+static bfd_boolean
+nds32_elf_section_flags (const Elf_Internal_Shdr *hdr)
+{
+ const char *name = hdr->bfd_section->name;
+
+ if (strncmp (name, ".sbss", 5) == 0
+ || strncmp (name, ".sdata", 6) == 0)
+ hdr->bfd_section->flags |= SEC_SMALL_DATA;
+
+ return TRUE;
+}
+
static bfd_boolean
nds32_elf_output_arch_syms (bfd *output_bfd ATTRIBUTE_UNUSED,
struct bfd_link_info *info,
goto error_return;
}
-finish:
+ finish:
if (relax_blank_list)
{
nds32_elf_relax_delete_blanks (abfd, sec, relax_blank_list);
}
return result;
-error_return:
+ error_return:
result = FALSE;
goto finish;
}
free (reloc_vector);
return data;
-error_return:
+ error_return:
free (reloc_vector);
return NULL;
}
}
while (FALSE);
- if ((relocs != NULL) && (elf_section_data (asec)->relocs != relocs))
+ if (elf_section_data (asec)->relocs != relocs)
free (relocs);
if ((min_id != relax_group_ptr->min_id)
}
while (FALSE);
- if (relocs != NULL && elf_section_data (asec)->relocs != relocs)
+ if (elf_section_data (asec)->relocs != relocs)
free (relocs);
return result;
#endif
}
-finish:
+ finish:
if (incontents)
contents = NULL;
- if (internal_relocs != NULL
- && elf_section_data (insec)->relocs != internal_relocs)
+ if (elf_section_data (insec)->relocs != internal_relocs)
free (internal_relocs);
- if (contents != NULL
- && elf_section_data (insec)->this_hdr.contents != contents)
+ if (elf_section_data (insec)->this_hdr.contents != contents)
free (contents);
- if (local_syms != NULL && symtab_hdr->contents != (bfd_byte *) local_syms)
+ if (symtab_hdr->contents != (bfd_byte *) local_syms)
free (local_syms);
if (chain.next)
return result;
-error_return:
+ error_return:
result = FALSE;
goto finish;
}
#define elf_backend_object_p nds32_elf_object_p
#define elf_backend_final_write_processing nds32_elf_final_write_processing
#define elf_backend_special_sections nds32_elf_special_sections
+#define elf_backend_section_flags nds32_elf_section_flags
#define bfd_elf32_bfd_get_relocated_section_contents \
nds32_elf_get_relocated_section_contents
#define bfd_elf32_bfd_is_target_special_symbol nds32_elf_is_target_special_symbol