elf64-alpha.c revision 115361
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
22115361Sobrien/* $FreeBSD: head/contrib/binutils/bfd/elf64-alpha.c 115361 2003-05-28 03:32:33Z obrien $ */
23115361Sobrien
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
78104841Sobrien  PARAMS((bfd *, Elf64_Internal_Shdr *, const 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
111104841Sobrien  PARAMS ((struct bfd_link_info *));
112104841Sobrienstatic boolean elf64_alpha_size_plt_section
113104841Sobrien  PARAMS ((struct bfd_link_info *));
114104841Sobrienstatic boolean elf64_alpha_size_plt_section_1
115104841Sobrien  PARAMS ((struct alpha_elf_link_hash_entry *, PTR));
11633965Sjdpstatic boolean elf64_alpha_always_size_sections
11733965Sjdp  PARAMS ((bfd *, struct bfd_link_info *));
118104841Sobrienstatic int alpha_dynamic_entries_for_reloc
119104841Sobrien  PARAMS ((int, int, int));
12033965Sjdpstatic boolean elf64_alpha_calc_dynrel_sizes
12133965Sjdp  PARAMS ((struct alpha_elf_link_hash_entry *, struct bfd_link_info *));
122104841Sobrienstatic boolean elf64_alpha_size_rela_got_section
123104841Sobrien  PARAMS ((struct bfd_link_info *));
124104841Sobrienstatic boolean elf64_alpha_size_rela_got_1
125104841Sobrien  PARAMS ((struct alpha_elf_link_hash_entry *, struct bfd_link_info *));
12660510Sobrienstatic boolean elf64_alpha_add_symbol_hook
12760510Sobrien  PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
12860510Sobrien	   const char **, flagword *, asection **, bfd_vma *));
129104841Sobrienstatic struct alpha_elf_got_entry *get_got_entry
130104841Sobrien  PARAMS ((bfd *, struct alpha_elf_link_hash_entry *, unsigned long,
131104841Sobrien	   unsigned long, bfd_vma));
13233965Sjdpstatic boolean elf64_alpha_check_relocs
13333965Sjdp  PARAMS((bfd *, struct bfd_link_info *, asection *sec,
13433965Sjdp	  const Elf_Internal_Rela *));
13533965Sjdpstatic boolean elf64_alpha_adjust_dynamic_symbol
13633965Sjdp  PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *));
13733965Sjdpstatic boolean elf64_alpha_size_dynamic_sections
13833965Sjdp  PARAMS((bfd *, struct bfd_link_info *));
139104841Sobrienstatic boolean elf64_alpha_relocate_section_r
140104841Sobrien  PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
141104841Sobrien	  Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
14233965Sjdpstatic boolean elf64_alpha_relocate_section
14333965Sjdp  PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
14433965Sjdp	  Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
14533965Sjdpstatic boolean elf64_alpha_finish_dynamic_symbol
14633965Sjdp  PARAMS((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
14733965Sjdp	  Elf_Internal_Sym *));
14833965Sjdpstatic boolean elf64_alpha_finish_dynamic_sections
14933965Sjdp  PARAMS((bfd *, struct bfd_link_info *));
15033965Sjdpstatic boolean elf64_alpha_final_link
15133965Sjdp  PARAMS((bfd *, struct bfd_link_info *));
15248850Sdfrstatic boolean elf64_alpha_merge_ind_symbols
15348850Sdfr  PARAMS((struct alpha_elf_link_hash_entry *, PTR));
15460510Sobrienstatic Elf_Internal_Rela * elf64_alpha_find_reloc_at_ofs
15560510Sobrien  PARAMS ((Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_vma, int));
15689862Sobrienstatic enum elf_reloc_type_class elf64_alpha_reloc_type_class
15789862Sobrien  PARAMS ((const Elf_Internal_Rela *));
15833965Sjdp
15933965Sjdpstruct alpha_elf_link_hash_entry
16033965Sjdp{
16133965Sjdp  struct elf_link_hash_entry root;
16233965Sjdp
16333965Sjdp  /* External symbol information.  */
16433965Sjdp  EXTR esym;
16533965Sjdp
16633965Sjdp  /* Cumulative flags for all the .got entries.  */
16733965Sjdp  int flags;
16833965Sjdp
169104841Sobrien  /* Contexts in which a literal was referenced.  */
170104841Sobrien#define ALPHA_ELF_LINK_HASH_LU_ADDR	0x01
171104841Sobrien#define ALPHA_ELF_LINK_HASH_LU_MEM	0x02
172104841Sobrien#define ALPHA_ELF_LINK_HASH_LU_BYTE	0x04
173104841Sobrien#define ALPHA_ELF_LINK_HASH_LU_JSR	0x08
174104841Sobrien#define ALPHA_ELF_LINK_HASH_LU_TLSGD	0x10
175104841Sobrien#define ALPHA_ELF_LINK_HASH_LU_TLSLDM	0x20
176104841Sobrien#define ALPHA_ELF_LINK_HASH_LU_FUNC	0x38
177104841Sobrien#define ALPHA_ELF_LINK_HASH_TLS_IE	0x40
17833965Sjdp
17933965Sjdp  /* Used to implement multiple .got subsections.  */
18033965Sjdp  struct alpha_elf_got_entry
18133965Sjdp  {
18233965Sjdp    struct alpha_elf_got_entry *next;
18333965Sjdp
18433965Sjdp    /* which .got subsection?  */
18533965Sjdp    bfd *gotobj;
18633965Sjdp
18733965Sjdp    /* the addend in effect for this entry.  */
18833965Sjdp    bfd_vma addend;
18933965Sjdp
19033965Sjdp    /* the .got offset for this entry.  */
19133965Sjdp    int got_offset;
19233965Sjdp
193104841Sobrien    /* How many references to this entry?  */
194104841Sobrien    int use_count;
19533965Sjdp
196104841Sobrien    /* The relocation type of this entry.  */
197104841Sobrien    unsigned char reloc_type;
19860510Sobrien
199104841Sobrien    /* How a LITERAL is used.  */
200104841Sobrien    unsigned char flags;
201104841Sobrien
202104841Sobrien    /* Have we initialized the dynamic relocation for this entry?  */
203104841Sobrien    unsigned char reloc_done;
204104841Sobrien
205104841Sobrien    /* Have we adjusted this entry for SEC_MERGE?  */
206104841Sobrien    unsigned char reloc_xlated;
20733965Sjdp  } *got_entries;
20833965Sjdp
20933965Sjdp  /* used to count non-got, non-plt relocations for delayed sizing
21033965Sjdp     of relocation sections.  */
21133965Sjdp  struct alpha_elf_reloc_entry
21233965Sjdp  {
21333965Sjdp    struct alpha_elf_reloc_entry *next;
21433965Sjdp
21533965Sjdp    /* which .reloc section? */
21633965Sjdp    asection *srel;
21733965Sjdp
21833965Sjdp    /* what kind of relocation? */
21989862Sobrien    unsigned int rtype;
22033965Sjdp
22189862Sobrien    /* is this against read-only section? */
22289862Sobrien    unsigned int reltext : 1;
22389862Sobrien
22433965Sjdp    /* how many did we find?  */
22533965Sjdp    unsigned long count;
22633965Sjdp  } *reloc_entries;
22733965Sjdp};
22833965Sjdp
22933965Sjdp/* Alpha ELF linker hash table.  */
23033965Sjdp
23133965Sjdpstruct alpha_elf_link_hash_table
23233965Sjdp{
23333965Sjdp  struct elf_link_hash_table root;
23433965Sjdp
23533965Sjdp  /* The head of a list of .got subsections linked through
23633965Sjdp     alpha_elf_tdata(abfd)->got_link_next.  */
23733965Sjdp  bfd *got_list;
23833965Sjdp};
23933965Sjdp
24033965Sjdp/* Look up an entry in a Alpha ELF linker hash table.  */
24133965Sjdp
24233965Sjdp#define alpha_elf_link_hash_lookup(table, string, create, copy, follow)	\
24333965Sjdp  ((struct alpha_elf_link_hash_entry *)					\
24433965Sjdp   elf_link_hash_lookup (&(table)->root, (string), (create),		\
24533965Sjdp			 (copy), (follow)))
24633965Sjdp
24733965Sjdp/* Traverse a Alpha ELF linker hash table.  */
24833965Sjdp
24933965Sjdp#define alpha_elf_link_hash_traverse(table, func, info)			\
25033965Sjdp  (elf_link_hash_traverse						\
25133965Sjdp   (&(table)->root,							\
25233965Sjdp    (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func),	\
25333965Sjdp    (info)))
25433965Sjdp
25533965Sjdp/* Get the Alpha ELF linker hash table from a link_info structure.  */
25633965Sjdp
25733965Sjdp#define alpha_elf_hash_table(p) \
25833965Sjdp  ((struct alpha_elf_link_hash_table *) ((p)->hash))
25933965Sjdp
26033965Sjdp/* Get the object's symbols as our own entry type.  */
26133965Sjdp
26233965Sjdp#define alpha_elf_sym_hashes(abfd) \
26333965Sjdp  ((struct alpha_elf_link_hash_entry **)elf_sym_hashes(abfd))
26433965Sjdp
26533965Sjdp/* Should we do dynamic things to this symbol?  */
26633965Sjdp
26777303Sobrienstatic int
26877303Sobrienalpha_elf_dynamic_symbol_p (h, info)
26977303Sobrien     struct elf_link_hash_entry *h;
27077303Sobrien     struct bfd_link_info *info;
27177303Sobrien{
27277303Sobrien  if (h == NULL)
27377303Sobrien    return false;
27433965Sjdp
27577303Sobrien  while (h->root.type == bfd_link_hash_indirect
27677303Sobrien	 || h->root.type == bfd_link_hash_warning)
27777303Sobrien    h = (struct elf_link_hash_entry *) h->root.u.i.link;
27877303Sobrien
27977303Sobrien  if (h->dynindx == -1)
28077303Sobrien    return false;
28177303Sobrien
28277303Sobrien  if (h->root.type == bfd_link_hash_undefweak
28377303Sobrien      || h->root.type == bfd_link_hash_defweak)
28477303Sobrien    return true;
28577303Sobrien
28678833Sobrien  switch (ELF_ST_VISIBILITY (h->other))
28778833Sobrien    {
28878833Sobrien    case STV_DEFAULT:
28978833Sobrien      break;
29078833Sobrien    case STV_HIDDEN:
29178833Sobrien    case STV_INTERNAL:
29278833Sobrien      return false;
29378833Sobrien    case STV_PROTECTED:
29478833Sobrien      if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
29578833Sobrien        return false;
29678833Sobrien      break;
29778833Sobrien    }
29878833Sobrien
29977303Sobrien  if ((info->shared && !info->symbolic)
30077303Sobrien      || ((h->elf_link_hash_flags
30177303Sobrien	   & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))
30277303Sobrien	  == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)))
30377303Sobrien    return true;
30477303Sobrien
30577303Sobrien  return false;
30677303Sobrien}
30777303Sobrien
30833965Sjdp/* Create an entry in a Alpha ELF linker hash table.  */
30933965Sjdp
31033965Sjdpstatic struct bfd_hash_entry *
31133965Sjdpelf64_alpha_link_hash_newfunc (entry, table, string)
31233965Sjdp     struct bfd_hash_entry *entry;
31333965Sjdp     struct bfd_hash_table *table;
31433965Sjdp     const char *string;
31533965Sjdp{
31633965Sjdp  struct alpha_elf_link_hash_entry *ret =
31733965Sjdp    (struct alpha_elf_link_hash_entry *) entry;
31833965Sjdp
31933965Sjdp  /* Allocate the structure if it has not already been allocated by a
32033965Sjdp     subclass.  */
32133965Sjdp  if (ret == (struct alpha_elf_link_hash_entry *) NULL)
32233965Sjdp    ret = ((struct alpha_elf_link_hash_entry *)
32333965Sjdp	   bfd_hash_allocate (table,
32433965Sjdp			      sizeof (struct alpha_elf_link_hash_entry)));
32533965Sjdp  if (ret == (struct alpha_elf_link_hash_entry *) NULL)
32633965Sjdp    return (struct bfd_hash_entry *) ret;
32733965Sjdp
32833965Sjdp  /* Call the allocation method of the superclass.  */
32933965Sjdp  ret = ((struct alpha_elf_link_hash_entry *)
33033965Sjdp	 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
33133965Sjdp				     table, string));
33233965Sjdp  if (ret != (struct alpha_elf_link_hash_entry *) NULL)
33333965Sjdp    {
33433965Sjdp      /* Set local fields.  */
33533965Sjdp      memset (&ret->esym, 0, sizeof (EXTR));
33633965Sjdp      /* We use -2 as a marker to indicate that the information has
33733965Sjdp	 not been set.  -1 means there is no associated ifd.  */
33833965Sjdp      ret->esym.ifd = -2;
33933965Sjdp      ret->flags = 0;
34033965Sjdp      ret->got_entries = NULL;
34133965Sjdp      ret->reloc_entries = NULL;
34233965Sjdp    }
34333965Sjdp
34433965Sjdp  return (struct bfd_hash_entry *) ret;
34533965Sjdp}
34633965Sjdp
34733965Sjdp/* Create a Alpha ELF linker hash table.  */
34833965Sjdp
34933965Sjdpstatic struct bfd_link_hash_table *
35033965Sjdpelf64_alpha_bfd_link_hash_table_create (abfd)
35133965Sjdp     bfd *abfd;
35233965Sjdp{
35333965Sjdp  struct alpha_elf_link_hash_table *ret;
35489862Sobrien  bfd_size_type amt = sizeof (struct alpha_elf_link_hash_table);
35533965Sjdp
356104841Sobrien  ret = (struct alpha_elf_link_hash_table *) bfd_zmalloc (amt);
35733965Sjdp  if (ret == (struct alpha_elf_link_hash_table *) NULL)
35833965Sjdp    return NULL;
35933965Sjdp
36033965Sjdp  if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
36133965Sjdp				       elf64_alpha_link_hash_newfunc))
36233965Sjdp    {
363104841Sobrien      free (ret);
36433965Sjdp      return NULL;
36533965Sjdp    }
36633965Sjdp
36733965Sjdp  return &ret->root.root;
36833965Sjdp}
36933965Sjdp
37033965Sjdp/* We have some private fields hanging off of the elf_tdata structure.  */
37133965Sjdp
37233965Sjdpstruct alpha_elf_obj_tdata
37333965Sjdp{
37433965Sjdp  struct elf_obj_tdata root;
37533965Sjdp
37633965Sjdp  /* For every input file, these are the got entries for that object's
37733965Sjdp     local symbols.  */
37833965Sjdp  struct alpha_elf_got_entry ** local_got_entries;
37933965Sjdp
38033965Sjdp  /* For every input file, this is the object that owns the got that
38133965Sjdp     this input file uses.  */
38233965Sjdp  bfd *gotobj;
38333965Sjdp
38433965Sjdp  /* For every got, this is a linked list through the objects using this got */
38533965Sjdp  bfd *in_got_link_next;
38633965Sjdp
38733965Sjdp  /* For every got, this is a link to the next got subsegment.  */
38833965Sjdp  bfd *got_link_next;
38933965Sjdp
39033965Sjdp  /* For every got, this is the section.  */
39133965Sjdp  asection *got;
39233965Sjdp
393104841Sobrien  /* For every got, this is it's total number of words.  */
394104841Sobrien  int total_got_size;
39533965Sjdp
396104841Sobrien  /* For every got, this is the sum of the number of words required
39733965Sjdp     to hold all of the member object's local got.  */
398104841Sobrien  int local_got_size;
39933965Sjdp};
40033965Sjdp
40133965Sjdp#define alpha_elf_tdata(abfd) \
40233965Sjdp  ((struct alpha_elf_obj_tdata *) (abfd)->tdata.any)
40333965Sjdp
40433965Sjdpstatic boolean
40533965Sjdpelf64_alpha_mkobject (abfd)
40633965Sjdp     bfd *abfd;
40733965Sjdp{
40889862Sobrien  bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata);
40989862Sobrien  abfd->tdata.any = bfd_zalloc (abfd, amt);
41033965Sjdp  if (abfd->tdata.any == NULL)
41133965Sjdp    return false;
41233965Sjdp  return true;
41333965Sjdp}
41433965Sjdp
41533965Sjdpstatic boolean
41633965Sjdpelf64_alpha_object_p (abfd)
41733965Sjdp     bfd *abfd;
41833965Sjdp{
41933965Sjdp  /* Allocate our special target data.  */
42033965Sjdp  struct alpha_elf_obj_tdata *new_tdata;
42189862Sobrien  bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata);
42289862Sobrien  new_tdata = bfd_zalloc (abfd, amt);
42333965Sjdp  if (new_tdata == NULL)
42433965Sjdp    return false;
42533965Sjdp  new_tdata->root = *abfd->tdata.elf_obj_data;
42633965Sjdp  abfd->tdata.any = new_tdata;
42733965Sjdp
42833965Sjdp  /* Set the right machine number for an Alpha ELF file.  */
42933965Sjdp  return bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0);
43033965Sjdp}
43133965Sjdp
43233965Sjdp/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
43333965Sjdp   from smaller values.  Start with zero, widen, *then* decrement.  */
43433965Sjdp#define MINUS_ONE	(((bfd_vma)0) - 1)
43533965Sjdp
43689862Sobrien#define SKIP_HOWTO(N) \
43789862Sobrien  HOWTO(N, 0, 0, 0, 0, 0, 0, elf64_alpha_reloc_bad, 0, 0, 0, 0, 0)
43889862Sobrien
43933965Sjdpstatic reloc_howto_type elf64_alpha_howto_table[] =
44033965Sjdp{
44133965Sjdp  HOWTO (R_ALPHA_NONE,		/* type */
44233965Sjdp	 0,			/* rightshift */
44333965Sjdp	 0,			/* size (0 = byte, 1 = short, 2 = long) */
44433965Sjdp	 8,			/* bitsize */
44533965Sjdp	 true,			/* pc_relative */
44633965Sjdp	 0,			/* bitpos */
44733965Sjdp	 complain_overflow_dont, /* complain_on_overflow */
44833965Sjdp	 elf64_alpha_reloc_nil,	/* special_function */
44933965Sjdp	 "NONE",		/* name */
45033965Sjdp	 false,			/* partial_inplace */
45133965Sjdp	 0,			/* src_mask */
45233965Sjdp	 0,			/* dst_mask */
45333965Sjdp	 true),			/* pcrel_offset */
45433965Sjdp
45533965Sjdp  /* A 32 bit reference to a symbol.  */
45633965Sjdp  HOWTO (R_ALPHA_REFLONG,	/* type */
45733965Sjdp	 0,			/* rightshift */
45833965Sjdp	 2,			/* size (0 = byte, 1 = short, 2 = long) */
45933965Sjdp	 32,			/* bitsize */
46033965Sjdp	 false,			/* pc_relative */
46133965Sjdp	 0,			/* bitpos */
46233965Sjdp	 complain_overflow_bitfield, /* complain_on_overflow */
46333965Sjdp	 0,			/* special_function */
46433965Sjdp	 "REFLONG",		/* name */
46533965Sjdp	 false,			/* partial_inplace */
46633965Sjdp	 0xffffffff,		/* src_mask */
46733965Sjdp	 0xffffffff,		/* dst_mask */
46833965Sjdp	 false),		/* pcrel_offset */
46933965Sjdp
47033965Sjdp  /* A 64 bit reference to a symbol.  */
47133965Sjdp  HOWTO (R_ALPHA_REFQUAD,	/* type */
47233965Sjdp	 0,			/* rightshift */
47333965Sjdp	 4,			/* size (0 = byte, 1 = short, 2 = long) */
47433965Sjdp	 64,			/* bitsize */
47533965Sjdp	 false,			/* pc_relative */
47633965Sjdp	 0,			/* bitpos */
47733965Sjdp	 complain_overflow_bitfield, /* complain_on_overflow */
47833965Sjdp	 0,			/* special_function */
47933965Sjdp	 "REFQUAD",		/* name */
48033965Sjdp	 false,			/* partial_inplace */
48133965Sjdp	 MINUS_ONE,		/* src_mask */
48233965Sjdp	 MINUS_ONE,		/* dst_mask */
48333965Sjdp	 false),		/* pcrel_offset */
48433965Sjdp
48533965Sjdp  /* A 32 bit GP relative offset.  This is just like REFLONG except
48633965Sjdp     that when the value is used the value of the gp register will be
48733965Sjdp     added in.  */
48833965Sjdp  HOWTO (R_ALPHA_GPREL32,	/* type */
48933965Sjdp	 0,			/* rightshift */
49033965Sjdp	 2,			/* size (0 = byte, 1 = short, 2 = long) */
49133965Sjdp	 32,			/* bitsize */
49233965Sjdp	 false,			/* pc_relative */
49333965Sjdp	 0,			/* bitpos */
49433965Sjdp	 complain_overflow_bitfield, /* complain_on_overflow */
49533965Sjdp	 0,			/* special_function */
49633965Sjdp	 "GPREL32",		/* name */
49733965Sjdp	 false,			/* partial_inplace */
49833965Sjdp	 0xffffffff,		/* src_mask */
49933965Sjdp	 0xffffffff,		/* dst_mask */
50033965Sjdp	 false),		/* pcrel_offset */
50133965Sjdp
50233965Sjdp  /* Used for an instruction that refers to memory off the GP register.  */
50333965Sjdp  HOWTO (R_ALPHA_LITERAL,	/* type */
50433965Sjdp	 0,			/* rightshift */
50589862Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
50633965Sjdp	 16,			/* bitsize */
50733965Sjdp	 false,			/* pc_relative */
50833965Sjdp	 0,			/* bitpos */
50933965Sjdp	 complain_overflow_signed, /* complain_on_overflow */
51033965Sjdp	 0,			/* special_function */
51133965Sjdp	 "ELF_LITERAL",		/* name */
51233965Sjdp	 false,			/* partial_inplace */
51333965Sjdp	 0xffff,		/* src_mask */
51433965Sjdp	 0xffff,		/* dst_mask */
51533965Sjdp	 false),		/* pcrel_offset */
51633965Sjdp
51733965Sjdp  /* This reloc only appears immediately following an ELF_LITERAL reloc.
51833965Sjdp     It identifies a use of the literal.  The symbol index is special:
51933965Sjdp     1 means the literal address is in the base register of a memory
52033965Sjdp     format instruction; 2 means the literal address is in the byte
52133965Sjdp     offset register of a byte-manipulation instruction; 3 means the
52233965Sjdp     literal address is in the target register of a jsr instruction.
52333965Sjdp     This does not actually do any relocation.  */
52433965Sjdp  HOWTO (R_ALPHA_LITUSE,	/* type */
52533965Sjdp	 0,			/* rightshift */
52689862Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
52733965Sjdp	 32,			/* bitsize */
52833965Sjdp	 false,			/* pc_relative */
52933965Sjdp	 0,			/* bitpos */
53033965Sjdp	 complain_overflow_dont, /* complain_on_overflow */
53133965Sjdp	 elf64_alpha_reloc_nil,	/* special_function */
53233965Sjdp	 "LITUSE",		/* name */
53333965Sjdp	 false,			/* partial_inplace */
53433965Sjdp	 0,			/* src_mask */
53533965Sjdp	 0,			/* dst_mask */
53633965Sjdp	 false),		/* pcrel_offset */
53733965Sjdp
53833965Sjdp  /* Load the gp register.  This is always used for a ldah instruction
53933965Sjdp     which loads the upper 16 bits of the gp register.  The symbol
54033965Sjdp     index of the GPDISP instruction is an offset in bytes to the lda
54133965Sjdp     instruction that loads the lower 16 bits.  The value to use for
54233965Sjdp     the relocation is the difference between the GP value and the
54333965Sjdp     current location; the load will always be done against a register
54433965Sjdp     holding the current address.
54533965Sjdp
54633965Sjdp     NOTE: Unlike ECOFF, partial in-place relocation is not done.  If
54733965Sjdp     any offset is present in the instructions, it is an offset from
54833965Sjdp     the register to the ldah instruction.  This lets us avoid any
54933965Sjdp     stupid hackery like inventing a gp value to do partial relocation
55033965Sjdp     against.  Also unlike ECOFF, we do the whole relocation off of
55133965Sjdp     the GPDISP rather than a GPDISP_HI16/GPDISP_LO16 pair.  An odd,
55233965Sjdp     space consuming bit, that, since all the information was present
55333965Sjdp     in the GPDISP_HI16 reloc.  */
55433965Sjdp  HOWTO (R_ALPHA_GPDISP,	/* type */
55533965Sjdp	 16,			/* rightshift */
55633965Sjdp	 2,			/* size (0 = byte, 1 = short, 2 = long) */
55733965Sjdp	 16,			/* bitsize */
55833965Sjdp	 false,			/* pc_relative */
55933965Sjdp	 0,			/* bitpos */
56033965Sjdp	 complain_overflow_dont, /* complain_on_overflow */
56133965Sjdp	 elf64_alpha_reloc_gpdisp, /* special_function */
56233965Sjdp	 "GPDISP",		/* name */
56333965Sjdp	 false,			/* partial_inplace */
56433965Sjdp	 0xffff,		/* src_mask */
56533965Sjdp	 0xffff,		/* dst_mask */
56633965Sjdp	 true),			/* pcrel_offset */
56733965Sjdp
56833965Sjdp  /* A 21 bit branch.  */
56933965Sjdp  HOWTO (R_ALPHA_BRADDR,	/* type */
57033965Sjdp	 2,			/* rightshift */
57133965Sjdp	 2,			/* size (0 = byte, 1 = short, 2 = long) */
57233965Sjdp	 21,			/* bitsize */
57333965Sjdp	 true,			/* pc_relative */
57433965Sjdp	 0,			/* bitpos */
57533965Sjdp	 complain_overflow_signed, /* complain_on_overflow */
57633965Sjdp	 0,			/* special_function */
57733965Sjdp	 "BRADDR",		/* name */
57833965Sjdp	 false,			/* partial_inplace */
57933965Sjdp	 0x1fffff,		/* src_mask */
58033965Sjdp	 0x1fffff,		/* dst_mask */
58133965Sjdp	 true),			/* pcrel_offset */
58233965Sjdp
58333965Sjdp  /* A hint for a jump to a register.  */
58433965Sjdp  HOWTO (R_ALPHA_HINT,		/* type */
58533965Sjdp	 2,			/* rightshift */
58689862Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
58733965Sjdp	 14,			/* bitsize */
58833965Sjdp	 true,			/* pc_relative */
58933965Sjdp	 0,			/* bitpos */
59033965Sjdp	 complain_overflow_dont, /* complain_on_overflow */
59133965Sjdp	 0,			/* special_function */
59233965Sjdp	 "HINT",		/* name */
59333965Sjdp	 false,			/* partial_inplace */
59433965Sjdp	 0x3fff,		/* src_mask */
59533965Sjdp	 0x3fff,		/* dst_mask */
59633965Sjdp	 true),			/* pcrel_offset */
59733965Sjdp
59833965Sjdp  /* 16 bit PC relative offset.  */
59933965Sjdp  HOWTO (R_ALPHA_SREL16,	/* type */
60033965Sjdp	 0,			/* rightshift */
60133965Sjdp	 1,			/* size (0 = byte, 1 = short, 2 = long) */
60233965Sjdp	 16,			/* bitsize */
60333965Sjdp	 true,			/* pc_relative */
60433965Sjdp	 0,			/* bitpos */
60533965Sjdp	 complain_overflow_signed, /* complain_on_overflow */
60633965Sjdp	 0,			/* special_function */
60733965Sjdp	 "SREL16",		/* name */
60833965Sjdp	 false,			/* partial_inplace */
60933965Sjdp	 0xffff,		/* src_mask */
61033965Sjdp	 0xffff,		/* dst_mask */
61178833Sobrien	 true),			/* pcrel_offset */
61233965Sjdp
61333965Sjdp  /* 32 bit PC relative offset.  */
61433965Sjdp  HOWTO (R_ALPHA_SREL32,	/* type */
61533965Sjdp	 0,			/* rightshift */
61633965Sjdp	 2,			/* size (0 = byte, 1 = short, 2 = long) */
61733965Sjdp	 32,			/* bitsize */
61833965Sjdp	 true,			/* pc_relative */
61933965Sjdp	 0,			/* bitpos */
62033965Sjdp	 complain_overflow_signed, /* complain_on_overflow */
62133965Sjdp	 0,			/* special_function */
62233965Sjdp	 "SREL32",		/* name */
62333965Sjdp	 false,			/* partial_inplace */
62433965Sjdp	 0xffffffff,		/* src_mask */
62533965Sjdp	 0xffffffff,		/* dst_mask */
62678833Sobrien	 true),			/* pcrel_offset */
62733965Sjdp
62833965Sjdp  /* A 64 bit PC relative offset.  */
62933965Sjdp  HOWTO (R_ALPHA_SREL64,	/* type */
63033965Sjdp	 0,			/* rightshift */
63133965Sjdp	 4,			/* size (0 = byte, 1 = short, 2 = long) */
63233965Sjdp	 64,			/* bitsize */
63333965Sjdp	 true,			/* pc_relative */
63433965Sjdp	 0,			/* bitpos */
63533965Sjdp	 complain_overflow_signed, /* complain_on_overflow */
63633965Sjdp	 0,			/* special_function */
63733965Sjdp	 "SREL64",		/* name */
63833965Sjdp	 false,			/* partial_inplace */
63933965Sjdp	 MINUS_ONE,		/* src_mask */
64033965Sjdp	 MINUS_ONE,		/* dst_mask */
64178833Sobrien	 true),			/* pcrel_offset */
64233965Sjdp
64389862Sobrien  /* Skip 12 - 16; deprecated ECOFF relocs.  */
64489862Sobrien  SKIP_HOWTO (12),
64589862Sobrien  SKIP_HOWTO (13),
64689862Sobrien  SKIP_HOWTO (14),
64789862Sobrien  SKIP_HOWTO (15),
64889862Sobrien  SKIP_HOWTO (16),
64933965Sjdp
65038889Sjdp  /* The high 16 bits of the displacement from GP to the target.  */
65138889Sjdp  HOWTO (R_ALPHA_GPRELHIGH,
65238889Sjdp	 0,			/* rightshift */
65389862Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
65460510Sobrien	 16,			/* bitsize */
65538889Sjdp	 false,			/* pc_relative */
65638889Sjdp	 0,			/* bitpos */
65760510Sobrien	 complain_overflow_signed, /* complain_on_overflow */
65889862Sobrien	 0,			/* special_function */
65938889Sjdp	 "GPRELHIGH",		/* name */
66038889Sjdp	 false,			/* partial_inplace */
66160510Sobrien	 0xffff,		/* src_mask */
66260510Sobrien	 0xffff,		/* dst_mask */
66338889Sjdp	 false),		/* pcrel_offset */
66438889Sjdp
66538889Sjdp  /* The low 16 bits of the displacement from GP to the target.  */
66638889Sjdp  HOWTO (R_ALPHA_GPRELLOW,
66738889Sjdp	 0,			/* rightshift */
66889862Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
66960510Sobrien	 16,			/* bitsize */
67038889Sjdp	 false,			/* pc_relative */
67138889Sjdp	 0,			/* bitpos */
67238889Sjdp	 complain_overflow_dont, /* complain_on_overflow */
67389862Sobrien	 0,			/* special_function */
67438889Sjdp	 "GPRELLOW",		/* name */
67538889Sjdp	 false,			/* partial_inplace */
67660510Sobrien	 0xffff,		/* src_mask */
67760510Sobrien	 0xffff,		/* dst_mask */
67838889Sjdp	 false),		/* pcrel_offset */
67938889Sjdp
68038889Sjdp  /* A 16-bit displacement from the GP to the target.  */
68189862Sobrien  HOWTO (R_ALPHA_GPREL16,
68238889Sjdp	 0,			/* rightshift */
68389862Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
68460510Sobrien	 16,			/* bitsize */
68538889Sjdp	 false,			/* pc_relative */
68638889Sjdp	 0,			/* bitpos */
68760510Sobrien	 complain_overflow_signed, /* complain_on_overflow */
68860510Sobrien	 0,			/* special_function */
68989862Sobrien	 "GPREL16",		/* name */
69038889Sjdp	 false,			/* partial_inplace */
69160510Sobrien	 0xffff,		/* src_mask */
69260510Sobrien	 0xffff,		/* dst_mask */
69338889Sjdp	 false),		/* pcrel_offset */
69438889Sjdp
69589862Sobrien  /* Skip 20 - 23; deprecated ECOFF relocs.  */
69689862Sobrien  SKIP_HOWTO (20),
69789862Sobrien  SKIP_HOWTO (21),
69889862Sobrien  SKIP_HOWTO (22),
69989862Sobrien  SKIP_HOWTO (23),
70038889Sjdp
70177303Sobrien  /* Misc ELF relocations.  */
70238889Sjdp
70338889Sjdp  /* A dynamic relocation to copy the target into our .dynbss section.  */
70438889Sjdp  /* Not generated, as all Alpha objects use PIC, so it is not needed.  It
70538889Sjdp     is present because every other ELF has one, but should not be used
70638889Sjdp     because .dynbss is an ugly thing.  */
70733965Sjdp  HOWTO (R_ALPHA_COPY,
70833965Sjdp	 0,
70933965Sjdp	 0,
71033965Sjdp	 0,
71133965Sjdp	 false,
71233965Sjdp	 0,
71333965Sjdp	 complain_overflow_dont,
71433965Sjdp	 bfd_elf_generic_reloc,
71533965Sjdp	 "COPY",
71633965Sjdp	 false,
71733965Sjdp	 0,
71833965Sjdp	 0,
71933965Sjdp	 true),
72033965Sjdp
72138889Sjdp  /* A dynamic relocation for a .got entry.  */
72233965Sjdp  HOWTO (R_ALPHA_GLOB_DAT,
72333965Sjdp	 0,
72433965Sjdp	 0,
72533965Sjdp	 0,
72633965Sjdp	 false,
72733965Sjdp	 0,
72833965Sjdp	 complain_overflow_dont,
72933965Sjdp	 bfd_elf_generic_reloc,
73033965Sjdp	 "GLOB_DAT",
73133965Sjdp	 false,
73233965Sjdp	 0,
73333965Sjdp	 0,
73433965Sjdp	 true),
73533965Sjdp
73638889Sjdp  /* A dynamic relocation for a .plt entry.  */
73733965Sjdp  HOWTO (R_ALPHA_JMP_SLOT,
73833965Sjdp	 0,
73933965Sjdp	 0,
74033965Sjdp	 0,
74133965Sjdp	 false,
74233965Sjdp	 0,
74333965Sjdp	 complain_overflow_dont,
74433965Sjdp	 bfd_elf_generic_reloc,
74533965Sjdp	 "JMP_SLOT",
74633965Sjdp	 false,
74733965Sjdp	 0,
74833965Sjdp	 0,
74933965Sjdp	 true),
75033965Sjdp
75138889Sjdp  /* A dynamic relocation to add the base of the DSO to a 64-bit field.  */
75233965Sjdp  HOWTO (R_ALPHA_RELATIVE,
75333965Sjdp	 0,
75433965Sjdp	 0,
75533965Sjdp	 0,
75633965Sjdp	 false,
75733965Sjdp	 0,
75833965Sjdp	 complain_overflow_dont,
75933965Sjdp	 bfd_elf_generic_reloc,
76033965Sjdp	 "RELATIVE",
76133965Sjdp	 false,
76233965Sjdp	 0,
76333965Sjdp	 0,
76491049Sobrien	 true),
76591049Sobrien
76691049Sobrien  /* A 21 bit branch that adjusts for gp loads.  */
76791049Sobrien  HOWTO (R_ALPHA_BRSGP,		/* type */
76891049Sobrien	 2,			/* rightshift */
76991049Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
77091049Sobrien	 21,			/* bitsize */
77191049Sobrien	 true,			/* pc_relative */
77291049Sobrien	 0,			/* bitpos */
77391049Sobrien	 complain_overflow_signed, /* complain_on_overflow */
77491049Sobrien	 0,			/* special_function */
77591049Sobrien	 "BRSGP",		/* name */
77691049Sobrien	 false,			/* partial_inplace */
77791049Sobrien	 0x1fffff,		/* src_mask */
77891049Sobrien	 0x1fffff,		/* dst_mask */
77991049Sobrien	 true),			/* pcrel_offset */
780104841Sobrien
781104841Sobrien  /* Creates a tls_index for the symbol in the got.  */
782104841Sobrien  HOWTO (R_ALPHA_TLSGD,		/* type */
783104841Sobrien	 0,			/* rightshift */
784104841Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
785104841Sobrien	 16,			/* bitsize */
786104841Sobrien	 false,			/* pc_relative */
787104841Sobrien	 0,			/* bitpos */
788104841Sobrien	 complain_overflow_signed, /* complain_on_overflow */
789104841Sobrien	 0,			/* special_function */
790104841Sobrien	 "TLSGD",		/* name */
791104841Sobrien	 false,			/* partial_inplace */
792104841Sobrien	 0xffff,		/* src_mask */
793104841Sobrien	 0xffff,		/* dst_mask */
794104841Sobrien	 false),		/* pcrel_offset */
795104841Sobrien
796104841Sobrien  /* Creates a tls_index for the (current) module in the got.  */
797104841Sobrien  HOWTO (R_ALPHA_TLSLDM,	/* type */
798104841Sobrien	 0,			/* rightshift */
799104841Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
800104841Sobrien	 16,			/* bitsize */
801104841Sobrien	 false,			/* pc_relative */
802104841Sobrien	 0,			/* bitpos */
803104841Sobrien	 complain_overflow_signed, /* complain_on_overflow */
804104841Sobrien	 0,			/* special_function */
805104841Sobrien	 "TLSLDM",		/* name */
806104841Sobrien	 false,			/* partial_inplace */
807104841Sobrien	 0xffff,		/* src_mask */
808104841Sobrien	 0xffff,		/* dst_mask */
809104841Sobrien	 false),		/* pcrel_offset */
810104841Sobrien
811104841Sobrien  /* A dynamic relocation for a DTP module entry.  */
812104841Sobrien  HOWTO (R_ALPHA_DTPMOD64,	/* type */
813104841Sobrien	 0,			/* rightshift */
814104841Sobrien	 4,			/* size (0 = byte, 1 = short, 2 = long) */
815104841Sobrien	 64,			/* bitsize */
816104841Sobrien	 false,			/* pc_relative */
817104841Sobrien	 0,			/* bitpos */
818104841Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
819104841Sobrien	 0,			/* special_function */
820104841Sobrien	 "DTPMOD64",		/* name */
821104841Sobrien	 false,			/* partial_inplace */
822104841Sobrien	 MINUS_ONE,		/* src_mask */
823104841Sobrien	 MINUS_ONE,		/* dst_mask */
824104841Sobrien	 false),		/* pcrel_offset */
825104841Sobrien
826104841Sobrien  /* Creates a 64-bit offset in the got for the displacement
827104841Sobrien     from DTP to the target.  */
828104841Sobrien  HOWTO (R_ALPHA_GOTDTPREL,	/* type */
829104841Sobrien	 0,			/* rightshift */
830104841Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
831104841Sobrien	 16,			/* bitsize */
832104841Sobrien	 false,			/* pc_relative */
833104841Sobrien	 0,			/* bitpos */
834104841Sobrien	 complain_overflow_signed, /* complain_on_overflow */
835104841Sobrien	 0,			/* special_function */
836104841Sobrien	 "GOTDTPREL",		/* name */
837104841Sobrien	 false,			/* partial_inplace */
838104841Sobrien	 0xffff,		/* src_mask */
839104841Sobrien	 0xffff,		/* dst_mask */
840104841Sobrien	 false),		/* pcrel_offset */
841104841Sobrien
842104841Sobrien  /* A dynamic relocation for a displacement from DTP to the target.  */
843104841Sobrien  HOWTO (R_ALPHA_DTPREL64,	/* type */
844104841Sobrien	 0,			/* rightshift */
845104841Sobrien	 4,			/* size (0 = byte, 1 = short, 2 = long) */
846104841Sobrien	 64,			/* bitsize */
847104841Sobrien	 false,			/* pc_relative */
848104841Sobrien	 0,			/* bitpos */
849104841Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
850104841Sobrien	 0,			/* special_function */
851104841Sobrien	 "DTPREL64",		/* name */
852104841Sobrien	 false,			/* partial_inplace */
853104841Sobrien	 MINUS_ONE,		/* src_mask */
854104841Sobrien	 MINUS_ONE,		/* dst_mask */
855104841Sobrien	 false),		/* pcrel_offset */
856104841Sobrien
857104841Sobrien  /* The high 16 bits of the displacement from DTP to the target.  */
858104841Sobrien  HOWTO (R_ALPHA_DTPRELHI,	/* type */
859104841Sobrien	 0,			/* rightshift */
860104841Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
861104841Sobrien	 16,			/* bitsize */
862104841Sobrien	 false,			/* pc_relative */
863104841Sobrien	 0,			/* bitpos */
864104841Sobrien	 complain_overflow_signed, /* complain_on_overflow */
865104841Sobrien	 0,			/* special_function */
866104841Sobrien	 "DTPRELHI",		/* name */
867104841Sobrien	 false,			/* partial_inplace */
868104841Sobrien	 0xffff,		/* src_mask */
869104841Sobrien	 0xffff,		/* dst_mask */
870104841Sobrien	 false),		/* pcrel_offset */
871104841Sobrien
872104841Sobrien  /* The low 16 bits of the displacement from DTP to the target.  */
873104841Sobrien  HOWTO (R_ALPHA_DTPRELLO,	/* type */
874104841Sobrien	 0,			/* rightshift */
875104841Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
876104841Sobrien	 16,			/* bitsize */
877104841Sobrien	 false,			/* pc_relative */
878104841Sobrien	 0,			/* bitpos */
879104841Sobrien	 complain_overflow_dont, /* complain_on_overflow */
880104841Sobrien	 0,			/* special_function */
881104841Sobrien	 "DTPRELLO",		/* name */
882104841Sobrien	 false,			/* partial_inplace */
883104841Sobrien	 0xffff,		/* src_mask */
884104841Sobrien	 0xffff,		/* dst_mask */
885104841Sobrien	 false),		/* pcrel_offset */
886104841Sobrien
887104841Sobrien  /* A 16-bit displacement from DTP to the target.  */
888104841Sobrien  HOWTO (R_ALPHA_DTPREL16,	/* type */
889104841Sobrien	 0,			/* rightshift */
890104841Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
891104841Sobrien	 16,			/* bitsize */
892104841Sobrien	 false,			/* pc_relative */
893104841Sobrien	 0,			/* bitpos */
894104841Sobrien	 complain_overflow_signed, /* complain_on_overflow */
895104841Sobrien	 0,			/* special_function */
896104841Sobrien	 "DTPREL16",		/* name */
897104841Sobrien	 false,			/* partial_inplace */
898104841Sobrien	 0xffff,		/* src_mask */
899104841Sobrien	 0xffff,		/* dst_mask */
900104841Sobrien	 false),		/* pcrel_offset */
901104841Sobrien
902104841Sobrien  /* Creates a 64-bit offset in the got for the displacement
903104841Sobrien     from TP to the target.  */
904104841Sobrien  HOWTO (R_ALPHA_GOTTPREL,	/* type */
905104841Sobrien	 0,			/* rightshift */
906104841Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
907104841Sobrien	 16,			/* bitsize */
908104841Sobrien	 false,			/* pc_relative */
909104841Sobrien	 0,			/* bitpos */
910104841Sobrien	 complain_overflow_signed, /* complain_on_overflow */
911104841Sobrien	 0,			/* special_function */
912104841Sobrien	 "GOTTPREL",		/* name */
913104841Sobrien	 false,			/* partial_inplace */
914104841Sobrien	 0xffff,		/* src_mask */
915104841Sobrien	 0xffff,		/* dst_mask */
916104841Sobrien	 false),		/* pcrel_offset */
917104841Sobrien
918104841Sobrien  /* A dynamic relocation for a displacement from TP to the target.  */
919104841Sobrien  HOWTO (R_ALPHA_TPREL64,	/* type */
920104841Sobrien	 0,			/* rightshift */
921104841Sobrien	 4,			/* size (0 = byte, 1 = short, 2 = long) */
922104841Sobrien	 64,			/* bitsize */
923104841Sobrien	 false,			/* pc_relative */
924104841Sobrien	 0,			/* bitpos */
925104841Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
926104841Sobrien	 0,			/* special_function */
927104841Sobrien	 "TPREL64",		/* name */
928104841Sobrien	 false,			/* partial_inplace */
929104841Sobrien	 MINUS_ONE,		/* src_mask */
930104841Sobrien	 MINUS_ONE,		/* dst_mask */
931104841Sobrien	 false),		/* pcrel_offset */
932104841Sobrien
933104841Sobrien  /* The high 16 bits of the displacement from TP to the target.  */
934104841Sobrien  HOWTO (R_ALPHA_TPRELHI,	/* type */
935104841Sobrien	 0,			/* rightshift */
936104841Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
937104841Sobrien	 16,			/* bitsize */
938104841Sobrien	 false,			/* pc_relative */
939104841Sobrien	 0,			/* bitpos */
940104841Sobrien	 complain_overflow_signed, /* complain_on_overflow */
941104841Sobrien	 0,			/* special_function */
942104841Sobrien	 "TPRELHI",		/* name */
943104841Sobrien	 false,			/* partial_inplace */
944104841Sobrien	 0xffff,		/* src_mask */
945104841Sobrien	 0xffff,		/* dst_mask */
946104841Sobrien	 false),		/* pcrel_offset */
947104841Sobrien
948104841Sobrien  /* The low 16 bits of the displacement from TP to the target.  */
949104841Sobrien  HOWTO (R_ALPHA_TPRELLO,	/* type */
950104841Sobrien	 0,			/* rightshift */
951104841Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
952104841Sobrien	 16,			/* bitsize */
953104841Sobrien	 false,			/* pc_relative */
954104841Sobrien	 0,			/* bitpos */
955104841Sobrien	 complain_overflow_dont, /* complain_on_overflow */
956104841Sobrien	 0,			/* special_function */
957104841Sobrien	 "TPRELLO",		/* name */
958104841Sobrien	 false,			/* partial_inplace */
959104841Sobrien	 0xffff,		/* src_mask */
960104841Sobrien	 0xffff,		/* dst_mask */
961104841Sobrien	 false),		/* pcrel_offset */
962104841Sobrien
963104841Sobrien  /* A 16-bit displacement from TP to the target.  */
964104841Sobrien  HOWTO (R_ALPHA_TPREL16,	/* type */
965104841Sobrien	 0,			/* rightshift */
966104841Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
967104841Sobrien	 16,			/* bitsize */
968104841Sobrien	 false,			/* pc_relative */
969104841Sobrien	 0,			/* bitpos */
970104841Sobrien	 complain_overflow_signed, /* complain_on_overflow */
971104841Sobrien	 0,			/* special_function */
972104841Sobrien	 "TPREL16",		/* name */
973104841Sobrien	 false,			/* partial_inplace */
974104841Sobrien	 0xffff,		/* src_mask */
975104841Sobrien	 0xffff,		/* dst_mask */
976104841Sobrien	 false),		/* pcrel_offset */
97733965Sjdp};
97833965Sjdp
97933965Sjdp/* A relocation function which doesn't do anything.  */
98033965Sjdp
98133965Sjdpstatic bfd_reloc_status_type
98233965Sjdpelf64_alpha_reloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message)
98378833Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
98433965Sjdp     arelent *reloc;
98578833Sobrien     asymbol *sym ATTRIBUTE_UNUSED;
98678833Sobrien     PTR data ATTRIBUTE_UNUSED;
98733965Sjdp     asection *sec;
98833965Sjdp     bfd *output_bfd;
98978833Sobrien     char **error_message ATTRIBUTE_UNUSED;
99033965Sjdp{
99133965Sjdp  if (output_bfd)
99233965Sjdp    reloc->address += sec->output_offset;
99333965Sjdp  return bfd_reloc_ok;
99433965Sjdp}
99533965Sjdp
99633965Sjdp/* A relocation function used for an unsupported reloc.  */
99733965Sjdp
99833965Sjdpstatic bfd_reloc_status_type
99933965Sjdpelf64_alpha_reloc_bad (abfd, reloc, sym, data, sec, output_bfd, error_message)
100078833Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
100133965Sjdp     arelent *reloc;
100278833Sobrien     asymbol *sym ATTRIBUTE_UNUSED;
100378833Sobrien     PTR data ATTRIBUTE_UNUSED;
100433965Sjdp     asection *sec;
100533965Sjdp     bfd *output_bfd;
100678833Sobrien     char **error_message ATTRIBUTE_UNUSED;
100733965Sjdp{
100833965Sjdp  if (output_bfd)
100933965Sjdp    reloc->address += sec->output_offset;
101033965Sjdp  return bfd_reloc_notsupported;
101133965Sjdp}
101233965Sjdp
101333965Sjdp/* Do the work of the GPDISP relocation.  */
101433965Sjdp
101533965Sjdpstatic bfd_reloc_status_type
101633965Sjdpelf64_alpha_do_reloc_gpdisp (abfd, gpdisp, p_ldah, p_lda)
101733965Sjdp     bfd *abfd;
101833965Sjdp     bfd_vma gpdisp;
101933965Sjdp     bfd_byte *p_ldah;
102033965Sjdp     bfd_byte *p_lda;
102133965Sjdp{
102233965Sjdp  bfd_reloc_status_type ret = bfd_reloc_ok;
102333965Sjdp  bfd_vma addend;
102433965Sjdp  unsigned long i_ldah, i_lda;
102533965Sjdp
102633965Sjdp  i_ldah = bfd_get_32 (abfd, p_ldah);
102733965Sjdp  i_lda = bfd_get_32 (abfd, p_lda);
102833965Sjdp
102933965Sjdp  /* Complain if the instructions are not correct.  */
103033965Sjdp  if (((i_ldah >> 26) & 0x3f) != 0x09
103133965Sjdp      || ((i_lda >> 26) & 0x3f) != 0x08)
103233965Sjdp    ret = bfd_reloc_dangerous;
103333965Sjdp
103433965Sjdp  /* Extract the user-supplied offset, mirroring the sign extensions
103533965Sjdp     that the instructions perform.  */
103633965Sjdp  addend = ((i_ldah & 0xffff) << 16) | (i_lda & 0xffff);
103733965Sjdp  addend = (addend ^ 0x80008000) - 0x80008000;
103833965Sjdp
103933965Sjdp  gpdisp += addend;
104033965Sjdp
104148850Sdfr  if ((bfd_signed_vma) gpdisp < -(bfd_signed_vma) 0x80000000
104248850Sdfr      || (bfd_signed_vma) gpdisp >= (bfd_signed_vma) 0x7fff8000)
104333965Sjdp    ret = bfd_reloc_overflow;
104433965Sjdp
104533965Sjdp  /* compensate for the sign extension again.  */
104633965Sjdp  i_ldah = ((i_ldah & 0xffff0000)
104733965Sjdp	    | (((gpdisp >> 16) + ((gpdisp >> 15) & 1)) & 0xffff));
104833965Sjdp  i_lda = (i_lda & 0xffff0000) | (gpdisp & 0xffff);
104933965Sjdp
105089862Sobrien  bfd_put_32 (abfd, (bfd_vma) i_ldah, p_ldah);
105189862Sobrien  bfd_put_32 (abfd, (bfd_vma) i_lda, p_lda);
105233965Sjdp
105333965Sjdp  return ret;
105433965Sjdp}
105533965Sjdp
105633965Sjdp/* The special function for the GPDISP reloc.  */
105733965Sjdp
105833965Sjdpstatic bfd_reloc_status_type
105933965Sjdpelf64_alpha_reloc_gpdisp (abfd, reloc_entry, sym, data, input_section,
106033965Sjdp			  output_bfd, err_msg)
106133965Sjdp     bfd *abfd;
106233965Sjdp     arelent *reloc_entry;
106378833Sobrien     asymbol *sym ATTRIBUTE_UNUSED;
106433965Sjdp     PTR data;
106533965Sjdp     asection *input_section;
106633965Sjdp     bfd *output_bfd;
106733965Sjdp     char **err_msg;
106833965Sjdp{
106933965Sjdp  bfd_reloc_status_type ret;
107033965Sjdp  bfd_vma gp, relocation;
107133965Sjdp  bfd_byte *p_ldah, *p_lda;
107233965Sjdp
107333965Sjdp  /* Don't do anything if we're not doing a final link.  */
107433965Sjdp  if (output_bfd)
107533965Sjdp    {
107633965Sjdp      reloc_entry->address += input_section->output_offset;
107733965Sjdp      return bfd_reloc_ok;
107833965Sjdp    }
107933965Sjdp
108033965Sjdp  if (reloc_entry->address > input_section->_cooked_size ||
108133965Sjdp      reloc_entry->address + reloc_entry->addend > input_section->_cooked_size)
108233965Sjdp    return bfd_reloc_outofrange;
108333965Sjdp
108433965Sjdp  /* The gp used in the portion of the output object to which this
108533965Sjdp     input object belongs is cached on the input bfd.  */
108633965Sjdp  gp = _bfd_get_gp_value (abfd);
108733965Sjdp
108833965Sjdp  relocation = (input_section->output_section->vma
108933965Sjdp		+ input_section->output_offset
109033965Sjdp		+ reloc_entry->address);
109133965Sjdp
109233965Sjdp  p_ldah = (bfd_byte *) data + reloc_entry->address;
109333965Sjdp  p_lda = p_ldah + reloc_entry->addend;
109433965Sjdp
109533965Sjdp  ret = elf64_alpha_do_reloc_gpdisp (abfd, gp - relocation, p_ldah, p_lda);
109633965Sjdp
109733965Sjdp  /* Complain if the instructions are not correct.  */
109833965Sjdp  if (ret == bfd_reloc_dangerous)
109960510Sobrien    *err_msg = _("GPDISP relocation did not find ldah and lda instructions");
110033965Sjdp
110133965Sjdp  return ret;
110233965Sjdp}
110333965Sjdp
110433965Sjdp/* A mapping from BFD reloc types to Alpha ELF reloc types.  */
110533965Sjdp
110633965Sjdpstruct elf_reloc_map
110733965Sjdp{
110833965Sjdp  bfd_reloc_code_real_type bfd_reloc_val;
110933965Sjdp  int elf_reloc_val;
111033965Sjdp};
111133965Sjdp
111233965Sjdpstatic const struct elf_reloc_map elf64_alpha_reloc_map[] =
111333965Sjdp{
111489862Sobrien  {BFD_RELOC_NONE,			R_ALPHA_NONE},
111589862Sobrien  {BFD_RELOC_32,			R_ALPHA_REFLONG},
111689862Sobrien  {BFD_RELOC_64,			R_ALPHA_REFQUAD},
111789862Sobrien  {BFD_RELOC_CTOR,			R_ALPHA_REFQUAD},
111889862Sobrien  {BFD_RELOC_GPREL32,			R_ALPHA_GPREL32},
111989862Sobrien  {BFD_RELOC_ALPHA_ELF_LITERAL,		R_ALPHA_LITERAL},
112089862Sobrien  {BFD_RELOC_ALPHA_LITUSE,		R_ALPHA_LITUSE},
112189862Sobrien  {BFD_RELOC_ALPHA_GPDISP,		R_ALPHA_GPDISP},
112289862Sobrien  {BFD_RELOC_23_PCREL_S2,		R_ALPHA_BRADDR},
112389862Sobrien  {BFD_RELOC_ALPHA_HINT,		R_ALPHA_HINT},
112489862Sobrien  {BFD_RELOC_16_PCREL,			R_ALPHA_SREL16},
112589862Sobrien  {BFD_RELOC_32_PCREL,			R_ALPHA_SREL32},
112689862Sobrien  {BFD_RELOC_64_PCREL,			R_ALPHA_SREL64},
112789862Sobrien  {BFD_RELOC_ALPHA_GPREL_HI16,		R_ALPHA_GPRELHIGH},
112889862Sobrien  {BFD_RELOC_ALPHA_GPREL_LO16,		R_ALPHA_GPRELLOW},
112989862Sobrien  {BFD_RELOC_GPREL16,			R_ALPHA_GPREL16},
113091049Sobrien  {BFD_RELOC_ALPHA_BRSGP,		R_ALPHA_BRSGP},
1131104841Sobrien  {BFD_RELOC_ALPHA_TLSGD,		R_ALPHA_TLSGD},
1132104841Sobrien  {BFD_RELOC_ALPHA_TLSLDM,		R_ALPHA_TLSLDM},
1133104841Sobrien  {BFD_RELOC_ALPHA_DTPMOD64,		R_ALPHA_DTPMOD64},
1134104841Sobrien  {BFD_RELOC_ALPHA_GOTDTPREL16,		R_ALPHA_GOTDTPREL},
1135104841Sobrien  {BFD_RELOC_ALPHA_DTPREL64,		R_ALPHA_DTPREL64},
1136104841Sobrien  {BFD_RELOC_ALPHA_DTPREL_HI16,		R_ALPHA_DTPRELHI},
1137104841Sobrien  {BFD_RELOC_ALPHA_DTPREL_LO16,		R_ALPHA_DTPRELLO},
1138104841Sobrien  {BFD_RELOC_ALPHA_DTPREL16,		R_ALPHA_DTPREL16},
1139104841Sobrien  {BFD_RELOC_ALPHA_GOTTPREL16,		R_ALPHA_GOTTPREL},
1140104841Sobrien  {BFD_RELOC_ALPHA_TPREL64,		R_ALPHA_TPREL64},
1141104841Sobrien  {BFD_RELOC_ALPHA_TPREL_HI16,		R_ALPHA_TPRELHI},
1142104841Sobrien  {BFD_RELOC_ALPHA_TPREL_LO16,		R_ALPHA_TPRELLO},
1143104841Sobrien  {BFD_RELOC_ALPHA_TPREL16,		R_ALPHA_TPREL16},
114433965Sjdp};
114533965Sjdp
114633965Sjdp/* Given a BFD reloc type, return a HOWTO structure.  */
114733965Sjdp
114833965Sjdpstatic reloc_howto_type *
114933965Sjdpelf64_alpha_bfd_reloc_type_lookup (abfd, code)
115078833Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
115133965Sjdp     bfd_reloc_code_real_type code;
115233965Sjdp{
115333965Sjdp  const struct elf_reloc_map *i, *e;
115433965Sjdp  i = e = elf64_alpha_reloc_map;
115533965Sjdp  e += sizeof (elf64_alpha_reloc_map) / sizeof (struct elf_reloc_map);
115633965Sjdp  for (; i != e; ++i)
115733965Sjdp    {
115833965Sjdp      if (i->bfd_reloc_val == code)
115933965Sjdp	return &elf64_alpha_howto_table[i->elf_reloc_val];
116033965Sjdp    }
116133965Sjdp  return 0;
116233965Sjdp}
116333965Sjdp
116433965Sjdp/* Given an Alpha ELF reloc type, fill in an arelent structure.  */
116533965Sjdp
116633965Sjdpstatic void
116733965Sjdpelf64_alpha_info_to_howto (abfd, cache_ptr, dst)
116878833Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
116933965Sjdp     arelent *cache_ptr;
117033965Sjdp     Elf64_Internal_Rela *dst;
117133965Sjdp{
117233965Sjdp  unsigned r_type;
117333965Sjdp
117433965Sjdp  r_type = ELF64_R_TYPE(dst->r_info);
117533965Sjdp  BFD_ASSERT (r_type < (unsigned int) R_ALPHA_max);
117633965Sjdp  cache_ptr->howto = &elf64_alpha_howto_table[r_type];
117733965Sjdp}
1178104841Sobrien
1179104841Sobrien/* These two relocations create a two-word entry in the got.  */
1180104841Sobrien#define alpha_got_entry_size(r_type) \
1181104841Sobrien  (r_type == R_ALPHA_TLSGD || r_type == R_ALPHA_TLSLDM ? 16 : 8)
1182104841Sobrien
1183104841Sobrien/* This is PT_TLS segment p_vaddr.  */
1184104841Sobrien#define alpha_get_dtprel_base(tlss) \
1185104841Sobrien  ((tlss)->start)
1186104841Sobrien
1187104841Sobrien/* Main program TLS (whose template starts at PT_TLS p_vaddr)
1188104841Sobrien   is assigned offset round(16, PT_TLS p_align).  */
1189104841Sobrien#define alpha_get_tprel_base(tlss) \
1190104841Sobrien  ((tlss)->start - align_power ((bfd_vma) 16, (tlss)->align))
119133965Sjdp
119277303Sobrien/* These functions do relaxation for Alpha ELF.
119360510Sobrien
119460510Sobrien   Currently I'm only handling what I can do with existing compiler
119560510Sobrien   and assembler support, which means no instructions are removed,
119660510Sobrien   though some may be nopped.  At this time GCC does not emit enough
119760510Sobrien   information to do all of the relaxing that is possible.  It will
119860510Sobrien   take some not small amount of work for that to happen.
119960510Sobrien
120060510Sobrien   There are a couple of interesting papers that I once read on this
120160510Sobrien   subject, that I cannot find references to at the moment, that
120260510Sobrien   related to Alpha in particular.  They are by David Wall, then of
120360510Sobrien   DEC WRL.  */
120460510Sobrien
120560510Sobrien#define OP_LDA		0x08
120660510Sobrien#define OP_LDAH		0x09
120760510Sobrien#define INSN_JSR	0x68004000
120860510Sobrien#define INSN_JSR_MASK	0xfc00c000
120960510Sobrien#define OP_LDQ		0x29
121060510Sobrien#define OP_BR		0x30
121160510Sobrien#define OP_BSR		0x34
121289862Sobrien#define INSN_UNOP	0x2ffe0000
1213104841Sobrien#define INSN_ADDQ	0x40000400
1214104841Sobrien#define INSN_RDUNIQ	0x0000009e
121560510Sobrien
121660510Sobrienstruct alpha_relax_info
121760510Sobrien{
121860510Sobrien  bfd *abfd;
121960510Sobrien  asection *sec;
122060510Sobrien  bfd_byte *contents;
1221104841Sobrien  Elf_Internal_Shdr *symtab_hdr;
122260510Sobrien  Elf_Internal_Rela *relocs, *relend;
122360510Sobrien  struct bfd_link_info *link_info;
1224104841Sobrien  struct elf_link_tls_segment *tls_segment;
122560510Sobrien  bfd_vma gp;
122660510Sobrien  bfd *gotobj;
122760510Sobrien  asection *tsec;
122860510Sobrien  struct alpha_elf_link_hash_entry *h;
1229104841Sobrien  struct alpha_elf_got_entry **first_gotent;
123060510Sobrien  struct alpha_elf_got_entry *gotent;
1231104841Sobrien  boolean changed_contents;
1232104841Sobrien  boolean changed_relocs;
123360510Sobrien  unsigned char other;
123460510Sobrien};
123560510Sobrien
1236104841Sobrienstatic boolean elf64_alpha_relax_with_lituse
123777303Sobrien  PARAMS((struct alpha_relax_info *info, bfd_vma symval,
123860510Sobrien          Elf_Internal_Rela *irel));
123960510Sobrienstatic bfd_vma elf64_alpha_relax_opt_call
124060510Sobrien  PARAMS((struct alpha_relax_info *info, bfd_vma symval));
1241104841Sobrienstatic boolean elf64_alpha_relax_got_load
1242104841Sobrien  PARAMS((struct alpha_relax_info *info, bfd_vma symval,
1243104841Sobrien          Elf_Internal_Rela *irel, unsigned long));
1244104841Sobrienstatic boolean elf64_alpha_relax_gprelhilo
1245104841Sobrien  PARAMS((struct alpha_relax_info *info, bfd_vma symval,
1246104841Sobrien          Elf_Internal_Rela *irel, boolean));
1247104841Sobrienstatic boolean elf64_alpha_relax_tls_get_addr
1248104841Sobrien  PARAMS((struct alpha_relax_info *info, bfd_vma symval,
1249104841Sobrien          Elf_Internal_Rela *irel, boolean));
1250104841Sobrienstatic struct elf_link_tls_segment *elf64_alpha_relax_find_tls_segment
1251104841Sobrien  PARAMS((struct alpha_relax_info *, struct elf_link_tls_segment *));
125260510Sobrienstatic boolean elf64_alpha_relax_section
125360510Sobrien  PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
125460510Sobrien	  boolean *again));
125560510Sobrien
125660510Sobrienstatic Elf_Internal_Rela *
125760510Sobrienelf64_alpha_find_reloc_at_ofs (rel, relend, offset, type)
125860510Sobrien     Elf_Internal_Rela *rel, *relend;
125960510Sobrien     bfd_vma offset;
126060510Sobrien     int type;
126160510Sobrien{
126260510Sobrien  while (rel < relend)
126360510Sobrien    {
126489862Sobrien      if (rel->r_offset == offset
126589862Sobrien	  && ELF64_R_TYPE (rel->r_info) == (unsigned int) type)
126660510Sobrien	return rel;
126760510Sobrien      ++rel;
126860510Sobrien    }
126960510Sobrien  return NULL;
127060510Sobrien}
127160510Sobrien
1272104841Sobrienstatic boolean
1273104841Sobrienelf64_alpha_relax_with_lituse (info, symval, irel)
127460510Sobrien     struct alpha_relax_info *info;
127560510Sobrien     bfd_vma symval;
1276104841Sobrien     Elf_Internal_Rela *irel;
127760510Sobrien{
1278104841Sobrien  Elf_Internal_Rela *urel, *irelend = info->relend;
127960510Sobrien  int flags, count, i;
128060510Sobrien  bfd_signed_vma disp;
128160510Sobrien  boolean fits16;
128260510Sobrien  boolean fits32;
128360510Sobrien  boolean lit_reused = false;
128460510Sobrien  boolean all_optimized = true;
128560510Sobrien  unsigned int lit_insn;
128660510Sobrien
128760510Sobrien  lit_insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset);
128860510Sobrien  if (lit_insn >> 26 != OP_LDQ)
128960510Sobrien    {
129060510Sobrien      ((*_bfd_error_handler)
129160510Sobrien       ("%s: %s+0x%lx: warning: LITERAL relocation against unexpected insn",
129289862Sobrien	bfd_archive_filename (info->abfd), info->sec->name,
129389862Sobrien	(unsigned long) irel->r_offset));
1294104841Sobrien      return true;
129560510Sobrien    }
129660510Sobrien
1297104841Sobrien  /* Can't relax dynamic symbols.  */
1298104841Sobrien  if (alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info))
1299104841Sobrien    return true;
1300104841Sobrien
130160510Sobrien  /* Summarize how this particular LITERAL is used.  */
130260510Sobrien  for (urel = irel+1, flags = count = 0; urel < irelend; ++urel, ++count)
130360510Sobrien    {
130460510Sobrien      if (ELF64_R_TYPE (urel->r_info) != R_ALPHA_LITUSE)
130560510Sobrien	break;
130689862Sobrien      if (urel->r_addend <= 3)
130760510Sobrien	flags |= 1 << urel->r_addend;
130860510Sobrien    }
130960510Sobrien
131077303Sobrien  /* A little preparation for the loop...  */
131160510Sobrien  disp = symval - info->gp;
131260510Sobrien
131360510Sobrien  for (urel = irel+1, i = 0; i < count; ++i, ++urel)
131460510Sobrien    {
131560510Sobrien      unsigned int insn;
131677303Sobrien      int insn_disp;
131777303Sobrien      bfd_signed_vma xdisp;
131877303Sobrien
131960510Sobrien      insn = bfd_get_32 (info->abfd, info->contents + urel->r_offset);
132060510Sobrien
132160510Sobrien      switch (urel->r_addend)
132260510Sobrien	{
1323104841Sobrien	case LITUSE_ALPHA_ADDR:
1324104841Sobrien	default:
132560510Sobrien	  /* This type is really just a placeholder to note that all
132660510Sobrien	     uses cannot be optimized, but to still allow some.  */
132760510Sobrien	  all_optimized = false;
132860510Sobrien	  break;
132960510Sobrien
1330104841Sobrien	case LITUSE_ALPHA_BASE:
133160510Sobrien	  /* We can always optimize 16-bit displacements.  */
133277303Sobrien
133377303Sobrien	  /* Extract the displacement from the instruction, sign-extending
133477303Sobrien	     it if necessary, then test whether it is within 16 or 32 bits
133577303Sobrien	     displacement from GP.  */
133677303Sobrien	  insn_disp = insn & 0x0000ffff;
1337104841Sobrien	  if (insn_disp & 0x8000)
1338104841Sobrien	    insn_disp |= ~0xffff;  /* Negative: sign-extend.  */
133977303Sobrien
134077303Sobrien	  xdisp = disp + insn_disp;
1341104841Sobrien	  fits16 = (xdisp >= - (bfd_signed_vma) 0x8000 && xdisp < 0x8000);
1342104841Sobrien	  fits32 = (xdisp >= - (bfd_signed_vma) 0x80000000
1343104841Sobrien		    && xdisp < 0x7fff8000);
134477303Sobrien
134560510Sobrien	  if (fits16)
134660510Sobrien	    {
134777303Sobrien	      /* Take the op code and dest from this insn, take the base
134860510Sobrien		 register from the literal insn.  Leave the offset alone.  */
134977303Sobrien	      insn = (insn & 0xffe0ffff) | (lit_insn & 0x001f0000);
135060510Sobrien	      urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
135189862Sobrien					   R_ALPHA_GPREL16);
135260510Sobrien	      urel->r_addend = irel->r_addend;
135360510Sobrien	      info->changed_relocs = true;
135460510Sobrien
135589862Sobrien	      bfd_put_32 (info->abfd, (bfd_vma) insn,
135689862Sobrien			  info->contents + urel->r_offset);
135760510Sobrien	      info->changed_contents = true;
135860510Sobrien	    }
135960510Sobrien
136060510Sobrien	  /* If all mem+byte, we can optimize 32-bit mem displacements.  */
136160510Sobrien	  else if (fits32 && !(flags & ~6))
136260510Sobrien	    {
136377303Sobrien	      /* FIXME: sanity check that lit insn Ra is mem insn Rb.  */
136460510Sobrien
136560510Sobrien	      irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
136660510Sobrien					   R_ALPHA_GPRELHIGH);
136760510Sobrien	      lit_insn = (OP_LDAH << 26) | (lit_insn & 0x03ff0000);
136889862Sobrien	      bfd_put_32 (info->abfd, (bfd_vma) lit_insn,
136960510Sobrien			  info->contents + irel->r_offset);
137060510Sobrien	      lit_reused = true;
137160510Sobrien	      info->changed_contents = true;
137260510Sobrien
137360510Sobrien	      urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
137460510Sobrien					   R_ALPHA_GPRELLOW);
137560510Sobrien	      urel->r_addend = irel->r_addend;
137660510Sobrien	      info->changed_relocs = true;
137760510Sobrien	    }
137860510Sobrien	  else
137960510Sobrien	    all_optimized = false;
138060510Sobrien	  break;
138160510Sobrien
1382104841Sobrien	case LITUSE_ALPHA_BYTOFF:
138360510Sobrien	  /* We can always optimize byte instructions.  */
138460510Sobrien
138560510Sobrien	  /* FIXME: sanity check the insn for byte op.  Check that the
138660510Sobrien	     literal dest reg is indeed Rb in the byte insn.  */
138760510Sobrien
138889862Sobrien	  insn &= ~ (unsigned) 0x001ff000;
138989862Sobrien	  insn |= ((symval & 7) << 13) | 0x1000;
139060510Sobrien
139160510Sobrien	  urel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
139260510Sobrien	  urel->r_addend = 0;
139360510Sobrien	  info->changed_relocs = true;
139460510Sobrien
139589862Sobrien	  bfd_put_32 (info->abfd, (bfd_vma) insn,
139689862Sobrien		      info->contents + urel->r_offset);
139760510Sobrien	  info->changed_contents = true;
139860510Sobrien	  break;
139960510Sobrien
1400104841Sobrien	case LITUSE_ALPHA_JSR:
1401104841Sobrien	case LITUSE_ALPHA_TLSGD:
1402104841Sobrien	case LITUSE_ALPHA_TLSLDM:
140360510Sobrien	  {
1404104841Sobrien	    bfd_vma optdest, org;
140560510Sobrien	    bfd_signed_vma odisp;
140660510Sobrien
1407104841Sobrien	    /* If not zero, place to jump without needing pv.  */
1408104841Sobrien	    optdest = elf64_alpha_relax_opt_call (info, symval);
1409104841Sobrien	    org = (info->sec->output_section->vma
1410104841Sobrien		   + info->sec->output_offset
1411104841Sobrien		   + urel->r_offset + 4);
141260510Sobrien	    odisp = (optdest ? optdest : symval) - org;
1413104841Sobrien
141460510Sobrien	    if (odisp >= -0x400000 && odisp < 0x400000)
141560510Sobrien	      {
141660510Sobrien		Elf_Internal_Rela *xrel;
141760510Sobrien
141877303Sobrien		/* Preserve branch prediction call stack when possible.  */
141960510Sobrien		if ((insn & INSN_JSR_MASK) == INSN_JSR)
142060510Sobrien		  insn = (OP_BSR << 26) | (insn & 0x03e00000);
142160510Sobrien		else
142260510Sobrien		  insn = (OP_BR << 26) | (insn & 0x03e00000);
142377303Sobrien
142460510Sobrien		urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
142560510Sobrien					     R_ALPHA_BRADDR);
142660510Sobrien		urel->r_addend = irel->r_addend;
142760510Sobrien
142860510Sobrien		if (optdest)
142960510Sobrien		  urel->r_addend += optdest - symval;
143060510Sobrien		else
143160510Sobrien		  all_optimized = false;
143260510Sobrien
143389862Sobrien		bfd_put_32 (info->abfd, (bfd_vma) insn,
143489862Sobrien			    info->contents + urel->r_offset);
143560510Sobrien
143660510Sobrien		/* Kill any HINT reloc that might exist for this insn.  */
143760510Sobrien		xrel = (elf64_alpha_find_reloc_at_ofs
143877303Sobrien			(info->relocs, info->relend, urel->r_offset,
143960510Sobrien			 R_ALPHA_HINT));
144060510Sobrien		if (xrel)
144160510Sobrien		  xrel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
144260510Sobrien
144360510Sobrien		info->changed_contents = true;
144460510Sobrien		info->changed_relocs = true;
144560510Sobrien	      }
144660510Sobrien	    else
144760510Sobrien	      all_optimized = false;
144860510Sobrien
144989862Sobrien	    /* Even if the target is not in range for a direct branch,
145089862Sobrien	       if we share a GP, we can eliminate the gp reload.  */
145189862Sobrien	    if (optdest)
145289862Sobrien	      {
145389862Sobrien		Elf_Internal_Rela *gpdisp
145489862Sobrien		  = (elf64_alpha_find_reloc_at_ofs
1455104841Sobrien		     (info->relocs, irelend, urel->r_offset + 4,
1456104841Sobrien		      R_ALPHA_GPDISP));
145789862Sobrien		if (gpdisp)
145889862Sobrien		  {
1459104841Sobrien		    bfd_byte *p_ldah = info->contents + gpdisp->r_offset;
146089862Sobrien		    bfd_byte *p_lda = p_ldah + gpdisp->r_addend;
146189862Sobrien		    unsigned int ldah = bfd_get_32 (info->abfd, p_ldah);
146289862Sobrien		    unsigned int lda = bfd_get_32 (info->abfd, p_lda);
146360510Sobrien
146489862Sobrien		    /* Verify that the instruction is "ldah $29,0($26)".
146589862Sobrien		       Consider a function that ends in a noreturn call,
146689862Sobrien		       and that the next function begins with an ldgp,
146789862Sobrien		       and that by accident there is no padding between.
146889862Sobrien		       In that case the insn would use $27 as the base.  */
146989862Sobrien		    if (ldah == 0x27ba0000 && lda == 0x23bd0000)
147089862Sobrien		      {
147189862Sobrien			bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_ldah);
147289862Sobrien			bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_lda);
147389862Sobrien
147489862Sobrien			gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
147589862Sobrien			info->changed_contents = true;
147689862Sobrien			info->changed_relocs = true;
147789862Sobrien		      }
147889862Sobrien		  }
147989862Sobrien	      }
148060510Sobrien	  }
148160510Sobrien	  break;
148260510Sobrien	}
148360510Sobrien    }
148460510Sobrien
148560510Sobrien  /* If all cases were optimized, we can reduce the use count on this
148660510Sobrien     got entry by one, possibly eliminating it.  */
148760510Sobrien  if (all_optimized)
148860510Sobrien    {
1489104841Sobrien      if (--info->gotent->use_count == 0)
1490104841Sobrien	{
1491104841Sobrien	  int sz = alpha_got_entry_size (R_ALPHA_LITERAL);
1492104841Sobrien	  alpha_elf_tdata (info->gotobj)->total_got_size -= sz;
1493104841Sobrien	  if (!info->h)
1494104841Sobrien	    alpha_elf_tdata (info->gotobj)->local_got_size -= sz;
1495104841Sobrien	}
149660510Sobrien
149760510Sobrien      /* If the literal instruction is no longer needed (it may have been
1498104841Sobrien	 reused.  We can eliminate it.  */
1499104841Sobrien      /* ??? For now, I don't want to deal with compacting the section,
150060510Sobrien	 so just nop it out.  */
150160510Sobrien      if (!lit_reused)
150260510Sobrien	{
150360510Sobrien	  irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
150460510Sobrien	  info->changed_relocs = true;
150560510Sobrien
150689862Sobrien	  bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP,
150789862Sobrien		      info->contents + irel->r_offset);
150860510Sobrien	  info->changed_contents = true;
150960510Sobrien	}
151060510Sobrien    }
151160510Sobrien
1512104841Sobrien  return true;
151360510Sobrien}
151460510Sobrien
151560510Sobrienstatic bfd_vma
151660510Sobrienelf64_alpha_relax_opt_call (info, symval)
151760510Sobrien     struct alpha_relax_info *info;
151860510Sobrien     bfd_vma symval;
151960510Sobrien{
152060510Sobrien  /* If the function has the same gp, and we can identify that the
152160510Sobrien     function does not use its function pointer, we can eliminate the
152260510Sobrien     address load.  */
152360510Sobrien
152460510Sobrien  /* If the symbol is marked NOPV, we are being told the function never
152560510Sobrien     needs its procedure value.  */
152677303Sobrien  if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_NOPV)
152760510Sobrien    return symval;
152860510Sobrien
152960510Sobrien  /* If the symbol is marked STD_GP, we are being told the function does
153077303Sobrien     a normal ldgp in the first two words.  */
153177303Sobrien  else if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_STD_GPLOAD)
153260510Sobrien    ;
153360510Sobrien
153460510Sobrien  /* Otherwise, we may be able to identify a GP load in the first two
153560510Sobrien     words, which we can then skip.  */
153677303Sobrien  else
153760510Sobrien    {
153860510Sobrien      Elf_Internal_Rela *tsec_relocs, *tsec_relend, *tsec_free, *gpdisp;
153960510Sobrien      bfd_vma ofs;
154060510Sobrien
154177303Sobrien      /* Load the relocations from the section that the target symbol is in.  */
154260510Sobrien      if (info->sec == info->tsec)
154360510Sobrien	{
154460510Sobrien	  tsec_relocs = info->relocs;
154560510Sobrien	  tsec_relend = info->relend;
154660510Sobrien	  tsec_free = NULL;
154760510Sobrien	}
154860510Sobrien      else
154960510Sobrien	{
155060510Sobrien	  tsec_relocs = (_bfd_elf64_link_read_relocs
155160510Sobrien		         (info->abfd, info->tsec, (PTR) NULL,
155260510Sobrien			 (Elf_Internal_Rela *) NULL,
155360510Sobrien			 info->link_info->keep_memory));
155460510Sobrien	  if (tsec_relocs == NULL)
155560510Sobrien	    return 0;
155660510Sobrien	  tsec_relend = tsec_relocs + info->tsec->reloc_count;
155760510Sobrien	  tsec_free = (info->link_info->keep_memory ? NULL : tsec_relocs);
155860510Sobrien	}
155960510Sobrien
156060510Sobrien      /* Recover the symbol's offset within the section.  */
156160510Sobrien      ofs = (symval - info->tsec->output_section->vma
156260510Sobrien	     - info->tsec->output_offset);
156377303Sobrien
156460510Sobrien      /* Look for a GPDISP reloc.  */
156560510Sobrien      gpdisp = (elf64_alpha_find_reloc_at_ofs
156660510Sobrien		(tsec_relocs, tsec_relend, ofs, R_ALPHA_GPDISP));
156760510Sobrien
156860510Sobrien      if (!gpdisp || gpdisp->r_addend != 4)
156960510Sobrien	{
157060510Sobrien	  if (tsec_free)
157160510Sobrien	    free (tsec_free);
157260510Sobrien	  return 0;
157360510Sobrien	}
157460510Sobrien      if (tsec_free)
157560510Sobrien        free (tsec_free);
157660510Sobrien    }
157760510Sobrien
157877303Sobrien  /* We've now determined that we can skip an initial gp load.  Verify
157960510Sobrien     that the call and the target use the same gp.   */
158060510Sobrien  if (info->link_info->hash->creator != info->tsec->owner->xvec
158160510Sobrien      || info->gotobj != alpha_elf_tdata (info->tsec->owner)->gotobj)
158260510Sobrien    return 0;
158360510Sobrien
158460510Sobrien  return symval + 8;
158560510Sobrien}
158660510Sobrien
158760510Sobrienstatic boolean
1588104841Sobrienelf64_alpha_relax_got_load (info, symval, irel, r_type)
158960510Sobrien     struct alpha_relax_info *info;
159060510Sobrien     bfd_vma symval;
159160510Sobrien     Elf_Internal_Rela *irel;
1592104841Sobrien     unsigned long r_type;
159360510Sobrien{
159460510Sobrien  unsigned int insn;
159560510Sobrien  bfd_signed_vma disp;
159660510Sobrien
159760510Sobrien  /* Get the instruction.  */
159860510Sobrien  insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset);
159960510Sobrien
160060510Sobrien  if (insn >> 26 != OP_LDQ)
160160510Sobrien    {
1602104841Sobrien      reloc_howto_type *howto = elf64_alpha_howto_table + r_type;
160360510Sobrien      ((*_bfd_error_handler)
1604104841Sobrien       ("%s: %s+0x%lx: warning: %s relocation against unexpected insn",
160589862Sobrien	bfd_archive_filename (info->abfd), info->sec->name,
1606104841Sobrien	(unsigned long) irel->r_offset, howto->name));
160760510Sobrien      return true;
160860510Sobrien    }
160960510Sobrien
1610104841Sobrien  /* Can't relax dynamic symbols.  */
1611104841Sobrien  if (alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info))
1612104841Sobrien    return true;
161360510Sobrien
1614104841Sobrien  /* Can't use local-exec relocations in shared libraries.  */
1615104841Sobrien  if (r_type == R_ALPHA_GOTTPREL && info->link_info->shared)
1616104841Sobrien    return true;
1617104841Sobrien
1618104841Sobrien  if (r_type == R_ALPHA_LITERAL)
1619104841Sobrien    disp = symval - info->gp;
1620104841Sobrien  else
1621104841Sobrien    {
1622104841Sobrien      bfd_vma dtp_base, tp_base;
1623104841Sobrien
1624104841Sobrien      BFD_ASSERT (info->tls_segment != NULL);
1625104841Sobrien      dtp_base = alpha_get_dtprel_base (info->tls_segment);
1626104841Sobrien      tp_base = alpha_get_tprel_base (info->tls_segment);
1627104841Sobrien      disp = symval - (r_type == R_ALPHA_GOTDTPREL ? dtp_base : tp_base);
1628104841Sobrien    }
1629104841Sobrien
163060510Sobrien  if (disp < -0x8000 || disp >= 0x8000)
163160510Sobrien    return true;
163260510Sobrien
1633104841Sobrien  /* Exchange LDQ for LDA.  In the case of the TLS relocs, we're loading
1634104841Sobrien     a constant, so force the base register to be $31.  */
1635104841Sobrien  if (r_type == R_ALPHA_LITERAL)
1636104841Sobrien    insn = (OP_LDA << 26) | (insn & 0x03ff0000);
1637104841Sobrien  else
1638104841Sobrien    insn = (OP_LDA << 26) | (insn & (31 << 21)) | (31 << 16);
163989862Sobrien  bfd_put_32 (info->abfd, (bfd_vma) insn, info->contents + irel->r_offset);
164060510Sobrien  info->changed_contents = true;
164160510Sobrien
1642104841Sobrien  switch (r_type)
1643104841Sobrien    {
1644104841Sobrien    case R_ALPHA_LITERAL:
1645104841Sobrien      r_type = R_ALPHA_GPREL16;
1646104841Sobrien      break;
1647104841Sobrien    case R_ALPHA_GOTDTPREL:
1648104841Sobrien      r_type = R_ALPHA_DTPREL16;
1649104841Sobrien      break;
1650104841Sobrien    case R_ALPHA_GOTTPREL:
1651104841Sobrien      r_type = R_ALPHA_TPREL16;
1652104841Sobrien      break;
1653104841Sobrien    default:
1654104841Sobrien      BFD_ASSERT (0);
1655104841Sobrien      return false;
1656104841Sobrien    }
1657104841Sobrien
1658104841Sobrien  irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), r_type);
165960510Sobrien  info->changed_relocs = true;
166060510Sobrien
166160510Sobrien  /* Reduce the use count on this got entry by one, possibly
166260510Sobrien     eliminating it.  */
1663104841Sobrien  if (--info->gotent->use_count == 0)
1664104841Sobrien    {
1665104841Sobrien      int sz = alpha_got_entry_size (r_type);
1666104841Sobrien      alpha_elf_tdata (info->gotobj)->total_got_size -= sz;
1667104841Sobrien      if (!info->h)
1668104841Sobrien	alpha_elf_tdata (info->gotobj)->local_got_size -= sz;
1669104841Sobrien    }
167060510Sobrien
167160510Sobrien  /* ??? Search forward through this basic block looking for insns
167260510Sobrien     that use the target register.  Stop after an insn modifying the
167360510Sobrien     register is seen, or after a branch or call.
167460510Sobrien
167560510Sobrien     Any such memory load insn may be substituted by a load directly
167660510Sobrien     off the GP.  This allows the memory load insn to be issued before
167777303Sobrien     the calculated GP register would otherwise be ready.
167860510Sobrien
167960510Sobrien     Any such jsr insn can be replaced by a bsr if it is in range.
168060510Sobrien
168160510Sobrien     This would mean that we'd have to _add_ relocations, the pain of
168260510Sobrien     which gives one pause.  */
168360510Sobrien
168460510Sobrien  return true;
168560510Sobrien}
168660510Sobrien
168760510Sobrienstatic boolean
1688104841Sobrienelf64_alpha_relax_gprelhilo (info, symval, irel, hi)
1689104841Sobrien     struct alpha_relax_info *info;
1690104841Sobrien     bfd_vma symval;
1691104841Sobrien     Elf_Internal_Rela *irel;
1692104841Sobrien     boolean hi;
1693104841Sobrien{
1694104841Sobrien  unsigned int insn;
1695104841Sobrien  bfd_signed_vma disp;
1696104841Sobrien  bfd_byte *pos = info->contents + irel->r_offset;
1697104841Sobrien
1698104841Sobrien  /* ??? This assumes that the compiler doesn't render
1699104841Sobrien
1700104841Sobrien	array[i]
1701104841Sobrien     as
1702104841Sobrien	ldah	t, array(gp)	!gprelhigh
1703104841Sobrien	s8addl	i, t, t
1704104841Sobrien	ldq	r, array(t)	!gprellow
1705104841Sobrien
1706104841Sobrien     which would indeed be the most efficient way to implement this.  */
1707104841Sobrien
1708104841Sobrien  return true;
1709104841Sobrien
1710104841Sobrien  disp = symval - info->gp;
1711104841Sobrien  if (disp < -0x8000 || disp >= 0x8000)
1712104841Sobrien    return true;
1713104841Sobrien
1714104841Sobrien  if (hi)
1715104841Sobrien    {
1716104841Sobrien      /* Nop out the high instruction.  */
1717104841Sobrien
1718104841Sobrien      bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos);
1719104841Sobrien      info->changed_contents = true;
1720104841Sobrien
1721104841Sobrien      irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
1722104841Sobrien      irel->r_addend = 0;
1723104841Sobrien      info->changed_relocs = true;
1724104841Sobrien    }
1725104841Sobrien  else
1726104841Sobrien    {
1727104841Sobrien      /* Adjust the low instruction to reference GP directly.  */
1728104841Sobrien
1729104841Sobrien      insn = bfd_get_32 (info->abfd, pos);
1730104841Sobrien      insn = (insn & 0xffe00000) | (29 << 16);
1731104841Sobrien      bfd_put_32 (info->abfd, (bfd_vma) insn, pos);
1732104841Sobrien      info->changed_contents = true;
1733104841Sobrien
1734104841Sobrien      irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
1735104841Sobrien				   R_ALPHA_GPREL16);
1736104841Sobrien      info->changed_relocs = true;
1737104841Sobrien    }
1738104841Sobrien
1739104841Sobrien  return true;
1740104841Sobrien}
1741104841Sobrien
1742104841Sobrienstatic boolean
1743104841Sobrienelf64_alpha_relax_tls_get_addr (info, symval, irel, is_gd)
1744104841Sobrien     struct alpha_relax_info *info;
1745104841Sobrien     bfd_vma symval;
1746104841Sobrien     Elf_Internal_Rela *irel;
1747104841Sobrien     boolean is_gd;
1748104841Sobrien{
1749104841Sobrien  bfd_byte *pos[5];
1750104841Sobrien  unsigned int insn;
1751104841Sobrien  Elf_Internal_Rela *gpdisp, *hint;
1752104841Sobrien  boolean dynamic, use_gottprel;
1753104841Sobrien
1754104841Sobrien  dynamic = alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info);
1755104841Sobrien
1756104841Sobrien  /* ??? For LD relaxation, we need a symbol referencing the beginning
1757104841Sobrien     of the TLS segment.  */
1758104841Sobrien  if (!is_gd)
1759104841Sobrien    return true;
1760104841Sobrien
1761104841Sobrien  /* If a TLS symbol is accessed using IE at least once, there is no point
1762104841Sobrien     to use dynamic model for it.  */
1763104841Sobrien  if (is_gd && info->h && (info->h->flags & ALPHA_ELF_LINK_HASH_TLS_IE))
1764104841Sobrien    ;
1765104841Sobrien
1766104841Sobrien  /* If the symbol is local, and we've already committed to DF_STATIC_TLS,
1767104841Sobrien     then we might as well relax to IE.  */
1768104841Sobrien  else if (info->link_info->shared && !dynamic
1769104841Sobrien	   && (info->link_info->flags & DF_STATIC_TLS))
1770104841Sobrien    ;
1771104841Sobrien
1772104841Sobrien  /* Otherwise we must be building an executable to do anything.  */
1773104841Sobrien  else if (info->link_info->shared)
1774104841Sobrien    return true;
1775104841Sobrien
1776104841Sobrien  /* The TLSGD/TLSLDM relocation must be followed by a LITERAL and
1777104841Sobrien     the matching LITUSE_TLS relocations.  */
1778104841Sobrien  if (irel + 2 >= info->relend)
1779104841Sobrien    return true;
1780104841Sobrien  if (ELF64_R_TYPE (irel[1].r_info) != R_ALPHA_LITERAL
1781104841Sobrien      || ELF64_R_TYPE (irel[2].r_info) != R_ALPHA_LITUSE
1782104841Sobrien      || irel[2].r_addend != (is_gd ? LITUSE_ALPHA_TLSGD : LITUSE_ALPHA_TLSLDM))
1783104841Sobrien    return true;
1784104841Sobrien
1785104841Sobrien  /* There must be a GPDISP relocation positioned immediately after the
1786104841Sobrien     LITUSE relocation.  */
1787104841Sobrien  gpdisp = elf64_alpha_find_reloc_at_ofs (info->relocs, info->relend,
1788104841Sobrien					  irel[2].r_offset + 4, R_ALPHA_GPDISP);
1789104841Sobrien  if (!gpdisp)
1790104841Sobrien    return true;
1791104841Sobrien
1792104841Sobrien  pos[0] = info->contents + irel[0].r_offset;
1793104841Sobrien  pos[1] = info->contents + irel[1].r_offset;
1794104841Sobrien  pos[2] = info->contents + irel[2].r_offset;
1795104841Sobrien  pos[3] = info->contents + gpdisp->r_offset;
1796104841Sobrien  pos[4] = pos[3] + gpdisp->r_addend;
1797104841Sobrien
1798104841Sobrien  /* Only positions 0 and 1 are allowed to be out of order.  */
1799104841Sobrien  if (pos[1] < pos[0])
1800104841Sobrien    {
1801104841Sobrien      bfd_byte *tmp = pos[0];
1802104841Sobrien      pos[0] = pos[1];
1803104841Sobrien      pos[1] = tmp;
1804104841Sobrien    }
1805104841Sobrien  if (pos[1] >= pos[2] || pos[2] >= pos[3] || pos[3] >= pos[4])
1806104841Sobrien    return true;
1807104841Sobrien
1808104841Sobrien  /* Reduce the use count on the LITERAL relocation.  Do this before we
1809104841Sobrien     smash the symndx when we adjust the relocations below.  */
1810104841Sobrien  {
1811104841Sobrien    struct alpha_elf_got_entry *lit_gotent;
1812104841Sobrien    struct alpha_elf_link_hash_entry *lit_h;
1813104841Sobrien    unsigned long indx;
1814104841Sobrien
1815104841Sobrien    BFD_ASSERT (ELF64_R_SYM (irel[1].r_info) >= info->symtab_hdr->sh_info);
1816104841Sobrien    indx = ELF64_R_SYM (irel[1].r_info) - info->symtab_hdr->sh_info;
1817104841Sobrien    lit_h = alpha_elf_sym_hashes (info->abfd)[indx];
1818104841Sobrien
1819104841Sobrien    while (lit_h->root.root.type == bfd_link_hash_indirect
1820104841Sobrien	   || lit_h->root.root.type == bfd_link_hash_warning)
1821104841Sobrien      lit_h = (struct alpha_elf_link_hash_entry *) lit_h->root.root.u.i.link;
1822104841Sobrien
1823104841Sobrien    for (lit_gotent = lit_h->got_entries; lit_gotent ;
1824104841Sobrien	 lit_gotent = lit_gotent->next)
1825104841Sobrien      if (lit_gotent->gotobj == info->gotobj
1826104841Sobrien	  && lit_gotent->reloc_type == R_ALPHA_LITERAL
1827104841Sobrien	  && lit_gotent->addend == irel[1].r_addend)
1828104841Sobrien	break;
1829104841Sobrien    BFD_ASSERT (lit_gotent);
1830104841Sobrien
1831104841Sobrien    if (--lit_gotent->use_count == 0)
1832104841Sobrien      {
1833104841Sobrien	int sz = alpha_got_entry_size (R_ALPHA_LITERAL);
1834104841Sobrien	alpha_elf_tdata (info->gotobj)->total_got_size -= sz;
1835104841Sobrien      }
1836104841Sobrien  }
1837104841Sobrien
1838104841Sobrien  /* Change
1839104841Sobrien
1840104841Sobrien	lda	$16,x($gp)		!tlsgd!1
1841104841Sobrien	ldq	$27,__tls_get_addr($gp)	!literal!1
1842104841Sobrien	jsr	$26,($27)__tls_get_addr	!lituse_tlsgd!1
1843104841Sobrien	ldah	$29,0($26)		!gpdisp!2
1844104841Sobrien	lda	$29,0($29)		!gpdisp!2
1845104841Sobrien     to
1846104841Sobrien	ldq	$16,x($gp)		!gottprel
1847104841Sobrien	unop
1848104841Sobrien	call_pal rduniq
1849104841Sobrien	addq	$16,$0,$0
1850104841Sobrien	unop
1851104841Sobrien     or the first pair to
1852104841Sobrien	lda	$16,x($gp)		!tprel
1853104841Sobrien	unop
1854104841Sobrien     or
1855104841Sobrien	ldah	$16,x($gp)		!tprelhi
1856104841Sobrien	lda	$16,x($16)		!tprello
1857104841Sobrien
1858104841Sobrien     as appropriate.  */
1859104841Sobrien
1860104841Sobrien  use_gottprel = false;
1861104841Sobrien  switch (!dynamic && !info->link_info->shared)
1862104841Sobrien    {
1863104841Sobrien    case 1:
1864104841Sobrien      {
1865104841Sobrien	bfd_vma tp_base;
1866104841Sobrien	bfd_signed_vma disp;
1867104841Sobrien
1868104841Sobrien	BFD_ASSERT (info->tls_segment != NULL);
1869104841Sobrien	tp_base = alpha_get_tprel_base (info->tls_segment);
1870104841Sobrien	disp = symval - tp_base;
1871104841Sobrien
1872104841Sobrien	if (disp >= -0x8000 && disp < 0x8000)
1873104841Sobrien	  {
1874104841Sobrien	    insn = (OP_LDA << 26) | (16 << 21) | (31 << 16);
1875104841Sobrien	    bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]);
1876104841Sobrien	    bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]);
1877104841Sobrien
1878104841Sobrien	    irel[0].r_offset = pos[0] - info->contents;
1879104841Sobrien	    irel[0].r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
1880104841Sobrien					   R_ALPHA_TPREL16);
1881104841Sobrien	    irel[1].r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
1882104841Sobrien	    break;
1883104841Sobrien	  }
1884104841Sobrien	else if (disp >= -(bfd_signed_vma) 0x80000000
1885104841Sobrien		 && disp < (bfd_signed_vma) 0x7fff8000)
1886104841Sobrien	  {
1887104841Sobrien	    insn = (OP_LDAH << 26) | (16 << 21) | (31 << 16);
1888104841Sobrien	    bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]);
1889104841Sobrien	    insn = (OP_LDA << 26) | (16 << 21) | (16 << 16);
1890104841Sobrien	    bfd_put_32 (info->abfd, (bfd_vma) insn, pos[1]);
1891104841Sobrien
1892104841Sobrien	    irel[0].r_offset = pos[0] - info->contents;
1893104841Sobrien	    irel[0].r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
1894104841Sobrien					   R_ALPHA_TPRELHI);
1895104841Sobrien	    irel[1].r_offset = pos[1] - info->contents;
1896104841Sobrien	    irel[1].r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
1897104841Sobrien					   R_ALPHA_TPRELLO);
1898104841Sobrien	    break;
1899104841Sobrien	  }
1900104841Sobrien      }
1901104841Sobrien      /* FALLTHRU */
1902104841Sobrien
1903104841Sobrien    default:
1904104841Sobrien      use_gottprel = true;
1905104841Sobrien
1906104841Sobrien      insn = (OP_LDQ << 26) | (16 << 21) | (29 << 16);
1907104841Sobrien      bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]);
1908104841Sobrien      bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]);
1909104841Sobrien
1910104841Sobrien      irel[0].r_offset = pos[0] - info->contents;
1911104841Sobrien      irel[0].r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
1912104841Sobrien				     R_ALPHA_GOTTPREL);
1913104841Sobrien      irel[1].r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
1914104841Sobrien      break;
1915104841Sobrien    }
1916104841Sobrien
1917104841Sobrien  bfd_put_32 (info->abfd, (bfd_vma) INSN_RDUNIQ, pos[2]);
1918104841Sobrien
1919104841Sobrien  insn = INSN_ADDQ | (16 << 21) | (0 << 16) | (0 << 0);
1920104841Sobrien  bfd_put_32 (info->abfd, (bfd_vma) insn, pos[3]);
1921104841Sobrien
1922104841Sobrien  bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[4]);
1923104841Sobrien
1924104841Sobrien  irel[2].r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
1925104841Sobrien  gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
1926104841Sobrien
1927104841Sobrien  hint = elf64_alpha_find_reloc_at_ofs (info->relocs, info->relend,
1928104841Sobrien					irel[2].r_offset, R_ALPHA_HINT);
1929104841Sobrien  if (hint)
1930104841Sobrien    hint->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
1931104841Sobrien
1932104841Sobrien  info->changed_contents = true;
1933104841Sobrien  info->changed_relocs = true;
1934104841Sobrien
1935104841Sobrien  /* Reduce the use count on the TLSGD/TLSLDM relocation.  */
1936104841Sobrien  if (--info->gotent->use_count == 0)
1937104841Sobrien    {
1938104841Sobrien      int sz = alpha_got_entry_size (info->gotent->reloc_type);
1939104841Sobrien      alpha_elf_tdata (info->gotobj)->total_got_size -= sz;
1940104841Sobrien      if (!info->h)
1941104841Sobrien	alpha_elf_tdata (info->gotobj)->local_got_size -= sz;
1942104841Sobrien    }
1943104841Sobrien
1944104841Sobrien  /* If we've switched to a GOTTPREL relocation, increment the reference
1945104841Sobrien     count on that got entry.  */
1946104841Sobrien  if (use_gottprel)
1947104841Sobrien    {
1948104841Sobrien      struct alpha_elf_got_entry *tprel_gotent;
1949104841Sobrien
1950104841Sobrien      for (tprel_gotent = *info->first_gotent; tprel_gotent ;
1951104841Sobrien	   tprel_gotent = tprel_gotent->next)
1952104841Sobrien	if (tprel_gotent->gotobj == info->gotobj
1953104841Sobrien	    && tprel_gotent->reloc_type == R_ALPHA_GOTTPREL
1954104841Sobrien	    && tprel_gotent->addend == irel->r_addend)
1955104841Sobrien	  break;
1956104841Sobrien      if (tprel_gotent)
1957104841Sobrien	tprel_gotent->use_count++;
1958104841Sobrien      else
1959104841Sobrien	{
1960104841Sobrien	  if (info->gotent->use_count == 0)
1961104841Sobrien	    tprel_gotent = info->gotent;
1962104841Sobrien	  else
1963104841Sobrien	    {
1964104841Sobrien	      tprel_gotent = (struct alpha_elf_got_entry *)
1965104841Sobrien		bfd_alloc (info->abfd, sizeof (struct alpha_elf_got_entry));
1966104841Sobrien	      if (!tprel_gotent)
1967104841Sobrien		return false;
1968104841Sobrien
1969104841Sobrien	      tprel_gotent->next = *info->first_gotent;
1970104841Sobrien	      *info->first_gotent = tprel_gotent;
1971104841Sobrien
1972104841Sobrien	      tprel_gotent->gotobj = info->gotobj;
1973104841Sobrien	      tprel_gotent->addend = irel->r_addend;
1974104841Sobrien	      tprel_gotent->got_offset = -1;
1975104841Sobrien	      tprel_gotent->reloc_done = 0;
1976104841Sobrien	      tprel_gotent->reloc_xlated = 0;
1977104841Sobrien	    }
1978104841Sobrien
1979104841Sobrien	  tprel_gotent->use_count = 1;
1980104841Sobrien	  tprel_gotent->reloc_type = R_ALPHA_GOTTPREL;
1981104841Sobrien	}
1982104841Sobrien    }
1983104841Sobrien
1984104841Sobrien  return true;
1985104841Sobrien}
1986104841Sobrien
1987104841Sobrienstatic struct elf_link_tls_segment *
1988104841Sobrienelf64_alpha_relax_find_tls_segment (info, seg)
1989104841Sobrien     struct alpha_relax_info *info;
1990104841Sobrien     struct elf_link_tls_segment *seg;
1991104841Sobrien{
1992104841Sobrien  bfd *output_bfd = info->sec->output_section->owner;
1993104841Sobrien  asection *o;
1994104841Sobrien  unsigned int align;
1995104841Sobrien  bfd_vma base, end;
1996104841Sobrien
1997104841Sobrien  for (o = output_bfd->sections; o ; o = o->next)
1998104841Sobrien    if ((o->flags & SEC_THREAD_LOCAL) != 0
1999104841Sobrien        && (o->flags & SEC_LOAD) != 0)
2000104841Sobrien      break;
2001104841Sobrien  if (!o)
2002104841Sobrien    return NULL;
2003104841Sobrien
2004104841Sobrien  base = o->vma;
2005104841Sobrien  align = 0;
2006104841Sobrien
2007104841Sobrien  do
2008104841Sobrien    {
2009104841Sobrien      bfd_vma size;
2010104841Sobrien
2011104841Sobrien      if (bfd_get_section_alignment (output_bfd, o) > align)
2012104841Sobrien	align = bfd_get_section_alignment (output_bfd, o);
2013104841Sobrien
2014104841Sobrien      size = o->_raw_size;
2015104841Sobrien      if (size == 0 && (o->flags & SEC_HAS_CONTENTS) == 0)
2016104841Sobrien	{
2017104841Sobrien	  struct bfd_link_order *lo;
2018104841Sobrien	  for (lo = o->link_order_head; lo ; lo = lo->next)
2019104841Sobrien	    if (size < lo->offset + lo->size)
2020104841Sobrien	      size = lo->offset + lo->size;
2021104841Sobrien	}
2022104841Sobrien      end = o->vma + size;
2023104841Sobrien      o = o->next;
2024104841Sobrien    }
2025104841Sobrien  while (o && (o->flags & SEC_THREAD_LOCAL));
2026104841Sobrien
2027104841Sobrien  seg->start = base;
2028104841Sobrien  seg->size = end - base;
2029104841Sobrien  seg->align = align;
2030104841Sobrien
2031104841Sobrien  return seg;
2032104841Sobrien}
2033104841Sobrien
2034104841Sobrienstatic boolean
203560510Sobrienelf64_alpha_relax_section (abfd, sec, link_info, again)
203660510Sobrien     bfd *abfd;
203760510Sobrien     asection *sec;
203860510Sobrien     struct bfd_link_info *link_info;
203960510Sobrien     boolean *again;
204060510Sobrien{
204160510Sobrien  Elf_Internal_Shdr *symtab_hdr;
204260510Sobrien  Elf_Internal_Rela *internal_relocs;
204360510Sobrien  Elf_Internal_Rela *irel, *irelend;
2044104841Sobrien  Elf_Internal_Sym *isymbuf = NULL;
204560510Sobrien  struct alpha_elf_got_entry **local_got_entries;
204660510Sobrien  struct alpha_relax_info info;
2047104841Sobrien  struct elf_link_tls_segment tls_segment;
204860510Sobrien
204960510Sobrien  /* We are not currently changing any sizes, so only one pass.  */
205060510Sobrien  *again = false;
205160510Sobrien
205260510Sobrien  if (link_info->relocateable
205360510Sobrien      || (sec->flags & SEC_RELOC) == 0
205460510Sobrien      || sec->reloc_count == 0)
205560510Sobrien    return true;
205660510Sobrien
205760510Sobrien  /* If this is the first time we have been called for this section,
205860510Sobrien     initialize the cooked size.  */
205960510Sobrien  if (sec->_cooked_size == 0)
206060510Sobrien    sec->_cooked_size = sec->_raw_size;
206160510Sobrien
206260510Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
206360510Sobrien  local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
206460510Sobrien
206560510Sobrien  /* Load the relocations for this section.  */
206660510Sobrien  internal_relocs = (_bfd_elf64_link_read_relocs
206760510Sobrien		     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
206860510Sobrien		      link_info->keep_memory));
206960510Sobrien  if (internal_relocs == NULL)
2070104841Sobrien    return false;
207160510Sobrien
207277303Sobrien  memset(&info, 0, sizeof (info));
207360510Sobrien  info.abfd = abfd;
207460510Sobrien  info.sec = sec;
207560510Sobrien  info.link_info = link_info;
2076104841Sobrien  info.symtab_hdr = symtab_hdr;
207760510Sobrien  info.relocs = internal_relocs;
207860510Sobrien  info.relend = irelend = internal_relocs + sec->reloc_count;
207960510Sobrien
2080104841Sobrien  /* Find the GP for this object.  Do not store the result back via
2081104841Sobrien     _bfd_set_gp_value, since this could change again before final.  */
208260510Sobrien  info.gotobj = alpha_elf_tdata (abfd)->gotobj;
208360510Sobrien  if (info.gotobj)
208460510Sobrien    {
208560510Sobrien      asection *sgot = alpha_elf_tdata (info.gotobj)->got;
2086104841Sobrien      info.gp = (sgot->output_section->vma
2087104841Sobrien		 + sgot->output_offset
2088104841Sobrien		 + 0x8000);
208960510Sobrien    }
209060510Sobrien
2091104841Sobrien  /* Get the section contents.  */
2092104841Sobrien  if (elf_section_data (sec)->this_hdr.contents != NULL)
2093104841Sobrien    info.contents = elf_section_data (sec)->this_hdr.contents;
2094104841Sobrien  else
2095104841Sobrien    {
2096104841Sobrien      info.contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
2097104841Sobrien      if (info.contents == NULL)
2098104841Sobrien	goto error_return;
2099104841Sobrien
2100104841Sobrien      if (! bfd_get_section_contents (abfd, sec, info.contents,
2101104841Sobrien				      (file_ptr) 0, sec->_raw_size))
2102104841Sobrien	goto error_return;
2103104841Sobrien    }
2104104841Sobrien
2105104841Sobrien  /* Compute the TLS segment information.  The version normally found in
2106104841Sobrien     elf_hash_table (link_info)->tls_segment isn't built until final_link.
2107104841Sobrien     ??? Probably should look into extracting this into a common function.  */
2108104841Sobrien  info.tls_segment = elf64_alpha_relax_find_tls_segment (&info, &tls_segment);
2109104841Sobrien
211060510Sobrien  for (irel = internal_relocs; irel < irelend; irel++)
211160510Sobrien    {
211260510Sobrien      bfd_vma symval;
211360510Sobrien      struct alpha_elf_got_entry *gotent;
2114104841Sobrien      unsigned long r_type = ELF64_R_TYPE (irel->r_info);
211560510Sobrien
2116104841Sobrien      /* Early exit for unhandled or unrelaxable relocations.  */
2117104841Sobrien      switch (r_type)
211860510Sobrien	{
2119104841Sobrien	case R_ALPHA_LITERAL:
2120104841Sobrien	case R_ALPHA_GPRELHIGH:
2121104841Sobrien	case R_ALPHA_GPRELLOW:
2122104841Sobrien	case R_ALPHA_GOTDTPREL:
2123104841Sobrien	case R_ALPHA_GOTTPREL:
2124104841Sobrien	case R_ALPHA_TLSGD:
2125104841Sobrien	case R_ALPHA_TLSLDM:
2126104841Sobrien	  break;
2127104841Sobrien	default:
2128104841Sobrien	  continue;
212960510Sobrien	}
213060510Sobrien
2131104841Sobrien      /* Get the value of the symbol referred to by the reloc.  */
2132104841Sobrien      if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
213360510Sobrien	{
2134104841Sobrien	  /* A local symbol.  */
2135104841Sobrien	  Elf_Internal_Sym *isym;
213689862Sobrien
2137104841Sobrien	  /* Read this BFD's local symbols.  */
2138104841Sobrien	  if (isymbuf == NULL)
213960510Sobrien	    {
2140104841Sobrien	      isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
2141104841Sobrien	      if (isymbuf == NULL)
2142104841Sobrien		isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
2143104841Sobrien						symtab_hdr->sh_info, 0,
2144104841Sobrien						NULL, NULL, NULL);
2145104841Sobrien	      if (isymbuf == NULL)
214660510Sobrien		goto error_return;
214760510Sobrien	    }
214889862Sobrien
2149104841Sobrien	  isym = isymbuf + ELF64_R_SYM (irel->r_info);
2150104841Sobrien	  if (isym->st_shndx == SHN_UNDEF)
2151104841Sobrien	    continue;
2152104841Sobrien	  else if (isym->st_shndx == SHN_ABS)
215360510Sobrien	    info.tsec = bfd_abs_section_ptr;
2154104841Sobrien	  else if (isym->st_shndx == SHN_COMMON)
215560510Sobrien	    info.tsec = bfd_com_section_ptr;
215677303Sobrien	  else
2157104841Sobrien	    info.tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
215860510Sobrien
215960510Sobrien	  info.h = NULL;
2160104841Sobrien	  info.other = isym->st_other;
2161104841Sobrien	  info.first_gotent = &local_got_entries[ELF64_R_SYM(irel->r_info)];
2162104841Sobrien	  symval = isym->st_value;
216360510Sobrien	}
216460510Sobrien      else
216560510Sobrien	{
216660510Sobrien	  unsigned long indx;
216760510Sobrien	  struct alpha_elf_link_hash_entry *h;
216860510Sobrien
216960510Sobrien	  indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info;
217060510Sobrien	  h = alpha_elf_sym_hashes (abfd)[indx];
217160510Sobrien	  BFD_ASSERT (h != NULL);
217260510Sobrien
217360510Sobrien	  while (h->root.root.type == bfd_link_hash_indirect
217460510Sobrien		 || h->root.root.type == bfd_link_hash_warning)
217560510Sobrien	    h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
217660510Sobrien
2177104841Sobrien	  /* If the symbol is undefined, we can't do anything with it.  */
2178104841Sobrien	  if (h->root.root.type == bfd_link_hash_undefweak
2179104841Sobrien	      || h->root.root.type == bfd_link_hash_undefined)
218060510Sobrien	    continue;
218160510Sobrien
2182104841Sobrien	  /* If the symbol isn't defined in the current module, again
2183104841Sobrien	     we can't do anything.  */
2184104841Sobrien	  if (!(h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
2185104841Sobrien	    continue;
2186104841Sobrien
218760510Sobrien	  info.h = h;
218860510Sobrien	  info.tsec = h->root.root.u.def.section;
218960510Sobrien	  info.other = h->root.other;
2190104841Sobrien	  info.first_gotent = &h->got_entries;
219160510Sobrien	  symval = h->root.root.u.def.value;
219260510Sobrien	}
219360510Sobrien
219460510Sobrien      /* Search for the got entry to be used by this relocation.  */
2195104841Sobrien      for (gotent = *info.first_gotent; gotent ; gotent = gotent->next)
2196104841Sobrien	if (gotent->gotobj == info.gotobj
2197104841Sobrien	    && gotent->reloc_type == r_type
2198104841Sobrien	    && gotent->addend == irel->r_addend)
2199104841Sobrien	  break;
220060510Sobrien      info.gotent = gotent;
220160510Sobrien
220260510Sobrien      symval += info.tsec->output_section->vma + info.tsec->output_offset;
220360510Sobrien      symval += irel->r_addend;
220460510Sobrien
2205104841Sobrien      switch (r_type)
2206104841Sobrien	{
2207104841Sobrien	case R_ALPHA_LITERAL:
2208104841Sobrien	  BFD_ASSERT(info.gotent != NULL);
220960510Sobrien
2210104841Sobrien	  /* If there exist LITUSE relocations immediately following, this
2211104841Sobrien	     opens up all sorts of interesting optimizations, because we
2212104841Sobrien	     now know every location that this address load is used.  */
2213104841Sobrien	  if (irel+1 < irelend
2214104841Sobrien	      && ELF64_R_TYPE (irel[1].r_info) == R_ALPHA_LITUSE)
2215104841Sobrien	    {
2216104841Sobrien	      if (!elf64_alpha_relax_with_lituse (&info, symval, irel))
2217104841Sobrien		goto error_return;
2218104841Sobrien	    }
2219104841Sobrien	  else
2220104841Sobrien	    {
2221104841Sobrien	      if (!elf64_alpha_relax_got_load (&info, symval, irel, r_type))
2222104841Sobrien		goto error_return;
2223104841Sobrien	    }
2224104841Sobrien	  break;
222560510Sobrien
2226104841Sobrien	case R_ALPHA_GPRELHIGH:
2227104841Sobrien	case R_ALPHA_GPRELLOW:
2228104841Sobrien	  if (!elf64_alpha_relax_gprelhilo (&info, symval, irel,
2229104841Sobrien					    r_type == R_ALPHA_GPRELHIGH))
223060510Sobrien	    goto error_return;
2231104841Sobrien	  break;
2232104841Sobrien
2233104841Sobrien	case R_ALPHA_GOTDTPREL:
2234104841Sobrien	case R_ALPHA_GOTTPREL:
2235104841Sobrien	  BFD_ASSERT(info.gotent != NULL);
2236104841Sobrien	  if (!elf64_alpha_relax_got_load (&info, symval, irel, r_type))
223760510Sobrien	    goto error_return;
2238104841Sobrien	  break;
2239104841Sobrien
2240104841Sobrien	case R_ALPHA_TLSGD:
2241104841Sobrien	case R_ALPHA_TLSLDM:
2242104841Sobrien	  BFD_ASSERT(info.gotent != NULL);
2243104841Sobrien	  if (!elf64_alpha_relax_tls_get_addr (&info, symval, irel,
2244104841Sobrien					       r_type == R_ALPHA_TLSGD))
2245104841Sobrien	    goto error_return;
2246104841Sobrien	  break;
224760510Sobrien	}
224860510Sobrien    }
224960510Sobrien
2250104841Sobrien  if (!elf64_alpha_size_plt_section (link_info))
225160510Sobrien    return false;
2252104841Sobrien  if (!elf64_alpha_size_got_sections (link_info))
2253104841Sobrien    return false;
2254104841Sobrien  if (!elf64_alpha_size_rela_got_section (link_info))
2255104841Sobrien    return false;
225660510Sobrien
2257104841Sobrien  if (isymbuf != NULL
2258104841Sobrien      && symtab_hdr->contents != (unsigned char *) isymbuf)
225960510Sobrien    {
2260104841Sobrien      if (!link_info->keep_memory)
2261104841Sobrien	free (isymbuf);
2262104841Sobrien      else
2263104841Sobrien	{
2264104841Sobrien	  /* Cache the symbols for elf_link_input_bfd.  */
2265104841Sobrien	  symtab_hdr->contents = (unsigned char *) isymbuf;
2266104841Sobrien	}
226760510Sobrien    }
226860510Sobrien
2269104841Sobrien  if (info.contents != NULL
2270104841Sobrien      && elf_section_data (sec)->this_hdr.contents != info.contents)
227160510Sobrien    {
2272104841Sobrien      if (!info.changed_contents && !link_info->keep_memory)
2273104841Sobrien	free (info.contents);
227460510Sobrien      else
227560510Sobrien	{
227660510Sobrien	  /* Cache the section contents for elf_link_input_bfd.  */
227760510Sobrien	  elf_section_data (sec)->this_hdr.contents = info.contents;
227860510Sobrien	}
227960510Sobrien    }
228060510Sobrien
2281104841Sobrien  if (elf_section_data (sec)->relocs != internal_relocs)
228260510Sobrien    {
2283104841Sobrien      if (!info.changed_relocs)
2284104841Sobrien	free (internal_relocs);
228560510Sobrien      else
2286104841Sobrien	elf_section_data (sec)->relocs = internal_relocs;
228760510Sobrien    }
228860510Sobrien
228960510Sobrien  *again = info.changed_contents || info.changed_relocs;
229060510Sobrien
229160510Sobrien  return true;
229260510Sobrien
229360510Sobrien error_return:
2294104841Sobrien  if (isymbuf != NULL
2295104841Sobrien      && symtab_hdr->contents != (unsigned char *) isymbuf)
2296104841Sobrien    free (isymbuf);
2297104841Sobrien  if (info.contents != NULL
2298104841Sobrien      && elf_section_data (sec)->this_hdr.contents != info.contents)
2299104841Sobrien    free (info.contents);
2300104841Sobrien  if (internal_relocs != NULL
2301104841Sobrien      && elf_section_data (sec)->relocs != internal_relocs)
2302104841Sobrien    free (internal_relocs);
230360510Sobrien  return false;
230460510Sobrien}
230560510Sobrien
230633965Sjdp/* PLT/GOT Stuff */
230733965Sjdp#define PLT_HEADER_SIZE 32
230889862Sobrien#define PLT_HEADER_WORD1	(bfd_vma) 0xc3600000	/* br   $27,.+4     */
230989862Sobrien#define PLT_HEADER_WORD2	(bfd_vma) 0xa77b000c	/* ldq  $27,12($27) */
231089862Sobrien#define PLT_HEADER_WORD3	(bfd_vma) 0x47ff041f	/* nop              */
231189862Sobrien#define PLT_HEADER_WORD4	(bfd_vma) 0x6b7b0000	/* jmp  $27,($27)   */
231233965Sjdp
231333965Sjdp#define PLT_ENTRY_SIZE 12
231438889Sjdp#define PLT_ENTRY_WORD1		0xc3800000	/* br   $28, plt0   */
231538889Sjdp#define PLT_ENTRY_WORD2		0
231638889Sjdp#define PLT_ENTRY_WORD3		0
231733965Sjdp
2318104841Sobrien#define MAX_GOT_SIZE		(64*1024)
231933965Sjdp
232068770Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so"
232133965Sjdp
232233965Sjdp/* Handle an Alpha specific section when reading an object file.  This
232333965Sjdp   is called when elfcode.h finds a section with an unknown type.
232460510Sobrien   FIXME: We need to handle the SHF_ALPHA_GPREL flag, but I'm not sure
232533965Sjdp   how to.  */
232633965Sjdp
232733965Sjdpstatic boolean
232833965Sjdpelf64_alpha_section_from_shdr (abfd, hdr, name)
232933965Sjdp     bfd *abfd;
233033965Sjdp     Elf64_Internal_Shdr *hdr;
2331104841Sobrien     const char *name;
233233965Sjdp{
233333965Sjdp  asection *newsect;
233433965Sjdp
233533965Sjdp  /* There ought to be a place to keep ELF backend specific flags, but
233633965Sjdp     at the moment there isn't one.  We just keep track of the
233733965Sjdp     sections by their name, instead.  Fortunately, the ABI gives
233833965Sjdp     suggested names for all the MIPS specific sections, so we will
233933965Sjdp     probably get away with this.  */
234033965Sjdp  switch (hdr->sh_type)
234133965Sjdp    {
234233965Sjdp    case SHT_ALPHA_DEBUG:
234333965Sjdp      if (strcmp (name, ".mdebug") != 0)
234433965Sjdp	return false;
234533965Sjdp      break;
234633965Sjdp    default:
234733965Sjdp      return false;
234833965Sjdp    }
234933965Sjdp
235033965Sjdp  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
235133965Sjdp    return false;
235233965Sjdp  newsect = hdr->bfd_section;
235333965Sjdp
235433965Sjdp  if (hdr->sh_type == SHT_ALPHA_DEBUG)
235533965Sjdp    {
235633965Sjdp      if (! bfd_set_section_flags (abfd, newsect,
235733965Sjdp				   (bfd_get_section_flags (abfd, newsect)
235833965Sjdp				    | SEC_DEBUGGING)))
235933965Sjdp	return false;
236033965Sjdp    }
236133965Sjdp
236289862Sobrien  return true;
236389862Sobrien}
236433965Sjdp
236589862Sobrien/* Convert Alpha specific section flags to bfd internal section flags.  */
236633965Sjdp
236789862Sobrienstatic boolean
236889862Sobrienelf64_alpha_section_flags (flags, hdr)
236989862Sobrien     flagword *flags;
237089862Sobrien     Elf64_Internal_Shdr *hdr;
237189862Sobrien{
237289862Sobrien  if (hdr->sh_flags & SHF_ALPHA_GPREL)
237389862Sobrien    *flags |= SEC_SMALL_DATA;
237489862Sobrien
237533965Sjdp  return true;
237633965Sjdp}
237733965Sjdp
237833965Sjdp/* Set the correct type for an Alpha ELF section.  We do this by the
237933965Sjdp   section name, which is a hack, but ought to work.  */
238033965Sjdp
238133965Sjdpstatic boolean
238233965Sjdpelf64_alpha_fake_sections (abfd, hdr, sec)
238333965Sjdp     bfd *abfd;
238433965Sjdp     Elf64_Internal_Shdr *hdr;
238533965Sjdp     asection *sec;
238633965Sjdp{
238733965Sjdp  register const char *name;
238833965Sjdp
238933965Sjdp  name = bfd_get_section_name (abfd, sec);
239033965Sjdp
239133965Sjdp  if (strcmp (name, ".mdebug") == 0)
239233965Sjdp    {
239333965Sjdp      hdr->sh_type = SHT_ALPHA_DEBUG;
239433965Sjdp      /* In a shared object on Irix 5.3, the .mdebug section has an
239533965Sjdp         entsize of 0.  FIXME: Does this matter?  */
239633965Sjdp      if ((abfd->flags & DYNAMIC) != 0 )
239733965Sjdp	hdr->sh_entsize = 0;
239833965Sjdp      else
239933965Sjdp	hdr->sh_entsize = 1;
240033965Sjdp    }
240189862Sobrien  else if ((sec->flags & SEC_SMALL_DATA)
240289862Sobrien	   || strcmp (name, ".sdata") == 0
240333965Sjdp	   || strcmp (name, ".sbss") == 0
240433965Sjdp	   || strcmp (name, ".lit4") == 0
240533965Sjdp	   || strcmp (name, ".lit8") == 0)
240633965Sjdp    hdr->sh_flags |= SHF_ALPHA_GPREL;
240733965Sjdp
240833965Sjdp  return true;
240933965Sjdp}
241033965Sjdp
241160510Sobrien/* Hook called by the linker routine which adds symbols from an object
241260510Sobrien   file.  We use it to put .comm items in .sbss, and not .bss.  */
241333965Sjdp
241460510Sobrienstatic boolean
241560510Sobrienelf64_alpha_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
241633965Sjdp     bfd *abfd;
241760510Sobrien     struct bfd_link_info *info;
241860510Sobrien     const Elf_Internal_Sym *sym;
241978833Sobrien     const char **namep ATTRIBUTE_UNUSED;
242078833Sobrien     flagword *flagsp ATTRIBUTE_UNUSED;
242160510Sobrien     asection **secp;
242260510Sobrien     bfd_vma *valp;
242333965Sjdp{
242460510Sobrien  if (sym->st_shndx == SHN_COMMON
242560510Sobrien      && !info->relocateable
242689862Sobrien      && sym->st_size <= elf_gp_size (abfd))
242760510Sobrien    {
242860510Sobrien      /* Common symbols less than or equal to -G nn bytes are
242960510Sobrien	 automatically put into .sbss.  */
243033965Sjdp
243160510Sobrien      asection *scomm = bfd_get_section_by_name (abfd, ".scommon");
243233965Sjdp
243360510Sobrien      if (scomm == NULL)
243460510Sobrien	{
243560510Sobrien	  scomm = bfd_make_section (abfd, ".scommon");
243660510Sobrien	  if (scomm == NULL
243760510Sobrien	      || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC
243860510Sobrien						       | SEC_IS_COMMON
243960510Sobrien						       | SEC_LINKER_CREATED)))
244060510Sobrien	    return false;
244160510Sobrien	}
244233965Sjdp
244360510Sobrien      *secp = scomm;
244460510Sobrien      *valp = sym->st_size;
244533965Sjdp    }
244633965Sjdp
244760510Sobrien  return true;
244833965Sjdp}
244933965Sjdp
245033965Sjdp/* Create the .got section.  */
245133965Sjdp
245233965Sjdpstatic boolean
245333965Sjdpelf64_alpha_create_got_section(abfd, info)
245433965Sjdp     bfd *abfd;
245578833Sobrien     struct bfd_link_info *info ATTRIBUTE_UNUSED;
245633965Sjdp{
245733965Sjdp  asection *s;
245833965Sjdp
245933965Sjdp  if (bfd_get_section_by_name (abfd, ".got"))
246033965Sjdp    return true;
246133965Sjdp
246233965Sjdp  s = bfd_make_section (abfd, ".got");
246333965Sjdp  if (s == NULL
246433965Sjdp      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
246533965Sjdp					   | SEC_HAS_CONTENTS
246633965Sjdp					   | SEC_IN_MEMORY
246733965Sjdp					   | SEC_LINKER_CREATED))
246833965Sjdp      || !bfd_set_section_alignment (abfd, s, 3))
246933965Sjdp    return false;
247033965Sjdp
247133965Sjdp  alpha_elf_tdata (abfd)->got = s;
247233965Sjdp
247333965Sjdp  return true;
247433965Sjdp}
247533965Sjdp
247633965Sjdp/* Create all the dynamic sections.  */
247733965Sjdp
247833965Sjdpstatic boolean
247933965Sjdpelf64_alpha_create_dynamic_sections (abfd, info)
248033965Sjdp     bfd *abfd;
248133965Sjdp     struct bfd_link_info *info;
248233965Sjdp{
248333965Sjdp  asection *s;
248433965Sjdp  struct elf_link_hash_entry *h;
2485107497Sobrien  struct bfd_link_hash_entry *bh;
248633965Sjdp
248733965Sjdp  /* We need to create .plt, .rela.plt, .got, and .rela.got sections.  */
248833965Sjdp
248933965Sjdp  s = bfd_make_section (abfd, ".plt");
249033965Sjdp  if (s == NULL
249133965Sjdp      || ! bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
249233965Sjdp					    | SEC_HAS_CONTENTS
249333965Sjdp					    | SEC_IN_MEMORY
249433965Sjdp					    | SEC_LINKER_CREATED
249533965Sjdp					    | SEC_CODE))
249633965Sjdp      || ! bfd_set_section_alignment (abfd, s, 3))
249733965Sjdp    return false;
249833965Sjdp
249933965Sjdp  /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
250033965Sjdp     .plt section.  */
2501107497Sobrien  bh = NULL;
250233965Sjdp  if (! (_bfd_generic_link_add_one_symbol
250333965Sjdp	 (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s,
250433965Sjdp	  (bfd_vma) 0, (const char *) NULL, false,
2505107497Sobrien	  get_elf_backend_data (abfd)->collect, &bh)))
250633965Sjdp    return false;
2507107497Sobrien  h = (struct elf_link_hash_entry *) bh;
250833965Sjdp  h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
250933965Sjdp  h->type = STT_OBJECT;
251033965Sjdp
251133965Sjdp  if (info->shared
251233965Sjdp      && ! _bfd_elf_link_record_dynamic_symbol (info, h))
251333965Sjdp    return false;
251433965Sjdp
251533965Sjdp  s = bfd_make_section (abfd, ".rela.plt");
251633965Sjdp  if (s == NULL
251733965Sjdp      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
251833965Sjdp					   | SEC_HAS_CONTENTS
251933965Sjdp					   | SEC_IN_MEMORY
252033965Sjdp					   | SEC_LINKER_CREATED
252133965Sjdp					   | SEC_READONLY))
252233965Sjdp      || ! bfd_set_section_alignment (abfd, s, 3))
252333965Sjdp    return false;
252433965Sjdp
252533965Sjdp  /* We may or may not have created a .got section for this object, but
252633965Sjdp     we definitely havn't done the rest of the work.  */
252733965Sjdp
252833965Sjdp  if (!elf64_alpha_create_got_section (abfd, info))
252933965Sjdp    return false;
253033965Sjdp
253133965Sjdp  s = bfd_make_section(abfd, ".rela.got");
253233965Sjdp  if (s == NULL
253333965Sjdp      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
253433965Sjdp					   | SEC_HAS_CONTENTS
253533965Sjdp					   | SEC_IN_MEMORY
253633965Sjdp					   | SEC_LINKER_CREATED
253733965Sjdp					   | SEC_READONLY))
253833965Sjdp      || !bfd_set_section_alignment (abfd, s, 3))
253933965Sjdp    return false;
254033965Sjdp
254133965Sjdp  /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the
254233965Sjdp     dynobj's .got section.  We don't do this in the linker script
254333965Sjdp     because we don't want to define the symbol if we are not creating
254433965Sjdp     a global offset table.  */
2545107497Sobrien  bh = NULL;
254633965Sjdp  if (!(_bfd_generic_link_add_one_symbol
254733965Sjdp	(info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL,
254833965Sjdp	 alpha_elf_tdata(abfd)->got, (bfd_vma) 0, (const char *) NULL,
2549107497Sobrien	 false, get_elf_backend_data (abfd)->collect, &bh)))
255033965Sjdp    return false;
2551107497Sobrien  h = (struct elf_link_hash_entry *) bh;
255233965Sjdp  h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
255333965Sjdp  h->type = STT_OBJECT;
255433965Sjdp
255533965Sjdp  if (info->shared
255633965Sjdp      && ! _bfd_elf_link_record_dynamic_symbol (info, h))
255733965Sjdp    return false;
255833965Sjdp
255933965Sjdp  elf_hash_table (info)->hgot = h;
256033965Sjdp
256133965Sjdp  return true;
256233965Sjdp}
256333965Sjdp
256433965Sjdp/* Read ECOFF debugging information from a .mdebug section into a
256533965Sjdp   ecoff_debug_info structure.  */
256633965Sjdp
256733965Sjdpstatic boolean
256833965Sjdpelf64_alpha_read_ecoff_info (abfd, section, debug)
256933965Sjdp     bfd *abfd;
257033965Sjdp     asection *section;
257133965Sjdp     struct ecoff_debug_info *debug;
257233965Sjdp{
257333965Sjdp  HDRR *symhdr;
257433965Sjdp  const struct ecoff_debug_swap *swap;
257533965Sjdp  char *ext_hdr = NULL;
257633965Sjdp
257733965Sjdp  swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
257877303Sobrien  memset (debug, 0, sizeof (*debug));
257933965Sjdp
258089862Sobrien  ext_hdr = (char *) bfd_malloc (swap->external_hdr_size);
258133965Sjdp  if (ext_hdr == NULL && swap->external_hdr_size != 0)
258233965Sjdp    goto error_return;
258333965Sjdp
2584104841Sobrien  if (! bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0,
2585104841Sobrien				  swap->external_hdr_size))
258633965Sjdp    goto error_return;
258733965Sjdp
258833965Sjdp  symhdr = &debug->symbolic_header;
258933965Sjdp  (*swap->swap_hdr_in) (abfd, ext_hdr, symhdr);
259033965Sjdp
259133965Sjdp  /* The symbolic header contains absolute file offsets and sizes to
259233965Sjdp     read.  */
259333965Sjdp#define READ(ptr, offset, count, size, type)				\
259433965Sjdp  if (symhdr->count == 0)						\
259533965Sjdp    debug->ptr = NULL;							\
259633965Sjdp  else									\
259733965Sjdp    {									\
259889862Sobrien      bfd_size_type amt = (bfd_size_type) size * symhdr->count;		\
259989862Sobrien      debug->ptr = (type) bfd_malloc (amt);				\
260033965Sjdp      if (debug->ptr == NULL)						\
260133965Sjdp	goto error_return;						\
260233965Sjdp      if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0	\
260389862Sobrien	  || bfd_bread (debug->ptr, amt, abfd) != amt)			\
260433965Sjdp	goto error_return;						\
260533965Sjdp    }
260633965Sjdp
260733965Sjdp  READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
260833965Sjdp  READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR);
260933965Sjdp  READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR);
261033965Sjdp  READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR);
261133965Sjdp  READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR);
261233965Sjdp  READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
261333965Sjdp	union aux_ext *);
261433965Sjdp  READ (ss, cbSsOffset, issMax, sizeof (char), char *);
261533965Sjdp  READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *);
261633965Sjdp  READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR);
261733965Sjdp  READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR);
261833965Sjdp  READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, PTR);
261933965Sjdp#undef READ
262033965Sjdp
262133965Sjdp  debug->fdr = NULL;
262233965Sjdp  debug->adjust = NULL;
262333965Sjdp
262433965Sjdp  return true;
262533965Sjdp
262633965Sjdp error_return:
262733965Sjdp  if (ext_hdr != NULL)
262833965Sjdp    free (ext_hdr);
262933965Sjdp  if (debug->line != NULL)
263033965Sjdp    free (debug->line);
263133965Sjdp  if (debug->external_dnr != NULL)
263233965Sjdp    free (debug->external_dnr);
263333965Sjdp  if (debug->external_pdr != NULL)
263433965Sjdp    free (debug->external_pdr);
263533965Sjdp  if (debug->external_sym != NULL)
263633965Sjdp    free (debug->external_sym);
263733965Sjdp  if (debug->external_opt != NULL)
263833965Sjdp    free (debug->external_opt);
263933965Sjdp  if (debug->external_aux != NULL)
264033965Sjdp    free (debug->external_aux);
264133965Sjdp  if (debug->ss != NULL)
264233965Sjdp    free (debug->ss);
264333965Sjdp  if (debug->ssext != NULL)
264433965Sjdp    free (debug->ssext);
264533965Sjdp  if (debug->external_fdr != NULL)
264633965Sjdp    free (debug->external_fdr);
264733965Sjdp  if (debug->external_rfd != NULL)
264833965Sjdp    free (debug->external_rfd);
264933965Sjdp  if (debug->external_ext != NULL)
265033965Sjdp    free (debug->external_ext);
265133965Sjdp  return false;
265233965Sjdp}
265333965Sjdp
265433965Sjdp/* Alpha ELF local labels start with '$'.  */
265533965Sjdp
265633965Sjdpstatic boolean
265733965Sjdpelf64_alpha_is_local_label_name (abfd, name)
265878833Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
265933965Sjdp     const char *name;
266033965Sjdp{
266133965Sjdp  return name[0] == '$';
266233965Sjdp}
266333965Sjdp
266433965Sjdp/* Alpha ELF follows MIPS ELF in using a special find_nearest_line
266533965Sjdp   routine in order to handle the ECOFF debugging information.  We
266633965Sjdp   still call this mips_elf_find_line because of the slot
266733965Sjdp   find_line_info in elf_obj_tdata is declared that way.  */
266833965Sjdp
266933965Sjdpstruct mips_elf_find_line
267033965Sjdp{
267133965Sjdp  struct ecoff_debug_info d;
267233965Sjdp  struct ecoff_find_line i;
267333965Sjdp};
267433965Sjdp
267533965Sjdpstatic boolean
267633965Sjdpelf64_alpha_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
267733965Sjdp			       functionname_ptr, line_ptr)
267833965Sjdp     bfd *abfd;
267933965Sjdp     asection *section;
268033965Sjdp     asymbol **symbols;
268133965Sjdp     bfd_vma offset;
268233965Sjdp     const char **filename_ptr;
268333965Sjdp     const char **functionname_ptr;
268433965Sjdp     unsigned int *line_ptr;
268533965Sjdp{
268633965Sjdp  asection *msec;
268733965Sjdp
268877303Sobrien  if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
268977303Sobrien				     filename_ptr, functionname_ptr,
269077303Sobrien				     line_ptr, 0,
269177303Sobrien				     &elf_tdata (abfd)->dwarf2_find_line_info))
269277303Sobrien    return true;
269377303Sobrien
269433965Sjdp  msec = bfd_get_section_by_name (abfd, ".mdebug");
269533965Sjdp  if (msec != NULL)
269633965Sjdp    {
269733965Sjdp      flagword origflags;
269833965Sjdp      struct mips_elf_find_line *fi;
269933965Sjdp      const struct ecoff_debug_swap * const swap =
270033965Sjdp	get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
270133965Sjdp
270233965Sjdp      /* If we are called during a link, alpha_elf_final_link may have
270333965Sjdp	 cleared the SEC_HAS_CONTENTS field.  We force it back on here
270433965Sjdp	 if appropriate (which it normally will be).  */
270533965Sjdp      origflags = msec->flags;
270633965Sjdp      if (elf_section_data (msec)->this_hdr.sh_type != SHT_NOBITS)
270733965Sjdp	msec->flags |= SEC_HAS_CONTENTS;
270833965Sjdp
270933965Sjdp      fi = elf_tdata (abfd)->find_line_info;
271033965Sjdp      if (fi == NULL)
271133965Sjdp	{
271233965Sjdp	  bfd_size_type external_fdr_size;
271333965Sjdp	  char *fraw_src;
271433965Sjdp	  char *fraw_end;
271533965Sjdp	  struct fdr *fdr_ptr;
271689862Sobrien	  bfd_size_type amt = sizeof (struct mips_elf_find_line);
271733965Sjdp
271889862Sobrien	  fi = (struct mips_elf_find_line *) bfd_zalloc (abfd, amt);
271933965Sjdp	  if (fi == NULL)
272033965Sjdp	    {
272133965Sjdp	      msec->flags = origflags;
272233965Sjdp	      return false;
272333965Sjdp	    }
272433965Sjdp
272533965Sjdp	  if (!elf64_alpha_read_ecoff_info (abfd, msec, &fi->d))
272633965Sjdp	    {
272733965Sjdp	      msec->flags = origflags;
272833965Sjdp	      return false;
272933965Sjdp	    }
273033965Sjdp
273133965Sjdp	  /* Swap in the FDR information.  */
273289862Sobrien	  amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr);
273389862Sobrien	  fi->d.fdr = (struct fdr *) bfd_alloc (abfd, amt);
273433965Sjdp	  if (fi->d.fdr == NULL)
273533965Sjdp	    {
273633965Sjdp	      msec->flags = origflags;
273733965Sjdp	      return false;
273833965Sjdp	    }
273933965Sjdp	  external_fdr_size = swap->external_fdr_size;
274033965Sjdp	  fdr_ptr = fi->d.fdr;
274133965Sjdp	  fraw_src = (char *) fi->d.external_fdr;
274233965Sjdp	  fraw_end = (fraw_src
274333965Sjdp		      + fi->d.symbolic_header.ifdMax * external_fdr_size);
274433965Sjdp	  for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
274533965Sjdp	    (*swap->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr);
274633965Sjdp
274733965Sjdp	  elf_tdata (abfd)->find_line_info = fi;
274833965Sjdp
274933965Sjdp	  /* Note that we don't bother to ever free this information.
275033965Sjdp             find_nearest_line is either called all the time, as in
275133965Sjdp             objdump -l, so the information should be saved, or it is
275233965Sjdp             rarely called, as in ld error messages, so the memory
275333965Sjdp             wasted is unimportant.  Still, it would probably be a
275433965Sjdp             good idea for free_cached_info to throw it away.  */
275533965Sjdp	}
275633965Sjdp
275733965Sjdp      if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap,
275833965Sjdp				  &fi->i, filename_ptr, functionname_ptr,
275933965Sjdp				  line_ptr))
276033965Sjdp	{
276133965Sjdp	  msec->flags = origflags;
276233965Sjdp	  return true;
276333965Sjdp	}
276433965Sjdp
276533965Sjdp      msec->flags = origflags;
276633965Sjdp    }
276733965Sjdp
276833965Sjdp  /* Fall back on the generic ELF find_nearest_line routine.  */
276933965Sjdp
277033965Sjdp  return _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
277133965Sjdp				     filename_ptr, functionname_ptr,
277233965Sjdp				     line_ptr);
277333965Sjdp}
277433965Sjdp
277533965Sjdp/* Structure used to pass information to alpha_elf_output_extsym.  */
277633965Sjdp
277733965Sjdpstruct extsym_info
277833965Sjdp{
277933965Sjdp  bfd *abfd;
278033965Sjdp  struct bfd_link_info *info;
278133965Sjdp  struct ecoff_debug_info *debug;
278233965Sjdp  const struct ecoff_debug_swap *swap;
278333965Sjdp  boolean failed;
278433965Sjdp};
278533965Sjdp
278633965Sjdpstatic boolean
278733965Sjdpelf64_alpha_output_extsym (h, data)
278833965Sjdp     struct alpha_elf_link_hash_entry *h;
278933965Sjdp     PTR data;
279033965Sjdp{
279133965Sjdp  struct extsym_info *einfo = (struct extsym_info *) data;
279233965Sjdp  boolean strip;
279333965Sjdp  asection *sec, *output_section;
279433965Sjdp
279594544Sobrien  if (h->root.root.type == bfd_link_hash_warning)
279694544Sobrien    h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
279794544Sobrien
279833965Sjdp  if (h->root.indx == -2)
279933965Sjdp    strip = false;
280033965Sjdp  else if (((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
280194544Sobrien	    || (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
280294544Sobrien	   && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
280394544Sobrien	   && (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
280433965Sjdp    strip = true;
280533965Sjdp  else if (einfo->info->strip == strip_all
280694544Sobrien	   || (einfo->info->strip == strip_some
280794544Sobrien	       && bfd_hash_lookup (einfo->info->keep_hash,
280894544Sobrien				   h->root.root.root.string,
280994544Sobrien				   false, false) == NULL))
281033965Sjdp    strip = true;
281133965Sjdp  else
281233965Sjdp    strip = false;
281333965Sjdp
281433965Sjdp  if (strip)
281533965Sjdp    return true;
281633965Sjdp
281733965Sjdp  if (h->esym.ifd == -2)
281833965Sjdp    {
281933965Sjdp      h->esym.jmptbl = 0;
282033965Sjdp      h->esym.cobol_main = 0;
282133965Sjdp      h->esym.weakext = 0;
282233965Sjdp      h->esym.reserved = 0;
282333965Sjdp      h->esym.ifd = ifdNil;
282433965Sjdp      h->esym.asym.value = 0;
282533965Sjdp      h->esym.asym.st = stGlobal;
282633965Sjdp
282733965Sjdp      if (h->root.root.type != bfd_link_hash_defined
282894544Sobrien	  && h->root.root.type != bfd_link_hash_defweak)
282994544Sobrien	h->esym.asym.sc = scAbs;
283033965Sjdp      else
283194544Sobrien	{
283294544Sobrien	  const char *name;
283333965Sjdp
283494544Sobrien	  sec = h->root.root.u.def.section;
283594544Sobrien	  output_section = sec->output_section;
283633965Sjdp
283794544Sobrien	  /* When making a shared library and symbol h is the one from
283894544Sobrien	     the another shared library, OUTPUT_SECTION may be null.  */
283994544Sobrien	  if (output_section == NULL)
284094544Sobrien	    h->esym.asym.sc = scUndefined;
284194544Sobrien	  else
284294544Sobrien	    {
284394544Sobrien	      name = bfd_section_name (output_section->owner, output_section);
284433965Sjdp
284594544Sobrien	      if (strcmp (name, ".text") == 0)
284694544Sobrien		h->esym.asym.sc = scText;
284794544Sobrien	      else if (strcmp (name, ".data") == 0)
284894544Sobrien		h->esym.asym.sc = scData;
284994544Sobrien	      else if (strcmp (name, ".sdata") == 0)
285094544Sobrien		h->esym.asym.sc = scSData;
285194544Sobrien	      else if (strcmp (name, ".rodata") == 0
285294544Sobrien		       || strcmp (name, ".rdata") == 0)
285394544Sobrien		h->esym.asym.sc = scRData;
285494544Sobrien	      else if (strcmp (name, ".bss") == 0)
285594544Sobrien		h->esym.asym.sc = scBss;
285694544Sobrien	      else if (strcmp (name, ".sbss") == 0)
285794544Sobrien		h->esym.asym.sc = scSBss;
285894544Sobrien	      else if (strcmp (name, ".init") == 0)
285994544Sobrien		h->esym.asym.sc = scInit;
286094544Sobrien	      else if (strcmp (name, ".fini") == 0)
286194544Sobrien		h->esym.asym.sc = scFini;
286294544Sobrien	      else
286394544Sobrien		h->esym.asym.sc = scAbs;
286494544Sobrien	    }
286594544Sobrien	}
286633965Sjdp
286733965Sjdp      h->esym.asym.reserved = 0;
286833965Sjdp      h->esym.asym.index = indexNil;
286933965Sjdp    }
287033965Sjdp
287133965Sjdp  if (h->root.root.type == bfd_link_hash_common)
287233965Sjdp    h->esym.asym.value = h->root.root.u.c.size;
287333965Sjdp  else if (h->root.root.type == bfd_link_hash_defined
287433965Sjdp	   || h->root.root.type == bfd_link_hash_defweak)
287533965Sjdp    {
287633965Sjdp      if (h->esym.asym.sc == scCommon)
287794544Sobrien	h->esym.asym.sc = scBss;
287833965Sjdp      else if (h->esym.asym.sc == scSCommon)
287994544Sobrien	h->esym.asym.sc = scSBss;
288033965Sjdp
288133965Sjdp      sec = h->root.root.u.def.section;
288233965Sjdp      output_section = sec->output_section;
288333965Sjdp      if (output_section != NULL)
288494544Sobrien	h->esym.asym.value = (h->root.root.u.def.value
288594544Sobrien			      + sec->output_offset
288694544Sobrien			      + output_section->vma);
288733965Sjdp      else
288894544Sobrien	h->esym.asym.value = 0;
288933965Sjdp    }
289033965Sjdp  else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
289133965Sjdp    {
289233965Sjdp      /* Set type and value for a symbol with a function stub.  */
289333965Sjdp      h->esym.asym.st = stProc;
289433965Sjdp      sec = bfd_get_section_by_name (einfo->abfd, ".plt");
289533965Sjdp      if (sec == NULL)
289633965Sjdp	h->esym.asym.value = 0;
289733965Sjdp      else
289833965Sjdp	{
289933965Sjdp	  output_section = sec->output_section;
290033965Sjdp	  if (output_section != NULL)
290160510Sobrien	    h->esym.asym.value = (h->root.plt.offset
290233965Sjdp				  + sec->output_offset
290333965Sjdp				  + output_section->vma);
290433965Sjdp	  else
290533965Sjdp	    h->esym.asym.value = 0;
290633965Sjdp	}
290733965Sjdp    }
290833965Sjdp
290933965Sjdp  if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap,
291094544Sobrien				      h->root.root.root.string,
291194544Sobrien				      &h->esym))
291233965Sjdp    {
291333965Sjdp      einfo->failed = true;
291433965Sjdp      return false;
291533965Sjdp    }
291633965Sjdp
291733965Sjdp  return true;
291833965Sjdp}
2919104841Sobrien
2920104841Sobrien/* Search for and possibly create a got entry.  */
292133965Sjdp
2922104841Sobrienstatic struct alpha_elf_got_entry *
2923104841Sobrienget_got_entry (abfd, h, r_type, r_symndx, r_addend)
2924104841Sobrien     bfd *abfd;
2925104841Sobrien     struct alpha_elf_link_hash_entry *h;
2926104841Sobrien     unsigned long r_type, r_symndx;
2927104841Sobrien     bfd_vma r_addend;
2928104841Sobrien{
2929104841Sobrien  struct alpha_elf_got_entry *gotent;
2930104841Sobrien  struct alpha_elf_got_entry **slot;
293133965Sjdp
2932104841Sobrien  if (h)
2933104841Sobrien    slot = &h->got_entries;
2934104841Sobrien  else
2935104841Sobrien    {
2936104841Sobrien      /* This is a local .got entry -- record for merge.  */
2937104841Sobrien
2938104841Sobrien      struct alpha_elf_got_entry **local_got_entries;
2939104841Sobrien
2940104841Sobrien      local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
2941104841Sobrien      if (!local_got_entries)
2942104841Sobrien	{
2943104841Sobrien	  bfd_size_type size;
2944104841Sobrien	  Elf_Internal_Shdr *symtab_hdr;
2945104841Sobrien
2946104841Sobrien	  symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
2947104841Sobrien	  size = symtab_hdr->sh_info;
2948104841Sobrien	  size *= sizeof (struct alpha_elf_got_entry *);
2949104841Sobrien
2950104841Sobrien	  local_got_entries
2951104841Sobrien	    = (struct alpha_elf_got_entry **) bfd_zalloc (abfd, size);
2952104841Sobrien	  if (!local_got_entries)
2953104841Sobrien	    return NULL;
2954104841Sobrien
2955104841Sobrien	  alpha_elf_tdata (abfd)->local_got_entries = local_got_entries;
2956104841Sobrien	}
2957104841Sobrien
2958104841Sobrien      slot = &local_got_entries[r_symndx];
2959104841Sobrien    }
2960104841Sobrien
2961104841Sobrien  for (gotent = *slot; gotent ; gotent = gotent->next)
2962104841Sobrien    if (gotent->gotobj == abfd
2963104841Sobrien	&& gotent->reloc_type == r_type
2964104841Sobrien	&& gotent->addend == r_addend)
2965104841Sobrien      break;
2966104841Sobrien
2967104841Sobrien  if (!gotent)
2968104841Sobrien    {
2969104841Sobrien      int entry_size;
2970104841Sobrien      bfd_size_type amt;
2971104841Sobrien
2972104841Sobrien      amt = sizeof (struct alpha_elf_got_entry);
2973104841Sobrien      gotent = (struct alpha_elf_got_entry *) bfd_alloc (abfd, amt);
2974104841Sobrien      if (!gotent)
2975104841Sobrien	return NULL;
2976104841Sobrien
2977104841Sobrien      gotent->gotobj = abfd;
2978104841Sobrien      gotent->addend = r_addend;
2979104841Sobrien      gotent->got_offset = -1;
2980104841Sobrien      gotent->use_count = 1;
2981104841Sobrien      gotent->reloc_type = r_type;
2982104841Sobrien      gotent->reloc_done = 0;
2983104841Sobrien      gotent->reloc_xlated = 0;
2984104841Sobrien
2985104841Sobrien      gotent->next = *slot;
2986104841Sobrien      *slot = gotent;
2987104841Sobrien
2988104841Sobrien      entry_size = alpha_got_entry_size (r_type);
2989104841Sobrien      alpha_elf_tdata (abfd)->total_got_size += entry_size;
2990104841Sobrien      if (!h)
2991104841Sobrien	alpha_elf_tdata(abfd)->local_got_size += entry_size;
2992104841Sobrien    }
2993104841Sobrien  else
2994104841Sobrien    gotent->use_count += 1;
2995104841Sobrien
2996104841Sobrien  return gotent;
2997104841Sobrien}
2998104841Sobrien
299933965Sjdp/* Handle dynamic relocations when doing an Alpha ELF link.  */
300033965Sjdp
300133965Sjdpstatic boolean
300233965Sjdpelf64_alpha_check_relocs (abfd, info, sec, relocs)
300333965Sjdp     bfd *abfd;
300433965Sjdp     struct bfd_link_info *info;
300533965Sjdp     asection *sec;
300633965Sjdp     const Elf_Internal_Rela *relocs;
300733965Sjdp{
300833965Sjdp  bfd *dynobj;
300933965Sjdp  asection *sreloc;
301033965Sjdp  const char *rel_sec_name;
301133965Sjdp  Elf_Internal_Shdr *symtab_hdr;
301233965Sjdp  struct alpha_elf_link_hash_entry **sym_hashes;
301333965Sjdp  const Elf_Internal_Rela *rel, *relend;
3014104841Sobrien  boolean got_created;
301589862Sobrien  bfd_size_type amt;
301633965Sjdp
301733965Sjdp  if (info->relocateable)
301833965Sjdp    return true;
301933965Sjdp
302033965Sjdp  dynobj = elf_hash_table(info)->dynobj;
302133965Sjdp  if (dynobj == NULL)
302233965Sjdp    elf_hash_table(info)->dynobj = dynobj = abfd;
302333965Sjdp
302433965Sjdp  sreloc = NULL;
302533965Sjdp  rel_sec_name = NULL;
302633965Sjdp  symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
302733965Sjdp  sym_hashes = alpha_elf_sym_hashes(abfd);
3028104841Sobrien  got_created = false;
302933965Sjdp
303033965Sjdp  relend = relocs + sec->reloc_count;
303133965Sjdp  for (rel = relocs; rel < relend; ++rel)
303233965Sjdp    {
3033104841Sobrien      enum {
3034104841Sobrien	NEED_GOT = 1,
3035104841Sobrien	NEED_GOT_ENTRY = 2,
3036104841Sobrien	NEED_DYNREL = 4
3037104841Sobrien      };
3038104841Sobrien
303933965Sjdp      unsigned long r_symndx, r_type;
304033965Sjdp      struct alpha_elf_link_hash_entry *h;
3041104841Sobrien      unsigned int gotent_flags;
3042104841Sobrien      boolean maybe_dynamic;
3043104841Sobrien      unsigned int need;
3044104841Sobrien      bfd_vma addend;
304533965Sjdp
304633965Sjdp      r_symndx = ELF64_R_SYM (rel->r_info);
304733965Sjdp      if (r_symndx < symtab_hdr->sh_info)
304833965Sjdp	h = NULL;
304933965Sjdp      else
305033965Sjdp	{
305133965Sjdp	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
305238889Sjdp
305338889Sjdp	  while (h->root.root.type == bfd_link_hash_indirect
305438889Sjdp		 || h->root.root.type == bfd_link_hash_warning)
305538889Sjdp	    h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
305638889Sjdp
305733965Sjdp	  h->root.elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
305833965Sjdp	}
3059104841Sobrien
3060104841Sobrien      /* We can only get preliminary data on whether a symbol is
3061104841Sobrien         locally or externally defined, as not all of the input files
3062104841Sobrien         have yet been processed.  Do something with what we know, as
3063104841Sobrien         this may help reduce memory usage and processing time later.  */
3064104841Sobrien      maybe_dynamic = false;
3065104841Sobrien      if (h && ((info->shared
3066104841Sobrien		 && (!info->symbolic || info->allow_shlib_undefined))
3067104841Sobrien		|| ! (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
3068104841Sobrien		|| h->root.root.type == bfd_link_hash_defweak))
3069104841Sobrien        maybe_dynamic = true;
3070104841Sobrien
3071104841Sobrien      need = 0;
3072104841Sobrien      gotent_flags = 0;
307333965Sjdp      r_type = ELF64_R_TYPE (rel->r_info);
3074104841Sobrien      addend = rel->r_addend;
307533965Sjdp
307633965Sjdp      switch (r_type)
307733965Sjdp	{
307833965Sjdp	case R_ALPHA_LITERAL:
3079104841Sobrien	  need = NEED_GOT | NEED_GOT_ENTRY;
308033965Sjdp
3081104841Sobrien	  /* Remember how this literal is used from its LITUSEs.
3082104841Sobrien	     This will be important when it comes to decide if we can
3083104841Sobrien	     create a .plt entry for a function symbol.  */
3084104841Sobrien	  while (++rel < relend && ELF64_R_TYPE (rel->r_info) == R_ALPHA_LITUSE)
3085104841Sobrien	    if (rel->r_addend >= 1 && rel->r_addend <= 5)
3086104841Sobrien	      gotent_flags |= 1 << rel->r_addend;
3087104841Sobrien	  --rel;
308833965Sjdp
3089104841Sobrien	  /* No LITUSEs -- presumably the address is used somehow.  */
3090104841Sobrien	  if (gotent_flags == 0)
3091104841Sobrien	    gotent_flags = ALPHA_ELF_LINK_HASH_LU_ADDR;
3092104841Sobrien	  break;
309333965Sjdp
309433965Sjdp	case R_ALPHA_GPDISP:
309589862Sobrien	case R_ALPHA_GPREL16:
309633965Sjdp	case R_ALPHA_GPREL32:
309760510Sobrien	case R_ALPHA_GPRELHIGH:
309860510Sobrien	case R_ALPHA_GPRELLOW:
309991049Sobrien	case R_ALPHA_BRSGP:
3100104841Sobrien	  need = NEED_GOT;
3101104841Sobrien	  break;
3102104841Sobrien
3103104841Sobrien	case R_ALPHA_REFLONG:
3104104841Sobrien	case R_ALPHA_REFQUAD:
3105107497Sobrien	  if ((info->shared && (sec->flags & SEC_ALLOC)) || maybe_dynamic)
3106104841Sobrien	    need = NEED_DYNREL;
3107104841Sobrien	  break;
3108104841Sobrien
3109104841Sobrien	case R_ALPHA_TLSGD:
3110104841Sobrien	case R_ALPHA_TLSLDM:
3111104841Sobrien	case R_ALPHA_GOTDTPREL:
3112104841Sobrien	  need = NEED_GOT | NEED_GOT_ENTRY;
3113104841Sobrien	  break;
3114104841Sobrien
3115104841Sobrien	case R_ALPHA_GOTTPREL:
3116104841Sobrien	  need = NEED_GOT | NEED_GOT_ENTRY;
3117104841Sobrien	  gotent_flags = ALPHA_ELF_LINK_HASH_TLS_IE;
3118104841Sobrien	  if (info->shared)
3119104841Sobrien	    info->flags |= DF_STATIC_TLS;
3120104841Sobrien	  break;
3121104841Sobrien
3122104841Sobrien	case R_ALPHA_TPREL64:
3123104841Sobrien	  if (info->shared || maybe_dynamic)
3124104841Sobrien	    need = NEED_DYNREL;
3125104841Sobrien	  if (info->shared)
3126104841Sobrien	    info->flags |= DF_STATIC_TLS;
3127104841Sobrien	  break;
3128104841Sobrien	}
3129104841Sobrien
3130104841Sobrien      if (need & NEED_GOT)
3131104841Sobrien	{
313233965Sjdp	  if (!got_created)
313333965Sjdp	    {
313433965Sjdp	      if (!elf64_alpha_create_got_section (abfd, info))
313533965Sjdp		return false;
313633965Sjdp
313733965Sjdp	      /* Make sure the object's gotobj is set to itself so
313833965Sjdp		 that we default to every object with its own .got.
313933965Sjdp		 We'll merge .gots later once we've collected each
314033965Sjdp		 object's info.  */
314133965Sjdp	      alpha_elf_tdata(abfd)->gotobj = abfd;
314233965Sjdp
314333965Sjdp	      got_created = 1;
314433965Sjdp	    }
3145104841Sobrien	}
314633965Sjdp
3147104841Sobrien      if (need & NEED_GOT_ENTRY)
3148104841Sobrien	{
3149104841Sobrien	  struct alpha_elf_got_entry *gotent;
315033965Sjdp
3151104841Sobrien	  gotent = get_got_entry (abfd, h, r_type, r_symndx, addend);
3152104841Sobrien	  if (!gotent)
3153104841Sobrien	    return false;
3154104841Sobrien
3155104841Sobrien	  if (gotent_flags)
3156104841Sobrien	    {
3157104841Sobrien	      gotent->flags |= gotent_flags;
3158104841Sobrien	      if (h)
3159104841Sobrien		{
3160104841Sobrien		  gotent_flags |= h->flags;
3161104841Sobrien		  h->flags = gotent_flags;
3162104841Sobrien
3163104841Sobrien		  /* Make a guess as to whether a .plt entry is needed.  */
3164104841Sobrien		  if ((gotent_flags & ALPHA_ELF_LINK_HASH_LU_FUNC)
3165104841Sobrien		      && !(gotent_flags & ~ALPHA_ELF_LINK_HASH_LU_FUNC))
3166104841Sobrien		    h->root.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
3167104841Sobrien		  else
3168104841Sobrien		    h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
3169104841Sobrien	        }
3170104841Sobrien	    }
3171104841Sobrien	}
3172104841Sobrien
3173104841Sobrien      if (need & NEED_DYNREL)
3174104841Sobrien	{
317533965Sjdp	  if (rel_sec_name == NULL)
317633965Sjdp	    {
317733965Sjdp	      rel_sec_name = (bfd_elf_string_from_elf_section
317833965Sjdp			      (abfd, elf_elfheader(abfd)->e_shstrndx,
317933965Sjdp			       elf_section_data(sec)->rel_hdr.sh_name));
318033965Sjdp	      if (rel_sec_name == NULL)
318133965Sjdp		return false;
318233965Sjdp
318333965Sjdp	      BFD_ASSERT (strncmp (rel_sec_name, ".rela", 5) == 0
318433965Sjdp			  && strcmp (bfd_get_section_name (abfd, sec),
318533965Sjdp				     rel_sec_name+5) == 0);
318633965Sjdp	    }
318733965Sjdp
318833965Sjdp	  /* We need to create the section here now whether we eventually
318933965Sjdp	     use it or not so that it gets mapped to an output section by
319033965Sjdp	     the linker.  If not used, we'll kill it in
319133965Sjdp	     size_dynamic_sections.  */
319233965Sjdp	  if (sreloc == NULL)
319333965Sjdp	    {
319433965Sjdp	      sreloc = bfd_get_section_by_name (dynobj, rel_sec_name);
319533965Sjdp	      if (sreloc == NULL)
319633965Sjdp		{
319789862Sobrien		  flagword flags;
319889862Sobrien
319933965Sjdp		  sreloc = bfd_make_section (dynobj, rel_sec_name);
320089862Sobrien		  flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY
320189862Sobrien			   | SEC_LINKER_CREATED | SEC_READONLY);
320289862Sobrien		  if (sec->flags & SEC_ALLOC)
320389862Sobrien		    flags |= SEC_ALLOC | SEC_LOAD;
320433965Sjdp		  if (sreloc == NULL
320589862Sobrien		      || !bfd_set_section_flags (dynobj, sreloc, flags)
320633965Sjdp		      || !bfd_set_section_alignment (dynobj, sreloc, 3))
320733965Sjdp		    return false;
320833965Sjdp		}
320933965Sjdp	    }
321033965Sjdp
321133965Sjdp	  if (h)
321233965Sjdp	    {
321333965Sjdp	      /* Since we havn't seen all of the input symbols yet, we
321433965Sjdp		 don't know whether we'll actually need a dynamic relocation
321533965Sjdp		 entry for this reloc.  So make a record of it.  Once we
321633965Sjdp		 find out if this thing needs dynamic relocation we'll
321777303Sobrien		 expand the relocation sections by the appropriate amount.  */
321833965Sjdp
321933965Sjdp	      struct alpha_elf_reloc_entry *rent;
322033965Sjdp
322133965Sjdp	      for (rent = h->reloc_entries; rent; rent = rent->next)
322233965Sjdp		if (rent->rtype == r_type && rent->srel == sreloc)
322333965Sjdp		  break;
322433965Sjdp
322533965Sjdp	      if (!rent)
322633965Sjdp		{
322789862Sobrien		  amt = sizeof (struct alpha_elf_reloc_entry);
322889862Sobrien		  rent = (struct alpha_elf_reloc_entry *) bfd_alloc (abfd, amt);
322933965Sjdp		  if (!rent)
323033965Sjdp		    return false;
323133965Sjdp
323233965Sjdp		  rent->srel = sreloc;
323333965Sjdp		  rent->rtype = r_type;
323433965Sjdp		  rent->count = 1;
323589862Sobrien		  rent->reltext = ((sec->flags & (SEC_READONLY | SEC_ALLOC))
323689862Sobrien				   == (SEC_READONLY | SEC_ALLOC));
323733965Sjdp
323833965Sjdp		  rent->next = h->reloc_entries;
323933965Sjdp		  h->reloc_entries = rent;
324033965Sjdp		}
324133965Sjdp	      else
324233965Sjdp		rent->count++;
324333965Sjdp	    }
3244104841Sobrien	  else if (info->shared)
324533965Sjdp	    {
324660510Sobrien	      /* If this is a shared library, and the section is to be
324760510Sobrien		 loaded into memory, we need a RELATIVE reloc.  */
324833965Sjdp	      sreloc->_raw_size += sizeof (Elf64_External_Rela);
3249104841Sobrien	      if ((sec->flags & (SEC_READONLY | SEC_ALLOC))
3250104841Sobrien		  == (SEC_READONLY | SEC_ALLOC))
325189862Sobrien		info->flags |= DF_TEXTREL;
325233965Sjdp	    }
325333965Sjdp	}
325433965Sjdp    }
325533965Sjdp
325633965Sjdp  return true;
325733965Sjdp}
325833965Sjdp
325933965Sjdp/* Adjust a symbol defined by a dynamic object and referenced by a
326033965Sjdp   regular object.  The current definition is in some section of the
326133965Sjdp   dynamic object, but we're not including those sections.  We have to
326233965Sjdp   change the definition to something the rest of the link can
326333965Sjdp   understand.  */
326433965Sjdp
326533965Sjdpstatic boolean
326633965Sjdpelf64_alpha_adjust_dynamic_symbol (info, h)
326733965Sjdp     struct bfd_link_info *info;
326833965Sjdp     struct elf_link_hash_entry *h;
326933965Sjdp{
327033965Sjdp  bfd *dynobj;
327133965Sjdp  asection *s;
327233965Sjdp  struct alpha_elf_link_hash_entry *ah;
327333965Sjdp
327433965Sjdp  dynobj = elf_hash_table(info)->dynobj;
327533965Sjdp  ah = (struct alpha_elf_link_hash_entry *)h;
327633965Sjdp
327733965Sjdp  /* Now that we've seen all of the input symbols, finalize our decision
327833965Sjdp     about whether this symbol should get a .plt entry.  */
327933965Sjdp
328089862Sobrien  if (alpha_elf_dynamic_symbol_p (h, info)
328133965Sjdp      && ((h->type == STT_FUNC
328233965Sjdp	   && !(ah->flags & ALPHA_ELF_LINK_HASH_LU_ADDR))
328333965Sjdp	  || (h->type == STT_NOTYPE
3284104841Sobrien	      && (ah->flags & ALPHA_ELF_LINK_HASH_LU_FUNC)
3285104841Sobrien	      && !(ah->flags & ~ALPHA_ELF_LINK_HASH_LU_FUNC)))
328633965Sjdp      /* Don't prevent otherwise valid programs from linking by attempting
328733965Sjdp	 to create a new .got entry somewhere.  A Correct Solution would be
328833965Sjdp	 to add a new .got section to a new object file and let it be merged
328933965Sjdp	 somewhere later.  But for now don't bother.  */
329033965Sjdp      && ah->got_entries)
329133965Sjdp    {
329233965Sjdp      h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
329333965Sjdp
329433965Sjdp      s = bfd_get_section_by_name(dynobj, ".plt");
329533965Sjdp      if (!s && !elf64_alpha_create_dynamic_sections (dynobj, info))
329633965Sjdp	return false;
329733965Sjdp
329833965Sjdp      /* The first bit of the .plt is reserved.  */
329933965Sjdp      if (s->_raw_size == 0)
330033965Sjdp	s->_raw_size = PLT_HEADER_SIZE;
330133965Sjdp
330260510Sobrien      h->plt.offset = s->_raw_size;
330333965Sjdp      s->_raw_size += PLT_ENTRY_SIZE;
330433965Sjdp
330533965Sjdp      /* If this symbol is not defined in a regular file, and we are not
330633965Sjdp	 generating a shared library, then set the symbol to the location
330733965Sjdp	 in the .plt.  This is required to make function pointers compare
330833965Sjdp	 equal between the normal executable and the shared library.  */
330948850Sdfr      if (! info->shared
331048850Sdfr	  && h->root.type != bfd_link_hash_defweak)
331133965Sjdp	{
331233965Sjdp	  h->root.u.def.section = s;
331360510Sobrien	  h->root.u.def.value = h->plt.offset;
331433965Sjdp	}
331533965Sjdp
331633965Sjdp      /* We also need a JMP_SLOT entry in the .rela.plt section.  */
331733965Sjdp      s = bfd_get_section_by_name (dynobj, ".rela.plt");
331833965Sjdp      BFD_ASSERT (s != NULL);
331933965Sjdp      s->_raw_size += sizeof (Elf64_External_Rela);
332033965Sjdp
332133965Sjdp      return true;
332233965Sjdp    }
332333965Sjdp  else
332433965Sjdp    h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
332533965Sjdp
332633965Sjdp  /* If this is a weak symbol, and there is a real definition, the
332733965Sjdp     processor independent code will have arranged for us to see the
332833965Sjdp     real definition first, and we can just use the same value.  */
332933965Sjdp  if (h->weakdef != NULL)
333033965Sjdp    {
333133965Sjdp      BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
333233965Sjdp		  || h->weakdef->root.type == bfd_link_hash_defweak);
333333965Sjdp      h->root.u.def.section = h->weakdef->root.u.def.section;
333433965Sjdp      h->root.u.def.value = h->weakdef->root.u.def.value;
333533965Sjdp      return true;
333633965Sjdp    }
333733965Sjdp
333833965Sjdp  /* This is a reference to a symbol defined by a dynamic object which
333933965Sjdp     is not a function.  The Alpha, since it uses .got entries for all
334033965Sjdp     symbols even in regular objects, does not need the hackery of a
334133965Sjdp     .dynbss section and COPY dynamic relocations.  */
334233965Sjdp
334333965Sjdp  return true;
334433965Sjdp}
334533965Sjdp
334638889Sjdp/* Symbol versioning can create new symbols, and make our old symbols
334738889Sjdp   indirect to the new ones.  Consolidate the got and reloc information
334838889Sjdp   in these situations.  */
334938889Sjdp
335038889Sjdpstatic boolean
335138889Sjdpelf64_alpha_merge_ind_symbols (hi, dummy)
335238889Sjdp     struct alpha_elf_link_hash_entry *hi;
335378833Sobrien     PTR dummy ATTRIBUTE_UNUSED;
335438889Sjdp{
335538889Sjdp  struct alpha_elf_link_hash_entry *hs;
335638889Sjdp
335738889Sjdp  if (hi->root.root.type != bfd_link_hash_indirect)
335838889Sjdp    return true;
335938889Sjdp  hs = hi;
336038889Sjdp  do {
336138889Sjdp    hs = (struct alpha_elf_link_hash_entry *)hs->root.root.u.i.link;
336238889Sjdp  } while (hs->root.root.type == bfd_link_hash_indirect);
336338889Sjdp
336438889Sjdp  /* Merge the flags.  Whee.  */
336538889Sjdp
336638889Sjdp  hs->flags |= hi->flags;
336738889Sjdp
336838889Sjdp  /* Merge the .got entries.  Cannibalize the old symbol's list in
336938889Sjdp     doing so, since we don't need it anymore.  */
337038889Sjdp
337138889Sjdp  if (hs->got_entries == NULL)
337238889Sjdp    hs->got_entries = hi->got_entries;
337338889Sjdp  else
337438889Sjdp    {
337538889Sjdp      struct alpha_elf_got_entry *gi, *gs, *gin, *gsh;
337638889Sjdp
337738889Sjdp      gsh = hs->got_entries;
337838889Sjdp      for (gi = hi->got_entries; gi ; gi = gin)
337938889Sjdp	{
338038889Sjdp	  gin = gi->next;
338138889Sjdp	  for (gs = gsh; gs ; gs = gs->next)
3382104841Sobrien	    if (gi->gotobj == gs->gotobj
3383104841Sobrien		&& gi->reloc_type == gs->reloc_type
3384104841Sobrien		&& gi->addend == gs->addend)
3385104841Sobrien	      {
3386104841Sobrien		gi->use_count += gs->use_count;
3387104841Sobrien	        goto got_found;
3388104841Sobrien	      }
338938889Sjdp	  gi->next = hs->got_entries;
339038889Sjdp	  hs->got_entries = gi;
339138889Sjdp	got_found:;
339238889Sjdp	}
339338889Sjdp    }
339438889Sjdp  hi->got_entries = NULL;
339538889Sjdp
339638889Sjdp  /* And similar for the reloc entries.  */
339738889Sjdp
339838889Sjdp  if (hs->reloc_entries == NULL)
339938889Sjdp    hs->reloc_entries = hi->reloc_entries;
340038889Sjdp  else
340138889Sjdp    {
340238889Sjdp      struct alpha_elf_reloc_entry *ri, *rs, *rin, *rsh;
340338889Sjdp
340438889Sjdp      rsh = hs->reloc_entries;
340538889Sjdp      for (ri = hi->reloc_entries; ri ; ri = rin)
340638889Sjdp	{
340738889Sjdp	  rin = ri->next;
340838889Sjdp	  for (rs = rsh; rs ; rs = rs->next)
3409104841Sobrien	    if (ri->rtype == rs->rtype && ri->srel == rs->srel)
341038889Sjdp	      {
341138889Sjdp		rs->count += ri->count;
341238889Sjdp		goto found_reloc;
341338889Sjdp	      }
341438889Sjdp	  ri->next = hs->reloc_entries;
341538889Sjdp	  hs->reloc_entries = ri;
341638889Sjdp	found_reloc:;
341738889Sjdp	}
341838889Sjdp    }
341938889Sjdp  hi->reloc_entries = NULL;
342038889Sjdp
342138889Sjdp  return true;
342238889Sjdp}
342338889Sjdp
342433965Sjdp/* Is it possible to merge two object file's .got tables?  */
342533965Sjdp
342633965Sjdpstatic boolean
342733965Sjdpelf64_alpha_can_merge_gots (a, b)
342833965Sjdp     bfd *a, *b;
342933965Sjdp{
3430104841Sobrien  int total = alpha_elf_tdata (a)->total_got_size;
343160510Sobrien  bfd *bsub;
343233965Sjdp
343333965Sjdp  /* Trivial quick fallout test.  */
3434104841Sobrien  if (total + alpha_elf_tdata (b)->total_got_size <= MAX_GOT_SIZE)
343533965Sjdp    return true;
343633965Sjdp
343733965Sjdp  /* By their nature, local .got entries cannot be merged.  */
3438104841Sobrien  if ((total += alpha_elf_tdata (b)->local_got_size) > MAX_GOT_SIZE)
343933965Sjdp    return false;
344033965Sjdp
344133965Sjdp  /* Failing the common trivial comparison, we must effectively
344233965Sjdp     perform the merge.  Not actually performing the merge means that
344333965Sjdp     we don't have to store undo information in case we fail.  */
344460510Sobrien  for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next)
344560510Sobrien    {
344660510Sobrien      struct alpha_elf_link_hash_entry **hashes = alpha_elf_sym_hashes (bsub);
344760510Sobrien      Elf_Internal_Shdr *symtab_hdr = &elf_tdata (bsub)->symtab_hdr;
344860510Sobrien      int i, n;
344933965Sjdp
345078833Sobrien      n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info;
345160510Sobrien      for (i = 0; i < n; ++i)
345260510Sobrien	{
345360510Sobrien	  struct alpha_elf_got_entry *ae, *be;
345460510Sobrien	  struct alpha_elf_link_hash_entry *h;
345538889Sjdp
345660510Sobrien	  h = hashes[i];
345760510Sobrien	  while (h->root.root.type == bfd_link_hash_indirect
345860510Sobrien	         || h->root.root.type == bfd_link_hash_warning)
345960510Sobrien	    h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
346038889Sjdp
346160510Sobrien	  for (be = h->got_entries; be ; be = be->next)
346260510Sobrien	    {
346360510Sobrien	      if (be->use_count == 0)
346460510Sobrien	        continue;
346560510Sobrien	      if (be->gotobj != b)
346660510Sobrien	        continue;
346733965Sjdp
346860510Sobrien	      for (ae = h->got_entries; ae ; ae = ae->next)
3469104841Sobrien	        if (ae->gotobj == a
3470104841Sobrien		    && ae->reloc_type == be->reloc_type
3471104841Sobrien		    && ae->addend == be->addend)
347260510Sobrien		  goto global_found;
347333965Sjdp
3474104841Sobrien	      total += alpha_got_entry_size (be->reloc_type);
3475104841Sobrien	      if (total > MAX_GOT_SIZE)
347660510Sobrien	        return false;
347760510Sobrien	    global_found:;
347860510Sobrien	    }
347960510Sobrien	}
348060510Sobrien    }
348133965Sjdp
348233965Sjdp  return true;
348333965Sjdp}
348433965Sjdp
348533965Sjdp/* Actually merge two .got tables.  */
348633965Sjdp
348733965Sjdpstatic void
348833965Sjdpelf64_alpha_merge_gots (a, b)
348933965Sjdp     bfd *a, *b;
349033965Sjdp{
3491104841Sobrien  int total = alpha_elf_tdata (a)->total_got_size;
349260510Sobrien  bfd *bsub;
349333965Sjdp
349433965Sjdp  /* Remember local expansion.  */
349533965Sjdp  {
3496104841Sobrien    int e = alpha_elf_tdata (b)->local_got_size;
349733965Sjdp    total += e;
3498104841Sobrien    alpha_elf_tdata (a)->local_got_size += e;
349933965Sjdp  }
350033965Sjdp
350160510Sobrien  for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next)
350260510Sobrien    {
350360510Sobrien      struct alpha_elf_got_entry **local_got_entries;
350460510Sobrien      struct alpha_elf_link_hash_entry **hashes;
350560510Sobrien      Elf_Internal_Shdr *symtab_hdr;
350660510Sobrien      int i, n;
350733965Sjdp
350860510Sobrien      /* Let the local .got entries know they are part of a new subsegment.  */
350960510Sobrien      local_got_entries = alpha_elf_tdata (bsub)->local_got_entries;
351060510Sobrien      if (local_got_entries)
351160510Sobrien        {
351260510Sobrien	  n = elf_tdata (bsub)->symtab_hdr.sh_info;
351360510Sobrien	  for (i = 0; i < n; ++i)
351460510Sobrien	    {
351560510Sobrien	      struct alpha_elf_got_entry *ent;
351660510Sobrien	      for (ent = local_got_entries[i]; ent; ent = ent->next)
351760510Sobrien	        ent->gotobj = a;
351860510Sobrien	    }
351960510Sobrien        }
352033965Sjdp
352160510Sobrien      /* Merge the global .got entries.  */
352260510Sobrien      hashes = alpha_elf_sym_hashes (bsub);
352360510Sobrien      symtab_hdr = &elf_tdata (bsub)->symtab_hdr;
352433965Sjdp
352578833Sobrien      n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info;
352660510Sobrien      for (i = 0; i < n; ++i)
352760510Sobrien        {
352860510Sobrien	  struct alpha_elf_got_entry *ae, *be, **pbe, **start;
352960510Sobrien	  struct alpha_elf_link_hash_entry *h;
353038889Sjdp
353160510Sobrien	  h = hashes[i];
353260510Sobrien	  while (h->root.root.type == bfd_link_hash_indirect
353360510Sobrien	         || h->root.root.type == bfd_link_hash_warning)
353460510Sobrien	    h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
353538889Sjdp
353660510Sobrien	  start = &h->got_entries;
353760510Sobrien	  for (pbe = start, be = *start; be ; pbe = &be->next, be = be->next)
353860510Sobrien	    {
353960510Sobrien	      if (be->use_count == 0)
354060510Sobrien	        {
354133965Sjdp		  *pbe = be->next;
354260510Sobrien		  continue;
354360510Sobrien	        }
354460510Sobrien	      if (be->gotobj != b)
354560510Sobrien	        continue;
354633965Sjdp
354760510Sobrien	      for (ae = *start; ae ; ae = ae->next)
3548104841Sobrien	        if (ae->gotobj == a
3549104841Sobrien		    && ae->reloc_type == be->reloc_type
3550104841Sobrien		    && ae->addend == be->addend)
355160510Sobrien		  {
355260510Sobrien		    ae->flags |= be->flags;
355360510Sobrien		    ae->use_count += be->use_count;
355460510Sobrien		    *pbe = be->next;
355560510Sobrien		    goto global_found;
355660510Sobrien		  }
355760510Sobrien	      be->gotobj = a;
3558104841Sobrien	      total += alpha_got_entry_size (be->reloc_type);
355960510Sobrien
356060510Sobrien	    global_found:;
356160510Sobrien	    }
356260510Sobrien        }
356360510Sobrien
356460510Sobrien      alpha_elf_tdata (bsub)->gotobj = a;
356560510Sobrien    }
3566104841Sobrien  alpha_elf_tdata (a)->total_got_size = total;
356760510Sobrien
356860510Sobrien  /* Merge the two in_got chains.  */
356960510Sobrien  {
357060510Sobrien    bfd *next;
357160510Sobrien
357260510Sobrien    bsub = a;
357360510Sobrien    while ((next = alpha_elf_tdata (bsub)->in_got_link_next) != NULL)
357460510Sobrien      bsub = next;
357560510Sobrien
357660510Sobrien    alpha_elf_tdata (bsub)->in_got_link_next = b;
357733965Sjdp  }
357833965Sjdp}
357933965Sjdp
358033965Sjdp/* Calculate the offsets for the got entries.  */
358133965Sjdp
358233965Sjdpstatic boolean
358333965Sjdpelf64_alpha_calc_got_offsets_for_symbol (h, arg)
358433965Sjdp     struct alpha_elf_link_hash_entry *h;
358589862Sobrien     PTR arg ATTRIBUTE_UNUSED;
358633965Sjdp{
358733965Sjdp  struct alpha_elf_got_entry *gotent;
358833965Sjdp
358994544Sobrien  if (h->root.root.type == bfd_link_hash_warning)
359094544Sobrien    h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
359194544Sobrien
359233965Sjdp  for (gotent = h->got_entries; gotent; gotent = gotent->next)
359360510Sobrien    if (gotent->use_count > 0)
359460510Sobrien      {
359560510Sobrien	bfd_size_type *plge
359660510Sobrien	  = &alpha_elf_tdata (gotent->gotobj)->got->_raw_size;
359733965Sjdp
359860510Sobrien	gotent->got_offset = *plge;
3599104841Sobrien	*plge += alpha_got_entry_size (gotent->reloc_type);
360060510Sobrien      }
360160510Sobrien
360233965Sjdp  return true;
360333965Sjdp}
360433965Sjdp
360533965Sjdpstatic void
360633965Sjdpelf64_alpha_calc_got_offsets (info)
360733965Sjdp     struct bfd_link_info *info;
360833965Sjdp{
360933965Sjdp  bfd *i, *got_list = alpha_elf_hash_table(info)->got_list;
361033965Sjdp
361133965Sjdp  /* First, zero out the .got sizes, as we may be recalculating the
361233965Sjdp     .got after optimizing it.  */
361333965Sjdp  for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next)
361433965Sjdp    alpha_elf_tdata(i)->got->_raw_size = 0;
361533965Sjdp
361633965Sjdp  /* Next, fill in the offsets for all the global entries.  */
361733965Sjdp  alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
361833965Sjdp				elf64_alpha_calc_got_offsets_for_symbol,
361933965Sjdp				NULL);
362033965Sjdp
362133965Sjdp  /* Finally, fill in the offsets for the local entries.  */
362233965Sjdp  for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next)
362333965Sjdp    {
362433965Sjdp      bfd_size_type got_offset = alpha_elf_tdata(i)->got->_raw_size;
362533965Sjdp      bfd *j;
362633965Sjdp
362733965Sjdp      for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next)
362833965Sjdp	{
362933965Sjdp	  struct alpha_elf_got_entry **local_got_entries, *gotent;
363033965Sjdp	  int k, n;
363133965Sjdp
363233965Sjdp	  local_got_entries = alpha_elf_tdata(j)->local_got_entries;
363333965Sjdp	  if (!local_got_entries)
363433965Sjdp	    continue;
363533965Sjdp
363633965Sjdp	  for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k)
363733965Sjdp	    for (gotent = local_got_entries[k]; gotent; gotent = gotent->next)
363860510Sobrien	      if (gotent->use_count > 0)
363960510Sobrien	        {
364060510Sobrien		  gotent->got_offset = got_offset;
3641104841Sobrien		  got_offset += alpha_got_entry_size (gotent->reloc_type);
364260510Sobrien	        }
364333965Sjdp	}
364433965Sjdp
364533965Sjdp      alpha_elf_tdata(i)->got->_raw_size = got_offset;
364660510Sobrien      alpha_elf_tdata(i)->got->_cooked_size = got_offset;
364733965Sjdp    }
364833965Sjdp}
364933965Sjdp
365033965Sjdp/* Constructs the gots.  */
365133965Sjdp
365233965Sjdpstatic boolean
3653104841Sobrienelf64_alpha_size_got_sections (info)
365433965Sjdp     struct bfd_link_info *info;
365533965Sjdp{
365689862Sobrien  bfd *i, *got_list, *cur_got_obj = NULL;
365760510Sobrien  int something_changed = 0;
365833965Sjdp
365960510Sobrien  got_list = alpha_elf_hash_table (info)->got_list;
366033965Sjdp
366160510Sobrien  /* On the first time through, pretend we have an existing got list
366260510Sobrien     consisting of all of the input files.  */
366360510Sobrien  if (got_list == NULL)
366433965Sjdp    {
366560510Sobrien      for (i = info->input_bfds; i ; i = i->link_next)
366660510Sobrien	{
366760510Sobrien	  bfd *this_got = alpha_elf_tdata (i)->gotobj;
366860510Sobrien	  if (this_got == NULL)
366960510Sobrien	    continue;
367033965Sjdp
367160510Sobrien	  /* We are assuming no merging has yet ocurred.  */
367260510Sobrien	  BFD_ASSERT (this_got == i);
367333965Sjdp
3674104841Sobrien          if (alpha_elf_tdata (this_got)->total_got_size > MAX_GOT_SIZE)
367533965Sjdp	    {
367660510Sobrien	      /* Yikes! A single object file has too many entries.  */
367760510Sobrien	      (*_bfd_error_handler)
367860510Sobrien	        (_("%s: .got subsegment exceeds 64K (size %d)"),
367989862Sobrien	         bfd_archive_filename (i),
3680104841Sobrien	         alpha_elf_tdata (this_got)->total_got_size);
368160510Sobrien	      return false;
368233965Sjdp	    }
368360510Sobrien
368460510Sobrien	  if (got_list == NULL)
368560510Sobrien	    got_list = this_got;
368633965Sjdp	  else
368760510Sobrien	    alpha_elf_tdata(cur_got_obj)->got_link_next = this_got;
368860510Sobrien	  cur_got_obj = this_got;
368933965Sjdp	}
369060510Sobrien
369160510Sobrien      /* Strange degenerate case of no got references.  */
369260510Sobrien      if (got_list == NULL)
369360510Sobrien	return true;
369460510Sobrien
369560510Sobrien      alpha_elf_hash_table (info)->got_list = got_list;
369660510Sobrien
369760510Sobrien      /* Force got offsets to be recalculated.  */
369860510Sobrien      something_changed = 1;
369960510Sobrien    }
370060510Sobrien
370160510Sobrien  cur_got_obj = got_list;
370260510Sobrien  i = alpha_elf_tdata(cur_got_obj)->got_link_next;
370360510Sobrien  while (i != NULL)
370460510Sobrien    {
370560510Sobrien      if (elf64_alpha_can_merge_gots (cur_got_obj, i))
370660510Sobrien	{
370760510Sobrien	  elf64_alpha_merge_gots (cur_got_obj, i);
370860510Sobrien	  i = alpha_elf_tdata(i)->got_link_next;
370960510Sobrien	  alpha_elf_tdata(cur_got_obj)->got_link_next = i;
371060510Sobrien	  something_changed = 1;
371160510Sobrien	}
371233965Sjdp      else
371333965Sjdp	{
371433965Sjdp	  cur_got_obj = i;
371560510Sobrien	  i = alpha_elf_tdata(i)->got_link_next;
371633965Sjdp	}
371733965Sjdp    }
371833965Sjdp
371960510Sobrien  /* Once the gots have been merged, fill in the got offsets for
372060510Sobrien     everything therein.  */
372160510Sobrien  if (1 || something_changed)
372260510Sobrien    elf64_alpha_calc_got_offsets (info);
372333965Sjdp
372460510Sobrien  return true;
372560510Sobrien}
372633965Sjdp
3727104841Sobrien/* Called from relax_section to rebuild the PLT in light of
3728104841Sobrien   potential changes in the function's status.  */
3729104841Sobrien
373060510Sobrienstatic boolean
3731104841Sobrienelf64_alpha_size_plt_section (info)
3732104841Sobrien     struct bfd_link_info *info;
3733104841Sobrien{
3734104841Sobrien  asection *splt, *spltrel;
3735104841Sobrien  unsigned long entries;
3736104841Sobrien  bfd *dynobj;
3737104841Sobrien
3738104841Sobrien  dynobj = elf_hash_table(info)->dynobj;
3739104841Sobrien  splt = bfd_get_section_by_name(dynobj, ".plt");
3740104841Sobrien  if (splt == NULL)
3741104841Sobrien    return true;
3742104841Sobrien
3743104841Sobrien  splt->_raw_size = 0;
3744104841Sobrien
3745104841Sobrien  alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
3746104841Sobrien				elf64_alpha_size_plt_section_1, splt);
3747104841Sobrien
3748104841Sobrien  splt->_cooked_size = splt->_raw_size;
3749104841Sobrien
3750104841Sobrien  /* Every plt entry requires a JMP_SLOT relocation.  */
3751104841Sobrien  spltrel = bfd_get_section_by_name (dynobj, ".rela.plt");
3752104841Sobrien  if (splt->_raw_size)
3753104841Sobrien    entries = (splt->_raw_size - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
3754104841Sobrien  else
3755104841Sobrien    entries = 0;
3756104841Sobrien  spltrel->_raw_size = entries * sizeof (Elf64_External_Rela);
3757104841Sobrien  spltrel->_cooked_size = spltrel->_raw_size;
3758104841Sobrien
3759104841Sobrien  return true;
3760104841Sobrien}
3761104841Sobrien
3762104841Sobrienstatic boolean
3763104841Sobrienelf64_alpha_size_plt_section_1 (h, data)
3764104841Sobrien     struct alpha_elf_link_hash_entry *h;
3765104841Sobrien     PTR data;
3766104841Sobrien{
3767104841Sobrien  asection *splt = (asection *) data;
3768104841Sobrien  struct alpha_elf_got_entry *gotent;
3769104841Sobrien
3770104841Sobrien  /* If we didn't need an entry before, we still don't.  */
3771104841Sobrien  if (!(h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT))
3772104841Sobrien    return true;
3773104841Sobrien
3774104841Sobrien  /* There must still be a LITERAL got entry for the function.  */
3775104841Sobrien  for (gotent = h->got_entries; gotent ; gotent = gotent->next)
3776104841Sobrien    if (gotent->reloc_type == R_ALPHA_LITERAL
3777104841Sobrien	&& gotent->use_count > 0)
3778104841Sobrien      break;
3779104841Sobrien
3780104841Sobrien  /* If there is, reset the PLT offset.  If not, there's no longer
3781104841Sobrien     a need for the PLT entry.  */
3782104841Sobrien  if (gotent)
3783104841Sobrien    {
3784104841Sobrien      if (splt->_raw_size == 0)
3785104841Sobrien	splt->_raw_size = PLT_HEADER_SIZE;
3786104841Sobrien      h->root.plt.offset = splt->_raw_size;
3787104841Sobrien      splt->_raw_size += PLT_ENTRY_SIZE;
3788104841Sobrien    }
3789104841Sobrien  else
3790104841Sobrien    {
3791104841Sobrien      h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
3792104841Sobrien      h->root.plt.offset = -1;
3793104841Sobrien    }
3794104841Sobrien
3795104841Sobrien  return true;
3796104841Sobrien}
3797104841Sobrien
3798104841Sobrienstatic boolean
379960510Sobrienelf64_alpha_always_size_sections (output_bfd, info)
3800104841Sobrien     bfd *output_bfd ATTRIBUTE_UNUSED;
380160510Sobrien     struct bfd_link_info *info;
380260510Sobrien{
380360510Sobrien  bfd *i;
380460510Sobrien
380560510Sobrien  if (info->relocateable)
380660510Sobrien    return true;
380760510Sobrien
380860510Sobrien  /* First, take care of the indirect symbols created by versioning.  */
380960510Sobrien  alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
381060510Sobrien				elf64_alpha_merge_ind_symbols,
381160510Sobrien				NULL);
381260510Sobrien
3813104841Sobrien  if (!elf64_alpha_size_got_sections (info))
381460510Sobrien    return false;
381560510Sobrien
381633965Sjdp  /* Allocate space for all of the .got subsections.  */
381760510Sobrien  i = alpha_elf_hash_table (info)->got_list;
381860510Sobrien  for ( ; i ; i = alpha_elf_tdata(i)->got_link_next)
381933965Sjdp    {
382033965Sjdp      asection *s = alpha_elf_tdata(i)->got;
382133965Sjdp      if (s->_raw_size > 0)
382233965Sjdp	{
382333965Sjdp	  s->contents = (bfd_byte *) bfd_zalloc (i, s->_raw_size);
382433965Sjdp	  if (s->contents == NULL)
382533965Sjdp	    return false;
382633965Sjdp	}
382733965Sjdp    }
382833965Sjdp
382933965Sjdp  return true;
383033965Sjdp}
383133965Sjdp
3832104841Sobrien/* The number of dynamic relocations required by a static relocation.  */
3833104841Sobrien
3834104841Sobrienstatic int
3835104841Sobrienalpha_dynamic_entries_for_reloc (r_type, dynamic, shared)
3836104841Sobrien     int r_type, dynamic, shared;
3837104841Sobrien{
3838104841Sobrien  switch (r_type)
3839104841Sobrien    {
3840104841Sobrien    /* May appear in GOT entries.  */
3841104841Sobrien    case R_ALPHA_TLSGD:
3842104841Sobrien      return (dynamic ? 2 : shared ? 1 : 0);
3843104841Sobrien    case R_ALPHA_TLSLDM:
3844104841Sobrien      return shared;
3845104841Sobrien    case R_ALPHA_LITERAL:
3846104841Sobrien      return dynamic || shared;
3847104841Sobrien    case R_ALPHA_GOTDTPREL:
3848104841Sobrien    case R_ALPHA_GOTTPREL:
3849104841Sobrien      return dynamic;
3850104841Sobrien
3851104841Sobrien    /* May appear in data sections.  */
3852104841Sobrien    case R_ALPHA_REFLONG:
3853104841Sobrien    case R_ALPHA_REFQUAD:
3854104841Sobrien      return dynamic || shared;
3855104841Sobrien    case R_ALPHA_SREL64:
3856104841Sobrien    case R_ALPHA_TPREL64:
3857104841Sobrien      return dynamic;
3858104841Sobrien
3859104841Sobrien    /* Everything else is illegal.  We'll issue an error during
3860104841Sobrien       relocate_section.  */
3861104841Sobrien    default:
3862104841Sobrien      return 0;
3863104841Sobrien    }
3864104841Sobrien}
3865104841Sobrien
386633965Sjdp/* Work out the sizes of the dynamic relocation entries.  */
386733965Sjdp
386833965Sjdpstatic boolean
386933965Sjdpelf64_alpha_calc_dynrel_sizes (h, info)
387033965Sjdp     struct alpha_elf_link_hash_entry *h;
387133965Sjdp     struct bfd_link_info *info;
387233965Sjdp{
3873104841Sobrien  boolean dynamic;
3874104841Sobrien  struct alpha_elf_reloc_entry *relent;
3875104841Sobrien  unsigned long entries;
3876104841Sobrien
387794544Sobrien  if (h->root.root.type == bfd_link_hash_warning)
387894544Sobrien    h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
387994544Sobrien
388033965Sjdp  /* If the symbol was defined as a common symbol in a regular object
388133965Sjdp     file, and there was no definition in any dynamic object, then the
388233965Sjdp     linker will have allocated space for the symbol in a common
388333965Sjdp     section but the ELF_LINK_HASH_DEF_REGULAR flag will not have been
388433965Sjdp     set.  This is done for dynamic symbols in
388533965Sjdp     elf_adjust_dynamic_symbol but this is not done for non-dynamic
388633965Sjdp     symbols, somehow.  */
388733965Sjdp  if (((h->root.elf_link_hash_flags
388833965Sjdp       & (ELF_LINK_HASH_DEF_REGULAR
388933965Sjdp	  | ELF_LINK_HASH_REF_REGULAR
389033965Sjdp	  | ELF_LINK_HASH_DEF_DYNAMIC))
389133965Sjdp       == ELF_LINK_HASH_REF_REGULAR)
389233965Sjdp      && (h->root.root.type == bfd_link_hash_defined
389333965Sjdp	  || h->root.root.type == bfd_link_hash_defweak)
389433965Sjdp      && !(h->root.root.u.def.section->owner->flags & DYNAMIC))
3895104841Sobrien    h->root.elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
389633965Sjdp
389733965Sjdp  /* If the symbol is dynamic, we'll need all the relocations in their
389860510Sobrien     natural form.  If this is a shared object, and it has been forced
389960510Sobrien     local, we'll need the same number of RELATIVE relocations.  */
390060510Sobrien
3901104841Sobrien  dynamic = alpha_elf_dynamic_symbol_p (&h->root, info);
3902104841Sobrien
3903104841Sobrien  for (relent = h->reloc_entries; relent; relent = relent->next)
390433965Sjdp    {
3905104841Sobrien      entries = alpha_dynamic_entries_for_reloc (relent->rtype, dynamic,
3906104841Sobrien						 info->shared);
3907104841Sobrien      if (entries)
3908104841Sobrien	{
3909104841Sobrien	  relent->srel->_raw_size +=
3910104841Sobrien	    entries * sizeof (Elf64_External_Rela) * relent->count;
3911104841Sobrien	  if (relent->reltext)
3912104841Sobrien	    info->flags |= DT_TEXTREL;
3913104841Sobrien	}
3914104841Sobrien    }
391533965Sjdp
3916104841Sobrien  return true;
3917104841Sobrien}
391833965Sjdp
3919104841Sobrien/* Set the sizes of the dynamic relocation sections.  */
392048850Sdfr
3921104841Sobrienstatic boolean
3922104841Sobrienelf64_alpha_size_rela_got_section (info)
3923104841Sobrien     struct bfd_link_info *info;
3924104841Sobrien{
3925104841Sobrien  unsigned long entries;
3926104841Sobrien  bfd *i, *dynobj;
3927104841Sobrien  asection *srel;
392848850Sdfr
3929104841Sobrien  /* Shared libraries often require RELATIVE relocs, and some relocs
3930104841Sobrien     require attention for the main application as well.  */
393148850Sdfr
3932104841Sobrien  entries = 0;
3933104841Sobrien  for (i = alpha_elf_hash_table(info)->got_list;
3934104841Sobrien       i ; i = alpha_elf_tdata(i)->got_link_next)
3935104841Sobrien    {
3936104841Sobrien      bfd *j;
3937104841Sobrien
3938104841Sobrien      for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next)
393933965Sjdp	{
3940104841Sobrien	  struct alpha_elf_got_entry **local_got_entries, *gotent;
3941104841Sobrien	  int k, n;
3942104841Sobrien
3943104841Sobrien	  local_got_entries = alpha_elf_tdata(j)->local_got_entries;
3944104841Sobrien	  if (!local_got_entries)
3945104841Sobrien	    continue;
3946104841Sobrien
3947104841Sobrien	  for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k)
3948104841Sobrien	    for (gotent = local_got_entries[k];
3949104841Sobrien		 gotent ; gotent = gotent->next)
3950104841Sobrien	      if (gotent->use_count > 0)
3951104841Sobrien		entries += (alpha_dynamic_entries_for_reloc
3952104841Sobrien			    (gotent->reloc_type, 0, info->shared));
395333965Sjdp	}
395433965Sjdp    }
395548850Sdfr
3956104841Sobrien  dynobj = elf_hash_table(info)->dynobj;
3957104841Sobrien  srel = bfd_get_section_by_name (dynobj, ".rela.got");
3958104841Sobrien  if (!srel)
3959104841Sobrien    {
3960104841Sobrien      BFD_ASSERT (entries == 0);
3961104841Sobrien      return true;
3962104841Sobrien    }
3963104841Sobrien  srel->_raw_size = sizeof (Elf64_External_Rela) * entries;
3964104841Sobrien
3965104841Sobrien  /* Now do the non-local symbols.  */
3966104841Sobrien  alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
3967104841Sobrien				elf64_alpha_size_rela_got_1, info);
3968104841Sobrien
3969104841Sobrien  srel->_cooked_size = srel->_raw_size;
3970104841Sobrien
397133965Sjdp  return true;
397233965Sjdp}
397333965Sjdp
3974104841Sobrien/* Subroutine of elf64_alpha_size_rela_got_section for doing the
3975104841Sobrien   global symbols.  */
3976104841Sobrien
3977104841Sobrienstatic boolean
3978104841Sobrienelf64_alpha_size_rela_got_1 (h, info)
3979104841Sobrien     struct alpha_elf_link_hash_entry *h;
3980104841Sobrien     struct bfd_link_info *info;
3981104841Sobrien{
3982104841Sobrien  boolean dynamic;
3983104841Sobrien  struct alpha_elf_got_entry *gotent;
3984104841Sobrien  unsigned long entries;
3985104841Sobrien
3986104841Sobrien  if (h->root.root.type == bfd_link_hash_warning)
3987104841Sobrien    h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
3988104841Sobrien
3989104841Sobrien  /* If the symbol is dynamic, we'll need all the relocations in their
3990104841Sobrien     natural form.  If this is a shared object, and it has been forced
3991104841Sobrien     local, we'll need the same number of RELATIVE relocations.  */
3992104841Sobrien
3993104841Sobrien  dynamic = alpha_elf_dynamic_symbol_p (&h->root, info);
3994104841Sobrien
3995104841Sobrien  entries = 0;
3996104841Sobrien  for (gotent = h->got_entries; gotent ; gotent = gotent->next)
3997104841Sobrien    if (gotent->use_count > 0)
3998104841Sobrien      entries += alpha_dynamic_entries_for_reloc (gotent->reloc_type,
3999104841Sobrien						  dynamic, info->shared);
4000104841Sobrien
4001104841Sobrien  /* If we are using a .plt entry, subtract one, as the first
4002104841Sobrien     reference uses a .rela.plt entry instead.  */
4003104841Sobrien  if (h->root.plt.offset != MINUS_ONE)
4004104841Sobrien    entries--;
4005104841Sobrien
4006104841Sobrien  if (entries > 0)
4007104841Sobrien    {
4008104841Sobrien      bfd *dynobj = elf_hash_table(info)->dynobj;
4009104841Sobrien      asection *srel = bfd_get_section_by_name (dynobj, ".rela.got");
4010104841Sobrien      BFD_ASSERT (srel != NULL);
4011104841Sobrien      srel->_raw_size += sizeof (Elf64_External_Rela) * entries;
4012104841Sobrien    }
4013104841Sobrien
4014104841Sobrien  return true;
4015104841Sobrien}
4016104841Sobrien
401733965Sjdp/* Set the sizes of the dynamic sections.  */
401833965Sjdp
401933965Sjdpstatic boolean
402033965Sjdpelf64_alpha_size_dynamic_sections (output_bfd, info)
402189862Sobrien     bfd *output_bfd ATTRIBUTE_UNUSED;
402233965Sjdp     struct bfd_link_info *info;
402333965Sjdp{
402433965Sjdp  bfd *dynobj;
402533965Sjdp  asection *s;
402633965Sjdp  boolean relplt;
402733965Sjdp
402833965Sjdp  dynobj = elf_hash_table(info)->dynobj;
402933965Sjdp  BFD_ASSERT(dynobj != NULL);
403033965Sjdp
403133965Sjdp  if (elf_hash_table (info)->dynamic_sections_created)
403233965Sjdp    {
403333965Sjdp      /* Set the contents of the .interp section to the interpreter.  */
403433965Sjdp      if (!info->shared)
403533965Sjdp	{
403633965Sjdp	  s = bfd_get_section_by_name (dynobj, ".interp");
403733965Sjdp	  BFD_ASSERT (s != NULL);
403833965Sjdp	  s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
403933965Sjdp	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
404033965Sjdp	}
404133965Sjdp
404233965Sjdp      /* Now that we've seen all of the input files, we can decide which
404333965Sjdp	 symbols need dynamic relocation entries and which don't.  We've
404433965Sjdp	 collected information in check_relocs that we can now apply to
404533965Sjdp	 size the dynamic relocation sections.  */
404633965Sjdp      alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
4047104841Sobrien				    elf64_alpha_calc_dynrel_sizes, info);
404833965Sjdp
4049104841Sobrien      elf64_alpha_size_rela_got_section (info);
405033965Sjdp    }
405133965Sjdp  /* else we're not dynamic and by definition we don't need such things.  */
405233965Sjdp
405333965Sjdp  /* The check_relocs and adjust_dynamic_symbol entry points have
405433965Sjdp     determined the sizes of the various dynamic sections.  Allocate
405533965Sjdp     memory for them.  */
405633965Sjdp  relplt = false;
405733965Sjdp  for (s = dynobj->sections; s != NULL; s = s->next)
405833965Sjdp    {
405933965Sjdp      const char *name;
406033965Sjdp      boolean strip;
406133965Sjdp
406233965Sjdp      if (!(s->flags & SEC_LINKER_CREATED))
406333965Sjdp	continue;
406433965Sjdp
406533965Sjdp      /* It's OK to base decisions on the section name, because none
406633965Sjdp	 of the dynobj section names depend upon the input files.  */
406733965Sjdp      name = bfd_get_section_name (dynobj, s);
406833965Sjdp
406933965Sjdp      /* If we don't need this section, strip it from the output file.
407033965Sjdp	 This is to handle .rela.bss and .rela.plt.  We must create it
407133965Sjdp	 in create_dynamic_sections, because it must be created before
407233965Sjdp	 the linker maps input sections to output sections.  The
407333965Sjdp	 linker does that before adjust_dynamic_symbol is called, and
407433965Sjdp	 it is that function which decides whether anything needs to
407533965Sjdp	 go into these sections.  */
407633965Sjdp
407733965Sjdp      strip = false;
407833965Sjdp
407933965Sjdp      if (strncmp (name, ".rela", 5) == 0)
408033965Sjdp	{
408133965Sjdp	  strip = (s->_raw_size == 0);
408233965Sjdp
408333965Sjdp	  if (!strip)
408433965Sjdp	    {
408533965Sjdp	      if (strcmp(name, ".rela.plt") == 0)
408633965Sjdp		relplt = true;
408733965Sjdp
408833965Sjdp	      /* We use the reloc_count field as a counter if we need
408933965Sjdp		 to copy relocs into the output file.  */
409033965Sjdp	      s->reloc_count = 0;
409133965Sjdp	    }
409233965Sjdp	}
409333965Sjdp      else if (strcmp (name, ".plt") != 0)
409433965Sjdp	{
409533965Sjdp	  /* It's not one of our dynamic sections, so don't allocate space.  */
409633965Sjdp	  continue;
409733965Sjdp	}
409833965Sjdp
409933965Sjdp      if (strip)
410060510Sobrien	_bfd_strip_section_from_output (info, s);
410133965Sjdp      else
410233965Sjdp	{
410333965Sjdp	  /* Allocate memory for the section contents.  */
410489862Sobrien	  s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
410533965Sjdp	  if (s->contents == NULL && s->_raw_size != 0)
410633965Sjdp	    return false;
410733965Sjdp	}
410833965Sjdp    }
410933965Sjdp
411033965Sjdp  if (elf_hash_table (info)->dynamic_sections_created)
411133965Sjdp    {
411233965Sjdp      /* Add some entries to the .dynamic section.  We fill in the
411333965Sjdp	 values later, in elf64_alpha_finish_dynamic_sections, but we
411433965Sjdp	 must add the entries now so that we get the correct size for
411533965Sjdp	 the .dynamic section.  The DT_DEBUG entry is filled in by the
411633965Sjdp	 dynamic linker and used by the debugger.  */
411789862Sobrien#define add_dynamic_entry(TAG, VAL) \
411889862Sobrien  bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
411989862Sobrien
412033965Sjdp      if (!info->shared)
412133965Sjdp	{
412289862Sobrien	  if (!add_dynamic_entry (DT_DEBUG, 0))
412333965Sjdp	    return false;
412433965Sjdp	}
412533965Sjdp
412633965Sjdp      if (relplt)
412733965Sjdp	{
4128102735Sobrien	  if (!add_dynamic_entry (DT_PLTGOT, 0)
4129102735Sobrien	      || !add_dynamic_entry (DT_PLTRELSZ, 0)
413089862Sobrien	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
413189862Sobrien	      || !add_dynamic_entry (DT_JMPREL, 0))
413233965Sjdp	    return false;
413333965Sjdp	}
413433965Sjdp
413589862Sobrien      if (!add_dynamic_entry (DT_RELA, 0)
413689862Sobrien	  || !add_dynamic_entry (DT_RELASZ, 0)
413789862Sobrien	  || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
413833965Sjdp	return false;
413933965Sjdp
414089862Sobrien      if (info->flags & DF_TEXTREL)
414133965Sjdp	{
414289862Sobrien	  if (!add_dynamic_entry (DT_TEXTREL, 0))
414333965Sjdp	    return false;
414433965Sjdp	}
414533965Sjdp    }
414689862Sobrien#undef add_dynamic_entry
414733965Sjdp
414833965Sjdp  return true;
414933965Sjdp}
415033965Sjdp
4151104841Sobrien/* Relocate an Alpha ELF section for a relocatable link.
4152104841Sobrien
4153104841Sobrien   We don't have to change anything unless the reloc is against a section
4154104841Sobrien   symbol, in which case we have to adjust according to where the section
4155104841Sobrien   symbol winds up in the output section.  */
4156104841Sobrien
4157104841Sobrienstatic boolean
4158104841Sobrienelf64_alpha_relocate_section_r (output_bfd, info, input_bfd, input_section,
4159104841Sobrien			        contents, relocs, local_syms, local_sections)
4160104841Sobrien     bfd *output_bfd ATTRIBUTE_UNUSED;
4161104841Sobrien     struct bfd_link_info *info ATTRIBUTE_UNUSED;
4162104841Sobrien     bfd *input_bfd;
4163104841Sobrien     asection *input_section;
4164104841Sobrien     bfd_byte *contents ATTRIBUTE_UNUSED;
4165104841Sobrien     Elf_Internal_Rela *relocs;
4166104841Sobrien     Elf_Internal_Sym *local_syms;
4167104841Sobrien     asection **local_sections;
4168104841Sobrien{
4169104841Sobrien  unsigned long symtab_hdr_sh_info;
4170104841Sobrien  Elf_Internal_Rela *rel;
4171104841Sobrien  Elf_Internal_Rela *relend;
4172104841Sobrien  boolean ret_val = true;
4173104841Sobrien
4174104841Sobrien  symtab_hdr_sh_info = elf_tdata (input_bfd)->symtab_hdr.sh_info;
4175104841Sobrien
4176104841Sobrien  relend = relocs + input_section->reloc_count;
4177104841Sobrien  for (rel = relocs; rel < relend; rel++)
4178104841Sobrien    {
4179104841Sobrien      unsigned long r_symndx;
4180104841Sobrien      Elf_Internal_Sym *sym;
4181104841Sobrien      asection *sec;
4182104841Sobrien      unsigned long r_type;
4183104841Sobrien
4184104841Sobrien      r_type = ELF64_R_TYPE(rel->r_info);
4185104841Sobrien      if (r_type >= R_ALPHA_max)
4186104841Sobrien	{
4187104841Sobrien	  (*_bfd_error_handler)
4188104841Sobrien	    (_("%s: unknown relocation type %d"),
4189104841Sobrien	     bfd_archive_filename (input_bfd), (int)r_type);
4190104841Sobrien	  bfd_set_error (bfd_error_bad_value);
4191104841Sobrien	  ret_val = false;
4192104841Sobrien	  continue;
4193104841Sobrien	}
4194104841Sobrien
4195104841Sobrien      r_symndx = ELF64_R_SYM(rel->r_info);
4196104841Sobrien
4197104841Sobrien      /* The symbol associated with GPDISP and LITUSE is
4198104841Sobrien	 immaterial.  Only the addend is significant.  */
4199104841Sobrien      if (r_type == R_ALPHA_GPDISP || r_type == R_ALPHA_LITUSE)
4200104841Sobrien	continue;
4201104841Sobrien
4202104841Sobrien      if (r_symndx < symtab_hdr_sh_info)
4203104841Sobrien	{
4204104841Sobrien	  sym = local_syms + r_symndx;
4205104841Sobrien	  if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
4206104841Sobrien	    {
4207104841Sobrien	      sec = local_sections[r_symndx];
4208104841Sobrien	      rel->r_addend += sec->output_offset + sym->st_value;
4209104841Sobrien	    }
4210104841Sobrien	}
4211104841Sobrien    }
4212104841Sobrien
4213104841Sobrien  return ret_val;
4214104841Sobrien}
4215104841Sobrien
421633965Sjdp/* Relocate an Alpha ELF section.  */
421733965Sjdp
421833965Sjdpstatic boolean
421933965Sjdpelf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
422033965Sjdp			      contents, relocs, local_syms, local_sections)
422133965Sjdp     bfd *output_bfd;
422233965Sjdp     struct bfd_link_info *info;
422333965Sjdp     bfd *input_bfd;
422433965Sjdp     asection *input_section;
422533965Sjdp     bfd_byte *contents;
422633965Sjdp     Elf_Internal_Rela *relocs;
422733965Sjdp     Elf_Internal_Sym *local_syms;
422833965Sjdp     asection **local_sections;
422933965Sjdp{
423033965Sjdp  Elf_Internal_Shdr *symtab_hdr;
423133965Sjdp  Elf_Internal_Rela *rel;
423233965Sjdp  Elf_Internal_Rela *relend;
4233104841Sobrien  struct elf_link_tls_segment *tls_segment;
4234104841Sobrien  asection *sgot, *srel, *srelgot;
423533965Sjdp  bfd *dynobj, *gotobj;
4236104841Sobrien  bfd_vma gp, tp_base, dtp_base;
4237104841Sobrien  struct alpha_elf_got_entry **local_got_entries;
4238104841Sobrien  boolean ret_val;
4239104841Sobrien  const char *section_name;
424033965Sjdp
4241104841Sobrien  /* Handle relocatable links with a smaller loop.  */
4242104841Sobrien  if (info->relocateable)
4243104841Sobrien    return elf64_alpha_relocate_section_r (output_bfd, info, input_bfd,
4244104841Sobrien					   input_section, contents, relocs,
4245104841Sobrien					   local_syms, local_sections);
4246104841Sobrien
4247104841Sobrien  /* This is a final link.  */
4248104841Sobrien
4249104841Sobrien  ret_val = true;
4250104841Sobrien
425133965Sjdp  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
4252104841Sobrien
425333965Sjdp  dynobj = elf_hash_table (info)->dynobj;
425433965Sjdp  if (dynobj)
4255104841Sobrien    srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
4256104841Sobrien  else
4257104841Sobrien    srelgot = NULL;
425833965Sjdp
4259104841Sobrien  section_name = (bfd_elf_string_from_elf_section
4260104841Sobrien		  (input_bfd, elf_elfheader(input_bfd)->e_shstrndx,
4261104841Sobrien		   elf_section_data(input_section)->rel_hdr.sh_name));
4262104841Sobrien  BFD_ASSERT(section_name != NULL);
4263104841Sobrien  srel = bfd_get_section_by_name (dynobj, section_name);
4264104841Sobrien
426533965Sjdp  /* Find the gp value for this input bfd.  */
426633965Sjdp  gotobj = alpha_elf_tdata (input_bfd)->gotobj;
426733965Sjdp  if (gotobj)
426833965Sjdp    {
426933965Sjdp      sgot = alpha_elf_tdata (gotobj)->got;
427033965Sjdp      gp = _bfd_get_gp_value (gotobj);
427133965Sjdp      if (gp == 0)
427233965Sjdp	{
427333965Sjdp	  gp = (sgot->output_section->vma
427433965Sjdp		+ sgot->output_offset
427533965Sjdp		+ 0x8000);
427633965Sjdp	  _bfd_set_gp_value (gotobj, gp);
427733965Sjdp	}
427833965Sjdp    }
4279104841Sobrien  else
4280104841Sobrien    {
4281104841Sobrien      sgot = NULL;
4282104841Sobrien      gp = 0;
4283104841Sobrien    }
428433965Sjdp
4285104841Sobrien  local_got_entries = alpha_elf_tdata(input_bfd)->local_got_entries;
4286104841Sobrien
4287104841Sobrien  tls_segment = elf_hash_table (info)->tls_segment;
4288104841Sobrien  if (tls_segment)
4289104841Sobrien    {
4290104841Sobrien      dtp_base = alpha_get_dtprel_base (tls_segment);
4291104841Sobrien      tp_base = alpha_get_tprel_base (tls_segment);
4292104841Sobrien    }
4293104841Sobrien  else
4294104841Sobrien    dtp_base = tp_base = 0;
4295104841Sobrien
429633965Sjdp  relend = relocs + input_section->reloc_count;
4297104841Sobrien  for (rel = relocs; rel < relend; rel++)
429833965Sjdp    {
4299104841Sobrien      struct alpha_elf_link_hash_entry *h = NULL;
4300104841Sobrien      struct alpha_elf_got_entry *gotent;
4301104841Sobrien      bfd_reloc_status_type r;
430233965Sjdp      reloc_howto_type *howto;
430333965Sjdp      unsigned long r_symndx;
4304104841Sobrien      Elf_Internal_Sym *sym = NULL;
4305104841Sobrien      asection *sec = NULL;
4306104841Sobrien      bfd_vma value;
430733965Sjdp      bfd_vma addend;
4308104841Sobrien      boolean dynamic_symbol_p;
4309104841Sobrien      boolean undef_weak_ref = false;
4310104841Sobrien      unsigned long r_type;
431133965Sjdp
431233965Sjdp      r_type = ELF64_R_TYPE(rel->r_info);
4313104841Sobrien      if (r_type >= R_ALPHA_max)
431433965Sjdp	{
4315104841Sobrien	  (*_bfd_error_handler)
4316104841Sobrien	    (_("%s: unknown relocation type %d"),
4317104841Sobrien	     bfd_archive_filename (input_bfd), (int)r_type);
431833965Sjdp	  bfd_set_error (bfd_error_bad_value);
4319104841Sobrien	  ret_val = false;
4320104841Sobrien	  continue;
432133965Sjdp	}
4322104841Sobrien
432333965Sjdp      howto = elf64_alpha_howto_table + r_type;
432433965Sjdp      r_symndx = ELF64_R_SYM(rel->r_info);
432533965Sjdp
4326104841Sobrien      if (r_symndx < symtab_hdr->sh_info)
432733965Sjdp	{
4328104841Sobrien	  sym = local_syms + r_symndx;
4329104841Sobrien	  sec = local_sections[r_symndx];
4330104841Sobrien	  value = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
433160510Sobrien
4332104841Sobrien	  if (local_got_entries)
4333104841Sobrien	    gotent = local_got_entries[r_symndx];
4334104841Sobrien	  else
4335104841Sobrien	    gotent = NULL;
433660510Sobrien
4337104841Sobrien	  /* Need to adjust local GOT entries' addends for SEC_MERGE
4338104841Sobrien	     unless it has been done already.  */
4339104841Sobrien	  if ((sec->flags & SEC_MERGE)
4340104841Sobrien	      && ELF_ST_TYPE (sym->st_info) == STT_SECTION
4341104841Sobrien	      && (elf_section_data (sec)->sec_info_type
4342104841Sobrien		  == ELF_INFO_TYPE_MERGE)
4343104841Sobrien	      && gotent
4344104841Sobrien	      && !gotent->reloc_xlated)
434533965Sjdp	    {
4346104841Sobrien	      struct alpha_elf_got_entry *ent;
4347104841Sobrien	      asection *msec;
4348104841Sobrien
4349104841Sobrien	      for (ent = gotent; ent; ent = ent->next)
435033965Sjdp		{
4351104841Sobrien		  ent->reloc_xlated = 1;
4352104841Sobrien		  if (ent->use_count == 0)
4353104841Sobrien		    continue;
4354104841Sobrien		  msec = sec;
4355104841Sobrien		  ent->addend =
4356104841Sobrien		    _bfd_merged_section_offset (output_bfd, &msec,
4357104841Sobrien						elf_section_data (sec)->
4358104841Sobrien						  sec_info,
4359104841Sobrien						sym->st_value + ent->addend,
4360104841Sobrien						(bfd_vma) 0);
4361104841Sobrien		  ent->addend -= sym->st_value;
4362104841Sobrien		  ent->addend += msec->output_section->vma
4363104841Sobrien				 + msec->output_offset
4364104841Sobrien				 - sec->output_section->vma
4365104841Sobrien				 - sec->output_offset;
436633965Sjdp		}
436733965Sjdp	    }
436833965Sjdp
4369104841Sobrien	  dynamic_symbol_p = false;
437033965Sjdp	}
437133965Sjdp      else
437233965Sjdp	{
437333965Sjdp	  h = alpha_elf_sym_hashes (input_bfd)[r_symndx - symtab_hdr->sh_info];
437433965Sjdp
437533965Sjdp	  while (h->root.root.type == bfd_link_hash_indirect
437633965Sjdp		 || h->root.root.type == bfd_link_hash_warning)
437733965Sjdp	    h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
437833965Sjdp
4379104841Sobrien	  value = 0;
438033965Sjdp	  if (h->root.root.type == bfd_link_hash_defined
438133965Sjdp	      || h->root.root.type == bfd_link_hash_defweak)
438233965Sjdp	    {
438333965Sjdp	      sec = h->root.root.u.def.section;
438433965Sjdp
4385104841Sobrien	      /* Detect the cases that sym_sec->output_section is
4386104841Sobrien		 expected to be NULL -- all cases in which the symbol
4387104841Sobrien		 is defined in another shared module.  This includes
4388104841Sobrien		 PLT relocs for which we've created a PLT entry and
4389104841Sobrien		 other relocs for which we're prepared to create
4390104841Sobrien		 dynamic relocations.  */
4391104841Sobrien	      /* ??? Just accept it NULL and continue.  */
4392104841Sobrien
4393104841Sobrien	      if (sec->output_section != NULL)
4394104841Sobrien		value = (h->root.root.u.def.value
4395104841Sobrien			 + sec->output_section->vma
4396104841Sobrien			      + sec->output_offset);
439733965Sjdp	    }
439833965Sjdp	  else if (h->root.root.type == bfd_link_hash_undefweak)
4399104841Sobrien	    undef_weak_ref = true;
440089862Sobrien	  else if (info->shared
440189862Sobrien		   && (!info->symbolic || info->allow_shlib_undefined)
440268770Sobrien		   && !info->no_undefined
440368770Sobrien		   && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
4404104841Sobrien	    ;
440533965Sjdp	  else
440633965Sjdp	    {
440733965Sjdp	      if (!((*info->callbacks->undefined_symbol)
440833965Sjdp		    (info, h->root.root.root.string, input_bfd,
440960510Sobrien		     input_section, rel->r_offset,
441068770Sobrien		     (!info->shared || info->no_undefined
441168770Sobrien		      || ELF_ST_VISIBILITY (h->root.other)))))
4412104841Sobrien		return false;
4413104841Sobrien	      ret_val = false;
4414104841Sobrien	      continue;
441533965Sjdp	    }
4416104841Sobrien
4417104841Sobrien          dynamic_symbol_p = alpha_elf_dynamic_symbol_p (&h->root, info);
4418104841Sobrien	  gotent = h->got_entries;
441933965Sjdp	}
4420104841Sobrien
442133965Sjdp      addend = rel->r_addend;
4422104841Sobrien      value += addend;
442333965Sjdp
4424104841Sobrien      /* Search for the proper got entry.  */
4425104841Sobrien      for (; gotent ; gotent = gotent->next)
4426104841Sobrien	if (gotent->gotobj == gotobj
4427104841Sobrien	    && gotent->reloc_type == r_type
4428104841Sobrien	    && gotent->addend == addend)
4429104841Sobrien	  break;
4430104841Sobrien
443133965Sjdp      switch (r_type)
443233965Sjdp	{
443333965Sjdp	case R_ALPHA_GPDISP:
443433965Sjdp	  {
443533965Sjdp	    bfd_byte *p_ldah, *p_lda;
443633965Sjdp
443733965Sjdp	    BFD_ASSERT(gp != 0);
443833965Sjdp
4439104841Sobrien	    value = (input_section->output_section->vma
4440104841Sobrien		     + input_section->output_offset
4441104841Sobrien		     + rel->r_offset);
444233965Sjdp
4443104841Sobrien	    p_ldah = contents + rel->r_offset;
444433965Sjdp	    p_lda = p_ldah + rel->r_addend;
444533965Sjdp
4446104841Sobrien	    r = elf64_alpha_do_reloc_gpdisp (input_bfd, gp - value,
444733965Sjdp					     p_ldah, p_lda);
444833965Sjdp	  }
444933965Sjdp	  break;
445033965Sjdp
445133965Sjdp	case R_ALPHA_LITERAL:
4452104841Sobrien	  BFD_ASSERT(sgot != NULL);
4453104841Sobrien	  BFD_ASSERT(gp != 0);
4454104841Sobrien	  BFD_ASSERT(gotent != NULL);
4455104841Sobrien	  BFD_ASSERT(gotent->use_count >= 1);
445633965Sjdp
4457104841Sobrien	  if (!gotent->reloc_done)
4458104841Sobrien	    {
4459104841Sobrien	      gotent->reloc_done = 1;
446033965Sjdp
4461104841Sobrien	      bfd_put_64 (output_bfd, value,
4462104841Sobrien			  sgot->contents + gotent->got_offset);
446389862Sobrien
4464104841Sobrien	      /* If the symbol has been forced local, output a
4465104841Sobrien		 RELATIVE reloc, otherwise it will be handled in
4466104841Sobrien		 finish_dynamic_symbol.  */
4467104841Sobrien	      if (info->shared && !dynamic_symbol_p)
4468104841Sobrien		{
4469104841Sobrien		  Elf_Internal_Rela outrel;
447089862Sobrien
4471104841Sobrien		  BFD_ASSERT(srelgot != NULL);
447233965Sjdp
4473104841Sobrien		  outrel.r_offset = (sgot->output_section->vma
4474104841Sobrien				     + sgot->output_offset
4475104841Sobrien				     + gotent->got_offset);
4476104841Sobrien		  outrel.r_info = ELF64_R_INFO (0, R_ALPHA_RELATIVE);
4477104841Sobrien		  outrel.r_addend = value;
447833965Sjdp
4479104841Sobrien		  bfd_elf64_swap_reloca_out (output_bfd, &outrel,
4480104841Sobrien					     ((Elf64_External_Rela *)
4481104841Sobrien					      srelgot->contents)
4482104841Sobrien					     + srelgot->reloc_count++);
4483104841Sobrien		  BFD_ASSERT (sizeof (Elf64_External_Rela)
4484104841Sobrien			      * srelgot->reloc_count
4485104841Sobrien			      <= srelgot->_cooked_size);
4486104841Sobrien		}
4487104841Sobrien	    }
448833965Sjdp
4489104841Sobrien	  value = (sgot->output_section->vma
4490104841Sobrien		   + sgot->output_offset
4491104841Sobrien		   + gotent->got_offset);
4492104841Sobrien	  value -= gp;
449333965Sjdp	  goto default_reloc;
449433965Sjdp
4495115361Sobrien	case R_ALPHA_GPREL32:
4496115361Sobrien	  /* If the target section was a removed linkonce section,
4497115361Sobrien	     r_symndx will be zero.  In this case, assume that the
4498115361Sobrien	     switch will not be used, so don't fill it in.  If we
4499115361Sobrien	     do nothing here, we'll get relocation truncated messages,
4500115361Sobrien	     due to the placement of the application above 4GB.  */
4501115361Sobrien	  if (r_symndx == 0)
4502115361Sobrien	    {
4503115361Sobrien	      r = bfd_reloc_ok;
4504115361Sobrien	      break;
4505115361Sobrien	    }
4506115361Sobrien	  /* FALLTHRU */
4507115361Sobrien
450889862Sobrien	case R_ALPHA_GPREL16:
450960510Sobrien	case R_ALPHA_GPRELLOW:
4510104841Sobrien	  if (dynamic_symbol_p)
451189862Sobrien            {
451289862Sobrien              (*_bfd_error_handler)
451389862Sobrien                (_("%s: gp-relative relocation against dynamic symbol %s"),
451489862Sobrien                 bfd_archive_filename (input_bfd), h->root.root.root.string);
451589862Sobrien              ret_val = false;
451689862Sobrien            }
451733965Sjdp	  BFD_ASSERT(gp != 0);
4518104841Sobrien	  value -= gp;
451933965Sjdp	  goto default_reloc;
452033965Sjdp
452160510Sobrien	case R_ALPHA_GPRELHIGH:
4522104841Sobrien	  if (dynamic_symbol_p)
452389862Sobrien            {
452489862Sobrien              (*_bfd_error_handler)
452589862Sobrien                (_("%s: gp-relative relocation against dynamic symbol %s"),
452689862Sobrien                 bfd_archive_filename (input_bfd), h->root.root.root.string);
452789862Sobrien              ret_val = false;
452889862Sobrien            }
452960510Sobrien	  BFD_ASSERT(gp != 0);
4530104841Sobrien	  value -= gp;
4531104841Sobrien	  value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
453260510Sobrien	  goto default_reloc;
453360510Sobrien
453489862Sobrien	case R_ALPHA_HINT:
453589862Sobrien	  /* A call to a dynamic symbol is definitely out of range of
453689862Sobrien	     the 16-bit displacement.  Don't bother writing anything.  */
4537104841Sobrien	  if (dynamic_symbol_p)
453889862Sobrien	    {
453989862Sobrien	      r = bfd_reloc_ok;
454089862Sobrien	      break;
454189862Sobrien	    }
4542104841Sobrien	  /* The regular PC-relative stuff measures from the start of
4543104841Sobrien	     the instruction rather than the end.  */
4544104841Sobrien	  value -= 4;
4545104841Sobrien	  goto default_reloc;
454689862Sobrien
454733965Sjdp	case R_ALPHA_BRADDR:
4548104841Sobrien	  if (dynamic_symbol_p)
4549104841Sobrien            {
4550104841Sobrien              (*_bfd_error_handler)
4551104841Sobrien                (_("%s: pc-relative relocation against dynamic symbol %s"),
4552104841Sobrien                 bfd_archive_filename (input_bfd), h->root.root.root.string);
4553104841Sobrien              ret_val = false;
4554104841Sobrien            }
455533965Sjdp	  /* The regular PC-relative stuff measures from the start of
455633965Sjdp	     the instruction rather than the end.  */
4557104841Sobrien	  value -= 4;
455833965Sjdp	  goto default_reloc;
455933965Sjdp
456091049Sobrien	case R_ALPHA_BRSGP:
456191049Sobrien	  {
456291049Sobrien	    int other;
456391049Sobrien	    const char *name;
456491049Sobrien
456591049Sobrien	    /* The regular PC-relative stuff measures from the start of
456691049Sobrien	       the instruction rather than the end.  */
4567104841Sobrien	    value -= 4;
456891049Sobrien
456991049Sobrien	    /* The source and destination gp must be the same.  Note that
457091049Sobrien	       the source will always have an assigned gp, since we forced
457191049Sobrien	       one in check_relocs, but that the destination may not, as
4572104841Sobrien	       it might not have had any relocations at all.  Also take
457391049Sobrien	       care not to crash if H is an undefined symbol.  */
457491049Sobrien	    if (h != NULL && sec != NULL
457591049Sobrien		&& alpha_elf_tdata (sec->owner)->gotobj
457691049Sobrien		&& gotobj != alpha_elf_tdata (sec->owner)->gotobj)
457791049Sobrien	      {
457891049Sobrien		(*_bfd_error_handler)
457991049Sobrien		  (_("%s: change in gp: BRSGP %s"),
458091049Sobrien		   bfd_archive_filename (input_bfd), h->root.root.root.string);
458191049Sobrien		ret_val = false;
458291049Sobrien	      }
458391049Sobrien
458491049Sobrien	    /* The symbol should be marked either NOPV or STD_GPLOAD.  */
458591049Sobrien	    if (h != NULL)
458691049Sobrien	      other = h->root.other;
458791049Sobrien	    else
458891049Sobrien	      other = sym->st_other;
458991049Sobrien	    switch (other & STO_ALPHA_STD_GPLOAD)
459091049Sobrien	      {
459191049Sobrien	      case STO_ALPHA_NOPV:
459291049Sobrien	        break;
459391049Sobrien	      case STO_ALPHA_STD_GPLOAD:
4594107497Sobrien		value += 8;
459591049Sobrien		break;
459691049Sobrien	      default:
459791049Sobrien		if (h != NULL)
459891049Sobrien		  name = h->root.root.root.string;
459991049Sobrien		else
460091049Sobrien		  {
460191049Sobrien		    name = (bfd_elf_string_from_elf_section
460291049Sobrien			    (input_bfd, symtab_hdr->sh_link, sym->st_name));
460391049Sobrien		    if (name == NULL)
460491049Sobrien		      name = _("<unknown>");
460591049Sobrien		    else if (name[0] == 0)
460691049Sobrien		      name = bfd_section_name (input_bfd, sec);
460791049Sobrien		  }
460891049Sobrien		(*_bfd_error_handler)
460991049Sobrien		  (_("%s: !samegp reloc against symbol without .prologue: %s"),
461091049Sobrien		   bfd_archive_filename (input_bfd), name);
461191049Sobrien		ret_val = false;
461291049Sobrien		break;
461391049Sobrien	      }
461491049Sobrien
461591049Sobrien	    goto default_reloc;
461691049Sobrien	  }
461791049Sobrien
461833965Sjdp	case R_ALPHA_REFLONG:
461933965Sjdp	case R_ALPHA_REFQUAD:
4620104841Sobrien	case R_ALPHA_DTPREL64:
4621104841Sobrien	case R_ALPHA_TPREL64:
462233965Sjdp	  {
462333965Sjdp	    Elf_Internal_Rela outrel;
462433965Sjdp
462533965Sjdp	    /* Careful here to remember RELATIVE relocations for global
462633965Sjdp	       variables for symbolic shared objects.  */
462733965Sjdp
4628104841Sobrien	    if (dynamic_symbol_p)
462933965Sjdp	      {
463033965Sjdp		BFD_ASSERT(h->root.dynindx != -1);
4631104841Sobrien		outrel.r_info = ELF64_R_INFO (h->root.dynindx, r_type);
463233965Sjdp		outrel.r_addend = addend;
4633104841Sobrien		addend = 0, value = 0;
463433965Sjdp	      }
4635104841Sobrien	    else if (r_type == R_ALPHA_DTPREL64)
4636104841Sobrien	      {
4637104841Sobrien		BFD_ASSERT(tls_segment != NULL);
4638104841Sobrien		value -= dtp_base;
4639104841Sobrien		goto default_reloc;
4640104841Sobrien	      }
4641104841Sobrien	    else if (r_type == R_ALPHA_TPREL64)
4642104841Sobrien	      {
4643104841Sobrien		BFD_ASSERT(tls_segment != NULL);
4644104841Sobrien		value -= dtp_base;
4645104841Sobrien		goto default_reloc;
4646104841Sobrien	      }
464789862Sobrien	    else if (info->shared
464889862Sobrien		     && r_symndx != 0
464989862Sobrien		     && (input_section->flags & SEC_ALLOC))
465033965Sjdp	      {
4651104841Sobrien		if (r_type == R_ALPHA_REFLONG)
4652104841Sobrien		  {
4653104841Sobrien		    (*_bfd_error_handler)
4654104841Sobrien		      (_("%s: unhandled dynamic relocation against %s"),
4655104841Sobrien		       bfd_archive_filename (input_bfd),
4656104841Sobrien		       h->root.root.root.string);
4657104841Sobrien		    ret_val = false;
4658104841Sobrien		  }
4659104841Sobrien		outrel.r_info = ELF64_R_INFO (0, R_ALPHA_RELATIVE);
4660104841Sobrien		outrel.r_addend = value;
466133965Sjdp	      }
466233965Sjdp	    else
466333965Sjdp	      goto default_reloc;
466433965Sjdp
4665104841Sobrien	    BFD_ASSERT(srel != NULL);
466633965Sjdp
466789862Sobrien	    outrel.r_offset =
466889862Sobrien	      _bfd_elf_section_offset (output_bfd, info, input_section,
466989862Sobrien				       rel->r_offset);
467091049Sobrien	    if ((outrel.r_offset | 1) != (bfd_vma) -1)
467133965Sjdp	      outrel.r_offset += (input_section->output_section->vma
467233965Sjdp				  + input_section->output_offset);
467333965Sjdp	    else
467433965Sjdp	      memset (&outrel, 0, sizeof outrel);
467533965Sjdp
467633965Sjdp	    bfd_elf64_swap_reloca_out (output_bfd, &outrel,
467733965Sjdp				       ((Elf64_External_Rela *)
467833965Sjdp					srel->contents)
467933965Sjdp				       + srel->reloc_count++);
468077303Sobrien	    BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
468148850Sdfr			<= srel->_cooked_size);
468233965Sjdp	  }
468333965Sjdp	  goto default_reloc;
468433965Sjdp
4685104841Sobrien	case R_ALPHA_SREL16:
468699465Sobrien	case R_ALPHA_SREL32:
468799465Sobrien	case R_ALPHA_SREL64:
4688104841Sobrien	  if (dynamic_symbol_p)
4689104841Sobrien            {
4690104841Sobrien              (*_bfd_error_handler)
4691104841Sobrien                (_("%s: pc-relative relocation against dynamic symbol %s"),
4692104841Sobrien                 bfd_archive_filename (input_bfd), h->root.root.root.string);
4693104841Sobrien              ret_val = false;
4694104841Sobrien            }
4695104841Sobrien
469699465Sobrien	  /* ??? .eh_frame references to discarded sections will be smashed
469799465Sobrien	     to relocations against SHN_UNDEF.  The .eh_frame format allows
469899465Sobrien	     NULL to be encoded as 0 in any format, so this works here.  */
469999465Sobrien	  if (r_symndx == 0)
470099465Sobrien	    howto = (elf64_alpha_howto_table
470199465Sobrien		     + (r_type - R_ALPHA_SREL32 + R_ALPHA_REFLONG));
470299465Sobrien	  goto default_reloc;
470399465Sobrien
4704104841Sobrien	case R_ALPHA_TLSLDM:
4705104841Sobrien	  /* Ignore the symbol for the relocation.  The result is always
4706104841Sobrien	     the current module.  */
4707104841Sobrien	  dynamic_symbol_p = 0;
4708104841Sobrien	  /* FALLTHRU */
4709104841Sobrien
4710104841Sobrien	case R_ALPHA_TLSGD:
4711104841Sobrien	  if (!gotent->reloc_done)
4712104841Sobrien	    {
4713104841Sobrien	      gotent->reloc_done = 1;
4714104841Sobrien
4715104841Sobrien	      /* Note that the module index for the main program is 1.  */
4716104841Sobrien	      bfd_put_64 (output_bfd, !info->shared && !dynamic_symbol_p,
4717104841Sobrien			  sgot->contents + gotent->got_offset);
4718104841Sobrien
4719104841Sobrien	      /* If the symbol has been forced local, output a
4720104841Sobrien		 DTPMOD64 reloc, otherwise it will be handled in
4721104841Sobrien		 finish_dynamic_symbol.  */
4722104841Sobrien	      if (info->shared && !dynamic_symbol_p)
4723104841Sobrien		{
4724104841Sobrien		  Elf_Internal_Rela outrel;
4725104841Sobrien
4726104841Sobrien		  BFD_ASSERT(srelgot != NULL);
4727104841Sobrien
4728104841Sobrien		  outrel.r_offset = (sgot->output_section->vma
4729104841Sobrien				     + sgot->output_offset
4730104841Sobrien				     + gotent->got_offset);
4731104841Sobrien		  /* ??? Proper dynindx here.  */
4732104841Sobrien		  outrel.r_info = ELF64_R_INFO (0, R_ALPHA_DTPMOD64);
4733104841Sobrien		  outrel.r_addend = 0;
4734104841Sobrien
4735104841Sobrien		  bfd_elf64_swap_reloca_out (output_bfd, &outrel,
4736104841Sobrien					     ((Elf64_External_Rela *)
4737104841Sobrien					      srelgot->contents)
4738104841Sobrien					     + srelgot->reloc_count++);
4739104841Sobrien		  BFD_ASSERT (sizeof (Elf64_External_Rela)
4740104841Sobrien			      * srelgot->reloc_count
4741104841Sobrien			      <= srelgot->_cooked_size);
4742104841Sobrien		}
4743104841Sobrien
4744104841Sobrien	      if (dynamic_symbol_p || r_type == R_ALPHA_TLSLDM)
4745104841Sobrien		value = 0;
4746104841Sobrien	      else
4747104841Sobrien		{
4748104841Sobrien		  BFD_ASSERT(tls_segment != NULL);
4749104841Sobrien	          value -= dtp_base;
4750104841Sobrien		}
4751104841Sobrien	      bfd_put_64 (output_bfd, value,
4752104841Sobrien			  sgot->contents + gotent->got_offset + 8);
4753104841Sobrien	    }
4754104841Sobrien
4755104841Sobrien	  value = (sgot->output_section->vma
4756104841Sobrien		   + sgot->output_offset
4757104841Sobrien		   + gotent->got_offset);
4758104841Sobrien	  value -= gp;
4759104841Sobrien	  goto default_reloc;
4760104841Sobrien
4761104841Sobrien	case R_ALPHA_DTPRELHI:
4762104841Sobrien	case R_ALPHA_DTPRELLO:
4763104841Sobrien	case R_ALPHA_DTPREL16:
4764104841Sobrien	  if (dynamic_symbol_p)
4765104841Sobrien            {
4766104841Sobrien              (*_bfd_error_handler)
4767104841Sobrien                (_("%s: dtp-relative relocation against dynamic symbol %s"),
4768104841Sobrien                 bfd_archive_filename (input_bfd), h->root.root.root.string);
4769104841Sobrien              ret_val = false;
4770104841Sobrien            }
4771104841Sobrien	  BFD_ASSERT(tls_segment != NULL);
4772104841Sobrien	  value -= dtp_base;
4773104841Sobrien	  if (r_type == R_ALPHA_DTPRELHI)
4774104841Sobrien	    value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
4775104841Sobrien	  goto default_reloc;
4776104841Sobrien
4777104841Sobrien	case R_ALPHA_TPRELHI:
4778104841Sobrien	case R_ALPHA_TPRELLO:
4779104841Sobrien	case R_ALPHA_TPREL16:
4780104841Sobrien	  if (info->shared)
4781104841Sobrien	    {
4782104841Sobrien	      (*_bfd_error_handler)
4783104841Sobrien		(_("%s: TLS local exec code cannot be linked into shared objects"),
4784104841Sobrien		bfd_archive_filename (input_bfd));
4785104841Sobrien              ret_val = false;
4786104841Sobrien	    }
4787104841Sobrien	  else if (dynamic_symbol_p)
4788104841Sobrien            {
4789104841Sobrien              (*_bfd_error_handler)
4790104841Sobrien                (_("%s: tp-relative relocation against dynamic symbol %s"),
4791104841Sobrien                 bfd_archive_filename (input_bfd), h->root.root.root.string);
4792104841Sobrien              ret_val = false;
4793104841Sobrien            }
4794104841Sobrien	  BFD_ASSERT(tls_segment != NULL);
4795104841Sobrien	  value -= tp_base;
4796104841Sobrien	  if (r_type == R_ALPHA_TPRELHI)
4797104841Sobrien	    value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
4798104841Sobrien	  goto default_reloc;
4799104841Sobrien
4800104841Sobrien	case R_ALPHA_GOTDTPREL:
4801104841Sobrien	case R_ALPHA_GOTTPREL:
4802104841Sobrien	  BFD_ASSERT(sgot != NULL);
4803104841Sobrien	  BFD_ASSERT(gp != 0);
4804104841Sobrien	  BFD_ASSERT(gotent != NULL);
4805104841Sobrien	  BFD_ASSERT(gotent->use_count >= 1);
4806104841Sobrien
4807104841Sobrien	  if (!gotent->reloc_done)
4808104841Sobrien	    {
4809104841Sobrien	      gotent->reloc_done = 1;
4810104841Sobrien
4811104841Sobrien	      if (dynamic_symbol_p)
4812104841Sobrien		value = 0;
4813104841Sobrien	      else
4814104841Sobrien		{
4815104841Sobrien		  BFD_ASSERT(tls_segment != NULL);
4816104841Sobrien		  value -= (r_type == R_ALPHA_GOTDTPREL ? dtp_base : tp_base);
4817104841Sobrien		}
4818104841Sobrien	      bfd_put_64 (output_bfd, value,
4819104841Sobrien			  sgot->contents + gotent->got_offset);
4820104841Sobrien	    }
4821104841Sobrien
4822104841Sobrien	  value = (sgot->output_section->vma
4823104841Sobrien		   + sgot->output_offset
4824104841Sobrien		   + gotent->got_offset);
4825104841Sobrien	  value -= gp;
4826104841Sobrien	  goto default_reloc;
4827104841Sobrien
482833965Sjdp	default:
482933965Sjdp	default_reloc:
483033965Sjdp	  r = _bfd_final_link_relocate (howto, input_bfd, input_section,
4831104841Sobrien					contents, rel->r_offset, value, 0);
483233965Sjdp	  break;
483333965Sjdp	}
483433965Sjdp
483533965Sjdp      switch (r)
483633965Sjdp	{
483733965Sjdp	case bfd_reloc_ok:
483833965Sjdp	  break;
483933965Sjdp
484033965Sjdp	case bfd_reloc_overflow:
484133965Sjdp	  {
484233965Sjdp	    const char *name;
484333965Sjdp
484489862Sobrien	    /* Don't warn if the overflow is due to pc relative reloc
484589862Sobrien	       against discarded section.  Section optimization code should
484689862Sobrien	       handle it.  */
484789862Sobrien
484889862Sobrien	    if (r_symndx < symtab_hdr->sh_info
484989862Sobrien		&& sec != NULL && howto->pc_relative
485089862Sobrien		&& elf_discarded_section (sec))
485189862Sobrien	      break;
485289862Sobrien
485333965Sjdp	    if (h != NULL)
485433965Sjdp	      name = h->root.root.root.string;
485533965Sjdp	    else
485633965Sjdp	      {
485733965Sjdp		name = (bfd_elf_string_from_elf_section
485833965Sjdp			(input_bfd, symtab_hdr->sh_link, sym->st_name));
485933965Sjdp		if (name == NULL)
486033965Sjdp		  return false;
486133965Sjdp		if (*name == '\0')
486233965Sjdp		  name = bfd_section_name (input_bfd, sec);
486333965Sjdp	      }
486433965Sjdp	    if (! ((*info->callbacks->reloc_overflow)
486533965Sjdp		   (info, name, howto->name, (bfd_vma) 0,
486633965Sjdp		    input_bfd, input_section, rel->r_offset)))
486789862Sobrien	      ret_val = false;
486833965Sjdp	  }
486933965Sjdp	  break;
487033965Sjdp
487133965Sjdp	default:
487233965Sjdp	case bfd_reloc_outofrange:
487333965Sjdp	  abort ();
487433965Sjdp	}
487533965Sjdp    }
487633965Sjdp
487789862Sobrien  return ret_val;
487833965Sjdp}
487933965Sjdp
488033965Sjdp/* Finish up dynamic symbol handling.  We set the contents of various
488133965Sjdp   dynamic sections here.  */
488233965Sjdp
488333965Sjdpstatic boolean
488433965Sjdpelf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym)
488533965Sjdp     bfd *output_bfd;
488633965Sjdp     struct bfd_link_info *info;
488733965Sjdp     struct elf_link_hash_entry *h;
488833965Sjdp     Elf_Internal_Sym *sym;
488933965Sjdp{
489033965Sjdp  bfd *dynobj = elf_hash_table(info)->dynobj;
489133965Sjdp
489260510Sobrien  if (h->plt.offset != MINUS_ONE)
489333965Sjdp    {
489433965Sjdp      /* Fill in the .plt entry for this symbol.  */
489533965Sjdp      asection *splt, *sgot, *srel;
489633965Sjdp      Elf_Internal_Rela outrel;
489733965Sjdp      bfd_vma got_addr, plt_addr;
489833965Sjdp      bfd_vma plt_index;
489933965Sjdp      struct alpha_elf_got_entry *gotent;
490033965Sjdp
490133965Sjdp      BFD_ASSERT (h->dynindx != -1);
490233965Sjdp
490333965Sjdp      /* The first .got entry will be updated by the .plt with the
490433965Sjdp	 address of the target function.  */
490533965Sjdp      gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
490633965Sjdp      BFD_ASSERT (gotent && gotent->addend == 0);
490733965Sjdp
490833965Sjdp      splt = bfd_get_section_by_name (dynobj, ".plt");
490933965Sjdp      BFD_ASSERT (splt != NULL);
491033965Sjdp      srel = bfd_get_section_by_name (dynobj, ".rela.plt");
491133965Sjdp      BFD_ASSERT (srel != NULL);
491233965Sjdp      sgot = alpha_elf_tdata (gotent->gotobj)->got;
491333965Sjdp      BFD_ASSERT (sgot != NULL);
491433965Sjdp
491533965Sjdp      got_addr = (sgot->output_section->vma
491633965Sjdp		  + sgot->output_offset
491733965Sjdp		  + gotent->got_offset);
491833965Sjdp      plt_addr = (splt->output_section->vma
491933965Sjdp		  + splt->output_offset
492060510Sobrien		  + h->plt.offset);
492133965Sjdp
492260510Sobrien      plt_index = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
492333965Sjdp
492433965Sjdp      /* Fill in the entry in the procedure linkage table.  */
492533965Sjdp      {
492689862Sobrien	bfd_vma insn1, insn2, insn3;
492733965Sjdp
492860510Sobrien	insn1 = PLT_ENTRY_WORD1 | ((-(h->plt.offset + 4) >> 2) & 0x1fffff);
492938889Sjdp	insn2 = PLT_ENTRY_WORD2;
493038889Sjdp	insn3 = PLT_ENTRY_WORD3;
493133965Sjdp
493260510Sobrien	bfd_put_32 (output_bfd, insn1, splt->contents + h->plt.offset);
493360510Sobrien	bfd_put_32 (output_bfd, insn2, splt->contents + h->plt.offset + 4);
493460510Sobrien	bfd_put_32 (output_bfd, insn3, splt->contents + h->plt.offset + 8);
493533965Sjdp      }
493633965Sjdp
493733965Sjdp      /* Fill in the entry in the .rela.plt section.  */
493833965Sjdp      outrel.r_offset = got_addr;
493933965Sjdp      outrel.r_info = ELF64_R_INFO(h->dynindx, R_ALPHA_JMP_SLOT);
494033965Sjdp      outrel.r_addend = 0;
494133965Sjdp
494233965Sjdp      bfd_elf64_swap_reloca_out (output_bfd, &outrel,
494333965Sjdp				 ((Elf64_External_Rela *)srel->contents
494433965Sjdp				  + plt_index));
494533965Sjdp
494633965Sjdp      if (!(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
494733965Sjdp	{
494833965Sjdp	  /* Mark the symbol as undefined, rather than as defined in the
494933965Sjdp	     .plt section.  Leave the value alone.  */
495033965Sjdp	  sym->st_shndx = SHN_UNDEF;
495133965Sjdp	}
495233965Sjdp
495333965Sjdp      /* Fill in the entries in the .got.  */
495433965Sjdp      bfd_put_64 (output_bfd, plt_addr, sgot->contents + gotent->got_offset);
495533965Sjdp
495633965Sjdp      /* Subsequent .got entries will continue to bounce through the .plt.  */
495748850Sdfr      if (gotent->next)
495833965Sjdp	{
495948850Sdfr	  srel = bfd_get_section_by_name (dynobj, ".rela.got");
496048850Sdfr	  BFD_ASSERT (! info->shared || srel != NULL);
496133965Sjdp
496248850Sdfr	  gotent = gotent->next;
496348850Sdfr	  do
496448850Sdfr	    {
496548850Sdfr	      sgot = alpha_elf_tdata(gotent->gotobj)->got;
496648850Sdfr	      BFD_ASSERT(sgot != NULL);
496748850Sdfr	      BFD_ASSERT(gotent->addend == 0);
496848850Sdfr
496948850Sdfr	      bfd_put_64 (output_bfd, plt_addr,
497048850Sdfr		          sgot->contents + gotent->got_offset);
497148850Sdfr
497248850Sdfr	      if (info->shared)
497348850Sdfr		{
497448850Sdfr		  outrel.r_offset = (sgot->output_section->vma
497548850Sdfr				     + sgot->output_offset
497648850Sdfr				     + gotent->got_offset);
497748850Sdfr		  outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE);
497889862Sobrien		  outrel.r_addend = plt_addr;
497948850Sdfr
498048850Sdfr		  bfd_elf64_swap_reloca_out (output_bfd, &outrel,
498148850Sdfr					     ((Elf64_External_Rela *)
498248850Sdfr					      srel->contents)
498348850Sdfr					     + srel->reloc_count++);
498477303Sobrien		  BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
498548850Sdfr			      <= srel->_cooked_size);
498648850Sdfr		}
498748850Sdfr
498848850Sdfr	      gotent = gotent->next;
498948850Sdfr	    }
499048850Sdfr          while (gotent != NULL);
499133965Sjdp	}
499233965Sjdp    }
499333965Sjdp  else if (alpha_elf_dynamic_symbol_p (h, info))
499433965Sjdp    {
499533965Sjdp      /* Fill in the dynamic relocations for this symbol's .got entries.  */
499633965Sjdp      asection *srel;
499733965Sjdp      Elf_Internal_Rela outrel;
499833965Sjdp      struct alpha_elf_got_entry *gotent;
499933965Sjdp
500033965Sjdp      srel = bfd_get_section_by_name (dynobj, ".rela.got");
500133965Sjdp      BFD_ASSERT (srel != NULL);
500233965Sjdp
500333965Sjdp      for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
500433965Sjdp	   gotent != NULL;
500533965Sjdp	   gotent = gotent->next)
500633965Sjdp	{
5007104841Sobrien	  asection *sgot;
5008104841Sobrien	  int r_type;
5009104841Sobrien
5010104841Sobrien	  if (gotent->use_count == 0)
5011104841Sobrien	    continue;
5012104841Sobrien
5013104841Sobrien	  sgot = alpha_elf_tdata (gotent->gotobj)->got;
501433965Sjdp	  outrel.r_offset = (sgot->output_section->vma
501533965Sjdp			     + sgot->output_offset
501633965Sjdp			     + gotent->got_offset);
5017104841Sobrien
5018104841Sobrien	  r_type = gotent->reloc_type;
5019104841Sobrien	  switch (r_type)
5020104841Sobrien	    {
5021104841Sobrien	    case R_ALPHA_LITERAL:
5022104841Sobrien	      r_type = R_ALPHA_GLOB_DAT;
5023104841Sobrien	      break;
5024104841Sobrien	    case R_ALPHA_TLSGD:
5025104841Sobrien	      r_type = R_ALPHA_DTPMOD64;
5026104841Sobrien	      break;
5027104841Sobrien	    case R_ALPHA_GOTDTPREL:
5028104841Sobrien	      r_type = R_ALPHA_DTPREL64;
5029104841Sobrien	      break;
5030104841Sobrien	    case R_ALPHA_GOTTPREL:
5031104841Sobrien	      r_type = R_ALPHA_TPREL64;
5032104841Sobrien	      break;
5033104841Sobrien	    case R_ALPHA_TLSLDM:
5034104841Sobrien	    default:
5035104841Sobrien	      abort ();
5036104841Sobrien	    }
5037104841Sobrien
5038104841Sobrien	  outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
503933965Sjdp	  outrel.r_addend = gotent->addend;
504033965Sjdp
504133965Sjdp	  bfd_elf64_swap_reloca_out (output_bfd, &outrel,
504233965Sjdp				     ((Elf64_External_Rela *)srel->contents
504333965Sjdp				      + srel->reloc_count++));
5044104841Sobrien
5045104841Sobrien	  if (gotent->reloc_type == R_ALPHA_TLSGD)
5046104841Sobrien	    {
5047104841Sobrien	      outrel.r_offset += 8;
5048104841Sobrien	      outrel.r_info = ELF64_R_INFO (h->dynindx, R_ALPHA_DTPREL64);
5049104841Sobrien
5050104841Sobrien	      bfd_elf64_swap_reloca_out (output_bfd, &outrel,
5051104841Sobrien				         ((Elf64_External_Rela *)srel->contents
5052104841Sobrien				          + srel->reloc_count++));
5053104841Sobrien	    }
5054104841Sobrien
505577303Sobrien	  BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
505648850Sdfr		      <= srel->_cooked_size);
505733965Sjdp	}
505833965Sjdp    }
505933965Sjdp
506033965Sjdp  /* Mark some specially defined symbols as absolute.  */
506133965Sjdp  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
506233965Sjdp      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
506333965Sjdp      || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
506433965Sjdp    sym->st_shndx = SHN_ABS;
506533965Sjdp
506633965Sjdp  return true;
506733965Sjdp}
506833965Sjdp
506933965Sjdp/* Finish up the dynamic sections.  */
507033965Sjdp
507133965Sjdpstatic boolean
507233965Sjdpelf64_alpha_finish_dynamic_sections (output_bfd, info)
507333965Sjdp     bfd *output_bfd;
507433965Sjdp     struct bfd_link_info *info;
507533965Sjdp{
507633965Sjdp  bfd *dynobj;
507733965Sjdp  asection *sdyn;
507833965Sjdp
507933965Sjdp  dynobj = elf_hash_table (info)->dynobj;
508033965Sjdp  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
508133965Sjdp
508233965Sjdp  if (elf_hash_table (info)->dynamic_sections_created)
508333965Sjdp    {
508433965Sjdp      asection *splt;
508533965Sjdp      Elf64_External_Dyn *dyncon, *dynconend;
508633965Sjdp
508733965Sjdp      splt = bfd_get_section_by_name (dynobj, ".plt");
508833965Sjdp      BFD_ASSERT (splt != NULL && sdyn != NULL);
508933965Sjdp
509033965Sjdp      dyncon = (Elf64_External_Dyn *) sdyn->contents;
509133965Sjdp      dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
509233965Sjdp      for (; dyncon < dynconend; dyncon++)
509333965Sjdp	{
509433965Sjdp	  Elf_Internal_Dyn dyn;
509533965Sjdp	  const char *name;
509633965Sjdp	  asection *s;
509733965Sjdp
509833965Sjdp	  bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn);
509933965Sjdp
510033965Sjdp	  switch (dyn.d_tag)
510133965Sjdp	    {
510233965Sjdp	    case DT_PLTGOT:
510333965Sjdp	      name = ".plt";
510433965Sjdp	      goto get_vma;
510533965Sjdp	    case DT_PLTRELSZ:
510633965Sjdp	      name = ".rela.plt";
510733965Sjdp	      goto get_size;
510833965Sjdp	    case DT_JMPREL:
510933965Sjdp	      name = ".rela.plt";
511033965Sjdp	      goto get_vma;
511133965Sjdp
511233965Sjdp	    case DT_RELASZ:
511333965Sjdp	      /* My interpretation of the TIS v1.1 ELF document indicates
511433965Sjdp		 that RELASZ should not include JMPREL.  This is not what
511533965Sjdp		 the rest of the BFD does.  It is, however, what the
511633965Sjdp		 glibc ld.so wants.  Do this fixup here until we found
511733965Sjdp		 out who is right.  */
511833965Sjdp	      s = bfd_get_section_by_name (output_bfd, ".rela.plt");
511933965Sjdp	      if (s)
512033965Sjdp		{
512133965Sjdp		  dyn.d_un.d_val -=
512233965Sjdp		    (s->_cooked_size ? s->_cooked_size : s->_raw_size);
512333965Sjdp		}
512433965Sjdp	      break;
512533965Sjdp
512633965Sjdp	    get_vma:
512733965Sjdp	      s = bfd_get_section_by_name (output_bfd, name);
512833965Sjdp	      dyn.d_un.d_ptr = (s ? s->vma : 0);
512933965Sjdp	      break;
513033965Sjdp
513133965Sjdp	    get_size:
513233965Sjdp	      s = bfd_get_section_by_name (output_bfd, name);
513333965Sjdp	      dyn.d_un.d_val =
513433965Sjdp		(s->_cooked_size ? s->_cooked_size : s->_raw_size);
513533965Sjdp	      break;
513633965Sjdp	    }
513733965Sjdp
513833965Sjdp	  bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
513933965Sjdp	}
514033965Sjdp
514133965Sjdp      /* Initialize the PLT0 entry */
514233965Sjdp      if (splt->_raw_size > 0)
514333965Sjdp	{
514433965Sjdp	  bfd_put_32 (output_bfd, PLT_HEADER_WORD1, splt->contents);
514533965Sjdp	  bfd_put_32 (output_bfd, PLT_HEADER_WORD2, splt->contents + 4);
514633965Sjdp	  bfd_put_32 (output_bfd, PLT_HEADER_WORD3, splt->contents + 8);
514733965Sjdp	  bfd_put_32 (output_bfd, PLT_HEADER_WORD4, splt->contents + 12);
514833965Sjdp
514933965Sjdp	  /* The next two words will be filled in by ld.so */
515089862Sobrien	  bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 16);
515189862Sobrien	  bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 24);
515233965Sjdp
515333965Sjdp	  elf_section_data (splt->output_section)->this_hdr.sh_entsize =
515433965Sjdp	    PLT_HEADER_SIZE;
515533965Sjdp	}
515633965Sjdp    }
515733965Sjdp
515833965Sjdp  return true;
515933965Sjdp}
516033965Sjdp
516189862Sobrien/* We need to use a special link routine to handle the .mdebug section.
516289862Sobrien   We need to merge all instances of these sections together, not write
516389862Sobrien   them all out sequentially.  */
516433965Sjdp
516533965Sjdpstatic boolean
516633965Sjdpelf64_alpha_final_link (abfd, info)
516733965Sjdp     bfd *abfd;
516833965Sjdp     struct bfd_link_info *info;
516933965Sjdp{
517033965Sjdp  asection *o;
517133965Sjdp  struct bfd_link_order *p;
517289862Sobrien  asection *mdebug_sec;
517333965Sjdp  struct ecoff_debug_info debug;
517433965Sjdp  const struct ecoff_debug_swap *swap
517533965Sjdp    = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
517633965Sjdp  HDRR *symhdr = &debug.symbolic_header;
517733965Sjdp  PTR mdebug_handle = NULL;
517833965Sjdp
517989862Sobrien  /* Go through the sections and collect the mdebug information.  */
518033965Sjdp  mdebug_sec = NULL;
518133965Sjdp  for (o = abfd->sections; o != (asection *) NULL; o = o->next)
518233965Sjdp    {
518333965Sjdp      if (strcmp (o->name, ".mdebug") == 0)
518433965Sjdp	{
518533965Sjdp	  struct extsym_info einfo;
518633965Sjdp
518733965Sjdp	  /* We have found the .mdebug section in the output file.
518833965Sjdp	     Look through all the link_orders comprising it and merge
518933965Sjdp	     the information together.  */
519033965Sjdp	  symhdr->magic = swap->sym_magic;
519133965Sjdp	  /* FIXME: What should the version stamp be?  */
519233965Sjdp	  symhdr->vstamp = 0;
519333965Sjdp	  symhdr->ilineMax = 0;
519433965Sjdp	  symhdr->cbLine = 0;
519533965Sjdp	  symhdr->idnMax = 0;
519633965Sjdp	  symhdr->ipdMax = 0;
519733965Sjdp	  symhdr->isymMax = 0;
519833965Sjdp	  symhdr->ioptMax = 0;
519933965Sjdp	  symhdr->iauxMax = 0;
520033965Sjdp	  symhdr->issMax = 0;
520133965Sjdp	  symhdr->issExtMax = 0;
520233965Sjdp	  symhdr->ifdMax = 0;
520333965Sjdp	  symhdr->crfd = 0;
520433965Sjdp	  symhdr->iextMax = 0;
520533965Sjdp
520633965Sjdp	  /* We accumulate the debugging information itself in the
520733965Sjdp	     debug_info structure.  */
520833965Sjdp	  debug.line = NULL;
520933965Sjdp	  debug.external_dnr = NULL;
521033965Sjdp	  debug.external_pdr = NULL;
521133965Sjdp	  debug.external_sym = NULL;
521233965Sjdp	  debug.external_opt = NULL;
521333965Sjdp	  debug.external_aux = NULL;
521433965Sjdp	  debug.ss = NULL;
521533965Sjdp	  debug.ssext = debug.ssext_end = NULL;
521633965Sjdp	  debug.external_fdr = NULL;
521733965Sjdp	  debug.external_rfd = NULL;
521833965Sjdp	  debug.external_ext = debug.external_ext_end = NULL;
521933965Sjdp
522033965Sjdp	  mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info);
522133965Sjdp	  if (mdebug_handle == (PTR) NULL)
522233965Sjdp	    return false;
522333965Sjdp
522433965Sjdp	  if (1)
522533965Sjdp	    {
522633965Sjdp	      asection *s;
522733965Sjdp	      EXTR esym;
522889862Sobrien	      bfd_vma last = 0;
522933965Sjdp	      unsigned int i;
523033965Sjdp	      static const char * const name[] =
523133965Sjdp		{
523233965Sjdp		  ".text", ".init", ".fini", ".data",
523333965Sjdp		  ".rodata", ".sdata", ".sbss", ".bss"
523433965Sjdp		};
523533965Sjdp	      static const int sc[] = { scText, scInit, scFini, scData,
523633965Sjdp					  scRData, scSData, scSBss, scBss };
523733965Sjdp
523833965Sjdp	      esym.jmptbl = 0;
523933965Sjdp	      esym.cobol_main = 0;
524033965Sjdp	      esym.weakext = 0;
524133965Sjdp	      esym.reserved = 0;
524233965Sjdp	      esym.ifd = ifdNil;
524333965Sjdp	      esym.asym.iss = issNil;
524433965Sjdp	      esym.asym.st = stLocal;
524533965Sjdp	      esym.asym.reserved = 0;
524633965Sjdp	      esym.asym.index = indexNil;
524733965Sjdp	      for (i = 0; i < 8; i++)
524833965Sjdp		{
524933965Sjdp		  esym.asym.sc = sc[i];
525033965Sjdp		  s = bfd_get_section_by_name (abfd, name[i]);
525133965Sjdp		  if (s != NULL)
525233965Sjdp		    {
525333965Sjdp		      esym.asym.value = s->vma;
525433965Sjdp		      last = s->vma + s->_raw_size;
525533965Sjdp		    }
525633965Sjdp		  else
525733965Sjdp		    esym.asym.value = last;
525833965Sjdp
525933965Sjdp		  if (! bfd_ecoff_debug_one_external (abfd, &debug, swap,
526033965Sjdp						      name[i], &esym))
526133965Sjdp		    return false;
526233965Sjdp		}
526333965Sjdp	    }
526433965Sjdp
526533965Sjdp	  for (p = o->link_order_head;
526633965Sjdp	       p != (struct bfd_link_order *) NULL;
526733965Sjdp	       p = p->next)
526833965Sjdp	    {
526933965Sjdp	      asection *input_section;
527033965Sjdp	      bfd *input_bfd;
527133965Sjdp	      const struct ecoff_debug_swap *input_swap;
527233965Sjdp	      struct ecoff_debug_info input_debug;
527333965Sjdp	      char *eraw_src;
527433965Sjdp	      char *eraw_end;
527533965Sjdp
527633965Sjdp	      if (p->type != bfd_indirect_link_order)
527733965Sjdp		{
5278104841Sobrien		  if (p->type == bfd_data_link_order)
527933965Sjdp		    continue;
528033965Sjdp		  abort ();
528133965Sjdp		}
528233965Sjdp
528333965Sjdp	      input_section = p->u.indirect.section;
528433965Sjdp	      input_bfd = input_section->owner;
528533965Sjdp
528633965Sjdp	      if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour
528733965Sjdp		  || (get_elf_backend_data (input_bfd)
528833965Sjdp		      ->elf_backend_ecoff_debug_swap) == NULL)
528933965Sjdp		{
529033965Sjdp		  /* I don't know what a non ALPHA ELF bfd would be
529133965Sjdp		     doing with a .mdebug section, but I don't really
529233965Sjdp		     want to deal with it.  */
529333965Sjdp		  continue;
529433965Sjdp		}
529533965Sjdp
529633965Sjdp	      input_swap = (get_elf_backend_data (input_bfd)
529733965Sjdp			    ->elf_backend_ecoff_debug_swap);
529833965Sjdp
529933965Sjdp	      BFD_ASSERT (p->size == input_section->_raw_size);
530033965Sjdp
530133965Sjdp	      /* The ECOFF linking code expects that we have already
530233965Sjdp		 read in the debugging information and set up an
530333965Sjdp		 ecoff_debug_info structure, so we do that now.  */
530433965Sjdp	      if (!elf64_alpha_read_ecoff_info (input_bfd, input_section,
530533965Sjdp						&input_debug))
530633965Sjdp		return false;
530733965Sjdp
530833965Sjdp	      if (! (bfd_ecoff_debug_accumulate
530933965Sjdp		     (mdebug_handle, abfd, &debug, swap, input_bfd,
531033965Sjdp		      &input_debug, input_swap, info)))
531133965Sjdp		return false;
531233965Sjdp
531333965Sjdp	      /* Loop through the external symbols.  For each one with
531433965Sjdp		 interesting information, try to find the symbol in
531533965Sjdp		 the linker global hash table and save the information
531633965Sjdp		 for the output external symbols.  */
531733965Sjdp	      eraw_src = input_debug.external_ext;
531833965Sjdp	      eraw_end = (eraw_src
531933965Sjdp			  + (input_debug.symbolic_header.iextMax
532033965Sjdp			     * input_swap->external_ext_size));
532133965Sjdp	      for (;
532233965Sjdp		   eraw_src < eraw_end;
532333965Sjdp		   eraw_src += input_swap->external_ext_size)
532433965Sjdp		{
532533965Sjdp		  EXTR ext;
532633965Sjdp		  const char *name;
532733965Sjdp		  struct alpha_elf_link_hash_entry *h;
532833965Sjdp
532933965Sjdp		  (*input_swap->swap_ext_in) (input_bfd, (PTR) eraw_src, &ext);
533033965Sjdp		  if (ext.asym.sc == scNil
533133965Sjdp		      || ext.asym.sc == scUndefined
533233965Sjdp		      || ext.asym.sc == scSUndefined)
533333965Sjdp		    continue;
533433965Sjdp
533533965Sjdp		  name = input_debug.ssext + ext.asym.iss;
533633965Sjdp		  h = alpha_elf_link_hash_lookup (alpha_elf_hash_table (info),
533733965Sjdp						  name, false, false, true);
533833965Sjdp		  if (h == NULL || h->esym.ifd != -2)
533933965Sjdp		    continue;
534033965Sjdp
534133965Sjdp		  if (ext.ifd != -1)
534233965Sjdp		    {
534333965Sjdp		      BFD_ASSERT (ext.ifd
534433965Sjdp				  < input_debug.symbolic_header.ifdMax);
534533965Sjdp		      ext.ifd = input_debug.ifdmap[ext.ifd];
534633965Sjdp		    }
534733965Sjdp
534833965Sjdp		  h->esym = ext;
534933965Sjdp		}
535033965Sjdp
535133965Sjdp	      /* Free up the information we just read.  */
535233965Sjdp	      free (input_debug.line);
535333965Sjdp	      free (input_debug.external_dnr);
535433965Sjdp	      free (input_debug.external_pdr);
535533965Sjdp	      free (input_debug.external_sym);
535633965Sjdp	      free (input_debug.external_opt);
535733965Sjdp	      free (input_debug.external_aux);
535833965Sjdp	      free (input_debug.ss);
535933965Sjdp	      free (input_debug.ssext);
536033965Sjdp	      free (input_debug.external_fdr);
536133965Sjdp	      free (input_debug.external_rfd);
536233965Sjdp	      free (input_debug.external_ext);
536333965Sjdp
536433965Sjdp	      /* Hack: reset the SEC_HAS_CONTENTS flag so that
536533965Sjdp		 elf_link_input_bfd ignores this section.  */
536633965Sjdp	      input_section->flags &=~ SEC_HAS_CONTENTS;
536733965Sjdp	    }
536833965Sjdp
536933965Sjdp	  /* Build the external symbol information.  */
537033965Sjdp	  einfo.abfd = abfd;
537133965Sjdp	  einfo.info = info;
537233965Sjdp	  einfo.debug = &debug;
537333965Sjdp	  einfo.swap = swap;
537433965Sjdp	  einfo.failed = false;
537533965Sjdp	  elf_link_hash_traverse (elf_hash_table (info),
537633965Sjdp				  elf64_alpha_output_extsym,
537733965Sjdp				  (PTR) &einfo);
537833965Sjdp	  if (einfo.failed)
537933965Sjdp	    return false;
538033965Sjdp
538133965Sjdp	  /* Set the size of the .mdebug section.  */
538233965Sjdp	  o->_raw_size = bfd_ecoff_debug_size (abfd, &debug, swap);
538333965Sjdp
538433965Sjdp	  /* Skip this section later on (I don't think this currently
538533965Sjdp	     matters, but someday it might).  */
538633965Sjdp	  o->link_order_head = (struct bfd_link_order *) NULL;
538733965Sjdp
538833965Sjdp	  mdebug_sec = o;
538933965Sjdp	}
539033965Sjdp    }
539133965Sjdp
539233965Sjdp  /* Invoke the regular ELF backend linker to do all the work.  */
539333965Sjdp  if (! bfd_elf64_bfd_final_link (abfd, info))
539433965Sjdp    return false;
539533965Sjdp
539633965Sjdp  /* Now write out the computed sections.  */
539733965Sjdp
539833965Sjdp  /* The .got subsections...  */
539933965Sjdp  {
540033965Sjdp    bfd *i, *dynobj = elf_hash_table(info)->dynobj;
540133965Sjdp    for (i = alpha_elf_hash_table(info)->got_list;
540233965Sjdp	 i != NULL;
540333965Sjdp	 i = alpha_elf_tdata(i)->got_link_next)
540433965Sjdp      {
540533965Sjdp	asection *sgot;
540633965Sjdp
540733965Sjdp	/* elf_bfd_final_link already did everything in dynobj.  */
540833965Sjdp	if (i == dynobj)
540933965Sjdp	  continue;
541033965Sjdp
541133965Sjdp	sgot = alpha_elf_tdata(i)->got;
541233965Sjdp	if (! bfd_set_section_contents (abfd, sgot->output_section,
541389862Sobrien					sgot->contents,
541489862Sobrien					(file_ptr) sgot->output_offset,
541533965Sjdp					sgot->_raw_size))
541633965Sjdp	  return false;
541733965Sjdp      }
541833965Sjdp  }
541933965Sjdp
542033965Sjdp  if (mdebug_sec != (asection *) NULL)
542133965Sjdp    {
542233965Sjdp      BFD_ASSERT (abfd->output_has_begun);
542333965Sjdp      if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug,
542433965Sjdp					       swap, info,
542533965Sjdp					       mdebug_sec->filepos))
542633965Sjdp	return false;
542733965Sjdp
542833965Sjdp      bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info);
542933965Sjdp    }
543033965Sjdp
543189862Sobrien  return true;
543289862Sobrien}
543333965Sjdp
543489862Sobrienstatic enum elf_reloc_type_class
543589862Sobrienelf64_alpha_reloc_type_class (rela)
543689862Sobrien     const Elf_Internal_Rela *rela;
543789862Sobrien{
543889862Sobrien  switch ((int) ELF64_R_TYPE (rela->r_info))
543933965Sjdp    {
544089862Sobrien    case R_ALPHA_RELATIVE:
544189862Sobrien      return reloc_class_relative;
544289862Sobrien    case R_ALPHA_JMP_SLOT:
544389862Sobrien      return reloc_class_plt;
544489862Sobrien    case R_ALPHA_COPY:
544589862Sobrien      return reloc_class_copy;
544689862Sobrien    default:
544789862Sobrien      return reloc_class_normal;
544833965Sjdp    }
544933965Sjdp}
545033965Sjdp
545133965Sjdp/* ECOFF swapping routines.  These are used when dealing with the
545233965Sjdp   .mdebug section, which is in the ECOFF debugging format.  Copied
545377303Sobrien   from elf32-mips.c.  */
545433965Sjdpstatic const struct ecoff_debug_swap
545533965Sjdpelf64_alpha_ecoff_debug_swap =
545633965Sjdp{
545733965Sjdp  /* Symbol table magic number.  */
545833965Sjdp  magicSym2,
545933965Sjdp  /* Alignment of debugging information.  E.g., 4.  */
546033965Sjdp  8,
546133965Sjdp  /* Sizes of external symbolic information.  */
546233965Sjdp  sizeof (struct hdr_ext),
546333965Sjdp  sizeof (struct dnr_ext),
546433965Sjdp  sizeof (struct pdr_ext),
546533965Sjdp  sizeof (struct sym_ext),
546633965Sjdp  sizeof (struct opt_ext),
546733965Sjdp  sizeof (struct fdr_ext),
546833965Sjdp  sizeof (struct rfd_ext),
546933965Sjdp  sizeof (struct ext_ext),
547033965Sjdp  /* Functions to swap in external symbolic data.  */
547133965Sjdp  ecoff_swap_hdr_in,
547233965Sjdp  ecoff_swap_dnr_in,
547333965Sjdp  ecoff_swap_pdr_in,
547433965Sjdp  ecoff_swap_sym_in,
547533965Sjdp  ecoff_swap_opt_in,
547633965Sjdp  ecoff_swap_fdr_in,
547733965Sjdp  ecoff_swap_rfd_in,
547833965Sjdp  ecoff_swap_ext_in,
547933965Sjdp  _bfd_ecoff_swap_tir_in,
548033965Sjdp  _bfd_ecoff_swap_rndx_in,
548133965Sjdp  /* Functions to swap out external symbolic data.  */
548233965Sjdp  ecoff_swap_hdr_out,
548333965Sjdp  ecoff_swap_dnr_out,
548433965Sjdp  ecoff_swap_pdr_out,
548533965Sjdp  ecoff_swap_sym_out,
548633965Sjdp  ecoff_swap_opt_out,
548733965Sjdp  ecoff_swap_fdr_out,
548833965Sjdp  ecoff_swap_rfd_out,
548933965Sjdp  ecoff_swap_ext_out,
549033965Sjdp  _bfd_ecoff_swap_tir_out,
549133965Sjdp  _bfd_ecoff_swap_rndx_out,
549233965Sjdp  /* Function to read in symbolic data.  */
549333965Sjdp  elf64_alpha_read_ecoff_info
549433965Sjdp};
549533965Sjdp
549677303Sobrien/* Use a non-standard hash bucket size of 8.  */
549777303Sobrien
5498104841Sobrienstatic const struct elf_size_info alpha_elf_size_info =
549977303Sobrien{
550077303Sobrien  sizeof (Elf64_External_Ehdr),
550177303Sobrien  sizeof (Elf64_External_Phdr),
550277303Sobrien  sizeof (Elf64_External_Shdr),
550377303Sobrien  sizeof (Elf64_External_Rel),
550477303Sobrien  sizeof (Elf64_External_Rela),
550577303Sobrien  sizeof (Elf64_External_Sym),
550677303Sobrien  sizeof (Elf64_External_Dyn),
550777303Sobrien  sizeof (Elf_External_Note),
550877303Sobrien  8,
550977303Sobrien  1,
551077303Sobrien  64, 8,
551177303Sobrien  ELFCLASS64, EV_CURRENT,
551277303Sobrien  bfd_elf64_write_out_phdrs,
551377303Sobrien  bfd_elf64_write_shdrs_and_ehdr,
551477303Sobrien  bfd_elf64_write_relocs,
5515104841Sobrien  bfd_elf64_swap_symbol_in,
551677303Sobrien  bfd_elf64_swap_symbol_out,
551777303Sobrien  bfd_elf64_slurp_reloc_table,
551877303Sobrien  bfd_elf64_slurp_symbol_table,
551977303Sobrien  bfd_elf64_swap_dyn_in,
552077303Sobrien  bfd_elf64_swap_dyn_out,
552177303Sobrien  NULL,
552277303Sobrien  NULL,
552377303Sobrien  NULL,
552477303Sobrien  NULL
552577303Sobrien};
552677303Sobrien
5527104841Sobrien#ifndef ELF_ARCH
552833965Sjdp#define TARGET_LITTLE_SYM	bfd_elf64_alpha_vec
552933965Sjdp#define TARGET_LITTLE_NAME	"elf64-alpha"
553033965Sjdp#define ELF_ARCH		bfd_arch_alpha
553178833Sobrien#define ELF_MACHINE_CODE	EM_ALPHA
553278833Sobrien#define ELF_MAXPAGESIZE	0x10000
5533104841Sobrien#endif /* ELF_ARCH */
553433965Sjdp
553533965Sjdp#define bfd_elf64_bfd_link_hash_table_create \
553633965Sjdp  elf64_alpha_bfd_link_hash_table_create
553733965Sjdp
553833965Sjdp#define bfd_elf64_bfd_reloc_type_lookup \
553933965Sjdp  elf64_alpha_bfd_reloc_type_lookup
554033965Sjdp#define elf_info_to_howto \
554133965Sjdp  elf64_alpha_info_to_howto
554233965Sjdp
554333965Sjdp#define bfd_elf64_mkobject \
554433965Sjdp  elf64_alpha_mkobject
554533965Sjdp#define elf_backend_object_p \
554633965Sjdp  elf64_alpha_object_p
554733965Sjdp
554833965Sjdp#define elf_backend_section_from_shdr \
554933965Sjdp  elf64_alpha_section_from_shdr
555089862Sobrien#define elf_backend_section_flags \
555189862Sobrien  elf64_alpha_section_flags
555233965Sjdp#define elf_backend_fake_sections \
555333965Sjdp  elf64_alpha_fake_sections
555433965Sjdp
555533965Sjdp#define bfd_elf64_bfd_is_local_label_name \
555633965Sjdp  elf64_alpha_is_local_label_name
555733965Sjdp#define bfd_elf64_find_nearest_line \
555833965Sjdp  elf64_alpha_find_nearest_line
555960510Sobrien#define bfd_elf64_bfd_relax_section \
556060510Sobrien  elf64_alpha_relax_section
556133965Sjdp
556260510Sobrien#define elf_backend_add_symbol_hook \
556360510Sobrien  elf64_alpha_add_symbol_hook
556433965Sjdp#define elf_backend_check_relocs \
556533965Sjdp  elf64_alpha_check_relocs
556633965Sjdp#define elf_backend_create_dynamic_sections \
556733965Sjdp  elf64_alpha_create_dynamic_sections
556833965Sjdp#define elf_backend_adjust_dynamic_symbol \
556933965Sjdp  elf64_alpha_adjust_dynamic_symbol
557033965Sjdp#define elf_backend_always_size_sections \
557133965Sjdp  elf64_alpha_always_size_sections
557233965Sjdp#define elf_backend_size_dynamic_sections \
557333965Sjdp  elf64_alpha_size_dynamic_sections
557433965Sjdp#define elf_backend_relocate_section \
557533965Sjdp  elf64_alpha_relocate_section
557633965Sjdp#define elf_backend_finish_dynamic_symbol \
557733965Sjdp  elf64_alpha_finish_dynamic_symbol
557833965Sjdp#define elf_backend_finish_dynamic_sections \
557933965Sjdp  elf64_alpha_finish_dynamic_sections
558033965Sjdp#define bfd_elf64_bfd_final_link \
558133965Sjdp  elf64_alpha_final_link
558289862Sobrien#define elf_backend_reloc_type_class \
558389862Sobrien  elf64_alpha_reloc_type_class
558433965Sjdp
558533965Sjdp#define elf_backend_ecoff_debug_swap \
558633965Sjdp  &elf64_alpha_ecoff_debug_swap
558733965Sjdp
558877303Sobrien#define elf_backend_size_info \
558977303Sobrien  alpha_elf_size_info
559077303Sobrien
559177303Sobrien/* A few constants that determine how the .plt section is set up.  */
559233965Sjdp#define elf_backend_want_got_plt 0
559333965Sjdp#define elf_backend_plt_readonly 0
559433965Sjdp#define elf_backend_want_plt_sym 1
559560510Sobrien#define elf_backend_got_header_size 0
559660510Sobrien#define elf_backend_plt_header_size PLT_HEADER_SIZE
559733965Sjdp
559833965Sjdp#include "elf64-target.h"
5599