Range of element index is too large on MIPS MSA element selection instructions.
[platform/upstream/binutils.git] / bfd / elf64-alpha.c
index efda753..3dbdab7 100644 (file)
@@ -1,13 +1,14 @@
 /* Alpha specific support for 64-bit ELF
    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-   2006, 2007 Free Software Foundation, Inc.
+   2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
+   Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@tamu.edu>.
 
    This file is part of BFD, the Binary File Descriptor library.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
 
 /* We need a published ABI spec for this.  Until one comes out, don't
    assume this'll remain unchanged forever.  */
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 
@@ -101,6 +104,57 @@ bfd_boolean elf64_alpha_use_secureplt = FALSE;
 
 #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so"
 \f
+
+/* Used to implement multiple .got subsections.  */
+struct alpha_elf_got_entry
+{
+  struct alpha_elf_got_entry *next;
+
+  /* Which .got subsection?  */
+  bfd *gotobj;
+
+  /* The addend in effect for this entry.  */
+  bfd_vma addend;
+
+  /* The .got offset for this entry.  */
+  int got_offset;
+
+  /* The .plt offset for this entry.  */
+  int plt_offset;
+
+  /* How many references to this entry?  */
+  int use_count;
+
+  /* The relocation type of this entry.  */
+  unsigned char reloc_type;
+
+  /* How a LITERAL is used.  */
+  unsigned char flags;
+
+  /* Have we initialized the dynamic relocation for this entry?  */
+  unsigned char reloc_done;
+
+  /* Have we adjusted this entry for SEC_MERGE?  */
+  unsigned char reloc_xlated;
+};
+
+struct alpha_elf_reloc_entry
+{
+  struct alpha_elf_reloc_entry *next;
+
+  /* Which .reloc section? */
+  asection *srel;
+
+  /* What kind of relocation? */
+  unsigned int rtype;
+
+  /* Is this against read-only section? */
+  unsigned int reltext : 1;
+
+  /* How many did we find?  */
+  unsigned long count;
+};
+
 struct alpha_elf_link_hash_entry
 {
   struct elf_link_hash_entry root;
@@ -123,56 +177,11 @@ struct alpha_elf_link_hash_entry
 #define ALPHA_ELF_LINK_HASH_TLS_IE      0x80
 
   /* Used to implement multiple .got subsections.  */
-  struct alpha_elf_got_entry
-  {
-    struct alpha_elf_got_entry *next;
-
-    /* Which .got subsection?  */
-    bfd *gotobj;
-
-    /* The addend in effect for this entry.  */
-    bfd_vma addend;
-
-    /* The .got offset for this entry.  */
-    int got_offset;
-
-    /* The .plt offset for this entry.  */
-    int plt_offset;
-
-    /* How many references to this entry?  */
-    int use_count;
-
-    /* The relocation type of this entry.  */
-    unsigned char reloc_type;
-
-    /* How a LITERAL is used.  */
-    unsigned char flags;
-
-    /* Have we initialized the dynamic relocation for this entry?  */
-    unsigned char reloc_done;
-
-    /* Have we adjusted this entry for SEC_MERGE?  */
-    unsigned char reloc_xlated;
-  } *got_entries;
+  struct alpha_elf_got_entry *got_entries;
 
   /* Used to count non-got, non-plt relocations for delayed sizing
      of relocation sections.  */
-  struct alpha_elf_reloc_entry
-  {
-    struct alpha_elf_reloc_entry *next;
-
-    /* Which .reloc section? */
-    asection *srel;
-
-    /* What kind of relocation? */
-    unsigned int rtype;
-
-    /* Is this against read-only section? */
-    unsigned int reltext : 1;
-
-    /* How many did we find?  */
-    unsigned long count;
-  } *reloc_entries;
+  struct alpha_elf_reloc_entry *reloc_entries;
 };
 
 /* Alpha ELF linker hash table.  */
@@ -184,6 +193,10 @@ struct alpha_elf_link_hash_table
   /* The head of a list of .got subsections linked through
      alpha_elf_tdata(abfd)->got_link_next.  */
   bfd *got_list;
+
+  /* The most recent relax pass that we've seen.  The GOTs
+     should be regenerated if this doesn't match.  */
+  int relax_trip;
 };
 
 /* Look up an entry in a Alpha ELF linker hash table.  */
@@ -198,20 +211,21 @@ struct alpha_elf_link_hash_table
 #define alpha_elf_link_hash_traverse(table, func, info)                        \
   (elf_link_hash_traverse                                              \
    (&(table)->root,                                                    \
-    (bfd_boolean (*) (struct elf_link_hash_entry *, PTR)) (func),      \
+    (bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func),   \
     (info)))
 
 /* Get the Alpha ELF linker hash table from a link_info structure.  */
 
 #define alpha_elf_hash_table(p) \
-  ((struct alpha_elf_link_hash_table *) ((p)->hash))
+  (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
+  == ALPHA_ELF_DATA ? ((struct alpha_elf_link_hash_table *) ((p)->hash)) : NULL)
 
 /* Get the object's symbols as our own entry type.  */
 
 #define alpha_elf_sym_hashes(abfd) \
   ((struct alpha_elf_link_hash_entry **)elf_sym_hashes(abfd))
 
-/* Should we do dynamic things to this symbol?  This differs from the 
+/* Should we do dynamic things to this symbol?  This differs from the
    generic version in that we never need to consider function pointer
    equality wrt PLT entries -- we don't create a PLT entry if a symbol's
    address is ever taken.  */
@@ -275,7 +289,8 @@ elf64_alpha_bfd_link_hash_table_create (bfd *abfd)
 
   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
                                      elf64_alpha_link_hash_newfunc,
-                                     sizeof (struct alpha_elf_link_hash_entry)))
+                                     sizeof (struct alpha_elf_link_hash_entry),
+                                     ALPHA_ELF_DATA))
     {
       free (ret);
       return NULL;
@@ -284,6 +299,15 @@ elf64_alpha_bfd_link_hash_table_create (bfd *abfd)
   return &ret->root.root;
 }
 \f
+/* Alpha ELF follows MIPS ELF in using a special find_nearest_line
+   routine in order to handle the ECOFF debugging information.  */
+
+struct alpha_elf_find_line
+{
+  struct ecoff_debug_info d;
+  struct ecoff_find_line i;
+};
+
 /* We have some private fields hanging off of the elf_tdata structure.  */
 
 struct alpha_elf_obj_tdata
@@ -313,22 +337,25 @@ struct alpha_elf_obj_tdata
   /* For every got, this is the sum of the number of words required
      to hold all of the member object's local got.  */
   int local_got_size;
+
+  /* Used by elf64_alpha_find_nearest_line entry point.  */
+  struct alpha_elf_find_line *find_line_info;
+
 };
 
 #define alpha_elf_tdata(abfd) \
   ((struct alpha_elf_obj_tdata *) (abfd)->tdata.any)
 
+#define is_alpha_elf(bfd) \
+  (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
+   && elf_tdata (bfd) != NULL \
+   && elf_object_id (bfd) == ALPHA_ELF_DATA)
+
 static bfd_boolean
 elf64_alpha_mkobject (bfd *abfd)
 {
-  if (abfd->tdata.any == NULL)
-    {
-      bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata);
-      abfd->tdata.any = bfd_zalloc (abfd, amt);
-      if (abfd->tdata.any == NULL)
-       return FALSE;
-    }
-  return bfd_elf_mkobject (abfd);
+  return bfd_elf_allocate_object (abfd, sizeof (struct alpha_elf_obj_tdata),
+                                 ALPHA_ELF_DATA);
 }
 
 static bfd_boolean
@@ -343,7 +370,7 @@ elf64_alpha_object_p (bfd *abfd)
 static bfd_reloc_status_type
 elf64_alpha_reloc_nil (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc,
                       asymbol *sym ATTRIBUTE_UNUSED,
-                      PTR data ATTRIBUTE_UNUSED, asection *sec,
+                      void * data ATTRIBUTE_UNUSED, asection *sec,
                       bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED)
 {
   if (output_bfd)
@@ -356,7 +383,7 @@ elf64_alpha_reloc_nil (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc,
 static bfd_reloc_status_type
 elf64_alpha_reloc_bad (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc,
                       asymbol *sym ATTRIBUTE_UNUSED,
-                      PTR data ATTRIBUTE_UNUSED, asection *sec,
+                      void * data ATTRIBUTE_UNUSED, asection *sec,
                       bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED)
 {
   if (output_bfd)
@@ -408,7 +435,7 @@ elf64_alpha_do_reloc_gpdisp (bfd *abfd, bfd_vma gpdisp, bfd_byte *p_ldah,
 
 static bfd_reloc_status_type
 elf64_alpha_reloc_gpdisp (bfd *abfd, arelent *reloc_entry,
-                         asymbol *sym ATTRIBUTE_UNUSED, PTR data,
+                         asymbol *sym ATTRIBUTE_UNUSED, void * data,
                          asection *input_section, bfd *output_bfd,
                          char **err_msg)
 {
@@ -453,8 +480,9 @@ elf64_alpha_reloc_gpdisp (bfd *abfd, arelent *reloc_entry,
    from smaller values.  Start with zero, widen, *then* decrement.  */
 #define MINUS_ONE      (((bfd_vma)0) - 1)
 
+
 #define SKIP_HOWTO(N) \
-  HOWTO(N, 0, 0, 0, 0, 0, 0, elf64_alpha_reloc_bad, 0, 0, 0, 0, 0)
+  HOWTO(N, 0, 0, 0, 0, 0, complain_overflow_dont, elf64_alpha_reloc_bad, 0, 0, 0, 0, 0)
 
 static reloc_howto_type elf64_alpha_howto_table[] =
 {
@@ -480,7 +508,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "REFLONG",             /* name */
         FALSE,                 /* partial_inplace */
         0xffffffff,            /* src_mask */
@@ -495,7 +523,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "REFQUAD",             /* name */
         FALSE,                 /* partial_inplace */
         MINUS_ONE,             /* src_mask */
@@ -512,7 +540,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "GPREL32",             /* name */
         FALSE,                 /* partial_inplace */
         0xffffffff,            /* src_mask */
@@ -527,7 +555,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "ELF_LITERAL",         /* name */
         FALSE,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -593,7 +621,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "BRADDR",              /* name */
         FALSE,                 /* partial_inplace */
         0x1fffff,              /* src_mask */
@@ -608,7 +636,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "HINT",                /* name */
         FALSE,                 /* partial_inplace */
         0x3fff,                /* src_mask */
@@ -623,7 +651,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "SREL16",              /* name */
         FALSE,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -638,7 +666,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "SREL32",              /* name */
         FALSE,                 /* partial_inplace */
         0xffffffff,            /* src_mask */
@@ -653,7 +681,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "SREL64",              /* name */
         FALSE,                 /* partial_inplace */
         MINUS_ONE,             /* src_mask */
@@ -675,7 +703,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "GPRELHIGH",           /* name */
         FALSE,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -690,7 +718,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "GPRELLOW",            /* name */
         FALSE,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -705,7 +733,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "GPREL16",             /* name */
         FALSE,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -791,7 +819,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "BRSGP",               /* name */
         FALSE,                 /* partial_inplace */
         0x1fffff,              /* src_mask */
@@ -806,7 +834,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "TLSGD",               /* name */
         FALSE,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -821,7 +849,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "TLSLDM",              /* name */
         FALSE,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -836,7 +864,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "DTPMOD64",            /* name */
         FALSE,                 /* partial_inplace */
         MINUS_ONE,             /* src_mask */
@@ -852,7 +880,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "GOTDTPREL",           /* name */
         FALSE,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -867,7 +895,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "DTPREL64",            /* name */
         FALSE,                 /* partial_inplace */
         MINUS_ONE,             /* src_mask */
@@ -882,7 +910,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "DTPRELHI",            /* name */
         FALSE,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -897,7 +925,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "DTPRELLO",            /* name */
         FALSE,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -912,7 +940,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "DTPREL16",            /* name */
         FALSE,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -928,7 +956,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "GOTTPREL",            /* name */
         FALSE,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -943,7 +971,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "TPREL64",             /* name */
         FALSE,                 /* partial_inplace */
         MINUS_ONE,             /* src_mask */
@@ -958,7 +986,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "TPRELHI",             /* name */
         FALSE,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -973,7 +1001,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "TPRELLO",             /* name */
         FALSE,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -988,7 +1016,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        0,                     /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "TPREL16",             /* name */
         FALSE,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -1055,6 +1083,23 @@ elf64_alpha_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   return 0;
 }
 
+static reloc_howto_type *
+elf64_alpha_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                                  const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0;
+       i < (sizeof (elf64_alpha_howto_table)
+           / sizeof (elf64_alpha_howto_table[0]));
+       i++)
+    if (elf64_alpha_howto_table[i].name != NULL
+       && strcasecmp (elf64_alpha_howto_table[i].name, r_name) == 0)
+      return &elf64_alpha_howto_table[i];
+
+  return NULL;
+}
+
 /* Given an Alpha ELF reloc type, fill in an arelent structure.  */
 
 static void
@@ -1211,6 +1256,9 @@ elf64_alpha_create_got_section (bfd *abfd,
   flagword flags;
   asection *s;
 
+  if (! is_alpha_elf (abfd))
+    return FALSE;
+
   flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
           | SEC_LINKER_CREATED);
   s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
@@ -1237,6 +1285,9 @@ elf64_alpha_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   flagword flags;
   struct elf_link_hash_entry *h;
 
+  if (! is_alpha_elf (abfd))
+    return FALSE;
+
   /* We need to create .plt, .rela.plt, .got, and .rela.got sections.  */
 
   flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_IN_MEMORY
@@ -1339,17 +1390,17 @@ elf64_alpha_read_ecoff_info (bfd *abfd, asection *section,
     }
 
   READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
-  READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR);
-  READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR);
-  READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR);
-  READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR);
+  READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *);
+  READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, void *);
+  READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, void *);
+  READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, void *);
   READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
        union aux_ext *);
   READ (ss, cbSsOffset, issMax, sizeof (char), char *);
   READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *);
-  READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR);
-  READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR);
-  READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, PTR);
+  READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, void *);
+  READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, void *);
+  READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, void *);
 #undef READ
 
   debug->fdr = NULL;
@@ -1392,17 +1443,6 @@ elf64_alpha_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, const char *name)
   return name[0] == '$';
 }
 
-/* Alpha ELF follows MIPS ELF in using a special find_nearest_line
-   routine in order to handle the ECOFF debugging information.  We
-   still call this mips_elf_find_line because of the slot
-   find_line_info in elf_obj_tdata is declared that way.  */
-
-struct mips_elf_find_line
-{
-  struct ecoff_debug_info d;
-  struct ecoff_find_line i;
-};
-
 static bfd_boolean
 elf64_alpha_find_nearest_line (bfd *abfd, asection *section, asymbol **symbols,
                               bfd_vma offset, const char **filename_ptr,
@@ -1411,9 +1451,10 @@ elf64_alpha_find_nearest_line (bfd *abfd, asection *section, asymbol **symbols,
 {
   asection *msec;
 
-  if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
+  if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections,
+                                     section, symbols, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr, 0,
+                                    line_ptr, NULL, 0,
                                     &elf_tdata (abfd)->dwarf2_find_line_info))
     return TRUE;
 
@@ -1421,7 +1462,7 @@ elf64_alpha_find_nearest_line (bfd *abfd, asection *section, asymbol **symbols,
   if (msec != NULL)
     {
       flagword origflags;
-      struct mips_elf_find_line *fi;
+      struct alpha_elf_find_line *fi;
       const struct ecoff_debug_swap * const swap =
        get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
 
@@ -1432,16 +1473,16 @@ elf64_alpha_find_nearest_line (bfd *abfd, asection *section, asymbol **symbols,
       if (elf_section_data (msec)->this_hdr.sh_type != SHT_NOBITS)
        msec->flags |= SEC_HAS_CONTENTS;
 
-      fi = elf_tdata (abfd)->find_line_info;
+      fi = alpha_elf_tdata (abfd)->find_line_info;
       if (fi == NULL)
        {
          bfd_size_type external_fdr_size;
          char *fraw_src;
          char *fraw_end;
          struct fdr *fdr_ptr;
-         bfd_size_type amt = sizeof (struct mips_elf_find_line);
+         bfd_size_type amt = sizeof (struct alpha_elf_find_line);
 
-         fi = (struct mips_elf_find_line *) bfd_zalloc (abfd, amt);
+         fi = (struct alpha_elf_find_line *) bfd_zalloc (abfd, amt);
          if (fi == NULL)
            {
              msec->flags = origflags;
@@ -1468,9 +1509,9 @@ elf64_alpha_find_nearest_line (bfd *abfd, asection *section, asymbol **symbols,
          fraw_end = (fraw_src
                      + fi->d.symbolic_header.ifdMax * external_fdr_size);
          for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
-           (*swap->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr);
+           (*swap->swap_fdr_in) (abfd, fraw_src, fdr_ptr);
 
-         elf_tdata (abfd)->find_line_info = fi;
+         alpha_elf_tdata (abfd)->find_line_info = fi;
 
          /* Note that we don't bother to ever free this information.
              find_nearest_line is either called all the time, as in
@@ -1510,15 +1551,12 @@ struct extsym_info
 };
 
 static bfd_boolean
-elf64_alpha_output_extsym (struct alpha_elf_link_hash_entry *h, PTR data)
+elf64_alpha_output_extsym (struct alpha_elf_link_hash_entry *h, void * data)
 {
   struct extsym_info *einfo = (struct extsym_info *) data;
   bfd_boolean strip;
   asection *sec, *output_section;
 
-  if (h->root.root.type == bfd_link_hash_warning)
-    h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
-
   if (h->root.indx == -2)
     strip = FALSE;
   else if ((h->root.def_dynamic
@@ -1720,7 +1758,6 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
 {
   bfd *dynobj;
   asection *sreloc;
-  const char *rel_sec_name;
   Elf_Internal_Shdr *symtab_hdr;
   struct alpha_elf_link_hash_entry **sym_hashes;
   const Elf_Internal_Rela *rel, *relend;
@@ -1738,14 +1775,15 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
   if ((sec->flags & SEC_ALLOC) == 0)
     return TRUE;
 
-  dynobj = elf_hash_table(info)->dynobj;
+  BFD_ASSERT (is_alpha_elf (abfd));
+
+  dynobj = elf_hash_table (info)->dynobj;
   if (dynobj == NULL)
-    elf_hash_table(info)->dynobj = dynobj = abfd;
+    elf_hash_table (info)->dynobj = dynobj = abfd;
 
   sreloc = NULL;
-  rel_sec_name = NULL;
-  symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
-  sym_hashes = alpha_elf_sym_hashes(abfd);
+  symtab_hdr = &elf_symtab_hdr (abfd);
+  sym_hashes = alpha_elf_sym_hashes (abfd);
 
   relend = relocs + sec->reloc_count;
   for (rel = relocs; rel < relend; ++rel)
@@ -1774,6 +1812,9 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
                 || h->root.root.type == bfd_link_hash_warning)
            h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
 
+         /* PR15323, ref flags aren't set for references in the same
+            object.  */
+         h->root.root.non_ir_ref = 1;
          h->root.ref_regular = 1;
        }
 
@@ -1829,8 +1870,8 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
        case R_ALPHA_TLSLDM:
          /* The symbol for a TLSLDM reloc is ignored.  Collapse the
-            reloc to the 0 symbol so that they all match.  */
-         r_symndx = 0;
+            reloc to the STN_UNDEF (0) symbol so that they all match.  */
+         r_symndx = STN_UNDEF;
          h = 0;
          maybe_dynamic = FALSE;
          /* FALLTHRU */
@@ -1848,10 +1889,13 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
          break;
 
        case R_ALPHA_TPREL64:
-         if (info->shared || maybe_dynamic)
+         if (info->shared && !info->pie)
+           {
+             info->flags |= DF_STATIC_TLS;
+             need = NEED_DYNREL;
+           }
+         else if (maybe_dynamic)
            need = NEED_DYNREL;
-         if (info->shared)
-           info->flags |= DF_STATIC_TLS;
          break;
        }
 
@@ -1893,41 +1937,16 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
       if (need & NEED_DYNREL)
        {
-         if (rel_sec_name == NULL)
-           {
-             rel_sec_name = (bfd_elf_string_from_elf_section
-                             (abfd, elf_elfheader(abfd)->e_shstrndx,
-                              elf_section_data(sec)->rel_hdr.sh_name));
-             if (rel_sec_name == NULL)
-               return FALSE;
-
-             BFD_ASSERT (CONST_STRNEQ (rel_sec_name, ".rela")
-                         && strcmp (bfd_get_section_name (abfd, sec),
-                                    rel_sec_name+5) == 0);
-           }
-
          /* We need to create the section here now whether we eventually
             use it or not so that it gets mapped to an output section by
-            the linker.  If not used, we'll kill it in
-            size_dynamic_sections.  */
+            the linker.  If not used, we'll kill it in size_dynamic_sections.  */
          if (sreloc == NULL)
            {
-             sreloc = bfd_get_section_by_name (dynobj, rel_sec_name);
+             sreloc = _bfd_elf_make_dynamic_reloc_section
+               (sec, dynobj, 3, abfd, /*rela?*/ TRUE);
+
              if (sreloc == NULL)
-               {
-                 flagword flags;
-
-                 flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY
-                          | SEC_LINKER_CREATED | SEC_READONLY);
-                 if (sec->flags & SEC_ALLOC)
-                   flags |= SEC_ALLOC | SEC_LOAD;
-                 sreloc = bfd_make_section_with_flags (dynobj,
-                                                       rel_sec_name,
-                                                       flags);
-                 if (sreloc == NULL
-                     || !bfd_set_section_alignment (dynobj, sreloc, 3))
-                   return FALSE;
-               }
+               return FALSE;
            }
 
          if (h)
@@ -1976,6 +1995,93 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
   return TRUE;
 }
 
+/* Return the section that should be marked against GC for a given
+   relocation.  */
+
+static asection *
+elf64_alpha_gc_mark_hook (asection *sec, struct bfd_link_info *info,
+                         Elf_Internal_Rela *rel,
+                         struct elf_link_hash_entry *h, Elf_Internal_Sym *sym)
+{
+  /* These relocations don't really reference a symbol.  Instead we store
+     extra data in their addend slot.  Ignore the symbol.  */
+  switch (ELF64_R_TYPE (rel->r_info))
+    {
+    case R_ALPHA_LITUSE:
+    case R_ALPHA_GPDISP:
+    case R_ALPHA_HINT:
+      return NULL;
+    }
+
+  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
+}
+
+/* Update the got entry reference counts for the section being removed.  */
+
+static bfd_boolean
+elf64_alpha_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
+                          asection *sec, const Elf_Internal_Rela *relocs)
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  struct alpha_elf_link_hash_entry **sym_hashes;
+  const Elf_Internal_Rela *rel, *relend;
+
+  if (info->relocatable)
+    return TRUE;
+
+  symtab_hdr = &elf_symtab_hdr (abfd);
+  sym_hashes = alpha_elf_sym_hashes (abfd);
+
+  relend = relocs + sec->reloc_count;
+  for (rel = relocs; rel < relend; rel++)
+    {
+      unsigned long r_symndx, r_type;
+      struct alpha_elf_link_hash_entry *h = NULL;
+      struct alpha_elf_got_entry *gotent;
+
+      r_symndx = ELF64_R_SYM (rel->r_info);
+      if (r_symndx >= symtab_hdr->sh_info)
+       {
+         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+         while (h->root.root.type == bfd_link_hash_indirect
+                || h->root.root.type == bfd_link_hash_warning)
+           h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
+       }
+
+      r_type = ELF64_R_TYPE (rel->r_info);
+      switch (r_type)
+       {
+       case R_ALPHA_LITERAL:
+         /* ??? Ignore re-computation of gotent_flags.  We're not
+            carrying a use-count for each bit in that mask.  */
+
+       case R_ALPHA_TLSGD:
+       case R_ALPHA_GOTDTPREL:
+       case R_ALPHA_GOTTPREL:
+         /* Fetch the got entry from the tables.  */
+         gotent = get_got_entry (abfd, h, r_type, r_symndx, rel->r_addend);
+
+         /* The got entry *must* exist, since we should have created it
+            before during check_relocs.  Also note that get_got_entry
+            assumed this was going to be another use, and so incremented
+            the use count again.  Thus the use count must be at least the
+            one real use and the "use" we just added.  */
+         if (gotent == NULL || gotent->use_count < 2)
+           {
+             abort ();
+             return FALSE;
+           }
+         gotent->use_count -= 2;
+         break;
+
+       default:
+         break;
+       }
+    }
+
+  return TRUE;
+}
+
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
@@ -2002,7 +2108,7 @@ elf64_alpha_adjust_dynamic_symbol (struct bfd_link_info *info,
     {
       h->needs_plt = TRUE;
 
-      s = bfd_get_section_by_name(dynobj, ".plt");
+      s = bfd_get_linker_section (dynobj, ".plt");
       if (!s && !elf64_alpha_create_dynamic_sections (dynobj, info))
        return FALSE;
 
@@ -2052,23 +2158,29 @@ elf64_alpha_merge_symbol_attribute (struct elf_link_hash_entry *h,
    indirect to the new ones.  Consolidate the got and reloc information
    in these situations.  */
 
-static bfd_boolean
-elf64_alpha_merge_ind_symbols (struct alpha_elf_link_hash_entry *hi,
-                              PTR dummy ATTRIBUTE_UNUSED)
+static void
+elf64_alpha_copy_indirect_symbol (struct bfd_link_info *info,
+                                 struct elf_link_hash_entry *dir,
+                                 struct elf_link_hash_entry *ind)
 {
-  struct alpha_elf_link_hash_entry *hs;
+  struct alpha_elf_link_hash_entry *hi
+    = (struct alpha_elf_link_hash_entry *) ind;
+  struct alpha_elf_link_hash_entry *hs
+    = (struct alpha_elf_link_hash_entry *) dir;
 
-  if (hi->root.root.type != bfd_link_hash_indirect)
-    return TRUE;
-  hs = hi;
-  do {
-    hs = (struct alpha_elf_link_hash_entry *)hs->root.root.u.i.link;
-  } while (hs->root.root.type == bfd_link_hash_indirect);
+  /* Do the merging in the superclass.  */
+  _bfd_elf_link_hash_copy_indirect(info, dir, ind);
 
   /* Merge the flags.  Whee.  */
-
   hs->flags |= hi->flags;
 
+  /* ??? It's unclear to me what's really supposed to happen when
+     "merging" defweak and defined symbols, given that we don't
+     actually throw away the defweak.  This more-or-less copies
+     the logic related to got and plt entries in the superclass.  */
+  if (ind->root.type != bfd_link_hash_indirect)
+    return;
+
   /* Merge the .got entries.  Cannibalize the old symbol's list in
      doing so, since we don't need it anymore.  */
 
@@ -2121,8 +2233,6 @@ elf64_alpha_merge_ind_symbols (struct alpha_elf_link_hash_entry *hi,
        }
     }
   hi->reloc_entries = NULL;
-
-  return TRUE;
 }
 
 /* Is it possible to merge two object file's .got tables?  */
@@ -2287,13 +2397,10 @@ elf64_alpha_merge_gots (bfd *a, bfd *b)
 
 static bfd_boolean
 elf64_alpha_calc_got_offsets_for_symbol (struct alpha_elf_link_hash_entry *h,
-                                        PTR arg ATTRIBUTE_UNUSED)
+                                        void * arg ATTRIBUTE_UNUSED)
 {
   struct alpha_elf_got_entry *gotent;
 
-  if (h->root.root.type == bfd_link_hash_warning)
-    h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
-
   for (gotent = h->got_entries; gotent; gotent = gotent->next)
     if (gotent->use_count > 0)
       {
@@ -2312,7 +2419,13 @@ elf64_alpha_calc_got_offsets_for_symbol (struct alpha_elf_link_hash_entry *h,
 static void
 elf64_alpha_calc_got_offsets (struct bfd_link_info *info)
 {
-  bfd *i, *got_list = alpha_elf_hash_table(info)->got_list;
+  bfd *i, *got_list;
+  struct alpha_elf_link_hash_table * htab;
+
+  htab = alpha_elf_hash_table (info);
+  if (htab == NULL)
+    return;
+  got_list = htab->got_list;
 
   /* First, zero out the .got sizes, as we may be recalculating the
      .got after optimizing it.  */
@@ -2320,7 +2433,7 @@ elf64_alpha_calc_got_offsets (struct bfd_link_info *info)
     alpha_elf_tdata(i)->got->size = 0;
 
   /* Next, fill in the offsets for all the global entries.  */
-  alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
+  alpha_elf_link_hash_traverse (htab,
                                elf64_alpha_calc_got_offsets_for_symbol,
                                NULL);
 
@@ -2358,9 +2471,12 @@ static bfd_boolean
 elf64_alpha_size_got_sections (struct bfd_link_info *info)
 {
   bfd *i, *got_list, *cur_got_obj = NULL;
-  int something_changed = 0;
+  struct alpha_elf_link_hash_table * htab;
 
-  got_list = alpha_elf_hash_table (info)->got_list;
+  htab = alpha_elf_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+  got_list = htab->got_list;
 
   /* On the first time through, pretend we have an existing got list
      consisting of all of the input files.  */
@@ -2368,7 +2484,12 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info)
     {
       for (i = info->input_bfds; i ; i = i->link_next)
        {
-         bfd *this_got = alpha_elf_tdata (i)->gotobj;
+         bfd *this_got;
+
+         if (! is_alpha_elf (i))
+           continue;
+
+         this_got = alpha_elf_tdata (i)->gotobj;
          if (this_got == NULL)
            continue;
 
@@ -2395,13 +2516,13 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info)
       if (got_list == NULL)
        return TRUE;
 
-      alpha_elf_hash_table (info)->got_list = got_list;
-
-      /* Force got offsets to be recalculated.  */
-      something_changed = 1;
+      htab->got_list = got_list;
     }
 
   cur_got_obj = got_list;
+  if (cur_got_obj == NULL)
+    return FALSE;
+
   i = alpha_elf_tdata(cur_got_obj)->got_link_next;
   while (i != NULL)
     {
@@ -2412,8 +2533,6 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info)
          alpha_elf_tdata(i)->got->size = 0;
          i = alpha_elf_tdata(i)->got_link_next;
          alpha_elf_tdata(cur_got_obj)->got_link_next = i;
-         
-         something_changed = 1;
        }
       else
        {
@@ -2424,14 +2543,14 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info)
 
   /* Once the gots have been merged, fill in the got offsets for
      everything therein.  */
-  if (1 || something_changed)
-    elf64_alpha_calc_got_offsets (info);
+  elf64_alpha_calc_got_offsets (info);
 
   return TRUE;
 }
 
 static bfd_boolean
-elf64_alpha_size_plt_section_1 (struct alpha_elf_link_hash_entry *h, PTR data)
+elf64_alpha_size_plt_section_1 (struct alpha_elf_link_hash_entry *h,
+                               void * data)
 {
   asection *splt = (asection *) data;
   struct alpha_elf_got_entry *gotent;
@@ -2460,28 +2579,34 @@ elf64_alpha_size_plt_section_1 (struct alpha_elf_link_hash_entry *h, PTR data)
   return TRUE;
 }
 
-/* Called from relax_section to rebuild the PLT in light of
-   potential changes in the function's status.  */
+/* Called from relax_section to rebuild the PLT in light of potential changes
+   in the function's status.  */
 
-static bfd_boolean
+static void
 elf64_alpha_size_plt_section (struct bfd_link_info *info)
 {
   asection *splt, *spltrel, *sgotplt;
   unsigned long entries;
   bfd *dynobj;
+  struct alpha_elf_link_hash_table * htab;
+
+  htab = alpha_elf_hash_table (info);
+  if (htab == NULL)
+    return;
 
   dynobj = elf_hash_table(info)->dynobj;
-  splt = bfd_get_section_by_name (dynobj, ".plt");
+  splt = bfd_get_linker_section (dynobj, ".plt");
   if (splt == NULL)
-    return TRUE;
+    return;
 
   splt->size = 0;
 
-  alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
+  alpha_elf_link_hash_traverse (htab,
                                elf64_alpha_size_plt_section_1, splt);
 
   /* Every plt entry requires a JMP_SLOT relocation.  */
-  spltrel = bfd_get_section_by_name (dynobj, ".rela.plt");
+  spltrel = bfd_get_linker_section (dynobj, ".rela.plt");
+  entries = 0;
   if (splt->size)
     {
       if (elf64_alpha_use_secureplt)
@@ -2489,8 +2614,6 @@ elf64_alpha_size_plt_section (struct bfd_link_info *info)
       else
        entries = (splt->size - OLD_PLT_HEADER_SIZE) / OLD_PLT_ENTRY_SIZE;
     }
-  else
-    entries = 0;
   spltrel->size = entries * sizeof (Elf64_External_Rela);
 
   /* When using the secureplt, we need two words somewhere in the data
@@ -2498,11 +2621,9 @@ elf64_alpha_size_plt_section (struct bfd_link_info *info)
      entire contents of the .got.plt section.  */
   if (elf64_alpha_use_secureplt)
     {
-      sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
+      sgotplt = bfd_get_linker_section (dynobj, ".got.plt");
       sgotplt->size = entries ? 16 : 0;
     }
-
-  return TRUE;
 }
 
 static bfd_boolean
@@ -2510,20 +2631,20 @@ elf64_alpha_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
                                  struct bfd_link_info *info)
 {
   bfd *i;
+  struct alpha_elf_link_hash_table * htab;
 
   if (info->relocatable)
     return TRUE;
 
-  /* First, take care of the indirect symbols created by versioning.  */
-  alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
-                               elf64_alpha_merge_ind_symbols,
-                               NULL);
+  htab = alpha_elf_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
 
   if (!elf64_alpha_size_got_sections (info))
     return FALSE;
 
   /* Allocate space for all of the .got subsections.  */
-  i = alpha_elf_hash_table (info)->got_list;
+  i = htab->got_list;
   for ( ; i ; i = alpha_elf_tdata(i)->got_link_next)
     {
       asection *s = alpha_elf_tdata(i)->got;
@@ -2541,7 +2662,7 @@ elf64_alpha_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 /* The number of dynamic relocations required by a static relocation.  */
 
 static int
-alpha_dynamic_entries_for_reloc (int r_type, int dynamic, int shared)
+alpha_dynamic_entries_for_reloc (int r_type, int dynamic, int shared, int pie)
 {
   switch (r_type)
     {
@@ -2551,16 +2672,18 @@ alpha_dynamic_entries_for_reloc (int r_type, int dynamic, int shared)
     case R_ALPHA_TLSLDM:
       return shared;
     case R_ALPHA_LITERAL:
-    case R_ALPHA_GOTTPREL:
       return dynamic || shared;
+    case R_ALPHA_GOTTPREL:
+      return dynamic || (shared && !pie);
     case R_ALPHA_GOTDTPREL:
       return dynamic;
 
     /* May appear in data sections.  */
     case R_ALPHA_REFLONG:
     case R_ALPHA_REFQUAD:
-    case R_ALPHA_TPREL64:
       return dynamic || shared;
+    case R_ALPHA_TPREL64:
+      return dynamic || (shared && !pie);
 
     /* Everything else is illegal.  We'll issue an error during
        relocate_section.  */
@@ -2579,9 +2702,6 @@ elf64_alpha_calc_dynrel_sizes (struct alpha_elf_link_hash_entry *h,
   struct alpha_elf_reloc_entry *relent;
   unsigned long entries;
 
-  if (h->root.root.type == bfd_link_hash_warning)
-    h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
-
   /* If the symbol was defined as a common symbol in a regular object
      file, and there was no definition in any dynamic object, then the
      linker will have allocated space for the symbol in a common
@@ -2611,7 +2731,7 @@ elf64_alpha_calc_dynrel_sizes (struct alpha_elf_link_hash_entry *h,
   for (relent = h->reloc_entries; relent; relent = relent->next)
     {
       entries = alpha_dynamic_entries_for_reloc (relent->rtype, dynamic,
-                                                info->shared);
+                                                info->shared, info->pie);
       if (entries)
        {
          relent->srel->size +=
@@ -2635,9 +2755,6 @@ elf64_alpha_size_rela_got_1 (struct alpha_elf_link_hash_entry *h,
   struct alpha_elf_got_entry *gotent;
   unsigned long entries;
 
-  if (h->root.root.type == bfd_link_hash_warning)
-    h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
-
   /* If we're using a plt for this symbol, then all of its relocations
      for its got entries go into .rela.plt.  */
   if (h->root.needs_plt)
@@ -2657,13 +2774,13 @@ elf64_alpha_size_rela_got_1 (struct alpha_elf_link_hash_entry *h,
   entries = 0;
   for (gotent = h->got_entries; gotent ; gotent = gotent->next)
     if (gotent->use_count > 0)
-      entries += alpha_dynamic_entries_for_reloc (gotent->reloc_type,
-                                                 dynamic, info->shared);
+      entries += alpha_dynamic_entries_for_reloc (gotent->reloc_type, dynamic,
+                                                 info->shared, info->pie);
 
   if (entries > 0)
     {
       bfd *dynobj = elf_hash_table(info)->dynobj;
-      asection *srel = bfd_get_section_by_name (dynobj, ".rela.got");
+      asection *srel = bfd_get_linker_section (dynobj, ".rela.got");
       BFD_ASSERT (srel != NULL);
       srel->size += sizeof (Elf64_External_Rela) * entries;
     }
@@ -2673,18 +2790,23 @@ elf64_alpha_size_rela_got_1 (struct alpha_elf_link_hash_entry *h,
 
 /* Set the sizes of the dynamic relocation sections.  */
 
-static bfd_boolean
+static void
 elf64_alpha_size_rela_got_section (struct bfd_link_info *info)
 {
   unsigned long entries;
   bfd *i, *dynobj;
   asection *srel;
+  struct alpha_elf_link_hash_table * htab;
+
+  htab = alpha_elf_hash_table (info);
+  if (htab == NULL)
+    return;
 
   /* Shared libraries often require RELATIVE relocs, and some relocs
      require attention for the main application as well.  */
 
   entries = 0;
-  for (i = alpha_elf_hash_table(info)->got_list;
+  for (i = htab->got_list;
        i ; i = alpha_elf_tdata(i)->got_link_next)
     {
       bfd *j;
@@ -2703,24 +2825,22 @@ elf64_alpha_size_rela_got_section (struct bfd_link_info *info)
                 gotent ; gotent = gotent->next)
              if (gotent->use_count > 0)
                entries += (alpha_dynamic_entries_for_reloc
-                           (gotent->reloc_type, 0, info->shared));
+                           (gotent->reloc_type, 0, info->shared, info->pie));
        }
     }
 
   dynobj = elf_hash_table(info)->dynobj;
-  srel = bfd_get_section_by_name (dynobj, ".rela.got");
+  srel = bfd_get_linker_section (dynobj, ".rela.got");
   if (!srel)
     {
       BFD_ASSERT (entries == 0);
-      return TRUE;
+      return;
     }
   srel->size = sizeof (Elf64_External_Rela) * entries;
 
   /* Now do the non-local symbols.  */
-  alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
+  alpha_elf_link_hash_traverse (htab,
                                elf64_alpha_size_rela_got_1, info);
-
-  return TRUE;
 }
 
 /* Set the sizes of the dynamic sections.  */
@@ -2732,6 +2852,11 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   bfd *dynobj;
   asection *s;
   bfd_boolean relplt;
+  struct alpha_elf_link_hash_table * htab;
+
+  htab = alpha_elf_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
 
   dynobj = elf_hash_table(info)->dynobj;
   BFD_ASSERT(dynobj != NULL);
@@ -2741,7 +2866,7 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       /* Set the contents of the .interp section to the interpreter.  */
       if (info->executable)
        {
-         s = bfd_get_section_by_name (dynobj, ".interp");
+         s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
          s->size = sizeof ELF_DYNAMIC_INTERPRETER;
          s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
@@ -2751,7 +2876,7 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         symbols need dynamic relocation entries and which don't.  We've
         collected information in check_relocs that we can now apply to
         size the dynamic relocation sections.  */
-      alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
+      alpha_elf_link_hash_traverse (htab,
                                    elf64_alpha_calc_dynrel_sizes, info);
 
       elf64_alpha_size_rela_got_section (info);
@@ -2803,7 +2928,8 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
             linker does that before adjust_dynamic_symbol is called, and
             it is that function which decides whether anything needs to
             go into these sections.  */
-         s->flags |= SEC_EXCLUDE;
+         if (!CONST_STRNEQ (name, ".got"))
+           s->flags |= SEC_EXCLUDE;
        }
       else if ((s->flags & SEC_HAS_CONTENTS) != 0)
        {
@@ -2931,7 +3057,8 @@ elf64_alpha_relax_got_load (struct alpha_relax_info *info, bfd_vma symval,
     return TRUE;
 
   /* Can't use local-exec relocations in shared libraries.  */
-  if (r_type == R_ALPHA_GOTTPREL && info->link_info->shared)
+  if (r_type == R_ALPHA_GOTTPREL
+      && (info->link_info->shared && !info->link_info->pie))
     return TRUE;
 
   if (r_type == R_ALPHA_LITERAL)
@@ -3049,7 +3176,7 @@ elf64_alpha_relax_opt_call (struct alpha_relax_info *info, bfd_vma symval)
       else
        {
          tsec_relocs = (_bfd_elf_link_read_relocs
-                        (info->abfd, info->tsec, (PTR) NULL,
+                        (info->abfd, info->tsec, NULL,
                         (Elf_Internal_Rela *) NULL,
                         info->link_info->keep_memory));
          if (tsec_relocs == NULL)
@@ -3078,7 +3205,7 @@ elf64_alpha_relax_opt_call (struct alpha_relax_info *info, bfd_vma symval)
 
   /* We've now determined that we can skip an initial gp load.  Verify
      that the call and the target use the same gp.   */
-  if (info->link_info->hash->creator != info->tsec->owner->xvec
+  if (info->link_info->output_bfd->xvec != info->tsec->owner->xvec
       || info->gotobj != alpha_elf_tdata (info->tsec->owner)->gotobj)
     return 0;
 
@@ -3345,9 +3472,9 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval,
                                Elf_Internal_Rela *irel, bfd_boolean is_gd)
 {
   bfd_byte *pos[5];
-  unsigned int insn;
+  unsigned int insn, tlsgd_reg;
   Elf_Internal_Rela *gpdisp, *hint;
-  bfd_boolean dynamic, use_gottprel, pos1_unusable;
+  bfd_boolean dynamic, use_gottprel;
   unsigned long new_symndx;
 
   dynamic = alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info);
@@ -3388,7 +3515,13 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval,
   pos[2] = info->contents + irel[2].r_offset;
   pos[3] = info->contents + gpdisp->r_offset;
   pos[4] = pos[3] + gpdisp->r_addend;
-  pos1_unusable = FALSE;
+
+  /* Beware of the compiler hoisting part of the sequence out a loop
+     and adjusting the destination register for the TLSGD insn.  If this
+     happens, there will be a move into $16 before the JSR insn, so only
+     transformations of the first insn pair should use this register.  */
+  tlsgd_reg = bfd_get_32 (info->abfd, pos[0]);
+  tlsgd_reg = (tlsgd_reg >> 21) & 31;
 
   /* Generally, the positions are not allowed to be out of order, lest the
      modified insn sequence have different register lifetimes.  We can make
@@ -3399,8 +3532,6 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval,
       pos[0] = pos[1];
       pos[1] = tmp;
     }
-  else if (pos[1] < pos[0])
-    pos1_unusable = TRUE;
   if (pos[1] >= pos[2] || pos[2] >= pos[3])
     return TRUE;
 
@@ -3457,8 +3588,11 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval,
      as appropriate.  */
 
   use_gottprel = FALSE;
-  new_symndx = is_gd ? ELF64_R_SYM (irel->r_info) : 0;
-  switch (!dynamic && !info->link_info->shared)
+  new_symndx = is_gd ? ELF64_R_SYM (irel->r_info) : STN_UNDEF;
+
+  /* Some compilers warn about a Boolean-looking expression being
+     used in a switch.  The explicit cast silences them.  */
+  switch ((int) (!dynamic && !info->link_info->shared))
     {
     case 1:
       {
@@ -3471,7 +3605,7 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval,
 
        if (disp >= -0x8000 && disp < 0x8000)
          {
-           insn = (OP_LDA << 26) | (16 << 21) | (31 << 16);
+           insn = (OP_LDA << 26) | (tlsgd_reg << 21) | (31 << 16);
            bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]);
            bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]);
 
@@ -3482,11 +3616,11 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval,
          }
        else if (disp >= -(bfd_signed_vma) 0x80000000
                 && disp < (bfd_signed_vma) 0x7fff8000
-                && !pos1_unusable)
+                && pos[0] + 4 == pos[1])
          {
-           insn = (OP_LDAH << 26) | (16 << 21) | (31 << 16);
+           insn = (OP_LDAH << 26) | (tlsgd_reg << 21) | (31 << 16);
            bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]);
-           insn = (OP_LDA << 26) | (16 << 21) | (16 << 16);
+           insn = (OP_LDA << 26) | (tlsgd_reg << 21) | (tlsgd_reg << 16);
            bfd_put_32 (info->abfd, (bfd_vma) insn, pos[1]);
 
            irel[0].r_offset = pos[0] - info->contents;
@@ -3501,7 +3635,7 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval,
     default:
       use_gottprel = TRUE;
 
-      insn = (OP_LDQ << 26) | (16 << 21) | (29 << 16);
+      insn = (OP_LDQ << 26) | (tlsgd_reg << 21) | (29 << 16);
       bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]);
       bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]);
 
@@ -3591,8 +3725,13 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
   Elf_Internal_Sym *isymbuf = NULL;
   struct alpha_elf_got_entry **local_got_entries;
   struct alpha_relax_info info;
+  struct alpha_elf_link_hash_table * htab;
 
-  /* We are not currently changing any sizes, so only one pass.  */
+  htab = alpha_elf_hash_table (link_info);
+  if (htab == NULL)
+    return FALSE;
+
+  /* There's nothing to change, yet.  */
   *again = FALSE;
 
   if (link_info->relocatable
@@ -3601,12 +3740,30 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
       || sec->reloc_count == 0)
     return TRUE;
 
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  BFD_ASSERT (is_alpha_elf (abfd));
+
+  /* Make sure our GOT and PLT tables are up-to-date.  */
+  if (htab->relax_trip != link_info->relax_trip)
+    {
+      htab->relax_trip = link_info->relax_trip;
+
+      /* This should never fail after the initial round, since the only
+        error is GOT overflow, and relaxation only shrinks the table.  */
+      if (!elf64_alpha_size_got_sections (link_info))
+       abort ();
+      if (elf_hash_table (link_info)->dynamic_sections_created)
+       {
+         elf64_alpha_size_plt_section (link_info);
+         elf64_alpha_size_rela_got_section (link_info);
+       }
+    }
+
+  symtab_hdr = &elf_symtab_hdr (abfd);
   local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
 
   /* Load the relocations for this section.  */
   internal_relocs = (_bfd_elf_link_read_relocs
-                    (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
+                    (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
                      link_info->keep_memory));
   if (internal_relocs == NULL)
     return FALSE;
@@ -3659,8 +3816,8 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
 
        case R_ALPHA_TLSLDM:
          /* The symbol for a TLSLDM reloc is ignored.  Collapse the
-             reloc to the 0 symbol so that they all match.  */
-         r_symndx = 0;
+             reloc to the STN_UNDEF (0) symbol so that they all match.  */
+         r_symndx = STN_UNDEF;
          break;
 
        default:
@@ -3810,13 +3967,6 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
        }
     }
 
-  if (!elf64_alpha_size_plt_section (link_info))
-    return FALSE;
-  if (!elf64_alpha_size_got_sections (link_info))
-    return FALSE;
-  if (!elf64_alpha_size_rela_got_section (link_info))
-    return FALSE;
-
   if (isymbuf != NULL
       && symtab_hdr->contents != (unsigned char *) isymbuf)
     {
@@ -3915,7 +4065,7 @@ elf64_alpha_relocate_section_r (bfd *output_bfd ATTRIBUTE_UNUSED,
   struct elf_link_hash_entry **sym_hashes;
   bfd_boolean ret_val = TRUE;
 
-  symtab_hdr_sh_info = elf_tdata (input_bfd)->symtab_hdr.sh_info;
+  symtab_hdr_sh_info = elf_symtab_hdr (input_bfd).sh_info;
   sym_hashes = elf_sym_hashes (input_bfd);
 
   relend = relocs + input_section->reloc_count;
@@ -3966,17 +4116,11 @@ elf64_alpha_relocate_section_r (bfd *output_bfd ATTRIBUTE_UNUSED,
          sec = h->root.u.def.section;
        }
 
-      if (sec != NULL && elf_discarded_section (sec))
-       {
-         /* For relocs against symbols from removed linkonce sections,
-            or sections discarded by a linker script, we just want the
-            section contents zeroed.  */
-         _bfd_clear_contents (elf64_alpha_howto_table + r_type,
-                              input_bfd, contents + rel->r_offset);
-         rel->r_info = 0;
-         rel->r_addend = 0;
-         continue;
-       }
+      if (sec != NULL && discarded_section (sec))
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                        rel, 1, relend,
+                                        elf64_alpha_howto_table + r_type, 0,
+                                        contents);
 
       if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
        rel->r_addend += sec->output_offset;
@@ -4003,6 +4147,8 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
   struct alpha_elf_got_entry **local_got_entries;
   bfd_boolean ret_val;
 
+  BFD_ASSERT (is_alpha_elf (input_bfd));
+
   /* Handle relocatable links with a smaller loop.  */
   if (info->relocatable)
     return elf64_alpha_relocate_section_r (output_bfd, info, input_bfd,
@@ -4013,11 +4159,11 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
   ret_val = TRUE;
 
-  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+  symtab_hdr = &elf_symtab_hdr (input_bfd);
 
   dynobj = elf_hash_table (info)->dynobj;
   if (dynobj)
-    srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+    srelgot = bfd_get_linker_section (dynobj, ".rela.got");
   else
     srelgot = NULL;
 
@@ -4026,9 +4172,9 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
       const char *section_name;
       section_name = (bfd_elf_string_from_elf_section
                      (input_bfd, elf_elfheader(input_bfd)->e_shstrndx,
-                      elf_section_data(input_section)->rel_hdr.sh_name));
+                      _bfd_elf_single_rel_hdr (input_section)->sh_name));
       BFD_ASSERT(section_name != NULL);
-      srel = bfd_get_section_by_name (dynobj, section_name);
+      srel = bfd_get_linker_section (dynobj, section_name);
     }
   else
     srel = NULL;
@@ -4076,6 +4222,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
       bfd_vma value;
       bfd_vma addend;
       bfd_boolean dynamic_symbol_p;
+      bfd_boolean unresolved_reloc = FALSE;
       bfd_boolean undef_weak_ref = FALSE;
       unsigned long r_type;
 
@@ -4094,9 +4241,9 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
       r_symndx = ELF64_R_SYM(rel->r_info);
 
       /* The symbol for a TLSLDM reloc is ignored.  Collapse the
-        reloc to the 0 symbol so that they all match.  */
+        reloc to the STN_UNDEF (0) symbol so that they all match.  */
       if (r_type == R_ALPHA_TLSLDM)
-       r_symndx = 0;
+       r_symndx = STN_UNDEF;
 
       if (r_symndx < symtab_hdr->sh_info)
        {
@@ -4106,10 +4253,10 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
          msec = sec;
          value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel);
 
-         /* If this is a tp-relative relocation against sym 0,
+         /* If this is a tp-relative relocation against sym STN_UNDEF (0),
             this is hackery from relax_section.  Force the value to
             be the tls module base.  */
-         if (r_symndx == 0
+         if (r_symndx == STN_UNDEF
              && (r_type == R_ALPHA_TLSLDM
                  || r_type == R_ALPHA_GOTTPREL
                  || r_type == R_ALPHA_TPREL64
@@ -4127,7 +4274,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
             unless it has been done already.  */
          if ((sec->flags & SEC_MERGE)
              && ELF_ST_TYPE (sym->st_info) == STT_SECTION
-             && sec->sec_info_type == ELF_INFO_TYPE_MERGE
+             && sec->sec_info_type == SEC_INFO_TYPE_MERGE
              && gotent
              && !gotent->reloc_xlated)
            {
@@ -4156,15 +4303,14 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        }
       else
        {
-         bfd_boolean warned;
-         bfd_boolean unresolved_reloc;
+         bfd_boolean warned, ignored;
          struct elf_link_hash_entry *hh;
          struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
 
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
                                   r_symndx, symtab_hdr, sym_hashes,
                                   hh, sec, value,
-                                  unresolved_reloc, warned);
+                                  unresolved_reloc, warned, ignored);
 
          if (warned)
            continue;
@@ -4179,16 +4325,9 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
          gotent = h->got_entries;
        }
 
-      if (sec != NULL && elf_discarded_section (sec))
-       {
-         /* For relocs against symbols from removed linkonce sections,
-            or sections discarded by a linker script, we just want the
-            section contents zeroed.  Avoid any special processing.  */
-         _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
-         rel->r_info = 0;
-         rel->r_addend = 0;
-         continue;
-       }
+      if (sec != NULL && discarded_section (sec))
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                        rel, 1, relend, howto, 0, contents);
 
       addend = rel->r_addend;
       value += addend;
@@ -4386,7 +4525,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
            else if (r_type == R_ALPHA_TPREL64)
              {
                BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
-               if (!info->shared)
+               if (!info->shared || info->pie)
                  {
                    value -= tp_base;
                    goto default_reloc;
@@ -4395,9 +4534,14 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                dynaddend = value - dtp_base;
              }
            else if (info->shared
-                    && r_symndx != 0
+                    && r_symndx != STN_UNDEF
                     && (input_section->flags & SEC_ALLOC)
-                    && !undef_weak_ref)
+                    && !undef_weak_ref
+                    && !(unresolved_reloc
+                         && (_bfd_elf_section_offset (output_bfd, info,
+                                                      input_section,
+                                                      rel->r_offset)
+                             == (bfd_vma) -1)))
              {
                if (r_type == R_ALPHA_REFLONG)
                  {
@@ -4443,7 +4587,11 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
          /* ??? .eh_frame references to discarded sections will be smashed
             to relocations against SHN_UNDEF.  The .eh_frame format allows
             NULL to be encoded as 0 in any format, so this works here.  */
-         if (r_symndx == 0)
+         if (r_symndx == STN_UNDEF
+             || (unresolved_reloc
+                 && _bfd_elf_section_offset (output_bfd, info,
+                                             input_section,
+                                             rel->r_offset) == (bfd_vma) -1))
            howto = (elf64_alpha_howto_table
                     + (r_type - R_ALPHA_SREL32 + R_ALPHA_REFLONG));
          goto default_reloc;
@@ -4507,7 +4655,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        case R_ALPHA_TPRELHI:
        case R_ALPHA_TPRELLO:
        case R_ALPHA_TPREL16:
-         if (info->shared)
+         if (info->shared && !info->pie)
            {
              (*_bfd_error_handler)
                (_("%B: TLS local exec code cannot be linked into shared objects"),
@@ -4588,7 +4736,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
            if (r_symndx < symtab_hdr->sh_info
                && sec != NULL && howto->pc_relative
-               && elf_discarded_section (sec))
+               && discarded_section (sec))
              break;
 
            if (h != NULL)
@@ -4642,9 +4790,9 @@ elf64_alpha_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info,
 
       BFD_ASSERT (h->dynindx != -1);
 
-      splt = bfd_get_section_by_name (dynobj, ".plt");
+      splt = bfd_get_linker_section (dynobj, ".plt");
       BFD_ASSERT (splt != NULL);
-      srel = bfd_get_section_by_name (dynobj, ".rela.plt");
+      srel = bfd_get_linker_section (dynobj, ".rela.plt");
       BFD_ASSERT (srel != NULL);
 
       for (gotent = ah->got_entries; gotent ; gotent = gotent->next)
@@ -4714,7 +4862,7 @@ elf64_alpha_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info,
       asection *srel;
       struct alpha_elf_got_entry *gotent;
 
-      srel = bfd_get_section_by_name (dynobj, ".rela.got");
+      srel = bfd_get_linker_section (dynobj, ".rela.got");
       BFD_ASSERT (srel != NULL);
 
       for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
@@ -4749,19 +4897,19 @@ elf64_alpha_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info,
              abort ();
            }
 
-         elf64_alpha_emit_dynrel (output_bfd, info, sgot, srel, 
+         elf64_alpha_emit_dynrel (output_bfd, info, sgot, srel,
                                   gotent->got_offset, h->dynindx,
                                   r_type, gotent->addend);
 
          if (gotent->reloc_type == R_ALPHA_TLSGD)
-           elf64_alpha_emit_dynrel (output_bfd, info, sgot, srel, 
+           elf64_alpha_emit_dynrel (output_bfd, info, sgot, srel,
                                     gotent->got_offset + 8, h->dynindx,
                                     R_ALPHA_DTPREL64, gotent->addend);
        }
     }
 
   /* Mark some specially defined symbols as absolute.  */
-  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
+  if (h == elf_hash_table (info)->hdynamic
       || h == elf_hash_table (info)->hgot
       || h == elf_hash_table (info)->hplt)
     sym->st_shndx = SHN_ABS;
@@ -4779,7 +4927,7 @@ elf64_alpha_finish_dynamic_sections (bfd *output_bfd,
   asection *sdyn;
 
   dynobj = elf_hash_table (info)->dynobj;
-  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
 
   if (elf_hash_table (info)->dynamic_sections_created)
     {
@@ -4787,8 +4935,8 @@ elf64_alpha_finish_dynamic_sections (bfd *output_bfd,
       Elf64_External_Dyn *dyncon, *dynconend;
       bfd_vma plt_vma, gotplt_vma;
 
-      splt = bfd_get_section_by_name (dynobj, ".plt");
-      srelaplt = bfd_get_section_by_name (output_bfd, ".rela.plt");
+      splt = bfd_get_linker_section (dynobj, ".plt");
+      srelaplt = bfd_get_linker_section (output_bfd, ".rela.plt");
       BFD_ASSERT (splt != NULL && sdyn != NULL);
 
       plt_vma = splt->output_section->vma + splt->output_offset;
@@ -4796,7 +4944,7 @@ elf64_alpha_finish_dynamic_sections (bfd *output_bfd,
       gotplt_vma = 0;
       if (elf64_alpha_use_secureplt)
        {
-         sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
+         sgotplt = bfd_get_linker_section (dynobj, ".got.plt");
          BFD_ASSERT (sgotplt != NULL);
          if (sgotplt->size > 0)
            gotplt_vma = sgotplt->output_section->vma + sgotplt->output_offset;
@@ -4914,7 +5062,12 @@ elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info)
   const struct ecoff_debug_swap *swap
     = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
   HDRR *symhdr = &debug.symbolic_header;
-  PTR mdebug_handle = NULL;
+  void * mdebug_handle = NULL;
+  struct alpha_elf_link_hash_table * htab;
+
+  htab = alpha_elf_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
 
   /* Go through the sections and collect the mdebug information.  */
   mdebug_sec = NULL;
@@ -4958,7 +5111,7 @@ elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info)
          debug.external_ext = debug.external_ext_end = NULL;
 
          mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info);
-         if (mdebug_handle == (PTR) NULL)
+         if (mdebug_handle == NULL)
            return FALSE;
 
          if (1)
@@ -5023,15 +5176,11 @@ elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info)
              input_section = p->u.indirect.section;
              input_bfd = input_section->owner;
 
-             if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour
-                 || (get_elf_backend_data (input_bfd)
-                     ->elf_backend_ecoff_debug_swap) == NULL)
-               {
-                 /* I don't know what a non ALPHA ELF bfd would be
-                    doing with a .mdebug section, but I don't really
-                    want to deal with it.  */
-                 continue;
-               }
+             if (! is_alpha_elf (input_bfd))
+               /* I don't know what a non ALPHA ELF bfd would be
+                  doing with a .mdebug section, but I don't really
+                  want to deal with it.  */
+               continue;
 
              input_swap = (get_elf_backend_data (input_bfd)
                            ->elf_backend_ecoff_debug_swap);
@@ -5054,7 +5203,7 @@ elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info)
                 interesting information, try to find the symbol in
                 the linker global hash table and save the information
                 for the output external symbols.  */
-             eraw_src = input_debug.external_ext;
+             eraw_src = (char *) input_debug.external_ext;
              eraw_end = (eraw_src
                          + (input_debug.symbolic_header.iextMax
                             * input_swap->external_ext_size));
@@ -5066,15 +5215,14 @@ elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info)
                  const char *name;
                  struct alpha_elf_link_hash_entry *h;
 
-                 (*input_swap->swap_ext_in) (input_bfd, (PTR) eraw_src, &ext);
+                 (*input_swap->swap_ext_in) (input_bfd, eraw_src, &ext);
                  if (ext.asym.sc == scNil
                      || ext.asym.sc == scUndefined
                      || ext.asym.sc == scSUndefined)
                    continue;
 
                  name = input_debug.ssext + ext.asym.iss;
-                 h = alpha_elf_link_hash_lookup (alpha_elf_hash_table (info),
-                                                 name, FALSE, FALSE, TRUE);
+                 h = alpha_elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE);
                  if (h == NULL || h->esym.ifd != -2)
                    continue;
 
@@ -5114,7 +5262,7 @@ elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info)
          einfo.failed = FALSE;
          elf_link_hash_traverse (elf_hash_table (info),
                                  elf64_alpha_output_extsym,
-                                 (PTR) &einfo);
+                                 &einfo);
          if (einfo.failed)
            return FALSE;
 
@@ -5138,7 +5286,7 @@ elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info)
   /* The .got subsections...  */
   {
     bfd *i, *dynobj = elf_hash_table(info)->dynobj;
-    for (i = alpha_elf_hash_table(info)->got_list;
+    for (i = htab->got_list;
         i != NULL;
         i = alpha_elf_tdata(i)->got_link_next)
       {
@@ -5172,7 +5320,9 @@ elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info)
 }
 
 static enum elf_reloc_type_class
-elf64_alpha_reloc_type_class (const Elf_Internal_Rela *rela)
+elf64_alpha_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                             const asection *rel_sec ATTRIBUTE_UNUSED,
+                             const Elf_Internal_Rela *rela)
 {
   switch ((int) ELF64_R_TYPE (rela->r_info))
     {
@@ -5257,6 +5407,7 @@ static const struct elf_size_info alpha_elf_size_info =
   ELFCLASS64, EV_CURRENT,
   bfd_elf64_write_out_phdrs,
   bfd_elf64_write_shdrs_and_ehdr,
+  bfd_elf64_checksum_contents,
   bfd_elf64_write_relocs,
   bfd_elf64_swap_symbol_in,
   bfd_elf64_swap_symbol_out,
@@ -5273,6 +5424,7 @@ static const struct elf_size_info alpha_elf_size_info =
 #define TARGET_LITTLE_SYM      bfd_elf64_alpha_vec
 #define TARGET_LITTLE_NAME     "elf64-alpha"
 #define ELF_ARCH               bfd_arch_alpha
+#define ELF_TARGET_ID          ALPHA_ELF_DATA
 #define ELF_MACHINE_CODE       EM_ALPHA
 #define ELF_MAXPAGESIZE        0x10000
 #define ELF_COMMONPAGESIZE     0x2000
@@ -5282,6 +5434,8 @@ static const struct elf_size_info alpha_elf_size_info =
 
 #define bfd_elf64_bfd_reloc_type_lookup \
   elf64_alpha_bfd_reloc_type_lookup
+#define bfd_elf64_bfd_reloc_name_lookup \
+  elf64_alpha_bfd_reloc_name_lookup
 #define elf_info_to_howto \
   elf64_alpha_info_to_howto
 
@@ -5306,6 +5460,8 @@ static const struct elf_size_info alpha_elf_size_info =
 
 #define elf_backend_add_symbol_hook \
   elf64_alpha_add_symbol_hook
+#define elf_backend_relocs_compatible \
+  _bfd_elf_relocs_compatible
 #define elf_backend_check_relocs \
   elf64_alpha_check_relocs
 #define elf_backend_create_dynamic_sections \
@@ -5314,6 +5470,8 @@ static const struct elf_size_info alpha_elf_size_info =
   elf64_alpha_adjust_dynamic_symbol
 #define elf_backend_merge_symbol_attribute \
   elf64_alpha_merge_symbol_attribute
+#define elf_backend_copy_indirect_symbol \
+  elf64_alpha_copy_indirect_symbol
 #define elf_backend_always_size_sections \
   elf64_alpha_always_size_sections
 #define elf_backend_size_dynamic_sections \
@@ -5331,6 +5489,10 @@ static const struct elf_size_info alpha_elf_size_info =
 #define elf_backend_reloc_type_class \
   elf64_alpha_reloc_type_class
 
+#define elf_backend_can_gc_sections    1
+#define elf_backend_gc_mark_hook       elf64_alpha_gc_mark_hook
+#define elf_backend_gc_sweep_hook      elf64_alpha_gc_sweep_hook
+
 #define elf_backend_ecoff_debug_swap \
   &elf64_alpha_ecoff_debug_swap