/* Alpha specific support for 64-bit ELF
- Copyright (C) 1996-2017 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)
{
/* xgettext:c-format */
- _bfd_error_handler (_("%B: unrecognised Alpha reloc number: %d"),
+ _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
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,
/* 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 && ((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;
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 (bfd_link_relocatable (info))
- 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
/* 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->addend == gs->addend)
{
gs->use_count += gi->use_count;
- goto got_found;
+ 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
/* xgettext:c-format */
- (_("%B: .got subsegment exceeds 64K (size %d)"),
- i, alpha_elf_tdata (this_got)->total_got_size);
+ (_("%pB: .got subsegment exceeds 64K (size %d)"),
+ i, alpha_elf_tdata (this_got)->total_got_size);
return FALSE;
}
reloc_howto_type *howto = elf64_alpha_howto_table + r_type;
_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);
+ (_("%pB: %pA+%#" PRIx64 ": warning: "
+ "%s relocation against unexpected insn"),
+ info->abfd, info->sec, (uint64_t) irel->r_offset, howto->name);
return TRUE;
}
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;
}
if (tsec_free)
- free (tsec_free);
+ free (tsec_free);
}
/* We've now determined that we can skip an initial gp load. Verify
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: %A+0x%lx: warning: LITERAL relocation against unexpected insn"),
- abfd, info->sec,
- (unsigned long) irel->r_offset);
+ (_("%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;
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;
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: unknown relocation type %d"),
+ (_("%pB: unsupported relocation type %#x"),
input_bfd, (int) r_type);
bfd_set_error (bfd_error_bad_value);
ret_val = FALSE;
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: unknown relocation type %d"),
+ (_("%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;
}
case R_ALPHA_GPREL16:
case R_ALPHA_GPRELLOW:
if (dynamic_symbol_p)
- {
+ {
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: gp-relative relocation against dynamic symbol %s"),
- input_bfd, h->root.root.root.string);
- ret_val = FALSE;
- }
+ (_("%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
/* xgettext:c-format */
- (_("%B: gp-relative relocation against dynamic symbol %s"),
- input_bfd, h->root.root.root.string);
- ret_val = FALSE;
- }
+ (_("%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
/* xgettext:c-format */
- (_("%B: pc-relative relocation against dynamic symbol %s"),
- input_bfd, h->root.root.root.string);
- ret_val = FALSE;
- }
+ (_("%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;
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: change in gp: BRSGP %s"),
+ (_("%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;
}
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: !samegp reloc against symbol without .prologue: %s"),
+ (_("%pB: !samegp reloc against symbol without .prologue: %s"),
input_bfd, name);
ret_val = FALSE;
break;
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: unhandled dynamic relocation against %s"),
+ (_("%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
/* xgettext:c-format */
- (_("%B: pc-relative relocation against dynamic symbol %s"),
- input_bfd, h->root.root.root.string);
- ret_val = FALSE;
- }
+ (_("%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 */
- (_("%B: pc-relative relocation against undefined weak symbol %s"),
- input_bfd, h->root.root.root.string);
- ret_val = FALSE;
- }
+ (_("%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
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
/* xgettext:c-format */
- (_("%B: dtp-relative relocation against dynamic symbol %s"),
- input_bfd, h->root.root.root.string);
- ret_val = FALSE;
- }
+ (_("%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)
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: TLS local exec code cannot be linked into shared objects"),
+ (_("%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
/* xgettext:c-format */
- (_("%B: tp-relative relocation against dynamic symbol %s"),
- input_bfd, h->root.root.root.string);
- ret_val = FALSE;
- }
+ (_("%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)
\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
#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