/* Alpha specific support for 64-bit ELF
- Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ Copyright (C) 1996-2017 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@tamu.edu>.
This file is part of BFD, the Binary File Descriptor library.
if (r_type >= R_ALPHA_max)
{
- (*_bfd_error_handler) (_("%B: unrecognised Alpha reloc number: %d"),
- abfd, r_type);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: unrecognised Alpha reloc number: %d"),
+ abfd, r_type);
bfd_set_error (bfd_error_bad_value);
r_type = R_ALPHA_NONE;
}
| SEC_LINKER_CREATED
| (elf64_alpha_use_secureplt ? SEC_READONLY : 0));
s = bfd_make_section_anyway_with_flags (abfd, ".plt", flags);
+ elf_hash_table (info)->splt = s;
if (s == NULL || ! bfd_set_section_alignment (abfd, s, 4))
return FALSE;
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED | SEC_READONLY);
s = bfd_make_section_anyway_with_flags (abfd, ".rela.plt", flags);
+ elf_hash_table (info)->srelplt = s;
if (s == NULL || ! bfd_set_section_alignment (abfd, s, 3))
return FALSE;
{
flags = SEC_ALLOC | SEC_LINKER_CREATED;
s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
+ elf_hash_table (info)->sgotplt = s;
if (s == NULL || ! bfd_set_section_alignment (abfd, s, 3))
return FALSE;
}
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED | SEC_READONLY);
s = bfd_make_section_anyway_with_flags (abfd, ".rela.got", flags);
+ elf_hash_table (info)->srelgot = s;
if (s == NULL
|| !bfd_set_section_alignment (abfd, s, 3))
return FALSE;
&& (ah->flags & ~ALPHA_ELF_LINK_HASH_LU_PLT) == 0);
}
+/* Whether to sort relocs output by ld -r or ld --emit-relocs, by r_offset.
+ Don't do so for code sections. We want to keep ordering of LITERAL/LITUSE
+ as is. On the other hand, elf-eh-frame.c processing requires .eh_frame
+ relocs to be sorted. */
+
+static bfd_boolean
+elf64_alpha_sort_relocs_p (asection *sec)
+{
+ return (sec->flags & SEC_CODE) == 0;
+}
+
+
/* Handle dynamic relocations when doing an Alpha ELF link. */
static bfd_boolean
/* PR15323, ref flags aren't set for references in the same
object. */
- h->root.root.non_ir_ref = 1;
+ h->root.root.non_ir_ref_regular = 1;
h->root.ref_regular = 1;
}
break;
case R_ALPHA_TPREL64:
- if (bfd_link_pic (info) && !bfd_link_pie (info))
+ if (bfd_link_dll (info))
{
info->flags |= DF_STATIC_TLS;
need = NEED_DYNREL;
{
h->needs_plt = TRUE;
- s = bfd_get_linker_section (dynobj, ".plt");
+ s = elf_hash_table(info)->splt;
if (!s && !elf64_alpha_create_dynamic_sections (dynobj, info))
return FALSE;
&& gi->reloc_type == gs->reloc_type
&& gi->addend == gs->addend)
{
- gi->use_count += gs->use_count;
+ gs->use_count += gi->use_count;
goto got_found;
}
gi->next = hs->got_entries;
if (alpha_elf_tdata (this_got)->total_got_size > MAX_GOT_SIZE)
{
/* Yikes! A single object file has too many entries. */
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: .got subsegment exceeds 64K (size %d)"),
i, alpha_elf_tdata (this_got)->total_got_size);
return FALSE;
{
asection *splt, *spltrel, *sgotplt;
unsigned long entries;
- bfd *dynobj;
struct alpha_elf_link_hash_table * htab;
htab = alpha_elf_hash_table (info);
if (htab == NULL)
return;
- dynobj = elf_hash_table(info)->dynobj;
- splt = bfd_get_linker_section (dynobj, ".plt");
+ splt = elf_hash_table(info)->splt;
if (splt == NULL)
return;
elf64_alpha_size_plt_section_1, splt);
/* Every plt entry requires a JMP_SLOT relocation. */
- spltrel = bfd_get_linker_section (dynobj, ".rela.plt");
+ spltrel = elf_hash_table(info)->srelplt;
entries = 0;
if (splt->size)
{
entire contents of the .got.plt section. */
if (elf64_alpha_use_secureplt)
{
- sgotplt = bfd_get_linker_section (dynobj, ".got.plt");
+ sgotplt = elf_hash_table(info)->sgotplt;
sgotplt->size = entries ? 16 : 0;
}
}
for (relent = h->reloc_entries; relent; relent = relent->next)
{
entries = alpha_dynamic_entries_for_reloc (relent->rtype, dynamic,
- bfd_link_pic (info), bfd_link_pie (info));
+ bfd_link_pic (info),
+ bfd_link_pie (info));
if (entries)
{
relent->srel->size +=
if (entries > 0)
{
- bfd *dynobj = elf_hash_table(info)->dynobj;
- asection *srel = bfd_get_linker_section (dynobj, ".rela.got");
+ asection *srel = elf_hash_table(info)->srelgot;
BFD_ASSERT (srel != NULL);
srel->size += sizeof (Elf64_External_Rela) * entries;
}
elf64_alpha_size_rela_got_section (struct bfd_link_info *info)
{
unsigned long entries;
- bfd *i, *dynobj;
+ bfd *i;
asection *srel;
struct alpha_elf_link_hash_table * htab;
}
}
- dynobj = elf_hash_table(info)->dynobj;
- srel = bfd_get_linker_section (dynobj, ".rela.got");
+ srel = elf_hash_table(info)->srelgot;
if (!srel)
{
BFD_ASSERT (entries == 0);
{
bfd *dynobj;
asection *s;
- bfd_boolean relplt;
+ bfd_boolean relplt, relocs;
struct alpha_elf_link_hash_table * htab;
htab = alpha_elf_hash_table (info);
if (elf_hash_table (info)->dynamic_sections_created)
{
/* Set the contents of the .interp section to the interpreter. */
- if (bfd_link_executable (info))
+ if (bfd_link_executable (info) && !info->nointerp)
{
s = bfd_get_linker_section (dynobj, ".interp");
BFD_ASSERT (s != NULL);
determined the sizes of the various dynamic sections. Allocate
memory for them. */
relplt = FALSE;
+ relocs = FALSE;
for (s = dynobj->sections; s != NULL; s = s->next)
{
const char *name;
{
if (strcmp (name, ".rela.plt") == 0)
relplt = TRUE;
+ else
+ relocs = TRUE;
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
return FALSE;
}
- if (!add_dynamic_entry (DT_RELA, 0)
- || !add_dynamic_entry (DT_RELASZ, 0)
- || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
- return FALSE;
-
- if (info->flags & DF_TEXTREL)
+ if (relocs)
{
- if (!add_dynamic_entry (DT_TEXTREL, 0))
+ if (!add_dynamic_entry (DT_RELA, 0)
+ || !add_dynamic_entry (DT_RELASZ, 0)
+ || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
return FALSE;
+
+ if (info->flags & DF_TEXTREL)
+ {
+ if (!add_dynamic_entry (DT_TEXTREL, 0))
+ return FALSE;
+ }
}
}
#undef add_dynamic_entry
if (insn >> 26 != OP_LDQ)
{
reloc_howto_type *howto = elf64_alpha_howto_table + r_type;
- ((*_bfd_error_handler)
- ("%B: %A+0x%lx: warning: %s relocation against unexpected insn",
- info->abfd, info->sec,
- (unsigned long) irel->r_offset, howto->name));
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: %A+0x%lx: warning: %s relocation against unexpected insn"),
+ info->abfd, info->sec,
+ (unsigned long) irel->r_offset, howto->name);
return TRUE;
}
/* Can't use local-exec relocations in shared libraries. */
if (r_type == R_ALPHA_GOTTPREL
- && (bfd_link_pic (info->link_info)
- && !bfd_link_pie (info->link_info)))
+ && bfd_link_dll (info->link_info))
return TRUE;
if (r_type == R_ALPHA_LITERAL)
if (tsec_relocs == NULL)
return 0;
tsec_relend = tsec_relocs + info->tsec->reloc_count;
- tsec_free = (info->link_info->keep_memory ? NULL : tsec_relocs);
+ tsec_free = (elf_section_data (info->tsec)->relocs == tsec_relocs
+ ? NULL
+ : tsec_relocs);
}
/* Recover the symbol's offset within the section. */
lit_insn = bfd_get_32 (abfd, contents + irel->r_offset);
if (lit_insn >> 26 != OP_LDQ)
{
- ((*_bfd_error_handler)
- ("%B: %A+0x%lx: warning: LITERAL relocation against unexpected insn",
- abfd, info->sec,
- (unsigned long) irel->r_offset));
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: %A+0x%lx: warning: LITERAL relocation against unexpected insn"),
+ abfd, info->sec,
+ (unsigned long) irel->r_offset);
return TRUE;
}
r_type = ELF64_R_TYPE (rel->r_info);
if (r_type >= R_ALPHA_max)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: unknown relocation type %d"),
input_bfd, (int) r_type);
bfd_set_error (bfd_error_bad_value);
symtab_hdr = &elf_symtab_hdr (input_bfd);
dynobj = elf_hash_table (info)->dynobj;
- if (dynobj)
- srelgot = bfd_get_linker_section (dynobj, ".rela.got");
- else
- srelgot = NULL;
+ srelgot = elf_hash_table (info)->srelgot;
if (input_section->flags & SEC_ALLOC)
{
r_type = ELF64_R_TYPE(rel->r_info);
if (r_type >= R_ALPHA_max)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: unknown relocation type %d"),
input_bfd, (int) r_type);
bfd_set_error (bfd_error_bad_value);
case R_ALPHA_GPRELLOW:
if (dynamic_symbol_p)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: gp-relative relocation against dynamic symbol %s"),
input_bfd, h->root.root.root.string);
ret_val = FALSE;
case R_ALPHA_GPRELHIGH:
if (dynamic_symbol_p)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: gp-relative relocation against dynamic symbol %s"),
input_bfd, h->root.root.root.string);
ret_val = FALSE;
case R_ALPHA_BRADDR:
if (dynamic_symbol_p)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: pc-relative relocation against dynamic symbol %s"),
input_bfd, h->root.root.root.string);
ret_val = FALSE;
&& alpha_elf_tdata (sec->owner)->gotobj
&& gotobj != alpha_elf_tdata (sec->owner)->gotobj)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: change in gp: BRSGP %s"),
input_bfd, h->root.root.root.string);
ret_val = FALSE;
else if (name[0] == 0)
name = bfd_section_name (input_bfd, sec);
}
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: !samegp reloc against symbol without .prologue: %s"),
input_bfd, name);
ret_val = FALSE;
else if (r_type == R_ALPHA_TPREL64)
{
BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
- if (!bfd_link_pic (info) || bfd_link_pie (info))
+ if (!bfd_link_dll (info))
{
value -= tp_base;
goto default_reloc;
{
if (r_type == R_ALPHA_REFLONG)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: unhandled dynamic relocation against %s"),
input_bfd,
h->root.root.root.string);
case R_ALPHA_SREL64:
if (dynamic_symbol_p)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: pc-relative relocation against dynamic symbol %s"),
input_bfd, h->root.root.root.string);
ret_val = FALSE;
}
- else if ((bfd_link_pic (info) || bfd_link_pie (info))
+ else if (bfd_link_pic (info)
&& undef_weak_ref)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: pc-relative relocation against undefined weak symbol %s"),
input_bfd, h->root.root.root.string);
ret_val = FALSE;
case R_ALPHA_DTPREL16:
if (dynamic_symbol_p)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: dtp-relative relocation against dynamic symbol %s"),
input_bfd, h->root.root.root.string);
ret_val = FALSE;
case R_ALPHA_TPRELHI:
case R_ALPHA_TPRELLO:
case R_ALPHA_TPREL16:
- if (bfd_link_pic (info) && !bfd_link_pie (info))
+ if (bfd_link_dll (info))
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: TLS local exec code cannot be linked into shared objects"),
input_bfd);
ret_val = FALSE;
}
else if (dynamic_symbol_p)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: tp-relative relocation against dynamic symbol %s"),
input_bfd, h->root.root.root.string);
ret_val = FALSE;
if (*name == '\0')
name = bfd_section_name (input_bfd, sec);
}
- if (! ((*info->callbacks->reloc_overflow)
- (info, (h ? &h->root.root : NULL), name, howto->name,
- (bfd_vma) 0, input_bfd, input_section,
- rel->r_offset)))
- ret_val = FALSE;
+ (*info->callbacks->reloc_overflow)
+ (info, (h ? &h->root.root : NULL), name, howto->name,
+ (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
}
break;
Elf_Internal_Sym *sym)
{
struct alpha_elf_link_hash_entry *ah = (struct alpha_elf_link_hash_entry *)h;
- bfd *dynobj = elf_hash_table(info)->dynobj;
if (h->needs_plt)
{
BFD_ASSERT (h->dynindx != -1);
- splt = bfd_get_linker_section (dynobj, ".plt");
+ splt = elf_hash_table (info)->splt;
BFD_ASSERT (splt != NULL);
- srel = bfd_get_linker_section (dynobj, ".rela.plt");
+ srel = elf_hash_table (info)->srelplt;
BFD_ASSERT (srel != NULL);
for (gotent = ah->got_entries; gotent ; gotent = gotent->next)
asection *srel;
struct alpha_elf_got_entry *gotent;
- srel = bfd_get_linker_section (dynobj, ".rela.got");
+ srel = elf_hash_table (info)->srelgot;
BFD_ASSERT (srel != NULL);
for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
Elf64_External_Dyn *dyncon, *dynconend;
bfd_vma plt_vma, gotplt_vma;
- splt = bfd_get_linker_section (dynobj, ".plt");
- srelaplt = bfd_get_linker_section (output_bfd, ".rela.plt");
+ splt = elf_hash_table (info)->splt;
+ srelaplt = elf_hash_table (info)->srelplt;
BFD_ASSERT (splt != NULL && sdyn != NULL);
plt_vma = splt->output_section->vma + splt->output_offset;
gotplt_vma = 0;
if (elf64_alpha_use_secureplt)
{
- sgotplt = bfd_get_linker_section (dynobj, ".got.plt");
+ sgotplt = elf_hash_table (info)->sgotplt;
BFD_ASSERT (sgotplt != NULL);
if (sgotplt->size > 0)
gotplt_vma = sgotplt->output_section->vma + sgotplt->output_offset;
dyn.d_un.d_val = srelaplt ? srelaplt->size : 0;
break;
case DT_JMPREL:
- dyn.d_un.d_ptr = srelaplt ? srelaplt->vma : 0;
- break;
-
- case DT_RELASZ:
- /* My interpretation of the TIS v1.1 ELF document indicates
- that RELASZ should not include JMPREL. This is not what
- the rest of the BFD does. It is, however, what the
- glibc ld.so wants. Do this fixup here until we found
- out who is right. */
- if (srelaplt)
- dyn.d_un.d_val -= srelaplt->size;
+ dyn.d_un.d_ptr = srelaplt ? (srelaplt->output_section->vma
+ + srelaplt->output_offset) : 0;
break;
}
elf64_alpha_add_symbol_hook
#define elf_backend_relocs_compatible \
_bfd_elf_relocs_compatible
+#define elf_backend_sort_relocs_p \
+ elf64_alpha_sort_relocs_p
#define elf_backend_check_relocs \
elf64_alpha_check_relocs
#define elf_backend_create_dynamic_sections \
#define elf_backend_plt_readonly 0
#define elf_backend_want_plt_sym 1
#define elf_backend_got_header_size 0
+#define elf_backend_dtrel_excludes_plt 1
#include "elf64-target.h"
\f