/* Alpha specific support for 64-bit ELF
- Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ Copyright (C) 1996-2019 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@tamu.edu>.
This file is part of BFD, the Binary File Descriptor library.
/* Given an Alpha ELF reloc type, fill in an arelent structure. */
-static void
-elf64_alpha_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
+static bfd_boolean
+elf64_alpha_info_to_howto (bfd *abfd, arelent *cache_ptr,
Elf_Internal_Rela *dst)
{
unsigned r_type = ELF64_R_TYPE(dst->r_info);
if (r_type >= R_ALPHA_max)
{
- (*_bfd_error_handler) (_("%A: unrecognised Alpha reloc number: %d"),
- abfd, r_type);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+ abfd, r_type);
bfd_set_error (bfd_error_bad_value);
- r_type = R_ALPHA_NONE;
+ return FALSE;
}
cache_ptr->howto = &elf64_alpha_howto_table[r_type];
+ return TRUE;
}
/* These two relocations create a two-word entry in the got. */
{
hdr->sh_type = SHT_ALPHA_DEBUG;
/* In a shared object on Irix 5.3, the .mdebug section has an
- entsize of 0. FIXME: Does this matter? */
+ entsize of 0. FIXME: Does this matter? */
if ((abfd->flags & DYNAMIC) != 0 )
hdr->sh_entsize = 0;
else
asection **secp, bfd_vma *valp)
{
if (sym->st_shndx == SHN_COMMON
- && !info->relocatable
+ && !bfd_link_relocatable (info)
&& sym->st_size <= elf_gp_size (abfd))
{
/* Common symbols less than or equal to -G nn bytes are
| 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;
if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
filename_ptr, functionname_ptr,
line_ptr, discriminator_ptr,
- dwarf_debug_sections, 0,
+ dwarf_debug_sections,
&elf_tdata (abfd)->dwarf2_find_line_info))
return TRUE;
alpha_elf_tdata (abfd)->find_line_info = fi;
/* Note that we don't bother to ever free this information.
- find_nearest_line is either called all the time, as in
- objdump -l, so the information should be saved, or it is
- rarely called, as in ld error messages, so the memory
- wasted is unimportant. Still, it would probably be a
- good idea for free_cached_info to throw it away. */
+ find_nearest_line is either called all the time, as in
+ objdump -l, so the information should be saved, or it is
+ rarely called, as in ld error messages, so the memory
+ wasted is unimportant. Still, it would probably be a
+ good idea for free_cached_info to throw it away. */
}
if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap,
&& (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
const Elf_Internal_Rela *rel, *relend;
bfd_size_type amt;
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
return TRUE;
/* Don't do anything special with non-loaded, non-alloced sections.
/* PR15323, ref flags aren't set for references in the same
object. */
- h->root.root.non_ir_ref = 1;
h->root.ref_regular = 1;
}
/* We can only get preliminary data on whether a symbol is
- locally or externally defined, as not all of the input files
- have yet been processed. Do something with what we know, as
- this may help reduce memory usage and processing time later. */
+ locally or externally defined, as not all of the input files
+ have yet been processed. Do something with what we know, as
+ this may help reduce memory usage and processing time later. */
maybe_dynamic = FALSE;
- if (h && ((info->shared
+ if (h && ((bfd_link_pic (info)
&& (!info->symbolic
|| info->unresolved_syms_in_shared_libs == RM_IGNORE))
|| !h->root.def_regular
|| h->root.root.type == bfd_link_hash_defweak))
- maybe_dynamic = TRUE;
+ maybe_dynamic = TRUE;
need = 0;
gotent_flags = 0;
case R_ALPHA_REFLONG:
case R_ALPHA_REFQUAD:
- if (info->shared || maybe_dynamic)
+ if (bfd_link_pic (info) || maybe_dynamic)
need = NEED_DYNREL;
break;
case R_ALPHA_GOTTPREL:
need = NEED_GOT | NEED_GOT_ENTRY;
gotent_flags = ALPHA_ELF_LINK_HASH_TLS_IE;
- if (info->shared)
+ if (bfd_link_pic (info))
info->flags |= DF_STATIC_TLS;
break;
case R_ALPHA_TPREL64:
- if (info->shared && !info->pie)
+ if (bfd_link_dll (info))
{
info->flags |= DF_STATIC_TLS;
need = NEED_DYNREL;
else
rent->count++;
}
- else if (info->shared)
+ else if (bfd_link_pic (info))
{
/* If this is a shared library, and the section is to be
loaded into memory, we need a RELATIVE reloc. */
return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}
-/* Update the got entry reference counts for the section being removed. */
-
-static bfd_boolean
-elf64_alpha_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
- asection *sec, const Elf_Internal_Rela *relocs)
-{
- Elf_Internal_Shdr *symtab_hdr;
- struct alpha_elf_link_hash_entry **sym_hashes;
- const Elf_Internal_Rela *rel, *relend;
-
- if (info->relocatable)
- return TRUE;
-
- symtab_hdr = &elf_symtab_hdr (abfd);
- sym_hashes = alpha_elf_sym_hashes (abfd);
-
- relend = relocs + sec->reloc_count;
- for (rel = relocs; rel < relend; rel++)
- {
- unsigned long r_symndx, r_type;
- struct alpha_elf_link_hash_entry *h = NULL;
- struct alpha_elf_got_entry *gotent;
-
- r_symndx = ELF64_R_SYM (rel->r_info);
- if (r_symndx >= symtab_hdr->sh_info)
- {
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- while (h->root.root.type == bfd_link_hash_indirect
- || h->root.root.type == bfd_link_hash_warning)
- h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
- }
-
- r_type = ELF64_R_TYPE (rel->r_info);
- switch (r_type)
- {
- case R_ALPHA_LITERAL:
- /* ??? Ignore re-computation of gotent_flags. We're not
- carrying a use-count for each bit in that mask. */
-
- case R_ALPHA_TLSGD:
- case R_ALPHA_GOTDTPREL:
- case R_ALPHA_GOTTPREL:
- /* Fetch the got entry from the tables. */
- gotent = get_got_entry (abfd, h, r_type, r_symndx, rel->r_addend);
-
- /* The got entry *must* exist, since we should have created it
- before during check_relocs. Also note that get_got_entry
- assumed this was going to be another use, and so incremented
- the use count again. Thus the use count must be at least the
- one real use and the "use" we just added. */
- if (gotent == NULL || gotent->use_count < 2)
- {
- abort ();
- return FALSE;
- }
- gotent->use_count -= 2;
- break;
-
- default:
- break;
- }
- }
-
- return TRUE;
-}
-
/* 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
{
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;
/* 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;
}
&& gi->reloc_type == gs->reloc_type
&& gi->addend == gs->addend)
{
- gi->use_count += gs->use_count;
- goto got_found;
+ gs->use_count += gi->use_count;
+ goto got_found;
}
gi->next = hs->got_entries;
hs->got_entries = gi;
h = hashes[i];
while (h->root.root.type == bfd_link_hash_indirect
- || h->root.root.type == bfd_link_hash_warning)
+ || h->root.root.type == bfd_link_hash_warning)
h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
for (be = h->got_entries; be ; be = be->next)
{
if (be->use_count == 0)
- continue;
+ continue;
if (be->gotobj != b)
- continue;
+ continue;
for (ae = h->got_entries; ae ; ae = ae->next)
- if (ae->gotobj == a
+ if (ae->gotobj == a
&& ae->reloc_type == be->reloc_type
&& ae->addend == be->addend)
goto global_found;
total += alpha_got_entry_size (be->reloc_type);
if (total > MAX_GOT_SIZE)
- return FALSE;
+ return FALSE;
global_found:;
}
}
/* Let the local .got entries know they are part of a new subsegment. */
local_got_entries = alpha_elf_tdata (bsub)->local_got_entries;
if (local_got_entries)
- {
+ {
n = elf_tdata (bsub)->symtab_hdr.sh_info;
for (i = 0; i < n; ++i)
{
struct alpha_elf_got_entry *ent;
for (ent = local_got_entries[i]; ent; ent = ent->next)
- ent->gotobj = a;
+ ent->gotobj = a;
}
- }
+ }
/* Merge the global .got entries. */
hashes = alpha_elf_sym_hashes (bsub);
n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info;
for (i = 0; i < n; ++i)
- {
+ {
struct alpha_elf_got_entry *ae, *be, **pbe, **start;
struct alpha_elf_link_hash_entry *h;
h = hashes[i];
while (h->root.root.type == bfd_link_hash_indirect
- || h->root.root.type == bfd_link_hash_warning)
+ || h->root.root.type == bfd_link_hash_warning)
h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
pbe = start = &h->got_entries;
while ((be = *pbe) != NULL)
{
if (be->use_count == 0)
- {
+ {
*pbe = be->next;
memset (be, 0xa5, sizeof (*be));
goto kill;
- }
+ }
if (be->gotobj != b)
- goto next;
+ goto next;
for (ae = *start; ae ; ae = ae->next)
- if (ae->gotobj == a
+ if (ae->gotobj == a
&& ae->reloc_type == be->reloc_type
&& ae->addend == be->addend)
{
pbe = &be->next;
kill:;
}
- }
+ }
alpha_elf_tdata (bsub)->gotobj = a;
}
for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k)
for (gotent = local_got_entries[k]; gotent; gotent = gotent->next)
if (gotent->use_count > 0)
- {
+ {
gotent->got_offset = got_offset;
got_offset += alpha_got_entry_size (gotent->reloc_type);
- }
+ }
}
alpha_elf_tdata(i)->got->size = got_offset;
static bfd_boolean
elf64_alpha_size_got_sections (struct bfd_link_info *info,
- bfd_boolean may_merge)
+ bfd_boolean may_merge)
{
bfd *i, *got_list, *cur_got_obj = NULL;
struct alpha_elf_link_hash_table * htab;
/* We are assuming no merging has yet occurred. */
BFD_ASSERT (this_got == i);
- if (alpha_elf_tdata (this_got)->total_got_size > MAX_GOT_SIZE)
+ if (alpha_elf_tdata (this_got)->total_got_size > MAX_GOT_SIZE)
{
/* Yikes! A single object file has too many entries. */
- (*_bfd_error_handler)
- (_("%B: .got subsegment exceeds 64K (size %d)"),
- i, alpha_elf_tdata (this_got)->total_got_size);
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: .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;
}
}
bfd *i;
struct alpha_elf_link_hash_table * htab;
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
return TRUE;
htab = alpha_elf_hash_table (info);
/* If the symbol is a hidden undefined weak, then we never have any
relocations. Avoid the loop which may want to add RELATIVE relocs
- based on info->shared. */
+ based on bfd_link_pic (info). */
if (h->root.root.type == bfd_link_hash_undefweak && !dynamic)
return TRUE;
for (relent = h->reloc_entries; relent; relent = relent->next)
{
entries = alpha_dynamic_entries_for_reloc (relent->rtype, dynamic,
- info->shared, info->pie);
+ bfd_link_pic (info),
+ bfd_link_pie (info));
if (entries)
{
relent->srel->size +=
/* If the symbol is a hidden undefined weak, then we never have any
relocations. Avoid the loop which may want to add RELATIVE relocs
- based on info->shared. */
+ based on bfd_link_pic (info). */
if (h->root.root.type == bfd_link_hash_undefweak && !dynamic)
return TRUE;
for (gotent = h->got_entries; gotent ; gotent = gotent->next)
if (gotent->use_count > 0)
entries += alpha_dynamic_entries_for_reloc (gotent->reloc_type, dynamic,
- info->shared, info->pie);
+ bfd_link_pic (info),
+ bfd_link_pie (info));
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;
gotent ; gotent = gotent->next)
if (gotent->use_count > 0)
entries += (alpha_dynamic_entries_for_reloc
- (gotent->reloc_type, 0, info->shared, info->pie));
+ (gotent->reloc_type, 0, bfd_link_pic (info),
+ bfd_link_pie (info)));
}
}
- 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 (info->executable)
+ 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. */
#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;
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 */
+ (_("%pB: %pA+%#" PRIx64 ": warning: "
+ "%s relocation against unexpected insn"),
+ info->abfd, info->sec, (uint64_t) irel->r_offset, howto->name);
return TRUE;
}
/* Can't use local-exec relocations in shared libraries. */
if (r_type == R_ALPHA_GOTTPREL
- && (info->link_info->shared && !info->link_info->pie))
+ && bfd_link_dll (info->link_info))
return TRUE;
if (r_type == R_ALPHA_LITERAL)
/* Look for nice constant addresses. This includes the not-uncommon
special case of 0 for undefweak symbols. */
if ((info->h && info->h->root.root.type == bfd_link_hash_undefweak)
- || (!info->link_info->shared
+ || (!bfd_link_pic (info->link_info)
&& (symval >= (bfd_vma)-0x8000 || symval < 0x8000)))
{
disp = 0;
else
{
tsec_relocs = (_bfd_elf_link_read_relocs
- (info->abfd, info->tsec, NULL,
+ (info->abfd, info->tsec, NULL,
(Elf_Internal_Rela *) NULL,
info->link_info->keep_memory));
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. */
return 0;
}
if (tsec_free)
- free (tsec_free);
+ free (tsec_free);
}
/* We've now determined that we can skip an initial gp load. Verify
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 */
+ (_("%pB: %pA+%#" PRIx64 ": warning: "
+ "%s relocation against unexpected insn"),
+ abfd, info->sec, (uint64_t) irel->r_offset, "LITERAL");
return TRUE;
}
nrel.r_addend = irel->r_addend;
/* As we adjust, move the reloc to the end so that we don't
- break the LITERAL+LITUSE chain. */
+ break the LITERAL+LITUSE chain. */
if (urel < --erel)
- *urel-- = *erel;
+ *urel-- = *erel;
*erel = nrel;
changed_relocs = TRUE;
}
lit_reused = TRUE;
changed_contents = TRUE;
- /* Since all relocs must be optimized, don't bother swapping
- this relocation to the end. */
+ /* Since all relocs must be optimized, don't bother swapping
+ this relocation to the end. */
urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
R_ALPHA_GPRELLOW);
urel->r_addend = irel->r_addend;
/* If the symbol is local, and we've already committed to DF_STATIC_TLS,
then we might as well relax to IE. */
- else if (info->link_info->shared && !dynamic
+ else if (bfd_link_pic (info->link_info) && !dynamic
&& (info->link_info->flags & DF_STATIC_TLS))
;
/* Otherwise we must be building an executable to do anything. */
- else if (info->link_info->shared)
+ else if (bfd_link_pic (info->link_info))
return TRUE;
/* The TLSGD/TLSLDM relocation must be followed by a LITERAL and
/* Some compilers warn about a Boolean-looking expression being
used in a switch. The explicit cast silences them. */
- switch ((int) (!dynamic && !info->link_info->shared))
+ switch ((int) (!dynamic && !bfd_link_pic (info->link_info)))
{
case 1:
{
/* There's nothing to change, yet. */
*again = FALSE;
- if (link_info->relocatable
+ if (bfd_link_relocatable (link_info)
|| ((sec->flags & (SEC_CODE | SEC_RELOC | SEC_ALLOC))
!= (SEC_CODE | SEC_RELOC | SEC_ALLOC))
|| sec->reloc_count == 0)
htab->relax_trip = link_info->relax_trip;
/* This should never fail after the initial round, since the only error
- is GOT overflow, and relaxation only shrinks the table. However, we
+ is GOT overflow, and relaxation only shrinks the table. However, we
may only merge got sections during the first pass. If we merge
sections after we've created GPREL relocs, the GP for the merged
section backs up which may put the relocs out of range. */
/* Early exit for unhandled or unrelaxable relocations. */
if (r_type != R_ALPHA_LITERAL)
- {
- /* We complete everything except LITERAL in the first pass. */
+ {
+ /* We complete everything except LITERAL in the first pass. */
if (relax_pass != 0)
continue;
if (r_type == R_ALPHA_TLSLDM)
{
/* The symbol for a TLSLDM reloc is ignored. Collapse the
- reloc to the STN_UNDEF (0) symbol so that they all match. */
+ reloc to the STN_UNDEF (0) symbol so that they all match. */
r_symndx = STN_UNDEF;
}
else if (r_type != R_ALPHA_GOTDTPREL
- && r_type != R_ALPHA_GOTTPREL
+ && r_type != R_ALPHA_GOTTPREL
&& r_type != R_ALPHA_TLSGD)
continue;
}
{
symval = isym->st_value;
if (isym->st_shndx == SHN_UNDEF)
- continue;
+ continue;
else if (isym->st_shndx == SHN_ABS)
- info.tsec = bfd_abs_section_ptr;
+ info.tsec = bfd_abs_section_ptr;
else if (isym->st_shndx == SHN_COMMON)
- info.tsec = bfd_com_section_ptr;
+ info.tsec = bfd_com_section_ptr;
else
- info.tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+ info.tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
}
info.h = NULL;
r_type = ELF64_R_TYPE (rel->r_info);
if (r_type >= R_ALPHA_max)
{
- (*_bfd_error_handler)
- (_("%B: unknown relocation type %d"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: unsupported relocation type %#x"),
input_bfd, (int) r_type);
bfd_set_error (bfd_error_bad_value);
ret_val = FALSE;
BFD_ASSERT (is_alpha_elf (input_bfd));
/* Handle relocatable links with a smaller loop. */
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
return elf64_alpha_relocate_section_r (output_bfd, info, input_bfd,
input_section, contents, relocs,
local_syms, local_sections);
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)
- (_("%B: unknown relocation type %d"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: unsupported relocation type %#x"),
input_bfd, (int) r_type);
bfd_set_error (bfd_error_bad_value);
ret_val = FALSE;
undef_weak_ref = TRUE;
h = (struct alpha_elf_link_hash_entry *) hh;
- dynamic_symbol_p = alpha_elf_dynamic_symbol_p (&h->root, info);
+ dynamic_symbol_p = alpha_elf_dynamic_symbol_p (&h->root, info);
gotent = h->got_entries;
}
/* If the symbol has been forced local, output a
RELATIVE reloc, otherwise it will be handled in
finish_dynamic_symbol. */
- if (info->shared && !dynamic_symbol_p && !undef_weak_ref)
+ if (bfd_link_pic (info)
+ && !dynamic_symbol_p
+ && !undef_weak_ref)
elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
gotent->got_offset, 0,
R_ALPHA_RELATIVE, value);
case R_ALPHA_GPREL16:
case R_ALPHA_GPRELLOW:
if (dynamic_symbol_p)
- {
- (*_bfd_error_handler)
- (_("%B: gp-relative relocation against dynamic symbol %s"),
- input_bfd, h->root.root.root.string);
- ret_val = FALSE;
- }
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: gp-relative relocation against dynamic symbol %s"),
+ input_bfd, h->root.root.root.string);
+ ret_val = FALSE;
+ }
BFD_ASSERT(gp != 0);
value -= gp;
goto default_reloc;
case R_ALPHA_GPRELHIGH:
if (dynamic_symbol_p)
- {
- (*_bfd_error_handler)
- (_("%B: gp-relative relocation against dynamic symbol %s"),
- input_bfd, h->root.root.root.string);
- ret_val = FALSE;
- }
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: gp-relative relocation against dynamic symbol %s"),
+ input_bfd, h->root.root.root.string);
+ ret_val = FALSE;
+ }
BFD_ASSERT(gp != 0);
value -= gp;
value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
case R_ALPHA_BRADDR:
if (dynamic_symbol_p)
- {
- (*_bfd_error_handler)
- (_("%B: pc-relative relocation against dynamic symbol %s"),
- input_bfd, h->root.root.root.string);
- ret_val = FALSE;
- }
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: pc-relative relocation against dynamic symbol %s"),
+ input_bfd, h->root.root.root.string);
+ ret_val = FALSE;
+ }
/* The regular PC-relative stuff measures from the start of
the instruction rather than the end. */
value -= 4;
&& alpha_elf_tdata (sec->owner)->gotobj
&& gotobj != alpha_elf_tdata (sec->owner)->gotobj)
{
- (*_bfd_error_handler)
- (_("%B: change in gp: BRSGP %s"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: change in gp: BRSGP %s"),
input_bfd, h->root.root.root.string);
ret_val = FALSE;
}
switch (other & STO_ALPHA_STD_GPLOAD)
{
case STO_ALPHA_NOPV:
- break;
+ break;
case STO_ALPHA_STD_GPLOAD:
value += 8;
break;
else if (name[0] == 0)
name = bfd_section_name (input_bfd, sec);
}
- (*_bfd_error_handler)
- (_("%B: !samegp reloc against symbol without .prologue: %s"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: !samegp reloc against symbol without .prologue: %s"),
input_bfd, name);
ret_val = FALSE;
break;
else if (r_type == R_ALPHA_TPREL64)
{
BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
- if (!info->shared || info->pie)
+ if (!bfd_link_dll (info))
{
value -= tp_base;
goto default_reloc;
dynindx = 0;
dynaddend = value - dtp_base;
}
- else if (info->shared
+ else if (bfd_link_pic (info)
&& r_symndx != STN_UNDEF
&& (input_section->flags & SEC_ALLOC)
&& !undef_weak_ref
{
if (r_type == R_ALPHA_REFLONG)
{
- (*_bfd_error_handler)
- (_("%B: unhandled dynamic relocation against %s"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: unhandled dynamic relocation against %s"),
input_bfd,
h->root.root.root.string);
ret_val = FALSE;
case R_ALPHA_SREL32:
case R_ALPHA_SREL64:
if (dynamic_symbol_p)
- {
- (*_bfd_error_handler)
- (_("%B: pc-relative relocation against dynamic symbol %s"),
- input_bfd, h->root.root.root.string);
- ret_val = FALSE;
- }
- else if ((info->shared || info->pie) && undef_weak_ref)
- {
- (*_bfd_error_handler)
- (_("%B: pc-relative relocation against undefined weak symbol %s"),
- input_bfd, h->root.root.root.string);
- ret_val = FALSE;
- }
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: pc-relative relocation against dynamic symbol %s"),
+ input_bfd, h->root.root.root.string);
+ ret_val = FALSE;
+ }
+ else if (bfd_link_pic (info)
+ && undef_weak_ref)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: pc-relative relocation against undefined weak symbol %s"),
+ input_bfd, h->root.root.root.string);
+ ret_val = FALSE;
+ }
/* ??? .eh_frame references to discarded sections will be smashed
gotent->reloc_done = 1;
/* Note that the module index for the main program is 1. */
- bfd_put_64 (output_bfd, !info->shared && !dynamic_symbol_p,
+ bfd_put_64 (output_bfd,
+ !bfd_link_pic (info) && !dynamic_symbol_p,
sgot->contents + gotent->got_offset);
/* If the symbol has been forced local, output a
DTPMOD64 reloc, otherwise it will be handled in
finish_dynamic_symbol. */
- if (info->shared && !dynamic_symbol_p)
+ if (bfd_link_pic (info) && !dynamic_symbol_p)
elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
gotent->got_offset, 0,
R_ALPHA_DTPMOD64, 0);
else
{
BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
- value -= dtp_base;
+ value -= dtp_base;
}
bfd_put_64 (output_bfd, value,
sgot->contents + gotent->got_offset + 8);
case R_ALPHA_DTPRELLO:
case R_ALPHA_DTPREL16:
if (dynamic_symbol_p)
- {
- (*_bfd_error_handler)
- (_("%B: dtp-relative relocation against dynamic symbol %s"),
- input_bfd, h->root.root.root.string);
- ret_val = FALSE;
- }
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: dtp-relative relocation against dynamic symbol %s"),
+ input_bfd, h->root.root.root.string);
+ ret_val = FALSE;
+ }
BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
value -= dtp_base;
if (r_type == R_ALPHA_DTPRELHI)
case R_ALPHA_TPRELHI:
case R_ALPHA_TPRELLO:
case R_ALPHA_TPREL16:
- if (info->shared && !info->pie)
+ if (bfd_link_dll (info))
{
- (*_bfd_error_handler)
- (_("%B: TLS local exec code cannot be linked into shared objects"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: TLS local exec code cannot be linked into shared objects"),
input_bfd);
- ret_val = FALSE;
+ ret_val = FALSE;
}
else if (dynamic_symbol_p)
- {
- (*_bfd_error_handler)
- (_("%B: tp-relative relocation against dynamic symbol %s"),
- input_bfd, h->root.root.root.string);
- ret_val = FALSE;
- }
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: tp-relative relocation against dynamic symbol %s"),
+ input_bfd, h->root.root.root.string);
+ ret_val = FALSE;
+ }
BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
value -= tp_base;
if (r_type == R_ALPHA_TPRELHI)
BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
if (r_type == R_ALPHA_GOTDTPREL)
value -= dtp_base;
- else if (!info->shared)
+ else if (bfd_link_executable (info))
value -= tp_base;
else
{
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;
}
\f
static const struct bfd_elf_special_section elf64_alpha_special_sections[] =
{
- { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
+ { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
{ STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
- { NULL, 0, 0, 0, 0 }
+ { NULL, 0, 0, 0, 0 }
};
/* ECOFF swapping routines. These are used when dealing with the
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_size_dynamic_sections \
elf64_alpha_size_dynamic_sections
#define elf_backend_omit_section_dynsym \
- ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
+ _bfd_elf_omit_section_dynsym_all
#define elf_backend_relocate_section \
elf64_alpha_relocate_section
#define elf_backend_finish_dynamic_symbol \
#define elf_backend_can_gc_sections 1
#define elf_backend_gc_mark_hook elf64_alpha_gc_mark_hook
-#define elf_backend_gc_sweep_hook elf64_alpha_gc_sweep_hook
#define elf_backend_ecoff_debug_swap \
&elf64_alpha_ecoff_debug_swap
#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