/* Alpha specific support for 64-bit ELF
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@tamu.edu>.
-This file is part of BFD, the Binary File Descriptor library.
+ This file is part of BFD, the Binary File Descriptor library.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* We need a published ABI spec for this. Until one comes out, don't
assume this'll remain unchanged forever. */
#define ECOFF_64
#include "ecoffswap.h"
-static int alpha_elf_dynamic_symbol_p
- PARAMS((struct elf_link_hash_entry *, struct bfd_link_info *));
+static bfd_boolean alpha_elf_dynamic_symbol_p
+ PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *));
static struct bfd_hash_entry * elf64_alpha_link_hash_newfunc
- PARAMS((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
static struct bfd_link_hash_table * elf64_alpha_bfd_link_hash_table_create
- PARAMS((bfd *));
+ PARAMS ((bfd *));
static bfd_reloc_status_type elf64_alpha_reloc_nil
- PARAMS((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static bfd_reloc_status_type elf64_alpha_reloc_bad
- PARAMS((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static bfd_reloc_status_type elf64_alpha_do_reloc_gpdisp
- PARAMS((bfd *, bfd_vma, bfd_byte *, bfd_byte *));
+ PARAMS ((bfd *, bfd_vma, bfd_byte *, bfd_byte *));
static bfd_reloc_status_type elf64_alpha_reloc_gpdisp
- PARAMS((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static reloc_howto_type * elf64_alpha_bfd_reloc_type_lookup
- PARAMS((bfd *, bfd_reloc_code_real_type));
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
static void elf64_alpha_info_to_howto
- PARAMS((bfd *, arelent *, Elf_Internal_Rela *));
+ PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
static bfd_boolean elf64_alpha_mkobject
- PARAMS((bfd *));
+ PARAMS ((bfd *));
static bfd_boolean elf64_alpha_object_p
- PARAMS((bfd *));
+ PARAMS ((bfd *));
static bfd_boolean elf64_alpha_section_from_shdr
- PARAMS((bfd *, Elf_Internal_Shdr *, const char *));
+ PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
static bfd_boolean elf64_alpha_section_flags
- PARAMS((flagword *, Elf_Internal_Shdr *));
+ PARAMS ((flagword *, Elf_Internal_Shdr *));
static bfd_boolean elf64_alpha_fake_sections
- PARAMS((bfd *, Elf_Internal_Shdr *, asection *));
+ PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
static bfd_boolean elf64_alpha_create_got_section
- PARAMS((bfd *, struct bfd_link_info *));
+ PARAMS ((bfd *, struct bfd_link_info *));
static bfd_boolean elf64_alpha_create_dynamic_sections
- PARAMS((bfd *, struct bfd_link_info *));
+ PARAMS ((bfd *, struct bfd_link_info *));
static bfd_boolean elf64_alpha_read_ecoff_info
- PARAMS((bfd *, asection *, struct ecoff_debug_info *));
+ PARAMS ((bfd *, asection *, struct ecoff_debug_info *));
static bfd_boolean elf64_alpha_is_local_label_name
- PARAMS((bfd *, const char *));
+ PARAMS ((bfd *, const char *));
static bfd_boolean elf64_alpha_find_nearest_line
- PARAMS((bfd *, asection *, asymbol **, bfd_vma, const char **,
- const char **, unsigned int *));
+ PARAMS ((bfd *, asection *, asymbol **, bfd_vma, const char **,
+ const char **, unsigned int *));
#if defined(__STDC__) || defined(ALMOST_STDC)
struct alpha_elf_link_hash_entry;
#endif
static bfd_boolean elf64_alpha_output_extsym
- PARAMS((struct alpha_elf_link_hash_entry *, PTR));
+ PARAMS ((struct alpha_elf_link_hash_entry *, PTR));
static bfd_boolean elf64_alpha_can_merge_gots
- PARAMS((bfd *, bfd *));
+ PARAMS ((bfd *, bfd *));
static void elf64_alpha_merge_gots
- PARAMS((bfd *, bfd *));
+ PARAMS ((bfd *, bfd *));
static bfd_boolean elf64_alpha_calc_got_offsets_for_symbol
PARAMS ((struct alpha_elf_link_hash_entry *, PTR));
static void elf64_alpha_calc_got_offsets
PARAMS ((bfd *, struct alpha_elf_link_hash_entry *, unsigned long,
unsigned long, bfd_vma));
static bfd_boolean elf64_alpha_check_relocs
- PARAMS((bfd *, struct bfd_link_info *, asection *sec,
+ PARAMS ((bfd *, struct bfd_link_info *, asection *sec,
const Elf_Internal_Rela *));
static bfd_boolean elf64_alpha_adjust_dynamic_symbol
- PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *));
+ PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
static bfd_boolean elf64_alpha_size_dynamic_sections
- PARAMS((bfd *, struct bfd_link_info *));
+ PARAMS ((bfd *, struct bfd_link_info *));
+static void elf64_alpha_emit_dynrel
+ PARAMS ((bfd *, struct bfd_link_info *, asection *, asection *,
+ bfd_vma, long, long, bfd_vma));
static bfd_boolean elf64_alpha_relocate_section_r
- PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
- Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
static bfd_boolean elf64_alpha_relocate_section
- PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
static bfd_boolean elf64_alpha_finish_dynamic_symbol
- PARAMS((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
- Elf_Internal_Sym *));
+ PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
+ Elf_Internal_Sym *));
static bfd_boolean elf64_alpha_finish_dynamic_sections
- PARAMS((bfd *, struct bfd_link_info *));
+ PARAMS ((bfd *, struct bfd_link_info *));
static bfd_boolean elf64_alpha_final_link
- PARAMS((bfd *, struct bfd_link_info *));
+ PARAMS ((bfd *, struct bfd_link_info *));
static bfd_boolean elf64_alpha_merge_ind_symbols
- PARAMS((struct alpha_elf_link_hash_entry *, PTR));
+ PARAMS ((struct alpha_elf_link_hash_entry *, PTR));
static Elf_Internal_Rela * elf64_alpha_find_reloc_at_ofs
PARAMS ((Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_vma, int));
static enum elf_reloc_type_class elf64_alpha_reloc_type_class
#define ALPHA_ELF_LINK_HASH_LU_TLSLDM 0x20
#define ALPHA_ELF_LINK_HASH_LU_FUNC 0x38
#define ALPHA_ELF_LINK_HASH_TLS_IE 0x40
+#define ALPHA_ELF_LINK_HASH_PLT_LOC 0x80
+
+ /* Used to undo the localization of a plt symbol. */
+ asection *plt_old_section;
+ bfd_vma plt_old_value;
/* Used to implement multiple .got subsections. */
struct alpha_elf_got_entry
{
struct alpha_elf_got_entry *next;
- /* which .got subsection? */
+ /* Which .got subsection? */
bfd *gotobj;
- /* the addend in effect for this entry. */
+ /* The addend in effect for this entry. */
bfd_vma addend;
- /* the .got offset for this entry. */
+ /* The .got offset for this entry. */
int got_offset;
/* How many references to this entry? */
unsigned char reloc_xlated;
} *got_entries;
- /* used to count non-got, non-plt relocations for delayed sizing
+ /* Used to count non-got, non-plt relocations for delayed sizing
of relocation sections. */
struct alpha_elf_reloc_entry
{
struct alpha_elf_reloc_entry *next;
- /* which .reloc section? */
+ /* Which .reloc section? */
asection *srel;
- /* what kind of relocation? */
+ /* What kind of relocation? */
unsigned int rtype;
- /* is this against read-only section? */
+ /* Is this against read-only section? */
unsigned int reltext : 1;
- /* how many did we find? */
+ /* How many did we find? */
unsigned long count;
} *reloc_entries;
};
#define alpha_elf_sym_hashes(abfd) \
((struct alpha_elf_link_hash_entry **)elf_sym_hashes(abfd))
-/* Should we do dynamic things to this symbol? */
+/* Should we do dynamic things to this symbol? This differs from the
+ generic version in that we never need to consider function pointer
+ equality wrt PLT entries -- we don't create a PLT entry if a symbol's
+ address is ever taken. */
-static int
+static inline bfd_boolean
alpha_elf_dynamic_symbol_p (h, info)
struct elf_link_hash_entry *h;
struct bfd_link_info *info;
{
- if (h == NULL)
- return FALSE;
-
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
- if (h->dynindx == -1)
- return FALSE;
-
- if (h->root.type == bfd_link_hash_undefweak
- || h->root.type == bfd_link_hash_defweak)
- return TRUE;
-
- switch (ELF_ST_VISIBILITY (h->other))
- {
- case STV_DEFAULT:
- break;
- case STV_HIDDEN:
- case STV_INTERNAL:
- return FALSE;
- case STV_PROTECTED:
- if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
- return FALSE;
- break;
- }
-
- if ((info->shared && !info->symbolic)
- || ((h->elf_link_hash_flags
- & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))
- == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)))
- return TRUE;
-
- return FALSE;
+ return _bfd_elf_dynamic_symbol_p (h, info, 0);
}
/* Create an entry in a Alpha ELF linker hash table. */
elf64_alpha_object_p (abfd)
bfd *abfd;
{
- /* Allocate our special target data. */
- struct alpha_elf_obj_tdata *new_tdata;
- bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata);
- new_tdata = bfd_zalloc (abfd, amt);
- if (new_tdata == NULL)
- return FALSE;
- new_tdata->root = *abfd->tdata.elf_obj_data;
- abfd->tdata.any = new_tdata;
-
/* Set the right machine number for an Alpha ELF file. */
return bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0);
}
(r_type == R_ALPHA_TLSGD || r_type == R_ALPHA_TLSLDM ? 16 : 8)
/* This is PT_TLS segment p_vaddr. */
-#define alpha_get_dtprel_base(tlss) \
- ((tlss)->start)
+#define alpha_get_dtprel_base(info) \
+ (elf_hash_table (info)->tls_sec->vma)
/* Main program TLS (whose template starts at PT_TLS p_vaddr)
is assigned offset round(16, PT_TLS p_align). */
-#define alpha_get_tprel_base(tlss) \
- ((tlss)->start - align_power ((bfd_vma) 16, (tlss)->align))
+#define alpha_get_tprel_base(info) \
+ (elf_hash_table (info)->tls_sec->vma \
+ - align_power ((bfd_vma) 16, \
+ elf_hash_table (info)->tls_sec->alignment_power))
\f
/* These functions do relaxation for Alpha ELF.
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *relocs, *relend;
struct bfd_link_info *link_info;
- struct elf_link_tls_segment *tls_segment;
bfd_vma gp;
bfd *gotobj;
asection *tsec;
static bfd_boolean elf64_alpha_relax_tls_get_addr
PARAMS((struct alpha_relax_info *info, bfd_vma symval,
Elf_Internal_Rela *irel, bfd_boolean));
-static struct elf_link_tls_segment *elf64_alpha_relax_find_tls_segment
- PARAMS((struct alpha_relax_info *, struct elf_link_tls_segment *));
static bfd_boolean elf64_alpha_relax_section
PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
bfd_boolean *again));
}
else
{
- tsec_relocs = (_bfd_elf64_link_read_relocs
+ tsec_relocs = (_bfd_elf_link_read_relocs
(info->abfd, info->tsec, (PTR) NULL,
(Elf_Internal_Rela *) NULL,
info->link_info->keep_memory));
{
bfd_vma dtp_base, tp_base;
- BFD_ASSERT (info->tls_segment != NULL);
- dtp_base = alpha_get_dtprel_base (info->tls_segment);
- tp_base = alpha_get_tprel_base (info->tls_segment);
+ BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL);
+ dtp_base = alpha_get_dtprel_base (info->link_info);
+ tp_base = alpha_get_tprel_base (info->link_info);
disp = symval - (r_type == R_ALPHA_GOTDTPREL ? dtp_base : tp_base);
}
bfd_put_32 (info->abfd, (bfd_vma) insn, info->contents + irel->r_offset);
info->changed_contents = TRUE;
+ /* Reduce the use count on this got entry by one, possibly
+ eliminating it. */
+ if (--info->gotent->use_count == 0)
+ {
+ int sz = alpha_got_entry_size (r_type);
+ alpha_elf_tdata (info->gotobj)->total_got_size -= sz;
+ if (!info->h)
+ alpha_elf_tdata (info->gotobj)->local_got_size -= sz;
+ }
+
+ /* Smash the existing GOT relocation for its 16-bit immediate pair. */
switch (r_type)
{
case R_ALPHA_LITERAL:
irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), r_type);
info->changed_relocs = TRUE;
- /* Reduce the use count on this got entry by one, possibly
- eliminating it. */
- if (--info->gotent->use_count == 0)
- {
- int sz = alpha_got_entry_size (r_type);
- alpha_elf_tdata (info->gotobj)->total_got_size -= sz;
- if (!info->h)
- alpha_elf_tdata (info->gotobj)->local_got_size -= sz;
- }
-
/* ??? Search forward through this basic block looking for insns
that use the target register. Stop after an insn modifying the
register is seen, or after a branch or call.
bfd_byte *pos[5];
unsigned int insn;
Elf_Internal_Rela *gpdisp, *hint;
- bfd_boolean dynamic, use_gottprel;
+ bfd_boolean dynamic, use_gottprel, pos1_unusable;
+ unsigned long new_symndx;
dynamic = alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info);
- /* ??? For LD relaxation, we need a symbol referencing the beginning
- of the TLS segment. */
- if (!is_gd)
- return TRUE;
-
/* If a TLS symbol is accessed using IE at least once, there is no point
to use dynamic model for it. */
if (is_gd && info->h && (info->h->flags & ALPHA_ELF_LINK_HASH_TLS_IE))
pos[2] = info->contents + irel[2].r_offset;
pos[3] = info->contents + gpdisp->r_offset;
pos[4] = pos[3] + gpdisp->r_addend;
+ pos1_unusable = FALSE;
- /* Only positions 0 and 1 are allowed to be out of order. */
- if (pos[1] < pos[0])
+ /* Generally, the positions are not allowed to be out of order, lest the
+ modified insn sequence have different register lifetimes. We can make
+ an exception when pos 1 is adjacent to pos 0. */
+ if (pos[1] + 4 == pos[0])
{
bfd_byte *tmp = pos[0];
pos[0] = pos[1];
pos[1] = tmp;
}
- if (pos[1] >= pos[2] || pos[2] >= pos[3] || pos[3] >= pos[4])
+ else if (pos[1] < pos[0])
+ pos1_unusable = TRUE;
+ if (pos[1] >= pos[2] || pos[2] >= pos[3])
return TRUE;
/* Reduce the use count on the LITERAL relocation. Do this before we
as appropriate. */
use_gottprel = FALSE;
+ new_symndx = is_gd ? ELF64_R_SYM (irel->r_info) : 0;
switch (!dynamic && !info->link_info->shared)
{
case 1:
bfd_vma tp_base;
bfd_signed_vma disp;
- BFD_ASSERT (info->tls_segment != NULL);
- tp_base = alpha_get_tprel_base (info->tls_segment);
+ BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL);
+ tp_base = alpha_get_tprel_base (info->link_info);
disp = symval - tp_base;
if (disp >= -0x8000 && disp < 0x8000)
bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]);
irel[0].r_offset = pos[0] - info->contents;
- irel[0].r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
- R_ALPHA_TPREL16);
+ irel[0].r_info = ELF64_R_INFO (new_symndx, R_ALPHA_TPREL16);
irel[1].r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
break;
}
else if (disp >= -(bfd_signed_vma) 0x80000000
- && disp < (bfd_signed_vma) 0x7fff8000)
+ && disp < (bfd_signed_vma) 0x7fff8000
+ && !pos1_unusable)
{
insn = (OP_LDAH << 26) | (16 << 21) | (31 << 16);
bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]);
bfd_put_32 (info->abfd, (bfd_vma) insn, pos[1]);
irel[0].r_offset = pos[0] - info->contents;
- irel[0].r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
- R_ALPHA_TPRELHI);
+ irel[0].r_info = ELF64_R_INFO (new_symndx, R_ALPHA_TPRELHI);
irel[1].r_offset = pos[1] - info->contents;
- irel[1].r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
- R_ALPHA_TPRELLO);
+ irel[1].r_info = ELF64_R_INFO (new_symndx, R_ALPHA_TPRELLO);
break;
}
}
bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]);
irel[0].r_offset = pos[0] - info->contents;
- irel[0].r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
- R_ALPHA_GOTTPREL);
+ irel[0].r_info = ELF64_R_INFO (new_symndx, R_ALPHA_GOTTPREL);
irel[1].r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
break;
}
return TRUE;
}
-static struct elf_link_tls_segment *
-elf64_alpha_relax_find_tls_segment (info, seg)
- struct alpha_relax_info *info;
- struct elf_link_tls_segment *seg;
-{
- bfd *output_bfd = info->sec->output_section->owner;
- asection *o;
- unsigned int align;
- bfd_vma base, end;
-
- for (o = output_bfd->sections; o ; o = o->next)
- if ((o->flags & SEC_THREAD_LOCAL) != 0
- && (o->flags & SEC_LOAD) != 0)
- break;
- if (!o)
- return NULL;
-
- base = o->vma;
- align = 0;
-
- do
- {
- bfd_vma size;
-
- if (bfd_get_section_alignment (output_bfd, o) > align)
- align = bfd_get_section_alignment (output_bfd, o);
-
- size = o->_raw_size;
- if (size == 0 && (o->flags & SEC_HAS_CONTENTS) == 0)
- {
- struct bfd_link_order *lo;
- for (lo = o->link_order_head; lo ; lo = lo->next)
- if (size < lo->offset + lo->size)
- size = lo->offset + lo->size;
- }
- end = o->vma + size;
- o = o->next;
- }
- while (o && (o->flags & SEC_THREAD_LOCAL));
-
- seg->start = base;
- seg->size = end - base;
- seg->align = align;
-
- return seg;
-}
-
static bfd_boolean
elf64_alpha_relax_section (abfd, sec, link_info, again)
bfd *abfd;
Elf_Internal_Sym *isymbuf = NULL;
struct alpha_elf_got_entry **local_got_entries;
struct alpha_relax_info info;
- struct elf_link_tls_segment tls_segment;
/* We are not currently changing any sizes, so only one pass. */
*again = FALSE;
- if (link_info->relocateable
+ if (link_info->relocatable
|| (sec->flags & SEC_RELOC) == 0
|| sec->reloc_count == 0)
return TRUE;
local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
/* Load the relocations for this section. */
- internal_relocs = (_bfd_elf64_link_read_relocs
+ internal_relocs = (_bfd_elf_link_read_relocs
(abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
link_info->keep_memory));
if (internal_relocs == NULL)
goto error_return;
}
- /* Compute the TLS segment information. The version normally found in
- elf_hash_table (link_info)->tls_segment isn't built until final_link.
- ??? Probably should look into extracting this into a common function. */
- info.tls_segment = elf64_alpha_relax_find_tls_segment (&info, &tls_segment);
-
for (irel = internal_relocs; irel < irelend; irel++)
{
bfd_vma symval;
struct alpha_elf_got_entry *gotent;
unsigned long r_type = ELF64_R_TYPE (irel->r_info);
+ unsigned long r_symndx = ELF64_R_SYM (irel->r_info);
/* Early exit for unhandled or unrelaxable relocations. */
switch (r_type)
case R_ALPHA_GOTDTPREL:
case R_ALPHA_GOTTPREL:
case R_ALPHA_TLSGD:
+ break;
+
case R_ALPHA_TLSLDM:
+ /* The symbol for a TLSLDM reloc is ignored. Collapse the
+ reloc to the 0 symbol so that they all match. */
+ r_symndx = 0;
break;
+
default:
continue;
}
/* Get the value of the symbol referred to by the reloc. */
- if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
+ if (r_symndx < symtab_hdr->sh_info)
{
/* A local symbol. */
Elf_Internal_Sym *isym;
goto error_return;
}
- isym = isymbuf + ELF64_R_SYM (irel->r_info);
- if (isym->st_shndx == SHN_UNDEF)
- continue;
- else if (isym->st_shndx == SHN_ABS)
- info.tsec = bfd_abs_section_ptr;
- else if (isym->st_shndx == SHN_COMMON)
- info.tsec = bfd_com_section_ptr;
+ isym = isymbuf + r_symndx;
+
+ /* Given the symbol for a TLSLDM reloc is ignored, this also
+ means forcing the symbol value to the tp base. */
+ if (r_type == R_ALPHA_TLSLDM)
+ {
+ info.tsec = bfd_abs_section_ptr;
+ symval = alpha_get_tprel_base (info.link_info);
+ }
else
- info.tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+ {
+ symval = isym->st_value;
+ if (isym->st_shndx == SHN_UNDEF)
+ continue;
+ else if (isym->st_shndx == SHN_ABS)
+ info.tsec = bfd_abs_section_ptr;
+ else if (isym->st_shndx == SHN_COMMON)
+ info.tsec = bfd_com_section_ptr;
+ else
+ info.tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+ }
info.h = NULL;
info.other = isym->st_other;
- info.first_gotent = &local_got_entries[ELF64_R_SYM(irel->r_info)];
- symval = isym->st_value;
+ if (local_got_entries)
+ info.first_gotent = &local_got_entries[r_symndx];
+ else
+ {
+ info.first_gotent = &info.gotent;
+ info.gotent = NULL;
+ }
}
else
{
unsigned long indx;
struct alpha_elf_link_hash_entry *h;
- indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info;
+ indx = r_symndx - symtab_hdr->sh_info;
h = alpha_elf_sym_hashes (abfd)[indx];
BFD_ASSERT (h != NULL);
/* If the symbol isn't defined in the current module, again
we can't do anything. */
if (!(h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
- continue;
+ {
+ /* Except for TLSGD relocs, which can sometimes be
+ relaxed to GOTTPREL relocs. */
+ if (r_type != R_ALPHA_TLSGD)
+ continue;
+ info.tsec = bfd_abs_section_ptr;
+ symval = 0;
+ }
+ else
+ {
+ info.tsec = h->root.root.u.def.section;
+ symval = h->root.root.u.def.value;
+ }
info.h = h;
- info.tsec = h->root.root.u.def.section;
info.other = h->root.other;
info.first_gotent = &h->got_entries;
- symval = h->root.root.u.def.value;
}
/* Search for the got entry to be used by this relocation. */
bfd_vma *valp;
{
if (sym->st_shndx == SHN_COMMON
- && !info->relocateable
+ && !info->relocatable
&& sym->st_size <= elf_gp_size (abfd))
{
/* Common symbols less than or equal to -G nn bytes are
{
asection *s;
- if (bfd_get_section_by_name (abfd, ".got"))
- return TRUE;
+ if ((s = bfd_get_section_by_name (abfd, ".got")))
+ {
+ /* Check for a non-linker created .got? */
+ if (alpha_elf_tdata (abfd)->got == NULL)
+ alpha_elf_tdata (abfd)->got = s;
+ return TRUE;
+ }
s = bfd_make_section (abfd, ".got");
if (s == NULL
bfd_boolean got_created;
bfd_size_type amt;
- if (info->relocateable)
+ if (info->relocatable)
return TRUE;
dynobj = elf_hash_table(info)->dynobj;
this may help reduce memory usage and processing time later. */
maybe_dynamic = FALSE;
if (h && ((info->shared
- && (!info->symbolic || info->allow_shlib_undefined))
+ && (!info->symbolic || info->unresolved_syms_in_shared_libs == RM_IGNORE))
|| ! (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
|| h->root.root.type == bfd_link_hash_defweak))
maybe_dynamic = TRUE;
need = NEED_DYNREL;
break;
- case R_ALPHA_TLSGD:
case R_ALPHA_TLSLDM:
+ /* The symbol for a TLSLDM reloc is ignored. Collapse the
+ reloc to the 0 symbol so that they all match. */
+ r_symndx = 0;
+ h = 0;
+ maybe_dynamic = FALSE;
+ /* FALLTHRU */
+
+ case R_ALPHA_TLSGD:
case R_ALPHA_GOTDTPREL:
need = NEED_GOT | NEED_GOT_ENTRY;
break;
if (! info->shared
&& h->root.type != bfd_link_hash_defweak)
{
+ ah->plt_old_section = h->root.u.def.section;
+ ah->plt_old_value = h->root.u.def.value;
+ ah->flags |= ALPHA_ELF_LINK_HASH_PLT_LOC;
h->root.u.def.section = s;
h->root.u.def.value = h->plt.offset;
}
struct alpha_elf_link_hash_entry *h;
PTR arg ATTRIBUTE_UNUSED;
{
+ bfd_boolean result = TRUE;
struct alpha_elf_got_entry *gotent;
if (h->root.root.type == bfd_link_hash_warning)
for (gotent = h->got_entries; gotent; gotent = gotent->next)
if (gotent->use_count > 0)
{
- bfd_size_type *plge
- = &alpha_elf_tdata (gotent->gotobj)->got->_raw_size;
+ struct alpha_elf_obj_tdata *td;
+ bfd_size_type *plge;
+ td = alpha_elf_tdata (gotent->gotobj);
+ if (td == NULL)
+ {
+ _bfd_error_handler (_("Symbol %s has no GOT subsection for offset 0x%x"),
+ h->root.root.root.string, gotent->got_offset);
+ result = FALSE;
+ continue;
+ }
+ plge = &td->got->_raw_size;
gotent->got_offset = *plge;
*plge += alpha_got_entry_size (gotent->reloc_type);
}
- return TRUE;
+ return result;
}
static void
if (this_got == NULL)
continue;
- /* We are assuming no merging has yet ocurred. */
+ /* 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)
{
h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
h->root.plt.offset = -1;
+
+ /* Undo the definition frobbing begun in adjust_dynamic_symbol. */
+ if (h->flags & ALPHA_ELF_LINK_HASH_PLT_LOC)
+ {
+ h->root.root.u.def.section = h->plt_old_section;
+ h->root.root.u.def.value = h->plt_old_value;
+ h->flags &= ~ALPHA_ELF_LINK_HASH_PLT_LOC;
+ }
}
return TRUE;
{
bfd *i;
- if (info->relocateable)
+ if (info->relocatable)
return TRUE;
/* First, take care of the indirect symbols created by versioning. */
case R_ALPHA_TLSLDM:
return shared;
case R_ALPHA_LITERAL:
+ case R_ALPHA_GOTTPREL:
return dynamic || shared;
case R_ALPHA_GOTDTPREL:
- case R_ALPHA_GOTTPREL:
return dynamic;
/* May appear in data sections. */
case R_ALPHA_REFLONG:
case R_ALPHA_REFQUAD:
- return dynamic || shared;
- case R_ALPHA_SREL64:
case R_ALPHA_TPREL64:
- return dynamic;
+ return dynamic || shared;
/* Everything else is illegal. We'll issue an error during
relocate_section. */
if (elf_hash_table (info)->dynamic_sections_created)
{
/* Set the contents of the .interp section to the interpreter. */
- if (!info->shared)
+ if (info->executable)
{
s = bfd_get_section_by_name (dynobj, ".interp");
BFD_ASSERT (s != NULL);
#define add_dynamic_entry(TAG, VAL) \
bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
- if (!info->shared)
+ if (info->executable)
{
if (!add_dynamic_entry (DT_DEBUG, 0))
return FALSE;
return TRUE;
}
+/* Emit a dynamic relocation for (DYNINDX, RTYPE, ADDEND) at (SEC, OFFSET)
+ into the next available slot in SREL. */
+
+static void
+elf64_alpha_emit_dynrel (abfd, info, sec, srel, offset, dynindx, rtype, addend)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec, *srel;
+ bfd_vma offset, addend;
+ long dynindx, rtype;
+{
+ Elf_Internal_Rela outrel;
+ bfd_byte *loc;
+
+ BFD_ASSERT (srel != NULL);
+
+ outrel.r_info = ELF64_R_INFO (dynindx, rtype);
+ outrel.r_addend = addend;
+
+ offset = _bfd_elf_section_offset (abfd, info, sec, offset);
+ if ((offset | 1) != (bfd_vma) -1)
+ outrel.r_offset = sec->output_section->vma + sec->output_offset + offset;
+ else
+ memset (&outrel, 0, sizeof (outrel));
+
+ loc = srel->contents;
+ loc += srel->reloc_count++ * sizeof (Elf64_External_Rela);
+ bfd_elf64_swap_reloca_out (abfd, &outrel, loc);
+ BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
+ <= srel->_cooked_size);
+}
+
/* Relocate an Alpha ELF section for a relocatable link.
We don't have to change anything unless the reloc is against a section
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
- struct elf_link_tls_segment *tls_segment;
asection *sgot, *srel, *srelgot;
bfd *dynobj, *gotobj;
bfd_vma gp, tp_base, dtp_base;
const char *section_name;
/* Handle relocatable links with a smaller loop. */
- if (info->relocateable)
+ if (info->relocatable)
return elf64_alpha_relocate_section_r (output_bfd, info, input_bfd,
input_section, contents, relocs,
local_syms, local_sections);
local_got_entries = alpha_elf_tdata(input_bfd)->local_got_entries;
- tls_segment = elf_hash_table (info)->tls_segment;
- if (tls_segment)
+ if (elf_hash_table (info)->tls_sec != NULL)
{
- dtp_base = alpha_get_dtprel_base (tls_segment);
- tp_base = alpha_get_tprel_base (tls_segment);
+ dtp_base = alpha_get_dtprel_base (info);
+ tp_base = alpha_get_tprel_base (info);
}
else
dtp_base = tp_base = 0;
howto = elf64_alpha_howto_table + r_type;
r_symndx = ELF64_R_SYM(rel->r_info);
+ /* The symbol for a TLSLDM reloc is ignored. Collapse the
+ reloc to the 0 symbol so that they all match. */
+ if (r_type == R_ALPHA_TLSLDM)
+ r_symndx = 0;
+
if (r_symndx < symtab_hdr->sh_info)
{
+ asection *msec;
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
- value = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
+ msec = sec;
+ value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel);
+
+ /* If this is a tp-relative relocation against sym 0,
+ this is hackery from relax_section. Force the value to
+ be the tls base. */
+ if (r_symndx == 0
+ && (r_type == R_ALPHA_TLSLDM
+ || r_type == R_ALPHA_GOTTPREL
+ || r_type == R_ALPHA_TPREL64
+ || r_type == R_ALPHA_TPRELHI
+ || r_type == R_ALPHA_TPRELLO
+ || r_type == R_ALPHA_TPREL16))
+ value = tp_base;
if (local_got_entries)
gotent = local_got_entries[r_symndx];
unless it has been done already. */
if ((sec->flags & SEC_MERGE)
&& ELF_ST_TYPE (sym->st_info) == STT_SECTION
- && (elf_section_data (sec)->sec_info_type
- == ELF_INFO_TYPE_MERGE)
+ && sec->sec_info_type == ELF_INFO_TYPE_MERGE
&& gotent
&& !gotent->reloc_xlated)
{
struct alpha_elf_got_entry *ent;
- asection *msec;
for (ent = gotent; ent; ent = ent->next)
{
}
else
{
- h = alpha_elf_sym_hashes (input_bfd)[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;
+ bfd_boolean warned;
+ bfd_boolean unresolved_reloc;
+ struct elf_link_hash_entry *hh;
+
+ RELOC_FOR_GLOBAL_SYMBOL (hh,
+ (struct elf_link_hash_entry *) alpha_elf_sym_hashes (input_bfd),
+ r_symndx, symtab_hdr, value,
+ sec, unresolved_reloc, info,
+ warned);
+
+ if (warned)
+ continue;
- value = 0;
- if (h->root.root.type == bfd_link_hash_defined
- || h->root.root.type == bfd_link_hash_defweak)
- {
- sec = h->root.root.u.def.section;
-
- /* Detect the cases that sym_sec->output_section is
- expected to be NULL -- all cases in which the symbol
- is defined in another shared module. This includes
- PLT relocs for which we've created a PLT entry and
- other relocs for which we're prepared to create
- dynamic relocations. */
- /* ??? Just accept it NULL and continue. */
-
- if (sec->output_section != NULL)
- value = (h->root.root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
- }
- else if (h->root.root.type == bfd_link_hash_undefweak)
+ if (value == 0
+ && ! unresolved_reloc
+ && hh->root.type == bfd_link_hash_undefweak)
undef_weak_ref = TRUE;
- else if (info->shared
- && (!info->symbolic || info->allow_shlib_undefined)
- && !info->no_undefined
- && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
- ;
- else
- {
- if (!((*info->callbacks->undefined_symbol)
- (info, h->root.root.root.string, input_bfd,
- input_section, rel->r_offset,
- (!info->shared || info->no_undefined
- || ELF_ST_VISIBILITY (h->root.other)))))
- return FALSE;
- ret_val = FALSE;
- continue;
- }
+ h = (struct alpha_elf_link_hash_entry *) hh;
dynamic_symbol_p = alpha_elf_dynamic_symbol_p (&h->root, info);
gotent = h->got_entries;
}
RELATIVE reloc, otherwise it will be handled in
finish_dynamic_symbol. */
if (info->shared && !dynamic_symbol_p)
- {
- Elf_Internal_Rela outrel;
- bfd_byte *loc;
-
- BFD_ASSERT(srelgot != NULL);
-
- outrel.r_offset = (sgot->output_section->vma
- + sgot->output_offset
- + gotent->got_offset);
- outrel.r_info = ELF64_R_INFO (0, R_ALPHA_RELATIVE);
- outrel.r_addend = value;
-
- loc = srelgot->contents;
- loc += srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
- bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
- BFD_ASSERT (sizeof (Elf64_External_Rela)
- * srelgot->reloc_count
- <= srelgot->_cooked_size);
- }
+ elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
+ gotent->got_offset, 0,
+ R_ALPHA_RELATIVE, value);
}
value = (sgot->output_section->vma
value -= gp;
goto default_reloc;
- case R_ALPHA_GPREL16:
case R_ALPHA_GPREL32:
+ /* If the target section was a removed linkonce section,
+ r_symndx will be zero. In this case, assume that the
+ switch will not be used, so don't fill it in. If we
+ do nothing here, we'll get relocation truncated messages,
+ due to the placement of the application above 4GB. */
+ if (r_symndx == 0)
+ {
+ r = bfd_reloc_ok;
+ break;
+ }
+ /* FALLTHRU */
+
+ case R_ALPHA_GPREL16:
case R_ALPHA_GPRELLOW:
if (dynamic_symbol_p)
{
case R_ALPHA_DTPREL64:
case R_ALPHA_TPREL64:
{
- Elf_Internal_Rela outrel;
- bfd_byte *loc;
+ long dynindx, dyntype = r_type;
+ bfd_vma dynaddend;
/* Careful here to remember RELATIVE relocations for global
variables for symbolic shared objects. */
if (dynamic_symbol_p)
{
BFD_ASSERT(h->root.dynindx != -1);
- outrel.r_info = ELF64_R_INFO (h->root.dynindx, r_type);
- outrel.r_addend = addend;
+ dynindx = h->root.dynindx;
+ dynaddend = addend;
addend = 0, value = 0;
}
else if (r_type == R_ALPHA_DTPREL64)
{
- BFD_ASSERT(tls_segment != NULL);
+ BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
value -= dtp_base;
goto default_reloc;
}
else if (r_type == R_ALPHA_TPREL64)
{
- BFD_ASSERT(tls_segment != NULL);
- value -= dtp_base;
- goto default_reloc;
+ BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
+ if (!info->shared)
+ {
+ value -= tp_base;
+ goto default_reloc;
+ }
+ dynindx = 0;
+ dynaddend = value - dtp_base;
}
else if (info->shared
&& r_symndx != 0
h->root.root.root.string);
ret_val = FALSE;
}
- outrel.r_info = ELF64_R_INFO (0, R_ALPHA_RELATIVE);
- outrel.r_addend = value;
+ dynindx = 0;
+ dyntype = R_ALPHA_RELATIVE;
+ dynaddend = value;
}
else
goto default_reloc;
- BFD_ASSERT(srel != NULL);
-
- outrel.r_offset =
- _bfd_elf_section_offset (output_bfd, info, input_section,
- rel->r_offset);
- if ((outrel.r_offset | 1) != (bfd_vma) -1)
- outrel.r_offset += (input_section->output_section->vma
- + input_section->output_offset);
- else
- memset (&outrel, 0, sizeof outrel);
-
- loc = srel->contents;
- loc += srel->reloc_count++ * sizeof (Elf64_External_Rela);
- bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
- BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
- <= srel->_cooked_size);
+ elf64_alpha_emit_dynrel (output_bfd, info, input_section,
+ srel, rel->r_offset, dynindx,
+ dyntype, dynaddend);
}
goto default_reloc;
DTPMOD64 reloc, otherwise it will be handled in
finish_dynamic_symbol. */
if (info->shared && !dynamic_symbol_p)
- {
- Elf_Internal_Rela outrel;
- bfd_byte *loc;
-
- BFD_ASSERT(srelgot != NULL);
-
- outrel.r_offset = (sgot->output_section->vma
- + sgot->output_offset
- + gotent->got_offset);
- /* ??? Proper dynindx here. */
- outrel.r_info = ELF64_R_INFO (0, R_ALPHA_DTPMOD64);
- outrel.r_addend = 0;
-
- loc = srelgot->contents;
- loc += srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
- bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
- BFD_ASSERT (sizeof (Elf64_External_Rela)
- * srelgot->reloc_count
- <= srelgot->_cooked_size);
- }
+ elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
+ gotent->got_offset, 0,
+ R_ALPHA_DTPMOD64, 0);
if (dynamic_symbol_p || r_type == R_ALPHA_TLSLDM)
value = 0;
else
{
- BFD_ASSERT(tls_segment != NULL);
+ BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
value -= dtp_base;
}
bfd_put_64 (output_bfd, value,
bfd_archive_filename (input_bfd), h->root.root.root.string);
ret_val = FALSE;
}
- BFD_ASSERT(tls_segment != NULL);
+ BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
value -= dtp_base;
if (r_type == R_ALPHA_DTPRELHI)
value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
bfd_archive_filename (input_bfd), h->root.root.root.string);
ret_val = FALSE;
}
- BFD_ASSERT(tls_segment != NULL);
+ BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
value -= tp_base;
if (r_type == R_ALPHA_TPRELHI)
value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
value = 0;
else
{
- BFD_ASSERT(tls_segment != NULL);
- value -= (r_type == R_ALPHA_GOTDTPREL ? dtp_base : tp_base);
+ BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
+ if (r_type == R_ALPHA_GOTDTPREL)
+ value -= dtp_base;
+ else if (!info->shared)
+ value -= tp_base;
+ else
+ {
+ elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
+ gotent->got_offset, 0,
+ R_ALPHA_TPREL64,
+ value - dtp_base);
+ value = 0;
+ }
}
bfd_put_64 (output_bfd, value,
sgot->contents + gotent->got_offset);
sgot->contents + gotent->got_offset);
if (info->shared)
- {
- outrel.r_offset = (sgot->output_section->vma
- + sgot->output_offset
- + gotent->got_offset);
- outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE);
- outrel.r_addend = plt_addr;
-
- loc = srel->contents;
- loc += srel->reloc_count++ * sizeof (Elf64_External_Rela);
- bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
- BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
- <= srel->_cooked_size);
- }
+ elf64_alpha_emit_dynrel (output_bfd, info, sgot, srel,
+ gotent->got_offset, 0,
+ R_ALPHA_RELATIVE, plt_addr);
gotent = gotent->next;
}
{
/* Fill in the dynamic relocations for this symbol's .got entries. */
asection *srel;
- Elf_Internal_Rela outrel;
- bfd_byte *loc;
struct alpha_elf_got_entry *gotent;
srel = bfd_get_section_by_name (dynobj, ".rela.got");
gotent = gotent->next)
{
asection *sgot;
- int r_type;
+ long r_type;
if (gotent->use_count == 0)
continue;
sgot = alpha_elf_tdata (gotent->gotobj)->got;
- outrel.r_offset = (sgot->output_section->vma
- + sgot->output_offset
- + gotent->got_offset);
r_type = gotent->reloc_type;
switch (r_type)
abort ();
}
- outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
- outrel.r_addend = gotent->addend;
-
- loc = srel->contents;
- loc += srel->reloc_count++ * sizeof (Elf64_External_Rela);
- bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+ elf64_alpha_emit_dynrel (output_bfd, info, sgot, srel,
+ gotent->got_offset, h->dynindx,
+ r_type, gotent->addend);
if (gotent->reloc_type == R_ALPHA_TLSGD)
- {
- outrel.r_offset += 8;
- outrel.r_info = ELF64_R_INFO (h->dynindx, R_ALPHA_DTPREL64);
-
- loc = srel->contents;
- loc += srel->reloc_count++ * sizeof (Elf64_External_Rela);
- bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
- }
-
- BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
- <= srel->_cooked_size);
+ elf64_alpha_emit_dynrel (output_bfd, info, sgot, srel,
+ gotent->got_offset + 8, h->dynindx,
+ R_ALPHA_DTPREL64, gotent->addend);
}
}
bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
}
- /* Initialize the PLT0 entry */
+ /* Initialize the PLT0 entry. */
if (splt->_raw_size > 0)
{
bfd_put_32 (output_bfd, PLT_HEADER_WORD1, splt->contents);
bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 16);
bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 24);
- elf_section_data (splt->output_section)->this_hdr.sh_entsize =
- PLT_HEADER_SIZE;
+ elf_section_data (splt->output_section)->this_hdr.sh_entsize = 0;
}
}
}
}
\f
+static struct bfd_elf_special_section const elf64_alpha_special_sections[]=
+{
+ { ".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
+ { ".sbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
+ { NULL, 0, 0, 0, 0 }
+};
+
/* ECOFF swapping routines. These are used when dealing with the
.mdebug section, which is in the ECOFF debugging format. Copied
from elf32-mips.c. */
sizeof (Elf_External_Note),
8,
1,
- 64, 8,
+ 64, 3,
ELFCLASS64, EV_CURRENT,
bfd_elf64_write_out_phdrs,
bfd_elf64_write_shdrs_and_ehdr,
#define elf_backend_size_info \
alpha_elf_size_info
+#define elf_backend_special_sections \
+ elf64_alpha_special_sections
+
/* A few constants that determine how the .plt section is set up. */
#define elf_backend_want_got_plt 0
#define elf_backend_plt_readonly 0
#define elf_backend_want_plt_sym 1
#define elf_backend_got_header_size 0
-#define elf_backend_plt_header_size PLT_HEADER_SIZE
#include "elf64-target.h"
\f
#define elf_backend_post_process_headers \
elf64_alpha_fbsd_post_process_headers
+#undef elf64_bed
#define elf64_bed elf64_alpha_fbsd_bed
#include "elf64-target.h"