elf64-alpha.c revision 89862
133965Sjdp/* Alpha specific support for 64-bit ELF
289862Sobrien   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
378833Sobrien   Free Software Foundation, Inc.
433965Sjdp   Contributed by Richard Henderson <rth@tamu.edu>.
533965Sjdp
633965SjdpThis file is part of BFD, the Binary File Descriptor library.
733965Sjdp
833965SjdpThis program is free software; you can redistribute it and/or modify
933965Sjdpit under the terms of the GNU General Public License as published by
1033965Sjdpthe Free Software Foundation; either version 2 of the License, or
1133965Sjdp(at your option) any later version.
1233965Sjdp
1333965SjdpThis program is distributed in the hope that it will be useful,
1433965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
1533965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1633965SjdpGNU General Public License for more details.
1733965Sjdp
1833965SjdpYou should have received a copy of the GNU General Public License
1933965Sjdpalong with this program; if not, write to the Free Software
2033965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
2133965Sjdp
2257406Sjdp/* $FreeBSD: head/contrib/binutils/bfd/elf64-alpha.c 89862 2002-01-27 12:08:15Z obrien $ */
2357406Sjdp
2433965Sjdp/* We need a published ABI spec for this.  Until one comes out, don't
2533965Sjdp   assume this'll remain unchanged forever.  */
2633965Sjdp
2733965Sjdp#include "bfd.h"
2833965Sjdp#include "sysdep.h"
2933965Sjdp#include "libbfd.h"
3033965Sjdp#include "elf-bfd.h"
3133965Sjdp
3233965Sjdp#include "elf/alpha.h"
3333965Sjdp
3433965Sjdp#define ALPHAECOFF
3533965Sjdp
3633965Sjdp#define NO_COFF_RELOCS
3733965Sjdp#define NO_COFF_SYMBOLS
3833965Sjdp#define NO_COFF_LINENOS
3933965Sjdp
4077303Sobrien/* Get the ECOFF swapping routines.  Needed for the debug information.  */
4133965Sjdp#include "coff/internal.h"
4233965Sjdp#include "coff/sym.h"
4333965Sjdp#include "coff/symconst.h"
4433965Sjdp#include "coff/ecoff.h"
4533965Sjdp#include "coff/alpha.h"
4633965Sjdp#include "aout/ar.h"
4733965Sjdp#include "libcoff.h"
4833965Sjdp#include "libecoff.h"
4933965Sjdp#define ECOFF_64
5033965Sjdp#include "ecoffswap.h"
5133965Sjdp
5277303Sobrienstatic int alpha_elf_dynamic_symbol_p
5377303Sobrien  PARAMS((struct elf_link_hash_entry *, struct bfd_link_info *));
5433965Sjdpstatic struct bfd_hash_entry * elf64_alpha_link_hash_newfunc
5533965Sjdp  PARAMS((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
5633965Sjdpstatic struct bfd_link_hash_table * elf64_alpha_bfd_link_hash_table_create
5733965Sjdp  PARAMS((bfd *));
5833965Sjdp
5933965Sjdpstatic bfd_reloc_status_type elf64_alpha_reloc_nil
6033965Sjdp  PARAMS((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
6133965Sjdpstatic bfd_reloc_status_type elf64_alpha_reloc_bad
6233965Sjdp  PARAMS((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
6333965Sjdpstatic bfd_reloc_status_type elf64_alpha_do_reloc_gpdisp
6433965Sjdp  PARAMS((bfd *, bfd_vma, bfd_byte *, bfd_byte *));
6533965Sjdpstatic bfd_reloc_status_type elf64_alpha_reloc_gpdisp
6633965Sjdp  PARAMS((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
6733965Sjdp
6833965Sjdpstatic reloc_howto_type * elf64_alpha_bfd_reloc_type_lookup
6933965Sjdp  PARAMS((bfd *, bfd_reloc_code_real_type));
7033965Sjdpstatic void elf64_alpha_info_to_howto
7133965Sjdp  PARAMS((bfd *, arelent *, Elf64_Internal_Rela *));
7233965Sjdp
7377303Sobrienstatic boolean elf64_alpha_mkobject
7477303Sobrien  PARAMS((bfd *));
7533965Sjdpstatic boolean elf64_alpha_object_p
7633965Sjdp  PARAMS((bfd *));
7733965Sjdpstatic boolean elf64_alpha_section_from_shdr
7833965Sjdp  PARAMS((bfd *, Elf64_Internal_Shdr *, char *));
7989862Sobrienstatic boolean elf64_alpha_section_flags
8089862Sobrien  PARAMS((flagword *, Elf64_Internal_Shdr *));
8133965Sjdpstatic boolean elf64_alpha_fake_sections
8233965Sjdp  PARAMS((bfd *, Elf64_Internal_Shdr *, asection *));
8333965Sjdpstatic boolean elf64_alpha_create_got_section
8433965Sjdp  PARAMS((bfd *, struct bfd_link_info *));
8533965Sjdpstatic boolean elf64_alpha_create_dynamic_sections
8633965Sjdp  PARAMS((bfd *, struct bfd_link_info *));
8733965Sjdp
8833965Sjdpstatic boolean elf64_alpha_read_ecoff_info
8933965Sjdp  PARAMS((bfd *, asection *, struct ecoff_debug_info *));
9033965Sjdpstatic boolean elf64_alpha_is_local_label_name
9133965Sjdp  PARAMS((bfd *, const char *));
9233965Sjdpstatic boolean elf64_alpha_find_nearest_line
9333965Sjdp  PARAMS((bfd *, asection *, asymbol **, bfd_vma, const char **,
9433965Sjdp	  const char **, unsigned int *));
9533965Sjdp
9633965Sjdp#if defined(__STDC__) || defined(ALMOST_STDC)
9733965Sjdpstruct alpha_elf_link_hash_entry;
9833965Sjdp#endif
9933965Sjdp
10033965Sjdpstatic boolean elf64_alpha_output_extsym
10133965Sjdp  PARAMS((struct alpha_elf_link_hash_entry *, PTR));
10233965Sjdp
10333965Sjdpstatic boolean elf64_alpha_can_merge_gots
10433965Sjdp  PARAMS((bfd *, bfd *));
10533965Sjdpstatic void elf64_alpha_merge_gots
10633965Sjdp  PARAMS((bfd *, bfd *));
10733965Sjdpstatic boolean elf64_alpha_calc_got_offsets_for_symbol
10833965Sjdp  PARAMS ((struct alpha_elf_link_hash_entry *, PTR));
10933965Sjdpstatic void elf64_alpha_calc_got_offsets PARAMS ((struct bfd_link_info *));
11060510Sobrienstatic boolean elf64_alpha_size_got_sections
11160510Sobrien  PARAMS ((bfd *, struct bfd_link_info *));
11233965Sjdpstatic boolean elf64_alpha_always_size_sections
11333965Sjdp  PARAMS ((bfd *, struct bfd_link_info *));
11433965Sjdpstatic boolean elf64_alpha_calc_dynrel_sizes
11533965Sjdp  PARAMS ((struct alpha_elf_link_hash_entry *, struct bfd_link_info *));
11660510Sobrienstatic boolean elf64_alpha_add_symbol_hook
11760510Sobrien  PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
11860510Sobrien	   const char **, flagword *, asection **, bfd_vma *));
11933965Sjdpstatic boolean elf64_alpha_check_relocs
12033965Sjdp  PARAMS((bfd *, struct bfd_link_info *, asection *sec,
12133965Sjdp	  const Elf_Internal_Rela *));
12233965Sjdpstatic boolean elf64_alpha_adjust_dynamic_symbol
12333965Sjdp  PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *));
12433965Sjdpstatic boolean elf64_alpha_size_dynamic_sections
12533965Sjdp  PARAMS((bfd *, struct bfd_link_info *));
12633965Sjdpstatic boolean elf64_alpha_relocate_section
12733965Sjdp  PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
12833965Sjdp	  Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
12933965Sjdpstatic boolean elf64_alpha_finish_dynamic_symbol
13033965Sjdp  PARAMS((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
13133965Sjdp	  Elf_Internal_Sym *));
13233965Sjdpstatic boolean elf64_alpha_finish_dynamic_sections
13333965Sjdp  PARAMS((bfd *, struct bfd_link_info *));
13433965Sjdpstatic boolean elf64_alpha_final_link
13533965Sjdp  PARAMS((bfd *, struct bfd_link_info *));
13648850Sdfrstatic boolean elf64_alpha_merge_ind_symbols
13748850Sdfr  PARAMS((struct alpha_elf_link_hash_entry *, PTR));
13860510Sobrienstatic Elf_Internal_Rela * elf64_alpha_find_reloc_at_ofs
13960510Sobrien  PARAMS ((Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_vma, int));
14089862Sobrienstatic enum elf_reloc_type_class elf64_alpha_reloc_type_class
14189862Sobrien  PARAMS ((const Elf_Internal_Rela *));
14233965Sjdp
14333965Sjdpstruct alpha_elf_link_hash_entry
14433965Sjdp{
14533965Sjdp  struct elf_link_hash_entry root;
14633965Sjdp
14733965Sjdp  /* External symbol information.  */
14833965Sjdp  EXTR esym;
14933965Sjdp
15033965Sjdp  /* Cumulative flags for all the .got entries.  */
15133965Sjdp  int flags;
15233965Sjdp
15333965Sjdp  /* Contexts (LITUSE) in which a literal was referenced.  */
15433965Sjdp#define ALPHA_ELF_LINK_HASH_LU_ADDR 0x01
15533965Sjdp#define ALPHA_ELF_LINK_HASH_LU_MEM  0x02
15633965Sjdp#define ALPHA_ELF_LINK_HASH_LU_BYTE 0x04
15733965Sjdp#define ALPHA_ELF_LINK_HASH_LU_FUNC 0x08
15833965Sjdp
15933965Sjdp  /* Used to implement multiple .got subsections.  */
16033965Sjdp  struct alpha_elf_got_entry
16133965Sjdp  {
16233965Sjdp    struct alpha_elf_got_entry *next;
16333965Sjdp
16433965Sjdp    /* which .got subsection?  */
16533965Sjdp    bfd *gotobj;
16633965Sjdp
16733965Sjdp    /* the addend in effect for this entry.  */
16833965Sjdp    bfd_vma addend;
16933965Sjdp
17033965Sjdp    /* the .got offset for this entry.  */
17133965Sjdp    int got_offset;
17233965Sjdp
17333965Sjdp    int flags;
17433965Sjdp
17589862Sobrien    /* Additional flags.  */
17633965Sjdp#define ALPHA_ELF_GOT_ENTRY_RELOCS_DONE 0x10
17789862Sobrien#define ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED 0x20
17860510Sobrien
17960510Sobrien    int use_count;
18033965Sjdp  } *got_entries;
18133965Sjdp
18233965Sjdp  /* used to count non-got, non-plt relocations for delayed sizing
18333965Sjdp     of relocation sections.  */
18433965Sjdp  struct alpha_elf_reloc_entry
18533965Sjdp  {
18633965Sjdp    struct alpha_elf_reloc_entry *next;
18733965Sjdp
18833965Sjdp    /* which .reloc section? */
18933965Sjdp    asection *srel;
19033965Sjdp
19133965Sjdp    /* what kind of relocation? */
19289862Sobrien    unsigned int rtype;
19333965Sjdp
19489862Sobrien    /* is this against read-only section? */
19589862Sobrien    unsigned int reltext : 1;
19689862Sobrien
19733965Sjdp    /* how many did we find?  */
19833965Sjdp    unsigned long count;
19933965Sjdp  } *reloc_entries;
20033965Sjdp};
20133965Sjdp
20233965Sjdp/* Alpha ELF linker hash table.  */
20333965Sjdp
20433965Sjdpstruct alpha_elf_link_hash_table
20533965Sjdp{
20633965Sjdp  struct elf_link_hash_table root;
20733965Sjdp
20833965Sjdp  /* The head of a list of .got subsections linked through
20933965Sjdp     alpha_elf_tdata(abfd)->got_link_next.  */
21033965Sjdp  bfd *got_list;
21133965Sjdp};
21233965Sjdp
21333965Sjdp/* Look up an entry in a Alpha ELF linker hash table.  */
21433965Sjdp
21533965Sjdp#define alpha_elf_link_hash_lookup(table, string, create, copy, follow)	\
21633965Sjdp  ((struct alpha_elf_link_hash_entry *)					\
21733965Sjdp   elf_link_hash_lookup (&(table)->root, (string), (create),		\
21833965Sjdp			 (copy), (follow)))
21933965Sjdp
22033965Sjdp/* Traverse a Alpha ELF linker hash table.  */
22133965Sjdp
22233965Sjdp#define alpha_elf_link_hash_traverse(table, func, info)			\
22333965Sjdp  (elf_link_hash_traverse						\
22433965Sjdp   (&(table)->root,							\
22533965Sjdp    (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func),	\
22633965Sjdp    (info)))
22733965Sjdp
22833965Sjdp/* Get the Alpha ELF linker hash table from a link_info structure.  */
22933965Sjdp
23033965Sjdp#define alpha_elf_hash_table(p) \
23133965Sjdp  ((struct alpha_elf_link_hash_table *) ((p)->hash))
23233965Sjdp
23333965Sjdp/* Get the object's symbols as our own entry type.  */
23433965Sjdp
23533965Sjdp#define alpha_elf_sym_hashes(abfd) \
23633965Sjdp  ((struct alpha_elf_link_hash_entry **)elf_sym_hashes(abfd))
23733965Sjdp
23833965Sjdp/* Should we do dynamic things to this symbol?  */
23933965Sjdp
24077303Sobrienstatic int
24177303Sobrienalpha_elf_dynamic_symbol_p (h, info)
24277303Sobrien     struct elf_link_hash_entry *h;
24377303Sobrien     struct bfd_link_info *info;
24477303Sobrien{
24577303Sobrien  if (h == NULL)
24677303Sobrien    return false;
24733965Sjdp
24877303Sobrien  while (h->root.type == bfd_link_hash_indirect
24977303Sobrien	 || h->root.type == bfd_link_hash_warning)
25077303Sobrien    h = (struct elf_link_hash_entry *) h->root.u.i.link;
25177303Sobrien
25277303Sobrien  if (h->dynindx == -1)
25377303Sobrien    return false;
25477303Sobrien
25577303Sobrien  if (h->root.type == bfd_link_hash_undefweak
25677303Sobrien      || h->root.type == bfd_link_hash_defweak)
25777303Sobrien    return true;
25877303Sobrien
25978833Sobrien  switch (ELF_ST_VISIBILITY (h->other))
26078833Sobrien    {
26178833Sobrien    case STV_DEFAULT:
26278833Sobrien      break;
26378833Sobrien    case STV_HIDDEN:
26478833Sobrien    case STV_INTERNAL:
26578833Sobrien      return false;
26678833Sobrien    case STV_PROTECTED:
26778833Sobrien      if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
26878833Sobrien        return false;
26978833Sobrien      break;
27078833Sobrien    }
27178833Sobrien
27277303Sobrien  if ((info->shared && !info->symbolic)
27377303Sobrien      || ((h->elf_link_hash_flags
27477303Sobrien	   & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))
27577303Sobrien	  == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)))
27677303Sobrien    return true;
27777303Sobrien
27877303Sobrien  return false;
27977303Sobrien}
28077303Sobrien
28133965Sjdp/* Create an entry in a Alpha ELF linker hash table.  */
28233965Sjdp
28333965Sjdpstatic struct bfd_hash_entry *
28433965Sjdpelf64_alpha_link_hash_newfunc (entry, table, string)
28533965Sjdp     struct bfd_hash_entry *entry;
28633965Sjdp     struct bfd_hash_table *table;
28733965Sjdp     const char *string;
28833965Sjdp{
28933965Sjdp  struct alpha_elf_link_hash_entry *ret =
29033965Sjdp    (struct alpha_elf_link_hash_entry *) entry;
29133965Sjdp
29233965Sjdp  /* Allocate the structure if it has not already been allocated by a
29333965Sjdp     subclass.  */
29433965Sjdp  if (ret == (struct alpha_elf_link_hash_entry *) NULL)
29533965Sjdp    ret = ((struct alpha_elf_link_hash_entry *)
29633965Sjdp	   bfd_hash_allocate (table,
29733965Sjdp			      sizeof (struct alpha_elf_link_hash_entry)));
29833965Sjdp  if (ret == (struct alpha_elf_link_hash_entry *) NULL)
29933965Sjdp    return (struct bfd_hash_entry *) ret;
30033965Sjdp
30133965Sjdp  /* Call the allocation method of the superclass.  */
30233965Sjdp  ret = ((struct alpha_elf_link_hash_entry *)
30333965Sjdp	 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
30433965Sjdp				     table, string));
30533965Sjdp  if (ret != (struct alpha_elf_link_hash_entry *) NULL)
30633965Sjdp    {
30733965Sjdp      /* Set local fields.  */
30833965Sjdp      memset (&ret->esym, 0, sizeof (EXTR));
30933965Sjdp      /* We use -2 as a marker to indicate that the information has
31033965Sjdp	 not been set.  -1 means there is no associated ifd.  */
31133965Sjdp      ret->esym.ifd = -2;
31233965Sjdp      ret->flags = 0;
31333965Sjdp      ret->got_entries = NULL;
31433965Sjdp      ret->reloc_entries = NULL;
31533965Sjdp    }
31633965Sjdp
31733965Sjdp  return (struct bfd_hash_entry *) ret;
31833965Sjdp}
31933965Sjdp
32033965Sjdp/* Create a Alpha ELF linker hash table.  */
32133965Sjdp
32233965Sjdpstatic struct bfd_link_hash_table *
32333965Sjdpelf64_alpha_bfd_link_hash_table_create (abfd)
32433965Sjdp     bfd *abfd;
32533965Sjdp{
32633965Sjdp  struct alpha_elf_link_hash_table *ret;
32789862Sobrien  bfd_size_type amt = sizeof (struct alpha_elf_link_hash_table);
32833965Sjdp
32989862Sobrien  ret = (struct alpha_elf_link_hash_table *) bfd_zalloc (abfd, amt);
33033965Sjdp  if (ret == (struct alpha_elf_link_hash_table *) NULL)
33133965Sjdp    return NULL;
33233965Sjdp
33333965Sjdp  if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
33433965Sjdp				       elf64_alpha_link_hash_newfunc))
33533965Sjdp    {
33633965Sjdp      bfd_release (abfd, ret);
33733965Sjdp      return NULL;
33833965Sjdp    }
33933965Sjdp
34033965Sjdp  return &ret->root.root;
34133965Sjdp}
34233965Sjdp
34333965Sjdp/* We have some private fields hanging off of the elf_tdata structure.  */
34433965Sjdp
34533965Sjdpstruct alpha_elf_obj_tdata
34633965Sjdp{
34733965Sjdp  struct elf_obj_tdata root;
34833965Sjdp
34933965Sjdp  /* For every input file, these are the got entries for that object's
35033965Sjdp     local symbols.  */
35133965Sjdp  struct alpha_elf_got_entry ** local_got_entries;
35233965Sjdp
35333965Sjdp  /* For every input file, this is the object that owns the got that
35433965Sjdp     this input file uses.  */
35533965Sjdp  bfd *gotobj;
35633965Sjdp
35733965Sjdp  /* For every got, this is a linked list through the objects using this got */
35833965Sjdp  bfd *in_got_link_next;
35933965Sjdp
36033965Sjdp  /* For every got, this is a link to the next got subsegment.  */
36133965Sjdp  bfd *got_link_next;
36233965Sjdp
36333965Sjdp  /* For every got, this is the section.  */
36433965Sjdp  asection *got;
36533965Sjdp
36633965Sjdp  /* For every got, this is it's total number of *entries*.  */
36733965Sjdp  int total_got_entries;
36833965Sjdp
36933965Sjdp  /* For every got, this is the sum of the number of *entries* required
37033965Sjdp     to hold all of the member object's local got.  */
37133965Sjdp  int n_local_got_entries;
37233965Sjdp};
37333965Sjdp
37433965Sjdp#define alpha_elf_tdata(abfd) \
37533965Sjdp  ((struct alpha_elf_obj_tdata *) (abfd)->tdata.any)
37633965Sjdp
37733965Sjdpstatic boolean
37833965Sjdpelf64_alpha_mkobject (abfd)
37933965Sjdp     bfd *abfd;
38033965Sjdp{
38189862Sobrien  bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata);
38289862Sobrien  abfd->tdata.any = bfd_zalloc (abfd, amt);
38333965Sjdp  if (abfd->tdata.any == NULL)
38433965Sjdp    return false;
38533965Sjdp  return true;
38633965Sjdp}
38733965Sjdp
38833965Sjdpstatic boolean
38933965Sjdpelf64_alpha_object_p (abfd)
39033965Sjdp     bfd *abfd;
39133965Sjdp{
39233965Sjdp  /* Allocate our special target data.  */
39333965Sjdp  struct alpha_elf_obj_tdata *new_tdata;
39489862Sobrien  bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata);
39589862Sobrien  new_tdata = bfd_zalloc (abfd, amt);
39633965Sjdp  if (new_tdata == NULL)
39733965Sjdp    return false;
39833965Sjdp  new_tdata->root = *abfd->tdata.elf_obj_data;
39933965Sjdp  abfd->tdata.any = new_tdata;
40033965Sjdp
40133965Sjdp  /* Set the right machine number for an Alpha ELF file.  */
40233965Sjdp  return bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0);
40333965Sjdp}
40433965Sjdp
40533965Sjdp/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
40633965Sjdp   from smaller values.  Start with zero, widen, *then* decrement.  */
40733965Sjdp#define MINUS_ONE	(((bfd_vma)0) - 1)
40833965Sjdp
40989862Sobrien#define SKIP_HOWTO(N) \
41089862Sobrien  HOWTO(N, 0, 0, 0, 0, 0, 0, elf64_alpha_reloc_bad, 0, 0, 0, 0, 0)
41189862Sobrien
41233965Sjdpstatic reloc_howto_type elf64_alpha_howto_table[] =
41333965Sjdp{
41433965Sjdp  HOWTO (R_ALPHA_NONE,		/* type */
41533965Sjdp	 0,			/* rightshift */
41633965Sjdp	 0,			/* size (0 = byte, 1 = short, 2 = long) */
41733965Sjdp	 8,			/* bitsize */
41833965Sjdp	 true,			/* pc_relative */
41933965Sjdp	 0,			/* bitpos */
42033965Sjdp	 complain_overflow_dont, /* complain_on_overflow */
42133965Sjdp	 elf64_alpha_reloc_nil,	/* special_function */
42233965Sjdp	 "NONE",		/* name */
42333965Sjdp	 false,			/* partial_inplace */
42433965Sjdp	 0,			/* src_mask */
42533965Sjdp	 0,			/* dst_mask */
42633965Sjdp	 true),			/* pcrel_offset */
42733965Sjdp
42833965Sjdp  /* A 32 bit reference to a symbol.  */
42933965Sjdp  HOWTO (R_ALPHA_REFLONG,	/* type */
43033965Sjdp	 0,			/* rightshift */
43133965Sjdp	 2,			/* size (0 = byte, 1 = short, 2 = long) */
43233965Sjdp	 32,			/* bitsize */
43333965Sjdp	 false,			/* pc_relative */
43433965Sjdp	 0,			/* bitpos */
43533965Sjdp	 complain_overflow_bitfield, /* complain_on_overflow */
43633965Sjdp	 0,			/* special_function */
43733965Sjdp	 "REFLONG",		/* name */
43833965Sjdp	 false,			/* partial_inplace */
43933965Sjdp	 0xffffffff,		/* src_mask */
44033965Sjdp	 0xffffffff,		/* dst_mask */
44133965Sjdp	 false),		/* pcrel_offset */
44233965Sjdp
44333965Sjdp  /* A 64 bit reference to a symbol.  */
44433965Sjdp  HOWTO (R_ALPHA_REFQUAD,	/* type */
44533965Sjdp	 0,			/* rightshift */
44633965Sjdp	 4,			/* size (0 = byte, 1 = short, 2 = long) */
44733965Sjdp	 64,			/* bitsize */
44833965Sjdp	 false,			/* pc_relative */
44933965Sjdp	 0,			/* bitpos */
45033965Sjdp	 complain_overflow_bitfield, /* complain_on_overflow */
45133965Sjdp	 0,			/* special_function */
45233965Sjdp	 "REFQUAD",		/* name */
45333965Sjdp	 false,			/* partial_inplace */
45433965Sjdp	 MINUS_ONE,		/* src_mask */
45533965Sjdp	 MINUS_ONE,		/* dst_mask */
45633965Sjdp	 false),		/* pcrel_offset */
45733965Sjdp
45833965Sjdp  /* A 32 bit GP relative offset.  This is just like REFLONG except
45933965Sjdp     that when the value is used the value of the gp register will be
46033965Sjdp     added in.  */
46133965Sjdp  HOWTO (R_ALPHA_GPREL32,	/* type */
46233965Sjdp	 0,			/* rightshift */
46333965Sjdp	 2,			/* size (0 = byte, 1 = short, 2 = long) */
46433965Sjdp	 32,			/* bitsize */
46533965Sjdp	 false,			/* pc_relative */
46633965Sjdp	 0,			/* bitpos */
46733965Sjdp	 complain_overflow_bitfield, /* complain_on_overflow */
46833965Sjdp	 0,			/* special_function */
46933965Sjdp	 "GPREL32",		/* name */
47033965Sjdp	 false,			/* partial_inplace */
47133965Sjdp	 0xffffffff,		/* src_mask */
47233965Sjdp	 0xffffffff,		/* dst_mask */
47333965Sjdp	 false),		/* pcrel_offset */
47433965Sjdp
47533965Sjdp  /* Used for an instruction that refers to memory off the GP register.  */
47633965Sjdp  HOWTO (R_ALPHA_LITERAL,	/* type */
47733965Sjdp	 0,			/* rightshift */
47889862Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
47933965Sjdp	 16,			/* bitsize */
48033965Sjdp	 false,			/* pc_relative */
48133965Sjdp	 0,			/* bitpos */
48233965Sjdp	 complain_overflow_signed, /* complain_on_overflow */
48333965Sjdp	 0,			/* special_function */
48433965Sjdp	 "ELF_LITERAL",		/* name */
48533965Sjdp	 false,			/* partial_inplace */
48633965Sjdp	 0xffff,		/* src_mask */
48733965Sjdp	 0xffff,		/* dst_mask */
48833965Sjdp	 false),		/* pcrel_offset */
48933965Sjdp
49033965Sjdp  /* This reloc only appears immediately following an ELF_LITERAL reloc.
49133965Sjdp     It identifies a use of the literal.  The symbol index is special:
49233965Sjdp     1 means the literal address is in the base register of a memory
49333965Sjdp     format instruction; 2 means the literal address is in the byte
49433965Sjdp     offset register of a byte-manipulation instruction; 3 means the
49533965Sjdp     literal address is in the target register of a jsr instruction.
49633965Sjdp     This does not actually do any relocation.  */
49733965Sjdp  HOWTO (R_ALPHA_LITUSE,	/* type */
49833965Sjdp	 0,			/* rightshift */
49989862Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
50033965Sjdp	 32,			/* bitsize */
50133965Sjdp	 false,			/* pc_relative */
50233965Sjdp	 0,			/* bitpos */
50333965Sjdp	 complain_overflow_dont, /* complain_on_overflow */
50433965Sjdp	 elf64_alpha_reloc_nil,	/* special_function */
50533965Sjdp	 "LITUSE",		/* name */
50633965Sjdp	 false,			/* partial_inplace */
50733965Sjdp	 0,			/* src_mask */
50833965Sjdp	 0,			/* dst_mask */
50933965Sjdp	 false),		/* pcrel_offset */
51033965Sjdp
51133965Sjdp  /* Load the gp register.  This is always used for a ldah instruction
51233965Sjdp     which loads the upper 16 bits of the gp register.  The symbol
51333965Sjdp     index of the GPDISP instruction is an offset in bytes to the lda
51433965Sjdp     instruction that loads the lower 16 bits.  The value to use for
51533965Sjdp     the relocation is the difference between the GP value and the
51633965Sjdp     current location; the load will always be done against a register
51733965Sjdp     holding the current address.
51833965Sjdp
51933965Sjdp     NOTE: Unlike ECOFF, partial in-place relocation is not done.  If
52033965Sjdp     any offset is present in the instructions, it is an offset from
52133965Sjdp     the register to the ldah instruction.  This lets us avoid any
52233965Sjdp     stupid hackery like inventing a gp value to do partial relocation
52333965Sjdp     against.  Also unlike ECOFF, we do the whole relocation off of
52433965Sjdp     the GPDISP rather than a GPDISP_HI16/GPDISP_LO16 pair.  An odd,
52533965Sjdp     space consuming bit, that, since all the information was present
52633965Sjdp     in the GPDISP_HI16 reloc.  */
52733965Sjdp  HOWTO (R_ALPHA_GPDISP,	/* type */
52833965Sjdp	 16,			/* rightshift */
52933965Sjdp	 2,			/* size (0 = byte, 1 = short, 2 = long) */
53033965Sjdp	 16,			/* bitsize */
53133965Sjdp	 false,			/* pc_relative */
53233965Sjdp	 0,			/* bitpos */
53333965Sjdp	 complain_overflow_dont, /* complain_on_overflow */
53433965Sjdp	 elf64_alpha_reloc_gpdisp, /* special_function */
53533965Sjdp	 "GPDISP",		/* name */
53633965Sjdp	 false,			/* partial_inplace */
53733965Sjdp	 0xffff,		/* src_mask */
53833965Sjdp	 0xffff,		/* dst_mask */
53933965Sjdp	 true),			/* pcrel_offset */
54033965Sjdp
54133965Sjdp  /* A 21 bit branch.  */
54233965Sjdp  HOWTO (R_ALPHA_BRADDR,	/* type */
54333965Sjdp	 2,			/* rightshift */
54433965Sjdp	 2,			/* size (0 = byte, 1 = short, 2 = long) */
54533965Sjdp	 21,			/* bitsize */
54633965Sjdp	 true,			/* pc_relative */
54733965Sjdp	 0,			/* bitpos */
54833965Sjdp	 complain_overflow_signed, /* complain_on_overflow */
54933965Sjdp	 0,			/* special_function */
55033965Sjdp	 "BRADDR",		/* name */
55133965Sjdp	 false,			/* partial_inplace */
55233965Sjdp	 0x1fffff,		/* src_mask */
55333965Sjdp	 0x1fffff,		/* dst_mask */
55433965Sjdp	 true),			/* pcrel_offset */
55533965Sjdp
55633965Sjdp  /* A hint for a jump to a register.  */
55733965Sjdp  HOWTO (R_ALPHA_HINT,		/* type */
55833965Sjdp	 2,			/* rightshift */
55989862Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
56033965Sjdp	 14,			/* bitsize */
56133965Sjdp	 true,			/* pc_relative */
56233965Sjdp	 0,			/* bitpos */
56333965Sjdp	 complain_overflow_dont, /* complain_on_overflow */
56433965Sjdp	 0,			/* special_function */
56533965Sjdp	 "HINT",		/* name */
56633965Sjdp	 false,			/* partial_inplace */
56733965Sjdp	 0x3fff,		/* src_mask */
56833965Sjdp	 0x3fff,		/* dst_mask */
56933965Sjdp	 true),			/* pcrel_offset */
57033965Sjdp
57133965Sjdp  /* 16 bit PC relative offset.  */
57233965Sjdp  HOWTO (R_ALPHA_SREL16,	/* type */
57333965Sjdp	 0,			/* rightshift */
57433965Sjdp	 1,			/* size (0 = byte, 1 = short, 2 = long) */
57533965Sjdp	 16,			/* bitsize */
57633965Sjdp	 true,			/* pc_relative */
57733965Sjdp	 0,			/* bitpos */
57833965Sjdp	 complain_overflow_signed, /* complain_on_overflow */
57933965Sjdp	 0,			/* special_function */
58033965Sjdp	 "SREL16",		/* name */
58133965Sjdp	 false,			/* partial_inplace */
58233965Sjdp	 0xffff,		/* src_mask */
58333965Sjdp	 0xffff,		/* dst_mask */
58478833Sobrien	 true),			/* pcrel_offset */
58533965Sjdp
58633965Sjdp  /* 32 bit PC relative offset.  */
58733965Sjdp  HOWTO (R_ALPHA_SREL32,	/* type */
58833965Sjdp	 0,			/* rightshift */
58933965Sjdp	 2,			/* size (0 = byte, 1 = short, 2 = long) */
59033965Sjdp	 32,			/* bitsize */
59133965Sjdp	 true,			/* pc_relative */
59233965Sjdp	 0,			/* bitpos */
59333965Sjdp	 complain_overflow_signed, /* complain_on_overflow */
59433965Sjdp	 0,			/* special_function */
59533965Sjdp	 "SREL32",		/* name */
59633965Sjdp	 false,			/* partial_inplace */
59733965Sjdp	 0xffffffff,		/* src_mask */
59833965Sjdp	 0xffffffff,		/* dst_mask */
59978833Sobrien	 true),			/* pcrel_offset */
60033965Sjdp
60133965Sjdp  /* A 64 bit PC relative offset.  */
60233965Sjdp  HOWTO (R_ALPHA_SREL64,	/* type */
60333965Sjdp	 0,			/* rightshift */
60433965Sjdp	 4,			/* size (0 = byte, 1 = short, 2 = long) */
60533965Sjdp	 64,			/* bitsize */
60633965Sjdp	 true,			/* pc_relative */
60733965Sjdp	 0,			/* bitpos */
60833965Sjdp	 complain_overflow_signed, /* complain_on_overflow */
60933965Sjdp	 0,			/* special_function */
61033965Sjdp	 "SREL64",		/* name */
61133965Sjdp	 false,			/* partial_inplace */
61233965Sjdp	 MINUS_ONE,		/* src_mask */
61333965Sjdp	 MINUS_ONE,		/* dst_mask */
61478833Sobrien	 true),			/* pcrel_offset */
61533965Sjdp
61689862Sobrien  /* Skip 12 - 16; deprecated ECOFF relocs.  */
61789862Sobrien  SKIP_HOWTO (12),
61889862Sobrien  SKIP_HOWTO (13),
61989862Sobrien  SKIP_HOWTO (14),
62089862Sobrien  SKIP_HOWTO (15),
62189862Sobrien  SKIP_HOWTO (16),
62233965Sjdp
62338889Sjdp  /* The high 16 bits of the displacement from GP to the target.  */
62438889Sjdp  HOWTO (R_ALPHA_GPRELHIGH,
62538889Sjdp	 0,			/* rightshift */
62689862Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
62760510Sobrien	 16,			/* bitsize */
62838889Sjdp	 false,			/* pc_relative */
62938889Sjdp	 0,			/* bitpos */
63060510Sobrien	 complain_overflow_signed, /* complain_on_overflow */
63189862Sobrien	 0,			/* special_function */
63238889Sjdp	 "GPRELHIGH",		/* name */
63338889Sjdp	 false,			/* partial_inplace */
63460510Sobrien	 0xffff,		/* src_mask */
63560510Sobrien	 0xffff,		/* dst_mask */
63638889Sjdp	 false),		/* pcrel_offset */
63738889Sjdp
63838889Sjdp  /* The low 16 bits of the displacement from GP to the target.  */
63938889Sjdp  HOWTO (R_ALPHA_GPRELLOW,
64038889Sjdp	 0,			/* rightshift */
64189862Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
64260510Sobrien	 16,			/* bitsize */
64338889Sjdp	 false,			/* pc_relative */
64438889Sjdp	 0,			/* bitpos */
64538889Sjdp	 complain_overflow_dont, /* complain_on_overflow */
64689862Sobrien	 0,			/* special_function */
64738889Sjdp	 "GPRELLOW",		/* name */
64838889Sjdp	 false,			/* partial_inplace */
64960510Sobrien	 0xffff,		/* src_mask */
65060510Sobrien	 0xffff,		/* dst_mask */
65138889Sjdp	 false),		/* pcrel_offset */
65238889Sjdp
65338889Sjdp  /* A 16-bit displacement from the GP to the target.  */
65489862Sobrien  HOWTO (R_ALPHA_GPREL16,
65538889Sjdp	 0,			/* rightshift */
65689862Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
65760510Sobrien	 16,			/* bitsize */
65838889Sjdp	 false,			/* pc_relative */
65938889Sjdp	 0,			/* bitpos */
66060510Sobrien	 complain_overflow_signed, /* complain_on_overflow */
66160510Sobrien	 0,			/* special_function */
66289862Sobrien	 "GPREL16",		/* name */
66338889Sjdp	 false,			/* partial_inplace */
66460510Sobrien	 0xffff,		/* src_mask */
66560510Sobrien	 0xffff,		/* dst_mask */
66638889Sjdp	 false),		/* pcrel_offset */
66738889Sjdp
66889862Sobrien  /* Skip 20 - 23; deprecated ECOFF relocs.  */
66989862Sobrien  SKIP_HOWTO (20),
67089862Sobrien  SKIP_HOWTO (21),
67189862Sobrien  SKIP_HOWTO (22),
67289862Sobrien  SKIP_HOWTO (23),
67338889Sjdp
67477303Sobrien  /* Misc ELF relocations.  */
67538889Sjdp
67638889Sjdp  /* A dynamic relocation to copy the target into our .dynbss section.  */
67738889Sjdp  /* Not generated, as all Alpha objects use PIC, so it is not needed.  It
67838889Sjdp     is present because every other ELF has one, but should not be used
67938889Sjdp     because .dynbss is an ugly thing.  */
68033965Sjdp  HOWTO (R_ALPHA_COPY,
68133965Sjdp	 0,
68233965Sjdp	 0,
68333965Sjdp	 0,
68433965Sjdp	 false,
68533965Sjdp	 0,
68633965Sjdp	 complain_overflow_dont,
68733965Sjdp	 bfd_elf_generic_reloc,
68833965Sjdp	 "COPY",
68933965Sjdp	 false,
69033965Sjdp	 0,
69133965Sjdp	 0,
69233965Sjdp	 true),
69333965Sjdp
69438889Sjdp  /* A dynamic relocation for a .got entry.  */
69533965Sjdp  HOWTO (R_ALPHA_GLOB_DAT,
69633965Sjdp	 0,
69733965Sjdp	 0,
69833965Sjdp	 0,
69933965Sjdp	 false,
70033965Sjdp	 0,
70133965Sjdp	 complain_overflow_dont,
70233965Sjdp	 bfd_elf_generic_reloc,
70333965Sjdp	 "GLOB_DAT",
70433965Sjdp	 false,
70533965Sjdp	 0,
70633965Sjdp	 0,
70733965Sjdp	 true),
70833965Sjdp
70938889Sjdp  /* A dynamic relocation for a .plt entry.  */
71033965Sjdp  HOWTO (R_ALPHA_JMP_SLOT,
71133965Sjdp	 0,
71233965Sjdp	 0,
71333965Sjdp	 0,
71433965Sjdp	 false,
71533965Sjdp	 0,
71633965Sjdp	 complain_overflow_dont,
71733965Sjdp	 bfd_elf_generic_reloc,
71833965Sjdp	 "JMP_SLOT",
71933965Sjdp	 false,
72033965Sjdp	 0,
72133965Sjdp	 0,
72233965Sjdp	 true),
72333965Sjdp
72438889Sjdp  /* A dynamic relocation to add the base of the DSO to a 64-bit field.  */
72533965Sjdp  HOWTO (R_ALPHA_RELATIVE,
72633965Sjdp	 0,
72733965Sjdp	 0,
72833965Sjdp	 0,
72933965Sjdp	 false,
73033965Sjdp	 0,
73133965Sjdp	 complain_overflow_dont,
73233965Sjdp	 bfd_elf_generic_reloc,
73333965Sjdp	 "RELATIVE",
73433965Sjdp	 false,
73533965Sjdp	 0,
73633965Sjdp	 0,
73733965Sjdp	 true)
73833965Sjdp};
73933965Sjdp
74033965Sjdp/* A relocation function which doesn't do anything.  */
74133965Sjdp
74233965Sjdpstatic bfd_reloc_status_type
74333965Sjdpelf64_alpha_reloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message)
74478833Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
74533965Sjdp     arelent *reloc;
74678833Sobrien     asymbol *sym ATTRIBUTE_UNUSED;
74778833Sobrien     PTR data ATTRIBUTE_UNUSED;
74833965Sjdp     asection *sec;
74933965Sjdp     bfd *output_bfd;
75078833Sobrien     char **error_message ATTRIBUTE_UNUSED;
75133965Sjdp{
75233965Sjdp  if (output_bfd)
75333965Sjdp    reloc->address += sec->output_offset;
75433965Sjdp  return bfd_reloc_ok;
75533965Sjdp}
75633965Sjdp
75733965Sjdp/* A relocation function used for an unsupported reloc.  */
75833965Sjdp
75933965Sjdpstatic bfd_reloc_status_type
76033965Sjdpelf64_alpha_reloc_bad (abfd, reloc, sym, data, sec, output_bfd, error_message)
76178833Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
76233965Sjdp     arelent *reloc;
76378833Sobrien     asymbol *sym ATTRIBUTE_UNUSED;
76478833Sobrien     PTR data ATTRIBUTE_UNUSED;
76533965Sjdp     asection *sec;
76633965Sjdp     bfd *output_bfd;
76778833Sobrien     char **error_message ATTRIBUTE_UNUSED;
76833965Sjdp{
76933965Sjdp  if (output_bfd)
77033965Sjdp    reloc->address += sec->output_offset;
77133965Sjdp  return bfd_reloc_notsupported;
77233965Sjdp}
77333965Sjdp
77433965Sjdp/* Do the work of the GPDISP relocation.  */
77533965Sjdp
77633965Sjdpstatic bfd_reloc_status_type
77733965Sjdpelf64_alpha_do_reloc_gpdisp (abfd, gpdisp, p_ldah, p_lda)
77833965Sjdp     bfd *abfd;
77933965Sjdp     bfd_vma gpdisp;
78033965Sjdp     bfd_byte *p_ldah;
78133965Sjdp     bfd_byte *p_lda;
78233965Sjdp{
78333965Sjdp  bfd_reloc_status_type ret = bfd_reloc_ok;
78433965Sjdp  bfd_vma addend;
78533965Sjdp  unsigned long i_ldah, i_lda;
78633965Sjdp
78733965Sjdp  i_ldah = bfd_get_32 (abfd, p_ldah);
78833965Sjdp  i_lda = bfd_get_32 (abfd, p_lda);
78933965Sjdp
79033965Sjdp  /* Complain if the instructions are not correct.  */
79133965Sjdp  if (((i_ldah >> 26) & 0x3f) != 0x09
79233965Sjdp      || ((i_lda >> 26) & 0x3f) != 0x08)
79333965Sjdp    ret = bfd_reloc_dangerous;
79433965Sjdp
79533965Sjdp  /* Extract the user-supplied offset, mirroring the sign extensions
79633965Sjdp     that the instructions perform.  */
79733965Sjdp  addend = ((i_ldah & 0xffff) << 16) | (i_lda & 0xffff);
79833965Sjdp  addend = (addend ^ 0x80008000) - 0x80008000;
79933965Sjdp
80033965Sjdp  gpdisp += addend;
80133965Sjdp
80248850Sdfr  if ((bfd_signed_vma) gpdisp < -(bfd_signed_vma) 0x80000000
80348850Sdfr      || (bfd_signed_vma) gpdisp >= (bfd_signed_vma) 0x7fff8000)
80433965Sjdp    ret = bfd_reloc_overflow;
80533965Sjdp
80633965Sjdp  /* compensate for the sign extension again.  */
80733965Sjdp  i_ldah = ((i_ldah & 0xffff0000)
80833965Sjdp	    | (((gpdisp >> 16) + ((gpdisp >> 15) & 1)) & 0xffff));
80933965Sjdp  i_lda = (i_lda & 0xffff0000) | (gpdisp & 0xffff);
81033965Sjdp
81189862Sobrien  bfd_put_32 (abfd, (bfd_vma) i_ldah, p_ldah);
81289862Sobrien  bfd_put_32 (abfd, (bfd_vma) i_lda, p_lda);
81333965Sjdp
81433965Sjdp  return ret;
81533965Sjdp}
81633965Sjdp
81733965Sjdp/* The special function for the GPDISP reloc.  */
81833965Sjdp
81933965Sjdpstatic bfd_reloc_status_type
82033965Sjdpelf64_alpha_reloc_gpdisp (abfd, reloc_entry, sym, data, input_section,
82133965Sjdp			  output_bfd, err_msg)
82233965Sjdp     bfd *abfd;
82333965Sjdp     arelent *reloc_entry;
82478833Sobrien     asymbol *sym ATTRIBUTE_UNUSED;
82533965Sjdp     PTR data;
82633965Sjdp     asection *input_section;
82733965Sjdp     bfd *output_bfd;
82833965Sjdp     char **err_msg;
82933965Sjdp{
83033965Sjdp  bfd_reloc_status_type ret;
83133965Sjdp  bfd_vma gp, relocation;
83233965Sjdp  bfd_byte *p_ldah, *p_lda;
83333965Sjdp
83433965Sjdp  /* Don't do anything if we're not doing a final link.  */
83533965Sjdp  if (output_bfd)
83633965Sjdp    {
83733965Sjdp      reloc_entry->address += input_section->output_offset;
83833965Sjdp      return bfd_reloc_ok;
83933965Sjdp    }
84033965Sjdp
84133965Sjdp  if (reloc_entry->address > input_section->_cooked_size ||
84233965Sjdp      reloc_entry->address + reloc_entry->addend > input_section->_cooked_size)
84333965Sjdp    return bfd_reloc_outofrange;
84433965Sjdp
84533965Sjdp  /* The gp used in the portion of the output object to which this
84633965Sjdp     input object belongs is cached on the input bfd.  */
84733965Sjdp  gp = _bfd_get_gp_value (abfd);
84833965Sjdp
84933965Sjdp  relocation = (input_section->output_section->vma
85033965Sjdp		+ input_section->output_offset
85133965Sjdp		+ reloc_entry->address);
85233965Sjdp
85333965Sjdp  p_ldah = (bfd_byte *) data + reloc_entry->address;
85433965Sjdp  p_lda = p_ldah + reloc_entry->addend;
85533965Sjdp
85633965Sjdp  ret = elf64_alpha_do_reloc_gpdisp (abfd, gp - relocation, p_ldah, p_lda);
85733965Sjdp
85833965Sjdp  /* Complain if the instructions are not correct.  */
85933965Sjdp  if (ret == bfd_reloc_dangerous)
86060510Sobrien    *err_msg = _("GPDISP relocation did not find ldah and lda instructions");
86133965Sjdp
86233965Sjdp  return ret;
86333965Sjdp}
86433965Sjdp
86533965Sjdp/* A mapping from BFD reloc types to Alpha ELF reloc types.  */
86633965Sjdp
86733965Sjdpstruct elf_reloc_map
86833965Sjdp{
86933965Sjdp  bfd_reloc_code_real_type bfd_reloc_val;
87033965Sjdp  int elf_reloc_val;
87133965Sjdp};
87233965Sjdp
87333965Sjdpstatic const struct elf_reloc_map elf64_alpha_reloc_map[] =
87433965Sjdp{
87589862Sobrien  {BFD_RELOC_NONE,			R_ALPHA_NONE},
87689862Sobrien  {BFD_RELOC_32,			R_ALPHA_REFLONG},
87789862Sobrien  {BFD_RELOC_64,			R_ALPHA_REFQUAD},
87889862Sobrien  {BFD_RELOC_CTOR,			R_ALPHA_REFQUAD},
87989862Sobrien  {BFD_RELOC_GPREL32,			R_ALPHA_GPREL32},
88089862Sobrien  {BFD_RELOC_ALPHA_ELF_LITERAL,		R_ALPHA_LITERAL},
88189862Sobrien  {BFD_RELOC_ALPHA_LITUSE,		R_ALPHA_LITUSE},
88289862Sobrien  {BFD_RELOC_ALPHA_GPDISP,		R_ALPHA_GPDISP},
88389862Sobrien  {BFD_RELOC_23_PCREL_S2,		R_ALPHA_BRADDR},
88489862Sobrien  {BFD_RELOC_ALPHA_HINT,		R_ALPHA_HINT},
88589862Sobrien  {BFD_RELOC_16_PCREL,			R_ALPHA_SREL16},
88689862Sobrien  {BFD_RELOC_32_PCREL,			R_ALPHA_SREL32},
88789862Sobrien  {BFD_RELOC_64_PCREL,			R_ALPHA_SREL64},
88889862Sobrien  {BFD_RELOC_ALPHA_GPREL_HI16,		R_ALPHA_GPRELHIGH},
88989862Sobrien  {BFD_RELOC_ALPHA_GPREL_LO16,		R_ALPHA_GPRELLOW},
89089862Sobrien  {BFD_RELOC_GPREL16,			R_ALPHA_GPREL16},
89133965Sjdp};
89233965Sjdp
89333965Sjdp/* Given a BFD reloc type, return a HOWTO structure.  */
89433965Sjdp
89533965Sjdpstatic reloc_howto_type *
89633965Sjdpelf64_alpha_bfd_reloc_type_lookup (abfd, code)
89778833Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
89833965Sjdp     bfd_reloc_code_real_type code;
89933965Sjdp{
90033965Sjdp  const struct elf_reloc_map *i, *e;
90133965Sjdp  i = e = elf64_alpha_reloc_map;
90233965Sjdp  e += sizeof (elf64_alpha_reloc_map) / sizeof (struct elf_reloc_map);
90333965Sjdp  for (; i != e; ++i)
90433965Sjdp    {
90533965Sjdp      if (i->bfd_reloc_val == code)
90633965Sjdp	return &elf64_alpha_howto_table[i->elf_reloc_val];
90733965Sjdp    }
90833965Sjdp  return 0;
90933965Sjdp}
91033965Sjdp
91133965Sjdp/* Given an Alpha ELF reloc type, fill in an arelent structure.  */
91233965Sjdp
91333965Sjdpstatic void
91433965Sjdpelf64_alpha_info_to_howto (abfd, cache_ptr, dst)
91578833Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
91633965Sjdp     arelent *cache_ptr;
91733965Sjdp     Elf64_Internal_Rela *dst;
91833965Sjdp{
91933965Sjdp  unsigned r_type;
92033965Sjdp
92133965Sjdp  r_type = ELF64_R_TYPE(dst->r_info);
92233965Sjdp  BFD_ASSERT (r_type < (unsigned int) R_ALPHA_max);
92333965Sjdp  cache_ptr->howto = &elf64_alpha_howto_table[r_type];
92433965Sjdp}
92533965Sjdp
92677303Sobrien/* These functions do relaxation for Alpha ELF.
92760510Sobrien
92860510Sobrien   Currently I'm only handling what I can do with existing compiler
92960510Sobrien   and assembler support, which means no instructions are removed,
93060510Sobrien   though some may be nopped.  At this time GCC does not emit enough
93160510Sobrien   information to do all of the relaxing that is possible.  It will
93260510Sobrien   take some not small amount of work for that to happen.
93360510Sobrien
93460510Sobrien   There are a couple of interesting papers that I once read on this
93560510Sobrien   subject, that I cannot find references to at the moment, that
93660510Sobrien   related to Alpha in particular.  They are by David Wall, then of
93760510Sobrien   DEC WRL.  */
93860510Sobrien
93960510Sobrien#define OP_LDA		0x08
94060510Sobrien#define OP_LDAH		0x09
94160510Sobrien#define INSN_JSR	0x68004000
94260510Sobrien#define INSN_JSR_MASK	0xfc00c000
94360510Sobrien#define OP_LDQ		0x29
94460510Sobrien#define OP_BR		0x30
94560510Sobrien#define OP_BSR		0x34
94689862Sobrien#define INSN_UNOP	0x2ffe0000
94760510Sobrien
94860510Sobrienstruct alpha_relax_info
94960510Sobrien{
95060510Sobrien  bfd *abfd;
95160510Sobrien  asection *sec;
95260510Sobrien  bfd_byte *contents;
95360510Sobrien  Elf_Internal_Rela *relocs, *relend;
95460510Sobrien  struct bfd_link_info *link_info;
95560510Sobrien  boolean changed_contents;
95660510Sobrien  boolean changed_relocs;
95760510Sobrien  bfd_vma gp;
95860510Sobrien  bfd *gotobj;
95960510Sobrien  asection *tsec;
96060510Sobrien  struct alpha_elf_link_hash_entry *h;
96160510Sobrien  struct alpha_elf_got_entry *gotent;
96260510Sobrien  unsigned char other;
96360510Sobrien};
96460510Sobrien
96560510Sobrienstatic Elf_Internal_Rela * elf64_alpha_relax_with_lituse
96677303Sobrien  PARAMS((struct alpha_relax_info *info, bfd_vma symval,
96760510Sobrien          Elf_Internal_Rela *irel, Elf_Internal_Rela *irelend));
96860510Sobrien
96960510Sobrienstatic boolean elf64_alpha_relax_without_lituse
97077303Sobrien  PARAMS((struct alpha_relax_info *info, bfd_vma symval,
97160510Sobrien          Elf_Internal_Rela *irel));
97260510Sobrien
97360510Sobrienstatic bfd_vma elf64_alpha_relax_opt_call
97460510Sobrien  PARAMS((struct alpha_relax_info *info, bfd_vma symval));
97560510Sobrien
97660510Sobrienstatic boolean elf64_alpha_relax_section
97760510Sobrien  PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
97860510Sobrien	  boolean *again));
97960510Sobrien
98060510Sobrienstatic Elf_Internal_Rela *
98160510Sobrienelf64_alpha_find_reloc_at_ofs (rel, relend, offset, type)
98260510Sobrien     Elf_Internal_Rela *rel, *relend;
98360510Sobrien     bfd_vma offset;
98460510Sobrien     int type;
98560510Sobrien{
98660510Sobrien  while (rel < relend)
98760510Sobrien    {
98889862Sobrien      if (rel->r_offset == offset
98989862Sobrien	  && ELF64_R_TYPE (rel->r_info) == (unsigned int) type)
99060510Sobrien	return rel;
99160510Sobrien      ++rel;
99260510Sobrien    }
99360510Sobrien  return NULL;
99460510Sobrien}
99560510Sobrien
99660510Sobrienstatic Elf_Internal_Rela *
99760510Sobrienelf64_alpha_relax_with_lituse (info, symval, irel, irelend)
99860510Sobrien     struct alpha_relax_info *info;
99960510Sobrien     bfd_vma symval;
100060510Sobrien     Elf_Internal_Rela *irel, *irelend;
100160510Sobrien{
100260510Sobrien  Elf_Internal_Rela *urel;
100360510Sobrien  int flags, count, i;
100460510Sobrien  bfd_signed_vma disp;
100560510Sobrien  boolean fits16;
100660510Sobrien  boolean fits32;
100760510Sobrien  boolean lit_reused = false;
100860510Sobrien  boolean all_optimized = true;
100960510Sobrien  unsigned int lit_insn;
101060510Sobrien
101160510Sobrien  lit_insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset);
101260510Sobrien  if (lit_insn >> 26 != OP_LDQ)
101360510Sobrien    {
101460510Sobrien      ((*_bfd_error_handler)
101560510Sobrien       ("%s: %s+0x%lx: warning: LITERAL relocation against unexpected insn",
101689862Sobrien	bfd_archive_filename (info->abfd), info->sec->name,
101789862Sobrien	(unsigned long) irel->r_offset));
101860510Sobrien      return irel;
101960510Sobrien    }
102060510Sobrien
102160510Sobrien  /* Summarize how this particular LITERAL is used.  */
102260510Sobrien  for (urel = irel+1, flags = count = 0; urel < irelend; ++urel, ++count)
102360510Sobrien    {
102460510Sobrien      if (ELF64_R_TYPE (urel->r_info) != R_ALPHA_LITUSE)
102560510Sobrien	break;
102689862Sobrien      if (urel->r_addend <= 3)
102760510Sobrien	flags |= 1 << urel->r_addend;
102860510Sobrien    }
102960510Sobrien
103077303Sobrien  /* A little preparation for the loop...  */
103160510Sobrien  disp = symval - info->gp;
103260510Sobrien
103360510Sobrien  for (urel = irel+1, i = 0; i < count; ++i, ++urel)
103460510Sobrien    {
103560510Sobrien      unsigned int insn;
103677303Sobrien      int insn_disp;
103777303Sobrien      bfd_signed_vma xdisp;
103877303Sobrien
103960510Sobrien      insn = bfd_get_32 (info->abfd, info->contents + urel->r_offset);
104060510Sobrien
104160510Sobrien      switch (urel->r_addend)
104260510Sobrien	{
104360510Sobrien	default: /* 0 = ADDRESS FORMAT */
104460510Sobrien	  /* This type is really just a placeholder to note that all
104560510Sobrien	     uses cannot be optimized, but to still allow some.  */
104660510Sobrien	  all_optimized = false;
104760510Sobrien	  break;
104860510Sobrien
104960510Sobrien	case 1: /* MEM FORMAT */
105060510Sobrien	  /* We can always optimize 16-bit displacements.  */
105177303Sobrien
105277303Sobrien	  /* Extract the displacement from the instruction, sign-extending
105377303Sobrien	     it if necessary, then test whether it is within 16 or 32 bits
105477303Sobrien	     displacement from GP.  */
105577303Sobrien	  insn_disp = insn & 0x0000ffff;
105677303Sobrien	  if (insn_disp & 0x00008000)
105777303Sobrien	    insn_disp |= 0xffff0000;  /* Negative: sign-extend.  */
105877303Sobrien
105977303Sobrien	  xdisp = disp + insn_disp;
106077303Sobrien	  fits16 = (xdisp >= - (bfd_signed_vma) 0x00008000 && xdisp < 0x00008000);
106177303Sobrien	  fits32 = (xdisp >= - (bfd_signed_vma) 0x80000000 && xdisp < 0x7fff8000);
106277303Sobrien
106360510Sobrien	  if (fits16)
106460510Sobrien	    {
106577303Sobrien	      /* Take the op code and dest from this insn, take the base
106660510Sobrien		 register from the literal insn.  Leave the offset alone.  */
106777303Sobrien	      insn = (insn & 0xffe0ffff) | (lit_insn & 0x001f0000);
106860510Sobrien	      urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
106989862Sobrien					   R_ALPHA_GPREL16);
107060510Sobrien	      urel->r_addend = irel->r_addend;
107160510Sobrien	      info->changed_relocs = true;
107260510Sobrien
107389862Sobrien	      bfd_put_32 (info->abfd, (bfd_vma) insn,
107489862Sobrien			  info->contents + urel->r_offset);
107560510Sobrien	      info->changed_contents = true;
107660510Sobrien	    }
107760510Sobrien
107860510Sobrien	  /* If all mem+byte, we can optimize 32-bit mem displacements.  */
107960510Sobrien	  else if (fits32 && !(flags & ~6))
108060510Sobrien	    {
108177303Sobrien	      /* FIXME: sanity check that lit insn Ra is mem insn Rb.  */
108260510Sobrien
108360510Sobrien	      irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
108460510Sobrien					   R_ALPHA_GPRELHIGH);
108560510Sobrien	      lit_insn = (OP_LDAH << 26) | (lit_insn & 0x03ff0000);
108689862Sobrien	      bfd_put_32 (info->abfd, (bfd_vma) lit_insn,
108760510Sobrien			  info->contents + irel->r_offset);
108860510Sobrien	      lit_reused = true;
108960510Sobrien	      info->changed_contents = true;
109060510Sobrien
109160510Sobrien	      urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
109260510Sobrien					   R_ALPHA_GPRELLOW);
109360510Sobrien	      urel->r_addend = irel->r_addend;
109460510Sobrien	      info->changed_relocs = true;
109560510Sobrien	    }
109660510Sobrien	  else
109760510Sobrien	    all_optimized = false;
109860510Sobrien	  break;
109960510Sobrien
110060510Sobrien	case 2: /* BYTE OFFSET FORMAT */
110160510Sobrien	  /* We can always optimize byte instructions.  */
110260510Sobrien
110360510Sobrien	  /* FIXME: sanity check the insn for byte op.  Check that the
110460510Sobrien	     literal dest reg is indeed Rb in the byte insn.  */
110560510Sobrien
110689862Sobrien	  insn &= ~ (unsigned) 0x001ff000;
110789862Sobrien	  insn |= ((symval & 7) << 13) | 0x1000;
110860510Sobrien
110960510Sobrien	  urel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
111060510Sobrien	  urel->r_addend = 0;
111160510Sobrien	  info->changed_relocs = true;
111260510Sobrien
111389862Sobrien	  bfd_put_32 (info->abfd, (bfd_vma) insn,
111489862Sobrien		      info->contents + urel->r_offset);
111560510Sobrien	  info->changed_contents = true;
111660510Sobrien	  break;
111760510Sobrien
111860510Sobrien	case 3: /* CALL FORMAT */
111960510Sobrien	  {
112060510Sobrien	    /* If not zero, place to jump without needing pv.  */
112160510Sobrien	    bfd_vma optdest = elf64_alpha_relax_opt_call (info, symval);
112260510Sobrien	    bfd_vma org = (info->sec->output_section->vma
112360510Sobrien			   + info->sec->output_offset
112460510Sobrien			   + urel->r_offset + 4);
112560510Sobrien	    bfd_signed_vma odisp;
112660510Sobrien
112760510Sobrien	    odisp = (optdest ? optdest : symval) - org;
112860510Sobrien	    if (odisp >= -0x400000 && odisp < 0x400000)
112960510Sobrien	      {
113060510Sobrien		Elf_Internal_Rela *xrel;
113160510Sobrien
113277303Sobrien		/* Preserve branch prediction call stack when possible.  */
113360510Sobrien		if ((insn & INSN_JSR_MASK) == INSN_JSR)
113460510Sobrien		  insn = (OP_BSR << 26) | (insn & 0x03e00000);
113560510Sobrien		else
113660510Sobrien		  insn = (OP_BR << 26) | (insn & 0x03e00000);
113777303Sobrien
113860510Sobrien		urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
113960510Sobrien					     R_ALPHA_BRADDR);
114060510Sobrien		urel->r_addend = irel->r_addend;
114160510Sobrien
114260510Sobrien		if (optdest)
114360510Sobrien		  urel->r_addend += optdest - symval;
114460510Sobrien		else
114560510Sobrien		  all_optimized = false;
114660510Sobrien
114789862Sobrien		bfd_put_32 (info->abfd, (bfd_vma) insn,
114889862Sobrien			    info->contents + urel->r_offset);
114960510Sobrien
115060510Sobrien		/* Kill any HINT reloc that might exist for this insn.  */
115160510Sobrien		xrel = (elf64_alpha_find_reloc_at_ofs
115277303Sobrien			(info->relocs, info->relend, urel->r_offset,
115360510Sobrien			 R_ALPHA_HINT));
115460510Sobrien		if (xrel)
115560510Sobrien		  xrel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
115660510Sobrien
115760510Sobrien		info->changed_contents = true;
115860510Sobrien		info->changed_relocs = true;
115960510Sobrien	      }
116060510Sobrien	    else
116160510Sobrien	      all_optimized = false;
116260510Sobrien
116389862Sobrien	    /* Even if the target is not in range for a direct branch,
116489862Sobrien	       if we share a GP, we can eliminate the gp reload.  */
116589862Sobrien	    if (optdest)
116689862Sobrien	      {
116789862Sobrien		Elf_Internal_Rela *gpdisp
116889862Sobrien		  = (elf64_alpha_find_reloc_at_ofs
116989862Sobrien		     (irel, irelend, urel->r_offset + 4, R_ALPHA_GPDISP));
117089862Sobrien		if (gpdisp)
117189862Sobrien		  {
117289862Sobrien		    bfd_byte *p_ldah = info->contents + gpdisp->r_offset;
117389862Sobrien		    bfd_byte *p_lda = p_ldah + gpdisp->r_addend;
117489862Sobrien		    unsigned int ldah = bfd_get_32 (info->abfd, p_ldah);
117589862Sobrien		    unsigned int lda = bfd_get_32 (info->abfd, p_lda);
117660510Sobrien
117789862Sobrien		    /* Verify that the instruction is "ldah $29,0($26)".
117889862Sobrien		       Consider a function that ends in a noreturn call,
117989862Sobrien		       and that the next function begins with an ldgp,
118089862Sobrien		       and that by accident there is no padding between.
118189862Sobrien		       In that case the insn would use $27 as the base.  */
118289862Sobrien		    if (ldah == 0x27ba0000 && lda == 0x23bd0000)
118389862Sobrien		      {
118489862Sobrien			bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_ldah);
118589862Sobrien			bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_lda);
118689862Sobrien
118789862Sobrien			gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
118889862Sobrien			info->changed_contents = true;
118989862Sobrien			info->changed_relocs = true;
119089862Sobrien		      }
119189862Sobrien		  }
119289862Sobrien	      }
119360510Sobrien	  }
119460510Sobrien	  break;
119560510Sobrien	}
119660510Sobrien    }
119760510Sobrien
119860510Sobrien  /* If all cases were optimized, we can reduce the use count on this
119960510Sobrien     got entry by one, possibly eliminating it.  */
120060510Sobrien  if (all_optimized)
120160510Sobrien    {
120260510Sobrien      info->gotent->use_count -= 1;
120360510Sobrien      alpha_elf_tdata (info->gotent->gotobj)->total_got_entries -= 1;
120460510Sobrien      if (!info->h)
120560510Sobrien	alpha_elf_tdata (info->gotent->gotobj)->n_local_got_entries -= 1;
120660510Sobrien
120760510Sobrien      /* If the literal instruction is no longer needed (it may have been
120860510Sobrien	 reused.  We can eliminate it.
120960510Sobrien	 ??? For now, I don't want to deal with compacting the section,
121060510Sobrien	 so just nop it out.  */
121160510Sobrien      if (!lit_reused)
121260510Sobrien	{
121360510Sobrien	  irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
121460510Sobrien	  info->changed_relocs = true;
121560510Sobrien
121689862Sobrien	  bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP,
121789862Sobrien		      info->contents + irel->r_offset);
121860510Sobrien	  info->changed_contents = true;
121960510Sobrien	}
122060510Sobrien    }
122160510Sobrien
122260510Sobrien  return irel + count;
122360510Sobrien}
122460510Sobrien
122560510Sobrienstatic bfd_vma
122660510Sobrienelf64_alpha_relax_opt_call (info, symval)
122760510Sobrien     struct alpha_relax_info *info;
122860510Sobrien     bfd_vma symval;
122960510Sobrien{
123060510Sobrien  /* If the function has the same gp, and we can identify that the
123160510Sobrien     function does not use its function pointer, we can eliminate the
123260510Sobrien     address load.  */
123360510Sobrien
123460510Sobrien  /* If the symbol is marked NOPV, we are being told the function never
123560510Sobrien     needs its procedure value.  */
123677303Sobrien  if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_NOPV)
123760510Sobrien    return symval;
123860510Sobrien
123960510Sobrien  /* If the symbol is marked STD_GP, we are being told the function does
124077303Sobrien     a normal ldgp in the first two words.  */
124177303Sobrien  else if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_STD_GPLOAD)
124260510Sobrien    ;
124360510Sobrien
124460510Sobrien  /* Otherwise, we may be able to identify a GP load in the first two
124560510Sobrien     words, which we can then skip.  */
124677303Sobrien  else
124760510Sobrien    {
124860510Sobrien      Elf_Internal_Rela *tsec_relocs, *tsec_relend, *tsec_free, *gpdisp;
124960510Sobrien      bfd_vma ofs;
125060510Sobrien
125177303Sobrien      /* Load the relocations from the section that the target symbol is in.  */
125260510Sobrien      if (info->sec == info->tsec)
125360510Sobrien	{
125460510Sobrien	  tsec_relocs = info->relocs;
125560510Sobrien	  tsec_relend = info->relend;
125660510Sobrien	  tsec_free = NULL;
125760510Sobrien	}
125860510Sobrien      else
125960510Sobrien	{
126060510Sobrien	  tsec_relocs = (_bfd_elf64_link_read_relocs
126160510Sobrien		         (info->abfd, info->tsec, (PTR) NULL,
126260510Sobrien			 (Elf_Internal_Rela *) NULL,
126360510Sobrien			 info->link_info->keep_memory));
126460510Sobrien	  if (tsec_relocs == NULL)
126560510Sobrien	    return 0;
126660510Sobrien	  tsec_relend = tsec_relocs + info->tsec->reloc_count;
126760510Sobrien	  tsec_free = (info->link_info->keep_memory ? NULL : tsec_relocs);
126860510Sobrien	}
126960510Sobrien
127060510Sobrien      /* Recover the symbol's offset within the section.  */
127160510Sobrien      ofs = (symval - info->tsec->output_section->vma
127260510Sobrien	     - info->tsec->output_offset);
127377303Sobrien
127460510Sobrien      /* Look for a GPDISP reloc.  */
127560510Sobrien      gpdisp = (elf64_alpha_find_reloc_at_ofs
127660510Sobrien		(tsec_relocs, tsec_relend, ofs, R_ALPHA_GPDISP));
127760510Sobrien
127860510Sobrien      if (!gpdisp || gpdisp->r_addend != 4)
127960510Sobrien	{
128060510Sobrien	  if (tsec_free)
128160510Sobrien	    free (tsec_free);
128260510Sobrien	  return 0;
128360510Sobrien	}
128460510Sobrien      if (tsec_free)
128560510Sobrien        free (tsec_free);
128660510Sobrien    }
128760510Sobrien
128877303Sobrien  /* We've now determined that we can skip an initial gp load.  Verify
128960510Sobrien     that the call and the target use the same gp.   */
129060510Sobrien  if (info->link_info->hash->creator != info->tsec->owner->xvec
129160510Sobrien      || info->gotobj != alpha_elf_tdata (info->tsec->owner)->gotobj)
129260510Sobrien    return 0;
129360510Sobrien
129460510Sobrien  return symval + 8;
129560510Sobrien}
129660510Sobrien
129760510Sobrienstatic boolean
129860510Sobrienelf64_alpha_relax_without_lituse (info, symval, irel)
129960510Sobrien     struct alpha_relax_info *info;
130060510Sobrien     bfd_vma symval;
130160510Sobrien     Elf_Internal_Rela *irel;
130260510Sobrien{
130360510Sobrien  unsigned int insn;
130460510Sobrien  bfd_signed_vma disp;
130560510Sobrien
130660510Sobrien  /* Get the instruction.  */
130760510Sobrien  insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset);
130860510Sobrien
130960510Sobrien  if (insn >> 26 != OP_LDQ)
131060510Sobrien    {
131160510Sobrien      ((*_bfd_error_handler)
131260510Sobrien       ("%s: %s+0x%lx: warning: LITERAL relocation against unexpected insn",
131389862Sobrien	bfd_archive_filename (info->abfd), info->sec->name,
131460510Sobrien	(unsigned long) irel->r_offset));
131560510Sobrien      return true;
131660510Sobrien    }
131760510Sobrien
131860510Sobrien  /* So we aren't told much.  Do what we can with the address load and
131960510Sobrien     fake the rest.  All of the optimizations here require that the
132060510Sobrien     offset from the GP fit in 16 bits.  */
132160510Sobrien
132260510Sobrien  disp = symval - info->gp;
132360510Sobrien  if (disp < -0x8000 || disp >= 0x8000)
132460510Sobrien    return true;
132560510Sobrien
132660510Sobrien  /* On the LITERAL instruction itself, consider exchanging
132760510Sobrien     `ldq R,X(gp)' for `lda R,Y(gp)'.  */
132860510Sobrien
132960510Sobrien  insn = (OP_LDA << 26) | (insn & 0x03ff0000);
133089862Sobrien  bfd_put_32 (info->abfd, (bfd_vma) insn, info->contents + irel->r_offset);
133160510Sobrien  info->changed_contents = true;
133260510Sobrien
133389862Sobrien  irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), R_ALPHA_GPREL16);
133460510Sobrien  info->changed_relocs = true;
133560510Sobrien
133660510Sobrien  /* Reduce the use count on this got entry by one, possibly
133760510Sobrien     eliminating it.  */
133860510Sobrien  info->gotent->use_count -= 1;
133960510Sobrien  alpha_elf_tdata (info->gotent->gotobj)->total_got_entries -= 1;
134060510Sobrien  if (!info->h)
134160510Sobrien    alpha_elf_tdata (info->gotent->gotobj)->n_local_got_entries -= 1;
134260510Sobrien
134360510Sobrien  /* ??? Search forward through this basic block looking for insns
134460510Sobrien     that use the target register.  Stop after an insn modifying the
134560510Sobrien     register is seen, or after a branch or call.
134660510Sobrien
134760510Sobrien     Any such memory load insn may be substituted by a load directly
134860510Sobrien     off the GP.  This allows the memory load insn to be issued before
134977303Sobrien     the calculated GP register would otherwise be ready.
135060510Sobrien
135160510Sobrien     Any such jsr insn can be replaced by a bsr if it is in range.
135260510Sobrien
135360510Sobrien     This would mean that we'd have to _add_ relocations, the pain of
135460510Sobrien     which gives one pause.  */
135560510Sobrien
135660510Sobrien  return true;
135760510Sobrien}
135860510Sobrien
135960510Sobrienstatic boolean
136060510Sobrienelf64_alpha_relax_section (abfd, sec, link_info, again)
136160510Sobrien     bfd *abfd;
136260510Sobrien     asection *sec;
136360510Sobrien     struct bfd_link_info *link_info;
136460510Sobrien     boolean *again;
136560510Sobrien{
136660510Sobrien  Elf_Internal_Shdr *symtab_hdr;
136789862Sobrien  Elf_Internal_Shdr *shndx_hdr;
136860510Sobrien  Elf_Internal_Rela *internal_relocs;
136960510Sobrien  Elf_Internal_Rela *free_relocs = NULL;
137060510Sobrien  Elf_Internal_Rela *irel, *irelend;
137160510Sobrien  bfd_byte *free_contents = NULL;
137260510Sobrien  Elf64_External_Sym *extsyms = NULL;
137360510Sobrien  Elf64_External_Sym *free_extsyms = NULL;
137489862Sobrien  Elf_External_Sym_Shndx *shndx_buf = NULL;
137560510Sobrien  struct alpha_elf_got_entry **local_got_entries;
137660510Sobrien  struct alpha_relax_info info;
137760510Sobrien
137860510Sobrien  /* We are not currently changing any sizes, so only one pass.  */
137960510Sobrien  *again = false;
138060510Sobrien
138160510Sobrien  if (link_info->relocateable
138260510Sobrien      || (sec->flags & SEC_RELOC) == 0
138360510Sobrien      || sec->reloc_count == 0)
138460510Sobrien    return true;
138560510Sobrien
138660510Sobrien  /* If this is the first time we have been called for this section,
138760510Sobrien     initialize the cooked size.  */
138860510Sobrien  if (sec->_cooked_size == 0)
138960510Sobrien    sec->_cooked_size = sec->_raw_size;
139060510Sobrien
139160510Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
139260510Sobrien  local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
139360510Sobrien
139460510Sobrien  /* Load the relocations for this section.  */
139560510Sobrien  internal_relocs = (_bfd_elf64_link_read_relocs
139660510Sobrien		     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
139760510Sobrien		      link_info->keep_memory));
139860510Sobrien  if (internal_relocs == NULL)
139960510Sobrien    goto error_return;
140060510Sobrien  if (! link_info->keep_memory)
140160510Sobrien    free_relocs = internal_relocs;
140260510Sobrien
140377303Sobrien  memset(&info, 0, sizeof (info));
140460510Sobrien  info.abfd = abfd;
140560510Sobrien  info.sec = sec;
140660510Sobrien  info.link_info = link_info;
140760510Sobrien  info.relocs = internal_relocs;
140860510Sobrien  info.relend = irelend = internal_relocs + sec->reloc_count;
140960510Sobrien
141060510Sobrien  /* Find the GP for this object.  */
141160510Sobrien  info.gotobj = alpha_elf_tdata (abfd)->gotobj;
141260510Sobrien  if (info.gotobj)
141360510Sobrien    {
141460510Sobrien      asection *sgot = alpha_elf_tdata (info.gotobj)->got;
141560510Sobrien      info.gp = _bfd_get_gp_value (info.gotobj);
141660510Sobrien      if (info.gp == 0)
141760510Sobrien	{
141860510Sobrien	  info.gp = (sgot->output_section->vma
141960510Sobrien		     + sgot->output_offset
142060510Sobrien		     + 0x8000);
142160510Sobrien	  _bfd_set_gp_value (info.gotobj, info.gp);
142260510Sobrien	}
142360510Sobrien    }
142460510Sobrien
142560510Sobrien  for (irel = internal_relocs; irel < irelend; irel++)
142660510Sobrien    {
142760510Sobrien      bfd_vma symval;
142860510Sobrien      Elf_Internal_Sym isym;
142960510Sobrien      struct alpha_elf_got_entry *gotent;
143060510Sobrien
143160510Sobrien      if (ELF64_R_TYPE (irel->r_info) != (int) R_ALPHA_LITERAL)
143260510Sobrien	continue;
143360510Sobrien
143460510Sobrien      /* Get the section contents.  */
143560510Sobrien      if (info.contents == NULL)
143660510Sobrien	{
143760510Sobrien	  if (elf_section_data (sec)->this_hdr.contents != NULL)
143860510Sobrien	    info.contents = elf_section_data (sec)->this_hdr.contents;
143960510Sobrien	  else
144060510Sobrien	    {
144160510Sobrien	      info.contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
144260510Sobrien	      if (info.contents == NULL)
144360510Sobrien		goto error_return;
144460510Sobrien	      free_contents = info.contents;
144560510Sobrien
144660510Sobrien	      if (! bfd_get_section_contents (abfd, sec, info.contents,
144760510Sobrien					      (file_ptr) 0, sec->_raw_size))
144860510Sobrien		goto error_return;
144960510Sobrien	    }
145060510Sobrien	}
145160510Sobrien
145260510Sobrien      /* Read this BFD's symbols if we haven't done so already.  */
145360510Sobrien      if (extsyms == NULL)
145460510Sobrien	{
145589862Sobrien	  bfd_size_type amt;
145689862Sobrien
145760510Sobrien	  if (symtab_hdr->contents != NULL)
145860510Sobrien	    extsyms = (Elf64_External_Sym *) symtab_hdr->contents;
145960510Sobrien	  else
146060510Sobrien	    {
146189862Sobrien	      amt = symtab_hdr->sh_info;
146289862Sobrien	      amt *= sizeof (Elf64_External_Sym);
146389862Sobrien	      extsyms = (Elf64_External_Sym *) bfd_malloc (amt);
146460510Sobrien	      if (extsyms == NULL)
146560510Sobrien		goto error_return;
146660510Sobrien	      free_extsyms = extsyms;
146760510Sobrien	      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
146889862Sobrien		  || bfd_bread ((PTR) extsyms, amt, abfd) != amt)
146960510Sobrien		goto error_return;
147060510Sobrien	    }
147189862Sobrien
147289862Sobrien	  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
147389862Sobrien	  if (shndx_hdr->sh_size != 0)
147489862Sobrien	    {
147589862Sobrien	      amt = symtab_hdr->sh_info;
147689862Sobrien	      amt *= sizeof (Elf_External_Sym_Shndx);
147789862Sobrien	      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
147889862Sobrien	      if (shndx_buf == NULL)
147989862Sobrien		goto error_return;
148089862Sobrien	      if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
148189862Sobrien		  || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
148289862Sobrien		goto error_return;
148389862Sobrien	    }
148460510Sobrien	}
148560510Sobrien
148660510Sobrien      /* Get the value of the symbol referred to by the reloc.  */
148760510Sobrien      if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
148860510Sobrien	{
148960510Sobrien	  /* A local symbol.  */
149089862Sobrien	  Elf64_External_Sym *esym;
149189862Sobrien	  Elf_External_Sym_Shndx *shndx;
149289862Sobrien
149389862Sobrien	  esym = extsyms + ELF64_R_SYM (irel->r_info);
149489862Sobrien	  shndx = shndx_buf + (shndx_buf ? ELF64_R_SYM (irel->r_info) : 0);
149589862Sobrien	  bfd_elf64_swap_symbol_in (abfd, esym, shndx, &isym);
149660510Sobrien	  if (isym.st_shndx == SHN_UNDEF)
149760510Sobrien	    info.tsec = bfd_und_section_ptr;
149860510Sobrien	  else if (isym.st_shndx == SHN_ABS)
149960510Sobrien	    info.tsec = bfd_abs_section_ptr;
150060510Sobrien	  else if (isym.st_shndx == SHN_COMMON)
150160510Sobrien	    info.tsec = bfd_com_section_ptr;
150277303Sobrien	  else
150389862Sobrien	    info.tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
150460510Sobrien
150560510Sobrien	  info.h = NULL;
150660510Sobrien	  info.other = isym.st_other;
150760510Sobrien	  gotent = local_got_entries[ELF64_R_SYM(irel->r_info)];
150860510Sobrien	  symval = isym.st_value;
150960510Sobrien	}
151060510Sobrien      else
151160510Sobrien	{
151260510Sobrien	  unsigned long indx;
151360510Sobrien	  struct alpha_elf_link_hash_entry *h;
151460510Sobrien
151560510Sobrien	  indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info;
151660510Sobrien	  h = alpha_elf_sym_hashes (abfd)[indx];
151760510Sobrien	  BFD_ASSERT (h != NULL);
151860510Sobrien
151960510Sobrien	  while (h->root.root.type == bfd_link_hash_indirect
152060510Sobrien		 || h->root.root.type == bfd_link_hash_warning)
152160510Sobrien	    h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
152260510Sobrien
152360510Sobrien	  /* We can't do anthing with undefined or dynamic symbols.  */
152460510Sobrien	  if (h->root.root.type == bfd_link_hash_undefined
152560510Sobrien	      || h->root.root.type == bfd_link_hash_undefweak
152660510Sobrien	      || alpha_elf_dynamic_symbol_p (&h->root, link_info))
152760510Sobrien	    continue;
152860510Sobrien
152960510Sobrien	  info.h = h;
153060510Sobrien	  info.tsec = h->root.root.u.def.section;
153160510Sobrien	  info.other = h->root.other;
153260510Sobrien	  gotent = h->got_entries;
153360510Sobrien	  symval = h->root.root.u.def.value;
153460510Sobrien	}
153560510Sobrien
153660510Sobrien      /* Search for the got entry to be used by this relocation.  */
153760510Sobrien      while (gotent->gotobj != info.gotobj || gotent->addend != irel->r_addend)
153860510Sobrien	gotent = gotent->next;
153960510Sobrien      info.gotent = gotent;
154060510Sobrien
154160510Sobrien      symval += info.tsec->output_section->vma + info.tsec->output_offset;
154260510Sobrien      symval += irel->r_addend;
154360510Sobrien
154460510Sobrien      BFD_ASSERT(info.gotent != NULL);
154560510Sobrien
154660510Sobrien      /* If there exist LITUSE relocations immediately following, this
154760510Sobrien	 opens up all sorts of interesting optimizations, because we
154860510Sobrien	 now know every location that this address load is used.  */
154960510Sobrien
155060510Sobrien      if (irel+1 < irelend && ELF64_R_TYPE (irel[1].r_info) == R_ALPHA_LITUSE)
155160510Sobrien	{
155260510Sobrien	  irel = elf64_alpha_relax_with_lituse (&info, symval, irel, irelend);
155360510Sobrien	  if (irel == NULL)
155460510Sobrien	    goto error_return;
155560510Sobrien	}
155660510Sobrien      else
155760510Sobrien	{
155860510Sobrien	  if (!elf64_alpha_relax_without_lituse (&info, symval, irel))
155960510Sobrien	    goto error_return;
156060510Sobrien	}
156160510Sobrien    }
156260510Sobrien
156360510Sobrien  if (!elf64_alpha_size_got_sections (abfd, link_info))
156460510Sobrien    return false;
156560510Sobrien
156660510Sobrien  if (info.changed_relocs)
156760510Sobrien    {
156860510Sobrien      elf_section_data (sec)->relocs = internal_relocs;
156960510Sobrien    }
157060510Sobrien  else if (free_relocs != NULL)
157160510Sobrien    {
157260510Sobrien      free (free_relocs);
157360510Sobrien    }
157460510Sobrien
157560510Sobrien  if (info.changed_contents)
157660510Sobrien    {
157760510Sobrien      elf_section_data (sec)->this_hdr.contents = info.contents;
157860510Sobrien    }
157960510Sobrien  else if (free_contents != NULL)
158060510Sobrien    {
158160510Sobrien      if (! link_info->keep_memory)
158260510Sobrien	free (free_contents);
158360510Sobrien      else
158460510Sobrien	{
158560510Sobrien	  /* Cache the section contents for elf_link_input_bfd.  */
158660510Sobrien	  elf_section_data (sec)->this_hdr.contents = info.contents;
158760510Sobrien	}
158860510Sobrien    }
158960510Sobrien
159089862Sobrien  if (shndx_buf != NULL)
159189862Sobrien    free (shndx_buf);
159289862Sobrien
159360510Sobrien  if (free_extsyms != NULL)
159460510Sobrien    {
159560510Sobrien      if (! link_info->keep_memory)
159660510Sobrien	free (free_extsyms);
159760510Sobrien      else
159860510Sobrien	{
159960510Sobrien	  /* Cache the symbols for elf_link_input_bfd.  */
160089862Sobrien	  symtab_hdr->contents = (unsigned char *) extsyms;
160160510Sobrien	}
160260510Sobrien    }
160360510Sobrien
160460510Sobrien  *again = info.changed_contents || info.changed_relocs;
160560510Sobrien
160660510Sobrien  return true;
160760510Sobrien
160860510Sobrien error_return:
160960510Sobrien  if (free_relocs != NULL)
161060510Sobrien    free (free_relocs);
161160510Sobrien  if (free_contents != NULL)
161260510Sobrien    free (free_contents);
161389862Sobrien  if (shndx_buf != NULL)
161489862Sobrien    free (shndx_buf);
161560510Sobrien  if (free_extsyms != NULL)
161660510Sobrien    free (free_extsyms);
161760510Sobrien  return false;
161860510Sobrien}
161960510Sobrien
162033965Sjdp/* PLT/GOT Stuff */
162133965Sjdp#define PLT_HEADER_SIZE 32
162289862Sobrien#define PLT_HEADER_WORD1	(bfd_vma) 0xc3600000	/* br   $27,.+4     */
162389862Sobrien#define PLT_HEADER_WORD2	(bfd_vma) 0xa77b000c	/* ldq  $27,12($27) */
162489862Sobrien#define PLT_HEADER_WORD3	(bfd_vma) 0x47ff041f	/* nop              */
162589862Sobrien#define PLT_HEADER_WORD4	(bfd_vma) 0x6b7b0000	/* jmp  $27,($27)   */
162633965Sjdp
162733965Sjdp#define PLT_ENTRY_SIZE 12
162838889Sjdp#define PLT_ENTRY_WORD1		0xc3800000	/* br   $28, plt0   */
162938889Sjdp#define PLT_ENTRY_WORD2		0
163038889Sjdp#define PLT_ENTRY_WORD3		0
163133965Sjdp
163233965Sjdp#define MAX_GOT_ENTRIES		(64*1024 / 8)
163333965Sjdp
163468770Sobrien#ifndef ELF_DYNAMIC_INTERPRETER
163568770Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so"
163668770Sobrien#endif
163733965Sjdp
163833965Sjdp/* Handle an Alpha specific section when reading an object file.  This
163933965Sjdp   is called when elfcode.h finds a section with an unknown type.
164060510Sobrien   FIXME: We need to handle the SHF_ALPHA_GPREL flag, but I'm not sure
164133965Sjdp   how to.  */
164233965Sjdp
164333965Sjdpstatic boolean
164433965Sjdpelf64_alpha_section_from_shdr (abfd, hdr, name)
164533965Sjdp     bfd *abfd;
164633965Sjdp     Elf64_Internal_Shdr *hdr;
164733965Sjdp     char *name;
164833965Sjdp{
164933965Sjdp  asection *newsect;
165033965Sjdp
165133965Sjdp  /* There ought to be a place to keep ELF backend specific flags, but
165233965Sjdp     at the moment there isn't one.  We just keep track of the
165333965Sjdp     sections by their name, instead.  Fortunately, the ABI gives
165433965Sjdp     suggested names for all the MIPS specific sections, so we will
165533965Sjdp     probably get away with this.  */
165633965Sjdp  switch (hdr->sh_type)
165733965Sjdp    {
165833965Sjdp    case SHT_ALPHA_DEBUG:
165933965Sjdp      if (strcmp (name, ".mdebug") != 0)
166033965Sjdp	return false;
166133965Sjdp      break;
166233965Sjdp    default:
166333965Sjdp      return false;
166433965Sjdp    }
166533965Sjdp
166633965Sjdp  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
166733965Sjdp    return false;
166833965Sjdp  newsect = hdr->bfd_section;
166933965Sjdp
167033965Sjdp  if (hdr->sh_type == SHT_ALPHA_DEBUG)
167133965Sjdp    {
167233965Sjdp      if (! bfd_set_section_flags (abfd, newsect,
167333965Sjdp				   (bfd_get_section_flags (abfd, newsect)
167433965Sjdp				    | SEC_DEBUGGING)))
167533965Sjdp	return false;
167633965Sjdp    }
167733965Sjdp
167889862Sobrien  return true;
167989862Sobrien}
168033965Sjdp
168189862Sobrien/* Convert Alpha specific section flags to bfd internal section flags.  */
168233965Sjdp
168389862Sobrienstatic boolean
168489862Sobrienelf64_alpha_section_flags (flags, hdr)
168589862Sobrien     flagword *flags;
168689862Sobrien     Elf64_Internal_Shdr *hdr;
168789862Sobrien{
168889862Sobrien  if (hdr->sh_flags & SHF_ALPHA_GPREL)
168989862Sobrien    *flags |= SEC_SMALL_DATA;
169089862Sobrien
169133965Sjdp  return true;
169233965Sjdp}
169333965Sjdp
169433965Sjdp/* Set the correct type for an Alpha ELF section.  We do this by the
169533965Sjdp   section name, which is a hack, but ought to work.  */
169633965Sjdp
169733965Sjdpstatic boolean
169833965Sjdpelf64_alpha_fake_sections (abfd, hdr, sec)
169933965Sjdp     bfd *abfd;
170033965Sjdp     Elf64_Internal_Shdr *hdr;
170133965Sjdp     asection *sec;
170233965Sjdp{
170333965Sjdp  register const char *name;
170433965Sjdp
170533965Sjdp  name = bfd_get_section_name (abfd, sec);
170633965Sjdp
170733965Sjdp  if (strcmp (name, ".mdebug") == 0)
170833965Sjdp    {
170933965Sjdp      hdr->sh_type = SHT_ALPHA_DEBUG;
171033965Sjdp      /* In a shared object on Irix 5.3, the .mdebug section has an
171133965Sjdp         entsize of 0.  FIXME: Does this matter?  */
171233965Sjdp      if ((abfd->flags & DYNAMIC) != 0 )
171333965Sjdp	hdr->sh_entsize = 0;
171433965Sjdp      else
171533965Sjdp	hdr->sh_entsize = 1;
171633965Sjdp    }
171789862Sobrien  else if ((sec->flags & SEC_SMALL_DATA)
171889862Sobrien	   || strcmp (name, ".sdata") == 0
171933965Sjdp	   || strcmp (name, ".sbss") == 0
172033965Sjdp	   || strcmp (name, ".lit4") == 0
172133965Sjdp	   || strcmp (name, ".lit8") == 0)
172233965Sjdp    hdr->sh_flags |= SHF_ALPHA_GPREL;
172333965Sjdp
172433965Sjdp  return true;
172533965Sjdp}
172633965Sjdp
172760510Sobrien/* Hook called by the linker routine which adds symbols from an object
172860510Sobrien   file.  We use it to put .comm items in .sbss, and not .bss.  */
172933965Sjdp
173060510Sobrienstatic boolean
173160510Sobrienelf64_alpha_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
173233965Sjdp     bfd *abfd;
173360510Sobrien     struct bfd_link_info *info;
173460510Sobrien     const Elf_Internal_Sym *sym;
173578833Sobrien     const char **namep ATTRIBUTE_UNUSED;
173678833Sobrien     flagword *flagsp ATTRIBUTE_UNUSED;
173760510Sobrien     asection **secp;
173860510Sobrien     bfd_vma *valp;
173933965Sjdp{
174060510Sobrien  if (sym->st_shndx == SHN_COMMON
174160510Sobrien      && !info->relocateable
174289862Sobrien      && sym->st_size <= elf_gp_size (abfd))
174360510Sobrien    {
174460510Sobrien      /* Common symbols less than or equal to -G nn bytes are
174560510Sobrien	 automatically put into .sbss.  */
174633965Sjdp
174760510Sobrien      asection *scomm = bfd_get_section_by_name (abfd, ".scommon");
174833965Sjdp
174960510Sobrien      if (scomm == NULL)
175060510Sobrien	{
175160510Sobrien	  scomm = bfd_make_section (abfd, ".scommon");
175260510Sobrien	  if (scomm == NULL
175360510Sobrien	      || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC
175460510Sobrien						       | SEC_IS_COMMON
175560510Sobrien						       | SEC_LINKER_CREATED)))
175660510Sobrien	    return false;
175760510Sobrien	}
175833965Sjdp
175960510Sobrien      *secp = scomm;
176060510Sobrien      *valp = sym->st_size;
176133965Sjdp    }
176233965Sjdp
176360510Sobrien  return true;
176433965Sjdp}
176533965Sjdp
176633965Sjdp/* Create the .got section.  */
176733965Sjdp
176833965Sjdpstatic boolean
176933965Sjdpelf64_alpha_create_got_section(abfd, info)
177033965Sjdp     bfd *abfd;
177178833Sobrien     struct bfd_link_info *info ATTRIBUTE_UNUSED;
177233965Sjdp{
177333965Sjdp  asection *s;
177433965Sjdp
177533965Sjdp  if (bfd_get_section_by_name (abfd, ".got"))
177633965Sjdp    return true;
177733965Sjdp
177833965Sjdp  s = bfd_make_section (abfd, ".got");
177933965Sjdp  if (s == NULL
178033965Sjdp      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
178133965Sjdp					   | SEC_HAS_CONTENTS
178233965Sjdp					   | SEC_IN_MEMORY
178333965Sjdp					   | SEC_LINKER_CREATED))
178433965Sjdp      || !bfd_set_section_alignment (abfd, s, 3))
178533965Sjdp    return false;
178633965Sjdp
178733965Sjdp  alpha_elf_tdata (abfd)->got = s;
178833965Sjdp
178933965Sjdp  return true;
179033965Sjdp}
179133965Sjdp
179233965Sjdp/* Create all the dynamic sections.  */
179333965Sjdp
179433965Sjdpstatic boolean
179533965Sjdpelf64_alpha_create_dynamic_sections (abfd, info)
179633965Sjdp     bfd *abfd;
179733965Sjdp     struct bfd_link_info *info;
179833965Sjdp{
179933965Sjdp  asection *s;
180033965Sjdp  struct elf_link_hash_entry *h;
180133965Sjdp
180233965Sjdp  /* We need to create .plt, .rela.plt, .got, and .rela.got sections.  */
180333965Sjdp
180433965Sjdp  s = bfd_make_section (abfd, ".plt");
180533965Sjdp  if (s == NULL
180633965Sjdp      || ! bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
180733965Sjdp					    | SEC_HAS_CONTENTS
180833965Sjdp					    | SEC_IN_MEMORY
180933965Sjdp					    | SEC_LINKER_CREATED
181033965Sjdp					    | SEC_CODE))
181133965Sjdp      || ! bfd_set_section_alignment (abfd, s, 3))
181233965Sjdp    return false;
181333965Sjdp
181433965Sjdp  /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
181533965Sjdp     .plt section.  */
181633965Sjdp  h = NULL;
181733965Sjdp  if (! (_bfd_generic_link_add_one_symbol
181833965Sjdp	 (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s,
181933965Sjdp	  (bfd_vma) 0, (const char *) NULL, false,
182033965Sjdp	  get_elf_backend_data (abfd)->collect,
182133965Sjdp	  (struct bfd_link_hash_entry **) &h)))
182233965Sjdp    return false;
182333965Sjdp  h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
182433965Sjdp  h->type = STT_OBJECT;
182533965Sjdp
182633965Sjdp  if (info->shared
182733965Sjdp      && ! _bfd_elf_link_record_dynamic_symbol (info, h))
182833965Sjdp    return false;
182933965Sjdp
183033965Sjdp  s = bfd_make_section (abfd, ".rela.plt");
183133965Sjdp  if (s == NULL
183233965Sjdp      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
183333965Sjdp					   | SEC_HAS_CONTENTS
183433965Sjdp					   | SEC_IN_MEMORY
183533965Sjdp					   | SEC_LINKER_CREATED
183633965Sjdp					   | SEC_READONLY))
183733965Sjdp      || ! bfd_set_section_alignment (abfd, s, 3))
183833965Sjdp    return false;
183933965Sjdp
184033965Sjdp  /* We may or may not have created a .got section for this object, but
184133965Sjdp     we definitely havn't done the rest of the work.  */
184233965Sjdp
184333965Sjdp  if (!elf64_alpha_create_got_section (abfd, info))
184433965Sjdp    return false;
184533965Sjdp
184633965Sjdp  s = bfd_make_section(abfd, ".rela.got");
184733965Sjdp  if (s == NULL
184833965Sjdp      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
184933965Sjdp					   | SEC_HAS_CONTENTS
185033965Sjdp					   | SEC_IN_MEMORY
185133965Sjdp					   | SEC_LINKER_CREATED
185233965Sjdp					   | SEC_READONLY))
185333965Sjdp      || !bfd_set_section_alignment (abfd, s, 3))
185433965Sjdp    return false;
185533965Sjdp
185633965Sjdp  /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the
185733965Sjdp     dynobj's .got section.  We don't do this in the linker script
185833965Sjdp     because we don't want to define the symbol if we are not creating
185933965Sjdp     a global offset table.  */
186033965Sjdp  h = NULL;
186133965Sjdp  if (!(_bfd_generic_link_add_one_symbol
186233965Sjdp	(info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL,
186333965Sjdp	 alpha_elf_tdata(abfd)->got, (bfd_vma) 0, (const char *) NULL,
186433965Sjdp	 false, get_elf_backend_data (abfd)->collect,
186533965Sjdp	 (struct bfd_link_hash_entry **) &h)))
186633965Sjdp    return false;
186733965Sjdp  h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
186833965Sjdp  h->type = STT_OBJECT;
186933965Sjdp
187033965Sjdp  if (info->shared
187133965Sjdp      && ! _bfd_elf_link_record_dynamic_symbol (info, h))
187233965Sjdp    return false;
187333965Sjdp
187433965Sjdp  elf_hash_table (info)->hgot = h;
187533965Sjdp
187633965Sjdp  return true;
187733965Sjdp}
187833965Sjdp
187933965Sjdp/* Read ECOFF debugging information from a .mdebug section into a
188033965Sjdp   ecoff_debug_info structure.  */
188133965Sjdp
188233965Sjdpstatic boolean
188333965Sjdpelf64_alpha_read_ecoff_info (abfd, section, debug)
188433965Sjdp     bfd *abfd;
188533965Sjdp     asection *section;
188633965Sjdp     struct ecoff_debug_info *debug;
188733965Sjdp{
188833965Sjdp  HDRR *symhdr;
188933965Sjdp  const struct ecoff_debug_swap *swap;
189033965Sjdp  char *ext_hdr = NULL;
189133965Sjdp
189233965Sjdp  swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
189377303Sobrien  memset (debug, 0, sizeof (*debug));
189433965Sjdp
189589862Sobrien  ext_hdr = (char *) bfd_malloc (swap->external_hdr_size);
189633965Sjdp  if (ext_hdr == NULL && swap->external_hdr_size != 0)
189733965Sjdp    goto error_return;
189833965Sjdp
189933965Sjdp  if (bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0,
190033965Sjdp				swap->external_hdr_size)
190133965Sjdp      == false)
190233965Sjdp    goto error_return;
190333965Sjdp
190433965Sjdp  symhdr = &debug->symbolic_header;
190533965Sjdp  (*swap->swap_hdr_in) (abfd, ext_hdr, symhdr);
190633965Sjdp
190733965Sjdp  /* The symbolic header contains absolute file offsets and sizes to
190833965Sjdp     read.  */
190933965Sjdp#define READ(ptr, offset, count, size, type)				\
191033965Sjdp  if (symhdr->count == 0)						\
191133965Sjdp    debug->ptr = NULL;							\
191233965Sjdp  else									\
191333965Sjdp    {									\
191489862Sobrien      bfd_size_type amt = (bfd_size_type) size * symhdr->count;		\
191589862Sobrien      debug->ptr = (type) bfd_malloc (amt);				\
191633965Sjdp      if (debug->ptr == NULL)						\
191733965Sjdp	goto error_return;						\
191833965Sjdp      if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0	\
191989862Sobrien	  || bfd_bread (debug->ptr, amt, abfd) != amt)			\
192033965Sjdp	goto error_return;						\
192133965Sjdp    }
192233965Sjdp
192333965Sjdp  READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
192433965Sjdp  READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR);
192533965Sjdp  READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR);
192633965Sjdp  READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR);
192733965Sjdp  READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR);
192833965Sjdp  READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
192933965Sjdp	union aux_ext *);
193033965Sjdp  READ (ss, cbSsOffset, issMax, sizeof (char), char *);
193133965Sjdp  READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *);
193233965Sjdp  READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR);
193333965Sjdp  READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR);
193433965Sjdp  READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, PTR);
193533965Sjdp#undef READ
193633965Sjdp
193733965Sjdp  debug->fdr = NULL;
193833965Sjdp  debug->adjust = NULL;
193933965Sjdp
194033965Sjdp  return true;
194133965Sjdp
194233965Sjdp error_return:
194333965Sjdp  if (ext_hdr != NULL)
194433965Sjdp    free (ext_hdr);
194533965Sjdp  if (debug->line != NULL)
194633965Sjdp    free (debug->line);
194733965Sjdp  if (debug->external_dnr != NULL)
194833965Sjdp    free (debug->external_dnr);
194933965Sjdp  if (debug->external_pdr != NULL)
195033965Sjdp    free (debug->external_pdr);
195133965Sjdp  if (debug->external_sym != NULL)
195233965Sjdp    free (debug->external_sym);
195333965Sjdp  if (debug->external_opt != NULL)
195433965Sjdp    free (debug->external_opt);
195533965Sjdp  if (debug->external_aux != NULL)
195633965Sjdp    free (debug->external_aux);
195733965Sjdp  if (debug->ss != NULL)
195833965Sjdp    free (debug->ss);
195933965Sjdp  if (debug->ssext != NULL)
196033965Sjdp    free (debug->ssext);
196133965Sjdp  if (debug->external_fdr != NULL)
196233965Sjdp    free (debug->external_fdr);
196333965Sjdp  if (debug->external_rfd != NULL)
196433965Sjdp    free (debug->external_rfd);
196533965Sjdp  if (debug->external_ext != NULL)
196633965Sjdp    free (debug->external_ext);
196733965Sjdp  return false;
196833965Sjdp}
196933965Sjdp
197033965Sjdp/* Alpha ELF local labels start with '$'.  */
197133965Sjdp
197233965Sjdpstatic boolean
197333965Sjdpelf64_alpha_is_local_label_name (abfd, name)
197478833Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
197533965Sjdp     const char *name;
197633965Sjdp{
197733965Sjdp  return name[0] == '$';
197833965Sjdp}
197933965Sjdp
198033965Sjdp/* Alpha ELF follows MIPS ELF in using a special find_nearest_line
198133965Sjdp   routine in order to handle the ECOFF debugging information.  We
198233965Sjdp   still call this mips_elf_find_line because of the slot
198333965Sjdp   find_line_info in elf_obj_tdata is declared that way.  */
198433965Sjdp
198533965Sjdpstruct mips_elf_find_line
198633965Sjdp{
198733965Sjdp  struct ecoff_debug_info d;
198833965Sjdp  struct ecoff_find_line i;
198933965Sjdp};
199033965Sjdp
199133965Sjdpstatic boolean
199233965Sjdpelf64_alpha_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
199333965Sjdp			       functionname_ptr, line_ptr)
199433965Sjdp     bfd *abfd;
199533965Sjdp     asection *section;
199633965Sjdp     asymbol **symbols;
199733965Sjdp     bfd_vma offset;
199833965Sjdp     const char **filename_ptr;
199933965Sjdp     const char **functionname_ptr;
200033965Sjdp     unsigned int *line_ptr;
200133965Sjdp{
200233965Sjdp  asection *msec;
200333965Sjdp
200477303Sobrien  if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
200577303Sobrien				     filename_ptr, functionname_ptr,
200677303Sobrien				     line_ptr, 0,
200777303Sobrien				     &elf_tdata (abfd)->dwarf2_find_line_info))
200877303Sobrien    return true;
200977303Sobrien
201033965Sjdp  msec = bfd_get_section_by_name (abfd, ".mdebug");
201133965Sjdp  if (msec != NULL)
201233965Sjdp    {
201333965Sjdp      flagword origflags;
201433965Sjdp      struct mips_elf_find_line *fi;
201533965Sjdp      const struct ecoff_debug_swap * const swap =
201633965Sjdp	get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
201733965Sjdp
201833965Sjdp      /* If we are called during a link, alpha_elf_final_link may have
201933965Sjdp	 cleared the SEC_HAS_CONTENTS field.  We force it back on here
202033965Sjdp	 if appropriate (which it normally will be).  */
202133965Sjdp      origflags = msec->flags;
202233965Sjdp      if (elf_section_data (msec)->this_hdr.sh_type != SHT_NOBITS)
202333965Sjdp	msec->flags |= SEC_HAS_CONTENTS;
202433965Sjdp
202533965Sjdp      fi = elf_tdata (abfd)->find_line_info;
202633965Sjdp      if (fi == NULL)
202733965Sjdp	{
202833965Sjdp	  bfd_size_type external_fdr_size;
202933965Sjdp	  char *fraw_src;
203033965Sjdp	  char *fraw_end;
203133965Sjdp	  struct fdr *fdr_ptr;
203289862Sobrien	  bfd_size_type amt = sizeof (struct mips_elf_find_line);
203333965Sjdp
203489862Sobrien	  fi = (struct mips_elf_find_line *) bfd_zalloc (abfd, amt);
203533965Sjdp	  if (fi == NULL)
203633965Sjdp	    {
203733965Sjdp	      msec->flags = origflags;
203833965Sjdp	      return false;
203933965Sjdp	    }
204033965Sjdp
204133965Sjdp	  if (!elf64_alpha_read_ecoff_info (abfd, msec, &fi->d))
204233965Sjdp	    {
204333965Sjdp	      msec->flags = origflags;
204433965Sjdp	      return false;
204533965Sjdp	    }
204633965Sjdp
204733965Sjdp	  /* Swap in the FDR information.  */
204889862Sobrien	  amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr);
204989862Sobrien	  fi->d.fdr = (struct fdr *) bfd_alloc (abfd, amt);
205033965Sjdp	  if (fi->d.fdr == NULL)
205133965Sjdp	    {
205233965Sjdp	      msec->flags = origflags;
205333965Sjdp	      return false;
205433965Sjdp	    }
205533965Sjdp	  external_fdr_size = swap->external_fdr_size;
205633965Sjdp	  fdr_ptr = fi->d.fdr;
205733965Sjdp	  fraw_src = (char *) fi->d.external_fdr;
205833965Sjdp	  fraw_end = (fraw_src
205933965Sjdp		      + fi->d.symbolic_header.ifdMax * external_fdr_size);
206033965Sjdp	  for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
206133965Sjdp	    (*swap->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr);
206233965Sjdp
206333965Sjdp	  elf_tdata (abfd)->find_line_info = fi;
206433965Sjdp
206533965Sjdp	  /* Note that we don't bother to ever free this information.
206633965Sjdp             find_nearest_line is either called all the time, as in
206733965Sjdp             objdump -l, so the information should be saved, or it is
206833965Sjdp             rarely called, as in ld error messages, so the memory
206933965Sjdp             wasted is unimportant.  Still, it would probably be a
207033965Sjdp             good idea for free_cached_info to throw it away.  */
207133965Sjdp	}
207233965Sjdp
207333965Sjdp      if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap,
207433965Sjdp				  &fi->i, filename_ptr, functionname_ptr,
207533965Sjdp				  line_ptr))
207633965Sjdp	{
207733965Sjdp	  msec->flags = origflags;
207833965Sjdp	  return true;
207933965Sjdp	}
208033965Sjdp
208133965Sjdp      msec->flags = origflags;
208233965Sjdp    }
208333965Sjdp
208433965Sjdp  /* Fall back on the generic ELF find_nearest_line routine.  */
208533965Sjdp
208633965Sjdp  return _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
208733965Sjdp				     filename_ptr, functionname_ptr,
208833965Sjdp				     line_ptr);
208933965Sjdp}
209033965Sjdp
209133965Sjdp/* Structure used to pass information to alpha_elf_output_extsym.  */
209233965Sjdp
209333965Sjdpstruct extsym_info
209433965Sjdp{
209533965Sjdp  bfd *abfd;
209633965Sjdp  struct bfd_link_info *info;
209733965Sjdp  struct ecoff_debug_info *debug;
209833965Sjdp  const struct ecoff_debug_swap *swap;
209933965Sjdp  boolean failed;
210033965Sjdp};
210133965Sjdp
210233965Sjdpstatic boolean
210333965Sjdpelf64_alpha_output_extsym (h, data)
210433965Sjdp     struct alpha_elf_link_hash_entry *h;
210533965Sjdp     PTR data;
210633965Sjdp{
210733965Sjdp  struct extsym_info *einfo = (struct extsym_info *) data;
210833965Sjdp  boolean strip;
210933965Sjdp  asection *sec, *output_section;
211033965Sjdp
211133965Sjdp  if (h->root.indx == -2)
211233965Sjdp    strip = false;
211333965Sjdp  else if (((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
211433965Sjdp           || (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
211533965Sjdp          && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
211633965Sjdp          && (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
211733965Sjdp    strip = true;
211833965Sjdp  else if (einfo->info->strip == strip_all
211933965Sjdp          || (einfo->info->strip == strip_some
212033965Sjdp              && bfd_hash_lookup (einfo->info->keep_hash,
212133965Sjdp                                  h->root.root.root.string,
212233965Sjdp                                  false, false) == NULL))
212333965Sjdp    strip = true;
212433965Sjdp  else
212533965Sjdp    strip = false;
212633965Sjdp
212733965Sjdp  if (strip)
212833965Sjdp    return true;
212933965Sjdp
213033965Sjdp  if (h->esym.ifd == -2)
213133965Sjdp    {
213233965Sjdp      h->esym.jmptbl = 0;
213333965Sjdp      h->esym.cobol_main = 0;
213433965Sjdp      h->esym.weakext = 0;
213533965Sjdp      h->esym.reserved = 0;
213633965Sjdp      h->esym.ifd = ifdNil;
213733965Sjdp      h->esym.asym.value = 0;
213833965Sjdp      h->esym.asym.st = stGlobal;
213933965Sjdp
214033965Sjdp      if (h->root.root.type != bfd_link_hash_defined
214133965Sjdp         && h->root.root.type != bfd_link_hash_defweak)
214233965Sjdp       h->esym.asym.sc = scAbs;
214333965Sjdp      else
214433965Sjdp       {
214533965Sjdp         const char *name;
214633965Sjdp
214733965Sjdp         sec = h->root.root.u.def.section;
214833965Sjdp         output_section = sec->output_section;
214933965Sjdp
215033965Sjdp         /* When making a shared library and symbol h is the one from
215133965Sjdp            the another shared library, OUTPUT_SECTION may be null.  */
215233965Sjdp         if (output_section == NULL)
215333965Sjdp           h->esym.asym.sc = scUndefined;
215433965Sjdp         else
215533965Sjdp           {
215633965Sjdp             name = bfd_section_name (output_section->owner, output_section);
215733965Sjdp
215833965Sjdp             if (strcmp (name, ".text") == 0)
215933965Sjdp               h->esym.asym.sc = scText;
216033965Sjdp             else if (strcmp (name, ".data") == 0)
216133965Sjdp               h->esym.asym.sc = scData;
216233965Sjdp             else if (strcmp (name, ".sdata") == 0)
216333965Sjdp               h->esym.asym.sc = scSData;
216433965Sjdp             else if (strcmp (name, ".rodata") == 0
216533965Sjdp                      || strcmp (name, ".rdata") == 0)
216633965Sjdp               h->esym.asym.sc = scRData;
216733965Sjdp             else if (strcmp (name, ".bss") == 0)
216833965Sjdp               h->esym.asym.sc = scBss;
216933965Sjdp             else if (strcmp (name, ".sbss") == 0)
217033965Sjdp               h->esym.asym.sc = scSBss;
217133965Sjdp             else if (strcmp (name, ".init") == 0)
217233965Sjdp               h->esym.asym.sc = scInit;
217333965Sjdp             else if (strcmp (name, ".fini") == 0)
217433965Sjdp               h->esym.asym.sc = scFini;
217533965Sjdp             else
217633965Sjdp               h->esym.asym.sc = scAbs;
217733965Sjdp           }
217833965Sjdp       }
217933965Sjdp
218033965Sjdp      h->esym.asym.reserved = 0;
218133965Sjdp      h->esym.asym.index = indexNil;
218233965Sjdp    }
218333965Sjdp
218433965Sjdp  if (h->root.root.type == bfd_link_hash_common)
218533965Sjdp    h->esym.asym.value = h->root.root.u.c.size;
218633965Sjdp  else if (h->root.root.type == bfd_link_hash_defined
218733965Sjdp	   || h->root.root.type == bfd_link_hash_defweak)
218833965Sjdp    {
218933965Sjdp      if (h->esym.asym.sc == scCommon)
219033965Sjdp       h->esym.asym.sc = scBss;
219133965Sjdp      else if (h->esym.asym.sc == scSCommon)
219233965Sjdp       h->esym.asym.sc = scSBss;
219333965Sjdp
219433965Sjdp      sec = h->root.root.u.def.section;
219533965Sjdp      output_section = sec->output_section;
219633965Sjdp      if (output_section != NULL)
219733965Sjdp       h->esym.asym.value = (h->root.root.u.def.value
219833965Sjdp                             + sec->output_offset
219933965Sjdp                             + output_section->vma);
220033965Sjdp      else
220133965Sjdp       h->esym.asym.value = 0;
220233965Sjdp    }
220333965Sjdp  else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
220433965Sjdp    {
220533965Sjdp      /* Set type and value for a symbol with a function stub.  */
220633965Sjdp      h->esym.asym.st = stProc;
220733965Sjdp      sec = bfd_get_section_by_name (einfo->abfd, ".plt");
220833965Sjdp      if (sec == NULL)
220933965Sjdp	h->esym.asym.value = 0;
221033965Sjdp      else
221133965Sjdp	{
221233965Sjdp	  output_section = sec->output_section;
221333965Sjdp	  if (output_section != NULL)
221460510Sobrien	    h->esym.asym.value = (h->root.plt.offset
221533965Sjdp				  + sec->output_offset
221633965Sjdp				  + output_section->vma);
221733965Sjdp	  else
221833965Sjdp	    h->esym.asym.value = 0;
221933965Sjdp	}
222033965Sjdp    }
222133965Sjdp
222233965Sjdp  if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap,
222333965Sjdp                                     h->root.root.root.string,
222433965Sjdp                                     &h->esym))
222533965Sjdp    {
222633965Sjdp      einfo->failed = true;
222733965Sjdp      return false;
222833965Sjdp    }
222933965Sjdp
223033965Sjdp  return true;
223133965Sjdp}
223233965Sjdp
223333965Sjdp/* FIXME:  Create a runtime procedure table from the .mdebug section.
223433965Sjdp
223533965Sjdpstatic boolean
223633965Sjdpmips_elf_create_procedure_table (handle, abfd, info, s, debug)
223733965Sjdp     PTR handle;
223833965Sjdp     bfd *abfd;
223933965Sjdp     struct bfd_link_info *info;
224033965Sjdp     asection *s;
224133965Sjdp     struct ecoff_debug_info *debug;
224233965Sjdp*/
224333965Sjdp
224433965Sjdp/* Handle dynamic relocations when doing an Alpha ELF link.  */
224533965Sjdp
224633965Sjdpstatic boolean
224733965Sjdpelf64_alpha_check_relocs (abfd, info, sec, relocs)
224833965Sjdp     bfd *abfd;
224933965Sjdp     struct bfd_link_info *info;
225033965Sjdp     asection *sec;
225133965Sjdp     const Elf_Internal_Rela *relocs;
225233965Sjdp{
225333965Sjdp  bfd *dynobj;
225433965Sjdp  asection *sreloc;
225533965Sjdp  const char *rel_sec_name;
225633965Sjdp  Elf_Internal_Shdr *symtab_hdr;
225733965Sjdp  struct alpha_elf_link_hash_entry **sym_hashes;
225833965Sjdp  struct alpha_elf_got_entry **local_got_entries;
225933965Sjdp  const Elf_Internal_Rela *rel, *relend;
226033965Sjdp  int got_created;
226189862Sobrien  bfd_size_type amt;
226233965Sjdp
226333965Sjdp  if (info->relocateable)
226433965Sjdp    return true;
226533965Sjdp
226633965Sjdp  dynobj = elf_hash_table(info)->dynobj;
226733965Sjdp  if (dynobj == NULL)
226833965Sjdp    elf_hash_table(info)->dynobj = dynobj = abfd;
226933965Sjdp
227033965Sjdp  sreloc = NULL;
227133965Sjdp  rel_sec_name = NULL;
227233965Sjdp  symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
227333965Sjdp  sym_hashes = alpha_elf_sym_hashes(abfd);
227433965Sjdp  local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
227533965Sjdp  got_created = 0;
227633965Sjdp
227733965Sjdp  relend = relocs + sec->reloc_count;
227833965Sjdp  for (rel = relocs; rel < relend; ++rel)
227933965Sjdp    {
228033965Sjdp      unsigned long r_symndx, r_type;
228133965Sjdp      struct alpha_elf_link_hash_entry *h;
228233965Sjdp
228333965Sjdp      r_symndx = ELF64_R_SYM (rel->r_info);
228433965Sjdp      if (r_symndx < symtab_hdr->sh_info)
228533965Sjdp	h = NULL;
228633965Sjdp      else
228733965Sjdp	{
228833965Sjdp	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
228938889Sjdp
229038889Sjdp	  while (h->root.root.type == bfd_link_hash_indirect
229138889Sjdp		 || h->root.root.type == bfd_link_hash_warning)
229238889Sjdp	    h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
229338889Sjdp
229433965Sjdp	  h->root.elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
229533965Sjdp	}
229633965Sjdp      r_type = ELF64_R_TYPE (rel->r_info);
229733965Sjdp
229833965Sjdp      switch (r_type)
229933965Sjdp	{
230033965Sjdp	case R_ALPHA_LITERAL:
230133965Sjdp	  {
230233965Sjdp	    struct alpha_elf_got_entry *gotent;
230333965Sjdp	    int flags = 0;
230433965Sjdp
230533965Sjdp	    if (h)
230633965Sjdp	      {
230733965Sjdp		/* Search for and possibly create a got entry.  */
230833965Sjdp		for (gotent = h->got_entries; gotent ; gotent = gotent->next)
230933965Sjdp		  if (gotent->gotobj == abfd &&
231033965Sjdp		      gotent->addend == rel->r_addend)
231133965Sjdp		    break;
231233965Sjdp
231333965Sjdp		if (!gotent)
231433965Sjdp		  {
231589862Sobrien		    amt = sizeof (struct alpha_elf_got_entry);
231633965Sjdp		    gotent = ((struct alpha_elf_got_entry *)
231789862Sobrien			      bfd_alloc (abfd, amt));
231833965Sjdp		    if (!gotent)
231933965Sjdp		      return false;
232033965Sjdp
232133965Sjdp		    gotent->gotobj = abfd;
232233965Sjdp		    gotent->addend = rel->r_addend;
232333965Sjdp		    gotent->got_offset = -1;
232433965Sjdp		    gotent->flags = 0;
232560510Sobrien		    gotent->use_count = 1;
232633965Sjdp
232733965Sjdp		    gotent->next = h->got_entries;
232833965Sjdp		    h->got_entries = gotent;
232933965Sjdp
233033965Sjdp		    alpha_elf_tdata (abfd)->total_got_entries++;
233133965Sjdp		  }
233260510Sobrien		else
233360510Sobrien		  gotent->use_count += 1;
233433965Sjdp	      }
233533965Sjdp	    else
233633965Sjdp	      {
233733965Sjdp		/* This is a local .got entry -- record for merge.  */
233833965Sjdp		if (!local_got_entries)
233933965Sjdp		  {
234089862Sobrien		    bfd_size_type size;
234189862Sobrien		    size = symtab_hdr->sh_info;
234289862Sobrien		    size *= sizeof (struct alpha_elf_got_entry *);
234333965Sjdp
234433965Sjdp		    local_got_entries = ((struct alpha_elf_got_entry **)
234533965Sjdp					 bfd_alloc (abfd, size));
234633965Sjdp		    if (!local_got_entries)
234733965Sjdp		      return false;
234833965Sjdp
234989862Sobrien		    memset (local_got_entries, 0, (size_t) size);
235033965Sjdp		    alpha_elf_tdata (abfd)->local_got_entries =
235133965Sjdp		      local_got_entries;
235233965Sjdp		  }
235333965Sjdp
235433965Sjdp		for (gotent = local_got_entries[ELF64_R_SYM(rel->r_info)];
235533965Sjdp		     gotent != NULL && gotent->addend != rel->r_addend;
235633965Sjdp		     gotent = gotent->next)
235733965Sjdp		  continue;
235833965Sjdp		if (!gotent)
235933965Sjdp		  {
236089862Sobrien		    amt = sizeof (struct alpha_elf_got_entry);
236133965Sjdp		    gotent = ((struct alpha_elf_got_entry *)
236289862Sobrien			      bfd_alloc (abfd, amt));
236333965Sjdp		    if (!gotent)
236433965Sjdp		      return false;
236533965Sjdp
236633965Sjdp		    gotent->gotobj = abfd;
236733965Sjdp		    gotent->addend = rel->r_addend;
236833965Sjdp		    gotent->got_offset = -1;
236933965Sjdp		    gotent->flags = 0;
237060510Sobrien		    gotent->use_count = 1;
237133965Sjdp
237233965Sjdp		    gotent->next = local_got_entries[ELF64_R_SYM(rel->r_info)];
237333965Sjdp		    local_got_entries[ELF64_R_SYM(rel->r_info)] = gotent;
237433965Sjdp
237533965Sjdp		    alpha_elf_tdata(abfd)->total_got_entries++;
237633965Sjdp		    alpha_elf_tdata(abfd)->n_local_got_entries++;
237733965Sjdp		  }
237860510Sobrien		else
237960510Sobrien		  gotent->use_count += 1;
238033965Sjdp	      }
238133965Sjdp
238233965Sjdp	    /* Remember how this literal is used from its LITUSEs.
238333965Sjdp	       This will be important when it comes to decide if we can
238433965Sjdp	       create a .plt entry for a function symbol.  */
238533965Sjdp	    if (rel+1 < relend
238633965Sjdp		&& ELF64_R_TYPE (rel[1].r_info) == R_ALPHA_LITUSE)
238733965Sjdp	      {
238833965Sjdp		do
238933965Sjdp		  {
239033965Sjdp		    ++rel;
239133965Sjdp		    if (rel->r_addend >= 1 && rel->r_addend <= 3)
239233965Sjdp		      flags |= 1 << rel->r_addend;
239333965Sjdp		  }
239433965Sjdp		while (rel+1 < relend &&
239533965Sjdp		       ELF64_R_TYPE (rel[1].r_info) == R_ALPHA_LITUSE);
239633965Sjdp	      }
239733965Sjdp	    else
239833965Sjdp	      {
239933965Sjdp		/* No LITUSEs -- presumably the address is not being
240033965Sjdp		   loaded for nothing.  */
240133965Sjdp		flags = ALPHA_ELF_LINK_HASH_LU_ADDR;
240233965Sjdp	      }
240333965Sjdp
240433965Sjdp	    gotent->flags |= flags;
240533965Sjdp	    if (h)
240633965Sjdp	      {
240733965Sjdp		/* Make a guess as to whether a .plt entry will be needed.  */
240833965Sjdp		if ((h->flags |= flags) == ALPHA_ELF_LINK_HASH_LU_FUNC)
240933965Sjdp		  h->root.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
241033965Sjdp		else
241133965Sjdp		  h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
241233965Sjdp	      }
241333965Sjdp	  }
241433965Sjdp	  /* FALLTHRU */
241533965Sjdp
241633965Sjdp	case R_ALPHA_GPDISP:
241789862Sobrien	case R_ALPHA_GPREL16:
241833965Sjdp	case R_ALPHA_GPREL32:
241960510Sobrien	case R_ALPHA_GPRELHIGH:
242060510Sobrien	case R_ALPHA_GPRELLOW:
242133965Sjdp	  /* We don't actually use the .got here, but the sections must
242233965Sjdp	     be created before the linker maps input sections to output
242333965Sjdp	     sections.  */
242433965Sjdp	  if (!got_created)
242533965Sjdp	    {
242633965Sjdp	      if (!elf64_alpha_create_got_section (abfd, info))
242733965Sjdp		return false;
242833965Sjdp
242933965Sjdp	      /* Make sure the object's gotobj is set to itself so
243033965Sjdp		 that we default to every object with its own .got.
243133965Sjdp		 We'll merge .gots later once we've collected each
243233965Sjdp		 object's info.  */
243333965Sjdp	      alpha_elf_tdata(abfd)->gotobj = abfd;
243433965Sjdp
243533965Sjdp	      got_created = 1;
243633965Sjdp	    }
243733965Sjdp	  break;
243833965Sjdp
243933965Sjdp	case R_ALPHA_SREL16:
244033965Sjdp	case R_ALPHA_SREL32:
244133965Sjdp	case R_ALPHA_SREL64:
244233965Sjdp	  if (h == NULL)
244333965Sjdp	    break;
244433965Sjdp	  /* FALLTHRU */
244533965Sjdp
244633965Sjdp	case R_ALPHA_REFLONG:
244733965Sjdp	case R_ALPHA_REFQUAD:
244833965Sjdp	  if (rel_sec_name == NULL)
244933965Sjdp	    {
245033965Sjdp	      rel_sec_name = (bfd_elf_string_from_elf_section
245133965Sjdp			      (abfd, elf_elfheader(abfd)->e_shstrndx,
245233965Sjdp			       elf_section_data(sec)->rel_hdr.sh_name));
245333965Sjdp	      if (rel_sec_name == NULL)
245433965Sjdp		return false;
245533965Sjdp
245633965Sjdp	      BFD_ASSERT (strncmp (rel_sec_name, ".rela", 5) == 0
245733965Sjdp			  && strcmp (bfd_get_section_name (abfd, sec),
245833965Sjdp				     rel_sec_name+5) == 0);
245933965Sjdp	    }
246033965Sjdp
246133965Sjdp	  /* We need to create the section here now whether we eventually
246233965Sjdp	     use it or not so that it gets mapped to an output section by
246333965Sjdp	     the linker.  If not used, we'll kill it in
246433965Sjdp	     size_dynamic_sections.  */
246533965Sjdp	  if (sreloc == NULL)
246633965Sjdp	    {
246733965Sjdp	      sreloc = bfd_get_section_by_name (dynobj, rel_sec_name);
246833965Sjdp	      if (sreloc == NULL)
246933965Sjdp		{
247089862Sobrien		  flagword flags;
247189862Sobrien
247233965Sjdp		  sreloc = bfd_make_section (dynobj, rel_sec_name);
247389862Sobrien		  flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY
247489862Sobrien			   | SEC_LINKER_CREATED | SEC_READONLY);
247589862Sobrien		  if (sec->flags & SEC_ALLOC)
247689862Sobrien		    flags |= SEC_ALLOC | SEC_LOAD;
247733965Sjdp		  if (sreloc == NULL
247889862Sobrien		      || !bfd_set_section_flags (dynobj, sreloc, flags)
247933965Sjdp		      || !bfd_set_section_alignment (dynobj, sreloc, 3))
248033965Sjdp		    return false;
248133965Sjdp		}
248233965Sjdp	    }
248333965Sjdp
248433965Sjdp	  if (h)
248533965Sjdp	    {
248633965Sjdp	      /* Since we havn't seen all of the input symbols yet, we
248733965Sjdp		 don't know whether we'll actually need a dynamic relocation
248833965Sjdp		 entry for this reloc.  So make a record of it.  Once we
248933965Sjdp		 find out if this thing needs dynamic relocation we'll
249077303Sobrien		 expand the relocation sections by the appropriate amount.  */
249133965Sjdp
249233965Sjdp	      struct alpha_elf_reloc_entry *rent;
249333965Sjdp
249433965Sjdp	      for (rent = h->reloc_entries; rent; rent = rent->next)
249533965Sjdp		if (rent->rtype == r_type && rent->srel == sreloc)
249633965Sjdp		  break;
249733965Sjdp
249833965Sjdp	      if (!rent)
249933965Sjdp		{
250089862Sobrien		  amt = sizeof (struct alpha_elf_reloc_entry);
250189862Sobrien		  rent = (struct alpha_elf_reloc_entry *) bfd_alloc (abfd, amt);
250233965Sjdp		  if (!rent)
250333965Sjdp		    return false;
250433965Sjdp
250533965Sjdp		  rent->srel = sreloc;
250633965Sjdp		  rent->rtype = r_type;
250733965Sjdp		  rent->count = 1;
250889862Sobrien		  rent->reltext = ((sec->flags & (SEC_READONLY | SEC_ALLOC))
250989862Sobrien				   == (SEC_READONLY | SEC_ALLOC));
251033965Sjdp
251133965Sjdp		  rent->next = h->reloc_entries;
251233965Sjdp		  h->reloc_entries = rent;
251333965Sjdp		}
251433965Sjdp	      else
251533965Sjdp		rent->count++;
251633965Sjdp	    }
251760510Sobrien	  else if (info->shared && (sec->flags & SEC_ALLOC))
251833965Sjdp	    {
251960510Sobrien	      /* If this is a shared library, and the section is to be
252060510Sobrien		 loaded into memory, we need a RELATIVE reloc.  */
252133965Sjdp	      sreloc->_raw_size += sizeof (Elf64_External_Rela);
252289862Sobrien	      if (sec->flags & SEC_READONLY)
252389862Sobrien		info->flags |= DF_TEXTREL;
252433965Sjdp	    }
252533965Sjdp	  break;
252633965Sjdp	}
252733965Sjdp    }
252833965Sjdp
252933965Sjdp  return true;
253033965Sjdp}
253133965Sjdp
253233965Sjdp/* Adjust a symbol defined by a dynamic object and referenced by a
253333965Sjdp   regular object.  The current definition is in some section of the
253433965Sjdp   dynamic object, but we're not including those sections.  We have to
253533965Sjdp   change the definition to something the rest of the link can
253633965Sjdp   understand.  */
253733965Sjdp
253833965Sjdpstatic boolean
253933965Sjdpelf64_alpha_adjust_dynamic_symbol (info, h)
254033965Sjdp     struct bfd_link_info *info;
254133965Sjdp     struct elf_link_hash_entry *h;
254233965Sjdp{
254333965Sjdp  bfd *dynobj;
254433965Sjdp  asection *s;
254533965Sjdp  struct alpha_elf_link_hash_entry *ah;
254633965Sjdp
254733965Sjdp  dynobj = elf_hash_table(info)->dynobj;
254833965Sjdp  ah = (struct alpha_elf_link_hash_entry *)h;
254933965Sjdp
255033965Sjdp  /* Now that we've seen all of the input symbols, finalize our decision
255133965Sjdp     about whether this symbol should get a .plt entry.  */
255233965Sjdp
255389862Sobrien  if (alpha_elf_dynamic_symbol_p (h, info)
255433965Sjdp      && ((h->type == STT_FUNC
255533965Sjdp	   && !(ah->flags & ALPHA_ELF_LINK_HASH_LU_ADDR))
255633965Sjdp	  || (h->type == STT_NOTYPE
255733965Sjdp	      && ah->flags == ALPHA_ELF_LINK_HASH_LU_FUNC))
255833965Sjdp      /* Don't prevent otherwise valid programs from linking by attempting
255933965Sjdp	 to create a new .got entry somewhere.  A Correct Solution would be
256033965Sjdp	 to add a new .got section to a new object file and let it be merged
256133965Sjdp	 somewhere later.  But for now don't bother.  */
256233965Sjdp      && ah->got_entries)
256333965Sjdp    {
256433965Sjdp      h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
256533965Sjdp
256633965Sjdp      s = bfd_get_section_by_name(dynobj, ".plt");
256733965Sjdp      if (!s && !elf64_alpha_create_dynamic_sections (dynobj, info))
256833965Sjdp	return false;
256933965Sjdp
257033965Sjdp      /* The first bit of the .plt is reserved.  */
257133965Sjdp      if (s->_raw_size == 0)
257233965Sjdp	s->_raw_size = PLT_HEADER_SIZE;
257333965Sjdp
257460510Sobrien      h->plt.offset = s->_raw_size;
257533965Sjdp      s->_raw_size += PLT_ENTRY_SIZE;
257633965Sjdp
257733965Sjdp      /* If this symbol is not defined in a regular file, and we are not
257833965Sjdp	 generating a shared library, then set the symbol to the location
257933965Sjdp	 in the .plt.  This is required to make function pointers compare
258033965Sjdp	 equal between the normal executable and the shared library.  */
258148850Sdfr      if (! info->shared
258248850Sdfr	  && h->root.type != bfd_link_hash_defweak)
258333965Sjdp	{
258433965Sjdp	  h->root.u.def.section = s;
258560510Sobrien	  h->root.u.def.value = h->plt.offset;
258633965Sjdp	}
258733965Sjdp
258833965Sjdp      /* We also need a JMP_SLOT entry in the .rela.plt section.  */
258933965Sjdp      s = bfd_get_section_by_name (dynobj, ".rela.plt");
259033965Sjdp      BFD_ASSERT (s != NULL);
259133965Sjdp      s->_raw_size += sizeof (Elf64_External_Rela);
259233965Sjdp
259333965Sjdp      return true;
259433965Sjdp    }
259533965Sjdp  else
259633965Sjdp    h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
259733965Sjdp
259833965Sjdp  /* If this is a weak symbol, and there is a real definition, the
259933965Sjdp     processor independent code will have arranged for us to see the
260033965Sjdp     real definition first, and we can just use the same value.  */
260133965Sjdp  if (h->weakdef != NULL)
260233965Sjdp    {
260333965Sjdp      BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
260433965Sjdp		  || h->weakdef->root.type == bfd_link_hash_defweak);
260533965Sjdp      h->root.u.def.section = h->weakdef->root.u.def.section;
260633965Sjdp      h->root.u.def.value = h->weakdef->root.u.def.value;
260733965Sjdp      return true;
260833965Sjdp    }
260933965Sjdp
261033965Sjdp  /* This is a reference to a symbol defined by a dynamic object which
261133965Sjdp     is not a function.  The Alpha, since it uses .got entries for all
261233965Sjdp     symbols even in regular objects, does not need the hackery of a
261333965Sjdp     .dynbss section and COPY dynamic relocations.  */
261433965Sjdp
261533965Sjdp  return true;
261633965Sjdp}
261733965Sjdp
261838889Sjdp/* Symbol versioning can create new symbols, and make our old symbols
261938889Sjdp   indirect to the new ones.  Consolidate the got and reloc information
262038889Sjdp   in these situations.  */
262138889Sjdp
262238889Sjdpstatic boolean
262338889Sjdpelf64_alpha_merge_ind_symbols (hi, dummy)
262438889Sjdp     struct alpha_elf_link_hash_entry *hi;
262578833Sobrien     PTR dummy ATTRIBUTE_UNUSED;
262638889Sjdp{
262738889Sjdp  struct alpha_elf_link_hash_entry *hs;
262838889Sjdp
262938889Sjdp  if (hi->root.root.type != bfd_link_hash_indirect)
263038889Sjdp    return true;
263138889Sjdp  hs = hi;
263238889Sjdp  do {
263338889Sjdp    hs = (struct alpha_elf_link_hash_entry *)hs->root.root.u.i.link;
263438889Sjdp  } while (hs->root.root.type == bfd_link_hash_indirect);
263538889Sjdp
263638889Sjdp  /* Merge the flags.  Whee.  */
263738889Sjdp
263838889Sjdp  hs->flags |= hi->flags;
263938889Sjdp
264038889Sjdp  /* Merge the .got entries.  Cannibalize the old symbol's list in
264138889Sjdp     doing so, since we don't need it anymore.  */
264238889Sjdp
264338889Sjdp  if (hs->got_entries == NULL)
264438889Sjdp    hs->got_entries = hi->got_entries;
264538889Sjdp  else
264638889Sjdp    {
264738889Sjdp      struct alpha_elf_got_entry *gi, *gs, *gin, *gsh;
264838889Sjdp
264938889Sjdp      gsh = hs->got_entries;
265038889Sjdp      for (gi = hi->got_entries; gi ; gi = gin)
265138889Sjdp	{
265238889Sjdp	  gin = gi->next;
265338889Sjdp	  for (gs = gsh; gs ; gs = gs->next)
265460510Sobrien	    if (gi->gotobj == gs->gotobj && gi->addend == gs->addend)
265538889Sjdp	      goto got_found;
265638889Sjdp	  gi->next = hs->got_entries;
265738889Sjdp	  hs->got_entries = gi;
265838889Sjdp	got_found:;
265938889Sjdp	}
266038889Sjdp    }
266138889Sjdp  hi->got_entries = NULL;
266238889Sjdp
266338889Sjdp  /* And similar for the reloc entries.  */
266438889Sjdp
266538889Sjdp  if (hs->reloc_entries == NULL)
266638889Sjdp    hs->reloc_entries = hi->reloc_entries;
266738889Sjdp  else
266838889Sjdp    {
266938889Sjdp      struct alpha_elf_reloc_entry *ri, *rs, *rin, *rsh;
267038889Sjdp
267138889Sjdp      rsh = hs->reloc_entries;
267238889Sjdp      for (ri = hi->reloc_entries; ri ; ri = rin)
267338889Sjdp	{
267438889Sjdp	  rin = ri->next;
267538889Sjdp	  for (rs = rsh; rs ; rs = rs->next)
267638889Sjdp	    if (ri->rtype == rs->rtype)
267738889Sjdp	      {
267838889Sjdp		rs->count += ri->count;
267938889Sjdp		goto found_reloc;
268038889Sjdp	      }
268138889Sjdp	  ri->next = hs->reloc_entries;
268238889Sjdp	  hs->reloc_entries = ri;
268338889Sjdp	found_reloc:;
268438889Sjdp	}
268538889Sjdp    }
268638889Sjdp  hi->reloc_entries = NULL;
268738889Sjdp
268838889Sjdp  return true;
268938889Sjdp}
269038889Sjdp
269133965Sjdp/* Is it possible to merge two object file's .got tables?  */
269233965Sjdp
269333965Sjdpstatic boolean
269433965Sjdpelf64_alpha_can_merge_gots (a, b)
269533965Sjdp     bfd *a, *b;
269633965Sjdp{
269733965Sjdp  int total = alpha_elf_tdata (a)->total_got_entries;
269860510Sobrien  bfd *bsub;
269933965Sjdp
270033965Sjdp  /* Trivial quick fallout test.  */
270133965Sjdp  if (total + alpha_elf_tdata (b)->total_got_entries <= MAX_GOT_ENTRIES)
270233965Sjdp    return true;
270333965Sjdp
270433965Sjdp  /* By their nature, local .got entries cannot be merged.  */
270533965Sjdp  if ((total += alpha_elf_tdata (b)->n_local_got_entries) > MAX_GOT_ENTRIES)
270633965Sjdp    return false;
270733965Sjdp
270833965Sjdp  /* Failing the common trivial comparison, we must effectively
270933965Sjdp     perform the merge.  Not actually performing the merge means that
271033965Sjdp     we don't have to store undo information in case we fail.  */
271160510Sobrien  for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next)
271260510Sobrien    {
271360510Sobrien      struct alpha_elf_link_hash_entry **hashes = alpha_elf_sym_hashes (bsub);
271460510Sobrien      Elf_Internal_Shdr *symtab_hdr = &elf_tdata (bsub)->symtab_hdr;
271560510Sobrien      int i, n;
271633965Sjdp
271778833Sobrien      n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info;
271860510Sobrien      for (i = 0; i < n; ++i)
271960510Sobrien	{
272060510Sobrien	  struct alpha_elf_got_entry *ae, *be;
272160510Sobrien	  struct alpha_elf_link_hash_entry *h;
272238889Sjdp
272360510Sobrien	  h = hashes[i];
272460510Sobrien	  while (h->root.root.type == bfd_link_hash_indirect
272560510Sobrien	         || h->root.root.type == bfd_link_hash_warning)
272660510Sobrien	    h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
272738889Sjdp
272860510Sobrien	  for (be = h->got_entries; be ; be = be->next)
272960510Sobrien	    {
273060510Sobrien	      if (be->use_count == 0)
273160510Sobrien	        continue;
273260510Sobrien	      if (be->gotobj != b)
273360510Sobrien	        continue;
273433965Sjdp
273560510Sobrien	      for (ae = h->got_entries; ae ; ae = ae->next)
273660510Sobrien	        if (ae->gotobj == a && ae->addend == be->addend)
273760510Sobrien		  goto global_found;
273833965Sjdp
273960510Sobrien	      if (++total > MAX_GOT_ENTRIES)
274060510Sobrien	        return false;
274160510Sobrien	    global_found:;
274260510Sobrien	    }
274360510Sobrien	}
274460510Sobrien    }
274533965Sjdp
274633965Sjdp  return true;
274733965Sjdp}
274833965Sjdp
274933965Sjdp/* Actually merge two .got tables.  */
275033965Sjdp
275133965Sjdpstatic void
275233965Sjdpelf64_alpha_merge_gots (a, b)
275333965Sjdp     bfd *a, *b;
275433965Sjdp{
275560510Sobrien  int total = alpha_elf_tdata (a)->total_got_entries;
275660510Sobrien  bfd *bsub;
275733965Sjdp
275833965Sjdp  /* Remember local expansion.  */
275933965Sjdp  {
276060510Sobrien    int e = alpha_elf_tdata (b)->n_local_got_entries;
276133965Sjdp    total += e;
276260510Sobrien    alpha_elf_tdata (a)->n_local_got_entries += e;
276333965Sjdp  }
276433965Sjdp
276560510Sobrien  for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next)
276660510Sobrien    {
276760510Sobrien      struct alpha_elf_got_entry **local_got_entries;
276860510Sobrien      struct alpha_elf_link_hash_entry **hashes;
276960510Sobrien      Elf_Internal_Shdr *symtab_hdr;
277060510Sobrien      int i, n;
277133965Sjdp
277260510Sobrien      /* Let the local .got entries know they are part of a new subsegment.  */
277360510Sobrien      local_got_entries = alpha_elf_tdata (bsub)->local_got_entries;
277460510Sobrien      if (local_got_entries)
277560510Sobrien        {
277660510Sobrien	  n = elf_tdata (bsub)->symtab_hdr.sh_info;
277760510Sobrien	  for (i = 0; i < n; ++i)
277860510Sobrien	    {
277960510Sobrien	      struct alpha_elf_got_entry *ent;
278060510Sobrien	      for (ent = local_got_entries[i]; ent; ent = ent->next)
278160510Sobrien	        ent->gotobj = a;
278260510Sobrien	    }
278360510Sobrien        }
278433965Sjdp
278560510Sobrien      /* Merge the global .got entries.  */
278660510Sobrien      hashes = alpha_elf_sym_hashes (bsub);
278760510Sobrien      symtab_hdr = &elf_tdata (bsub)->symtab_hdr;
278833965Sjdp
278978833Sobrien      n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info;
279060510Sobrien      for (i = 0; i < n; ++i)
279160510Sobrien        {
279260510Sobrien	  struct alpha_elf_got_entry *ae, *be, **pbe, **start;
279360510Sobrien	  struct alpha_elf_link_hash_entry *h;
279438889Sjdp
279560510Sobrien	  h = hashes[i];
279660510Sobrien	  while (h->root.root.type == bfd_link_hash_indirect
279760510Sobrien	         || h->root.root.type == bfd_link_hash_warning)
279860510Sobrien	    h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
279938889Sjdp
280060510Sobrien	  start = &h->got_entries;
280160510Sobrien	  for (pbe = start, be = *start; be ; pbe = &be->next, be = be->next)
280260510Sobrien	    {
280360510Sobrien	      if (be->use_count == 0)
280460510Sobrien	        {
280533965Sjdp		  *pbe = be->next;
280660510Sobrien		  continue;
280760510Sobrien	        }
280860510Sobrien	      if (be->gotobj != b)
280960510Sobrien	        continue;
281033965Sjdp
281160510Sobrien	      for (ae = *start; ae ; ae = ae->next)
281260510Sobrien	        if (ae->gotobj == a && ae->addend == be->addend)
281360510Sobrien		  {
281460510Sobrien		    ae->flags |= be->flags;
281560510Sobrien		    ae->use_count += be->use_count;
281660510Sobrien		    *pbe = be->next;
281760510Sobrien		    goto global_found;
281860510Sobrien		  }
281960510Sobrien	      be->gotobj = a;
282060510Sobrien	      total += 1;
282160510Sobrien
282260510Sobrien	    global_found:;
282360510Sobrien	    }
282460510Sobrien        }
282560510Sobrien
282660510Sobrien      alpha_elf_tdata (bsub)->gotobj = a;
282760510Sobrien    }
282860510Sobrien  alpha_elf_tdata (a)->total_got_entries = total;
282960510Sobrien
283060510Sobrien  /* Merge the two in_got chains.  */
283160510Sobrien  {
283260510Sobrien    bfd *next;
283360510Sobrien
283460510Sobrien    bsub = a;
283560510Sobrien    while ((next = alpha_elf_tdata (bsub)->in_got_link_next) != NULL)
283660510Sobrien      bsub = next;
283760510Sobrien
283860510Sobrien    alpha_elf_tdata (bsub)->in_got_link_next = b;
283933965Sjdp  }
284033965Sjdp}
284133965Sjdp
284233965Sjdp/* Calculate the offsets for the got entries.  */
284333965Sjdp
284433965Sjdpstatic boolean
284533965Sjdpelf64_alpha_calc_got_offsets_for_symbol (h, arg)
284633965Sjdp     struct alpha_elf_link_hash_entry *h;
284789862Sobrien     PTR arg ATTRIBUTE_UNUSED;
284833965Sjdp{
284933965Sjdp  struct alpha_elf_got_entry *gotent;
285033965Sjdp
285133965Sjdp  for (gotent = h->got_entries; gotent; gotent = gotent->next)
285260510Sobrien    if (gotent->use_count > 0)
285360510Sobrien      {
285460510Sobrien	bfd_size_type *plge
285560510Sobrien	  = &alpha_elf_tdata (gotent->gotobj)->got->_raw_size;
285633965Sjdp
285760510Sobrien	gotent->got_offset = *plge;
285860510Sobrien	*plge += 8;
285960510Sobrien      }
286060510Sobrien
286133965Sjdp  return true;
286233965Sjdp}
286333965Sjdp
286433965Sjdpstatic void
286533965Sjdpelf64_alpha_calc_got_offsets (info)
286633965Sjdp     struct bfd_link_info *info;
286733965Sjdp{
286833965Sjdp  bfd *i, *got_list = alpha_elf_hash_table(info)->got_list;
286933965Sjdp
287033965Sjdp  /* First, zero out the .got sizes, as we may be recalculating the
287133965Sjdp     .got after optimizing it.  */
287233965Sjdp  for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next)
287333965Sjdp    alpha_elf_tdata(i)->got->_raw_size = 0;
287433965Sjdp
287533965Sjdp  /* Next, fill in the offsets for all the global entries.  */
287633965Sjdp  alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
287733965Sjdp				elf64_alpha_calc_got_offsets_for_symbol,
287833965Sjdp				NULL);
287933965Sjdp
288033965Sjdp  /* Finally, fill in the offsets for the local entries.  */
288133965Sjdp  for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next)
288233965Sjdp    {
288333965Sjdp      bfd_size_type got_offset = alpha_elf_tdata(i)->got->_raw_size;
288433965Sjdp      bfd *j;
288533965Sjdp
288633965Sjdp      for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next)
288733965Sjdp	{
288833965Sjdp	  struct alpha_elf_got_entry **local_got_entries, *gotent;
288933965Sjdp	  int k, n;
289033965Sjdp
289133965Sjdp	  local_got_entries = alpha_elf_tdata(j)->local_got_entries;
289233965Sjdp	  if (!local_got_entries)
289333965Sjdp	    continue;
289433965Sjdp
289533965Sjdp	  for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k)
289633965Sjdp	    for (gotent = local_got_entries[k]; gotent; gotent = gotent->next)
289760510Sobrien	      if (gotent->use_count > 0)
289860510Sobrien	        {
289960510Sobrien		  gotent->got_offset = got_offset;
290060510Sobrien		  got_offset += 8;
290160510Sobrien	        }
290233965Sjdp	}
290333965Sjdp
290433965Sjdp      alpha_elf_tdata(i)->got->_raw_size = got_offset;
290560510Sobrien      alpha_elf_tdata(i)->got->_cooked_size = got_offset;
290633965Sjdp    }
290733965Sjdp}
290833965Sjdp
290933965Sjdp/* Constructs the gots.  */
291033965Sjdp
291133965Sjdpstatic boolean
291260510Sobrienelf64_alpha_size_got_sections (output_bfd, info)
291389862Sobrien     bfd *output_bfd ATTRIBUTE_UNUSED;
291433965Sjdp     struct bfd_link_info *info;
291533965Sjdp{
291689862Sobrien  bfd *i, *got_list, *cur_got_obj = NULL;
291760510Sobrien  int something_changed = 0;
291833965Sjdp
291960510Sobrien  got_list = alpha_elf_hash_table (info)->got_list;
292033965Sjdp
292160510Sobrien  /* On the first time through, pretend we have an existing got list
292260510Sobrien     consisting of all of the input files.  */
292360510Sobrien  if (got_list == NULL)
292433965Sjdp    {
292560510Sobrien      for (i = info->input_bfds; i ; i = i->link_next)
292660510Sobrien	{
292760510Sobrien	  bfd *this_got = alpha_elf_tdata (i)->gotobj;
292860510Sobrien	  if (this_got == NULL)
292960510Sobrien	    continue;
293033965Sjdp
293160510Sobrien	  /* We are assuming no merging has yet ocurred.  */
293260510Sobrien	  BFD_ASSERT (this_got == i);
293333965Sjdp
293460510Sobrien          if (alpha_elf_tdata (this_got)->total_got_entries > MAX_GOT_ENTRIES)
293533965Sjdp	    {
293660510Sobrien	      /* Yikes! A single object file has too many entries.  */
293760510Sobrien	      (*_bfd_error_handler)
293860510Sobrien	        (_("%s: .got subsegment exceeds 64K (size %d)"),
293989862Sobrien	         bfd_archive_filename (i),
294060510Sobrien	         alpha_elf_tdata (this_got)->total_got_entries * 8);
294160510Sobrien	      return false;
294233965Sjdp	    }
294360510Sobrien
294460510Sobrien	  if (got_list == NULL)
294560510Sobrien	    got_list = this_got;
294633965Sjdp	  else
294760510Sobrien	    alpha_elf_tdata(cur_got_obj)->got_link_next = this_got;
294860510Sobrien	  cur_got_obj = this_got;
294933965Sjdp	}
295060510Sobrien
295160510Sobrien      /* Strange degenerate case of no got references.  */
295260510Sobrien      if (got_list == NULL)
295360510Sobrien	return true;
295460510Sobrien
295560510Sobrien      alpha_elf_hash_table (info)->got_list = got_list;
295660510Sobrien
295760510Sobrien      /* Force got offsets to be recalculated.  */
295860510Sobrien      something_changed = 1;
295960510Sobrien    }
296060510Sobrien
296160510Sobrien  cur_got_obj = got_list;
296260510Sobrien  i = alpha_elf_tdata(cur_got_obj)->got_link_next;
296360510Sobrien  while (i != NULL)
296460510Sobrien    {
296560510Sobrien      if (elf64_alpha_can_merge_gots (cur_got_obj, i))
296660510Sobrien	{
296760510Sobrien	  elf64_alpha_merge_gots (cur_got_obj, i);
296860510Sobrien	  i = alpha_elf_tdata(i)->got_link_next;
296960510Sobrien	  alpha_elf_tdata(cur_got_obj)->got_link_next = i;
297060510Sobrien	  something_changed = 1;
297160510Sobrien	}
297233965Sjdp      else
297333965Sjdp	{
297433965Sjdp	  cur_got_obj = i;
297560510Sobrien	  i = alpha_elf_tdata(i)->got_link_next;
297633965Sjdp	}
297733965Sjdp    }
297833965Sjdp
297960510Sobrien  /* Once the gots have been merged, fill in the got offsets for
298060510Sobrien     everything therein.  */
298160510Sobrien  if (1 || something_changed)
298260510Sobrien    elf64_alpha_calc_got_offsets (info);
298333965Sjdp
298460510Sobrien  return true;
298560510Sobrien}
298633965Sjdp
298760510Sobrienstatic boolean
298860510Sobrienelf64_alpha_always_size_sections (output_bfd, info)
298960510Sobrien     bfd *output_bfd;
299060510Sobrien     struct bfd_link_info *info;
299160510Sobrien{
299260510Sobrien  bfd *i;
299360510Sobrien
299460510Sobrien  if (info->relocateable)
299560510Sobrien    return true;
299660510Sobrien
299760510Sobrien  /* First, take care of the indirect symbols created by versioning.  */
299860510Sobrien  alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
299960510Sobrien				elf64_alpha_merge_ind_symbols,
300060510Sobrien				NULL);
300160510Sobrien
300260510Sobrien  if (!elf64_alpha_size_got_sections (output_bfd, info))
300360510Sobrien    return false;
300460510Sobrien
300533965Sjdp  /* Allocate space for all of the .got subsections.  */
300660510Sobrien  i = alpha_elf_hash_table (info)->got_list;
300760510Sobrien  for ( ; i ; i = alpha_elf_tdata(i)->got_link_next)
300833965Sjdp    {
300933965Sjdp      asection *s = alpha_elf_tdata(i)->got;
301033965Sjdp      if (s->_raw_size > 0)
301133965Sjdp	{
301233965Sjdp	  s->contents = (bfd_byte *) bfd_zalloc (i, s->_raw_size);
301333965Sjdp	  if (s->contents == NULL)
301433965Sjdp	    return false;
301533965Sjdp	}
301633965Sjdp    }
301733965Sjdp
301833965Sjdp  return true;
301933965Sjdp}
302033965Sjdp
302133965Sjdp/* Work out the sizes of the dynamic relocation entries.  */
302233965Sjdp
302333965Sjdpstatic boolean
302433965Sjdpelf64_alpha_calc_dynrel_sizes (h, info)
302533965Sjdp     struct alpha_elf_link_hash_entry *h;
302633965Sjdp     struct bfd_link_info *info;
302733965Sjdp{
302833965Sjdp  /* If the symbol was defined as a common symbol in a regular object
302933965Sjdp     file, and there was no definition in any dynamic object, then the
303033965Sjdp     linker will have allocated space for the symbol in a common
303133965Sjdp     section but the ELF_LINK_HASH_DEF_REGULAR flag will not have been
303233965Sjdp     set.  This is done for dynamic symbols in
303333965Sjdp     elf_adjust_dynamic_symbol but this is not done for non-dynamic
303433965Sjdp     symbols, somehow.  */
303533965Sjdp  if (((h->root.elf_link_hash_flags
303633965Sjdp       & (ELF_LINK_HASH_DEF_REGULAR
303733965Sjdp	  | ELF_LINK_HASH_REF_REGULAR
303833965Sjdp	  | ELF_LINK_HASH_DEF_DYNAMIC))
303933965Sjdp       == ELF_LINK_HASH_REF_REGULAR)
304033965Sjdp      && (h->root.root.type == bfd_link_hash_defined
304133965Sjdp	  || h->root.root.type == bfd_link_hash_defweak)
304233965Sjdp      && !(h->root.root.u.def.section->owner->flags & DYNAMIC))
304333965Sjdp    {
304433965Sjdp      h->root.elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
304533965Sjdp    }
304633965Sjdp
304733965Sjdp  /* If the symbol is dynamic, we'll need all the relocations in their
304860510Sobrien     natural form.  If this is a shared object, and it has been forced
304960510Sobrien     local, we'll need the same number of RELATIVE relocations.  */
305060510Sobrien
305160510Sobrien  if (alpha_elf_dynamic_symbol_p (&h->root, info) || info->shared)
305233965Sjdp    {
305333965Sjdp      struct alpha_elf_reloc_entry *relent;
305448850Sdfr      bfd *dynobj;
305548850Sdfr      struct alpha_elf_got_entry *gotent;
305648850Sdfr      bfd_size_type count;
305748850Sdfr      asection *srel;
305833965Sjdp
305933965Sjdp      for (relent = h->reloc_entries; relent; relent = relent->next)
306060510Sobrien	if (relent->rtype == R_ALPHA_REFLONG
306160510Sobrien	    || relent->rtype == R_ALPHA_REFQUAD)
306260510Sobrien	  {
306360510Sobrien	    relent->srel->_raw_size +=
306477303Sobrien	      sizeof (Elf64_External_Rela) * relent->count;
306589862Sobrien	    if (relent->reltext)
306689862Sobrien	      info->flags |= DT_TEXTREL;
306760510Sobrien	  }
306833965Sjdp
306948850Sdfr      dynobj = elf_hash_table(info)->dynobj;
307048850Sdfr      count = 0;
307148850Sdfr
307248850Sdfr      for (gotent = h->got_entries; gotent ; gotent = gotent->next)
307348850Sdfr	count++;
307448850Sdfr
307548850Sdfr      /* If we are using a .plt entry, subtract one, as the first
307648850Sdfr	 reference uses a .rela.plt entry instead.  */
307760510Sobrien      if (h->root.plt.offset != MINUS_ONE)
307848850Sdfr	count--;
307948850Sdfr
308048850Sdfr      if (count > 0)
308133965Sjdp	{
308248850Sdfr	  srel = bfd_get_section_by_name (dynobj, ".rela.got");
308348850Sdfr	  BFD_ASSERT (srel != NULL);
308448850Sdfr	  srel->_raw_size += sizeof (Elf64_External_Rela) * count;
308533965Sjdp	}
308633965Sjdp    }
308748850Sdfr
308833965Sjdp  return true;
308933965Sjdp}
309033965Sjdp
309133965Sjdp/* Set the sizes of the dynamic sections.  */
309233965Sjdp
309333965Sjdpstatic boolean
309433965Sjdpelf64_alpha_size_dynamic_sections (output_bfd, info)
309589862Sobrien     bfd *output_bfd ATTRIBUTE_UNUSED;
309633965Sjdp     struct bfd_link_info *info;
309733965Sjdp{
309833965Sjdp  bfd *dynobj;
309933965Sjdp  asection *s;
310033965Sjdp  boolean relplt;
310133965Sjdp
310233965Sjdp  dynobj = elf_hash_table(info)->dynobj;
310333965Sjdp  BFD_ASSERT(dynobj != NULL);
310433965Sjdp
310533965Sjdp  if (elf_hash_table (info)->dynamic_sections_created)
310633965Sjdp    {
310733965Sjdp      /* Set the contents of the .interp section to the interpreter.  */
310833965Sjdp      if (!info->shared)
310933965Sjdp	{
311033965Sjdp	  s = bfd_get_section_by_name (dynobj, ".interp");
311133965Sjdp	  BFD_ASSERT (s != NULL);
311233965Sjdp	  s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
311333965Sjdp	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
311433965Sjdp	}
311533965Sjdp
311633965Sjdp      /* Now that we've seen all of the input files, we can decide which
311733965Sjdp	 symbols need dynamic relocation entries and which don't.  We've
311833965Sjdp	 collected information in check_relocs that we can now apply to
311933965Sjdp	 size the dynamic relocation sections.  */
312033965Sjdp      alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
312133965Sjdp				    elf64_alpha_calc_dynrel_sizes,
312233965Sjdp				    info);
312333965Sjdp
312433965Sjdp      /* When building shared libraries, each local .got entry needs a
312533965Sjdp	 RELATIVE reloc.  */
312633965Sjdp      if (info->shared)
312733965Sjdp	{
312833965Sjdp	  bfd *i;
312933965Sjdp	  asection *srel;
313033965Sjdp	  bfd_size_type count;
313133965Sjdp
313233965Sjdp	  srel = bfd_get_section_by_name (dynobj, ".rela.got");
313333965Sjdp	  BFD_ASSERT (srel != NULL);
313433965Sjdp
313533965Sjdp	  for (i = alpha_elf_hash_table(info)->got_list, count = 0;
313633965Sjdp	       i != NULL;
313733965Sjdp	       i = alpha_elf_tdata(i)->got_link_next)
313833965Sjdp	    count += alpha_elf_tdata(i)->n_local_got_entries;
313933965Sjdp
314077303Sobrien	  srel->_raw_size += count * sizeof (Elf64_External_Rela);
314133965Sjdp	}
314233965Sjdp    }
314333965Sjdp  /* else we're not dynamic and by definition we don't need such things.  */
314433965Sjdp
314533965Sjdp  /* The check_relocs and adjust_dynamic_symbol entry points have
314633965Sjdp     determined the sizes of the various dynamic sections.  Allocate
314733965Sjdp     memory for them.  */
314833965Sjdp  relplt = false;
314933965Sjdp  for (s = dynobj->sections; s != NULL; s = s->next)
315033965Sjdp    {
315133965Sjdp      const char *name;
315233965Sjdp      boolean strip;
315333965Sjdp
315433965Sjdp      if (!(s->flags & SEC_LINKER_CREATED))
315533965Sjdp	continue;
315633965Sjdp
315733965Sjdp      /* It's OK to base decisions on the section name, because none
315833965Sjdp	 of the dynobj section names depend upon the input files.  */
315933965Sjdp      name = bfd_get_section_name (dynobj, s);
316033965Sjdp
316133965Sjdp      /* If we don't need this section, strip it from the output file.
316233965Sjdp	 This is to handle .rela.bss and .rela.plt.  We must create it
316333965Sjdp	 in create_dynamic_sections, because it must be created before
316433965Sjdp	 the linker maps input sections to output sections.  The
316533965Sjdp	 linker does that before adjust_dynamic_symbol is called, and
316633965Sjdp	 it is that function which decides whether anything needs to
316733965Sjdp	 go into these sections.  */
316833965Sjdp
316933965Sjdp      strip = false;
317033965Sjdp
317133965Sjdp      if (strncmp (name, ".rela", 5) == 0)
317233965Sjdp	{
317333965Sjdp	  strip = (s->_raw_size == 0);
317433965Sjdp
317533965Sjdp	  if (!strip)
317633965Sjdp	    {
317733965Sjdp	      if (strcmp(name, ".rela.plt") == 0)
317833965Sjdp		relplt = true;
317933965Sjdp
318033965Sjdp	      /* We use the reloc_count field as a counter if we need
318133965Sjdp		 to copy relocs into the output file.  */
318233965Sjdp	      s->reloc_count = 0;
318333965Sjdp	    }
318433965Sjdp	}
318533965Sjdp      else if (strcmp (name, ".plt") != 0)
318633965Sjdp	{
318733965Sjdp	  /* It's not one of our dynamic sections, so don't allocate space.  */
318833965Sjdp	  continue;
318933965Sjdp	}
319033965Sjdp
319133965Sjdp      if (strip)
319260510Sobrien	_bfd_strip_section_from_output (info, s);
319333965Sjdp      else
319433965Sjdp	{
319533965Sjdp	  /* Allocate memory for the section contents.  */
319689862Sobrien	  s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
319733965Sjdp	  if (s->contents == NULL && s->_raw_size != 0)
319833965Sjdp	    return false;
319933965Sjdp	}
320033965Sjdp    }
320133965Sjdp
320233965Sjdp  if (elf_hash_table (info)->dynamic_sections_created)
320333965Sjdp    {
320433965Sjdp      /* Add some entries to the .dynamic section.  We fill in the
320533965Sjdp	 values later, in elf64_alpha_finish_dynamic_sections, but we
320633965Sjdp	 must add the entries now so that we get the correct size for
320733965Sjdp	 the .dynamic section.  The DT_DEBUG entry is filled in by the
320833965Sjdp	 dynamic linker and used by the debugger.  */
320989862Sobrien#define add_dynamic_entry(TAG, VAL) \
321089862Sobrien  bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
321189862Sobrien
321233965Sjdp      if (!info->shared)
321333965Sjdp	{
321489862Sobrien	  if (!add_dynamic_entry (DT_DEBUG, 0))
321533965Sjdp	    return false;
321633965Sjdp	}
321733965Sjdp
321889862Sobrien      if (!add_dynamic_entry (DT_PLTGOT, 0))
321933965Sjdp	return false;
322033965Sjdp
322133965Sjdp      if (relplt)
322233965Sjdp	{
322389862Sobrien	  if (!add_dynamic_entry (DT_PLTRELSZ, 0)
322489862Sobrien	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
322589862Sobrien	      || !add_dynamic_entry (DT_JMPREL, 0))
322633965Sjdp	    return false;
322733965Sjdp	}
322833965Sjdp
322989862Sobrien      if (!add_dynamic_entry (DT_RELA, 0)
323089862Sobrien	  || !add_dynamic_entry (DT_RELASZ, 0)
323189862Sobrien	  || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
323233965Sjdp	return false;
323333965Sjdp
323489862Sobrien      if (info->flags & DF_TEXTREL)
323533965Sjdp	{
323689862Sobrien	  if (!add_dynamic_entry (DT_TEXTREL, 0))
323733965Sjdp	    return false;
323833965Sjdp	}
323933965Sjdp    }
324089862Sobrien#undef add_dynamic_entry
324133965Sjdp
324233965Sjdp  return true;
324333965Sjdp}
324433965Sjdp
324533965Sjdp/* Relocate an Alpha ELF section.  */
324633965Sjdp
324733965Sjdpstatic boolean
324833965Sjdpelf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
324933965Sjdp			      contents, relocs, local_syms, local_sections)
325033965Sjdp     bfd *output_bfd;
325133965Sjdp     struct bfd_link_info *info;
325233965Sjdp     bfd *input_bfd;
325333965Sjdp     asection *input_section;
325433965Sjdp     bfd_byte *contents;
325533965Sjdp     Elf_Internal_Rela *relocs;
325633965Sjdp     Elf_Internal_Sym *local_syms;
325733965Sjdp     asection **local_sections;
325833965Sjdp{
325933965Sjdp  Elf_Internal_Shdr *symtab_hdr;
326033965Sjdp  Elf_Internal_Rela *rel;
326133965Sjdp  Elf_Internal_Rela *relend;
326233965Sjdp  asection *sec, *sgot, *srel, *srelgot;
326333965Sjdp  bfd *dynobj, *gotobj;
326433965Sjdp  bfd_vma gp;
326589862Sobrien  boolean ret_val = true;
326633965Sjdp
326733965Sjdp  srelgot = srel = NULL;
326833965Sjdp  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
326933965Sjdp  dynobj = elf_hash_table (info)->dynobj;
327033965Sjdp  if (dynobj)
327133965Sjdp    {
327233965Sjdp      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
327333965Sjdp    }
327433965Sjdp
327533965Sjdp  /* Find the gp value for this input bfd.  */
327633965Sjdp  sgot = NULL;
327733965Sjdp  gp = 0;
327833965Sjdp  gotobj = alpha_elf_tdata (input_bfd)->gotobj;
327933965Sjdp  if (gotobj)
328033965Sjdp    {
328133965Sjdp      sgot = alpha_elf_tdata (gotobj)->got;
328233965Sjdp      gp = _bfd_get_gp_value (gotobj);
328333965Sjdp      if (gp == 0)
328433965Sjdp	{
328533965Sjdp	  gp = (sgot->output_section->vma
328633965Sjdp		+ sgot->output_offset
328733965Sjdp		+ 0x8000);
328833965Sjdp	  _bfd_set_gp_value (gotobj, gp);
328933965Sjdp	}
329033965Sjdp    }
329133965Sjdp
329233965Sjdp  rel = relocs;
329333965Sjdp  relend = relocs + input_section->reloc_count;
329433965Sjdp  for (; rel < relend; rel++)
329533965Sjdp    {
329633965Sjdp      int r_type;
329733965Sjdp      reloc_howto_type *howto;
329833965Sjdp      unsigned long r_symndx;
329933965Sjdp      struct alpha_elf_link_hash_entry *h;
330033965Sjdp      Elf_Internal_Sym *sym;
330133965Sjdp      bfd_vma relocation;
330233965Sjdp      bfd_vma addend;
330333965Sjdp      bfd_reloc_status_type r;
330433965Sjdp
330533965Sjdp      r_type = ELF64_R_TYPE(rel->r_info);
330633965Sjdp      if (r_type < 0 || r_type >= (int) R_ALPHA_max)
330733965Sjdp	{
330833965Sjdp	  bfd_set_error (bfd_error_bad_value);
330933965Sjdp	  return false;
331033965Sjdp	}
331133965Sjdp      howto = elf64_alpha_howto_table + r_type;
331233965Sjdp
331333965Sjdp      r_symndx = ELF64_R_SYM(rel->r_info);
331433965Sjdp
331533965Sjdp      if (info->relocateable)
331633965Sjdp	{
331733965Sjdp	  /* This is a relocateable link.  We don't have to change
331833965Sjdp	     anything, unless the reloc is against a section symbol,
331933965Sjdp	     in which case we have to adjust according to where the
332033965Sjdp	     section symbol winds up in the output section.  */
332160510Sobrien
332277303Sobrien	  /* The symbol associated with GPDISP and LITUSE is
332360510Sobrien	     immaterial.  Only the addend is significant.  */
332460510Sobrien	  if (r_type == R_ALPHA_GPDISP || r_type == R_ALPHA_LITUSE)
332560510Sobrien	    continue;
332660510Sobrien
332733965Sjdp	  if (r_symndx < symtab_hdr->sh_info)
332833965Sjdp	    {
332933965Sjdp	      sym = local_syms + r_symndx;
333033965Sjdp	      if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
333133965Sjdp		{
333233965Sjdp		  sec = local_sections[r_symndx];
333333965Sjdp		  rel->r_addend += sec->output_offset + sym->st_value;
333433965Sjdp		}
333533965Sjdp	    }
333633965Sjdp
333733965Sjdp	  continue;
333833965Sjdp	}
333933965Sjdp
334033965Sjdp      /* This is a final link.  */
334133965Sjdp
334233965Sjdp      h = NULL;
334333965Sjdp      sym = NULL;
334433965Sjdp      sec = NULL;
334533965Sjdp
334633965Sjdp      if (r_symndx < symtab_hdr->sh_info)
334733965Sjdp	{
334833965Sjdp	  sym = local_syms + r_symndx;
334933965Sjdp	  sec = local_sections[r_symndx];
335089862Sobrien	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
335133965Sjdp	}
335233965Sjdp      else
335333965Sjdp	{
335433965Sjdp	  h = alpha_elf_sym_hashes (input_bfd)[r_symndx - symtab_hdr->sh_info];
335533965Sjdp
335633965Sjdp	  while (h->root.root.type == bfd_link_hash_indirect
335733965Sjdp		 || h->root.root.type == bfd_link_hash_warning)
335833965Sjdp	    h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
335933965Sjdp
336033965Sjdp	  if (h->root.root.type == bfd_link_hash_defined
336133965Sjdp	      || h->root.root.type == bfd_link_hash_defweak)
336233965Sjdp	    {
336333965Sjdp	      sec = h->root.root.u.def.section;
336433965Sjdp
336533965Sjdp	      if (sec->output_section == NULL)
336633965Sjdp		relocation = 0;
336733965Sjdp	      else
336833965Sjdp		{
336933965Sjdp		  relocation = (h->root.root.u.def.value
337033965Sjdp				+ sec->output_section->vma
337133965Sjdp				+ sec->output_offset);
337233965Sjdp		}
337333965Sjdp	    }
337433965Sjdp	  else if (h->root.root.type == bfd_link_hash_undefweak)
337533965Sjdp	    relocation = 0;
337689862Sobrien	  else if (info->shared
337789862Sobrien		   && (!info->symbolic || info->allow_shlib_undefined)
337868770Sobrien		   && !info->no_undefined
337968770Sobrien		   && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
338033965Sjdp	    relocation = 0;
338133965Sjdp	  else
338233965Sjdp	    {
338333965Sjdp	      if (!((*info->callbacks->undefined_symbol)
338433965Sjdp		    (info, h->root.root.root.string, input_bfd,
338560510Sobrien		     input_section, rel->r_offset,
338668770Sobrien		     (!info->shared || info->no_undefined
338768770Sobrien		      || ELF_ST_VISIBILITY (h->root.other)))))
338889862Sobrien		ret_val = false;
338933965Sjdp	      relocation = 0;
339033965Sjdp	    }
339133965Sjdp	}
339233965Sjdp      addend = rel->r_addend;
339333965Sjdp
339433965Sjdp      switch (r_type)
339533965Sjdp	{
339633965Sjdp	case R_ALPHA_GPDISP:
339733965Sjdp	  {
339833965Sjdp	    bfd_byte *p_ldah, *p_lda;
339933965Sjdp
340033965Sjdp	    BFD_ASSERT(gp != 0);
340133965Sjdp
340233965Sjdp	    relocation = (input_section->output_section->vma
340333965Sjdp			  + input_section->output_offset
340433965Sjdp			  + rel->r_offset);
340533965Sjdp
340633965Sjdp	    p_ldah = contents + rel->r_offset - input_section->vma;
340733965Sjdp	    p_lda = p_ldah + rel->r_addend;
340833965Sjdp
340933965Sjdp	    r = elf64_alpha_do_reloc_gpdisp (input_bfd, gp - relocation,
341033965Sjdp					     p_ldah, p_lda);
341133965Sjdp	  }
341233965Sjdp	  break;
341333965Sjdp
341433965Sjdp	case R_ALPHA_LITERAL:
341533965Sjdp	  {
341633965Sjdp	    struct alpha_elf_got_entry *gotent;
341760510Sobrien	    boolean dynamic_symbol;
341833965Sjdp
341933965Sjdp	    BFD_ASSERT(sgot != NULL);
342033965Sjdp	    BFD_ASSERT(gp != 0);
342133965Sjdp
342233965Sjdp	    if (h != NULL)
342333965Sjdp	      {
342433965Sjdp		gotent = h->got_entries;
342560510Sobrien		dynamic_symbol = alpha_elf_dynamic_symbol_p (&h->root, info);
342633965Sjdp	      }
342733965Sjdp	    else
342833965Sjdp	      {
342933965Sjdp		gotent = (alpha_elf_tdata(input_bfd)->
343033965Sjdp			  local_got_entries[r_symndx]);
343160510Sobrien		dynamic_symbol = false;
343289862Sobrien
343389862Sobrien		/* Need to adjust local GOT entries' addends for SEC_MERGE
343489862Sobrien		   unless it has been done already.  */
343589862Sobrien		if ((sec->flags & SEC_MERGE)
343689862Sobrien		    && ELF_ST_TYPE (sym->st_info) == STT_SECTION
343789862Sobrien		    && (elf_section_data (sec)->sec_info_type
343889862Sobrien			== ELF_INFO_TYPE_MERGE)
343989862Sobrien		    && (gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED) == 0)
344089862Sobrien		  {
344189862Sobrien		    struct alpha_elf_got_entry *ent;
344289862Sobrien		    asection *msec;
344389862Sobrien
344489862Sobrien		    for (ent = gotent; ent; ent = ent->next)
344589862Sobrien		      {
344689862Sobrien			ent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED;
344789862Sobrien			if (ent->use_count == 0)
344889862Sobrien			  continue;
344989862Sobrien			msec = sec;
345089862Sobrien			ent->addend =
345189862Sobrien			  _bfd_merged_section_offset (output_bfd, &msec,
345289862Sobrien						      elf_section_data (sec)->
345389862Sobrien						      sec_info,
345489862Sobrien						      sym->st_value
345589862Sobrien						      + ent->addend,
345689862Sobrien						      (bfd_vma) 0);
345789862Sobrien			ent->addend -= sym->st_value;
345889862Sobrien			ent->addend += msec->output_section->vma
345989862Sobrien				       + msec->output_offset
346089862Sobrien				       - sec->output_section->vma
346189862Sobrien				       - sec->output_offset;
346289862Sobrien		      }
346389862Sobrien		  }
346460510Sobrien	      }
346533965Sjdp
346660510Sobrien	    BFD_ASSERT(gotent != NULL);
346733965Sjdp
346860510Sobrien	    while (gotent->gotobj != gotobj || gotent->addend != addend)
346960510Sobrien	      gotent = gotent->next;
347033965Sjdp
347160510Sobrien	    BFD_ASSERT(gotent->use_count >= 1);
347233965Sjdp
347360510Sobrien	    /* Initialize the .got entry's value.  */
347460510Sobrien	    if (!(gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_DONE))
347560510Sobrien	      {
347689862Sobrien		bfd_put_64 (output_bfd, relocation + addend,
347760510Sobrien			    sgot->contents + gotent->got_offset);
347833965Sjdp
347960510Sobrien		/* If the symbol has been forced local, output a
348060510Sobrien		   RELATIVE reloc, otherwise it will be handled in
348160510Sobrien		   finish_dynamic_symbol.  */
348260510Sobrien		if (info->shared && !dynamic_symbol)
348360510Sobrien		  {
348460510Sobrien		    Elf_Internal_Rela outrel;
348533965Sjdp
348660510Sobrien		    BFD_ASSERT(srelgot != NULL);
348760510Sobrien
348860510Sobrien		    outrel.r_offset = (sgot->output_section->vma
348960510Sobrien				       + sgot->output_offset
349060510Sobrien				       + gotent->got_offset);
349160510Sobrien		    outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE);
349289862Sobrien		    outrel.r_addend = relocation + addend;
349360510Sobrien
349460510Sobrien		    bfd_elf64_swap_reloca_out (output_bfd, &outrel,
349560510Sobrien					       ((Elf64_External_Rela *)
349660510Sobrien					        srelgot->contents)
349760510Sobrien					       + srelgot->reloc_count++);
349877303Sobrien		    BFD_ASSERT (sizeof (Elf64_External_Rela)
349960510Sobrien				* srelgot->reloc_count
350060510Sobrien				<= srelgot->_cooked_size);
350133965Sjdp		  }
350260510Sobrien
350360510Sobrien		gotent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_DONE;
350433965Sjdp	      }
350533965Sjdp
350633965Sjdp	    /* Figure the gprel relocation.  */
350733965Sjdp	    addend = 0;
350833965Sjdp	    relocation = (sgot->output_section->vma
350933965Sjdp			  + sgot->output_offset
351033965Sjdp			  + gotent->got_offset);
351133965Sjdp	    relocation -= gp;
351233965Sjdp	  }
351333965Sjdp	  /* overflow handled by _bfd_final_link_relocate */
351433965Sjdp	  goto default_reloc;
351533965Sjdp
351689862Sobrien	case R_ALPHA_GPREL16:
351733965Sjdp	case R_ALPHA_GPREL32:
351860510Sobrien	case R_ALPHA_GPRELLOW:
351989862Sobrien	  if (h && alpha_elf_dynamic_symbol_p (&h->root, info))
352089862Sobrien            {
352189862Sobrien              (*_bfd_error_handler)
352289862Sobrien                (_("%s: gp-relative relocation against dynamic symbol %s"),
352389862Sobrien                 bfd_archive_filename (input_bfd), h->root.root.root.string);
352489862Sobrien              ret_val = false;
352589862Sobrien            }
352633965Sjdp	  BFD_ASSERT(gp != 0);
352733965Sjdp	  relocation -= gp;
352833965Sjdp	  goto default_reloc;
352933965Sjdp
353060510Sobrien	case R_ALPHA_GPRELHIGH:
353189862Sobrien	  if (h && alpha_elf_dynamic_symbol_p (&h->root, info))
353289862Sobrien            {
353389862Sobrien              (*_bfd_error_handler)
353489862Sobrien                (_("%s: gp-relative relocation against dynamic symbol %s"),
353589862Sobrien                 bfd_archive_filename (input_bfd), h->root.root.root.string);
353689862Sobrien              ret_val = false;
353789862Sobrien            }
353860510Sobrien	  BFD_ASSERT(gp != 0);
353960510Sobrien	  relocation -= gp;
354060510Sobrien	  relocation += addend;
354160510Sobrien	  addend = 0;
354260510Sobrien	  relocation = (((bfd_signed_vma) relocation >> 16)
354360510Sobrien			+ ((relocation >> 15) & 1));
354460510Sobrien	  goto default_reloc;
354560510Sobrien
354689862Sobrien	case R_ALPHA_HINT:
354789862Sobrien	  /* A call to a dynamic symbol is definitely out of range of
354889862Sobrien	     the 16-bit displacement.  Don't bother writing anything.  */
354989862Sobrien	  if (h && alpha_elf_dynamic_symbol_p (&h->root, info))
355089862Sobrien	    {
355189862Sobrien	      r = bfd_reloc_ok;
355289862Sobrien	      break;
355389862Sobrien	    }
355489862Sobrien	  /* FALLTHRU */
355589862Sobrien
355633965Sjdp	case R_ALPHA_BRADDR:
355733965Sjdp	  /* The regular PC-relative stuff measures from the start of
355833965Sjdp	     the instruction rather than the end.  */
355933965Sjdp	  addend -= 4;
356033965Sjdp	  goto default_reloc;
356133965Sjdp
356233965Sjdp	case R_ALPHA_REFLONG:
356333965Sjdp	case R_ALPHA_REFQUAD:
356433965Sjdp	  {
356533965Sjdp	    Elf_Internal_Rela outrel;
356633965Sjdp
356733965Sjdp	    /* Careful here to remember RELATIVE relocations for global
356833965Sjdp	       variables for symbolic shared objects.  */
356933965Sjdp
357033965Sjdp	    if (h && alpha_elf_dynamic_symbol_p (&h->root, info))
357133965Sjdp	      {
357233965Sjdp		BFD_ASSERT(h->root.dynindx != -1);
357333965Sjdp		outrel.r_info = ELF64_R_INFO(h->root.dynindx, r_type);
357433965Sjdp		outrel.r_addend = addend;
357533965Sjdp		addend = 0, relocation = 0;
357633965Sjdp	      }
357789862Sobrien	    else if (info->shared
357889862Sobrien		     && r_symndx != 0
357989862Sobrien		     && (input_section->flags & SEC_ALLOC))
358033965Sjdp	      {
358133965Sjdp		outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE);
358289862Sobrien		outrel.r_addend = relocation + addend;
358333965Sjdp	      }
358433965Sjdp	    else
358533965Sjdp	      goto default_reloc;
358633965Sjdp
358733965Sjdp	    if (!srel)
358833965Sjdp	      {
358933965Sjdp		const char *name;
359033965Sjdp
359133965Sjdp		name = (bfd_elf_string_from_elf_section
359233965Sjdp			(input_bfd, elf_elfheader(input_bfd)->e_shstrndx,
359333965Sjdp			 elf_section_data(input_section)->rel_hdr.sh_name));
359433965Sjdp		BFD_ASSERT(name != NULL);
359533965Sjdp
359633965Sjdp		srel = bfd_get_section_by_name (dynobj, name);
359733965Sjdp		BFD_ASSERT(srel != NULL);
359833965Sjdp	      }
359933965Sjdp
360089862Sobrien	    outrel.r_offset =
360189862Sobrien	      _bfd_elf_section_offset (output_bfd, info, input_section,
360289862Sobrien				       rel->r_offset);
360389862Sobrien	    if (outrel.r_offset != (bfd_vma) -1)
360433965Sjdp	      outrel.r_offset += (input_section->output_section->vma
360533965Sjdp				  + input_section->output_offset);
360633965Sjdp	    else
360733965Sjdp	      memset (&outrel, 0, sizeof outrel);
360833965Sjdp
360933965Sjdp	    bfd_elf64_swap_reloca_out (output_bfd, &outrel,
361033965Sjdp				       ((Elf64_External_Rela *)
361133965Sjdp					srel->contents)
361233965Sjdp				       + srel->reloc_count++);
361377303Sobrien	    BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
361448850Sdfr			<= srel->_cooked_size);
361533965Sjdp	  }
361633965Sjdp	  goto default_reloc;
361733965Sjdp
361833965Sjdp	default:
361933965Sjdp	default_reloc:
362033965Sjdp	  r = _bfd_final_link_relocate (howto, input_bfd, input_section,
362133965Sjdp					contents, rel->r_offset, relocation,
362233965Sjdp					addend);
362333965Sjdp	  break;
362433965Sjdp	}
362533965Sjdp
362633965Sjdp      switch (r)
362733965Sjdp	{
362833965Sjdp	case bfd_reloc_ok:
362933965Sjdp	  break;
363033965Sjdp
363133965Sjdp	case bfd_reloc_overflow:
363233965Sjdp	  {
363333965Sjdp	    const char *name;
363433965Sjdp
363589862Sobrien	    /* Don't warn if the overflow is due to pc relative reloc
363689862Sobrien	       against discarded section.  Section optimization code should
363789862Sobrien	       handle it.  */
363889862Sobrien
363989862Sobrien	    if (r_symndx < symtab_hdr->sh_info
364089862Sobrien		&& sec != NULL && howto->pc_relative
364189862Sobrien		&& elf_discarded_section (sec))
364289862Sobrien	      break;
364389862Sobrien
364433965Sjdp	    if (h != NULL)
364533965Sjdp	      name = h->root.root.root.string;
364633965Sjdp	    else
364733965Sjdp	      {
364833965Sjdp		name = (bfd_elf_string_from_elf_section
364933965Sjdp			(input_bfd, symtab_hdr->sh_link, sym->st_name));
365033965Sjdp		if (name == NULL)
365133965Sjdp		  return false;
365233965Sjdp		if (*name == '\0')
365333965Sjdp		  name = bfd_section_name (input_bfd, sec);
365433965Sjdp	      }
365533965Sjdp	    if (! ((*info->callbacks->reloc_overflow)
365633965Sjdp		   (info, name, howto->name, (bfd_vma) 0,
365733965Sjdp		    input_bfd, input_section, rel->r_offset)))
365889862Sobrien	      ret_val = false;
365933965Sjdp	  }
366033965Sjdp	  break;
366133965Sjdp
366233965Sjdp	default:
366333965Sjdp	case bfd_reloc_outofrange:
366433965Sjdp	  abort ();
366533965Sjdp	}
366633965Sjdp    }
366733965Sjdp
366889862Sobrien  return ret_val;
366933965Sjdp}
367033965Sjdp
367133965Sjdp/* Finish up dynamic symbol handling.  We set the contents of various
367233965Sjdp   dynamic sections here.  */
367333965Sjdp
367433965Sjdpstatic boolean
367533965Sjdpelf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym)
367633965Sjdp     bfd *output_bfd;
367733965Sjdp     struct bfd_link_info *info;
367833965Sjdp     struct elf_link_hash_entry *h;
367933965Sjdp     Elf_Internal_Sym *sym;
368033965Sjdp{
368133965Sjdp  bfd *dynobj = elf_hash_table(info)->dynobj;
368233965Sjdp
368360510Sobrien  if (h->plt.offset != MINUS_ONE)
368433965Sjdp    {
368533965Sjdp      /* Fill in the .plt entry for this symbol.  */
368633965Sjdp      asection *splt, *sgot, *srel;
368733965Sjdp      Elf_Internal_Rela outrel;
368833965Sjdp      bfd_vma got_addr, plt_addr;
368933965Sjdp      bfd_vma plt_index;
369033965Sjdp      struct alpha_elf_got_entry *gotent;
369133965Sjdp
369233965Sjdp      BFD_ASSERT (h->dynindx != -1);
369333965Sjdp
369433965Sjdp      /* The first .got entry will be updated by the .plt with the
369533965Sjdp	 address of the target function.  */
369633965Sjdp      gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
369733965Sjdp      BFD_ASSERT (gotent && gotent->addend == 0);
369833965Sjdp
369933965Sjdp      splt = bfd_get_section_by_name (dynobj, ".plt");
370033965Sjdp      BFD_ASSERT (splt != NULL);
370133965Sjdp      srel = bfd_get_section_by_name (dynobj, ".rela.plt");
370233965Sjdp      BFD_ASSERT (srel != NULL);
370333965Sjdp      sgot = alpha_elf_tdata (gotent->gotobj)->got;
370433965Sjdp      BFD_ASSERT (sgot != NULL);
370533965Sjdp
370633965Sjdp      got_addr = (sgot->output_section->vma
370733965Sjdp		  + sgot->output_offset
370833965Sjdp		  + gotent->got_offset);
370933965Sjdp      plt_addr = (splt->output_section->vma
371033965Sjdp		  + splt->output_offset
371160510Sobrien		  + h->plt.offset);
371233965Sjdp
371360510Sobrien      plt_index = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
371433965Sjdp
371533965Sjdp      /* Fill in the entry in the procedure linkage table.  */
371633965Sjdp      {
371789862Sobrien	bfd_vma insn1, insn2, insn3;
371833965Sjdp
371960510Sobrien	insn1 = PLT_ENTRY_WORD1 | ((-(h->plt.offset + 4) >> 2) & 0x1fffff);
372038889Sjdp	insn2 = PLT_ENTRY_WORD2;
372138889Sjdp	insn3 = PLT_ENTRY_WORD3;
372233965Sjdp
372360510Sobrien	bfd_put_32 (output_bfd, insn1, splt->contents + h->plt.offset);
372460510Sobrien	bfd_put_32 (output_bfd, insn2, splt->contents + h->plt.offset + 4);
372560510Sobrien	bfd_put_32 (output_bfd, insn3, splt->contents + h->plt.offset + 8);
372633965Sjdp      }
372733965Sjdp
372833965Sjdp      /* Fill in the entry in the .rela.plt section.  */
372933965Sjdp      outrel.r_offset = got_addr;
373033965Sjdp      outrel.r_info = ELF64_R_INFO(h->dynindx, R_ALPHA_JMP_SLOT);
373133965Sjdp      outrel.r_addend = 0;
373233965Sjdp
373333965Sjdp      bfd_elf64_swap_reloca_out (output_bfd, &outrel,
373433965Sjdp				 ((Elf64_External_Rela *)srel->contents
373533965Sjdp				  + plt_index));
373633965Sjdp
373733965Sjdp      if (!(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
373833965Sjdp	{
373933965Sjdp	  /* Mark the symbol as undefined, rather than as defined in the
374033965Sjdp	     .plt section.  Leave the value alone.  */
374133965Sjdp	  sym->st_shndx = SHN_UNDEF;
374233965Sjdp	}
374333965Sjdp
374433965Sjdp      /* Fill in the entries in the .got.  */
374533965Sjdp      bfd_put_64 (output_bfd, plt_addr, sgot->contents + gotent->got_offset);
374633965Sjdp
374733965Sjdp      /* Subsequent .got entries will continue to bounce through the .plt.  */
374848850Sdfr      if (gotent->next)
374933965Sjdp	{
375048850Sdfr	  srel = bfd_get_section_by_name (dynobj, ".rela.got");
375148850Sdfr	  BFD_ASSERT (! info->shared || srel != NULL);
375233965Sjdp
375348850Sdfr	  gotent = gotent->next;
375448850Sdfr	  do
375548850Sdfr	    {
375648850Sdfr	      sgot = alpha_elf_tdata(gotent->gotobj)->got;
375748850Sdfr	      BFD_ASSERT(sgot != NULL);
375848850Sdfr	      BFD_ASSERT(gotent->addend == 0);
375948850Sdfr
376048850Sdfr	      bfd_put_64 (output_bfd, plt_addr,
376148850Sdfr		          sgot->contents + gotent->got_offset);
376248850Sdfr
376348850Sdfr	      if (info->shared)
376448850Sdfr		{
376548850Sdfr		  outrel.r_offset = (sgot->output_section->vma
376648850Sdfr				     + sgot->output_offset
376748850Sdfr				     + gotent->got_offset);
376848850Sdfr		  outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE);
376989862Sobrien		  outrel.r_addend = plt_addr;
377048850Sdfr
377148850Sdfr		  bfd_elf64_swap_reloca_out (output_bfd, &outrel,
377248850Sdfr					     ((Elf64_External_Rela *)
377348850Sdfr					      srel->contents)
377448850Sdfr					     + srel->reloc_count++);
377577303Sobrien		  BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
377648850Sdfr			      <= srel->_cooked_size);
377748850Sdfr		}
377848850Sdfr
377948850Sdfr	      gotent = gotent->next;
378048850Sdfr	    }
378148850Sdfr          while (gotent != NULL);
378233965Sjdp	}
378333965Sjdp    }
378433965Sjdp  else if (alpha_elf_dynamic_symbol_p (h, info))
378533965Sjdp    {
378633965Sjdp      /* Fill in the dynamic relocations for this symbol's .got entries.  */
378733965Sjdp      asection *srel;
378833965Sjdp      Elf_Internal_Rela outrel;
378933965Sjdp      struct alpha_elf_got_entry *gotent;
379033965Sjdp
379133965Sjdp      srel = bfd_get_section_by_name (dynobj, ".rela.got");
379233965Sjdp      BFD_ASSERT (srel != NULL);
379333965Sjdp
379433965Sjdp      outrel.r_info = ELF64_R_INFO (h->dynindx, R_ALPHA_GLOB_DAT);
379533965Sjdp      for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
379633965Sjdp	   gotent != NULL;
379733965Sjdp	   gotent = gotent->next)
379833965Sjdp	{
379933965Sjdp	  asection *sgot = alpha_elf_tdata (gotent->gotobj)->got;
380033965Sjdp	  outrel.r_offset = (sgot->output_section->vma
380133965Sjdp			     + sgot->output_offset
380233965Sjdp			     + gotent->got_offset);
380333965Sjdp	  outrel.r_addend = gotent->addend;
380433965Sjdp
380533965Sjdp	  bfd_elf64_swap_reloca_out (output_bfd, &outrel,
380633965Sjdp				     ((Elf64_External_Rela *)srel->contents
380733965Sjdp				      + srel->reloc_count++));
380877303Sobrien	  BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
380948850Sdfr		      <= srel->_cooked_size);
381033965Sjdp	}
381133965Sjdp    }
381233965Sjdp
381333965Sjdp  /* Mark some specially defined symbols as absolute.  */
381433965Sjdp  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
381533965Sjdp      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
381633965Sjdp      || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
381733965Sjdp    sym->st_shndx = SHN_ABS;
381833965Sjdp
381933965Sjdp  return true;
382033965Sjdp}
382133965Sjdp
382233965Sjdp/* Finish up the dynamic sections.  */
382333965Sjdp
382433965Sjdpstatic boolean
382533965Sjdpelf64_alpha_finish_dynamic_sections (output_bfd, info)
382633965Sjdp     bfd *output_bfd;
382733965Sjdp     struct bfd_link_info *info;
382833965Sjdp{
382933965Sjdp  bfd *dynobj;
383033965Sjdp  asection *sdyn;
383133965Sjdp
383233965Sjdp  dynobj = elf_hash_table (info)->dynobj;
383333965Sjdp  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
383433965Sjdp
383533965Sjdp  if (elf_hash_table (info)->dynamic_sections_created)
383633965Sjdp    {
383733965Sjdp      asection *splt;
383833965Sjdp      Elf64_External_Dyn *dyncon, *dynconend;
383933965Sjdp
384033965Sjdp      splt = bfd_get_section_by_name (dynobj, ".plt");
384133965Sjdp      BFD_ASSERT (splt != NULL && sdyn != NULL);
384233965Sjdp
384333965Sjdp      dyncon = (Elf64_External_Dyn *) sdyn->contents;
384433965Sjdp      dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
384533965Sjdp      for (; dyncon < dynconend; dyncon++)
384633965Sjdp	{
384733965Sjdp	  Elf_Internal_Dyn dyn;
384833965Sjdp	  const char *name;
384933965Sjdp	  asection *s;
385033965Sjdp
385133965Sjdp	  bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn);
385233965Sjdp
385333965Sjdp	  switch (dyn.d_tag)
385433965Sjdp	    {
385533965Sjdp	    case DT_PLTGOT:
385633965Sjdp	      name = ".plt";
385733965Sjdp	      goto get_vma;
385833965Sjdp	    case DT_PLTRELSZ:
385933965Sjdp	      name = ".rela.plt";
386033965Sjdp	      goto get_size;
386133965Sjdp	    case DT_JMPREL:
386233965Sjdp	      name = ".rela.plt";
386333965Sjdp	      goto get_vma;
386433965Sjdp
386533965Sjdp	    case DT_RELASZ:
386633965Sjdp	      /* My interpretation of the TIS v1.1 ELF document indicates
386733965Sjdp		 that RELASZ should not include JMPREL.  This is not what
386833965Sjdp		 the rest of the BFD does.  It is, however, what the
386933965Sjdp		 glibc ld.so wants.  Do this fixup here until we found
387033965Sjdp		 out who is right.  */
387133965Sjdp	      s = bfd_get_section_by_name (output_bfd, ".rela.plt");
387233965Sjdp	      if (s)
387333965Sjdp		{
387433965Sjdp		  dyn.d_un.d_val -=
387533965Sjdp		    (s->_cooked_size ? s->_cooked_size : s->_raw_size);
387633965Sjdp		}
387733965Sjdp	      break;
387833965Sjdp
387933965Sjdp	    get_vma:
388033965Sjdp	      s = bfd_get_section_by_name (output_bfd, name);
388133965Sjdp	      dyn.d_un.d_ptr = (s ? s->vma : 0);
388233965Sjdp	      break;
388333965Sjdp
388433965Sjdp	    get_size:
388533965Sjdp	      s = bfd_get_section_by_name (output_bfd, name);
388633965Sjdp	      dyn.d_un.d_val =
388733965Sjdp		(s->_cooked_size ? s->_cooked_size : s->_raw_size);
388833965Sjdp	      break;
388933965Sjdp	    }
389033965Sjdp
389133965Sjdp	  bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
389233965Sjdp	}
389333965Sjdp
389433965Sjdp      /* Initialize the PLT0 entry */
389533965Sjdp      if (splt->_raw_size > 0)
389633965Sjdp	{
389733965Sjdp	  bfd_put_32 (output_bfd, PLT_HEADER_WORD1, splt->contents);
389833965Sjdp	  bfd_put_32 (output_bfd, PLT_HEADER_WORD2, splt->contents + 4);
389933965Sjdp	  bfd_put_32 (output_bfd, PLT_HEADER_WORD3, splt->contents + 8);
390033965Sjdp	  bfd_put_32 (output_bfd, PLT_HEADER_WORD4, splt->contents + 12);
390133965Sjdp
390233965Sjdp	  /* The next two words will be filled in by ld.so */
390389862Sobrien	  bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 16);
390489862Sobrien	  bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 24);
390533965Sjdp
390633965Sjdp	  elf_section_data (splt->output_section)->this_hdr.sh_entsize =
390733965Sjdp	    PLT_HEADER_SIZE;
390833965Sjdp	}
390933965Sjdp    }
391033965Sjdp
391133965Sjdp  return true;
391233965Sjdp}
391333965Sjdp
391489862Sobrien/* We need to use a special link routine to handle the .mdebug section.
391589862Sobrien   We need to merge all instances of these sections together, not write
391689862Sobrien   them all out sequentially.  */
391733965Sjdp
391833965Sjdpstatic boolean
391933965Sjdpelf64_alpha_final_link (abfd, info)
392033965Sjdp     bfd *abfd;
392133965Sjdp     struct bfd_link_info *info;
392233965Sjdp{
392333965Sjdp  asection *o;
392433965Sjdp  struct bfd_link_order *p;
392589862Sobrien  asection *mdebug_sec;
392633965Sjdp  struct ecoff_debug_info debug;
392733965Sjdp  const struct ecoff_debug_swap *swap
392833965Sjdp    = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
392933965Sjdp  HDRR *symhdr = &debug.symbolic_header;
393033965Sjdp  PTR mdebug_handle = NULL;
393133965Sjdp
393289862Sobrien  /* Go through the sections and collect the mdebug information.  */
393333965Sjdp  mdebug_sec = NULL;
393433965Sjdp  for (o = abfd->sections; o != (asection *) NULL; o = o->next)
393533965Sjdp    {
393633965Sjdp      if (strcmp (o->name, ".mdebug") == 0)
393733965Sjdp	{
393833965Sjdp	  struct extsym_info einfo;
393933965Sjdp
394033965Sjdp	  /* We have found the .mdebug section in the output file.
394133965Sjdp	     Look through all the link_orders comprising it and merge
394233965Sjdp	     the information together.  */
394333965Sjdp	  symhdr->magic = swap->sym_magic;
394433965Sjdp	  /* FIXME: What should the version stamp be?  */
394533965Sjdp	  symhdr->vstamp = 0;
394633965Sjdp	  symhdr->ilineMax = 0;
394733965Sjdp	  symhdr->cbLine = 0;
394833965Sjdp	  symhdr->idnMax = 0;
394933965Sjdp	  symhdr->ipdMax = 0;
395033965Sjdp	  symhdr->isymMax = 0;
395133965Sjdp	  symhdr->ioptMax = 0;
395233965Sjdp	  symhdr->iauxMax = 0;
395333965Sjdp	  symhdr->issMax = 0;
395433965Sjdp	  symhdr->issExtMax = 0;
395533965Sjdp	  symhdr->ifdMax = 0;
395633965Sjdp	  symhdr->crfd = 0;
395733965Sjdp	  symhdr->iextMax = 0;
395833965Sjdp
395933965Sjdp	  /* We accumulate the debugging information itself in the
396033965Sjdp	     debug_info structure.  */
396133965Sjdp	  debug.line = NULL;
396233965Sjdp	  debug.external_dnr = NULL;
396333965Sjdp	  debug.external_pdr = NULL;
396433965Sjdp	  debug.external_sym = NULL;
396533965Sjdp	  debug.external_opt = NULL;
396633965Sjdp	  debug.external_aux = NULL;
396733965Sjdp	  debug.ss = NULL;
396833965Sjdp	  debug.ssext = debug.ssext_end = NULL;
396933965Sjdp	  debug.external_fdr = NULL;
397033965Sjdp	  debug.external_rfd = NULL;
397133965Sjdp	  debug.external_ext = debug.external_ext_end = NULL;
397233965Sjdp
397333965Sjdp	  mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info);
397433965Sjdp	  if (mdebug_handle == (PTR) NULL)
397533965Sjdp	    return false;
397633965Sjdp
397733965Sjdp	  if (1)
397833965Sjdp	    {
397933965Sjdp	      asection *s;
398033965Sjdp	      EXTR esym;
398189862Sobrien	      bfd_vma last = 0;
398233965Sjdp	      unsigned int i;
398333965Sjdp	      static const char * const name[] =
398433965Sjdp		{
398533965Sjdp		  ".text", ".init", ".fini", ".data",
398633965Sjdp		  ".rodata", ".sdata", ".sbss", ".bss"
398733965Sjdp		};
398833965Sjdp	      static const int sc[] = { scText, scInit, scFini, scData,
398933965Sjdp					  scRData, scSData, scSBss, scBss };
399033965Sjdp
399133965Sjdp	      esym.jmptbl = 0;
399233965Sjdp	      esym.cobol_main = 0;
399333965Sjdp	      esym.weakext = 0;
399433965Sjdp	      esym.reserved = 0;
399533965Sjdp	      esym.ifd = ifdNil;
399633965Sjdp	      esym.asym.iss = issNil;
399733965Sjdp	      esym.asym.st = stLocal;
399833965Sjdp	      esym.asym.reserved = 0;
399933965Sjdp	      esym.asym.index = indexNil;
400033965Sjdp	      for (i = 0; i < 8; i++)
400133965Sjdp		{
400233965Sjdp		  esym.asym.sc = sc[i];
400333965Sjdp		  s = bfd_get_section_by_name (abfd, name[i]);
400433965Sjdp		  if (s != NULL)
400533965Sjdp		    {
400633965Sjdp		      esym.asym.value = s->vma;
400733965Sjdp		      last = s->vma + s->_raw_size;
400833965Sjdp		    }
400933965Sjdp		  else
401033965Sjdp		    esym.asym.value = last;
401133965Sjdp
401233965Sjdp		  if (! bfd_ecoff_debug_one_external (abfd, &debug, swap,
401333965Sjdp						      name[i], &esym))
401433965Sjdp		    return false;
401533965Sjdp		}
401633965Sjdp	    }
401733965Sjdp
401833965Sjdp	  for (p = o->link_order_head;
401933965Sjdp	       p != (struct bfd_link_order *) NULL;
402033965Sjdp	       p = p->next)
402133965Sjdp	    {
402233965Sjdp	      asection *input_section;
402333965Sjdp	      bfd *input_bfd;
402433965Sjdp	      const struct ecoff_debug_swap *input_swap;
402533965Sjdp	      struct ecoff_debug_info input_debug;
402633965Sjdp	      char *eraw_src;
402733965Sjdp	      char *eraw_end;
402833965Sjdp
402933965Sjdp	      if (p->type != bfd_indirect_link_order)
403033965Sjdp		{
403133965Sjdp		  if (p->type == bfd_fill_link_order)
403233965Sjdp		    continue;
403333965Sjdp		  abort ();
403433965Sjdp		}
403533965Sjdp
403633965Sjdp	      input_section = p->u.indirect.section;
403733965Sjdp	      input_bfd = input_section->owner;
403833965Sjdp
403933965Sjdp	      if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour
404033965Sjdp		  || (get_elf_backend_data (input_bfd)
404133965Sjdp		      ->elf_backend_ecoff_debug_swap) == NULL)
404233965Sjdp		{
404333965Sjdp		  /* I don't know what a non ALPHA ELF bfd would be
404433965Sjdp		     doing with a .mdebug section, but I don't really
404533965Sjdp		     want to deal with it.  */
404633965Sjdp		  continue;
404733965Sjdp		}
404833965Sjdp
404933965Sjdp	      input_swap = (get_elf_backend_data (input_bfd)
405033965Sjdp			    ->elf_backend_ecoff_debug_swap);
405133965Sjdp
405233965Sjdp	      BFD_ASSERT (p->size == input_section->_raw_size);
405333965Sjdp
405433965Sjdp	      /* The ECOFF linking code expects that we have already
405533965Sjdp		 read in the debugging information and set up an
405633965Sjdp		 ecoff_debug_info structure, so we do that now.  */
405733965Sjdp	      if (!elf64_alpha_read_ecoff_info (input_bfd, input_section,
405833965Sjdp						&input_debug))
405933965Sjdp		return false;
406033965Sjdp
406133965Sjdp	      if (! (bfd_ecoff_debug_accumulate
406233965Sjdp		     (mdebug_handle, abfd, &debug, swap, input_bfd,
406333965Sjdp		      &input_debug, input_swap, info)))
406433965Sjdp		return false;
406533965Sjdp
406633965Sjdp	      /* Loop through the external symbols.  For each one with
406733965Sjdp		 interesting information, try to find the symbol in
406833965Sjdp		 the linker global hash table and save the information
406933965Sjdp		 for the output external symbols.  */
407033965Sjdp	      eraw_src = input_debug.external_ext;
407133965Sjdp	      eraw_end = (eraw_src
407233965Sjdp			  + (input_debug.symbolic_header.iextMax
407333965Sjdp			     * input_swap->external_ext_size));
407433965Sjdp	      for (;
407533965Sjdp		   eraw_src < eraw_end;
407633965Sjdp		   eraw_src += input_swap->external_ext_size)
407733965Sjdp		{
407833965Sjdp		  EXTR ext;
407933965Sjdp		  const char *name;
408033965Sjdp		  struct alpha_elf_link_hash_entry *h;
408133965Sjdp
408233965Sjdp		  (*input_swap->swap_ext_in) (input_bfd, (PTR) eraw_src, &ext);
408333965Sjdp		  if (ext.asym.sc == scNil
408433965Sjdp		      || ext.asym.sc == scUndefined
408533965Sjdp		      || ext.asym.sc == scSUndefined)
408633965Sjdp		    continue;
408733965Sjdp
408833965Sjdp		  name = input_debug.ssext + ext.asym.iss;
408933965Sjdp		  h = alpha_elf_link_hash_lookup (alpha_elf_hash_table (info),
409033965Sjdp						  name, false, false, true);
409133965Sjdp		  if (h == NULL || h->esym.ifd != -2)
409233965Sjdp		    continue;
409333965Sjdp
409433965Sjdp		  if (ext.ifd != -1)
409533965Sjdp		    {
409633965Sjdp		      BFD_ASSERT (ext.ifd
409733965Sjdp				  < input_debug.symbolic_header.ifdMax);
409833965Sjdp		      ext.ifd = input_debug.ifdmap[ext.ifd];
409933965Sjdp		    }
410033965Sjdp
410133965Sjdp		  h->esym = ext;
410233965Sjdp		}
410333965Sjdp
410433965Sjdp	      /* Free up the information we just read.  */
410533965Sjdp	      free (input_debug.line);
410633965Sjdp	      free (input_debug.external_dnr);
410733965Sjdp	      free (input_debug.external_pdr);
410833965Sjdp	      free (input_debug.external_sym);
410933965Sjdp	      free (input_debug.external_opt);
411033965Sjdp	      free (input_debug.external_aux);
411133965Sjdp	      free (input_debug.ss);
411233965Sjdp	      free (input_debug.ssext);
411333965Sjdp	      free (input_debug.external_fdr);
411433965Sjdp	      free (input_debug.external_rfd);
411533965Sjdp	      free (input_debug.external_ext);
411633965Sjdp
411733965Sjdp	      /* Hack: reset the SEC_HAS_CONTENTS flag so that
411833965Sjdp		 elf_link_input_bfd ignores this section.  */
411933965Sjdp	      input_section->flags &=~ SEC_HAS_CONTENTS;
412033965Sjdp	    }
412133965Sjdp
412233965Sjdp	  /* Build the external symbol information.  */
412333965Sjdp	  einfo.abfd = abfd;
412433965Sjdp	  einfo.info = info;
412533965Sjdp	  einfo.debug = &debug;
412633965Sjdp	  einfo.swap = swap;
412733965Sjdp	  einfo.failed = false;
412833965Sjdp	  elf_link_hash_traverse (elf_hash_table (info),
412933965Sjdp				  elf64_alpha_output_extsym,
413033965Sjdp				  (PTR) &einfo);
413133965Sjdp	  if (einfo.failed)
413233965Sjdp	    return false;
413333965Sjdp
413433965Sjdp	  /* Set the size of the .mdebug section.  */
413533965Sjdp	  o->_raw_size = bfd_ecoff_debug_size (abfd, &debug, swap);
413633965Sjdp
413733965Sjdp	  /* Skip this section later on (I don't think this currently
413833965Sjdp	     matters, but someday it might).  */
413933965Sjdp	  o->link_order_head = (struct bfd_link_order *) NULL;
414033965Sjdp
414133965Sjdp	  mdebug_sec = o;
414233965Sjdp	}
414333965Sjdp    }
414433965Sjdp
414533965Sjdp  /* Invoke the regular ELF backend linker to do all the work.  */
414633965Sjdp  if (! bfd_elf64_bfd_final_link (abfd, info))
414733965Sjdp    return false;
414833965Sjdp
414933965Sjdp  /* Now write out the computed sections.  */
415033965Sjdp
415133965Sjdp  /* The .got subsections...  */
415233965Sjdp  {
415333965Sjdp    bfd *i, *dynobj = elf_hash_table(info)->dynobj;
415433965Sjdp    for (i = alpha_elf_hash_table(info)->got_list;
415533965Sjdp	 i != NULL;
415633965Sjdp	 i = alpha_elf_tdata(i)->got_link_next)
415733965Sjdp      {
415833965Sjdp	asection *sgot;
415933965Sjdp
416033965Sjdp	/* elf_bfd_final_link already did everything in dynobj.  */
416133965Sjdp	if (i == dynobj)
416233965Sjdp	  continue;
416333965Sjdp
416433965Sjdp	sgot = alpha_elf_tdata(i)->got;
416533965Sjdp	if (! bfd_set_section_contents (abfd, sgot->output_section,
416689862Sobrien					sgot->contents,
416789862Sobrien					(file_ptr) sgot->output_offset,
416833965Sjdp					sgot->_raw_size))
416933965Sjdp	  return false;
417033965Sjdp      }
417133965Sjdp  }
417233965Sjdp
417333965Sjdp  if (mdebug_sec != (asection *) NULL)
417433965Sjdp    {
417533965Sjdp      BFD_ASSERT (abfd->output_has_begun);
417633965Sjdp      if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug,
417733965Sjdp					       swap, info,
417833965Sjdp					       mdebug_sec->filepos))
417933965Sjdp	return false;
418033965Sjdp
418133965Sjdp      bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info);
418233965Sjdp    }
418333965Sjdp
418489862Sobrien  return true;
418589862Sobrien}
418633965Sjdp
418789862Sobrienstatic enum elf_reloc_type_class
418889862Sobrienelf64_alpha_reloc_type_class (rela)
418989862Sobrien     const Elf_Internal_Rela *rela;
419089862Sobrien{
419189862Sobrien  switch ((int) ELF64_R_TYPE (rela->r_info))
419233965Sjdp    {
419389862Sobrien    case R_ALPHA_RELATIVE:
419489862Sobrien      return reloc_class_relative;
419589862Sobrien    case R_ALPHA_JMP_SLOT:
419689862Sobrien      return reloc_class_plt;
419789862Sobrien    case R_ALPHA_COPY:
419889862Sobrien      return reloc_class_copy;
419989862Sobrien    default:
420089862Sobrien      return reloc_class_normal;
420133965Sjdp    }
420233965Sjdp}
420333965Sjdp
420433965Sjdp/* ECOFF swapping routines.  These are used when dealing with the
420533965Sjdp   .mdebug section, which is in the ECOFF debugging format.  Copied
420677303Sobrien   from elf32-mips.c.  */
420733965Sjdpstatic const struct ecoff_debug_swap
420833965Sjdpelf64_alpha_ecoff_debug_swap =
420933965Sjdp{
421033965Sjdp  /* Symbol table magic number.  */
421133965Sjdp  magicSym2,
421233965Sjdp  /* Alignment of debugging information.  E.g., 4.  */
421333965Sjdp  8,
421433965Sjdp  /* Sizes of external symbolic information.  */
421533965Sjdp  sizeof (struct hdr_ext),
421633965Sjdp  sizeof (struct dnr_ext),
421733965Sjdp  sizeof (struct pdr_ext),
421833965Sjdp  sizeof (struct sym_ext),
421933965Sjdp  sizeof (struct opt_ext),
422033965Sjdp  sizeof (struct fdr_ext),
422133965Sjdp  sizeof (struct rfd_ext),
422233965Sjdp  sizeof (struct ext_ext),
422333965Sjdp  /* Functions to swap in external symbolic data.  */
422433965Sjdp  ecoff_swap_hdr_in,
422533965Sjdp  ecoff_swap_dnr_in,
422633965Sjdp  ecoff_swap_pdr_in,
422733965Sjdp  ecoff_swap_sym_in,
422833965Sjdp  ecoff_swap_opt_in,
422933965Sjdp  ecoff_swap_fdr_in,
423033965Sjdp  ecoff_swap_rfd_in,
423133965Sjdp  ecoff_swap_ext_in,
423233965Sjdp  _bfd_ecoff_swap_tir_in,
423333965Sjdp  _bfd_ecoff_swap_rndx_in,
423433965Sjdp  /* Functions to swap out external symbolic data.  */
423533965Sjdp  ecoff_swap_hdr_out,
423633965Sjdp  ecoff_swap_dnr_out,
423733965Sjdp  ecoff_swap_pdr_out,
423833965Sjdp  ecoff_swap_sym_out,
423933965Sjdp  ecoff_swap_opt_out,
424033965Sjdp  ecoff_swap_fdr_out,
424133965Sjdp  ecoff_swap_rfd_out,
424233965Sjdp  ecoff_swap_ext_out,
424333965Sjdp  _bfd_ecoff_swap_tir_out,
424433965Sjdp  _bfd_ecoff_swap_rndx_out,
424533965Sjdp  /* Function to read in symbolic data.  */
424633965Sjdp  elf64_alpha_read_ecoff_info
424733965Sjdp};
424833965Sjdp
424977303Sobrien/* Use a non-standard hash bucket size of 8.  */
425077303Sobrien
425177303Sobrienconst struct elf_size_info alpha_elf_size_info =
425277303Sobrien{
425377303Sobrien  sizeof (Elf64_External_Ehdr),
425477303Sobrien  sizeof (Elf64_External_Phdr),
425577303Sobrien  sizeof (Elf64_External_Shdr),
425677303Sobrien  sizeof (Elf64_External_Rel),
425777303Sobrien  sizeof (Elf64_External_Rela),
425877303Sobrien  sizeof (Elf64_External_Sym),
425977303Sobrien  sizeof (Elf64_External_Dyn),
426077303Sobrien  sizeof (Elf_External_Note),
426177303Sobrien  8,
426277303Sobrien  1,
426377303Sobrien  64, 8,
426477303Sobrien  ELFCLASS64, EV_CURRENT,
426577303Sobrien  bfd_elf64_write_out_phdrs,
426677303Sobrien  bfd_elf64_write_shdrs_and_ehdr,
426777303Sobrien  bfd_elf64_write_relocs,
426877303Sobrien  bfd_elf64_swap_symbol_out,
426977303Sobrien  bfd_elf64_slurp_reloc_table,
427077303Sobrien  bfd_elf64_slurp_symbol_table,
427177303Sobrien  bfd_elf64_swap_dyn_in,
427277303Sobrien  bfd_elf64_swap_dyn_out,
427377303Sobrien  NULL,
427477303Sobrien  NULL,
427577303Sobrien  NULL,
427677303Sobrien  NULL
427777303Sobrien};
427877303Sobrien
427933965Sjdp#define TARGET_LITTLE_SYM	bfd_elf64_alpha_vec
428033965Sjdp#define TARGET_LITTLE_NAME	"elf64-alpha"
428133965Sjdp#define ELF_ARCH		bfd_arch_alpha
428278833Sobrien#define ELF_MACHINE_CODE	EM_ALPHA
428378833Sobrien#define ELF_MAXPAGESIZE	0x10000
428433965Sjdp
428533965Sjdp#define bfd_elf64_bfd_link_hash_table_create \
428633965Sjdp  elf64_alpha_bfd_link_hash_table_create
428733965Sjdp
428833965Sjdp#define bfd_elf64_bfd_reloc_type_lookup \
428933965Sjdp  elf64_alpha_bfd_reloc_type_lookup
429033965Sjdp#define elf_info_to_howto \
429133965Sjdp  elf64_alpha_info_to_howto
429233965Sjdp
429333965Sjdp#define bfd_elf64_mkobject \
429433965Sjdp  elf64_alpha_mkobject
429533965Sjdp#define elf_backend_object_p \
429633965Sjdp  elf64_alpha_object_p
429733965Sjdp
429833965Sjdp#define elf_backend_section_from_shdr \
429933965Sjdp  elf64_alpha_section_from_shdr
430089862Sobrien#define elf_backend_section_flags \
430189862Sobrien  elf64_alpha_section_flags
430233965Sjdp#define elf_backend_fake_sections \
430333965Sjdp  elf64_alpha_fake_sections
430433965Sjdp
430533965Sjdp#define bfd_elf64_bfd_is_local_label_name \
430633965Sjdp  elf64_alpha_is_local_label_name
430733965Sjdp#define bfd_elf64_find_nearest_line \
430833965Sjdp  elf64_alpha_find_nearest_line
430960510Sobrien#define bfd_elf64_bfd_relax_section \
431060510Sobrien  elf64_alpha_relax_section
431133965Sjdp
431260510Sobrien#define elf_backend_add_symbol_hook \
431360510Sobrien  elf64_alpha_add_symbol_hook
431433965Sjdp#define elf_backend_check_relocs \
431533965Sjdp  elf64_alpha_check_relocs
431633965Sjdp#define elf_backend_create_dynamic_sections \
431733965Sjdp  elf64_alpha_create_dynamic_sections
431833965Sjdp#define elf_backend_adjust_dynamic_symbol \
431933965Sjdp  elf64_alpha_adjust_dynamic_symbol
432033965Sjdp#define elf_backend_always_size_sections \
432133965Sjdp  elf64_alpha_always_size_sections
432233965Sjdp#define elf_backend_size_dynamic_sections \
432333965Sjdp  elf64_alpha_size_dynamic_sections
432433965Sjdp#define elf_backend_relocate_section \
432533965Sjdp  elf64_alpha_relocate_section
432633965Sjdp#define elf_backend_finish_dynamic_symbol \
432733965Sjdp  elf64_alpha_finish_dynamic_symbol
432833965Sjdp#define elf_backend_finish_dynamic_sections \
432933965Sjdp  elf64_alpha_finish_dynamic_sections
433033965Sjdp#define bfd_elf64_bfd_final_link \
433133965Sjdp  elf64_alpha_final_link
433289862Sobrien#define elf_backend_reloc_type_class \
433389862Sobrien  elf64_alpha_reloc_type_class
433433965Sjdp
433533965Sjdp#define elf_backend_ecoff_debug_swap \
433633965Sjdp  &elf64_alpha_ecoff_debug_swap
433733965Sjdp
433877303Sobrien#define elf_backend_size_info \
433977303Sobrien  alpha_elf_size_info
434077303Sobrien
434177303Sobrien/* A few constants that determine how the .plt section is set up.  */
434233965Sjdp#define elf_backend_want_got_plt 0
434333965Sjdp#define elf_backend_plt_readonly 0
434433965Sjdp#define elf_backend_want_plt_sym 1
434560510Sobrien#define elf_backend_got_header_size 0
434660510Sobrien#define elf_backend_plt_header_size PLT_HEADER_SIZE
434733965Sjdp
434833965Sjdp#include "elf64-target.h"
4349