elf64-alpha.c revision 91049
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 91049 2002-02-22 04:46:20Z 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,
73791049Sobrien	 true),
73891049Sobrien
73991049Sobrien  /* A 21 bit branch that adjusts for gp loads.  */
74091049Sobrien  HOWTO (R_ALPHA_BRSGP,		/* type */
74191049Sobrien	 2,			/* rightshift */
74291049Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
74391049Sobrien	 21,			/* bitsize */
74491049Sobrien	 true,			/* pc_relative */
74591049Sobrien	 0,			/* bitpos */
74691049Sobrien	 complain_overflow_signed, /* complain_on_overflow */
74791049Sobrien	 0,			/* special_function */
74891049Sobrien	 "BRSGP",		/* name */
74991049Sobrien	 false,			/* partial_inplace */
75091049Sobrien	 0x1fffff,		/* src_mask */
75191049Sobrien	 0x1fffff,		/* dst_mask */
75291049Sobrien	 true),			/* pcrel_offset */
75333965Sjdp};
75433965Sjdp
75533965Sjdp/* A relocation function which doesn't do anything.  */
75633965Sjdp
75733965Sjdpstatic bfd_reloc_status_type
75833965Sjdpelf64_alpha_reloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message)
75978833Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
76033965Sjdp     arelent *reloc;
76178833Sobrien     asymbol *sym ATTRIBUTE_UNUSED;
76278833Sobrien     PTR data ATTRIBUTE_UNUSED;
76333965Sjdp     asection *sec;
76433965Sjdp     bfd *output_bfd;
76578833Sobrien     char **error_message ATTRIBUTE_UNUSED;
76633965Sjdp{
76733965Sjdp  if (output_bfd)
76833965Sjdp    reloc->address += sec->output_offset;
76933965Sjdp  return bfd_reloc_ok;
77033965Sjdp}
77133965Sjdp
77233965Sjdp/* A relocation function used for an unsupported reloc.  */
77333965Sjdp
77433965Sjdpstatic bfd_reloc_status_type
77533965Sjdpelf64_alpha_reloc_bad (abfd, reloc, sym, data, sec, output_bfd, error_message)
77678833Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
77733965Sjdp     arelent *reloc;
77878833Sobrien     asymbol *sym ATTRIBUTE_UNUSED;
77978833Sobrien     PTR data ATTRIBUTE_UNUSED;
78033965Sjdp     asection *sec;
78133965Sjdp     bfd *output_bfd;
78278833Sobrien     char **error_message ATTRIBUTE_UNUSED;
78333965Sjdp{
78433965Sjdp  if (output_bfd)
78533965Sjdp    reloc->address += sec->output_offset;
78633965Sjdp  return bfd_reloc_notsupported;
78733965Sjdp}
78833965Sjdp
78933965Sjdp/* Do the work of the GPDISP relocation.  */
79033965Sjdp
79133965Sjdpstatic bfd_reloc_status_type
79233965Sjdpelf64_alpha_do_reloc_gpdisp (abfd, gpdisp, p_ldah, p_lda)
79333965Sjdp     bfd *abfd;
79433965Sjdp     bfd_vma gpdisp;
79533965Sjdp     bfd_byte *p_ldah;
79633965Sjdp     bfd_byte *p_lda;
79733965Sjdp{
79833965Sjdp  bfd_reloc_status_type ret = bfd_reloc_ok;
79933965Sjdp  bfd_vma addend;
80033965Sjdp  unsigned long i_ldah, i_lda;
80133965Sjdp
80233965Sjdp  i_ldah = bfd_get_32 (abfd, p_ldah);
80333965Sjdp  i_lda = bfd_get_32 (abfd, p_lda);
80433965Sjdp
80533965Sjdp  /* Complain if the instructions are not correct.  */
80633965Sjdp  if (((i_ldah >> 26) & 0x3f) != 0x09
80733965Sjdp      || ((i_lda >> 26) & 0x3f) != 0x08)
80833965Sjdp    ret = bfd_reloc_dangerous;
80933965Sjdp
81033965Sjdp  /* Extract the user-supplied offset, mirroring the sign extensions
81133965Sjdp     that the instructions perform.  */
81233965Sjdp  addend = ((i_ldah & 0xffff) << 16) | (i_lda & 0xffff);
81333965Sjdp  addend = (addend ^ 0x80008000) - 0x80008000;
81433965Sjdp
81533965Sjdp  gpdisp += addend;
81633965Sjdp
81748850Sdfr  if ((bfd_signed_vma) gpdisp < -(bfd_signed_vma) 0x80000000
81848850Sdfr      || (bfd_signed_vma) gpdisp >= (bfd_signed_vma) 0x7fff8000)
81933965Sjdp    ret = bfd_reloc_overflow;
82033965Sjdp
82133965Sjdp  /* compensate for the sign extension again.  */
82233965Sjdp  i_ldah = ((i_ldah & 0xffff0000)
82333965Sjdp	    | (((gpdisp >> 16) + ((gpdisp >> 15) & 1)) & 0xffff));
82433965Sjdp  i_lda = (i_lda & 0xffff0000) | (gpdisp & 0xffff);
82533965Sjdp
82689862Sobrien  bfd_put_32 (abfd, (bfd_vma) i_ldah, p_ldah);
82789862Sobrien  bfd_put_32 (abfd, (bfd_vma) i_lda, p_lda);
82833965Sjdp
82933965Sjdp  return ret;
83033965Sjdp}
83133965Sjdp
83233965Sjdp/* The special function for the GPDISP reloc.  */
83333965Sjdp
83433965Sjdpstatic bfd_reloc_status_type
83533965Sjdpelf64_alpha_reloc_gpdisp (abfd, reloc_entry, sym, data, input_section,
83633965Sjdp			  output_bfd, err_msg)
83733965Sjdp     bfd *abfd;
83833965Sjdp     arelent *reloc_entry;
83978833Sobrien     asymbol *sym ATTRIBUTE_UNUSED;
84033965Sjdp     PTR data;
84133965Sjdp     asection *input_section;
84233965Sjdp     bfd *output_bfd;
84333965Sjdp     char **err_msg;
84433965Sjdp{
84533965Sjdp  bfd_reloc_status_type ret;
84633965Sjdp  bfd_vma gp, relocation;
84733965Sjdp  bfd_byte *p_ldah, *p_lda;
84833965Sjdp
84933965Sjdp  /* Don't do anything if we're not doing a final link.  */
85033965Sjdp  if (output_bfd)
85133965Sjdp    {
85233965Sjdp      reloc_entry->address += input_section->output_offset;
85333965Sjdp      return bfd_reloc_ok;
85433965Sjdp    }
85533965Sjdp
85633965Sjdp  if (reloc_entry->address > input_section->_cooked_size ||
85733965Sjdp      reloc_entry->address + reloc_entry->addend > input_section->_cooked_size)
85833965Sjdp    return bfd_reloc_outofrange;
85933965Sjdp
86033965Sjdp  /* The gp used in the portion of the output object to which this
86133965Sjdp     input object belongs is cached on the input bfd.  */
86233965Sjdp  gp = _bfd_get_gp_value (abfd);
86333965Sjdp
86433965Sjdp  relocation = (input_section->output_section->vma
86533965Sjdp		+ input_section->output_offset
86633965Sjdp		+ reloc_entry->address);
86733965Sjdp
86833965Sjdp  p_ldah = (bfd_byte *) data + reloc_entry->address;
86933965Sjdp  p_lda = p_ldah + reloc_entry->addend;
87033965Sjdp
87133965Sjdp  ret = elf64_alpha_do_reloc_gpdisp (abfd, gp - relocation, p_ldah, p_lda);
87233965Sjdp
87333965Sjdp  /* Complain if the instructions are not correct.  */
87433965Sjdp  if (ret == bfd_reloc_dangerous)
87560510Sobrien    *err_msg = _("GPDISP relocation did not find ldah and lda instructions");
87633965Sjdp
87733965Sjdp  return ret;
87833965Sjdp}
87933965Sjdp
88033965Sjdp/* A mapping from BFD reloc types to Alpha ELF reloc types.  */
88133965Sjdp
88233965Sjdpstruct elf_reloc_map
88333965Sjdp{
88433965Sjdp  bfd_reloc_code_real_type bfd_reloc_val;
88533965Sjdp  int elf_reloc_val;
88633965Sjdp};
88733965Sjdp
88833965Sjdpstatic const struct elf_reloc_map elf64_alpha_reloc_map[] =
88933965Sjdp{
89089862Sobrien  {BFD_RELOC_NONE,			R_ALPHA_NONE},
89189862Sobrien  {BFD_RELOC_32,			R_ALPHA_REFLONG},
89289862Sobrien  {BFD_RELOC_64,			R_ALPHA_REFQUAD},
89389862Sobrien  {BFD_RELOC_CTOR,			R_ALPHA_REFQUAD},
89489862Sobrien  {BFD_RELOC_GPREL32,			R_ALPHA_GPREL32},
89589862Sobrien  {BFD_RELOC_ALPHA_ELF_LITERAL,		R_ALPHA_LITERAL},
89689862Sobrien  {BFD_RELOC_ALPHA_LITUSE,		R_ALPHA_LITUSE},
89789862Sobrien  {BFD_RELOC_ALPHA_GPDISP,		R_ALPHA_GPDISP},
89889862Sobrien  {BFD_RELOC_23_PCREL_S2,		R_ALPHA_BRADDR},
89989862Sobrien  {BFD_RELOC_ALPHA_HINT,		R_ALPHA_HINT},
90089862Sobrien  {BFD_RELOC_16_PCREL,			R_ALPHA_SREL16},
90189862Sobrien  {BFD_RELOC_32_PCREL,			R_ALPHA_SREL32},
90289862Sobrien  {BFD_RELOC_64_PCREL,			R_ALPHA_SREL64},
90389862Sobrien  {BFD_RELOC_ALPHA_GPREL_HI16,		R_ALPHA_GPRELHIGH},
90489862Sobrien  {BFD_RELOC_ALPHA_GPREL_LO16,		R_ALPHA_GPRELLOW},
90589862Sobrien  {BFD_RELOC_GPREL16,			R_ALPHA_GPREL16},
90691049Sobrien  {BFD_RELOC_ALPHA_BRSGP,		R_ALPHA_BRSGP},
90733965Sjdp};
90833965Sjdp
90933965Sjdp/* Given a BFD reloc type, return a HOWTO structure.  */
91033965Sjdp
91133965Sjdpstatic reloc_howto_type *
91233965Sjdpelf64_alpha_bfd_reloc_type_lookup (abfd, code)
91378833Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
91433965Sjdp     bfd_reloc_code_real_type code;
91533965Sjdp{
91633965Sjdp  const struct elf_reloc_map *i, *e;
91733965Sjdp  i = e = elf64_alpha_reloc_map;
91833965Sjdp  e += sizeof (elf64_alpha_reloc_map) / sizeof (struct elf_reloc_map);
91933965Sjdp  for (; i != e; ++i)
92033965Sjdp    {
92133965Sjdp      if (i->bfd_reloc_val == code)
92233965Sjdp	return &elf64_alpha_howto_table[i->elf_reloc_val];
92333965Sjdp    }
92433965Sjdp  return 0;
92533965Sjdp}
92633965Sjdp
92733965Sjdp/* Given an Alpha ELF reloc type, fill in an arelent structure.  */
92833965Sjdp
92933965Sjdpstatic void
93033965Sjdpelf64_alpha_info_to_howto (abfd, cache_ptr, dst)
93178833Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
93233965Sjdp     arelent *cache_ptr;
93333965Sjdp     Elf64_Internal_Rela *dst;
93433965Sjdp{
93533965Sjdp  unsigned r_type;
93633965Sjdp
93733965Sjdp  r_type = ELF64_R_TYPE(dst->r_info);
93833965Sjdp  BFD_ASSERT (r_type < (unsigned int) R_ALPHA_max);
93933965Sjdp  cache_ptr->howto = &elf64_alpha_howto_table[r_type];
94033965Sjdp}
94133965Sjdp
94277303Sobrien/* These functions do relaxation for Alpha ELF.
94360510Sobrien
94460510Sobrien   Currently I'm only handling what I can do with existing compiler
94560510Sobrien   and assembler support, which means no instructions are removed,
94660510Sobrien   though some may be nopped.  At this time GCC does not emit enough
94760510Sobrien   information to do all of the relaxing that is possible.  It will
94860510Sobrien   take some not small amount of work for that to happen.
94960510Sobrien
95060510Sobrien   There are a couple of interesting papers that I once read on this
95160510Sobrien   subject, that I cannot find references to at the moment, that
95260510Sobrien   related to Alpha in particular.  They are by David Wall, then of
95360510Sobrien   DEC WRL.  */
95460510Sobrien
95560510Sobrien#define OP_LDA		0x08
95660510Sobrien#define OP_LDAH		0x09
95760510Sobrien#define INSN_JSR	0x68004000
95860510Sobrien#define INSN_JSR_MASK	0xfc00c000
95960510Sobrien#define OP_LDQ		0x29
96060510Sobrien#define OP_BR		0x30
96160510Sobrien#define OP_BSR		0x34
96289862Sobrien#define INSN_UNOP	0x2ffe0000
96360510Sobrien
96460510Sobrienstruct alpha_relax_info
96560510Sobrien{
96660510Sobrien  bfd *abfd;
96760510Sobrien  asection *sec;
96860510Sobrien  bfd_byte *contents;
96960510Sobrien  Elf_Internal_Rela *relocs, *relend;
97060510Sobrien  struct bfd_link_info *link_info;
97160510Sobrien  boolean changed_contents;
97260510Sobrien  boolean changed_relocs;
97360510Sobrien  bfd_vma gp;
97460510Sobrien  bfd *gotobj;
97560510Sobrien  asection *tsec;
97660510Sobrien  struct alpha_elf_link_hash_entry *h;
97760510Sobrien  struct alpha_elf_got_entry *gotent;
97860510Sobrien  unsigned char other;
97960510Sobrien};
98060510Sobrien
98160510Sobrienstatic Elf_Internal_Rela * elf64_alpha_relax_with_lituse
98277303Sobrien  PARAMS((struct alpha_relax_info *info, bfd_vma symval,
98360510Sobrien          Elf_Internal_Rela *irel, Elf_Internal_Rela *irelend));
98460510Sobrien
98560510Sobrienstatic boolean elf64_alpha_relax_without_lituse
98677303Sobrien  PARAMS((struct alpha_relax_info *info, bfd_vma symval,
98760510Sobrien          Elf_Internal_Rela *irel));
98860510Sobrien
98960510Sobrienstatic bfd_vma elf64_alpha_relax_opt_call
99060510Sobrien  PARAMS((struct alpha_relax_info *info, bfd_vma symval));
99160510Sobrien
99260510Sobrienstatic boolean elf64_alpha_relax_section
99360510Sobrien  PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
99460510Sobrien	  boolean *again));
99560510Sobrien
99660510Sobrienstatic Elf_Internal_Rela *
99760510Sobrienelf64_alpha_find_reloc_at_ofs (rel, relend, offset, type)
99860510Sobrien     Elf_Internal_Rela *rel, *relend;
99960510Sobrien     bfd_vma offset;
100060510Sobrien     int type;
100160510Sobrien{
100260510Sobrien  while (rel < relend)
100360510Sobrien    {
100489862Sobrien      if (rel->r_offset == offset
100589862Sobrien	  && ELF64_R_TYPE (rel->r_info) == (unsigned int) type)
100660510Sobrien	return rel;
100760510Sobrien      ++rel;
100860510Sobrien    }
100960510Sobrien  return NULL;
101060510Sobrien}
101160510Sobrien
101260510Sobrienstatic Elf_Internal_Rela *
101360510Sobrienelf64_alpha_relax_with_lituse (info, symval, irel, irelend)
101460510Sobrien     struct alpha_relax_info *info;
101560510Sobrien     bfd_vma symval;
101660510Sobrien     Elf_Internal_Rela *irel, *irelend;
101760510Sobrien{
101860510Sobrien  Elf_Internal_Rela *urel;
101960510Sobrien  int flags, count, i;
102060510Sobrien  bfd_signed_vma disp;
102160510Sobrien  boolean fits16;
102260510Sobrien  boolean fits32;
102360510Sobrien  boolean lit_reused = false;
102460510Sobrien  boolean all_optimized = true;
102560510Sobrien  unsigned int lit_insn;
102660510Sobrien
102760510Sobrien  lit_insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset);
102860510Sobrien  if (lit_insn >> 26 != OP_LDQ)
102960510Sobrien    {
103060510Sobrien      ((*_bfd_error_handler)
103160510Sobrien       ("%s: %s+0x%lx: warning: LITERAL relocation against unexpected insn",
103289862Sobrien	bfd_archive_filename (info->abfd), info->sec->name,
103389862Sobrien	(unsigned long) irel->r_offset));
103460510Sobrien      return irel;
103560510Sobrien    }
103660510Sobrien
103760510Sobrien  /* Summarize how this particular LITERAL is used.  */
103860510Sobrien  for (urel = irel+1, flags = count = 0; urel < irelend; ++urel, ++count)
103960510Sobrien    {
104060510Sobrien      if (ELF64_R_TYPE (urel->r_info) != R_ALPHA_LITUSE)
104160510Sobrien	break;
104289862Sobrien      if (urel->r_addend <= 3)
104360510Sobrien	flags |= 1 << urel->r_addend;
104460510Sobrien    }
104560510Sobrien
104677303Sobrien  /* A little preparation for the loop...  */
104760510Sobrien  disp = symval - info->gp;
104860510Sobrien
104960510Sobrien  for (urel = irel+1, i = 0; i < count; ++i, ++urel)
105060510Sobrien    {
105160510Sobrien      unsigned int insn;
105277303Sobrien      int insn_disp;
105377303Sobrien      bfd_signed_vma xdisp;
105477303Sobrien
105560510Sobrien      insn = bfd_get_32 (info->abfd, info->contents + urel->r_offset);
105660510Sobrien
105760510Sobrien      switch (urel->r_addend)
105860510Sobrien	{
105960510Sobrien	default: /* 0 = ADDRESS FORMAT */
106060510Sobrien	  /* This type is really just a placeholder to note that all
106160510Sobrien	     uses cannot be optimized, but to still allow some.  */
106260510Sobrien	  all_optimized = false;
106360510Sobrien	  break;
106460510Sobrien
106560510Sobrien	case 1: /* MEM FORMAT */
106660510Sobrien	  /* We can always optimize 16-bit displacements.  */
106777303Sobrien
106877303Sobrien	  /* Extract the displacement from the instruction, sign-extending
106977303Sobrien	     it if necessary, then test whether it is within 16 or 32 bits
107077303Sobrien	     displacement from GP.  */
107177303Sobrien	  insn_disp = insn & 0x0000ffff;
107277303Sobrien	  if (insn_disp & 0x00008000)
107377303Sobrien	    insn_disp |= 0xffff0000;  /* Negative: sign-extend.  */
107477303Sobrien
107577303Sobrien	  xdisp = disp + insn_disp;
107677303Sobrien	  fits16 = (xdisp >= - (bfd_signed_vma) 0x00008000 && xdisp < 0x00008000);
107777303Sobrien	  fits32 = (xdisp >= - (bfd_signed_vma) 0x80000000 && xdisp < 0x7fff8000);
107877303Sobrien
107960510Sobrien	  if (fits16)
108060510Sobrien	    {
108177303Sobrien	      /* Take the op code and dest from this insn, take the base
108260510Sobrien		 register from the literal insn.  Leave the offset alone.  */
108377303Sobrien	      insn = (insn & 0xffe0ffff) | (lit_insn & 0x001f0000);
108460510Sobrien	      urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
108589862Sobrien					   R_ALPHA_GPREL16);
108660510Sobrien	      urel->r_addend = irel->r_addend;
108760510Sobrien	      info->changed_relocs = true;
108860510Sobrien
108989862Sobrien	      bfd_put_32 (info->abfd, (bfd_vma) insn,
109089862Sobrien			  info->contents + urel->r_offset);
109160510Sobrien	      info->changed_contents = true;
109260510Sobrien	    }
109360510Sobrien
109460510Sobrien	  /* If all mem+byte, we can optimize 32-bit mem displacements.  */
109560510Sobrien	  else if (fits32 && !(flags & ~6))
109660510Sobrien	    {
109777303Sobrien	      /* FIXME: sanity check that lit insn Ra is mem insn Rb.  */
109860510Sobrien
109960510Sobrien	      irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
110060510Sobrien					   R_ALPHA_GPRELHIGH);
110160510Sobrien	      lit_insn = (OP_LDAH << 26) | (lit_insn & 0x03ff0000);
110289862Sobrien	      bfd_put_32 (info->abfd, (bfd_vma) lit_insn,
110360510Sobrien			  info->contents + irel->r_offset);
110460510Sobrien	      lit_reused = true;
110560510Sobrien	      info->changed_contents = true;
110660510Sobrien
110760510Sobrien	      urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
110860510Sobrien					   R_ALPHA_GPRELLOW);
110960510Sobrien	      urel->r_addend = irel->r_addend;
111060510Sobrien	      info->changed_relocs = true;
111160510Sobrien	    }
111260510Sobrien	  else
111360510Sobrien	    all_optimized = false;
111460510Sobrien	  break;
111560510Sobrien
111660510Sobrien	case 2: /* BYTE OFFSET FORMAT */
111760510Sobrien	  /* We can always optimize byte instructions.  */
111860510Sobrien
111960510Sobrien	  /* FIXME: sanity check the insn for byte op.  Check that the
112060510Sobrien	     literal dest reg is indeed Rb in the byte insn.  */
112160510Sobrien
112289862Sobrien	  insn &= ~ (unsigned) 0x001ff000;
112389862Sobrien	  insn |= ((symval & 7) << 13) | 0x1000;
112460510Sobrien
112560510Sobrien	  urel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
112660510Sobrien	  urel->r_addend = 0;
112760510Sobrien	  info->changed_relocs = true;
112860510Sobrien
112989862Sobrien	  bfd_put_32 (info->abfd, (bfd_vma) insn,
113089862Sobrien		      info->contents + urel->r_offset);
113160510Sobrien	  info->changed_contents = true;
113260510Sobrien	  break;
113360510Sobrien
113460510Sobrien	case 3: /* CALL FORMAT */
113560510Sobrien	  {
113660510Sobrien	    /* If not zero, place to jump without needing pv.  */
113760510Sobrien	    bfd_vma optdest = elf64_alpha_relax_opt_call (info, symval);
113860510Sobrien	    bfd_vma org = (info->sec->output_section->vma
113960510Sobrien			   + info->sec->output_offset
114060510Sobrien			   + urel->r_offset + 4);
114160510Sobrien	    bfd_signed_vma odisp;
114260510Sobrien
114360510Sobrien	    odisp = (optdest ? optdest : symval) - org;
114460510Sobrien	    if (odisp >= -0x400000 && odisp < 0x400000)
114560510Sobrien	      {
114660510Sobrien		Elf_Internal_Rela *xrel;
114760510Sobrien
114877303Sobrien		/* Preserve branch prediction call stack when possible.  */
114960510Sobrien		if ((insn & INSN_JSR_MASK) == INSN_JSR)
115060510Sobrien		  insn = (OP_BSR << 26) | (insn & 0x03e00000);
115160510Sobrien		else
115260510Sobrien		  insn = (OP_BR << 26) | (insn & 0x03e00000);
115377303Sobrien
115460510Sobrien		urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
115560510Sobrien					     R_ALPHA_BRADDR);
115660510Sobrien		urel->r_addend = irel->r_addend;
115760510Sobrien
115860510Sobrien		if (optdest)
115960510Sobrien		  urel->r_addend += optdest - symval;
116060510Sobrien		else
116160510Sobrien		  all_optimized = false;
116260510Sobrien
116389862Sobrien		bfd_put_32 (info->abfd, (bfd_vma) insn,
116489862Sobrien			    info->contents + urel->r_offset);
116560510Sobrien
116660510Sobrien		/* Kill any HINT reloc that might exist for this insn.  */
116760510Sobrien		xrel = (elf64_alpha_find_reloc_at_ofs
116877303Sobrien			(info->relocs, info->relend, urel->r_offset,
116960510Sobrien			 R_ALPHA_HINT));
117060510Sobrien		if (xrel)
117160510Sobrien		  xrel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
117260510Sobrien
117360510Sobrien		info->changed_contents = true;
117460510Sobrien		info->changed_relocs = true;
117560510Sobrien	      }
117660510Sobrien	    else
117760510Sobrien	      all_optimized = false;
117860510Sobrien
117989862Sobrien	    /* Even if the target is not in range for a direct branch,
118089862Sobrien	       if we share a GP, we can eliminate the gp reload.  */
118189862Sobrien	    if (optdest)
118289862Sobrien	      {
118389862Sobrien		Elf_Internal_Rela *gpdisp
118489862Sobrien		  = (elf64_alpha_find_reloc_at_ofs
118589862Sobrien		     (irel, irelend, urel->r_offset + 4, R_ALPHA_GPDISP));
118689862Sobrien		if (gpdisp)
118789862Sobrien		  {
118889862Sobrien		    bfd_byte *p_ldah = info->contents + gpdisp->r_offset;
118989862Sobrien		    bfd_byte *p_lda = p_ldah + gpdisp->r_addend;
119089862Sobrien		    unsigned int ldah = bfd_get_32 (info->abfd, p_ldah);
119189862Sobrien		    unsigned int lda = bfd_get_32 (info->abfd, p_lda);
119260510Sobrien
119389862Sobrien		    /* Verify that the instruction is "ldah $29,0($26)".
119489862Sobrien		       Consider a function that ends in a noreturn call,
119589862Sobrien		       and that the next function begins with an ldgp,
119689862Sobrien		       and that by accident there is no padding between.
119789862Sobrien		       In that case the insn would use $27 as the base.  */
119889862Sobrien		    if (ldah == 0x27ba0000 && lda == 0x23bd0000)
119989862Sobrien		      {
120089862Sobrien			bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_ldah);
120189862Sobrien			bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_lda);
120289862Sobrien
120389862Sobrien			gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
120489862Sobrien			info->changed_contents = true;
120589862Sobrien			info->changed_relocs = true;
120689862Sobrien		      }
120789862Sobrien		  }
120889862Sobrien	      }
120960510Sobrien	  }
121060510Sobrien	  break;
121160510Sobrien	}
121260510Sobrien    }
121360510Sobrien
121460510Sobrien  /* If all cases were optimized, we can reduce the use count on this
121560510Sobrien     got entry by one, possibly eliminating it.  */
121660510Sobrien  if (all_optimized)
121760510Sobrien    {
121860510Sobrien      info->gotent->use_count -= 1;
121960510Sobrien      alpha_elf_tdata (info->gotent->gotobj)->total_got_entries -= 1;
122060510Sobrien      if (!info->h)
122160510Sobrien	alpha_elf_tdata (info->gotent->gotobj)->n_local_got_entries -= 1;
122260510Sobrien
122360510Sobrien      /* If the literal instruction is no longer needed (it may have been
122460510Sobrien	 reused.  We can eliminate it.
122560510Sobrien	 ??? For now, I don't want to deal with compacting the section,
122660510Sobrien	 so just nop it out.  */
122760510Sobrien      if (!lit_reused)
122860510Sobrien	{
122960510Sobrien	  irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
123060510Sobrien	  info->changed_relocs = true;
123160510Sobrien
123289862Sobrien	  bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP,
123389862Sobrien		      info->contents + irel->r_offset);
123460510Sobrien	  info->changed_contents = true;
123560510Sobrien	}
123660510Sobrien    }
123760510Sobrien
123860510Sobrien  return irel + count;
123960510Sobrien}
124060510Sobrien
124160510Sobrienstatic bfd_vma
124260510Sobrienelf64_alpha_relax_opt_call (info, symval)
124360510Sobrien     struct alpha_relax_info *info;
124460510Sobrien     bfd_vma symval;
124560510Sobrien{
124660510Sobrien  /* If the function has the same gp, and we can identify that the
124760510Sobrien     function does not use its function pointer, we can eliminate the
124860510Sobrien     address load.  */
124960510Sobrien
125060510Sobrien  /* If the symbol is marked NOPV, we are being told the function never
125160510Sobrien     needs its procedure value.  */
125277303Sobrien  if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_NOPV)
125360510Sobrien    return symval;
125460510Sobrien
125560510Sobrien  /* If the symbol is marked STD_GP, we are being told the function does
125677303Sobrien     a normal ldgp in the first two words.  */
125777303Sobrien  else if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_STD_GPLOAD)
125860510Sobrien    ;
125960510Sobrien
126060510Sobrien  /* Otherwise, we may be able to identify a GP load in the first two
126160510Sobrien     words, which we can then skip.  */
126277303Sobrien  else
126360510Sobrien    {
126460510Sobrien      Elf_Internal_Rela *tsec_relocs, *tsec_relend, *tsec_free, *gpdisp;
126560510Sobrien      bfd_vma ofs;
126660510Sobrien
126777303Sobrien      /* Load the relocations from the section that the target symbol is in.  */
126860510Sobrien      if (info->sec == info->tsec)
126960510Sobrien	{
127060510Sobrien	  tsec_relocs = info->relocs;
127160510Sobrien	  tsec_relend = info->relend;
127260510Sobrien	  tsec_free = NULL;
127360510Sobrien	}
127460510Sobrien      else
127560510Sobrien	{
127660510Sobrien	  tsec_relocs = (_bfd_elf64_link_read_relocs
127760510Sobrien		         (info->abfd, info->tsec, (PTR) NULL,
127860510Sobrien			 (Elf_Internal_Rela *) NULL,
127960510Sobrien			 info->link_info->keep_memory));
128060510Sobrien	  if (tsec_relocs == NULL)
128160510Sobrien	    return 0;
128260510Sobrien	  tsec_relend = tsec_relocs + info->tsec->reloc_count;
128360510Sobrien	  tsec_free = (info->link_info->keep_memory ? NULL : tsec_relocs);
128460510Sobrien	}
128560510Sobrien
128660510Sobrien      /* Recover the symbol's offset within the section.  */
128760510Sobrien      ofs = (symval - info->tsec->output_section->vma
128860510Sobrien	     - info->tsec->output_offset);
128977303Sobrien
129060510Sobrien      /* Look for a GPDISP reloc.  */
129160510Sobrien      gpdisp = (elf64_alpha_find_reloc_at_ofs
129260510Sobrien		(tsec_relocs, tsec_relend, ofs, R_ALPHA_GPDISP));
129360510Sobrien
129460510Sobrien      if (!gpdisp || gpdisp->r_addend != 4)
129560510Sobrien	{
129660510Sobrien	  if (tsec_free)
129760510Sobrien	    free (tsec_free);
129860510Sobrien	  return 0;
129960510Sobrien	}
130060510Sobrien      if (tsec_free)
130160510Sobrien        free (tsec_free);
130260510Sobrien    }
130360510Sobrien
130477303Sobrien  /* We've now determined that we can skip an initial gp load.  Verify
130560510Sobrien     that the call and the target use the same gp.   */
130660510Sobrien  if (info->link_info->hash->creator != info->tsec->owner->xvec
130760510Sobrien      || info->gotobj != alpha_elf_tdata (info->tsec->owner)->gotobj)
130860510Sobrien    return 0;
130960510Sobrien
131060510Sobrien  return symval + 8;
131160510Sobrien}
131260510Sobrien
131360510Sobrienstatic boolean
131460510Sobrienelf64_alpha_relax_without_lituse (info, symval, irel)
131560510Sobrien     struct alpha_relax_info *info;
131660510Sobrien     bfd_vma symval;
131760510Sobrien     Elf_Internal_Rela *irel;
131860510Sobrien{
131960510Sobrien  unsigned int insn;
132060510Sobrien  bfd_signed_vma disp;
132160510Sobrien
132260510Sobrien  /* Get the instruction.  */
132360510Sobrien  insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset);
132460510Sobrien
132560510Sobrien  if (insn >> 26 != OP_LDQ)
132660510Sobrien    {
132760510Sobrien      ((*_bfd_error_handler)
132860510Sobrien       ("%s: %s+0x%lx: warning: LITERAL relocation against unexpected insn",
132989862Sobrien	bfd_archive_filename (info->abfd), info->sec->name,
133060510Sobrien	(unsigned long) irel->r_offset));
133160510Sobrien      return true;
133260510Sobrien    }
133360510Sobrien
133460510Sobrien  /* So we aren't told much.  Do what we can with the address load and
133560510Sobrien     fake the rest.  All of the optimizations here require that the
133660510Sobrien     offset from the GP fit in 16 bits.  */
133760510Sobrien
133860510Sobrien  disp = symval - info->gp;
133960510Sobrien  if (disp < -0x8000 || disp >= 0x8000)
134060510Sobrien    return true;
134160510Sobrien
134260510Sobrien  /* On the LITERAL instruction itself, consider exchanging
134360510Sobrien     `ldq R,X(gp)' for `lda R,Y(gp)'.  */
134460510Sobrien
134560510Sobrien  insn = (OP_LDA << 26) | (insn & 0x03ff0000);
134689862Sobrien  bfd_put_32 (info->abfd, (bfd_vma) insn, info->contents + irel->r_offset);
134760510Sobrien  info->changed_contents = true;
134860510Sobrien
134989862Sobrien  irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), R_ALPHA_GPREL16);
135060510Sobrien  info->changed_relocs = true;
135160510Sobrien
135260510Sobrien  /* Reduce the use count on this got entry by one, possibly
135360510Sobrien     eliminating it.  */
135460510Sobrien  info->gotent->use_count -= 1;
135560510Sobrien  alpha_elf_tdata (info->gotent->gotobj)->total_got_entries -= 1;
135660510Sobrien  if (!info->h)
135760510Sobrien    alpha_elf_tdata (info->gotent->gotobj)->n_local_got_entries -= 1;
135860510Sobrien
135960510Sobrien  /* ??? Search forward through this basic block looking for insns
136060510Sobrien     that use the target register.  Stop after an insn modifying the
136160510Sobrien     register is seen, or after a branch or call.
136260510Sobrien
136360510Sobrien     Any such memory load insn may be substituted by a load directly
136460510Sobrien     off the GP.  This allows the memory load insn to be issued before
136577303Sobrien     the calculated GP register would otherwise be ready.
136660510Sobrien
136760510Sobrien     Any such jsr insn can be replaced by a bsr if it is in range.
136860510Sobrien
136960510Sobrien     This would mean that we'd have to _add_ relocations, the pain of
137060510Sobrien     which gives one pause.  */
137160510Sobrien
137260510Sobrien  return true;
137360510Sobrien}
137460510Sobrien
137560510Sobrienstatic boolean
137660510Sobrienelf64_alpha_relax_section (abfd, sec, link_info, again)
137760510Sobrien     bfd *abfd;
137860510Sobrien     asection *sec;
137960510Sobrien     struct bfd_link_info *link_info;
138060510Sobrien     boolean *again;
138160510Sobrien{
138260510Sobrien  Elf_Internal_Shdr *symtab_hdr;
138389862Sobrien  Elf_Internal_Shdr *shndx_hdr;
138460510Sobrien  Elf_Internal_Rela *internal_relocs;
138560510Sobrien  Elf_Internal_Rela *free_relocs = NULL;
138660510Sobrien  Elf_Internal_Rela *irel, *irelend;
138760510Sobrien  bfd_byte *free_contents = NULL;
138860510Sobrien  Elf64_External_Sym *extsyms = NULL;
138960510Sobrien  Elf64_External_Sym *free_extsyms = NULL;
139089862Sobrien  Elf_External_Sym_Shndx *shndx_buf = NULL;
139160510Sobrien  struct alpha_elf_got_entry **local_got_entries;
139260510Sobrien  struct alpha_relax_info info;
139360510Sobrien
139460510Sobrien  /* We are not currently changing any sizes, so only one pass.  */
139560510Sobrien  *again = false;
139660510Sobrien
139760510Sobrien  if (link_info->relocateable
139860510Sobrien      || (sec->flags & SEC_RELOC) == 0
139960510Sobrien      || sec->reloc_count == 0)
140060510Sobrien    return true;
140160510Sobrien
140260510Sobrien  /* If this is the first time we have been called for this section,
140360510Sobrien     initialize the cooked size.  */
140460510Sobrien  if (sec->_cooked_size == 0)
140560510Sobrien    sec->_cooked_size = sec->_raw_size;
140660510Sobrien
140760510Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
140860510Sobrien  local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
140960510Sobrien
141060510Sobrien  /* Load the relocations for this section.  */
141160510Sobrien  internal_relocs = (_bfd_elf64_link_read_relocs
141260510Sobrien		     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
141360510Sobrien		      link_info->keep_memory));
141460510Sobrien  if (internal_relocs == NULL)
141560510Sobrien    goto error_return;
141660510Sobrien  if (! link_info->keep_memory)
141760510Sobrien    free_relocs = internal_relocs;
141860510Sobrien
141977303Sobrien  memset(&info, 0, sizeof (info));
142060510Sobrien  info.abfd = abfd;
142160510Sobrien  info.sec = sec;
142260510Sobrien  info.link_info = link_info;
142360510Sobrien  info.relocs = internal_relocs;
142460510Sobrien  info.relend = irelend = internal_relocs + sec->reloc_count;
142560510Sobrien
142660510Sobrien  /* Find the GP for this object.  */
142760510Sobrien  info.gotobj = alpha_elf_tdata (abfd)->gotobj;
142860510Sobrien  if (info.gotobj)
142960510Sobrien    {
143060510Sobrien      asection *sgot = alpha_elf_tdata (info.gotobj)->got;
143160510Sobrien      info.gp = _bfd_get_gp_value (info.gotobj);
143260510Sobrien      if (info.gp == 0)
143360510Sobrien	{
143460510Sobrien	  info.gp = (sgot->output_section->vma
143560510Sobrien		     + sgot->output_offset
143660510Sobrien		     + 0x8000);
143760510Sobrien	  _bfd_set_gp_value (info.gotobj, info.gp);
143860510Sobrien	}
143960510Sobrien    }
144060510Sobrien
144160510Sobrien  for (irel = internal_relocs; irel < irelend; irel++)
144260510Sobrien    {
144360510Sobrien      bfd_vma symval;
144460510Sobrien      Elf_Internal_Sym isym;
144560510Sobrien      struct alpha_elf_got_entry *gotent;
144660510Sobrien
144760510Sobrien      if (ELF64_R_TYPE (irel->r_info) != (int) R_ALPHA_LITERAL)
144860510Sobrien	continue;
144960510Sobrien
145060510Sobrien      /* Get the section contents.  */
145160510Sobrien      if (info.contents == NULL)
145260510Sobrien	{
145360510Sobrien	  if (elf_section_data (sec)->this_hdr.contents != NULL)
145460510Sobrien	    info.contents = elf_section_data (sec)->this_hdr.contents;
145560510Sobrien	  else
145660510Sobrien	    {
145760510Sobrien	      info.contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
145860510Sobrien	      if (info.contents == NULL)
145960510Sobrien		goto error_return;
146060510Sobrien	      free_contents = info.contents;
146160510Sobrien
146260510Sobrien	      if (! bfd_get_section_contents (abfd, sec, info.contents,
146360510Sobrien					      (file_ptr) 0, sec->_raw_size))
146460510Sobrien		goto error_return;
146560510Sobrien	    }
146660510Sobrien	}
146760510Sobrien
146860510Sobrien      /* Read this BFD's symbols if we haven't done so already.  */
146960510Sobrien      if (extsyms == NULL)
147060510Sobrien	{
147189862Sobrien	  bfd_size_type amt;
147289862Sobrien
147360510Sobrien	  if (symtab_hdr->contents != NULL)
147460510Sobrien	    extsyms = (Elf64_External_Sym *) symtab_hdr->contents;
147560510Sobrien	  else
147660510Sobrien	    {
147789862Sobrien	      amt = symtab_hdr->sh_info;
147889862Sobrien	      amt *= sizeof (Elf64_External_Sym);
147989862Sobrien	      extsyms = (Elf64_External_Sym *) bfd_malloc (amt);
148060510Sobrien	      if (extsyms == NULL)
148160510Sobrien		goto error_return;
148260510Sobrien	      free_extsyms = extsyms;
148360510Sobrien	      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
148489862Sobrien		  || bfd_bread ((PTR) extsyms, amt, abfd) != amt)
148560510Sobrien		goto error_return;
148660510Sobrien	    }
148789862Sobrien
148889862Sobrien	  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
148989862Sobrien	  if (shndx_hdr->sh_size != 0)
149089862Sobrien	    {
149189862Sobrien	      amt = symtab_hdr->sh_info;
149289862Sobrien	      amt *= sizeof (Elf_External_Sym_Shndx);
149389862Sobrien	      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
149489862Sobrien	      if (shndx_buf == NULL)
149589862Sobrien		goto error_return;
149689862Sobrien	      if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
149789862Sobrien		  || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
149889862Sobrien		goto error_return;
149989862Sobrien	    }
150060510Sobrien	}
150160510Sobrien
150260510Sobrien      /* Get the value of the symbol referred to by the reloc.  */
150360510Sobrien      if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
150460510Sobrien	{
150560510Sobrien	  /* A local symbol.  */
150689862Sobrien	  Elf64_External_Sym *esym;
150789862Sobrien	  Elf_External_Sym_Shndx *shndx;
150889862Sobrien
150989862Sobrien	  esym = extsyms + ELF64_R_SYM (irel->r_info);
151089862Sobrien	  shndx = shndx_buf + (shndx_buf ? ELF64_R_SYM (irel->r_info) : 0);
151189862Sobrien	  bfd_elf64_swap_symbol_in (abfd, esym, shndx, &isym);
151260510Sobrien	  if (isym.st_shndx == SHN_UNDEF)
151360510Sobrien	    info.tsec = bfd_und_section_ptr;
151460510Sobrien	  else if (isym.st_shndx == SHN_ABS)
151560510Sobrien	    info.tsec = bfd_abs_section_ptr;
151660510Sobrien	  else if (isym.st_shndx == SHN_COMMON)
151760510Sobrien	    info.tsec = bfd_com_section_ptr;
151877303Sobrien	  else
151989862Sobrien	    info.tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
152060510Sobrien
152160510Sobrien	  info.h = NULL;
152260510Sobrien	  info.other = isym.st_other;
152360510Sobrien	  gotent = local_got_entries[ELF64_R_SYM(irel->r_info)];
152460510Sobrien	  symval = isym.st_value;
152560510Sobrien	}
152660510Sobrien      else
152760510Sobrien	{
152860510Sobrien	  unsigned long indx;
152960510Sobrien	  struct alpha_elf_link_hash_entry *h;
153060510Sobrien
153160510Sobrien	  indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info;
153260510Sobrien	  h = alpha_elf_sym_hashes (abfd)[indx];
153360510Sobrien	  BFD_ASSERT (h != NULL);
153460510Sobrien
153560510Sobrien	  while (h->root.root.type == bfd_link_hash_indirect
153660510Sobrien		 || h->root.root.type == bfd_link_hash_warning)
153760510Sobrien	    h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
153860510Sobrien
153960510Sobrien	  /* We can't do anthing with undefined or dynamic symbols.  */
154060510Sobrien	  if (h->root.root.type == bfd_link_hash_undefined
154160510Sobrien	      || h->root.root.type == bfd_link_hash_undefweak
154260510Sobrien	      || alpha_elf_dynamic_symbol_p (&h->root, link_info))
154360510Sobrien	    continue;
154460510Sobrien
154560510Sobrien	  info.h = h;
154660510Sobrien	  info.tsec = h->root.root.u.def.section;
154760510Sobrien	  info.other = h->root.other;
154860510Sobrien	  gotent = h->got_entries;
154960510Sobrien	  symval = h->root.root.u.def.value;
155060510Sobrien	}
155160510Sobrien
155260510Sobrien      /* Search for the got entry to be used by this relocation.  */
155360510Sobrien      while (gotent->gotobj != info.gotobj || gotent->addend != irel->r_addend)
155460510Sobrien	gotent = gotent->next;
155560510Sobrien      info.gotent = gotent;
155660510Sobrien
155760510Sobrien      symval += info.tsec->output_section->vma + info.tsec->output_offset;
155860510Sobrien      symval += irel->r_addend;
155960510Sobrien
156060510Sobrien      BFD_ASSERT(info.gotent != NULL);
156160510Sobrien
156260510Sobrien      /* If there exist LITUSE relocations immediately following, this
156360510Sobrien	 opens up all sorts of interesting optimizations, because we
156460510Sobrien	 now know every location that this address load is used.  */
156560510Sobrien
156660510Sobrien      if (irel+1 < irelend && ELF64_R_TYPE (irel[1].r_info) == R_ALPHA_LITUSE)
156760510Sobrien	{
156860510Sobrien	  irel = elf64_alpha_relax_with_lituse (&info, symval, irel, irelend);
156960510Sobrien	  if (irel == NULL)
157060510Sobrien	    goto error_return;
157160510Sobrien	}
157260510Sobrien      else
157360510Sobrien	{
157460510Sobrien	  if (!elf64_alpha_relax_without_lituse (&info, symval, irel))
157560510Sobrien	    goto error_return;
157660510Sobrien	}
157760510Sobrien    }
157860510Sobrien
157960510Sobrien  if (!elf64_alpha_size_got_sections (abfd, link_info))
158060510Sobrien    return false;
158160510Sobrien
158260510Sobrien  if (info.changed_relocs)
158360510Sobrien    {
158460510Sobrien      elf_section_data (sec)->relocs = internal_relocs;
158560510Sobrien    }
158660510Sobrien  else if (free_relocs != NULL)
158760510Sobrien    {
158860510Sobrien      free (free_relocs);
158960510Sobrien    }
159060510Sobrien
159160510Sobrien  if (info.changed_contents)
159260510Sobrien    {
159360510Sobrien      elf_section_data (sec)->this_hdr.contents = info.contents;
159460510Sobrien    }
159560510Sobrien  else if (free_contents != NULL)
159660510Sobrien    {
159760510Sobrien      if (! link_info->keep_memory)
159860510Sobrien	free (free_contents);
159960510Sobrien      else
160060510Sobrien	{
160160510Sobrien	  /* Cache the section contents for elf_link_input_bfd.  */
160260510Sobrien	  elf_section_data (sec)->this_hdr.contents = info.contents;
160360510Sobrien	}
160460510Sobrien    }
160560510Sobrien
160689862Sobrien  if (shndx_buf != NULL)
160789862Sobrien    free (shndx_buf);
160889862Sobrien
160960510Sobrien  if (free_extsyms != NULL)
161060510Sobrien    {
161160510Sobrien      if (! link_info->keep_memory)
161260510Sobrien	free (free_extsyms);
161360510Sobrien      else
161460510Sobrien	{
161560510Sobrien	  /* Cache the symbols for elf_link_input_bfd.  */
161689862Sobrien	  symtab_hdr->contents = (unsigned char *) extsyms;
161760510Sobrien	}
161860510Sobrien    }
161960510Sobrien
162060510Sobrien  *again = info.changed_contents || info.changed_relocs;
162160510Sobrien
162260510Sobrien  return true;
162360510Sobrien
162460510Sobrien error_return:
162560510Sobrien  if (free_relocs != NULL)
162660510Sobrien    free (free_relocs);
162760510Sobrien  if (free_contents != NULL)
162860510Sobrien    free (free_contents);
162989862Sobrien  if (shndx_buf != NULL)
163089862Sobrien    free (shndx_buf);
163160510Sobrien  if (free_extsyms != NULL)
163260510Sobrien    free (free_extsyms);
163360510Sobrien  return false;
163460510Sobrien}
163560510Sobrien
163633965Sjdp/* PLT/GOT Stuff */
163733965Sjdp#define PLT_HEADER_SIZE 32
163889862Sobrien#define PLT_HEADER_WORD1	(bfd_vma) 0xc3600000	/* br   $27,.+4     */
163989862Sobrien#define PLT_HEADER_WORD2	(bfd_vma) 0xa77b000c	/* ldq  $27,12($27) */
164089862Sobrien#define PLT_HEADER_WORD3	(bfd_vma) 0x47ff041f	/* nop              */
164189862Sobrien#define PLT_HEADER_WORD4	(bfd_vma) 0x6b7b0000	/* jmp  $27,($27)   */
164233965Sjdp
164333965Sjdp#define PLT_ENTRY_SIZE 12
164438889Sjdp#define PLT_ENTRY_WORD1		0xc3800000	/* br   $28, plt0   */
164538889Sjdp#define PLT_ENTRY_WORD2		0
164638889Sjdp#define PLT_ENTRY_WORD3		0
164733965Sjdp
164833965Sjdp#define MAX_GOT_ENTRIES		(64*1024 / 8)
164933965Sjdp
165068770Sobrien#ifndef ELF_DYNAMIC_INTERPRETER
165168770Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so"
165268770Sobrien#endif
165333965Sjdp
165433965Sjdp/* Handle an Alpha specific section when reading an object file.  This
165533965Sjdp   is called when elfcode.h finds a section with an unknown type.
165660510Sobrien   FIXME: We need to handle the SHF_ALPHA_GPREL flag, but I'm not sure
165733965Sjdp   how to.  */
165833965Sjdp
165933965Sjdpstatic boolean
166033965Sjdpelf64_alpha_section_from_shdr (abfd, hdr, name)
166133965Sjdp     bfd *abfd;
166233965Sjdp     Elf64_Internal_Shdr *hdr;
166333965Sjdp     char *name;
166433965Sjdp{
166533965Sjdp  asection *newsect;
166633965Sjdp
166733965Sjdp  /* There ought to be a place to keep ELF backend specific flags, but
166833965Sjdp     at the moment there isn't one.  We just keep track of the
166933965Sjdp     sections by their name, instead.  Fortunately, the ABI gives
167033965Sjdp     suggested names for all the MIPS specific sections, so we will
167133965Sjdp     probably get away with this.  */
167233965Sjdp  switch (hdr->sh_type)
167333965Sjdp    {
167433965Sjdp    case SHT_ALPHA_DEBUG:
167533965Sjdp      if (strcmp (name, ".mdebug") != 0)
167633965Sjdp	return false;
167733965Sjdp      break;
167833965Sjdp    default:
167933965Sjdp      return false;
168033965Sjdp    }
168133965Sjdp
168233965Sjdp  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
168333965Sjdp    return false;
168433965Sjdp  newsect = hdr->bfd_section;
168533965Sjdp
168633965Sjdp  if (hdr->sh_type == SHT_ALPHA_DEBUG)
168733965Sjdp    {
168833965Sjdp      if (! bfd_set_section_flags (abfd, newsect,
168933965Sjdp				   (bfd_get_section_flags (abfd, newsect)
169033965Sjdp				    | SEC_DEBUGGING)))
169133965Sjdp	return false;
169233965Sjdp    }
169333965Sjdp
169489862Sobrien  return true;
169589862Sobrien}
169633965Sjdp
169789862Sobrien/* Convert Alpha specific section flags to bfd internal section flags.  */
169833965Sjdp
169989862Sobrienstatic boolean
170089862Sobrienelf64_alpha_section_flags (flags, hdr)
170189862Sobrien     flagword *flags;
170289862Sobrien     Elf64_Internal_Shdr *hdr;
170389862Sobrien{
170489862Sobrien  if (hdr->sh_flags & SHF_ALPHA_GPREL)
170589862Sobrien    *flags |= SEC_SMALL_DATA;
170689862Sobrien
170733965Sjdp  return true;
170833965Sjdp}
170933965Sjdp
171033965Sjdp/* Set the correct type for an Alpha ELF section.  We do this by the
171133965Sjdp   section name, which is a hack, but ought to work.  */
171233965Sjdp
171333965Sjdpstatic boolean
171433965Sjdpelf64_alpha_fake_sections (abfd, hdr, sec)
171533965Sjdp     bfd *abfd;
171633965Sjdp     Elf64_Internal_Shdr *hdr;
171733965Sjdp     asection *sec;
171833965Sjdp{
171933965Sjdp  register const char *name;
172033965Sjdp
172133965Sjdp  name = bfd_get_section_name (abfd, sec);
172233965Sjdp
172333965Sjdp  if (strcmp (name, ".mdebug") == 0)
172433965Sjdp    {
172533965Sjdp      hdr->sh_type = SHT_ALPHA_DEBUG;
172633965Sjdp      /* In a shared object on Irix 5.3, the .mdebug section has an
172733965Sjdp         entsize of 0.  FIXME: Does this matter?  */
172833965Sjdp      if ((abfd->flags & DYNAMIC) != 0 )
172933965Sjdp	hdr->sh_entsize = 0;
173033965Sjdp      else
173133965Sjdp	hdr->sh_entsize = 1;
173233965Sjdp    }
173389862Sobrien  else if ((sec->flags & SEC_SMALL_DATA)
173489862Sobrien	   || strcmp (name, ".sdata") == 0
173533965Sjdp	   || strcmp (name, ".sbss") == 0
173633965Sjdp	   || strcmp (name, ".lit4") == 0
173733965Sjdp	   || strcmp (name, ".lit8") == 0)
173833965Sjdp    hdr->sh_flags |= SHF_ALPHA_GPREL;
173933965Sjdp
174033965Sjdp  return true;
174133965Sjdp}
174233965Sjdp
174360510Sobrien/* Hook called by the linker routine which adds symbols from an object
174460510Sobrien   file.  We use it to put .comm items in .sbss, and not .bss.  */
174533965Sjdp
174660510Sobrienstatic boolean
174760510Sobrienelf64_alpha_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
174833965Sjdp     bfd *abfd;
174960510Sobrien     struct bfd_link_info *info;
175060510Sobrien     const Elf_Internal_Sym *sym;
175178833Sobrien     const char **namep ATTRIBUTE_UNUSED;
175278833Sobrien     flagword *flagsp ATTRIBUTE_UNUSED;
175360510Sobrien     asection **secp;
175460510Sobrien     bfd_vma *valp;
175533965Sjdp{
175660510Sobrien  if (sym->st_shndx == SHN_COMMON
175760510Sobrien      && !info->relocateable
175889862Sobrien      && sym->st_size <= elf_gp_size (abfd))
175960510Sobrien    {
176060510Sobrien      /* Common symbols less than or equal to -G nn bytes are
176160510Sobrien	 automatically put into .sbss.  */
176233965Sjdp
176360510Sobrien      asection *scomm = bfd_get_section_by_name (abfd, ".scommon");
176433965Sjdp
176560510Sobrien      if (scomm == NULL)
176660510Sobrien	{
176760510Sobrien	  scomm = bfd_make_section (abfd, ".scommon");
176860510Sobrien	  if (scomm == NULL
176960510Sobrien	      || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC
177060510Sobrien						       | SEC_IS_COMMON
177160510Sobrien						       | SEC_LINKER_CREATED)))
177260510Sobrien	    return false;
177360510Sobrien	}
177433965Sjdp
177560510Sobrien      *secp = scomm;
177660510Sobrien      *valp = sym->st_size;
177733965Sjdp    }
177833965Sjdp
177960510Sobrien  return true;
178033965Sjdp}
178133965Sjdp
178233965Sjdp/* Create the .got section.  */
178333965Sjdp
178433965Sjdpstatic boolean
178533965Sjdpelf64_alpha_create_got_section(abfd, info)
178633965Sjdp     bfd *abfd;
178778833Sobrien     struct bfd_link_info *info ATTRIBUTE_UNUSED;
178833965Sjdp{
178933965Sjdp  asection *s;
179033965Sjdp
179133965Sjdp  if (bfd_get_section_by_name (abfd, ".got"))
179233965Sjdp    return true;
179333965Sjdp
179433965Sjdp  s = bfd_make_section (abfd, ".got");
179533965Sjdp  if (s == NULL
179633965Sjdp      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
179733965Sjdp					   | SEC_HAS_CONTENTS
179833965Sjdp					   | SEC_IN_MEMORY
179933965Sjdp					   | SEC_LINKER_CREATED))
180033965Sjdp      || !bfd_set_section_alignment (abfd, s, 3))
180133965Sjdp    return false;
180233965Sjdp
180333965Sjdp  alpha_elf_tdata (abfd)->got = s;
180433965Sjdp
180533965Sjdp  return true;
180633965Sjdp}
180733965Sjdp
180833965Sjdp/* Create all the dynamic sections.  */
180933965Sjdp
181033965Sjdpstatic boolean
181133965Sjdpelf64_alpha_create_dynamic_sections (abfd, info)
181233965Sjdp     bfd *abfd;
181333965Sjdp     struct bfd_link_info *info;
181433965Sjdp{
181533965Sjdp  asection *s;
181633965Sjdp  struct elf_link_hash_entry *h;
181733965Sjdp
181833965Sjdp  /* We need to create .plt, .rela.plt, .got, and .rela.got sections.  */
181933965Sjdp
182033965Sjdp  s = bfd_make_section (abfd, ".plt");
182133965Sjdp  if (s == NULL
182233965Sjdp      || ! bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
182333965Sjdp					    | SEC_HAS_CONTENTS
182433965Sjdp					    | SEC_IN_MEMORY
182533965Sjdp					    | SEC_LINKER_CREATED
182633965Sjdp					    | SEC_CODE))
182733965Sjdp      || ! bfd_set_section_alignment (abfd, s, 3))
182833965Sjdp    return false;
182933965Sjdp
183033965Sjdp  /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
183133965Sjdp     .plt section.  */
183233965Sjdp  h = NULL;
183333965Sjdp  if (! (_bfd_generic_link_add_one_symbol
183433965Sjdp	 (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s,
183533965Sjdp	  (bfd_vma) 0, (const char *) NULL, false,
183633965Sjdp	  get_elf_backend_data (abfd)->collect,
183733965Sjdp	  (struct bfd_link_hash_entry **) &h)))
183833965Sjdp    return false;
183933965Sjdp  h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
184033965Sjdp  h->type = STT_OBJECT;
184133965Sjdp
184233965Sjdp  if (info->shared
184333965Sjdp      && ! _bfd_elf_link_record_dynamic_symbol (info, h))
184433965Sjdp    return false;
184533965Sjdp
184633965Sjdp  s = bfd_make_section (abfd, ".rela.plt");
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  /* We may or may not have created a .got section for this object, but
185733965Sjdp     we definitely havn't done the rest of the work.  */
185833965Sjdp
185933965Sjdp  if (!elf64_alpha_create_got_section (abfd, info))
186033965Sjdp    return false;
186133965Sjdp
186233965Sjdp  s = bfd_make_section(abfd, ".rela.got");
186333965Sjdp  if (s == NULL
186433965Sjdp      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
186533965Sjdp					   | SEC_HAS_CONTENTS
186633965Sjdp					   | SEC_IN_MEMORY
186733965Sjdp					   | SEC_LINKER_CREATED
186833965Sjdp					   | SEC_READONLY))
186933965Sjdp      || !bfd_set_section_alignment (abfd, s, 3))
187033965Sjdp    return false;
187133965Sjdp
187233965Sjdp  /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the
187333965Sjdp     dynobj's .got section.  We don't do this in the linker script
187433965Sjdp     because we don't want to define the symbol if we are not creating
187533965Sjdp     a global offset table.  */
187633965Sjdp  h = NULL;
187733965Sjdp  if (!(_bfd_generic_link_add_one_symbol
187833965Sjdp	(info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL,
187933965Sjdp	 alpha_elf_tdata(abfd)->got, (bfd_vma) 0, (const char *) NULL,
188033965Sjdp	 false, get_elf_backend_data (abfd)->collect,
188133965Sjdp	 (struct bfd_link_hash_entry **) &h)))
188233965Sjdp    return false;
188333965Sjdp  h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
188433965Sjdp  h->type = STT_OBJECT;
188533965Sjdp
188633965Sjdp  if (info->shared
188733965Sjdp      && ! _bfd_elf_link_record_dynamic_symbol (info, h))
188833965Sjdp    return false;
188933965Sjdp
189033965Sjdp  elf_hash_table (info)->hgot = h;
189133965Sjdp
189233965Sjdp  return true;
189333965Sjdp}
189433965Sjdp
189533965Sjdp/* Read ECOFF debugging information from a .mdebug section into a
189633965Sjdp   ecoff_debug_info structure.  */
189733965Sjdp
189833965Sjdpstatic boolean
189933965Sjdpelf64_alpha_read_ecoff_info (abfd, section, debug)
190033965Sjdp     bfd *abfd;
190133965Sjdp     asection *section;
190233965Sjdp     struct ecoff_debug_info *debug;
190333965Sjdp{
190433965Sjdp  HDRR *symhdr;
190533965Sjdp  const struct ecoff_debug_swap *swap;
190633965Sjdp  char *ext_hdr = NULL;
190733965Sjdp
190833965Sjdp  swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
190977303Sobrien  memset (debug, 0, sizeof (*debug));
191033965Sjdp
191189862Sobrien  ext_hdr = (char *) bfd_malloc (swap->external_hdr_size);
191233965Sjdp  if (ext_hdr == NULL && swap->external_hdr_size != 0)
191333965Sjdp    goto error_return;
191433965Sjdp
191533965Sjdp  if (bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0,
191633965Sjdp				swap->external_hdr_size)
191733965Sjdp      == false)
191833965Sjdp    goto error_return;
191933965Sjdp
192033965Sjdp  symhdr = &debug->symbolic_header;
192133965Sjdp  (*swap->swap_hdr_in) (abfd, ext_hdr, symhdr);
192233965Sjdp
192333965Sjdp  /* The symbolic header contains absolute file offsets and sizes to
192433965Sjdp     read.  */
192533965Sjdp#define READ(ptr, offset, count, size, type)				\
192633965Sjdp  if (symhdr->count == 0)						\
192733965Sjdp    debug->ptr = NULL;							\
192833965Sjdp  else									\
192933965Sjdp    {									\
193089862Sobrien      bfd_size_type amt = (bfd_size_type) size * symhdr->count;		\
193189862Sobrien      debug->ptr = (type) bfd_malloc (amt);				\
193233965Sjdp      if (debug->ptr == NULL)						\
193333965Sjdp	goto error_return;						\
193433965Sjdp      if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0	\
193589862Sobrien	  || bfd_bread (debug->ptr, amt, abfd) != amt)			\
193633965Sjdp	goto error_return;						\
193733965Sjdp    }
193833965Sjdp
193933965Sjdp  READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
194033965Sjdp  READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR);
194133965Sjdp  READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR);
194233965Sjdp  READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR);
194333965Sjdp  READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR);
194433965Sjdp  READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
194533965Sjdp	union aux_ext *);
194633965Sjdp  READ (ss, cbSsOffset, issMax, sizeof (char), char *);
194733965Sjdp  READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *);
194833965Sjdp  READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR);
194933965Sjdp  READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR);
195033965Sjdp  READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, PTR);
195133965Sjdp#undef READ
195233965Sjdp
195333965Sjdp  debug->fdr = NULL;
195433965Sjdp  debug->adjust = NULL;
195533965Sjdp
195633965Sjdp  return true;
195733965Sjdp
195833965Sjdp error_return:
195933965Sjdp  if (ext_hdr != NULL)
196033965Sjdp    free (ext_hdr);
196133965Sjdp  if (debug->line != NULL)
196233965Sjdp    free (debug->line);
196333965Sjdp  if (debug->external_dnr != NULL)
196433965Sjdp    free (debug->external_dnr);
196533965Sjdp  if (debug->external_pdr != NULL)
196633965Sjdp    free (debug->external_pdr);
196733965Sjdp  if (debug->external_sym != NULL)
196833965Sjdp    free (debug->external_sym);
196933965Sjdp  if (debug->external_opt != NULL)
197033965Sjdp    free (debug->external_opt);
197133965Sjdp  if (debug->external_aux != NULL)
197233965Sjdp    free (debug->external_aux);
197333965Sjdp  if (debug->ss != NULL)
197433965Sjdp    free (debug->ss);
197533965Sjdp  if (debug->ssext != NULL)
197633965Sjdp    free (debug->ssext);
197733965Sjdp  if (debug->external_fdr != NULL)
197833965Sjdp    free (debug->external_fdr);
197933965Sjdp  if (debug->external_rfd != NULL)
198033965Sjdp    free (debug->external_rfd);
198133965Sjdp  if (debug->external_ext != NULL)
198233965Sjdp    free (debug->external_ext);
198333965Sjdp  return false;
198433965Sjdp}
198533965Sjdp
198633965Sjdp/* Alpha ELF local labels start with '$'.  */
198733965Sjdp
198833965Sjdpstatic boolean
198933965Sjdpelf64_alpha_is_local_label_name (abfd, name)
199078833Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
199133965Sjdp     const char *name;
199233965Sjdp{
199333965Sjdp  return name[0] == '$';
199433965Sjdp}
199533965Sjdp
199633965Sjdp/* Alpha ELF follows MIPS ELF in using a special find_nearest_line
199733965Sjdp   routine in order to handle the ECOFF debugging information.  We
199833965Sjdp   still call this mips_elf_find_line because of the slot
199933965Sjdp   find_line_info in elf_obj_tdata is declared that way.  */
200033965Sjdp
200133965Sjdpstruct mips_elf_find_line
200233965Sjdp{
200333965Sjdp  struct ecoff_debug_info d;
200433965Sjdp  struct ecoff_find_line i;
200533965Sjdp};
200633965Sjdp
200733965Sjdpstatic boolean
200833965Sjdpelf64_alpha_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
200933965Sjdp			       functionname_ptr, line_ptr)
201033965Sjdp     bfd *abfd;
201133965Sjdp     asection *section;
201233965Sjdp     asymbol **symbols;
201333965Sjdp     bfd_vma offset;
201433965Sjdp     const char **filename_ptr;
201533965Sjdp     const char **functionname_ptr;
201633965Sjdp     unsigned int *line_ptr;
201733965Sjdp{
201833965Sjdp  asection *msec;
201933965Sjdp
202077303Sobrien  if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
202177303Sobrien				     filename_ptr, functionname_ptr,
202277303Sobrien				     line_ptr, 0,
202377303Sobrien				     &elf_tdata (abfd)->dwarf2_find_line_info))
202477303Sobrien    return true;
202577303Sobrien
202633965Sjdp  msec = bfd_get_section_by_name (abfd, ".mdebug");
202733965Sjdp  if (msec != NULL)
202833965Sjdp    {
202933965Sjdp      flagword origflags;
203033965Sjdp      struct mips_elf_find_line *fi;
203133965Sjdp      const struct ecoff_debug_swap * const swap =
203233965Sjdp	get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
203333965Sjdp
203433965Sjdp      /* If we are called during a link, alpha_elf_final_link may have
203533965Sjdp	 cleared the SEC_HAS_CONTENTS field.  We force it back on here
203633965Sjdp	 if appropriate (which it normally will be).  */
203733965Sjdp      origflags = msec->flags;
203833965Sjdp      if (elf_section_data (msec)->this_hdr.sh_type != SHT_NOBITS)
203933965Sjdp	msec->flags |= SEC_HAS_CONTENTS;
204033965Sjdp
204133965Sjdp      fi = elf_tdata (abfd)->find_line_info;
204233965Sjdp      if (fi == NULL)
204333965Sjdp	{
204433965Sjdp	  bfd_size_type external_fdr_size;
204533965Sjdp	  char *fraw_src;
204633965Sjdp	  char *fraw_end;
204733965Sjdp	  struct fdr *fdr_ptr;
204889862Sobrien	  bfd_size_type amt = sizeof (struct mips_elf_find_line);
204933965Sjdp
205089862Sobrien	  fi = (struct mips_elf_find_line *) bfd_zalloc (abfd, amt);
205133965Sjdp	  if (fi == NULL)
205233965Sjdp	    {
205333965Sjdp	      msec->flags = origflags;
205433965Sjdp	      return false;
205533965Sjdp	    }
205633965Sjdp
205733965Sjdp	  if (!elf64_alpha_read_ecoff_info (abfd, msec, &fi->d))
205833965Sjdp	    {
205933965Sjdp	      msec->flags = origflags;
206033965Sjdp	      return false;
206133965Sjdp	    }
206233965Sjdp
206333965Sjdp	  /* Swap in the FDR information.  */
206489862Sobrien	  amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr);
206589862Sobrien	  fi->d.fdr = (struct fdr *) bfd_alloc (abfd, amt);
206633965Sjdp	  if (fi->d.fdr == NULL)
206733965Sjdp	    {
206833965Sjdp	      msec->flags = origflags;
206933965Sjdp	      return false;
207033965Sjdp	    }
207133965Sjdp	  external_fdr_size = swap->external_fdr_size;
207233965Sjdp	  fdr_ptr = fi->d.fdr;
207333965Sjdp	  fraw_src = (char *) fi->d.external_fdr;
207433965Sjdp	  fraw_end = (fraw_src
207533965Sjdp		      + fi->d.symbolic_header.ifdMax * external_fdr_size);
207633965Sjdp	  for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
207733965Sjdp	    (*swap->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr);
207833965Sjdp
207933965Sjdp	  elf_tdata (abfd)->find_line_info = fi;
208033965Sjdp
208133965Sjdp	  /* Note that we don't bother to ever free this information.
208233965Sjdp             find_nearest_line is either called all the time, as in
208333965Sjdp             objdump -l, so the information should be saved, or it is
208433965Sjdp             rarely called, as in ld error messages, so the memory
208533965Sjdp             wasted is unimportant.  Still, it would probably be a
208633965Sjdp             good idea for free_cached_info to throw it away.  */
208733965Sjdp	}
208833965Sjdp
208933965Sjdp      if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap,
209033965Sjdp				  &fi->i, filename_ptr, functionname_ptr,
209133965Sjdp				  line_ptr))
209233965Sjdp	{
209333965Sjdp	  msec->flags = origflags;
209433965Sjdp	  return true;
209533965Sjdp	}
209633965Sjdp
209733965Sjdp      msec->flags = origflags;
209833965Sjdp    }
209933965Sjdp
210033965Sjdp  /* Fall back on the generic ELF find_nearest_line routine.  */
210133965Sjdp
210233965Sjdp  return _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
210333965Sjdp				     filename_ptr, functionname_ptr,
210433965Sjdp				     line_ptr);
210533965Sjdp}
210633965Sjdp
210733965Sjdp/* Structure used to pass information to alpha_elf_output_extsym.  */
210833965Sjdp
210933965Sjdpstruct extsym_info
211033965Sjdp{
211133965Sjdp  bfd *abfd;
211233965Sjdp  struct bfd_link_info *info;
211333965Sjdp  struct ecoff_debug_info *debug;
211433965Sjdp  const struct ecoff_debug_swap *swap;
211533965Sjdp  boolean failed;
211633965Sjdp};
211733965Sjdp
211833965Sjdpstatic boolean
211933965Sjdpelf64_alpha_output_extsym (h, data)
212033965Sjdp     struct alpha_elf_link_hash_entry *h;
212133965Sjdp     PTR data;
212233965Sjdp{
212333965Sjdp  struct extsym_info *einfo = (struct extsym_info *) data;
212433965Sjdp  boolean strip;
212533965Sjdp  asection *sec, *output_section;
212633965Sjdp
212733965Sjdp  if (h->root.indx == -2)
212833965Sjdp    strip = false;
212933965Sjdp  else if (((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
213033965Sjdp           || (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
213133965Sjdp          && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
213233965Sjdp          && (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
213333965Sjdp    strip = true;
213433965Sjdp  else if (einfo->info->strip == strip_all
213533965Sjdp          || (einfo->info->strip == strip_some
213633965Sjdp              && bfd_hash_lookup (einfo->info->keep_hash,
213733965Sjdp                                  h->root.root.root.string,
213833965Sjdp                                  false, false) == NULL))
213933965Sjdp    strip = true;
214033965Sjdp  else
214133965Sjdp    strip = false;
214233965Sjdp
214333965Sjdp  if (strip)
214433965Sjdp    return true;
214533965Sjdp
214633965Sjdp  if (h->esym.ifd == -2)
214733965Sjdp    {
214833965Sjdp      h->esym.jmptbl = 0;
214933965Sjdp      h->esym.cobol_main = 0;
215033965Sjdp      h->esym.weakext = 0;
215133965Sjdp      h->esym.reserved = 0;
215233965Sjdp      h->esym.ifd = ifdNil;
215333965Sjdp      h->esym.asym.value = 0;
215433965Sjdp      h->esym.asym.st = stGlobal;
215533965Sjdp
215633965Sjdp      if (h->root.root.type != bfd_link_hash_defined
215733965Sjdp         && h->root.root.type != bfd_link_hash_defweak)
215833965Sjdp       h->esym.asym.sc = scAbs;
215933965Sjdp      else
216033965Sjdp       {
216133965Sjdp         const char *name;
216233965Sjdp
216333965Sjdp         sec = h->root.root.u.def.section;
216433965Sjdp         output_section = sec->output_section;
216533965Sjdp
216633965Sjdp         /* When making a shared library and symbol h is the one from
216733965Sjdp            the another shared library, OUTPUT_SECTION may be null.  */
216833965Sjdp         if (output_section == NULL)
216933965Sjdp           h->esym.asym.sc = scUndefined;
217033965Sjdp         else
217133965Sjdp           {
217233965Sjdp             name = bfd_section_name (output_section->owner, output_section);
217333965Sjdp
217433965Sjdp             if (strcmp (name, ".text") == 0)
217533965Sjdp               h->esym.asym.sc = scText;
217633965Sjdp             else if (strcmp (name, ".data") == 0)
217733965Sjdp               h->esym.asym.sc = scData;
217833965Sjdp             else if (strcmp (name, ".sdata") == 0)
217933965Sjdp               h->esym.asym.sc = scSData;
218033965Sjdp             else if (strcmp (name, ".rodata") == 0
218133965Sjdp                      || strcmp (name, ".rdata") == 0)
218233965Sjdp               h->esym.asym.sc = scRData;
218333965Sjdp             else if (strcmp (name, ".bss") == 0)
218433965Sjdp               h->esym.asym.sc = scBss;
218533965Sjdp             else if (strcmp (name, ".sbss") == 0)
218633965Sjdp               h->esym.asym.sc = scSBss;
218733965Sjdp             else if (strcmp (name, ".init") == 0)
218833965Sjdp               h->esym.asym.sc = scInit;
218933965Sjdp             else if (strcmp (name, ".fini") == 0)
219033965Sjdp               h->esym.asym.sc = scFini;
219133965Sjdp             else
219233965Sjdp               h->esym.asym.sc = scAbs;
219333965Sjdp           }
219433965Sjdp       }
219533965Sjdp
219633965Sjdp      h->esym.asym.reserved = 0;
219733965Sjdp      h->esym.asym.index = indexNil;
219833965Sjdp    }
219933965Sjdp
220033965Sjdp  if (h->root.root.type == bfd_link_hash_common)
220133965Sjdp    h->esym.asym.value = h->root.root.u.c.size;
220233965Sjdp  else if (h->root.root.type == bfd_link_hash_defined
220333965Sjdp	   || h->root.root.type == bfd_link_hash_defweak)
220433965Sjdp    {
220533965Sjdp      if (h->esym.asym.sc == scCommon)
220633965Sjdp       h->esym.asym.sc = scBss;
220733965Sjdp      else if (h->esym.asym.sc == scSCommon)
220833965Sjdp       h->esym.asym.sc = scSBss;
220933965Sjdp
221033965Sjdp      sec = h->root.root.u.def.section;
221133965Sjdp      output_section = sec->output_section;
221233965Sjdp      if (output_section != NULL)
221333965Sjdp       h->esym.asym.value = (h->root.root.u.def.value
221433965Sjdp                             + sec->output_offset
221533965Sjdp                             + output_section->vma);
221633965Sjdp      else
221733965Sjdp       h->esym.asym.value = 0;
221833965Sjdp    }
221933965Sjdp  else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
222033965Sjdp    {
222133965Sjdp      /* Set type and value for a symbol with a function stub.  */
222233965Sjdp      h->esym.asym.st = stProc;
222333965Sjdp      sec = bfd_get_section_by_name (einfo->abfd, ".plt");
222433965Sjdp      if (sec == NULL)
222533965Sjdp	h->esym.asym.value = 0;
222633965Sjdp      else
222733965Sjdp	{
222833965Sjdp	  output_section = sec->output_section;
222933965Sjdp	  if (output_section != NULL)
223060510Sobrien	    h->esym.asym.value = (h->root.plt.offset
223133965Sjdp				  + sec->output_offset
223233965Sjdp				  + output_section->vma);
223333965Sjdp	  else
223433965Sjdp	    h->esym.asym.value = 0;
223533965Sjdp	}
223633965Sjdp    }
223733965Sjdp
223833965Sjdp  if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap,
223933965Sjdp                                     h->root.root.root.string,
224033965Sjdp                                     &h->esym))
224133965Sjdp    {
224233965Sjdp      einfo->failed = true;
224333965Sjdp      return false;
224433965Sjdp    }
224533965Sjdp
224633965Sjdp  return true;
224733965Sjdp}
224833965Sjdp
224933965Sjdp/* FIXME:  Create a runtime procedure table from the .mdebug section.
225033965Sjdp
225133965Sjdpstatic boolean
225233965Sjdpmips_elf_create_procedure_table (handle, abfd, info, s, debug)
225333965Sjdp     PTR handle;
225433965Sjdp     bfd *abfd;
225533965Sjdp     struct bfd_link_info *info;
225633965Sjdp     asection *s;
225733965Sjdp     struct ecoff_debug_info *debug;
225833965Sjdp*/
225933965Sjdp
226033965Sjdp/* Handle dynamic relocations when doing an Alpha ELF link.  */
226133965Sjdp
226233965Sjdpstatic boolean
226333965Sjdpelf64_alpha_check_relocs (abfd, info, sec, relocs)
226433965Sjdp     bfd *abfd;
226533965Sjdp     struct bfd_link_info *info;
226633965Sjdp     asection *sec;
226733965Sjdp     const Elf_Internal_Rela *relocs;
226833965Sjdp{
226933965Sjdp  bfd *dynobj;
227033965Sjdp  asection *sreloc;
227133965Sjdp  const char *rel_sec_name;
227233965Sjdp  Elf_Internal_Shdr *symtab_hdr;
227333965Sjdp  struct alpha_elf_link_hash_entry **sym_hashes;
227433965Sjdp  struct alpha_elf_got_entry **local_got_entries;
227533965Sjdp  const Elf_Internal_Rela *rel, *relend;
227633965Sjdp  int got_created;
227789862Sobrien  bfd_size_type amt;
227833965Sjdp
227933965Sjdp  if (info->relocateable)
228033965Sjdp    return true;
228133965Sjdp
228233965Sjdp  dynobj = elf_hash_table(info)->dynobj;
228333965Sjdp  if (dynobj == NULL)
228433965Sjdp    elf_hash_table(info)->dynobj = dynobj = abfd;
228533965Sjdp
228633965Sjdp  sreloc = NULL;
228733965Sjdp  rel_sec_name = NULL;
228833965Sjdp  symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
228933965Sjdp  sym_hashes = alpha_elf_sym_hashes(abfd);
229033965Sjdp  local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
229133965Sjdp  got_created = 0;
229233965Sjdp
229333965Sjdp  relend = relocs + sec->reloc_count;
229433965Sjdp  for (rel = relocs; rel < relend; ++rel)
229533965Sjdp    {
229633965Sjdp      unsigned long r_symndx, r_type;
229733965Sjdp      struct alpha_elf_link_hash_entry *h;
229833965Sjdp
229933965Sjdp      r_symndx = ELF64_R_SYM (rel->r_info);
230033965Sjdp      if (r_symndx < symtab_hdr->sh_info)
230133965Sjdp	h = NULL;
230233965Sjdp      else
230333965Sjdp	{
230433965Sjdp	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
230538889Sjdp
230638889Sjdp	  while (h->root.root.type == bfd_link_hash_indirect
230738889Sjdp		 || h->root.root.type == bfd_link_hash_warning)
230838889Sjdp	    h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
230938889Sjdp
231033965Sjdp	  h->root.elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
231133965Sjdp	}
231233965Sjdp      r_type = ELF64_R_TYPE (rel->r_info);
231333965Sjdp
231433965Sjdp      switch (r_type)
231533965Sjdp	{
231633965Sjdp	case R_ALPHA_LITERAL:
231733965Sjdp	  {
231833965Sjdp	    struct alpha_elf_got_entry *gotent;
231933965Sjdp	    int flags = 0;
232033965Sjdp
232133965Sjdp	    if (h)
232233965Sjdp	      {
232333965Sjdp		/* Search for and possibly create a got entry.  */
232433965Sjdp		for (gotent = h->got_entries; gotent ; gotent = gotent->next)
232533965Sjdp		  if (gotent->gotobj == abfd &&
232633965Sjdp		      gotent->addend == rel->r_addend)
232733965Sjdp		    break;
232833965Sjdp
232933965Sjdp		if (!gotent)
233033965Sjdp		  {
233189862Sobrien		    amt = sizeof (struct alpha_elf_got_entry);
233233965Sjdp		    gotent = ((struct alpha_elf_got_entry *)
233389862Sobrien			      bfd_alloc (abfd, amt));
233433965Sjdp		    if (!gotent)
233533965Sjdp		      return false;
233633965Sjdp
233733965Sjdp		    gotent->gotobj = abfd;
233833965Sjdp		    gotent->addend = rel->r_addend;
233933965Sjdp		    gotent->got_offset = -1;
234033965Sjdp		    gotent->flags = 0;
234160510Sobrien		    gotent->use_count = 1;
234233965Sjdp
234333965Sjdp		    gotent->next = h->got_entries;
234433965Sjdp		    h->got_entries = gotent;
234533965Sjdp
234633965Sjdp		    alpha_elf_tdata (abfd)->total_got_entries++;
234733965Sjdp		  }
234860510Sobrien		else
234960510Sobrien		  gotent->use_count += 1;
235033965Sjdp	      }
235133965Sjdp	    else
235233965Sjdp	      {
235333965Sjdp		/* This is a local .got entry -- record for merge.  */
235433965Sjdp		if (!local_got_entries)
235533965Sjdp		  {
235689862Sobrien		    bfd_size_type size;
235789862Sobrien		    size = symtab_hdr->sh_info;
235889862Sobrien		    size *= sizeof (struct alpha_elf_got_entry *);
235933965Sjdp
236033965Sjdp		    local_got_entries = ((struct alpha_elf_got_entry **)
236133965Sjdp					 bfd_alloc (abfd, size));
236233965Sjdp		    if (!local_got_entries)
236333965Sjdp		      return false;
236433965Sjdp
236589862Sobrien		    memset (local_got_entries, 0, (size_t) size);
236633965Sjdp		    alpha_elf_tdata (abfd)->local_got_entries =
236733965Sjdp		      local_got_entries;
236833965Sjdp		  }
236933965Sjdp
237033965Sjdp		for (gotent = local_got_entries[ELF64_R_SYM(rel->r_info)];
237133965Sjdp		     gotent != NULL && gotent->addend != rel->r_addend;
237233965Sjdp		     gotent = gotent->next)
237333965Sjdp		  continue;
237433965Sjdp		if (!gotent)
237533965Sjdp		  {
237689862Sobrien		    amt = sizeof (struct alpha_elf_got_entry);
237733965Sjdp		    gotent = ((struct alpha_elf_got_entry *)
237889862Sobrien			      bfd_alloc (abfd, amt));
237933965Sjdp		    if (!gotent)
238033965Sjdp		      return false;
238133965Sjdp
238233965Sjdp		    gotent->gotobj = abfd;
238333965Sjdp		    gotent->addend = rel->r_addend;
238433965Sjdp		    gotent->got_offset = -1;
238533965Sjdp		    gotent->flags = 0;
238660510Sobrien		    gotent->use_count = 1;
238733965Sjdp
238833965Sjdp		    gotent->next = local_got_entries[ELF64_R_SYM(rel->r_info)];
238933965Sjdp		    local_got_entries[ELF64_R_SYM(rel->r_info)] = gotent;
239033965Sjdp
239133965Sjdp		    alpha_elf_tdata(abfd)->total_got_entries++;
239233965Sjdp		    alpha_elf_tdata(abfd)->n_local_got_entries++;
239333965Sjdp		  }
239460510Sobrien		else
239560510Sobrien		  gotent->use_count += 1;
239633965Sjdp	      }
239733965Sjdp
239833965Sjdp	    /* Remember how this literal is used from its LITUSEs.
239933965Sjdp	       This will be important when it comes to decide if we can
240033965Sjdp	       create a .plt entry for a function symbol.  */
240133965Sjdp	    if (rel+1 < relend
240233965Sjdp		&& ELF64_R_TYPE (rel[1].r_info) == R_ALPHA_LITUSE)
240333965Sjdp	      {
240433965Sjdp		do
240533965Sjdp		  {
240633965Sjdp		    ++rel;
240733965Sjdp		    if (rel->r_addend >= 1 && rel->r_addend <= 3)
240833965Sjdp		      flags |= 1 << rel->r_addend;
240933965Sjdp		  }
241033965Sjdp		while (rel+1 < relend &&
241133965Sjdp		       ELF64_R_TYPE (rel[1].r_info) == R_ALPHA_LITUSE);
241233965Sjdp	      }
241333965Sjdp	    else
241433965Sjdp	      {
241533965Sjdp		/* No LITUSEs -- presumably the address is not being
241633965Sjdp		   loaded for nothing.  */
241733965Sjdp		flags = ALPHA_ELF_LINK_HASH_LU_ADDR;
241833965Sjdp	      }
241933965Sjdp
242033965Sjdp	    gotent->flags |= flags;
242133965Sjdp	    if (h)
242233965Sjdp	      {
242333965Sjdp		/* Make a guess as to whether a .plt entry will be needed.  */
242433965Sjdp		if ((h->flags |= flags) == ALPHA_ELF_LINK_HASH_LU_FUNC)
242533965Sjdp		  h->root.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
242633965Sjdp		else
242733965Sjdp		  h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
242833965Sjdp	      }
242933965Sjdp	  }
243033965Sjdp	  /* FALLTHRU */
243133965Sjdp
243233965Sjdp	case R_ALPHA_GPDISP:
243389862Sobrien	case R_ALPHA_GPREL16:
243433965Sjdp	case R_ALPHA_GPREL32:
243560510Sobrien	case R_ALPHA_GPRELHIGH:
243660510Sobrien	case R_ALPHA_GPRELLOW:
243791049Sobrien	case R_ALPHA_BRSGP:
243833965Sjdp	  /* We don't actually use the .got here, but the sections must
243933965Sjdp	     be created before the linker maps input sections to output
244033965Sjdp	     sections.  */
244133965Sjdp	  if (!got_created)
244233965Sjdp	    {
244333965Sjdp	      if (!elf64_alpha_create_got_section (abfd, info))
244433965Sjdp		return false;
244533965Sjdp
244633965Sjdp	      /* Make sure the object's gotobj is set to itself so
244733965Sjdp		 that we default to every object with its own .got.
244833965Sjdp		 We'll merge .gots later once we've collected each
244933965Sjdp		 object's info.  */
245033965Sjdp	      alpha_elf_tdata(abfd)->gotobj = abfd;
245133965Sjdp
245233965Sjdp	      got_created = 1;
245333965Sjdp	    }
245433965Sjdp	  break;
245533965Sjdp
245633965Sjdp	case R_ALPHA_SREL16:
245733965Sjdp	case R_ALPHA_SREL32:
245833965Sjdp	case R_ALPHA_SREL64:
245933965Sjdp	  if (h == NULL)
246033965Sjdp	    break;
246133965Sjdp	  /* FALLTHRU */
246233965Sjdp
246333965Sjdp	case R_ALPHA_REFLONG:
246433965Sjdp	case R_ALPHA_REFQUAD:
246533965Sjdp	  if (rel_sec_name == NULL)
246633965Sjdp	    {
246733965Sjdp	      rel_sec_name = (bfd_elf_string_from_elf_section
246833965Sjdp			      (abfd, elf_elfheader(abfd)->e_shstrndx,
246933965Sjdp			       elf_section_data(sec)->rel_hdr.sh_name));
247033965Sjdp	      if (rel_sec_name == NULL)
247133965Sjdp		return false;
247233965Sjdp
247333965Sjdp	      BFD_ASSERT (strncmp (rel_sec_name, ".rela", 5) == 0
247433965Sjdp			  && strcmp (bfd_get_section_name (abfd, sec),
247533965Sjdp				     rel_sec_name+5) == 0);
247633965Sjdp	    }
247733965Sjdp
247833965Sjdp	  /* We need to create the section here now whether we eventually
247933965Sjdp	     use it or not so that it gets mapped to an output section by
248033965Sjdp	     the linker.  If not used, we'll kill it in
248133965Sjdp	     size_dynamic_sections.  */
248233965Sjdp	  if (sreloc == NULL)
248333965Sjdp	    {
248433965Sjdp	      sreloc = bfd_get_section_by_name (dynobj, rel_sec_name);
248533965Sjdp	      if (sreloc == NULL)
248633965Sjdp		{
248789862Sobrien		  flagword flags;
248889862Sobrien
248933965Sjdp		  sreloc = bfd_make_section (dynobj, rel_sec_name);
249089862Sobrien		  flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY
249189862Sobrien			   | SEC_LINKER_CREATED | SEC_READONLY);
249289862Sobrien		  if (sec->flags & SEC_ALLOC)
249389862Sobrien		    flags |= SEC_ALLOC | SEC_LOAD;
249433965Sjdp		  if (sreloc == NULL
249589862Sobrien		      || !bfd_set_section_flags (dynobj, sreloc, flags)
249633965Sjdp		      || !bfd_set_section_alignment (dynobj, sreloc, 3))
249733965Sjdp		    return false;
249833965Sjdp		}
249933965Sjdp	    }
250033965Sjdp
250133965Sjdp	  if (h)
250233965Sjdp	    {
250333965Sjdp	      /* Since we havn't seen all of the input symbols yet, we
250433965Sjdp		 don't know whether we'll actually need a dynamic relocation
250533965Sjdp		 entry for this reloc.  So make a record of it.  Once we
250633965Sjdp		 find out if this thing needs dynamic relocation we'll
250777303Sobrien		 expand the relocation sections by the appropriate amount.  */
250833965Sjdp
250933965Sjdp	      struct alpha_elf_reloc_entry *rent;
251033965Sjdp
251133965Sjdp	      for (rent = h->reloc_entries; rent; rent = rent->next)
251233965Sjdp		if (rent->rtype == r_type && rent->srel == sreloc)
251333965Sjdp		  break;
251433965Sjdp
251533965Sjdp	      if (!rent)
251633965Sjdp		{
251789862Sobrien		  amt = sizeof (struct alpha_elf_reloc_entry);
251889862Sobrien		  rent = (struct alpha_elf_reloc_entry *) bfd_alloc (abfd, amt);
251933965Sjdp		  if (!rent)
252033965Sjdp		    return false;
252133965Sjdp
252233965Sjdp		  rent->srel = sreloc;
252333965Sjdp		  rent->rtype = r_type;
252433965Sjdp		  rent->count = 1;
252589862Sobrien		  rent->reltext = ((sec->flags & (SEC_READONLY | SEC_ALLOC))
252689862Sobrien				   == (SEC_READONLY | SEC_ALLOC));
252733965Sjdp
252833965Sjdp		  rent->next = h->reloc_entries;
252933965Sjdp		  h->reloc_entries = rent;
253033965Sjdp		}
253133965Sjdp	      else
253233965Sjdp		rent->count++;
253333965Sjdp	    }
253460510Sobrien	  else if (info->shared && (sec->flags & SEC_ALLOC))
253533965Sjdp	    {
253660510Sobrien	      /* If this is a shared library, and the section is to be
253760510Sobrien		 loaded into memory, we need a RELATIVE reloc.  */
253833965Sjdp	      sreloc->_raw_size += sizeof (Elf64_External_Rela);
253989862Sobrien	      if (sec->flags & SEC_READONLY)
254089862Sobrien		info->flags |= DF_TEXTREL;
254133965Sjdp	    }
254233965Sjdp	  break;
254333965Sjdp	}
254433965Sjdp    }
254533965Sjdp
254633965Sjdp  return true;
254733965Sjdp}
254833965Sjdp
254933965Sjdp/* Adjust a symbol defined by a dynamic object and referenced by a
255033965Sjdp   regular object.  The current definition is in some section of the
255133965Sjdp   dynamic object, but we're not including those sections.  We have to
255233965Sjdp   change the definition to something the rest of the link can
255333965Sjdp   understand.  */
255433965Sjdp
255533965Sjdpstatic boolean
255633965Sjdpelf64_alpha_adjust_dynamic_symbol (info, h)
255733965Sjdp     struct bfd_link_info *info;
255833965Sjdp     struct elf_link_hash_entry *h;
255933965Sjdp{
256033965Sjdp  bfd *dynobj;
256133965Sjdp  asection *s;
256233965Sjdp  struct alpha_elf_link_hash_entry *ah;
256333965Sjdp
256433965Sjdp  dynobj = elf_hash_table(info)->dynobj;
256533965Sjdp  ah = (struct alpha_elf_link_hash_entry *)h;
256633965Sjdp
256733965Sjdp  /* Now that we've seen all of the input symbols, finalize our decision
256833965Sjdp     about whether this symbol should get a .plt entry.  */
256933965Sjdp
257089862Sobrien  if (alpha_elf_dynamic_symbol_p (h, info)
257133965Sjdp      && ((h->type == STT_FUNC
257233965Sjdp	   && !(ah->flags & ALPHA_ELF_LINK_HASH_LU_ADDR))
257333965Sjdp	  || (h->type == STT_NOTYPE
257433965Sjdp	      && ah->flags == ALPHA_ELF_LINK_HASH_LU_FUNC))
257533965Sjdp      /* Don't prevent otherwise valid programs from linking by attempting
257633965Sjdp	 to create a new .got entry somewhere.  A Correct Solution would be
257733965Sjdp	 to add a new .got section to a new object file and let it be merged
257833965Sjdp	 somewhere later.  But for now don't bother.  */
257933965Sjdp      && ah->got_entries)
258033965Sjdp    {
258133965Sjdp      h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
258233965Sjdp
258333965Sjdp      s = bfd_get_section_by_name(dynobj, ".plt");
258433965Sjdp      if (!s && !elf64_alpha_create_dynamic_sections (dynobj, info))
258533965Sjdp	return false;
258633965Sjdp
258733965Sjdp      /* The first bit of the .plt is reserved.  */
258833965Sjdp      if (s->_raw_size == 0)
258933965Sjdp	s->_raw_size = PLT_HEADER_SIZE;
259033965Sjdp
259160510Sobrien      h->plt.offset = s->_raw_size;
259233965Sjdp      s->_raw_size += PLT_ENTRY_SIZE;
259333965Sjdp
259433965Sjdp      /* If this symbol is not defined in a regular file, and we are not
259533965Sjdp	 generating a shared library, then set the symbol to the location
259633965Sjdp	 in the .plt.  This is required to make function pointers compare
259733965Sjdp	 equal between the normal executable and the shared library.  */
259848850Sdfr      if (! info->shared
259948850Sdfr	  && h->root.type != bfd_link_hash_defweak)
260033965Sjdp	{
260133965Sjdp	  h->root.u.def.section = s;
260260510Sobrien	  h->root.u.def.value = h->plt.offset;
260333965Sjdp	}
260433965Sjdp
260533965Sjdp      /* We also need a JMP_SLOT entry in the .rela.plt section.  */
260633965Sjdp      s = bfd_get_section_by_name (dynobj, ".rela.plt");
260733965Sjdp      BFD_ASSERT (s != NULL);
260833965Sjdp      s->_raw_size += sizeof (Elf64_External_Rela);
260933965Sjdp
261033965Sjdp      return true;
261133965Sjdp    }
261233965Sjdp  else
261333965Sjdp    h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
261433965Sjdp
261533965Sjdp  /* If this is a weak symbol, and there is a real definition, the
261633965Sjdp     processor independent code will have arranged for us to see the
261733965Sjdp     real definition first, and we can just use the same value.  */
261833965Sjdp  if (h->weakdef != NULL)
261933965Sjdp    {
262033965Sjdp      BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
262133965Sjdp		  || h->weakdef->root.type == bfd_link_hash_defweak);
262233965Sjdp      h->root.u.def.section = h->weakdef->root.u.def.section;
262333965Sjdp      h->root.u.def.value = h->weakdef->root.u.def.value;
262433965Sjdp      return true;
262533965Sjdp    }
262633965Sjdp
262733965Sjdp  /* This is a reference to a symbol defined by a dynamic object which
262833965Sjdp     is not a function.  The Alpha, since it uses .got entries for all
262933965Sjdp     symbols even in regular objects, does not need the hackery of a
263033965Sjdp     .dynbss section and COPY dynamic relocations.  */
263133965Sjdp
263233965Sjdp  return true;
263333965Sjdp}
263433965Sjdp
263538889Sjdp/* Symbol versioning can create new symbols, and make our old symbols
263638889Sjdp   indirect to the new ones.  Consolidate the got and reloc information
263738889Sjdp   in these situations.  */
263838889Sjdp
263938889Sjdpstatic boolean
264038889Sjdpelf64_alpha_merge_ind_symbols (hi, dummy)
264138889Sjdp     struct alpha_elf_link_hash_entry *hi;
264278833Sobrien     PTR dummy ATTRIBUTE_UNUSED;
264338889Sjdp{
264438889Sjdp  struct alpha_elf_link_hash_entry *hs;
264538889Sjdp
264638889Sjdp  if (hi->root.root.type != bfd_link_hash_indirect)
264738889Sjdp    return true;
264838889Sjdp  hs = hi;
264938889Sjdp  do {
265038889Sjdp    hs = (struct alpha_elf_link_hash_entry *)hs->root.root.u.i.link;
265138889Sjdp  } while (hs->root.root.type == bfd_link_hash_indirect);
265238889Sjdp
265338889Sjdp  /* Merge the flags.  Whee.  */
265438889Sjdp
265538889Sjdp  hs->flags |= hi->flags;
265638889Sjdp
265738889Sjdp  /* Merge the .got entries.  Cannibalize the old symbol's list in
265838889Sjdp     doing so, since we don't need it anymore.  */
265938889Sjdp
266038889Sjdp  if (hs->got_entries == NULL)
266138889Sjdp    hs->got_entries = hi->got_entries;
266238889Sjdp  else
266338889Sjdp    {
266438889Sjdp      struct alpha_elf_got_entry *gi, *gs, *gin, *gsh;
266538889Sjdp
266638889Sjdp      gsh = hs->got_entries;
266738889Sjdp      for (gi = hi->got_entries; gi ; gi = gin)
266838889Sjdp	{
266938889Sjdp	  gin = gi->next;
267038889Sjdp	  for (gs = gsh; gs ; gs = gs->next)
267160510Sobrien	    if (gi->gotobj == gs->gotobj && gi->addend == gs->addend)
267238889Sjdp	      goto got_found;
267338889Sjdp	  gi->next = hs->got_entries;
267438889Sjdp	  hs->got_entries = gi;
267538889Sjdp	got_found:;
267638889Sjdp	}
267738889Sjdp    }
267838889Sjdp  hi->got_entries = NULL;
267938889Sjdp
268038889Sjdp  /* And similar for the reloc entries.  */
268138889Sjdp
268238889Sjdp  if (hs->reloc_entries == NULL)
268338889Sjdp    hs->reloc_entries = hi->reloc_entries;
268438889Sjdp  else
268538889Sjdp    {
268638889Sjdp      struct alpha_elf_reloc_entry *ri, *rs, *rin, *rsh;
268738889Sjdp
268838889Sjdp      rsh = hs->reloc_entries;
268938889Sjdp      for (ri = hi->reloc_entries; ri ; ri = rin)
269038889Sjdp	{
269138889Sjdp	  rin = ri->next;
269238889Sjdp	  for (rs = rsh; rs ; rs = rs->next)
269338889Sjdp	    if (ri->rtype == rs->rtype)
269438889Sjdp	      {
269538889Sjdp		rs->count += ri->count;
269638889Sjdp		goto found_reloc;
269738889Sjdp	      }
269838889Sjdp	  ri->next = hs->reloc_entries;
269938889Sjdp	  hs->reloc_entries = ri;
270038889Sjdp	found_reloc:;
270138889Sjdp	}
270238889Sjdp    }
270338889Sjdp  hi->reloc_entries = NULL;
270438889Sjdp
270538889Sjdp  return true;
270638889Sjdp}
270738889Sjdp
270833965Sjdp/* Is it possible to merge two object file's .got tables?  */
270933965Sjdp
271033965Sjdpstatic boolean
271133965Sjdpelf64_alpha_can_merge_gots (a, b)
271233965Sjdp     bfd *a, *b;
271333965Sjdp{
271433965Sjdp  int total = alpha_elf_tdata (a)->total_got_entries;
271560510Sobrien  bfd *bsub;
271633965Sjdp
271733965Sjdp  /* Trivial quick fallout test.  */
271833965Sjdp  if (total + alpha_elf_tdata (b)->total_got_entries <= MAX_GOT_ENTRIES)
271933965Sjdp    return true;
272033965Sjdp
272133965Sjdp  /* By their nature, local .got entries cannot be merged.  */
272233965Sjdp  if ((total += alpha_elf_tdata (b)->n_local_got_entries) > MAX_GOT_ENTRIES)
272333965Sjdp    return false;
272433965Sjdp
272533965Sjdp  /* Failing the common trivial comparison, we must effectively
272633965Sjdp     perform the merge.  Not actually performing the merge means that
272733965Sjdp     we don't have to store undo information in case we fail.  */
272860510Sobrien  for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next)
272960510Sobrien    {
273060510Sobrien      struct alpha_elf_link_hash_entry **hashes = alpha_elf_sym_hashes (bsub);
273160510Sobrien      Elf_Internal_Shdr *symtab_hdr = &elf_tdata (bsub)->symtab_hdr;
273260510Sobrien      int i, n;
273333965Sjdp
273478833Sobrien      n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info;
273560510Sobrien      for (i = 0; i < n; ++i)
273660510Sobrien	{
273760510Sobrien	  struct alpha_elf_got_entry *ae, *be;
273860510Sobrien	  struct alpha_elf_link_hash_entry *h;
273938889Sjdp
274060510Sobrien	  h = hashes[i];
274160510Sobrien	  while (h->root.root.type == bfd_link_hash_indirect
274260510Sobrien	         || h->root.root.type == bfd_link_hash_warning)
274360510Sobrien	    h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
274438889Sjdp
274560510Sobrien	  for (be = h->got_entries; be ; be = be->next)
274660510Sobrien	    {
274760510Sobrien	      if (be->use_count == 0)
274860510Sobrien	        continue;
274960510Sobrien	      if (be->gotobj != b)
275060510Sobrien	        continue;
275133965Sjdp
275260510Sobrien	      for (ae = h->got_entries; ae ; ae = ae->next)
275360510Sobrien	        if (ae->gotobj == a && ae->addend == be->addend)
275460510Sobrien		  goto global_found;
275533965Sjdp
275660510Sobrien	      if (++total > MAX_GOT_ENTRIES)
275760510Sobrien	        return false;
275860510Sobrien	    global_found:;
275960510Sobrien	    }
276060510Sobrien	}
276160510Sobrien    }
276233965Sjdp
276333965Sjdp  return true;
276433965Sjdp}
276533965Sjdp
276633965Sjdp/* Actually merge two .got tables.  */
276733965Sjdp
276833965Sjdpstatic void
276933965Sjdpelf64_alpha_merge_gots (a, b)
277033965Sjdp     bfd *a, *b;
277133965Sjdp{
277260510Sobrien  int total = alpha_elf_tdata (a)->total_got_entries;
277360510Sobrien  bfd *bsub;
277433965Sjdp
277533965Sjdp  /* Remember local expansion.  */
277633965Sjdp  {
277760510Sobrien    int e = alpha_elf_tdata (b)->n_local_got_entries;
277833965Sjdp    total += e;
277960510Sobrien    alpha_elf_tdata (a)->n_local_got_entries += e;
278033965Sjdp  }
278133965Sjdp
278260510Sobrien  for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next)
278360510Sobrien    {
278460510Sobrien      struct alpha_elf_got_entry **local_got_entries;
278560510Sobrien      struct alpha_elf_link_hash_entry **hashes;
278660510Sobrien      Elf_Internal_Shdr *symtab_hdr;
278760510Sobrien      int i, n;
278833965Sjdp
278960510Sobrien      /* Let the local .got entries know they are part of a new subsegment.  */
279060510Sobrien      local_got_entries = alpha_elf_tdata (bsub)->local_got_entries;
279160510Sobrien      if (local_got_entries)
279260510Sobrien        {
279360510Sobrien	  n = elf_tdata (bsub)->symtab_hdr.sh_info;
279460510Sobrien	  for (i = 0; i < n; ++i)
279560510Sobrien	    {
279660510Sobrien	      struct alpha_elf_got_entry *ent;
279760510Sobrien	      for (ent = local_got_entries[i]; ent; ent = ent->next)
279860510Sobrien	        ent->gotobj = a;
279960510Sobrien	    }
280060510Sobrien        }
280133965Sjdp
280260510Sobrien      /* Merge the global .got entries.  */
280360510Sobrien      hashes = alpha_elf_sym_hashes (bsub);
280460510Sobrien      symtab_hdr = &elf_tdata (bsub)->symtab_hdr;
280533965Sjdp
280678833Sobrien      n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info;
280760510Sobrien      for (i = 0; i < n; ++i)
280860510Sobrien        {
280960510Sobrien	  struct alpha_elf_got_entry *ae, *be, **pbe, **start;
281060510Sobrien	  struct alpha_elf_link_hash_entry *h;
281138889Sjdp
281260510Sobrien	  h = hashes[i];
281360510Sobrien	  while (h->root.root.type == bfd_link_hash_indirect
281460510Sobrien	         || h->root.root.type == bfd_link_hash_warning)
281560510Sobrien	    h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
281638889Sjdp
281760510Sobrien	  start = &h->got_entries;
281860510Sobrien	  for (pbe = start, be = *start; be ; pbe = &be->next, be = be->next)
281960510Sobrien	    {
282060510Sobrien	      if (be->use_count == 0)
282160510Sobrien	        {
282233965Sjdp		  *pbe = be->next;
282360510Sobrien		  continue;
282460510Sobrien	        }
282560510Sobrien	      if (be->gotobj != b)
282660510Sobrien	        continue;
282733965Sjdp
282860510Sobrien	      for (ae = *start; ae ; ae = ae->next)
282960510Sobrien	        if (ae->gotobj == a && ae->addend == be->addend)
283060510Sobrien		  {
283160510Sobrien		    ae->flags |= be->flags;
283260510Sobrien		    ae->use_count += be->use_count;
283360510Sobrien		    *pbe = be->next;
283460510Sobrien		    goto global_found;
283560510Sobrien		  }
283660510Sobrien	      be->gotobj = a;
283760510Sobrien	      total += 1;
283860510Sobrien
283960510Sobrien	    global_found:;
284060510Sobrien	    }
284160510Sobrien        }
284260510Sobrien
284360510Sobrien      alpha_elf_tdata (bsub)->gotobj = a;
284460510Sobrien    }
284560510Sobrien  alpha_elf_tdata (a)->total_got_entries = total;
284660510Sobrien
284760510Sobrien  /* Merge the two in_got chains.  */
284860510Sobrien  {
284960510Sobrien    bfd *next;
285060510Sobrien
285160510Sobrien    bsub = a;
285260510Sobrien    while ((next = alpha_elf_tdata (bsub)->in_got_link_next) != NULL)
285360510Sobrien      bsub = next;
285460510Sobrien
285560510Sobrien    alpha_elf_tdata (bsub)->in_got_link_next = b;
285633965Sjdp  }
285733965Sjdp}
285833965Sjdp
285933965Sjdp/* Calculate the offsets for the got entries.  */
286033965Sjdp
286133965Sjdpstatic boolean
286233965Sjdpelf64_alpha_calc_got_offsets_for_symbol (h, arg)
286333965Sjdp     struct alpha_elf_link_hash_entry *h;
286489862Sobrien     PTR arg ATTRIBUTE_UNUSED;
286533965Sjdp{
286633965Sjdp  struct alpha_elf_got_entry *gotent;
286733965Sjdp
286833965Sjdp  for (gotent = h->got_entries; gotent; gotent = gotent->next)
286960510Sobrien    if (gotent->use_count > 0)
287060510Sobrien      {
287160510Sobrien	bfd_size_type *plge
287260510Sobrien	  = &alpha_elf_tdata (gotent->gotobj)->got->_raw_size;
287333965Sjdp
287460510Sobrien	gotent->got_offset = *plge;
287560510Sobrien	*plge += 8;
287660510Sobrien      }
287760510Sobrien
287833965Sjdp  return true;
287933965Sjdp}
288033965Sjdp
288133965Sjdpstatic void
288233965Sjdpelf64_alpha_calc_got_offsets (info)
288333965Sjdp     struct bfd_link_info *info;
288433965Sjdp{
288533965Sjdp  bfd *i, *got_list = alpha_elf_hash_table(info)->got_list;
288633965Sjdp
288733965Sjdp  /* First, zero out the .got sizes, as we may be recalculating the
288833965Sjdp     .got after optimizing it.  */
288933965Sjdp  for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next)
289033965Sjdp    alpha_elf_tdata(i)->got->_raw_size = 0;
289133965Sjdp
289233965Sjdp  /* Next, fill in the offsets for all the global entries.  */
289333965Sjdp  alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
289433965Sjdp				elf64_alpha_calc_got_offsets_for_symbol,
289533965Sjdp				NULL);
289633965Sjdp
289733965Sjdp  /* Finally, fill in the offsets for the local entries.  */
289833965Sjdp  for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next)
289933965Sjdp    {
290033965Sjdp      bfd_size_type got_offset = alpha_elf_tdata(i)->got->_raw_size;
290133965Sjdp      bfd *j;
290233965Sjdp
290333965Sjdp      for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next)
290433965Sjdp	{
290533965Sjdp	  struct alpha_elf_got_entry **local_got_entries, *gotent;
290633965Sjdp	  int k, n;
290733965Sjdp
290833965Sjdp	  local_got_entries = alpha_elf_tdata(j)->local_got_entries;
290933965Sjdp	  if (!local_got_entries)
291033965Sjdp	    continue;
291133965Sjdp
291233965Sjdp	  for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k)
291333965Sjdp	    for (gotent = local_got_entries[k]; gotent; gotent = gotent->next)
291460510Sobrien	      if (gotent->use_count > 0)
291560510Sobrien	        {
291660510Sobrien		  gotent->got_offset = got_offset;
291760510Sobrien		  got_offset += 8;
291860510Sobrien	        }
291933965Sjdp	}
292033965Sjdp
292133965Sjdp      alpha_elf_tdata(i)->got->_raw_size = got_offset;
292260510Sobrien      alpha_elf_tdata(i)->got->_cooked_size = got_offset;
292333965Sjdp    }
292433965Sjdp}
292533965Sjdp
292633965Sjdp/* Constructs the gots.  */
292733965Sjdp
292833965Sjdpstatic boolean
292960510Sobrienelf64_alpha_size_got_sections (output_bfd, info)
293089862Sobrien     bfd *output_bfd ATTRIBUTE_UNUSED;
293133965Sjdp     struct bfd_link_info *info;
293233965Sjdp{
293389862Sobrien  bfd *i, *got_list, *cur_got_obj = NULL;
293460510Sobrien  int something_changed = 0;
293533965Sjdp
293660510Sobrien  got_list = alpha_elf_hash_table (info)->got_list;
293733965Sjdp
293860510Sobrien  /* On the first time through, pretend we have an existing got list
293960510Sobrien     consisting of all of the input files.  */
294060510Sobrien  if (got_list == NULL)
294133965Sjdp    {
294260510Sobrien      for (i = info->input_bfds; i ; i = i->link_next)
294360510Sobrien	{
294460510Sobrien	  bfd *this_got = alpha_elf_tdata (i)->gotobj;
294560510Sobrien	  if (this_got == NULL)
294660510Sobrien	    continue;
294733965Sjdp
294860510Sobrien	  /* We are assuming no merging has yet ocurred.  */
294960510Sobrien	  BFD_ASSERT (this_got == i);
295033965Sjdp
295160510Sobrien          if (alpha_elf_tdata (this_got)->total_got_entries > MAX_GOT_ENTRIES)
295233965Sjdp	    {
295360510Sobrien	      /* Yikes! A single object file has too many entries.  */
295460510Sobrien	      (*_bfd_error_handler)
295560510Sobrien	        (_("%s: .got subsegment exceeds 64K (size %d)"),
295689862Sobrien	         bfd_archive_filename (i),
295760510Sobrien	         alpha_elf_tdata (this_got)->total_got_entries * 8);
295860510Sobrien	      return false;
295933965Sjdp	    }
296060510Sobrien
296160510Sobrien	  if (got_list == NULL)
296260510Sobrien	    got_list = this_got;
296333965Sjdp	  else
296460510Sobrien	    alpha_elf_tdata(cur_got_obj)->got_link_next = this_got;
296560510Sobrien	  cur_got_obj = this_got;
296633965Sjdp	}
296760510Sobrien
296860510Sobrien      /* Strange degenerate case of no got references.  */
296960510Sobrien      if (got_list == NULL)
297060510Sobrien	return true;
297160510Sobrien
297260510Sobrien      alpha_elf_hash_table (info)->got_list = got_list;
297360510Sobrien
297460510Sobrien      /* Force got offsets to be recalculated.  */
297560510Sobrien      something_changed = 1;
297660510Sobrien    }
297760510Sobrien
297860510Sobrien  cur_got_obj = got_list;
297960510Sobrien  i = alpha_elf_tdata(cur_got_obj)->got_link_next;
298060510Sobrien  while (i != NULL)
298160510Sobrien    {
298260510Sobrien      if (elf64_alpha_can_merge_gots (cur_got_obj, i))
298360510Sobrien	{
298460510Sobrien	  elf64_alpha_merge_gots (cur_got_obj, i);
298560510Sobrien	  i = alpha_elf_tdata(i)->got_link_next;
298660510Sobrien	  alpha_elf_tdata(cur_got_obj)->got_link_next = i;
298760510Sobrien	  something_changed = 1;
298860510Sobrien	}
298933965Sjdp      else
299033965Sjdp	{
299133965Sjdp	  cur_got_obj = i;
299260510Sobrien	  i = alpha_elf_tdata(i)->got_link_next;
299333965Sjdp	}
299433965Sjdp    }
299533965Sjdp
299660510Sobrien  /* Once the gots have been merged, fill in the got offsets for
299760510Sobrien     everything therein.  */
299860510Sobrien  if (1 || something_changed)
299960510Sobrien    elf64_alpha_calc_got_offsets (info);
300033965Sjdp
300160510Sobrien  return true;
300260510Sobrien}
300333965Sjdp
300460510Sobrienstatic boolean
300560510Sobrienelf64_alpha_always_size_sections (output_bfd, info)
300660510Sobrien     bfd *output_bfd;
300760510Sobrien     struct bfd_link_info *info;
300860510Sobrien{
300960510Sobrien  bfd *i;
301060510Sobrien
301160510Sobrien  if (info->relocateable)
301260510Sobrien    return true;
301360510Sobrien
301460510Sobrien  /* First, take care of the indirect symbols created by versioning.  */
301560510Sobrien  alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
301660510Sobrien				elf64_alpha_merge_ind_symbols,
301760510Sobrien				NULL);
301860510Sobrien
301960510Sobrien  if (!elf64_alpha_size_got_sections (output_bfd, info))
302060510Sobrien    return false;
302160510Sobrien
302233965Sjdp  /* Allocate space for all of the .got subsections.  */
302360510Sobrien  i = alpha_elf_hash_table (info)->got_list;
302460510Sobrien  for ( ; i ; i = alpha_elf_tdata(i)->got_link_next)
302533965Sjdp    {
302633965Sjdp      asection *s = alpha_elf_tdata(i)->got;
302733965Sjdp      if (s->_raw_size > 0)
302833965Sjdp	{
302933965Sjdp	  s->contents = (bfd_byte *) bfd_zalloc (i, s->_raw_size);
303033965Sjdp	  if (s->contents == NULL)
303133965Sjdp	    return false;
303233965Sjdp	}
303333965Sjdp    }
303433965Sjdp
303533965Sjdp  return true;
303633965Sjdp}
303733965Sjdp
303833965Sjdp/* Work out the sizes of the dynamic relocation entries.  */
303933965Sjdp
304033965Sjdpstatic boolean
304133965Sjdpelf64_alpha_calc_dynrel_sizes (h, info)
304233965Sjdp     struct alpha_elf_link_hash_entry *h;
304333965Sjdp     struct bfd_link_info *info;
304433965Sjdp{
304533965Sjdp  /* If the symbol was defined as a common symbol in a regular object
304633965Sjdp     file, and there was no definition in any dynamic object, then the
304733965Sjdp     linker will have allocated space for the symbol in a common
304833965Sjdp     section but the ELF_LINK_HASH_DEF_REGULAR flag will not have been
304933965Sjdp     set.  This is done for dynamic symbols in
305033965Sjdp     elf_adjust_dynamic_symbol but this is not done for non-dynamic
305133965Sjdp     symbols, somehow.  */
305233965Sjdp  if (((h->root.elf_link_hash_flags
305333965Sjdp       & (ELF_LINK_HASH_DEF_REGULAR
305433965Sjdp	  | ELF_LINK_HASH_REF_REGULAR
305533965Sjdp	  | ELF_LINK_HASH_DEF_DYNAMIC))
305633965Sjdp       == ELF_LINK_HASH_REF_REGULAR)
305733965Sjdp      && (h->root.root.type == bfd_link_hash_defined
305833965Sjdp	  || h->root.root.type == bfd_link_hash_defweak)
305933965Sjdp      && !(h->root.root.u.def.section->owner->flags & DYNAMIC))
306033965Sjdp    {
306133965Sjdp      h->root.elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
306233965Sjdp    }
306333965Sjdp
306433965Sjdp  /* If the symbol is dynamic, we'll need all the relocations in their
306560510Sobrien     natural form.  If this is a shared object, and it has been forced
306660510Sobrien     local, we'll need the same number of RELATIVE relocations.  */
306760510Sobrien
306860510Sobrien  if (alpha_elf_dynamic_symbol_p (&h->root, info) || info->shared)
306933965Sjdp    {
307033965Sjdp      struct alpha_elf_reloc_entry *relent;
307148850Sdfr      bfd *dynobj;
307248850Sdfr      struct alpha_elf_got_entry *gotent;
307348850Sdfr      bfd_size_type count;
307448850Sdfr      asection *srel;
307533965Sjdp
307633965Sjdp      for (relent = h->reloc_entries; relent; relent = relent->next)
307760510Sobrien	if (relent->rtype == R_ALPHA_REFLONG
307860510Sobrien	    || relent->rtype == R_ALPHA_REFQUAD)
307960510Sobrien	  {
308060510Sobrien	    relent->srel->_raw_size +=
308177303Sobrien	      sizeof (Elf64_External_Rela) * relent->count;
308289862Sobrien	    if (relent->reltext)
308389862Sobrien	      info->flags |= DT_TEXTREL;
308460510Sobrien	  }
308533965Sjdp
308648850Sdfr      dynobj = elf_hash_table(info)->dynobj;
308748850Sdfr      count = 0;
308848850Sdfr
308948850Sdfr      for (gotent = h->got_entries; gotent ; gotent = gotent->next)
309048850Sdfr	count++;
309148850Sdfr
309248850Sdfr      /* If we are using a .plt entry, subtract one, as the first
309348850Sdfr	 reference uses a .rela.plt entry instead.  */
309460510Sobrien      if (h->root.plt.offset != MINUS_ONE)
309548850Sdfr	count--;
309648850Sdfr
309748850Sdfr      if (count > 0)
309833965Sjdp	{
309948850Sdfr	  srel = bfd_get_section_by_name (dynobj, ".rela.got");
310048850Sdfr	  BFD_ASSERT (srel != NULL);
310148850Sdfr	  srel->_raw_size += sizeof (Elf64_External_Rela) * count;
310233965Sjdp	}
310333965Sjdp    }
310448850Sdfr
310533965Sjdp  return true;
310633965Sjdp}
310733965Sjdp
310833965Sjdp/* Set the sizes of the dynamic sections.  */
310933965Sjdp
311033965Sjdpstatic boolean
311133965Sjdpelf64_alpha_size_dynamic_sections (output_bfd, info)
311289862Sobrien     bfd *output_bfd ATTRIBUTE_UNUSED;
311333965Sjdp     struct bfd_link_info *info;
311433965Sjdp{
311533965Sjdp  bfd *dynobj;
311633965Sjdp  asection *s;
311733965Sjdp  boolean relplt;
311833965Sjdp
311933965Sjdp  dynobj = elf_hash_table(info)->dynobj;
312033965Sjdp  BFD_ASSERT(dynobj != NULL);
312133965Sjdp
312233965Sjdp  if (elf_hash_table (info)->dynamic_sections_created)
312333965Sjdp    {
312433965Sjdp      /* Set the contents of the .interp section to the interpreter.  */
312533965Sjdp      if (!info->shared)
312633965Sjdp	{
312733965Sjdp	  s = bfd_get_section_by_name (dynobj, ".interp");
312833965Sjdp	  BFD_ASSERT (s != NULL);
312933965Sjdp	  s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
313033965Sjdp	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
313133965Sjdp	}
313233965Sjdp
313333965Sjdp      /* Now that we've seen all of the input files, we can decide which
313433965Sjdp	 symbols need dynamic relocation entries and which don't.  We've
313533965Sjdp	 collected information in check_relocs that we can now apply to
313633965Sjdp	 size the dynamic relocation sections.  */
313733965Sjdp      alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
313833965Sjdp				    elf64_alpha_calc_dynrel_sizes,
313933965Sjdp				    info);
314033965Sjdp
314133965Sjdp      /* When building shared libraries, each local .got entry needs a
314233965Sjdp	 RELATIVE reloc.  */
314333965Sjdp      if (info->shared)
314433965Sjdp	{
314533965Sjdp	  bfd *i;
314633965Sjdp	  asection *srel;
314733965Sjdp	  bfd_size_type count;
314833965Sjdp
314933965Sjdp	  srel = bfd_get_section_by_name (dynobj, ".rela.got");
315033965Sjdp	  BFD_ASSERT (srel != NULL);
315133965Sjdp
315233965Sjdp	  for (i = alpha_elf_hash_table(info)->got_list, count = 0;
315333965Sjdp	       i != NULL;
315433965Sjdp	       i = alpha_elf_tdata(i)->got_link_next)
315533965Sjdp	    count += alpha_elf_tdata(i)->n_local_got_entries;
315633965Sjdp
315777303Sobrien	  srel->_raw_size += count * sizeof (Elf64_External_Rela);
315833965Sjdp	}
315933965Sjdp    }
316033965Sjdp  /* else we're not dynamic and by definition we don't need such things.  */
316133965Sjdp
316233965Sjdp  /* The check_relocs and adjust_dynamic_symbol entry points have
316333965Sjdp     determined the sizes of the various dynamic sections.  Allocate
316433965Sjdp     memory for them.  */
316533965Sjdp  relplt = false;
316633965Sjdp  for (s = dynobj->sections; s != NULL; s = s->next)
316733965Sjdp    {
316833965Sjdp      const char *name;
316933965Sjdp      boolean strip;
317033965Sjdp
317133965Sjdp      if (!(s->flags & SEC_LINKER_CREATED))
317233965Sjdp	continue;
317333965Sjdp
317433965Sjdp      /* It's OK to base decisions on the section name, because none
317533965Sjdp	 of the dynobj section names depend upon the input files.  */
317633965Sjdp      name = bfd_get_section_name (dynobj, s);
317733965Sjdp
317833965Sjdp      /* If we don't need this section, strip it from the output file.
317933965Sjdp	 This is to handle .rela.bss and .rela.plt.  We must create it
318033965Sjdp	 in create_dynamic_sections, because it must be created before
318133965Sjdp	 the linker maps input sections to output sections.  The
318233965Sjdp	 linker does that before adjust_dynamic_symbol is called, and
318333965Sjdp	 it is that function which decides whether anything needs to
318433965Sjdp	 go into these sections.  */
318533965Sjdp
318633965Sjdp      strip = false;
318733965Sjdp
318833965Sjdp      if (strncmp (name, ".rela", 5) == 0)
318933965Sjdp	{
319033965Sjdp	  strip = (s->_raw_size == 0);
319133965Sjdp
319233965Sjdp	  if (!strip)
319333965Sjdp	    {
319433965Sjdp	      if (strcmp(name, ".rela.plt") == 0)
319533965Sjdp		relplt = true;
319633965Sjdp
319733965Sjdp	      /* We use the reloc_count field as a counter if we need
319833965Sjdp		 to copy relocs into the output file.  */
319933965Sjdp	      s->reloc_count = 0;
320033965Sjdp	    }
320133965Sjdp	}
320233965Sjdp      else if (strcmp (name, ".plt") != 0)
320333965Sjdp	{
320433965Sjdp	  /* It's not one of our dynamic sections, so don't allocate space.  */
320533965Sjdp	  continue;
320633965Sjdp	}
320733965Sjdp
320833965Sjdp      if (strip)
320960510Sobrien	_bfd_strip_section_from_output (info, s);
321033965Sjdp      else
321133965Sjdp	{
321233965Sjdp	  /* Allocate memory for the section contents.  */
321389862Sobrien	  s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
321433965Sjdp	  if (s->contents == NULL && s->_raw_size != 0)
321533965Sjdp	    return false;
321633965Sjdp	}
321733965Sjdp    }
321833965Sjdp
321933965Sjdp  if (elf_hash_table (info)->dynamic_sections_created)
322033965Sjdp    {
322133965Sjdp      /* Add some entries to the .dynamic section.  We fill in the
322233965Sjdp	 values later, in elf64_alpha_finish_dynamic_sections, but we
322333965Sjdp	 must add the entries now so that we get the correct size for
322433965Sjdp	 the .dynamic section.  The DT_DEBUG entry is filled in by the
322533965Sjdp	 dynamic linker and used by the debugger.  */
322689862Sobrien#define add_dynamic_entry(TAG, VAL) \
322789862Sobrien  bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
322889862Sobrien
322933965Sjdp      if (!info->shared)
323033965Sjdp	{
323189862Sobrien	  if (!add_dynamic_entry (DT_DEBUG, 0))
323233965Sjdp	    return false;
323333965Sjdp	}
323433965Sjdp
323589862Sobrien      if (!add_dynamic_entry (DT_PLTGOT, 0))
323633965Sjdp	return false;
323733965Sjdp
323833965Sjdp      if (relplt)
323933965Sjdp	{
324089862Sobrien	  if (!add_dynamic_entry (DT_PLTRELSZ, 0)
324189862Sobrien	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
324289862Sobrien	      || !add_dynamic_entry (DT_JMPREL, 0))
324333965Sjdp	    return false;
324433965Sjdp	}
324533965Sjdp
324689862Sobrien      if (!add_dynamic_entry (DT_RELA, 0)
324789862Sobrien	  || !add_dynamic_entry (DT_RELASZ, 0)
324889862Sobrien	  || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
324933965Sjdp	return false;
325033965Sjdp
325189862Sobrien      if (info->flags & DF_TEXTREL)
325233965Sjdp	{
325389862Sobrien	  if (!add_dynamic_entry (DT_TEXTREL, 0))
325433965Sjdp	    return false;
325533965Sjdp	}
325633965Sjdp    }
325789862Sobrien#undef add_dynamic_entry
325833965Sjdp
325933965Sjdp  return true;
326033965Sjdp}
326133965Sjdp
326233965Sjdp/* Relocate an Alpha ELF section.  */
326333965Sjdp
326433965Sjdpstatic boolean
326533965Sjdpelf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
326633965Sjdp			      contents, relocs, local_syms, local_sections)
326733965Sjdp     bfd *output_bfd;
326833965Sjdp     struct bfd_link_info *info;
326933965Sjdp     bfd *input_bfd;
327033965Sjdp     asection *input_section;
327133965Sjdp     bfd_byte *contents;
327233965Sjdp     Elf_Internal_Rela *relocs;
327333965Sjdp     Elf_Internal_Sym *local_syms;
327433965Sjdp     asection **local_sections;
327533965Sjdp{
327633965Sjdp  Elf_Internal_Shdr *symtab_hdr;
327733965Sjdp  Elf_Internal_Rela *rel;
327833965Sjdp  Elf_Internal_Rela *relend;
327933965Sjdp  asection *sec, *sgot, *srel, *srelgot;
328033965Sjdp  bfd *dynobj, *gotobj;
328133965Sjdp  bfd_vma gp;
328289862Sobrien  boolean ret_val = true;
328333965Sjdp
328433965Sjdp  srelgot = srel = NULL;
328533965Sjdp  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
328633965Sjdp  dynobj = elf_hash_table (info)->dynobj;
328733965Sjdp  if (dynobj)
328833965Sjdp    {
328933965Sjdp      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
329033965Sjdp    }
329133965Sjdp
329233965Sjdp  /* Find the gp value for this input bfd.  */
329333965Sjdp  sgot = NULL;
329433965Sjdp  gp = 0;
329533965Sjdp  gotobj = alpha_elf_tdata (input_bfd)->gotobj;
329633965Sjdp  if (gotobj)
329733965Sjdp    {
329833965Sjdp      sgot = alpha_elf_tdata (gotobj)->got;
329933965Sjdp      gp = _bfd_get_gp_value (gotobj);
330033965Sjdp      if (gp == 0)
330133965Sjdp	{
330233965Sjdp	  gp = (sgot->output_section->vma
330333965Sjdp		+ sgot->output_offset
330433965Sjdp		+ 0x8000);
330533965Sjdp	  _bfd_set_gp_value (gotobj, gp);
330633965Sjdp	}
330733965Sjdp    }
330833965Sjdp
330933965Sjdp  rel = relocs;
331033965Sjdp  relend = relocs + input_section->reloc_count;
331133965Sjdp  for (; rel < relend; rel++)
331233965Sjdp    {
331333965Sjdp      int r_type;
331433965Sjdp      reloc_howto_type *howto;
331533965Sjdp      unsigned long r_symndx;
331633965Sjdp      struct alpha_elf_link_hash_entry *h;
331733965Sjdp      Elf_Internal_Sym *sym;
331833965Sjdp      bfd_vma relocation;
331933965Sjdp      bfd_vma addend;
332033965Sjdp      bfd_reloc_status_type r;
332133965Sjdp
332233965Sjdp      r_type = ELF64_R_TYPE(rel->r_info);
332333965Sjdp      if (r_type < 0 || r_type >= (int) R_ALPHA_max)
332433965Sjdp	{
332533965Sjdp	  bfd_set_error (bfd_error_bad_value);
332633965Sjdp	  return false;
332733965Sjdp	}
332833965Sjdp      howto = elf64_alpha_howto_table + r_type;
332933965Sjdp
333033965Sjdp      r_symndx = ELF64_R_SYM(rel->r_info);
333133965Sjdp
333233965Sjdp      if (info->relocateable)
333333965Sjdp	{
333433965Sjdp	  /* This is a relocateable link.  We don't have to change
333533965Sjdp	     anything, unless the reloc is against a section symbol,
333633965Sjdp	     in which case we have to adjust according to where the
333733965Sjdp	     section symbol winds up in the output section.  */
333860510Sobrien
333977303Sobrien	  /* The symbol associated with GPDISP and LITUSE is
334060510Sobrien	     immaterial.  Only the addend is significant.  */
334160510Sobrien	  if (r_type == R_ALPHA_GPDISP || r_type == R_ALPHA_LITUSE)
334260510Sobrien	    continue;
334360510Sobrien
334433965Sjdp	  if (r_symndx < symtab_hdr->sh_info)
334533965Sjdp	    {
334633965Sjdp	      sym = local_syms + r_symndx;
334733965Sjdp	      if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
334833965Sjdp		{
334933965Sjdp		  sec = local_sections[r_symndx];
335033965Sjdp		  rel->r_addend += sec->output_offset + sym->st_value;
335133965Sjdp		}
335233965Sjdp	    }
335333965Sjdp
335433965Sjdp	  continue;
335533965Sjdp	}
335633965Sjdp
335733965Sjdp      /* This is a final link.  */
335833965Sjdp
335933965Sjdp      h = NULL;
336033965Sjdp      sym = NULL;
336133965Sjdp      sec = NULL;
336233965Sjdp
336333965Sjdp      if (r_symndx < symtab_hdr->sh_info)
336433965Sjdp	{
336533965Sjdp	  sym = local_syms + r_symndx;
336633965Sjdp	  sec = local_sections[r_symndx];
336789862Sobrien	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
336833965Sjdp	}
336933965Sjdp      else
337033965Sjdp	{
337133965Sjdp	  h = alpha_elf_sym_hashes (input_bfd)[r_symndx - symtab_hdr->sh_info];
337233965Sjdp
337333965Sjdp	  while (h->root.root.type == bfd_link_hash_indirect
337433965Sjdp		 || h->root.root.type == bfd_link_hash_warning)
337533965Sjdp	    h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
337633965Sjdp
337733965Sjdp	  if (h->root.root.type == bfd_link_hash_defined
337833965Sjdp	      || h->root.root.type == bfd_link_hash_defweak)
337933965Sjdp	    {
338033965Sjdp	      sec = h->root.root.u.def.section;
338133965Sjdp
338233965Sjdp	      if (sec->output_section == NULL)
338333965Sjdp		relocation = 0;
338433965Sjdp	      else
338533965Sjdp		{
338633965Sjdp		  relocation = (h->root.root.u.def.value
338733965Sjdp				+ sec->output_section->vma
338833965Sjdp				+ sec->output_offset);
338933965Sjdp		}
339033965Sjdp	    }
339133965Sjdp	  else if (h->root.root.type == bfd_link_hash_undefweak)
339233965Sjdp	    relocation = 0;
339389862Sobrien	  else if (info->shared
339489862Sobrien		   && (!info->symbolic || info->allow_shlib_undefined)
339568770Sobrien		   && !info->no_undefined
339668770Sobrien		   && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
339733965Sjdp	    relocation = 0;
339833965Sjdp	  else
339933965Sjdp	    {
340033965Sjdp	      if (!((*info->callbacks->undefined_symbol)
340133965Sjdp		    (info, h->root.root.root.string, input_bfd,
340260510Sobrien		     input_section, rel->r_offset,
340368770Sobrien		     (!info->shared || info->no_undefined
340468770Sobrien		      || ELF_ST_VISIBILITY (h->root.other)))))
340589862Sobrien		ret_val = false;
340633965Sjdp	      relocation = 0;
340733965Sjdp	    }
340833965Sjdp	}
340933965Sjdp      addend = rel->r_addend;
341033965Sjdp
341133965Sjdp      switch (r_type)
341233965Sjdp	{
341333965Sjdp	case R_ALPHA_GPDISP:
341433965Sjdp	  {
341533965Sjdp	    bfd_byte *p_ldah, *p_lda;
341633965Sjdp
341733965Sjdp	    BFD_ASSERT(gp != 0);
341833965Sjdp
341933965Sjdp	    relocation = (input_section->output_section->vma
342033965Sjdp			  + input_section->output_offset
342133965Sjdp			  + rel->r_offset);
342233965Sjdp
342333965Sjdp	    p_ldah = contents + rel->r_offset - input_section->vma;
342433965Sjdp	    p_lda = p_ldah + rel->r_addend;
342533965Sjdp
342633965Sjdp	    r = elf64_alpha_do_reloc_gpdisp (input_bfd, gp - relocation,
342733965Sjdp					     p_ldah, p_lda);
342833965Sjdp	  }
342933965Sjdp	  break;
343033965Sjdp
343133965Sjdp	case R_ALPHA_LITERAL:
343233965Sjdp	  {
343333965Sjdp	    struct alpha_elf_got_entry *gotent;
343460510Sobrien	    boolean dynamic_symbol;
343533965Sjdp
343633965Sjdp	    BFD_ASSERT(sgot != NULL);
343733965Sjdp	    BFD_ASSERT(gp != 0);
343833965Sjdp
343933965Sjdp	    if (h != NULL)
344033965Sjdp	      {
344133965Sjdp		gotent = h->got_entries;
344260510Sobrien		dynamic_symbol = alpha_elf_dynamic_symbol_p (&h->root, info);
344333965Sjdp	      }
344433965Sjdp	    else
344533965Sjdp	      {
344633965Sjdp		gotent = (alpha_elf_tdata(input_bfd)->
344733965Sjdp			  local_got_entries[r_symndx]);
344860510Sobrien		dynamic_symbol = false;
344989862Sobrien
345089862Sobrien		/* Need to adjust local GOT entries' addends for SEC_MERGE
345189862Sobrien		   unless it has been done already.  */
345289862Sobrien		if ((sec->flags & SEC_MERGE)
345389862Sobrien		    && ELF_ST_TYPE (sym->st_info) == STT_SECTION
345489862Sobrien		    && (elf_section_data (sec)->sec_info_type
345589862Sobrien			== ELF_INFO_TYPE_MERGE)
345689862Sobrien		    && (gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED) == 0)
345789862Sobrien		  {
345889862Sobrien		    struct alpha_elf_got_entry *ent;
345989862Sobrien		    asection *msec;
346089862Sobrien
346189862Sobrien		    for (ent = gotent; ent; ent = ent->next)
346289862Sobrien		      {
346389862Sobrien			ent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED;
346489862Sobrien			if (ent->use_count == 0)
346589862Sobrien			  continue;
346689862Sobrien			msec = sec;
346789862Sobrien			ent->addend =
346889862Sobrien			  _bfd_merged_section_offset (output_bfd, &msec,
346989862Sobrien						      elf_section_data (sec)->
347089862Sobrien						      sec_info,
347189862Sobrien						      sym->st_value
347289862Sobrien						      + ent->addend,
347389862Sobrien						      (bfd_vma) 0);
347489862Sobrien			ent->addend -= sym->st_value;
347589862Sobrien			ent->addend += msec->output_section->vma
347689862Sobrien				       + msec->output_offset
347789862Sobrien				       - sec->output_section->vma
347889862Sobrien				       - sec->output_offset;
347989862Sobrien		      }
348089862Sobrien		  }
348160510Sobrien	      }
348233965Sjdp
348360510Sobrien	    BFD_ASSERT(gotent != NULL);
348433965Sjdp
348560510Sobrien	    while (gotent->gotobj != gotobj || gotent->addend != addend)
348660510Sobrien	      gotent = gotent->next;
348733965Sjdp
348860510Sobrien	    BFD_ASSERT(gotent->use_count >= 1);
348933965Sjdp
349060510Sobrien	    /* Initialize the .got entry's value.  */
349160510Sobrien	    if (!(gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_DONE))
349260510Sobrien	      {
349389862Sobrien		bfd_put_64 (output_bfd, relocation + addend,
349460510Sobrien			    sgot->contents + gotent->got_offset);
349533965Sjdp
349660510Sobrien		/* If the symbol has been forced local, output a
349760510Sobrien		   RELATIVE reloc, otherwise it will be handled in
349860510Sobrien		   finish_dynamic_symbol.  */
349960510Sobrien		if (info->shared && !dynamic_symbol)
350060510Sobrien		  {
350160510Sobrien		    Elf_Internal_Rela outrel;
350233965Sjdp
350360510Sobrien		    BFD_ASSERT(srelgot != NULL);
350460510Sobrien
350560510Sobrien		    outrel.r_offset = (sgot->output_section->vma
350660510Sobrien				       + sgot->output_offset
350760510Sobrien				       + gotent->got_offset);
350860510Sobrien		    outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE);
350989862Sobrien		    outrel.r_addend = relocation + addend;
351060510Sobrien
351160510Sobrien		    bfd_elf64_swap_reloca_out (output_bfd, &outrel,
351260510Sobrien					       ((Elf64_External_Rela *)
351360510Sobrien					        srelgot->contents)
351460510Sobrien					       + srelgot->reloc_count++);
351577303Sobrien		    BFD_ASSERT (sizeof (Elf64_External_Rela)
351660510Sobrien				* srelgot->reloc_count
351760510Sobrien				<= srelgot->_cooked_size);
351833965Sjdp		  }
351960510Sobrien
352060510Sobrien		gotent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_DONE;
352133965Sjdp	      }
352233965Sjdp
352333965Sjdp	    /* Figure the gprel relocation.  */
352433965Sjdp	    addend = 0;
352533965Sjdp	    relocation = (sgot->output_section->vma
352633965Sjdp			  + sgot->output_offset
352733965Sjdp			  + gotent->got_offset);
352833965Sjdp	    relocation -= gp;
352933965Sjdp	  }
353033965Sjdp	  /* overflow handled by _bfd_final_link_relocate */
353133965Sjdp	  goto default_reloc;
353233965Sjdp
353389862Sobrien	case R_ALPHA_GPREL16:
353433965Sjdp	case R_ALPHA_GPREL32:
353560510Sobrien	case R_ALPHA_GPRELLOW:
353689862Sobrien	  if (h && alpha_elf_dynamic_symbol_p (&h->root, info))
353789862Sobrien            {
353889862Sobrien              (*_bfd_error_handler)
353989862Sobrien                (_("%s: gp-relative relocation against dynamic symbol %s"),
354089862Sobrien                 bfd_archive_filename (input_bfd), h->root.root.root.string);
354189862Sobrien              ret_val = false;
354289862Sobrien            }
354333965Sjdp	  BFD_ASSERT(gp != 0);
354433965Sjdp	  relocation -= gp;
354533965Sjdp	  goto default_reloc;
354633965Sjdp
354760510Sobrien	case R_ALPHA_GPRELHIGH:
354889862Sobrien	  if (h && alpha_elf_dynamic_symbol_p (&h->root, info))
354989862Sobrien            {
355089862Sobrien              (*_bfd_error_handler)
355189862Sobrien                (_("%s: gp-relative relocation against dynamic symbol %s"),
355289862Sobrien                 bfd_archive_filename (input_bfd), h->root.root.root.string);
355389862Sobrien              ret_val = false;
355489862Sobrien            }
355560510Sobrien	  BFD_ASSERT(gp != 0);
355660510Sobrien	  relocation -= gp;
355760510Sobrien	  relocation += addend;
355860510Sobrien	  addend = 0;
355960510Sobrien	  relocation = (((bfd_signed_vma) relocation >> 16)
356060510Sobrien			+ ((relocation >> 15) & 1));
356160510Sobrien	  goto default_reloc;
356260510Sobrien
356389862Sobrien	case R_ALPHA_HINT:
356489862Sobrien	  /* A call to a dynamic symbol is definitely out of range of
356589862Sobrien	     the 16-bit displacement.  Don't bother writing anything.  */
356689862Sobrien	  if (h && alpha_elf_dynamic_symbol_p (&h->root, info))
356789862Sobrien	    {
356889862Sobrien	      r = bfd_reloc_ok;
356989862Sobrien	      break;
357089862Sobrien	    }
357189862Sobrien	  /* FALLTHRU */
357289862Sobrien
357333965Sjdp	case R_ALPHA_BRADDR:
357433965Sjdp	  /* The regular PC-relative stuff measures from the start of
357533965Sjdp	     the instruction rather than the end.  */
357633965Sjdp	  addend -= 4;
357733965Sjdp	  goto default_reloc;
357833965Sjdp
357991049Sobrien	case R_ALPHA_BRSGP:
358091049Sobrien	  {
358191049Sobrien	    int other;
358291049Sobrien	    const char *name;
358391049Sobrien
358491049Sobrien	    /* The regular PC-relative stuff measures from the start of
358591049Sobrien	       the instruction rather than the end.  */
358691049Sobrien	    addend -= 4;
358791049Sobrien
358891049Sobrien	    /* The source and destination gp must be the same.  Note that
358991049Sobrien	       the source will always have an assigned gp, since we forced
359091049Sobrien	       one in check_relocs, but that the destination may not, as
359191049Sobrien	       it might not have had any relocations at all.  Also take
359291049Sobrien	       care not to crash if H is an undefined symbol.  */
359391049Sobrien	    if (h != NULL && sec != NULL
359491049Sobrien		&& alpha_elf_tdata (sec->owner)->gotobj
359591049Sobrien		&& gotobj != alpha_elf_tdata (sec->owner)->gotobj)
359691049Sobrien	      {
359791049Sobrien		(*_bfd_error_handler)
359891049Sobrien		  (_("%s: change in gp: BRSGP %s"),
359991049Sobrien		   bfd_archive_filename (input_bfd), h->root.root.root.string);
360091049Sobrien		ret_val = false;
360191049Sobrien	      }
360291049Sobrien
360391049Sobrien	    /* The symbol should be marked either NOPV or STD_GPLOAD.  */
360491049Sobrien	    if (h != NULL)
360591049Sobrien	      other = h->root.other;
360691049Sobrien	    else
360791049Sobrien	      other = sym->st_other;
360891049Sobrien	    switch (other & STO_ALPHA_STD_GPLOAD)
360991049Sobrien	      {
361091049Sobrien	      case STO_ALPHA_NOPV:
361191049Sobrien	        break;
361291049Sobrien	      case STO_ALPHA_STD_GPLOAD:
361391049Sobrien		addend += 8;
361491049Sobrien		break;
361591049Sobrien	      default:
361691049Sobrien		if (h != NULL)
361791049Sobrien		  name = h->root.root.root.string;
361891049Sobrien		else
361991049Sobrien		  {
362091049Sobrien		    name = (bfd_elf_string_from_elf_section
362191049Sobrien			    (input_bfd, symtab_hdr->sh_link, sym->st_name));
362291049Sobrien		    if (name == NULL)
362391049Sobrien		      name = _("<unknown>");
362491049Sobrien		    else if (name[0] == 0)
362591049Sobrien		      name = bfd_section_name (input_bfd, sec);
362691049Sobrien		  }
362791049Sobrien		(*_bfd_error_handler)
362891049Sobrien		  (_("%s: !samegp reloc against symbol without .prologue: %s"),
362991049Sobrien		   bfd_archive_filename (input_bfd), name);
363091049Sobrien		ret_val = false;
363191049Sobrien		break;
363291049Sobrien	      }
363391049Sobrien
363491049Sobrien	    goto default_reloc;
363591049Sobrien	  }
363691049Sobrien
363733965Sjdp	case R_ALPHA_REFLONG:
363833965Sjdp	case R_ALPHA_REFQUAD:
363933965Sjdp	  {
364033965Sjdp	    Elf_Internal_Rela outrel;
364133965Sjdp
364233965Sjdp	    /* Careful here to remember RELATIVE relocations for global
364333965Sjdp	       variables for symbolic shared objects.  */
364433965Sjdp
364533965Sjdp	    if (h && alpha_elf_dynamic_symbol_p (&h->root, info))
364633965Sjdp	      {
364733965Sjdp		BFD_ASSERT(h->root.dynindx != -1);
364833965Sjdp		outrel.r_info = ELF64_R_INFO(h->root.dynindx, r_type);
364933965Sjdp		outrel.r_addend = addend;
365033965Sjdp		addend = 0, relocation = 0;
365133965Sjdp	      }
365289862Sobrien	    else if (info->shared
365389862Sobrien		     && r_symndx != 0
365489862Sobrien		     && (input_section->flags & SEC_ALLOC))
365533965Sjdp	      {
365633965Sjdp		outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE);
365789862Sobrien		outrel.r_addend = relocation + addend;
365833965Sjdp	      }
365933965Sjdp	    else
366033965Sjdp	      goto default_reloc;
366133965Sjdp
366233965Sjdp	    if (!srel)
366333965Sjdp	      {
366433965Sjdp		const char *name;
366533965Sjdp
366633965Sjdp		name = (bfd_elf_string_from_elf_section
366733965Sjdp			(input_bfd, elf_elfheader(input_bfd)->e_shstrndx,
366833965Sjdp			 elf_section_data(input_section)->rel_hdr.sh_name));
366933965Sjdp		BFD_ASSERT(name != NULL);
367033965Sjdp
367133965Sjdp		srel = bfd_get_section_by_name (dynobj, name);
367233965Sjdp		BFD_ASSERT(srel != NULL);
367333965Sjdp	      }
367433965Sjdp
367589862Sobrien	    outrel.r_offset =
367689862Sobrien	      _bfd_elf_section_offset (output_bfd, info, input_section,
367789862Sobrien				       rel->r_offset);
367891049Sobrien	    if ((outrel.r_offset | 1) != (bfd_vma) -1)
367933965Sjdp	      outrel.r_offset += (input_section->output_section->vma
368033965Sjdp				  + input_section->output_offset);
368133965Sjdp	    else
368233965Sjdp	      memset (&outrel, 0, sizeof outrel);
368333965Sjdp
368433965Sjdp	    bfd_elf64_swap_reloca_out (output_bfd, &outrel,
368533965Sjdp				       ((Elf64_External_Rela *)
368633965Sjdp					srel->contents)
368733965Sjdp				       + srel->reloc_count++);
368877303Sobrien	    BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
368948850Sdfr			<= srel->_cooked_size);
369033965Sjdp	  }
369133965Sjdp	  goto default_reloc;
369233965Sjdp
369333965Sjdp	default:
369433965Sjdp	default_reloc:
369533965Sjdp	  r = _bfd_final_link_relocate (howto, input_bfd, input_section,
369633965Sjdp					contents, rel->r_offset, relocation,
369733965Sjdp					addend);
369833965Sjdp	  break;
369933965Sjdp	}
370033965Sjdp
370133965Sjdp      switch (r)
370233965Sjdp	{
370333965Sjdp	case bfd_reloc_ok:
370433965Sjdp	  break;
370533965Sjdp
370633965Sjdp	case bfd_reloc_overflow:
370733965Sjdp	  {
370833965Sjdp	    const char *name;
370933965Sjdp
371089862Sobrien	    /* Don't warn if the overflow is due to pc relative reloc
371189862Sobrien	       against discarded section.  Section optimization code should
371289862Sobrien	       handle it.  */
371389862Sobrien
371489862Sobrien	    if (r_symndx < symtab_hdr->sh_info
371589862Sobrien		&& sec != NULL && howto->pc_relative
371689862Sobrien		&& elf_discarded_section (sec))
371789862Sobrien	      break;
371889862Sobrien
371933965Sjdp	    if (h != NULL)
372033965Sjdp	      name = h->root.root.root.string;
372133965Sjdp	    else
372233965Sjdp	      {
372333965Sjdp		name = (bfd_elf_string_from_elf_section
372433965Sjdp			(input_bfd, symtab_hdr->sh_link, sym->st_name));
372533965Sjdp		if (name == NULL)
372633965Sjdp		  return false;
372733965Sjdp		if (*name == '\0')
372833965Sjdp		  name = bfd_section_name (input_bfd, sec);
372933965Sjdp	      }
373033965Sjdp	    if (! ((*info->callbacks->reloc_overflow)
373133965Sjdp		   (info, name, howto->name, (bfd_vma) 0,
373233965Sjdp		    input_bfd, input_section, rel->r_offset)))
373389862Sobrien	      ret_val = false;
373433965Sjdp	  }
373533965Sjdp	  break;
373633965Sjdp
373733965Sjdp	default:
373833965Sjdp	case bfd_reloc_outofrange:
373933965Sjdp	  abort ();
374033965Sjdp	}
374133965Sjdp    }
374233965Sjdp
374389862Sobrien  return ret_val;
374433965Sjdp}
374533965Sjdp
374633965Sjdp/* Finish up dynamic symbol handling.  We set the contents of various
374733965Sjdp   dynamic sections here.  */
374833965Sjdp
374933965Sjdpstatic boolean
375033965Sjdpelf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym)
375133965Sjdp     bfd *output_bfd;
375233965Sjdp     struct bfd_link_info *info;
375333965Sjdp     struct elf_link_hash_entry *h;
375433965Sjdp     Elf_Internal_Sym *sym;
375533965Sjdp{
375633965Sjdp  bfd *dynobj = elf_hash_table(info)->dynobj;
375733965Sjdp
375860510Sobrien  if (h->plt.offset != MINUS_ONE)
375933965Sjdp    {
376033965Sjdp      /* Fill in the .plt entry for this symbol.  */
376133965Sjdp      asection *splt, *sgot, *srel;
376233965Sjdp      Elf_Internal_Rela outrel;
376333965Sjdp      bfd_vma got_addr, plt_addr;
376433965Sjdp      bfd_vma plt_index;
376533965Sjdp      struct alpha_elf_got_entry *gotent;
376633965Sjdp
376733965Sjdp      BFD_ASSERT (h->dynindx != -1);
376833965Sjdp
376933965Sjdp      /* The first .got entry will be updated by the .plt with the
377033965Sjdp	 address of the target function.  */
377133965Sjdp      gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
377233965Sjdp      BFD_ASSERT (gotent && gotent->addend == 0);
377333965Sjdp
377433965Sjdp      splt = bfd_get_section_by_name (dynobj, ".plt");
377533965Sjdp      BFD_ASSERT (splt != NULL);
377633965Sjdp      srel = bfd_get_section_by_name (dynobj, ".rela.plt");
377733965Sjdp      BFD_ASSERT (srel != NULL);
377833965Sjdp      sgot = alpha_elf_tdata (gotent->gotobj)->got;
377933965Sjdp      BFD_ASSERT (sgot != NULL);
378033965Sjdp
378133965Sjdp      got_addr = (sgot->output_section->vma
378233965Sjdp		  + sgot->output_offset
378333965Sjdp		  + gotent->got_offset);
378433965Sjdp      plt_addr = (splt->output_section->vma
378533965Sjdp		  + splt->output_offset
378660510Sobrien		  + h->plt.offset);
378733965Sjdp
378860510Sobrien      plt_index = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
378933965Sjdp
379033965Sjdp      /* Fill in the entry in the procedure linkage table.  */
379133965Sjdp      {
379289862Sobrien	bfd_vma insn1, insn2, insn3;
379333965Sjdp
379460510Sobrien	insn1 = PLT_ENTRY_WORD1 | ((-(h->plt.offset + 4) >> 2) & 0x1fffff);
379538889Sjdp	insn2 = PLT_ENTRY_WORD2;
379638889Sjdp	insn3 = PLT_ENTRY_WORD3;
379733965Sjdp
379860510Sobrien	bfd_put_32 (output_bfd, insn1, splt->contents + h->plt.offset);
379960510Sobrien	bfd_put_32 (output_bfd, insn2, splt->contents + h->plt.offset + 4);
380060510Sobrien	bfd_put_32 (output_bfd, insn3, splt->contents + h->plt.offset + 8);
380133965Sjdp      }
380233965Sjdp
380333965Sjdp      /* Fill in the entry in the .rela.plt section.  */
380433965Sjdp      outrel.r_offset = got_addr;
380533965Sjdp      outrel.r_info = ELF64_R_INFO(h->dynindx, R_ALPHA_JMP_SLOT);
380633965Sjdp      outrel.r_addend = 0;
380733965Sjdp
380833965Sjdp      bfd_elf64_swap_reloca_out (output_bfd, &outrel,
380933965Sjdp				 ((Elf64_External_Rela *)srel->contents
381033965Sjdp				  + plt_index));
381133965Sjdp
381233965Sjdp      if (!(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
381333965Sjdp	{
381433965Sjdp	  /* Mark the symbol as undefined, rather than as defined in the
381533965Sjdp	     .plt section.  Leave the value alone.  */
381633965Sjdp	  sym->st_shndx = SHN_UNDEF;
381733965Sjdp	}
381833965Sjdp
381933965Sjdp      /* Fill in the entries in the .got.  */
382033965Sjdp      bfd_put_64 (output_bfd, plt_addr, sgot->contents + gotent->got_offset);
382133965Sjdp
382233965Sjdp      /* Subsequent .got entries will continue to bounce through the .plt.  */
382348850Sdfr      if (gotent->next)
382433965Sjdp	{
382548850Sdfr	  srel = bfd_get_section_by_name (dynobj, ".rela.got");
382648850Sdfr	  BFD_ASSERT (! info->shared || srel != NULL);
382733965Sjdp
382848850Sdfr	  gotent = gotent->next;
382948850Sdfr	  do
383048850Sdfr	    {
383148850Sdfr	      sgot = alpha_elf_tdata(gotent->gotobj)->got;
383248850Sdfr	      BFD_ASSERT(sgot != NULL);
383348850Sdfr	      BFD_ASSERT(gotent->addend == 0);
383448850Sdfr
383548850Sdfr	      bfd_put_64 (output_bfd, plt_addr,
383648850Sdfr		          sgot->contents + gotent->got_offset);
383748850Sdfr
383848850Sdfr	      if (info->shared)
383948850Sdfr		{
384048850Sdfr		  outrel.r_offset = (sgot->output_section->vma
384148850Sdfr				     + sgot->output_offset
384248850Sdfr				     + gotent->got_offset);
384348850Sdfr		  outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE);
384489862Sobrien		  outrel.r_addend = plt_addr;
384548850Sdfr
384648850Sdfr		  bfd_elf64_swap_reloca_out (output_bfd, &outrel,
384748850Sdfr					     ((Elf64_External_Rela *)
384848850Sdfr					      srel->contents)
384948850Sdfr					     + srel->reloc_count++);
385077303Sobrien		  BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
385148850Sdfr			      <= srel->_cooked_size);
385248850Sdfr		}
385348850Sdfr
385448850Sdfr	      gotent = gotent->next;
385548850Sdfr	    }
385648850Sdfr          while (gotent != NULL);
385733965Sjdp	}
385833965Sjdp    }
385933965Sjdp  else if (alpha_elf_dynamic_symbol_p (h, info))
386033965Sjdp    {
386133965Sjdp      /* Fill in the dynamic relocations for this symbol's .got entries.  */
386233965Sjdp      asection *srel;
386333965Sjdp      Elf_Internal_Rela outrel;
386433965Sjdp      struct alpha_elf_got_entry *gotent;
386533965Sjdp
386633965Sjdp      srel = bfd_get_section_by_name (dynobj, ".rela.got");
386733965Sjdp      BFD_ASSERT (srel != NULL);
386833965Sjdp
386933965Sjdp      outrel.r_info = ELF64_R_INFO (h->dynindx, R_ALPHA_GLOB_DAT);
387033965Sjdp      for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
387133965Sjdp	   gotent != NULL;
387233965Sjdp	   gotent = gotent->next)
387333965Sjdp	{
387433965Sjdp	  asection *sgot = alpha_elf_tdata (gotent->gotobj)->got;
387533965Sjdp	  outrel.r_offset = (sgot->output_section->vma
387633965Sjdp			     + sgot->output_offset
387733965Sjdp			     + gotent->got_offset);
387833965Sjdp	  outrel.r_addend = gotent->addend;
387933965Sjdp
388033965Sjdp	  bfd_elf64_swap_reloca_out (output_bfd, &outrel,
388133965Sjdp				     ((Elf64_External_Rela *)srel->contents
388233965Sjdp				      + srel->reloc_count++));
388377303Sobrien	  BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
388448850Sdfr		      <= srel->_cooked_size);
388533965Sjdp	}
388633965Sjdp    }
388733965Sjdp
388833965Sjdp  /* Mark some specially defined symbols as absolute.  */
388933965Sjdp  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
389033965Sjdp      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
389133965Sjdp      || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
389233965Sjdp    sym->st_shndx = SHN_ABS;
389333965Sjdp
389433965Sjdp  return true;
389533965Sjdp}
389633965Sjdp
389733965Sjdp/* Finish up the dynamic sections.  */
389833965Sjdp
389933965Sjdpstatic boolean
390033965Sjdpelf64_alpha_finish_dynamic_sections (output_bfd, info)
390133965Sjdp     bfd *output_bfd;
390233965Sjdp     struct bfd_link_info *info;
390333965Sjdp{
390433965Sjdp  bfd *dynobj;
390533965Sjdp  asection *sdyn;
390633965Sjdp
390733965Sjdp  dynobj = elf_hash_table (info)->dynobj;
390833965Sjdp  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
390933965Sjdp
391033965Sjdp  if (elf_hash_table (info)->dynamic_sections_created)
391133965Sjdp    {
391233965Sjdp      asection *splt;
391333965Sjdp      Elf64_External_Dyn *dyncon, *dynconend;
391433965Sjdp
391533965Sjdp      splt = bfd_get_section_by_name (dynobj, ".plt");
391633965Sjdp      BFD_ASSERT (splt != NULL && sdyn != NULL);
391733965Sjdp
391833965Sjdp      dyncon = (Elf64_External_Dyn *) sdyn->contents;
391933965Sjdp      dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
392033965Sjdp      for (; dyncon < dynconend; dyncon++)
392133965Sjdp	{
392233965Sjdp	  Elf_Internal_Dyn dyn;
392333965Sjdp	  const char *name;
392433965Sjdp	  asection *s;
392533965Sjdp
392633965Sjdp	  bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn);
392733965Sjdp
392833965Sjdp	  switch (dyn.d_tag)
392933965Sjdp	    {
393033965Sjdp	    case DT_PLTGOT:
393133965Sjdp	      name = ".plt";
393233965Sjdp	      goto get_vma;
393333965Sjdp	    case DT_PLTRELSZ:
393433965Sjdp	      name = ".rela.plt";
393533965Sjdp	      goto get_size;
393633965Sjdp	    case DT_JMPREL:
393733965Sjdp	      name = ".rela.plt";
393833965Sjdp	      goto get_vma;
393933965Sjdp
394033965Sjdp	    case DT_RELASZ:
394133965Sjdp	      /* My interpretation of the TIS v1.1 ELF document indicates
394233965Sjdp		 that RELASZ should not include JMPREL.  This is not what
394333965Sjdp		 the rest of the BFD does.  It is, however, what the
394433965Sjdp		 glibc ld.so wants.  Do this fixup here until we found
394533965Sjdp		 out who is right.  */
394633965Sjdp	      s = bfd_get_section_by_name (output_bfd, ".rela.plt");
394733965Sjdp	      if (s)
394833965Sjdp		{
394933965Sjdp		  dyn.d_un.d_val -=
395033965Sjdp		    (s->_cooked_size ? s->_cooked_size : s->_raw_size);
395133965Sjdp		}
395233965Sjdp	      break;
395333965Sjdp
395433965Sjdp	    get_vma:
395533965Sjdp	      s = bfd_get_section_by_name (output_bfd, name);
395633965Sjdp	      dyn.d_un.d_ptr = (s ? s->vma : 0);
395733965Sjdp	      break;
395833965Sjdp
395933965Sjdp	    get_size:
396033965Sjdp	      s = bfd_get_section_by_name (output_bfd, name);
396133965Sjdp	      dyn.d_un.d_val =
396233965Sjdp		(s->_cooked_size ? s->_cooked_size : s->_raw_size);
396333965Sjdp	      break;
396433965Sjdp	    }
396533965Sjdp
396633965Sjdp	  bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
396733965Sjdp	}
396833965Sjdp
396933965Sjdp      /* Initialize the PLT0 entry */
397033965Sjdp      if (splt->_raw_size > 0)
397133965Sjdp	{
397233965Sjdp	  bfd_put_32 (output_bfd, PLT_HEADER_WORD1, splt->contents);
397333965Sjdp	  bfd_put_32 (output_bfd, PLT_HEADER_WORD2, splt->contents + 4);
397433965Sjdp	  bfd_put_32 (output_bfd, PLT_HEADER_WORD3, splt->contents + 8);
397533965Sjdp	  bfd_put_32 (output_bfd, PLT_HEADER_WORD4, splt->contents + 12);
397633965Sjdp
397733965Sjdp	  /* The next two words will be filled in by ld.so */
397889862Sobrien	  bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 16);
397989862Sobrien	  bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 24);
398033965Sjdp
398133965Sjdp	  elf_section_data (splt->output_section)->this_hdr.sh_entsize =
398233965Sjdp	    PLT_HEADER_SIZE;
398333965Sjdp	}
398433965Sjdp    }
398533965Sjdp
398633965Sjdp  return true;
398733965Sjdp}
398833965Sjdp
398989862Sobrien/* We need to use a special link routine to handle the .mdebug section.
399089862Sobrien   We need to merge all instances of these sections together, not write
399189862Sobrien   them all out sequentially.  */
399233965Sjdp
399333965Sjdpstatic boolean
399433965Sjdpelf64_alpha_final_link (abfd, info)
399533965Sjdp     bfd *abfd;
399633965Sjdp     struct bfd_link_info *info;
399733965Sjdp{
399833965Sjdp  asection *o;
399933965Sjdp  struct bfd_link_order *p;
400089862Sobrien  asection *mdebug_sec;
400133965Sjdp  struct ecoff_debug_info debug;
400233965Sjdp  const struct ecoff_debug_swap *swap
400333965Sjdp    = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
400433965Sjdp  HDRR *symhdr = &debug.symbolic_header;
400533965Sjdp  PTR mdebug_handle = NULL;
400633965Sjdp
400789862Sobrien  /* Go through the sections and collect the mdebug information.  */
400833965Sjdp  mdebug_sec = NULL;
400933965Sjdp  for (o = abfd->sections; o != (asection *) NULL; o = o->next)
401033965Sjdp    {
401133965Sjdp      if (strcmp (o->name, ".mdebug") == 0)
401233965Sjdp	{
401333965Sjdp	  struct extsym_info einfo;
401433965Sjdp
401533965Sjdp	  /* We have found the .mdebug section in the output file.
401633965Sjdp	     Look through all the link_orders comprising it and merge
401733965Sjdp	     the information together.  */
401833965Sjdp	  symhdr->magic = swap->sym_magic;
401933965Sjdp	  /* FIXME: What should the version stamp be?  */
402033965Sjdp	  symhdr->vstamp = 0;
402133965Sjdp	  symhdr->ilineMax = 0;
402233965Sjdp	  symhdr->cbLine = 0;
402333965Sjdp	  symhdr->idnMax = 0;
402433965Sjdp	  symhdr->ipdMax = 0;
402533965Sjdp	  symhdr->isymMax = 0;
402633965Sjdp	  symhdr->ioptMax = 0;
402733965Sjdp	  symhdr->iauxMax = 0;
402833965Sjdp	  symhdr->issMax = 0;
402933965Sjdp	  symhdr->issExtMax = 0;
403033965Sjdp	  symhdr->ifdMax = 0;
403133965Sjdp	  symhdr->crfd = 0;
403233965Sjdp	  symhdr->iextMax = 0;
403333965Sjdp
403433965Sjdp	  /* We accumulate the debugging information itself in the
403533965Sjdp	     debug_info structure.  */
403633965Sjdp	  debug.line = NULL;
403733965Sjdp	  debug.external_dnr = NULL;
403833965Sjdp	  debug.external_pdr = NULL;
403933965Sjdp	  debug.external_sym = NULL;
404033965Sjdp	  debug.external_opt = NULL;
404133965Sjdp	  debug.external_aux = NULL;
404233965Sjdp	  debug.ss = NULL;
404333965Sjdp	  debug.ssext = debug.ssext_end = NULL;
404433965Sjdp	  debug.external_fdr = NULL;
404533965Sjdp	  debug.external_rfd = NULL;
404633965Sjdp	  debug.external_ext = debug.external_ext_end = NULL;
404733965Sjdp
404833965Sjdp	  mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info);
404933965Sjdp	  if (mdebug_handle == (PTR) NULL)
405033965Sjdp	    return false;
405133965Sjdp
405233965Sjdp	  if (1)
405333965Sjdp	    {
405433965Sjdp	      asection *s;
405533965Sjdp	      EXTR esym;
405689862Sobrien	      bfd_vma last = 0;
405733965Sjdp	      unsigned int i;
405833965Sjdp	      static const char * const name[] =
405933965Sjdp		{
406033965Sjdp		  ".text", ".init", ".fini", ".data",
406133965Sjdp		  ".rodata", ".sdata", ".sbss", ".bss"
406233965Sjdp		};
406333965Sjdp	      static const int sc[] = { scText, scInit, scFini, scData,
406433965Sjdp					  scRData, scSData, scSBss, scBss };
406533965Sjdp
406633965Sjdp	      esym.jmptbl = 0;
406733965Sjdp	      esym.cobol_main = 0;
406833965Sjdp	      esym.weakext = 0;
406933965Sjdp	      esym.reserved = 0;
407033965Sjdp	      esym.ifd = ifdNil;
407133965Sjdp	      esym.asym.iss = issNil;
407233965Sjdp	      esym.asym.st = stLocal;
407333965Sjdp	      esym.asym.reserved = 0;
407433965Sjdp	      esym.asym.index = indexNil;
407533965Sjdp	      for (i = 0; i < 8; i++)
407633965Sjdp		{
407733965Sjdp		  esym.asym.sc = sc[i];
407833965Sjdp		  s = bfd_get_section_by_name (abfd, name[i]);
407933965Sjdp		  if (s != NULL)
408033965Sjdp		    {
408133965Sjdp		      esym.asym.value = s->vma;
408233965Sjdp		      last = s->vma + s->_raw_size;
408333965Sjdp		    }
408433965Sjdp		  else
408533965Sjdp		    esym.asym.value = last;
408633965Sjdp
408733965Sjdp		  if (! bfd_ecoff_debug_one_external (abfd, &debug, swap,
408833965Sjdp						      name[i], &esym))
408933965Sjdp		    return false;
409033965Sjdp		}
409133965Sjdp	    }
409233965Sjdp
409333965Sjdp	  for (p = o->link_order_head;
409433965Sjdp	       p != (struct bfd_link_order *) NULL;
409533965Sjdp	       p = p->next)
409633965Sjdp	    {
409733965Sjdp	      asection *input_section;
409833965Sjdp	      bfd *input_bfd;
409933965Sjdp	      const struct ecoff_debug_swap *input_swap;
410033965Sjdp	      struct ecoff_debug_info input_debug;
410133965Sjdp	      char *eraw_src;
410233965Sjdp	      char *eraw_end;
410333965Sjdp
410433965Sjdp	      if (p->type != bfd_indirect_link_order)
410533965Sjdp		{
410633965Sjdp		  if (p->type == bfd_fill_link_order)
410733965Sjdp		    continue;
410833965Sjdp		  abort ();
410933965Sjdp		}
411033965Sjdp
411133965Sjdp	      input_section = p->u.indirect.section;
411233965Sjdp	      input_bfd = input_section->owner;
411333965Sjdp
411433965Sjdp	      if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour
411533965Sjdp		  || (get_elf_backend_data (input_bfd)
411633965Sjdp		      ->elf_backend_ecoff_debug_swap) == NULL)
411733965Sjdp		{
411833965Sjdp		  /* I don't know what a non ALPHA ELF bfd would be
411933965Sjdp		     doing with a .mdebug section, but I don't really
412033965Sjdp		     want to deal with it.  */
412133965Sjdp		  continue;
412233965Sjdp		}
412333965Sjdp
412433965Sjdp	      input_swap = (get_elf_backend_data (input_bfd)
412533965Sjdp			    ->elf_backend_ecoff_debug_swap);
412633965Sjdp
412733965Sjdp	      BFD_ASSERT (p->size == input_section->_raw_size);
412833965Sjdp
412933965Sjdp	      /* The ECOFF linking code expects that we have already
413033965Sjdp		 read in the debugging information and set up an
413133965Sjdp		 ecoff_debug_info structure, so we do that now.  */
413233965Sjdp	      if (!elf64_alpha_read_ecoff_info (input_bfd, input_section,
413333965Sjdp						&input_debug))
413433965Sjdp		return false;
413533965Sjdp
413633965Sjdp	      if (! (bfd_ecoff_debug_accumulate
413733965Sjdp		     (mdebug_handle, abfd, &debug, swap, input_bfd,
413833965Sjdp		      &input_debug, input_swap, info)))
413933965Sjdp		return false;
414033965Sjdp
414133965Sjdp	      /* Loop through the external symbols.  For each one with
414233965Sjdp		 interesting information, try to find the symbol in
414333965Sjdp		 the linker global hash table and save the information
414433965Sjdp		 for the output external symbols.  */
414533965Sjdp	      eraw_src = input_debug.external_ext;
414633965Sjdp	      eraw_end = (eraw_src
414733965Sjdp			  + (input_debug.symbolic_header.iextMax
414833965Sjdp			     * input_swap->external_ext_size));
414933965Sjdp	      for (;
415033965Sjdp		   eraw_src < eraw_end;
415133965Sjdp		   eraw_src += input_swap->external_ext_size)
415233965Sjdp		{
415333965Sjdp		  EXTR ext;
415433965Sjdp		  const char *name;
415533965Sjdp		  struct alpha_elf_link_hash_entry *h;
415633965Sjdp
415733965Sjdp		  (*input_swap->swap_ext_in) (input_bfd, (PTR) eraw_src, &ext);
415833965Sjdp		  if (ext.asym.sc == scNil
415933965Sjdp		      || ext.asym.sc == scUndefined
416033965Sjdp		      || ext.asym.sc == scSUndefined)
416133965Sjdp		    continue;
416233965Sjdp
416333965Sjdp		  name = input_debug.ssext + ext.asym.iss;
416433965Sjdp		  h = alpha_elf_link_hash_lookup (alpha_elf_hash_table (info),
416533965Sjdp						  name, false, false, true);
416633965Sjdp		  if (h == NULL || h->esym.ifd != -2)
416733965Sjdp		    continue;
416833965Sjdp
416933965Sjdp		  if (ext.ifd != -1)
417033965Sjdp		    {
417133965Sjdp		      BFD_ASSERT (ext.ifd
417233965Sjdp				  < input_debug.symbolic_header.ifdMax);
417333965Sjdp		      ext.ifd = input_debug.ifdmap[ext.ifd];
417433965Sjdp		    }
417533965Sjdp
417633965Sjdp		  h->esym = ext;
417733965Sjdp		}
417833965Sjdp
417933965Sjdp	      /* Free up the information we just read.  */
418033965Sjdp	      free (input_debug.line);
418133965Sjdp	      free (input_debug.external_dnr);
418233965Sjdp	      free (input_debug.external_pdr);
418333965Sjdp	      free (input_debug.external_sym);
418433965Sjdp	      free (input_debug.external_opt);
418533965Sjdp	      free (input_debug.external_aux);
418633965Sjdp	      free (input_debug.ss);
418733965Sjdp	      free (input_debug.ssext);
418833965Sjdp	      free (input_debug.external_fdr);
418933965Sjdp	      free (input_debug.external_rfd);
419033965Sjdp	      free (input_debug.external_ext);
419133965Sjdp
419233965Sjdp	      /* Hack: reset the SEC_HAS_CONTENTS flag so that
419333965Sjdp		 elf_link_input_bfd ignores this section.  */
419433965Sjdp	      input_section->flags &=~ SEC_HAS_CONTENTS;
419533965Sjdp	    }
419633965Sjdp
419733965Sjdp	  /* Build the external symbol information.  */
419833965Sjdp	  einfo.abfd = abfd;
419933965Sjdp	  einfo.info = info;
420033965Sjdp	  einfo.debug = &debug;
420133965Sjdp	  einfo.swap = swap;
420233965Sjdp	  einfo.failed = false;
420333965Sjdp	  elf_link_hash_traverse (elf_hash_table (info),
420433965Sjdp				  elf64_alpha_output_extsym,
420533965Sjdp				  (PTR) &einfo);
420633965Sjdp	  if (einfo.failed)
420733965Sjdp	    return false;
420833965Sjdp
420933965Sjdp	  /* Set the size of the .mdebug section.  */
421033965Sjdp	  o->_raw_size = bfd_ecoff_debug_size (abfd, &debug, swap);
421133965Sjdp
421233965Sjdp	  /* Skip this section later on (I don't think this currently
421333965Sjdp	     matters, but someday it might).  */
421433965Sjdp	  o->link_order_head = (struct bfd_link_order *) NULL;
421533965Sjdp
421633965Sjdp	  mdebug_sec = o;
421733965Sjdp	}
421833965Sjdp    }
421933965Sjdp
422033965Sjdp  /* Invoke the regular ELF backend linker to do all the work.  */
422133965Sjdp  if (! bfd_elf64_bfd_final_link (abfd, info))
422233965Sjdp    return false;
422333965Sjdp
422433965Sjdp  /* Now write out the computed sections.  */
422533965Sjdp
422633965Sjdp  /* The .got subsections...  */
422733965Sjdp  {
422833965Sjdp    bfd *i, *dynobj = elf_hash_table(info)->dynobj;
422933965Sjdp    for (i = alpha_elf_hash_table(info)->got_list;
423033965Sjdp	 i != NULL;
423133965Sjdp	 i = alpha_elf_tdata(i)->got_link_next)
423233965Sjdp      {
423333965Sjdp	asection *sgot;
423433965Sjdp
423533965Sjdp	/* elf_bfd_final_link already did everything in dynobj.  */
423633965Sjdp	if (i == dynobj)
423733965Sjdp	  continue;
423833965Sjdp
423933965Sjdp	sgot = alpha_elf_tdata(i)->got;
424033965Sjdp	if (! bfd_set_section_contents (abfd, sgot->output_section,
424189862Sobrien					sgot->contents,
424289862Sobrien					(file_ptr) sgot->output_offset,
424333965Sjdp					sgot->_raw_size))
424433965Sjdp	  return false;
424533965Sjdp      }
424633965Sjdp  }
424733965Sjdp
424833965Sjdp  if (mdebug_sec != (asection *) NULL)
424933965Sjdp    {
425033965Sjdp      BFD_ASSERT (abfd->output_has_begun);
425133965Sjdp      if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug,
425233965Sjdp					       swap, info,
425333965Sjdp					       mdebug_sec->filepos))
425433965Sjdp	return false;
425533965Sjdp
425633965Sjdp      bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info);
425733965Sjdp    }
425833965Sjdp
425989862Sobrien  return true;
426089862Sobrien}
426133965Sjdp
426289862Sobrienstatic enum elf_reloc_type_class
426389862Sobrienelf64_alpha_reloc_type_class (rela)
426489862Sobrien     const Elf_Internal_Rela *rela;
426589862Sobrien{
426689862Sobrien  switch ((int) ELF64_R_TYPE (rela->r_info))
426733965Sjdp    {
426889862Sobrien    case R_ALPHA_RELATIVE:
426989862Sobrien      return reloc_class_relative;
427089862Sobrien    case R_ALPHA_JMP_SLOT:
427189862Sobrien      return reloc_class_plt;
427289862Sobrien    case R_ALPHA_COPY:
427389862Sobrien      return reloc_class_copy;
427489862Sobrien    default:
427589862Sobrien      return reloc_class_normal;
427633965Sjdp    }
427733965Sjdp}
427833965Sjdp
427933965Sjdp/* ECOFF swapping routines.  These are used when dealing with the
428033965Sjdp   .mdebug section, which is in the ECOFF debugging format.  Copied
428177303Sobrien   from elf32-mips.c.  */
428233965Sjdpstatic const struct ecoff_debug_swap
428333965Sjdpelf64_alpha_ecoff_debug_swap =
428433965Sjdp{
428533965Sjdp  /* Symbol table magic number.  */
428633965Sjdp  magicSym2,
428733965Sjdp  /* Alignment of debugging information.  E.g., 4.  */
428833965Sjdp  8,
428933965Sjdp  /* Sizes of external symbolic information.  */
429033965Sjdp  sizeof (struct hdr_ext),
429133965Sjdp  sizeof (struct dnr_ext),
429233965Sjdp  sizeof (struct pdr_ext),
429333965Sjdp  sizeof (struct sym_ext),
429433965Sjdp  sizeof (struct opt_ext),
429533965Sjdp  sizeof (struct fdr_ext),
429633965Sjdp  sizeof (struct rfd_ext),
429733965Sjdp  sizeof (struct ext_ext),
429833965Sjdp  /* Functions to swap in external symbolic data.  */
429933965Sjdp  ecoff_swap_hdr_in,
430033965Sjdp  ecoff_swap_dnr_in,
430133965Sjdp  ecoff_swap_pdr_in,
430233965Sjdp  ecoff_swap_sym_in,
430333965Sjdp  ecoff_swap_opt_in,
430433965Sjdp  ecoff_swap_fdr_in,
430533965Sjdp  ecoff_swap_rfd_in,
430633965Sjdp  ecoff_swap_ext_in,
430733965Sjdp  _bfd_ecoff_swap_tir_in,
430833965Sjdp  _bfd_ecoff_swap_rndx_in,
430933965Sjdp  /* Functions to swap out external symbolic data.  */
431033965Sjdp  ecoff_swap_hdr_out,
431133965Sjdp  ecoff_swap_dnr_out,
431233965Sjdp  ecoff_swap_pdr_out,
431333965Sjdp  ecoff_swap_sym_out,
431433965Sjdp  ecoff_swap_opt_out,
431533965Sjdp  ecoff_swap_fdr_out,
431633965Sjdp  ecoff_swap_rfd_out,
431733965Sjdp  ecoff_swap_ext_out,
431833965Sjdp  _bfd_ecoff_swap_tir_out,
431933965Sjdp  _bfd_ecoff_swap_rndx_out,
432033965Sjdp  /* Function to read in symbolic data.  */
432133965Sjdp  elf64_alpha_read_ecoff_info
432233965Sjdp};
432333965Sjdp
432477303Sobrien/* Use a non-standard hash bucket size of 8.  */
432577303Sobrien
432677303Sobrienconst struct elf_size_info alpha_elf_size_info =
432777303Sobrien{
432877303Sobrien  sizeof (Elf64_External_Ehdr),
432977303Sobrien  sizeof (Elf64_External_Phdr),
433077303Sobrien  sizeof (Elf64_External_Shdr),
433177303Sobrien  sizeof (Elf64_External_Rel),
433277303Sobrien  sizeof (Elf64_External_Rela),
433377303Sobrien  sizeof (Elf64_External_Sym),
433477303Sobrien  sizeof (Elf64_External_Dyn),
433577303Sobrien  sizeof (Elf_External_Note),
433677303Sobrien  8,
433777303Sobrien  1,
433877303Sobrien  64, 8,
433977303Sobrien  ELFCLASS64, EV_CURRENT,
434077303Sobrien  bfd_elf64_write_out_phdrs,
434177303Sobrien  bfd_elf64_write_shdrs_and_ehdr,
434277303Sobrien  bfd_elf64_write_relocs,
434377303Sobrien  bfd_elf64_swap_symbol_out,
434477303Sobrien  bfd_elf64_slurp_reloc_table,
434577303Sobrien  bfd_elf64_slurp_symbol_table,
434677303Sobrien  bfd_elf64_swap_dyn_in,
434777303Sobrien  bfd_elf64_swap_dyn_out,
434877303Sobrien  NULL,
434977303Sobrien  NULL,
435077303Sobrien  NULL,
435177303Sobrien  NULL
435277303Sobrien};
435377303Sobrien
435433965Sjdp#define TARGET_LITTLE_SYM	bfd_elf64_alpha_vec
435533965Sjdp#define TARGET_LITTLE_NAME	"elf64-alpha"
435633965Sjdp#define ELF_ARCH		bfd_arch_alpha
435778833Sobrien#define ELF_MACHINE_CODE	EM_ALPHA
435878833Sobrien#define ELF_MAXPAGESIZE	0x10000
435933965Sjdp
436033965Sjdp#define bfd_elf64_bfd_link_hash_table_create \
436133965Sjdp  elf64_alpha_bfd_link_hash_table_create
436233965Sjdp
436333965Sjdp#define bfd_elf64_bfd_reloc_type_lookup \
436433965Sjdp  elf64_alpha_bfd_reloc_type_lookup
436533965Sjdp#define elf_info_to_howto \
436633965Sjdp  elf64_alpha_info_to_howto
436733965Sjdp
436833965Sjdp#define bfd_elf64_mkobject \
436933965Sjdp  elf64_alpha_mkobject
437033965Sjdp#define elf_backend_object_p \
437133965Sjdp  elf64_alpha_object_p
437233965Sjdp
437333965Sjdp#define elf_backend_section_from_shdr \
437433965Sjdp  elf64_alpha_section_from_shdr
437589862Sobrien#define elf_backend_section_flags \
437689862Sobrien  elf64_alpha_section_flags
437733965Sjdp#define elf_backend_fake_sections \
437833965Sjdp  elf64_alpha_fake_sections
437933965Sjdp
438033965Sjdp#define bfd_elf64_bfd_is_local_label_name \
438133965Sjdp  elf64_alpha_is_local_label_name
438233965Sjdp#define bfd_elf64_find_nearest_line \
438333965Sjdp  elf64_alpha_find_nearest_line
438460510Sobrien#define bfd_elf64_bfd_relax_section \
438560510Sobrien  elf64_alpha_relax_section
438633965Sjdp
438760510Sobrien#define elf_backend_add_symbol_hook \
438860510Sobrien  elf64_alpha_add_symbol_hook
438933965Sjdp#define elf_backend_check_relocs \
439033965Sjdp  elf64_alpha_check_relocs
439133965Sjdp#define elf_backend_create_dynamic_sections \
439233965Sjdp  elf64_alpha_create_dynamic_sections
439333965Sjdp#define elf_backend_adjust_dynamic_symbol \
439433965Sjdp  elf64_alpha_adjust_dynamic_symbol
439533965Sjdp#define elf_backend_always_size_sections \
439633965Sjdp  elf64_alpha_always_size_sections
439733965Sjdp#define elf_backend_size_dynamic_sections \
439833965Sjdp  elf64_alpha_size_dynamic_sections
439933965Sjdp#define elf_backend_relocate_section \
440033965Sjdp  elf64_alpha_relocate_section
440133965Sjdp#define elf_backend_finish_dynamic_symbol \
440233965Sjdp  elf64_alpha_finish_dynamic_symbol
440333965Sjdp#define elf_backend_finish_dynamic_sections \
440433965Sjdp  elf64_alpha_finish_dynamic_sections
440533965Sjdp#define bfd_elf64_bfd_final_link \
440633965Sjdp  elf64_alpha_final_link
440789862Sobrien#define elf_backend_reloc_type_class \
440889862Sobrien  elf64_alpha_reloc_type_class
440933965Sjdp
441033965Sjdp#define elf_backend_ecoff_debug_swap \
441133965Sjdp  &elf64_alpha_ecoff_debug_swap
441233965Sjdp
441377303Sobrien#define elf_backend_size_info \
441477303Sobrien  alpha_elf_size_info
441577303Sobrien
441677303Sobrien/* A few constants that determine how the .plt section is set up.  */
441733965Sjdp#define elf_backend_want_got_plt 0
441833965Sjdp#define elf_backend_plt_readonly 0
441933965Sjdp#define elf_backend_want_plt_sym 1
442060510Sobrien#define elf_backend_got_header_size 0
442160510Sobrien#define elf_backend_plt_header_size PLT_HEADER_SIZE
442233965Sjdp
442333965Sjdp#include "elf64-target.h"
4424