/* Or1k-specific support for 32-bit ELF.
- Copyright (C) 2001-2015 Free Software Foundation, Inc.
+ Copyright (C) 2001-2016 Free Software Foundation, Inc.
Contributed for OR32 by Johan Rydberg, jrydberg@opencores.org
PIC parts added by Stefan Kristiansson, stefan.kristiansson@saunalahti.fi,
FALSE, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
- FALSE), /* pcrel_offset */
+ TRUE), /* pcrel_offset */
HOWTO (R_OR1K_16_PCREL,
0, /* rightshift */
FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
- FALSE), /* pcrel_offset */
+ TRUE), /* pcrel_offset */
HOWTO (R_OR1K_8_PCREL,
0, /* rightshift */
FALSE, /* partial_inplace */
0, /* src_mask */
0xff, /* dst_mask */
- FALSE), /* pcrel_offset */
+ TRUE), /* pcrel_offset */
HOWTO (R_OR1K_GOTPC_HI16, /* Type. */
16, /* Rightshift. */
struct elf_link_hash_table root;
/* Short-cuts to get to dynamic linker sections. */
- asection *sgot;
- asection *sgotplt;
- asection *srelgot;
- asection *splt;
- asection *srelplt;
asection *sdynbss;
asection *srelbss;
{
unsigned int i;
- for (i = ARRAY_SIZE (or1k_reloc_map); --i;)
+ for (i = ARRAY_SIZE (or1k_reloc_map); i--;)
if (or1k_reloc_map[i].bfd_reloc_val == code)
return & or1k_elf_howto_table[or1k_reloc_map[i].or1k_reloc_val];
r_type = ELF32_R_TYPE (dst->r_info);
if (r_type >= (unsigned int) R_OR1K_max)
{
- _bfd_error_handler (_("%A: invalid OR1K reloc number: %d"), abfd, r_type);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: invalid OR1K reloc number: %d"), abfd, r_type);
r_type = 0;
}
cache_ptr->howto = & or1k_elf_howto_table[r_type];
sreloc = elf_section_data (input_section)->sreloc;
- sgot = htab->sgot;
+ sgot = htab->root.sgot;
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
rel, 1, relend, howto, 0, contents);
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
continue;
switch (howto->type)
{
case R_OR1K_PLT26:
{
- if (htab->splt != NULL && h != NULL
+ if (htab->root.splt != NULL && h != NULL
&& h->plt.offset != (bfd_vma) -1)
{
- relocation = (htab->splt->output_section->vma
- + htab->splt->output_offset
+ relocation = (htab->root.splt->output_section->vma
+ + htab->root.splt->output_offset
+ h->plt.offset);
}
break;
BFD_ASSERT (off != (bfd_vma) -1);
dyn = htab->root.dynamic_sections_created;
- if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
- || (info->shared
+ if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
+ bfd_link_pic (info),
+ h)
+ || (bfd_link_pic (info)
&& SYMBOL_REFERENCES_LOCAL (info, h)))
{
/* This is actually a static link, or it is a
{
/* Write entry in GOT. */
bfd_put_32 (output_bfd, relocation, sgot->contents + off);
- if (info->shared)
+ if (bfd_link_pic (info))
{
asection *srelgot;
Elf_Internal_Rela outrel;
/* We need to generate a R_OR1K_RELATIVE reloc
for the dynamic linker. */
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ srelgot = htab->root.srelgot;
BFD_ASSERT (srelgot != NULL);
outrel.r_offset = (sgot->output_section->vma
/* Addend should be zero. */
if (rel->r_addend != 0)
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("internal error: addend should be zero for R_OR1K_GOT16"));
break;
case R_OR1K_GOTOFF_HI16:
/* Relocation is offset from GOT. */
BFD_ASSERT (sgot != NULL);
- relocation -= sgot->output_section->vma;
+ relocation
+ -= (htab->root.hgot->root.u.def.value
+ + htab->root.hgot->root.u.def.section->output_offset
+ + htab->root.hgot->root.u.def.section->output_section->vma);
break;
case R_OR1K_INSN_REL_26:
|| (input_section->flags & SEC_ALLOC) == 0)
break;
- if ((info->shared
+ if ((bfd_link_pic (info)
&& (h == NULL
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak)
&& (howto->type != R_OR1K_INSN_REL_26
|| !SYMBOL_CALLS_LOCAL (info, h)))
- || (!info->shared
+ || (!bfd_link_pic (info)
&& h != NULL
&& h->dynindx != -1
&& !h->non_got_ref
else
{
BFD_FAIL ();
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("%B: probably compiled without -fPIC?"),
input_bfd);
bfd_set_error (bfd_error_bad_value);
case R_OR1K_TLS_LDO_LO16:
/* TODO: implement support for local dynamic. */
BFD_FAIL ();
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("%B: support for local dynamic not implemented"),
input_bfd);
bfd_set_error (bfd_error_bad_value);
/* Dynamic entries will require relocations. if we do not need
them we will just use the default R_OR1K_NONE and
not set anything. */
- dynamic = info->shared
+ dynamic = bfd_link_pic (info)
|| (sec && (sec->flags & SEC_ALLOC) != 0
&& h != NULL
&& (h->root.type == bfd_link_hash_defweak || !h->def_regular));
/* These are resolved dynamically on load and shouldn't
be used as linker input. */
BFD_FAIL ();
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("%B: will not resolve runtime TLS relocation"),
input_bfd);
bfd_set_error (bfd_error_bad_value);
switch (r)
{
case bfd_reloc_overflow:
- r = info->callbacks->reloc_overflow
+ (*info->callbacks->reloc_overflow)
(info, (h ? &h->root : NULL), name, howto->name,
(bfd_vma) 0, input_bfd, input_section, rel->r_offset);
break;
case bfd_reloc_undefined:
- r = info->callbacks->undefined_symbol
+ (*info->callbacks->undefined_symbol)
(info, name, input_bfd, input_section, rel->r_offset, TRUE);
break;
}
if (msg)
- r = info->callbacks->warning
- (info, msg, name, input_bfd, input_section, rel->r_offset);
-
- if (!r)
- return FALSE;
+ (*info->callbacks->warning) (info, msg, name, input_bfd,
+ input_section, rel->r_offset);
}
}
return TRUE;
}
-/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up
- shortcuts to them in our hash table. */
-
-static bfd_boolean
-create_got_section (bfd *dynobj, struct bfd_link_info *info)
-{
- struct elf_or1k_link_hash_table *htab;
- asection *s;
-
- /* This function may be called more than once. */
- s = bfd_get_section_by_name (dynobj, ".got");
- if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0)
- return TRUE;
-
- htab = or1k_elf_hash_table (info);
- if (htab == NULL)
- return FALSE;
-
- if (! _bfd_elf_create_got_section (dynobj, info))
- 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");
-
- if (! htab->sgot || ! htab->sgotplt || ! htab->srelgot)
- abort ();
-
- if (! bfd_set_section_flags (dynobj, htab->srelgot, SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED
- | SEC_READONLY)
- || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
- return FALSE;
-
- return TRUE;
-}
-
/* Look through the relocs for a section during the first phase. */
static bfd_boolean
bfd *dynobj;
asection *sreloc = NULL;
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
return TRUE;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
case R_OR1K_TLS_GD_LO16:
case R_OR1K_TLS_IE_HI16:
case R_OR1K_TLS_IE_LO16:
- if (htab->sgot == NULL)
+ if (htab->root.sgot == NULL)
{
if (dynobj == NULL)
htab->root.dynobj = dynobj = abfd;
- if (! create_got_section (dynobj, info))
+ if (!_bfd_elf_create_got_section (dynobj, info))
return FALSE;
}
case R_OR1K_32:
/* R_OR1K_16? */
{
- if (h != NULL && !info->shared)
+ if (h != NULL && !bfd_link_pic (info))
{
/* We may need a copy reloc. */
h->non_got_ref = 1;
dynamic library if we manage to avoid copy relocs for the
symbol. */
- if ((info->shared
+ if ((bfd_link_pic (info)
&& (sec->flags & SEC_ALLOC) != 0
&& (ELF32_R_TYPE (rel->r_info) != R_OR1K_INSN_REL_26
|| (h != NULL
&& (!SYMBOLIC_BIND (info, h)
|| h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
- || (!info->shared
+ || (!bfd_link_pic (info)
&& (sec->flags & SEC_ALLOC) != 0
&& h != NULL
&& (h->root.type == bfd_link_hash_defweak
|| strcmp (bfd_get_section_name (abfd, sec),
name + 5) != 0)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: bad relocation section name `%s\'"),
abfd, name);
}
dynobj = htab->root.dynobj;
- sgot = htab->sgotplt;
+ sgot = htab->root.sgotplt;
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
if (htab->root.dynamic_sections_created)
continue;
case DT_PLTGOT:
- s = htab->sgot->output_section;
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_ptr = s->vma;
+ s = htab->root.sgotplt;
+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
break;
case DT_JMPREL:
- s = htab->srelplt->output_section;
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_ptr = s->vma;
+ s = htab->root.srelplt;
+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
break;
case DT_PLTRELSZ:
- s = htab->srelplt->output_section;
- BFD_ASSERT (s != NULL);
+ s = htab->root.srelplt;
dyn.d_un.d_val = s->size;
break;
-
- case DT_RELASZ:
- /* My reading of the SVR4 ABI indicates that the
- procedure linkage table relocs (DT_JMPREL) should be
- included in the overall relocs (DT_RELA). This is
- what Solaris does. However, UnixWare can not handle
- that case. Therefore, we override the DT_RELASZ entry
- here to make it not include the JMPREL relocs. Since
- the linker script arranges for .rela.plt to follow all
- other relocation sections, we don't have to worry
- about changing the DT_RELA entry. */
- if (htab->srelplt != NULL)
- {
- /* FIXME: this calculation sometimes produces
- wrong result, the problem is that the dyn.d_un.d_val
- is not always correct, needs investigation why
- that happens. In the meantime, reading the
- ".rela.dyn" section by name seems to yield
- correct result.
-
- s = htab->srelplt->output_section;
- dyn.d_un.d_val -= s->size;
- */
-
- s = bfd_get_section_by_name (output_bfd, ".rela.dyn");
- dyn.d_un.d_val = s ? s->size : 0;
- }
- break;
}
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
}
/* Fill in the first entry in the procedure linkage table. */
- splt = htab->splt;
+ splt = htab->root.splt;
if (splt && splt->size > 0)
{
- if (info->shared)
+ if (bfd_link_pic (info))
{
bfd_put_32 (output_bfd, PLT0_PIC_ENTRY_WORD0,
splt->contents);
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
}
- if (htab->sgot && htab->sgot->size > 0)
- elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize = 4;
+ if (htab->root.sgot && htab->root.sgot->size > 0)
+ elf_section_data (htab->root.sgot->output_section)->this_hdr.sh_entsize = 4;
return TRUE;
}
it up. */
BFD_ASSERT (h->dynindx != -1);
- splt = htab->splt;
- sgot = htab->sgotplt;
- srela = htab->srelplt;
+ splt = htab->root.splt;
+ sgot = htab->root.sgotplt;
+ srela = htab->root.srelplt;
BFD_ASSERT (splt != NULL && sgot != NULL && srela != NULL);
/* Get the index in the procedure linkage table which
got_addr = got_offset;
/* Fill in the entry in the procedure linkage table. */
- if (! info->shared)
+ if (! bfd_link_pic (info))
{
- got_addr += htab->sgotplt->output_section->vma
- + htab->sgotplt->output_offset;
+ got_addr += htab->root.sgotplt->output_section->vma
+ + htab->root.sgotplt->output_offset;
bfd_put_32 (output_bfd, PLT_ENTRY_WORD0 | ((got_addr >> 16) & 0xffff),
splt->contents + h->plt.offset);
bfd_put_32 (output_bfd, PLT_ENTRY_WORD1 | (got_addr & 0xffff),
/* This symbol has an entry in the global offset table. Set it
up. */
- sgot = htab->sgot;
- srela = htab->srelgot;
+ sgot = htab->root.sgot;
+ srela = htab->root.srelgot;
BFD_ASSERT (sgot != NULL && srela != NULL);
rela.r_offset = (sgot->output_section->vma
the symbol was forced to be local because of a version file.
The entry in the global offset table will already have been
initialized in the relocate_section function. */
- if (info->shared && SYMBOL_REFERENCES_LOCAL (info, h))
+ if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h))
{
rela.r_info = ELF32_R_INFO (0, R_OR1K_RELATIVE);
rela.r_addend = (h->root.u.def.value
if (h->type == STT_FUNC
|| h->needs_plt)
{
- if (! info->shared
+ if (! bfd_link_pic (info)
&& !h->def_dynamic
&& !h->ref_dynamic
&& h->root.type != bfd_link_hash_undefweak
only references to the symbol are via the global offset table.
For such cases we need not do anything here; the relocations will
be handled correctly by relocate_section. */
- if (info->shared)
+ if (bfd_link_pic (info))
return TRUE;
/* If there are no references to this symbol that do not use the
return FALSE;
}
- if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
{
- asection *s = htab->splt;
+ asection *s = htab->root.splt;
/* If this is the first .plt entry, make room for the special
first entry. */
location in the .plt. This is required to make function
pointers compare as equal between the normal executable and
the shared library. */
- if (! info->shared
+ if (! bfd_link_pic (info)
&& !h->def_regular)
{
h->root.u.def.section = s;
/* We also need to make an entry in the .got.plt section, which
will be placed in the .got section by the linker script. */
- htab->sgotplt->size += 4;
+ htab->root.sgotplt->size += 4;
/* We also need to make an entry in the .rel.plt section. */
- htab->srelplt->size += sizeof (Elf32_External_Rela);
+ htab->root.srelplt->size += sizeof (Elf32_External_Rela);
}
else
{
return FALSE;
}
- s = htab->sgot;
+ s = htab->root.sgot;
h->got.offset = s->size;
else
s->size += 4;
dyn = htab->root.dynamic_sections_created;
- if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h))
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h))
{
if (tls_type == TLS_GD)
- htab->srelgot->size += 2 * sizeof (Elf32_External_Rela);
+ htab->root.srelgot->size += 2 * sizeof (Elf32_External_Rela);
else
- htab->srelgot->size += sizeof (Elf32_External_Rela);
+ htab->root.srelgot->size += sizeof (Elf32_External_Rela);
}
}
else
space for pc-relative relocs that have become local due to symbol
visibility changes. */
- if (info->shared)
+ if (bfd_link_pic (info))
{
if (SYMBOL_CALLS_LOCAL (info, h))
{
if (htab->root.dynamic_sections_created)
{
/* Set the contents of the .interp section to the interpreter. */
- if (info->executable)
+ if (bfd_link_executable (info) && !info->nointerp)
{
s = bfd_get_section_by_name (dynobj, ".interp");
BFD_ASSERT (s != NULL);
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
locsymcount = symtab_hdr->sh_info;
end_local_got = local_got + locsymcount;
- s = htab->sgot;
- srel = htab->srelgot;
+ s = htab->root.sgot;
+ srel = htab->root.srelgot;
local_tls_type = (unsigned char *) elf_or1k_local_tls_type (ibfd);
for (; local_got < end_local_got; ++local_got)
{
s->size += 8;
else
s->size += 4;
- if (info->shared)
+ if (bfd_link_pic (info))
{
if (local_tls_type != NULL && *local_tls_type == TLS_GD)
srel->size += 2 * sizeof (Elf32_External_Rela);
if ((s->flags & SEC_LINKER_CREATED) == 0)
continue;
- if (s == htab->splt
- || s == htab->sgot
- || s == htab->sgotplt
+ if (s == htab->root.splt
+ || s == htab->root.sgot
+ || s == htab->root.sgotplt
|| s == htab->sdynbss)
{
/* Strip this section if we don't need it; see the
}
else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela"))
{
- if (s->size != 0 && s != htab->srelplt)
+ if (s->size != 0 && s != htab->root.srelplt)
relocs = TRUE;
/* We use the reloc_count field as a counter if we need
#define add_dynamic_entry(TAG, VAL) \
_bfd_elf_add_dynamic_entry (info, TAG, VAL)
- if (info->executable)
+ if (bfd_link_executable (info))
{
if (! add_dynamic_entry (DT_DEBUG, 0))
return FALSE;
}
- if (htab->splt->size != 0)
+ if (htab->root.splt->size != 0)
{
if (! add_dynamic_entry (DT_PLTGOT, 0)
|| ! add_dynamic_entry (DT_PLTRELSZ, 0)
if (htab == NULL)
return FALSE;
- if (!htab->sgot && !create_got_section (dynobj, info))
+ if (!htab->root.sgot && !_bfd_elf_create_got_section (dynobj, info))
return FALSE;
if (!_bfd_elf_create_dynamic_sections (dynobj, info))
return FALSE;
- htab->splt = bfd_get_section_by_name (dynobj, ".plt");
- htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
- if (!info->shared)
+ if (!bfd_link_pic (info))
htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
- if (!htab->splt || !htab->srelplt || !htab->sdynbss
- || (!info->shared && !htab->srelbss))
+ if (!htab->root.splt || !htab->root.srelplt || !htab->sdynbss
+ || (!bfd_link_pic (info) && !htab->srelbss))
abort ();
return TRUE;
EF_OR1K_NODELAY flag setting. */
static bfd_boolean
-elf32_or1k_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+elf32_or1k_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
{
+ bfd *obfd = info->output_bfd;
flagword out_flags;
flagword in_flags;
if ((in_flags & EF_OR1K_NODELAY) != (out_flags & EF_OR1K_NODELAY))
{
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("%B: EF_OR1K_NODELAY flag mismatch with previous modules"), ibfd);
bfd_set_error (bfd_error_bad_value);
#define elf_backend_want_got_plt 1
#define elf_backend_want_plt_sym 0
#define elf_backend_got_header_size 12
+#define elf_backend_dtrel_excludes_plt 1
+
#define bfd_elf32_bfd_link_hash_table_create or1k_elf_link_hash_table_create
#define elf_backend_copy_indirect_symbol or1k_elf_copy_indirect_symbol
#define elf_backend_create_dynamic_sections or1k_elf_create_dynamic_sections