gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / bfd / elf64-alpha.c
index 4efe02a6ec4d046e2a4021f7a1e376ccedd3c35c..4e4efae0b1bf2d76980d7f51a6a4183674d3e1de 100644 (file)
@@ -1,6 +1,5 @@
 /* Alpha specific support for 64-bit ELF
-   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-   2006, 2007, 2008, 2009, 2010, 2011  Free Software Foundation, Inc.
+   Copyright (C) 1996-2020 Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@tamu.edu>.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -28,6 +27,7 @@
 #include "bfd.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
+#include "ecoff-bfd.h"
 
 #include "elf/alpha.h"
 
@@ -144,14 +144,14 @@ struct alpha_elf_reloc_entry
   /* Which .reloc section? */
   asection *srel;
 
-  /* What kind of relocation? */
-  unsigned int rtype;
-
-  /* Is this against read-only section? */
-  unsigned int reltext : 1;
+  /* Which section this relocation is against? */
+  asection *sec;
 
   /* How many did we find?  */
   unsigned long count;
+
+  /* What kind of relocation? */
+  unsigned int rtype;
 };
 
 struct alpha_elf_link_hash_entry
@@ -210,7 +210,7 @@ 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.  */
@@ -224,7 +224,7 @@ struct alpha_elf_link_hash_table
 #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.  */
@@ -280,7 +280,7 @@ static struct bfd_link_hash_table *
 elf64_alpha_bfd_link_hash_table_create (bfd *abfd)
 {
   struct alpha_elf_link_hash_table *ret;
-  bfd_size_type amt = sizeof (struct alpha_elf_link_hash_table);
+  size_t amt = sizeof (struct alpha_elf_link_hash_table);
 
   ret = (struct alpha_elf_link_hash_table *) bfd_zmalloc (amt);
   if (ret == (struct alpha_elf_link_hash_table *) NULL)
@@ -298,6 +298,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
@@ -327,6 +336,10 @@ 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) \
@@ -356,7 +369,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)
@@ -369,7 +382,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)
@@ -421,7 +434,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)
 {
@@ -474,8 +487,8 @@ static reloc_howto_type elf64_alpha_howto_table[] =
 {
   HOWTO (R_ALPHA_NONE,         /* type */
         0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
-        8,                     /* bitsize */
+        3,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
@@ -1088,13 +1101,22 @@ elf64_alpha_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 
 /* Given an Alpha ELF reloc type, fill in an arelent structure.  */
 
-static void
-elf64_alpha_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
+static bfd_boolean
+elf64_alpha_info_to_howto (bfd *abfd, arelent *cache_ptr,
                           Elf_Internal_Rela *dst)
 {
   unsigned r_type = ELF64_R_TYPE(dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_ALPHA_max);
+
+  if (r_type >= R_ALPHA_max)
+    {
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+                         abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
   cache_ptr->howto = &elf64_alpha_howto_table[r_type];
+  return TRUE;
 }
 
 /* These two relocations create a two-word entry in the got.  */
@@ -1114,9 +1136,7 @@ elf64_alpha_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
 \f
 /* Handle an Alpha specific section when reading an object file.  This
    is called when bfd_section_from_shdr finds a section with an unknown
-   type.
-   FIXME: We need to handle the SHF_ALPHA_GPREL flag, but I'm not sure
-   how to.  */
+   type.  */
 
 static bfd_boolean
 elf64_alpha_section_from_shdr (bfd *abfd,
@@ -1147,9 +1167,8 @@ elf64_alpha_section_from_shdr (bfd *abfd,
 
   if (hdr->sh_type == SHT_ALPHA_DEBUG)
     {
-      if (! bfd_set_section_flags (abfd, newsect,
-                                  (bfd_get_section_flags (abfd, newsect)
-                                   | SEC_DEBUGGING)))
+      if (!bfd_set_section_flags (newsect,
+                                 bfd_section_flags (newsect) | SEC_DEBUGGING))
        return FALSE;
     }
 
@@ -1159,10 +1178,10 @@ elf64_alpha_section_from_shdr (bfd *abfd,
 /* Convert Alpha specific section flags to bfd internal section flags.  */
 
 static bfd_boolean
-elf64_alpha_section_flags (flagword *flags, const Elf_Internal_Shdr *hdr)
+elf64_alpha_section_flags (const Elf_Internal_Shdr *hdr)
 {
   if (hdr->sh_flags & SHF_ALPHA_GPREL)
-    *flags |= SEC_SMALL_DATA;
+    hdr->bfd_section->flags |= SEC_SMALL_DATA;
 
   return TRUE;
 }
@@ -1175,13 +1194,13 @@ elf64_alpha_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec)
 {
   register const char *name;
 
-  name = bfd_get_section_name (abfd, sec);
+  name = bfd_section_name (sec);
 
   if (strcmp (name, ".mdebug") == 0)
     {
       hdr->sh_type = SHT_ALPHA_DEBUG;
       /* In a shared object on Irix 5.3, the .mdebug section has an
-         entsize of 0.  FIXME: Does this matter?  */
+        entsize of 0.  FIXME: Does this matter?  */
       if ((abfd->flags & DYNAMIC) != 0 )
        hdr->sh_entsize = 0;
       else
@@ -1208,7 +1227,7 @@ elf64_alpha_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
                             asection **secp, bfd_vma *valp)
 {
   if (sym->st_shndx == SHN_COMMON
-      && !info->relocatable
+      && !bfd_link_relocatable (info)
       && sym->st_size <= elf_gp_size (abfd))
     {
       /* Common symbols less than or equal to -G nn bytes are
@@ -1249,7 +1268,7 @@ elf64_alpha_create_got_section (bfd *abfd,
           | SEC_LINKER_CREATED);
   s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
   if (s == NULL
-      || !bfd_set_section_alignment (abfd, s, 3))
+      || !bfd_set_section_alignment (s, 3))
     return FALSE;
 
   alpha_elf_tdata (abfd)->got = s;
@@ -1280,7 +1299,8 @@ elf64_alpha_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
           | SEC_LINKER_CREATED
           | (elf64_alpha_use_secureplt ? SEC_READONLY : 0));
   s = bfd_make_section_anyway_with_flags (abfd, ".plt", flags);
-  if (s == NULL || ! bfd_set_section_alignment (abfd, s, 4))
+  elf_hash_table (info)->splt = s;
+  if (s == NULL || ! bfd_set_section_alignment (s, 4))
     return FALSE;
 
   /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
@@ -1294,14 +1314,16 @@ elf64_alpha_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
           | SEC_LINKER_CREATED | SEC_READONLY);
   s = bfd_make_section_anyway_with_flags (abfd, ".rela.plt", flags);
-  if (s == NULL || ! bfd_set_section_alignment (abfd, s, 3))
+  elf_hash_table (info)->srelplt = s;
+  if (s == NULL || ! bfd_set_section_alignment (s, 3))
     return FALSE;
 
   if (elf64_alpha_use_secureplt)
     {
       flags = SEC_ALLOC | SEC_LINKER_CREATED;
       s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
-      if (s == NULL || ! bfd_set_section_alignment (abfd, s, 3))
+      elf_hash_table (info)->sgotplt = s;
+      if (s == NULL || ! bfd_set_section_alignment (s, 3))
        return FALSE;
     }
 
@@ -1317,8 +1339,9 @@ elf64_alpha_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
           | SEC_LINKER_CREATED | SEC_READONLY);
   s = bfd_make_section_anyway_with_flags (abfd, ".rela.got", flags);
+  elf_hash_table (info)->srelgot = s;
   if (s == NULL
-      || !bfd_set_section_alignment (abfd, s, 3))
+      || !bfd_set_section_alignment (s, 3))
     return FALSE;
 
   /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the
@@ -1362,31 +1385,36 @@ elf64_alpha_read_ecoff_info (bfd *abfd, asection *section,
   /* The symbolic header contains absolute file offsets and sizes to
      read.  */
 #define READ(ptr, offset, count, size, type)                           \
-  if (symhdr->count == 0)                                              \
-    debug->ptr = NULL;                                                 \
-  else                                                                 \
+  do                                                                   \
     {                                                                  \
-      bfd_size_type amt = (bfd_size_type) size * symhdr->count;                \
-      debug->ptr = (type) bfd_malloc (amt);                            \
-      if (debug->ptr == NULL)                                          \
+      size_t amt;                                                      \
+      debug->ptr = NULL;                                               \
+      if (symhdr->count == 0)                                          \
+       break;                                                          \
+      if (_bfd_mul_overflow (size, symhdr->count, &amt))               \
+       {                                                               \
+         bfd_set_error (bfd_error_file_too_big);                       \
+         goto error_return;                                            \
+       }                                                               \
+      if (bfd_seek (abfd, symhdr->offset, SEEK_SET) != 0)              \
        goto error_return;                                              \
-      if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0    \
-         || bfd_bread (debug->ptr, amt, abfd) != amt)                  \
+      debug->ptr = (type) _bfd_malloc_and_read (abfd, amt, amt);       \
+      if (debug->ptr == NULL)                                          \
        goto error_return;                                              \
-    }
+    } while (0)
 
   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;
@@ -1394,30 +1422,18 @@ elf64_alpha_read_ecoff_info (bfd *abfd, asection *section,
   return TRUE;
 
  error_return:
-  if (ext_hdr != NULL)
-    free (ext_hdr);
-  if (debug->line != NULL)
-    free (debug->line);
-  if (debug->external_dnr != NULL)
-    free (debug->external_dnr);
-  if (debug->external_pdr != NULL)
-    free (debug->external_pdr);
-  if (debug->external_sym != NULL)
-    free (debug->external_sym);
-  if (debug->external_opt != NULL)
-    free (debug->external_opt);
-  if (debug->external_aux != NULL)
-    free (debug->external_aux);
-  if (debug->ss != NULL)
-    free (debug->ss);
-  if (debug->ssext != NULL)
-    free (debug->ssext);
-  if (debug->external_fdr != NULL)
-    free (debug->external_fdr);
-  if (debug->external_rfd != NULL)
-    free (debug->external_rfd);
-  if (debug->external_ext != NULL)
-    free (debug->external_ext);
+  free (ext_hdr);
+  free (debug->line);
+  free (debug->external_dnr);
+  free (debug->external_pdr);
+  free (debug->external_sym);
+  free (debug->external_opt);
+  free (debug->external_aux);
+  free (debug->ss);
+  free (debug->ssext);
+  free (debug->external_fdr);
+  free (debug->external_rfd);
+  free (debug->external_ext);
   return FALSE;
 }
 
@@ -1429,36 +1445,29 @@ 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,
+elf64_alpha_find_nearest_line (bfd *abfd, asymbol **symbols,
+                              asection *section, bfd_vma offset,
+                              const char **filename_ptr,
                               const char **functionname_ptr,
-                              unsigned int *line_ptr)
+                              unsigned int *line_ptr,
+                              unsigned int *discriminator_ptr)
 {
   asection *msec;
 
-  if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
+  if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr, 0,
-                                    &elf_tdata (abfd)->dwarf2_find_line_info))
+                                    line_ptr, discriminator_ptr,
+                                    dwarf_debug_sections,
+                                    &elf_tdata (abfd)->dwarf2_find_line_info)
+      == 1)
     return TRUE;
 
   msec = bfd_get_section_by_name (abfd, ".mdebug");
   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;
 
@@ -1469,16 +1478,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;
@@ -1505,16 +1514,16 @@ 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
-             objdump -l, so the information should be saved, or it is
-             rarely called, as in ld error messages, so the memory
-             wasted is unimportant.  Still, it would probably be a
-             good idea for free_cached_info to throw it away.  */
+            find_nearest_line is either called all the time, as in
+            objdump -l, so the information should be saved, or it is
+            rarely called, as in ld error messages, so the memory
+            wasted is unimportant.  Still, it would probably be a
+            good idea for free_cached_info to throw it away.  */
        }
 
       if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap,
@@ -1530,9 +1539,9 @@ elf64_alpha_find_nearest_line (bfd *abfd, asection *section, asymbol **symbols,
 
   /* Fall back on the generic ELF find_nearest_line routine.  */
 
-  return _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
+  return _bfd_elf_find_nearest_line (abfd, symbols, section, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr);
+                                    line_ptr, discriminator_ptr);
 }
 \f
 /* Structure used to pass information to alpha_elf_output_extsym.  */
@@ -1547,7 +1556,7 @@ 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;
@@ -1599,7 +1608,7 @@ elf64_alpha_output_extsym (struct alpha_elf_link_hash_entry *h, PTR data)
            h->esym.asym.sc = scUndefined;
          else
            {
-             name = bfd_section_name (output_section->owner, output_section);
+             name = bfd_section_name (output_section);
 
              if (strcmp (name, ".text") == 0)
                h->esym.asym.sc = scText;
@@ -1706,7 +1715,7 @@ get_got_entry (bfd *abfd, struct alpha_elf_link_hash_entry *h,
   if (!gotent)
     {
       int entry_size;
-      bfd_size_type amt;
+      size_t amt;
 
       amt = sizeof (struct alpha_elf_got_entry);
       gotent = (struct alpha_elf_got_entry *) bfd_alloc (abfd, amt);
@@ -1746,6 +1755,18 @@ elf64_alpha_want_plt (struct alpha_elf_link_hash_entry *ah)
          && (ah->flags & ~ALPHA_ELF_LINK_HASH_LU_PLT) == 0);
 }
 
+/* Whether to sort relocs output by ld -r or ld --emit-relocs, by r_offset.
+   Don't do so for code sections.  We want to keep ordering of LITERAL/LITUSE
+   as is.  On the other hand, elf-eh-frame.c processing requires .eh_frame
+   relocs to be sorted.  */
+
+static bfd_boolean
+elf64_alpha_sort_relocs_p (asection *sec)
+{
+  return (sec->flags & SEC_CODE) == 0;
+}
+
+
 /* Handle dynamic relocations when doing an Alpha ELF link.  */
 
 static bfd_boolean
@@ -1757,9 +1778,8 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
   Elf_Internal_Shdr *symtab_hdr;
   struct alpha_elf_link_hash_entry **sym_hashes;
   const Elf_Internal_Rela *rel, *relend;
-  bfd_size_type amt;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   /* Don't do anything special with non-loaded, non-alloced sections.
@@ -1808,20 +1828,22 @@ 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.ref_regular = 1;
        }
 
       /* We can only get preliminary data on whether a symbol is
-         locally or externally defined, as not all of the input files
-         have yet been processed.  Do something with what we know, as
-         this may help reduce memory usage and processing time later.  */
+        locally or externally defined, as not all of the input files
+        have yet been processed.  Do something with what we know, as
+        this may help reduce memory usage and processing time later.  */
       maybe_dynamic = FALSE;
-      if (h && ((info->shared
+      if (h && ((bfd_link_pic (info)
                 && (!info->symbolic
                     || info->unresolved_syms_in_shared_libs == RM_IGNORE))
                || !h->root.def_regular
                || h->root.root.type == bfd_link_hash_defweak))
-        maybe_dynamic = TRUE;
+       maybe_dynamic = TRUE;
 
       need = 0;
       gotent_flags = 0;
@@ -1857,7 +1879,7 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
        case R_ALPHA_REFLONG:
        case R_ALPHA_REFQUAD:
-         if (info->shared || maybe_dynamic)
+         if (bfd_link_pic (info) || maybe_dynamic)
            need = NEED_DYNREL;
          break;
 
@@ -1877,15 +1899,18 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_ALPHA_GOTTPREL:
          need = NEED_GOT | NEED_GOT_ENTRY;
          gotent_flags = ALPHA_ELF_LINK_HASH_TLS_IE;
-         if (info->shared)
+         if (bfd_link_pic (info))
            info->flags |= DF_STATIC_TLS;
          break;
 
        case R_ALPHA_TPREL64:
-         if (info->shared || maybe_dynamic)
+         if (bfd_link_dll (info))
+           {
+             info->flags |= DF_STATIC_TLS;
+             need = NEED_DYNREL;
+           }
+         else if (maybe_dynamic)
            need = NEED_DYNREL;
-         if (info->shared)
-           info->flags |= DF_STATIC_TLS;
          break;
        }
 
@@ -1955,15 +1980,15 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
              if (!rent)
                {
-                 amt = sizeof (struct alpha_elf_reloc_entry);
+                 size_t amt = sizeof (struct alpha_elf_reloc_entry);
                  rent = (struct alpha_elf_reloc_entry *) bfd_alloc (abfd, amt);
                  if (!rent)
                    return FALSE;
 
                  rent->srel = sreloc;
+                 rent->sec = sec;
                  rent->rtype = r_type;
                  rent->count = 1;
-                 rent->reltext = (sec->flags & SEC_READONLY) != 0;
 
                  rent->next = h->reloc_entries;
                  h->reloc_entries = rent;
@@ -1971,13 +1996,19 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
              else
                rent->count++;
            }
-         else if (info->shared)
+         else if (bfd_link_pic (info))
            {
              /* If this is a shared library, and the section is to be
                 loaded into memory, we need a RELATIVE reloc.  */
              sreloc->size += sizeof (Elf64_External_Rela);
              if (sec->flags & SEC_READONLY)
-               info->flags |= DF_TEXTREL;
+               {
+                 info->flags |= DF_TEXTREL;
+                 info->callbacks->minfo
+                   (_("%pB: dynamic relocation against `%pT' in "
+                      "read-only section `%pA'\n"),
+                    sec->owner, h->root.root.root.string, sec);
+               }
            }
        }
     }
@@ -2006,72 +2037,6 @@ elf64_alpha_gc_mark_hook (asection *sec, struct bfd_link_info *info,
   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
@@ -2098,7 +2063,7 @@ elf64_alpha_adjust_dynamic_symbol (struct bfd_link_info *info,
     {
       h->needs_plt = TRUE;
 
-      s = bfd_get_section_by_name(dynobj, ".plt");
+      s = elf_hash_table(info)->splt;
       if (!s && !elf64_alpha_create_dynamic_sections (dynobj, info))
        return FALSE;
 
@@ -2114,12 +2079,12 @@ elf64_alpha_adjust_dynamic_symbol (struct bfd_link_info *info,
   /* If this is a weak symbol, and there is a real definition, the
      processor independent code will have arranged for us to see the
      real definition first, and we can just use the same value.  */
-  if (h->u.weakdef != NULL)
+  if (h->is_weakalias)
     {
-      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
-                 || h->u.weakdef->root.type == bfd_link_hash_defweak);
-      h->root.u.def.section = h->u.weakdef->root.u.def.section;
-      h->root.u.def.value = h->u.weakdef->root.u.def.value;
+      struct elf_link_hash_entry *def = weakdef (h);
+      BFD_ASSERT (def->root.type == bfd_link_hash_defined);
+      h->root.u.def.section = def->root.u.def.section;
+      h->root.u.def.value = def->root.u.def.value;
       return TRUE;
     }
 
@@ -2148,23 +2113,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.  */
 
@@ -2183,8 +2154,8 @@ elf64_alpha_merge_ind_symbols (struct alpha_elf_link_hash_entry *hi,
                && gi->reloc_type == gs->reloc_type
                && gi->addend == gs->addend)
              {
-               gi->use_count += gs->use_count;
-               goto got_found;
+               gs->use_count += gi->use_count;
+               goto got_found;
              }
          gi->next = hs->got_entries;
          hs->got_entries = gi;
@@ -2217,8 +2188,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?  */
@@ -2254,25 +2223,25 @@ elf64_alpha_can_merge_gots (bfd *a, bfd *b)
 
          h = hashes[i];
          while (h->root.root.type == bfd_link_hash_indirect
-                || h->root.root.type == bfd_link_hash_warning)
+                || h->root.root.type == bfd_link_hash_warning)
            h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
 
          for (be = h->got_entries; be ; be = be->next)
            {
              if (be->use_count == 0)
-               continue;
+               continue;
              if (be->gotobj != b)
-               continue;
+               continue;
 
              for (ae = h->got_entries; ae ; ae = ae->next)
-               if (ae->gotobj == a
+               if (ae->gotobj == a
                    && ae->reloc_type == be->reloc_type
                    && ae->addend == be->addend)
                  goto global_found;
 
              total += alpha_got_entry_size (be->reloc_type);
              if (total > MAX_GOT_SIZE)
-               return FALSE;
+               return FALSE;
            global_found:;
            }
        }
@@ -2306,15 +2275,15 @@ elf64_alpha_merge_gots (bfd *a, bfd *b)
       /* Let the local .got entries know they are part of a new subsegment.  */
       local_got_entries = alpha_elf_tdata (bsub)->local_got_entries;
       if (local_got_entries)
-        {
+       {
          n = elf_tdata (bsub)->symtab_hdr.sh_info;
          for (i = 0; i < n; ++i)
            {
              struct alpha_elf_got_entry *ent;
              for (ent = local_got_entries[i]; ent; ent = ent->next)
-               ent->gotobj = a;
+               ent->gotobj = a;
            }
-        }
+       }
 
       /* Merge the global .got entries.  */
       hashes = alpha_elf_sym_hashes (bsub);
@@ -2322,29 +2291,29 @@ elf64_alpha_merge_gots (bfd *a, bfd *b)
 
       n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info;
       for (i = 0; i < n; ++i)
-        {
+       {
          struct alpha_elf_got_entry *ae, *be, **pbe, **start;
          struct alpha_elf_link_hash_entry *h;
 
          h = hashes[i];
          while (h->root.root.type == bfd_link_hash_indirect
-                || h->root.root.type == bfd_link_hash_warning)
+                || h->root.root.type == bfd_link_hash_warning)
            h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
 
          pbe = start = &h->got_entries;
          while ((be = *pbe) != NULL)
            {
              if (be->use_count == 0)
-               {
+               {
                  *pbe = be->next;
                  memset (be, 0xa5, sizeof (*be));
                  goto kill;
-               }
+               }
              if (be->gotobj != b)
-               goto next;
+               goto next;
 
              for (ae = *start; ae ; ae = ae->next)
-               if (ae->gotobj == a
+               if (ae->gotobj == a
                    && ae->reloc_type == be->reloc_type
                    && ae->addend == be->addend)
                  {
@@ -2361,7 +2330,7 @@ elf64_alpha_merge_gots (bfd *a, bfd *b)
              pbe = &be->next;
            kill:;
            }
-        }
+       }
 
       alpha_elf_tdata (bsub)->gotobj = a;
     }
@@ -2383,7 +2352,7 @@ 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;
 
@@ -2441,10 +2410,10 @@ elf64_alpha_calc_got_offsets (struct bfd_link_info *info)
          for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k)
            for (gotent = local_got_entries[k]; gotent; gotent = gotent->next)
              if (gotent->use_count > 0)
-               {
+               {
                  gotent->got_offset = got_offset;
                  got_offset += alpha_got_entry_size (gotent->reloc_type);
-               }
+               }
        }
 
       alpha_elf_tdata(i)->got->size = got_offset;
@@ -2454,7 +2423,8 @@ elf64_alpha_calc_got_offsets (struct bfd_link_info *info)
 /* Constructs the gots.  */
 
 static bfd_boolean
-elf64_alpha_size_got_sections (struct bfd_link_info *info)
+elf64_alpha_size_got_sections (struct bfd_link_info *info,
+                              bfd_boolean may_merge)
 {
   bfd *i, *got_list, *cur_got_obj = NULL;
   struct alpha_elf_link_hash_table * htab;
@@ -2468,7 +2438,7 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info)
      consisting of all of the input files.  */
   if (got_list == NULL)
     {
-      for (i = info->input_bfds; i ; i = i->link_next)
+      for (i = info->input_bfds; i ; i = i->link.next)
        {
          bfd *this_got;
 
@@ -2482,12 +2452,13 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info)
          /* We are assuming no merging has yet occurred.  */
          BFD_ASSERT (this_got == i);
 
-          if (alpha_elf_tdata (this_got)->total_got_size > MAX_GOT_SIZE)
+         if (alpha_elf_tdata (this_got)->total_got_size > MAX_GOT_SIZE)
            {
              /* Yikes! A single object file has too many entries.  */
-             (*_bfd_error_handler)
-               (_("%B: .got subsegment exceeds 64K (size %d)"),
-                i, alpha_elf_tdata (this_got)->total_got_size);
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("%pB: .got subsegment exceeds 64K (size %d)"),
+                i, alpha_elf_tdata (this_got)->total_got_size);
              return FALSE;
            }
 
@@ -2509,21 +2480,24 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info)
   if (cur_got_obj == NULL)
     return FALSE;
 
-  i = alpha_elf_tdata(cur_got_obj)->got_link_next;
-  while (i != NULL)
+  if (may_merge)
     {
-      if (elf64_alpha_can_merge_gots (cur_got_obj, i))
+      i = alpha_elf_tdata(cur_got_obj)->got_link_next;
+      while (i != NULL)
        {
-         elf64_alpha_merge_gots (cur_got_obj, i);
+         if (elf64_alpha_can_merge_gots (cur_got_obj, i))
+           {
+             elf64_alpha_merge_gots (cur_got_obj, i);
 
-         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;
-       }
-      else
-       {
-         cur_got_obj = i;
-         i = alpha_elf_tdata(i)->got_link_next;
+             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;
+           }
+         else
+           {
+             cur_got_obj = i;
+             i = alpha_elf_tdata(i)->got_link_next;
+           }
        }
     }
 
@@ -2535,7 +2509,8 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info)
 }
 
 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;
@@ -2572,15 +2547,13 @@ 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 = elf_hash_table(info)->splt;
   if (splt == NULL)
     return;
 
@@ -2590,7 +2563,7 @@ elf64_alpha_size_plt_section (struct bfd_link_info *info)
                                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 = elf_hash_table(info)->srelplt;
   entries = 0;
   if (splt->size)
     {
@@ -2606,7 +2579,7 @@ 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 = elf_hash_table(info)->sgotplt;
       sgotplt->size = entries ? 16 : 0;
     }
 }
@@ -2618,18 +2591,14 @@ elf64_alpha_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   bfd *i;
   struct alpha_elf_link_hash_table * htab;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   htab = alpha_elf_hash_table (info);
   if (htab == NULL)
     return FALSE;
 
-  /* First, take care of the indirect symbols created by versioning.  */
-  alpha_elf_link_hash_traverse (htab, elf64_alpha_merge_ind_symbols,
-                               NULL);
-
-  if (!elf64_alpha_size_got_sections (info))
+  if (!elf64_alpha_size_got_sections (info, TRUE))
     return FALSE;
 
   /* Allocate space for all of the .got subsections.  */
@@ -2651,7 +2620,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)
     {
@@ -2661,16 +2630,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.  */
@@ -2711,20 +2682,28 @@ elf64_alpha_calc_dynrel_sizes (struct alpha_elf_link_hash_entry *h,
 
   /* If the symbol is a hidden undefined weak, then we never have any
      relocations.  Avoid the loop which may want to add RELATIVE relocs
-     based on info->shared.  */
+     based on bfd_link_pic (info).  */
   if (h->root.root.type == bfd_link_hash_undefweak && !dynamic)
     return TRUE;
 
   for (relent = h->reloc_entries; relent; relent = relent->next)
     {
       entries = alpha_dynamic_entries_for_reloc (relent->rtype, dynamic,
-                                                info->shared);
+                                                bfd_link_pic (info),
+                                                bfd_link_pie (info));
       if (entries)
        {
+         asection *sec = relent->sec;
          relent->srel->size +=
            entries * sizeof (Elf64_External_Rela) * relent->count;
-         if (relent->reltext)
-           info->flags |= DT_TEXTREL;
+         if ((sec->flags & SEC_READONLY) != 0)
+           {
+             info->flags |= DT_TEXTREL;
+             info->callbacks->minfo
+               (_("%pB: dynamic relocation against `%pT' in "
+                  "read-only section `%pA'\n"),
+                sec->owner, h->root.root.root.string, sec);
+           }
        }
     }
 
@@ -2754,20 +2733,20 @@ elf64_alpha_size_rela_got_1 (struct alpha_elf_link_hash_entry *h,
 
   /* If the symbol is a hidden undefined weak, then we never have any
      relocations.  Avoid the loop which may want to add RELATIVE relocs
-     based on info->shared.  */
+     based on bfd_link_pic (info).  */
   if (h->root.root.type == bfd_link_hash_undefweak && !dynamic)
     return TRUE;
 
   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,
+                                                 bfd_link_pic (info),
+                                                 bfd_link_pie (info));
 
   if (entries > 0)
     {
-      bfd *dynobj = elf_hash_table(info)->dynobj;
-      asection *srel = bfd_get_section_by_name (dynobj, ".rela.got");
+      asection *srel = elf_hash_table(info)->srelgot;
       BFD_ASSERT (srel != NULL);
       srel->size += sizeof (Elf64_External_Rela) * entries;
     }
@@ -2781,7 +2760,7 @@ static void
 elf64_alpha_size_rela_got_section (struct bfd_link_info *info)
 {
   unsigned long entries;
-  bfd *i, *dynobj;
+  bfd *i;
   asection *srel;
   struct alpha_elf_link_hash_table * htab;
 
@@ -2812,12 +2791,12 @@ 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, bfd_link_pic (info),
+                            bfd_link_pie (info)));
        }
     }
 
-  dynobj = elf_hash_table(info)->dynobj;
-  srel = bfd_get_section_by_name (dynobj, ".rela.got");
+  srel = elf_hash_table(info)->srelgot;
   if (!srel)
     {
       BFD_ASSERT (entries == 0);
@@ -2838,7 +2817,7 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 {
   bfd *dynobj;
   asection *s;
-  bfd_boolean relplt;
+  bfd_boolean relplt, relocs;
   struct alpha_elf_link_hash_table * htab;
 
   htab = alpha_elf_hash_table (info);
@@ -2851,9 +2830,9 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (info->executable)
+      if (bfd_link_executable (info) && !info->nointerp)
        {
-         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;
@@ -2875,6 +2854,7 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
      determined the sizes of the various dynamic sections.  Allocate
      memory for them.  */
   relplt = FALSE;
+  relocs = FALSE;
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
       const char *name;
@@ -2884,7 +2864,7 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
       /* It's OK to base decisions on the section name, because none
         of the dynobj section names depend upon the input files.  */
-      name = bfd_get_section_name (dynobj, s);
+      name = bfd_section_name (s);
 
       if (CONST_STRNEQ (name, ".rela"))
        {
@@ -2892,6 +2872,8 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
            {
              if (strcmp (name, ".rela.plt") == 0)
                relplt = TRUE;
+             else
+               relocs = TRUE;
 
              /* We use the reloc_count field as a counter if we need
                 to copy relocs into the output file.  */
@@ -2937,7 +2919,7 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 #define add_dynamic_entry(TAG, VAL) \
   _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
-      if (info->executable)
+      if (bfd_link_executable (info))
        {
          if (!add_dynamic_entry (DT_DEBUG, 0))
            return FALSE;
@@ -2956,15 +2938,18 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
            return FALSE;
        }
 
-      if (!add_dynamic_entry (DT_RELA, 0)
-         || !add_dynamic_entry (DT_RELASZ, 0)
-         || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
-       return FALSE;
-
-      if (info->flags & DF_TEXTREL)
+      if (relocs)
        {
-         if (!add_dynamic_entry (DT_TEXTREL, 0))
+         if (!add_dynamic_entry (DT_RELA, 0)
+             || !add_dynamic_entry (DT_RELASZ, 0)
+             || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
            return FALSE;
+
+         if (info->flags & DF_TEXTREL)
+           {
+             if (!add_dynamic_entry (DT_TEXTREL, 0))
+               return FALSE;
+           }
        }
     }
 #undef add_dynamic_entry
@@ -3032,10 +3017,11 @@ elf64_alpha_relax_got_load (struct alpha_relax_info *info, bfd_vma symval,
   if (insn >> 26 != OP_LDQ)
     {
       reloc_howto_type *howto = elf64_alpha_howto_table + r_type;
-      ((*_bfd_error_handler)
-       ("%B: %A+0x%lx: warning: %s relocation against unexpected insn",
-       info->abfd, info->sec,
-       (unsigned long) irel->r_offset, howto->name));
+      _bfd_error_handler
+       /* xgettext:c-format */
+       (_("%pB: %pA+%#" PRIx64 ": warning: "
+          "%s relocation against unexpected insn"),
+        info->abfd, info->sec, (uint64_t) irel->r_offset, howto->name);
       return TRUE;
     }
 
@@ -3044,7 +3030,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
+      && bfd_link_dll (info->link_info))
     return TRUE;
 
   if (r_type == R_ALPHA_LITERAL)
@@ -3052,7 +3039,7 @@ elf64_alpha_relax_got_load (struct alpha_relax_info *info, bfd_vma symval,
       /* Look for nice constant addresses.  This includes the not-uncommon
         special case of 0 for undefweak symbols.  */
       if ((info->h && info->h->root.root.type == bfd_link_hash_undefweak)
-         || (!info->link_info->shared
+         || (!bfd_link_pic (info->link_info)
              && (symval >= (bfd_vma)-0x8000 || symval < 0x8000)))
        {
          disp = 0;
@@ -3062,6 +3049,10 @@ elf64_alpha_relax_got_load (struct alpha_relax_info *info, bfd_vma symval,
        }
       else
        {
+         /* We may only create GPREL relocs during the second pass.  */
+         if (info->link_info->relax_pass == 0)
+           return TRUE;
+
          disp = symval - info->gp;
          insn = (OP_LDA << 26) | (insn & 0x03ff0000);
          r_type = R_ALPHA_GPREL16;
@@ -3162,13 +3153,15 @@ 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)
            return 0;
          tsec_relend = tsec_relocs + info->tsec->reloc_count;
-         tsec_free = (info->link_info->keep_memory ? NULL : tsec_relocs);
+         tsec_free = (elf_section_data (info->tsec)->relocs == tsec_relocs
+                      ? NULL
+                      : tsec_relocs);
        }
 
       /* Recover the symbol's offset within the section.  */
@@ -3181,12 +3174,10 @@ elf64_alpha_relax_opt_call (struct alpha_relax_info *info, bfd_vma symval)
 
       if (!gpdisp || gpdisp->r_addend != 4)
        {
-         if (tsec_free)
-           free (tsec_free);
+         free (tsec_free);
          return 0;
        }
-      if (tsec_free)
-        free (tsec_free);
+      free (tsec_free);
     }
 
   /* We've now determined that we can skip an initial gp load.  Verify
@@ -3202,22 +3193,29 @@ static bfd_boolean
 elf64_alpha_relax_with_lituse (struct alpha_relax_info *info,
                               bfd_vma symval, Elf_Internal_Rela *irel)
 {
-  Elf_Internal_Rela *urel, *irelend = info->relend;
-  int flags, count, i;
+  Elf_Internal_Rela *urel, *erel, *irelend = info->relend;
+  int flags;
   bfd_signed_vma disp;
   bfd_boolean fits16;
   bfd_boolean fits32;
   bfd_boolean lit_reused = FALSE;
   bfd_boolean all_optimized = TRUE;
+  bfd_boolean changed_contents;
+  bfd_boolean changed_relocs;
+  bfd_byte *contents = info->contents;
+  bfd *abfd = info->abfd;
+  bfd_vma sec_output_vma;
   unsigned int lit_insn;
+  int relax_pass;
 
-  lit_insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset);
+  lit_insn = bfd_get_32 (abfd, contents + irel->r_offset);
   if (lit_insn >> 26 != OP_LDQ)
     {
-      ((*_bfd_error_handler)
-       ("%B: %A+0x%lx: warning: LITERAL relocation against unexpected insn",
-       info->abfd, info->sec,
-       (unsigned long) irel->r_offset));
+      _bfd_error_handler
+       /* xgettext:c-format */
+       (_("%pB: %pA+%#" PRIx64 ": warning: "
+          "%s relocation against unexpected insn"),
+        abfd, info->sec, (uint64_t) irel->r_offset, "LITERAL");
       return TRUE;
     }
 
@@ -3225,25 +3223,32 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info,
   if (alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info))
     return TRUE;
 
+  changed_contents = info->changed_contents;
+  changed_relocs = info->changed_relocs;
+  sec_output_vma = info->sec->output_section->vma + info->sec->output_offset;
+  relax_pass = info->link_info->relax_pass;
+
   /* Summarize how this particular LITERAL is used.  */
-  for (urel = irel+1, flags = count = 0; urel < irelend; ++urel, ++count)
+  for (erel = irel+1, flags = 0; erel < irelend; ++erel)
     {
-      if (ELF64_R_TYPE (urel->r_info) != R_ALPHA_LITUSE)
+      if (ELF64_R_TYPE (erel->r_info) != R_ALPHA_LITUSE)
        break;
-      if (urel->r_addend <= 6)
-       flags |= 1 << urel->r_addend;
+      if (erel->r_addend <= 6)
+       flags |= 1 << erel->r_addend;
     }
 
   /* A little preparation for the loop...  */
   disp = symval - info->gp;
 
-  for (urel = irel+1, i = 0; i < count; ++i, ++urel)
+  for (urel = irel+1; urel < erel; ++urel)
     {
+      bfd_vma urel_r_offset = urel->r_offset;
       unsigned int insn;
       int insn_disp;
       bfd_signed_vma xdisp;
+      Elf_Internal_Rela nrel;
 
-      insn = bfd_get_32 (info->abfd, info->contents + urel->r_offset);
+      insn = bfd_get_32 (abfd, contents + urel_r_offset);
 
       switch (urel->r_addend)
        {
@@ -3255,6 +3260,13 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info,
          break;
 
        case LITUSE_ALPHA_BASE:
+         /* We may only create GPREL relocs during the second pass.  */
+         if (relax_pass == 0)
+           {
+             all_optimized = FALSE;
+             break;
+           }
+
          /* We can always optimize 16-bit displacements.  */
 
          /* Extract the displacement from the instruction, sign-extending
@@ -3272,14 +3284,20 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info,
              /* Take the op code and dest from this insn, take the base
                 register from the literal insn.  Leave the offset alone.  */
              insn = (insn & 0xffe0ffff) | (lit_insn & 0x001f0000);
-             urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
-                                          R_ALPHA_GPREL16);
-             urel->r_addend = irel->r_addend;
-             info->changed_relocs = TRUE;
-
-             bfd_put_32 (info->abfd, (bfd_vma) insn,
-                         info->contents + urel->r_offset);
-             info->changed_contents = TRUE;
+             bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset);
+             changed_contents = TRUE;
+
+             nrel = *urel;
+             nrel.r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
+                                         R_ALPHA_GPREL16);
+             nrel.r_addend = irel->r_addend;
+
+             /* As we adjust, move the reloc to the end so that we don't
+                break the LITERAL+LITUSE chain.  */
+             if (urel < --erel)
+               *urel-- = *erel;
+             *erel = nrel;
+             changed_relocs = TRUE;
            }
 
          /* If all mem+byte, we can optimize 32-bit mem displacements.  */
@@ -3290,15 +3308,16 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info,
              irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
                                           R_ALPHA_GPRELHIGH);
              lit_insn = (OP_LDAH << 26) | (lit_insn & 0x03ff0000);
-             bfd_put_32 (info->abfd, (bfd_vma) lit_insn,
-                         info->contents + irel->r_offset);
+             bfd_put_32 (abfd, (bfd_vma) lit_insn, contents + irel->r_offset);
              lit_reused = TRUE;
-             info->changed_contents = TRUE;
+             changed_contents = TRUE;
 
+             /* Since all relocs must be optimized, don't bother swapping
+                this relocation to the end.  */
              urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
                                           R_ALPHA_GPRELLOW);
              urel->r_addend = irel->r_addend;
-             info->changed_relocs = TRUE;
+             changed_relocs = TRUE;
            }
          else
            all_optimized = FALSE;
@@ -3312,14 +3331,19 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info,
 
          insn &= ~ (unsigned) 0x001ff000;
          insn |= ((symval & 7) << 13) | 0x1000;
-
-         urel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
-         urel->r_addend = 0;
-         info->changed_relocs = TRUE;
-
-         bfd_put_32 (info->abfd, (bfd_vma) insn,
-                     info->contents + urel->r_offset);
-         info->changed_contents = TRUE;
+         bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset);
+         changed_contents = TRUE;
+
+         nrel = *urel;
+         nrel.r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
+         nrel.r_addend = 0;
+
+         /* As we adjust, move the reloc to the end so that we don't
+            break the LITERAL+LITUSE chain.  */
+         if (urel < --erel)
+           *urel-- = *erel;
+         *erel = nrel;
+         changed_relocs = TRUE;
          break;
 
        case LITUSE_ALPHA_JSR:
@@ -3336,18 +3360,15 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info,
            if (info->h && info->h->root.root.type == bfd_link_hash_undefweak)
              {
                insn |= 31 << 16;
-               bfd_put_32 (info->abfd, (bfd_vma) insn,
-                           info->contents + urel->r_offset);
+               bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset);
 
-               info->changed_contents = TRUE;
+               changed_contents = TRUE;
                break;
              }
 
            /* If not zero, place to jump without needing pv.  */
            optdest = elf64_alpha_relax_opt_call (info, symval);
-           org = (info->sec->output_section->vma
-                  + info->sec->output_offset
-                  + urel->r_offset + 4);
+           org = sec_output_vma + urel_r_offset + 4;
            odisp = (optdest ? optdest : symval) - org;
 
            if (odisp >= -0x400000 && odisp < 0x400000)
@@ -3359,27 +3380,32 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info,
                  insn = (OP_BSR << 26) | (insn & 0x03e00000);
                else
                  insn = (OP_BR << 26) | (insn & 0x03e00000);
+               bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset);
+               changed_contents = TRUE;
 
-               urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
-                                            R_ALPHA_BRADDR);
-               urel->r_addend = irel->r_addend;
+               nrel = *urel;
+               nrel.r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
+                                           R_ALPHA_BRADDR);
+               nrel.r_addend = irel->r_addend;
 
                if (optdest)
-                 urel->r_addend += optdest - symval;
+                 nrel.r_addend += optdest - symval;
                else
                  all_optimized = FALSE;
 
-               bfd_put_32 (info->abfd, (bfd_vma) insn,
-                           info->contents + urel->r_offset);
-
                /* Kill any HINT reloc that might exist for this insn.  */
                xrel = (elf64_alpha_find_reloc_at_ofs
-                       (info->relocs, info->relend, urel->r_offset,
+                       (info->relocs, info->relend, urel_r_offset,
                         R_ALPHA_HINT));
                if (xrel)
                  xrel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
 
-               info->changed_contents = TRUE;
+               /* As we adjust, move the reloc to the end so that we don't
+                  break the LITERAL+LITUSE chain.  */
+               if (urel < --erel)
+                 *urel-- = *erel;
+               *erel = nrel;
+
                info->changed_relocs = TRUE;
              }
            else
@@ -3391,14 +3417,14 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info,
              {
                Elf_Internal_Rela *gpdisp
                  = (elf64_alpha_find_reloc_at_ofs
-                    (info->relocs, irelend, urel->r_offset + 4,
+                    (info->relocs, irelend, urel_r_offset + 4,
                      R_ALPHA_GPDISP));
                if (gpdisp)
                  {
-                   bfd_byte *p_ldah = info->contents + gpdisp->r_offset;
+                   bfd_byte *p_ldah = contents + gpdisp->r_offset;
                    bfd_byte *p_lda = p_ldah + gpdisp->r_addend;
-                   unsigned int ldah = bfd_get_32 (info->abfd, p_ldah);
-                   unsigned int lda = bfd_get_32 (info->abfd, p_lda);
+                   unsigned int ldah = bfd_get_32 (abfd, p_ldah);
+                   unsigned int lda = bfd_get_32 (abfd, p_lda);
 
                    /* Verify that the instruction is "ldah $29,0($26)".
                       Consider a function that ends in a noreturn call,
@@ -3407,12 +3433,12 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info,
                       In that case the insn would use $27 as the base.  */
                    if (ldah == 0x27ba0000 && lda == 0x23bd0000)
                      {
-                       bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_ldah);
-                       bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_lda);
+                       bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, p_ldah);
+                       bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, p_lda);
 
                        gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
-                       info->changed_contents = TRUE;
-                       info->changed_relocs = TRUE;
+                       changed_contents = TRUE;
+                       changed_relocs = TRUE;
                      }
                  }
              }
@@ -3421,6 +3447,9 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info,
        }
     }
 
+  /* If we reused the literal instruction, we must have optimized all.  */
+  BFD_ASSERT(!lit_reused || all_optimized);
+
   /* If all cases were optimized, we can reduce the use count on this
      got entry by one, possibly eliminating it.  */
   if (all_optimized)
@@ -3440,17 +3469,19 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info,
       if (!lit_reused)
        {
          irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
-         info->changed_relocs = TRUE;
+         changed_relocs = TRUE;
 
-         bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP,
-                     info->contents + irel->r_offset);
-         info->changed_contents = TRUE;
+         bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, contents + irel->r_offset);
+         changed_contents = TRUE;
        }
-
-      return TRUE;
     }
-  else
-    return elf64_alpha_relax_got_load (info, symval, irel, R_ALPHA_LITERAL);
+
+  info->changed_contents = changed_contents;
+  info->changed_relocs = changed_relocs;
+
+  if (all_optimized || relax_pass == 0)
+    return TRUE;
+  return elf64_alpha_relax_got_load (info, symval, irel, R_ALPHA_LITERAL);
 }
 
 static bfd_boolean
@@ -3472,12 +3503,12 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval,
 
   /* If the symbol is local, and we've already committed to DF_STATIC_TLS,
      then we might as well relax to IE.  */
-  else if (info->link_info->shared && !dynamic
+  else if (bfd_link_pic (info->link_info) && !dynamic
           && (info->link_info->flags & DF_STATIC_TLS))
     ;
 
   /* Otherwise we must be building an executable to do anything.  */
-  else if (info->link_info->shared)
+  else if (bfd_link_pic (info->link_info))
     return TRUE;
 
   /* The TLSGD/TLSLDM relocation must be followed by a LITERAL and
@@ -3502,6 +3533,13 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval,
   pos[3] = info->contents + gpdisp->r_offset;
   pos[4] = pos[3] + gpdisp->r_addend;
 
+  /* 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
      an exception when pos 1 is adjacent to pos 0.  */
@@ -3569,14 +3607,9 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval,
   use_gottprel = FALSE;
   new_symndx = is_gd ? ELF64_R_SYM (irel->r_info) : STN_UNDEF;
 
-  /* 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;
-
-  switch (!dynamic && !info->link_info->shared)
+  /* Some compilers warn about a Boolean-looking expression being
+     used in a switch.  The explicit cast silences them.  */
+  switch ((int) (!dynamic && !bfd_link_pic (info->link_info)))
     {
     case 1:
       {
@@ -3710,6 +3743,7 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
   struct alpha_elf_got_entry **local_got_entries;
   struct alpha_relax_info info;
   struct alpha_elf_link_hash_table * htab;
+  int relax_pass;
 
   htab = alpha_elf_hash_table (link_info);
   if (htab == NULL)
@@ -3718,22 +3752,26 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
   /* There's nothing to change, yet.  */
   *again = FALSE;
 
-  if (link_info->relocatable
+  if (bfd_link_relocatable (link_info)
       || ((sec->flags & (SEC_CODE | SEC_RELOC | SEC_ALLOC))
          != (SEC_CODE | SEC_RELOC | SEC_ALLOC))
       || sec->reloc_count == 0)
     return TRUE;
 
   BFD_ASSERT (is_alpha_elf (abfd));
+  relax_pass = link_info->relax_pass;
 
   /* 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))
+      /* This should never fail after the initial round, since the only error
+        is GOT overflow, and relaxation only shrinks the table.  However, we
+        may only merge got sections during the first pass.  If we merge
+        sections after we've created GPREL relocs, the GP for the merged
+        section backs up which may put the relocs out of range.  */
+      if (!elf64_alpha_size_got_sections (link_info, relax_pass == 0))
        abort ();
       if (elf_hash_table (link_info)->dynamic_sections_created)
        {
@@ -3747,7 +3785,7 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
 
   /* 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;
@@ -3788,24 +3826,21 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
       unsigned long r_symndx = ELF64_R_SYM (irel->r_info);
 
       /* Early exit for unhandled or unrelaxable relocations.  */
-      switch (r_type)
+      if (r_type != R_ALPHA_LITERAL)
        {
-       case R_ALPHA_LITERAL:
-       case R_ALPHA_GPRELHIGH:
-       case R_ALPHA_GPRELLOW:
-       case R_ALPHA_GOTDTPREL:
-       case R_ALPHA_GOTTPREL:
-       case R_ALPHA_TLSGD:
-         break;
-
-       case R_ALPHA_TLSLDM:
-         /* The symbol for a TLSLDM reloc is ignored.  Collapse the
-             reloc to the STN_UNDEF (0) symbol so that they all match.  */
-         r_symndx = STN_UNDEF;
-         break;
-
-       default:
-         continue;
+         /* We complete everything except LITERAL in the first pass.  */
+         if (relax_pass != 0)
+           continue;
+         if (r_type == R_ALPHA_TLSLDM)
+           {
+             /* The symbol for a TLSLDM reloc is ignored.  Collapse the
+                reloc to the STN_UNDEF (0) symbol so that they all match.  */
+             r_symndx = STN_UNDEF;
+           }
+         else if (r_type != R_ALPHA_GOTDTPREL
+                  && r_type != R_ALPHA_GOTTPREL
+                  && r_type != R_ALPHA_TLSGD)
+           continue;
        }
 
       /* Get the value of the symbol referred to by the reloc.  */
@@ -3839,13 +3874,13 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
            {
              symval = isym->st_value;
              if (isym->st_shndx == SHN_UNDEF)
-               continue;
+               continue;
              else if (isym->st_shndx == SHN_ABS)
-               info.tsec = bfd_abs_section_ptr;
+               info.tsec = bfd_abs_section_ptr;
              else if (isym->st_shndx == SHN_COMMON)
-               info.tsec = bfd_com_section_ptr;
+               info.tsec = bfd_com_section_ptr;
              else
-               info.tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+               info.tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
            }
 
          info.h = NULL;
@@ -3988,14 +4023,11 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
   return TRUE;
 
  error_return:
-  if (isymbuf != NULL
-      && symtab_hdr->contents != (unsigned char *) isymbuf)
+  if (symtab_hdr->contents != (unsigned char *) isymbuf)
     free (isymbuf);
-  if (info.contents != NULL
-      && elf_section_data (sec)->this_hdr.contents != info.contents)
+  if (elf_section_data (sec)->this_hdr.contents != info.contents)
     free (info.contents);
-  if (internal_relocs != NULL
-      && elf_section_data (sec)->relocs != internal_relocs)
+  if (elf_section_data (sec)->relocs != internal_relocs)
     free (internal_relocs);
   return FALSE;
 }
@@ -4063,8 +4095,9 @@ elf64_alpha_relocate_section_r (bfd *output_bfd ATTRIBUTE_UNUSED,
       r_type = ELF64_R_TYPE (rel->r_info);
       if (r_type >= R_ALPHA_max)
        {
-         (*_bfd_error_handler)
-           (_("%B: unknown relocation type %d"),
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("%pB: unsupported relocation type %#x"),
             input_bfd, (int) r_type);
          bfd_set_error (bfd_error_bad_value);
          ret_val = FALSE;
@@ -4100,10 +4133,10 @@ elf64_alpha_relocate_section_r (bfd *output_bfd ATTRIBUTE_UNUSED,
          sec = h->root.u.def.section;
        }
 
-      if (sec != NULL && elf_discarded_section (sec))
+      if (sec != NULL && discarded_section (sec))
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-                                        rel, relend,
-                                        elf64_alpha_howto_table + r_type,
+                                        rel, 1, relend,
+                                        elf64_alpha_howto_table + r_type, 0,
                                         contents);
 
       if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
@@ -4132,9 +4165,9 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
   bfd_boolean ret_val;
 
   BFD_ASSERT (is_alpha_elf (input_bfd));
-  
+
   /* Handle relocatable links with a smaller loop.  */
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return elf64_alpha_relocate_section_r (output_bfd, info, input_bfd,
                                           input_section, contents, relocs,
                                           local_syms, local_sections);
@@ -4146,10 +4179,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
   symtab_hdr = &elf_symtab_hdr (input_bfd);
 
   dynobj = elf_hash_table (info)->dynobj;
-  if (dynobj)
-    srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
-  else
-    srelgot = NULL;
+  srelgot = elf_hash_table (info)->srelgot;
 
   if (input_section->flags & SEC_ALLOC)
     {
@@ -4158,7 +4188,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                      (input_bfd, elf_elfheader(input_bfd)->e_shstrndx,
                       _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;
@@ -4206,14 +4236,16 @@ 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;
 
       r_type = ELF64_R_TYPE(rel->r_info);
       if (r_type >= R_ALPHA_max)
        {
-         (*_bfd_error_handler)
-           (_("%B: unknown relocation type %d"),
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("%pB: unsupported relocation type %#x"),
             input_bfd, (int) r_type);
          bfd_set_error (bfd_error_bad_value);
          ret_val = FALSE;
@@ -4257,7 +4289,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)
            {
@@ -4286,15 +4318,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;
@@ -4305,13 +4336,13 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
            undef_weak_ref = TRUE;
 
          h = (struct alpha_elf_link_hash_entry *) hh;
-          dynamic_symbol_p = alpha_elf_dynamic_symbol_p (&h->root, info);
+         dynamic_symbol_p = alpha_elf_dynamic_symbol_p (&h->root, info);
          gotent = h->got_entries;
        }
 
-      if (sec != NULL && elf_discarded_section (sec))
+      if (sec != NULL && discarded_section (sec))
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-                                        rel, relend, howto, contents);
+                                        rel, 1, relend, howto, 0, contents);
 
       addend = rel->r_addend;
       value += addend;
@@ -4359,7 +4390,9 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
              /* If the symbol has been forced local, output a
                 RELATIVE reloc, otherwise it will be handled in
                 finish_dynamic_symbol.  */
-             if (info->shared && !dynamic_symbol_p && !undef_weak_ref)
+             if (bfd_link_pic (info)
+                 && !dynamic_symbol_p
+                 && !undef_weak_ref)
                elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
                                         gotent->got_offset, 0,
                                         R_ALPHA_RELATIVE, value);
@@ -4375,24 +4408,26 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        case R_ALPHA_GPREL16:
        case R_ALPHA_GPRELLOW:
          if (dynamic_symbol_p)
-            {
-              (*_bfd_error_handler)
-                (_("%B: gp-relative relocation against dynamic symbol %s"),
-                 input_bfd, h->root.root.root.string);
-              ret_val = FALSE;
-            }
+           {
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("%pB: gp-relative relocation against dynamic symbol %s"),
+                input_bfd, h->root.root.root.string);
+             ret_val = FALSE;
+           }
          BFD_ASSERT(gp != 0);
          value -= gp;
          goto default_reloc;
 
        case R_ALPHA_GPRELHIGH:
          if (dynamic_symbol_p)
-            {
-              (*_bfd_error_handler)
-                (_("%B: gp-relative relocation against dynamic symbol %s"),
-                 input_bfd, h->root.root.root.string);
-              ret_val = FALSE;
-            }
+           {
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("%pB: gp-relative relocation against dynamic symbol %s"),
+                input_bfd, h->root.root.root.string);
+             ret_val = FALSE;
+           }
          BFD_ASSERT(gp != 0);
          value -= gp;
          value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
@@ -4413,12 +4448,13 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
        case R_ALPHA_BRADDR:
          if (dynamic_symbol_p)
-            {
-              (*_bfd_error_handler)
-                (_("%B: pc-relative relocation against dynamic symbol %s"),
-                 input_bfd, h->root.root.root.string);
-              ret_val = FALSE;
-            }
+           {
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("%pB: pc-relative relocation against dynamic symbol %s"),
+                input_bfd, h->root.root.root.string);
+             ret_val = FALSE;
+           }
          /* The regular PC-relative stuff measures from the start of
             the instruction rather than the end.  */
          value -= 4;
@@ -4442,8 +4478,9 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                && alpha_elf_tdata (sec->owner)->gotobj
                && gotobj != alpha_elf_tdata (sec->owner)->gotobj)
              {
-               (*_bfd_error_handler)
-                 (_("%B: change in gp: BRSGP %s"),
+               _bfd_error_handler
+                 /* xgettext:c-format */
+                 (_("%pB: change in gp: BRSGP %s"),
                   input_bfd, h->root.root.root.string);
                ret_val = FALSE;
              }
@@ -4456,7 +4493,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
            switch (other & STO_ALPHA_STD_GPLOAD)
              {
              case STO_ALPHA_NOPV:
-               break;
+               break;
              case STO_ALPHA_STD_GPLOAD:
                value += 8;
                break;
@@ -4470,10 +4507,11 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                    if (name == NULL)
                      name = _("<unknown>");
                    else if (name[0] == 0)
-                     name = bfd_section_name (input_bfd, sec);
+                     name = bfd_section_name (sec);
                  }
-               (*_bfd_error_handler)
-                 (_("%B: !samegp reloc against symbol without .prologue: %s"),
+               _bfd_error_handler
+                 /* xgettext:c-format */
+                 (_("%pB: !samegp reloc against symbol without .prologue: %s"),
                   input_bfd, name);
                ret_val = FALSE;
                break;
@@ -4509,7 +4547,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 (!bfd_link_dll (info))
                  {
                    value -= tp_base;
                    goto default_reloc;
@@ -4517,15 +4555,21 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                dynindx = 0;
                dynaddend = value - dtp_base;
              }
-           else if (info->shared
+           else if (bfd_link_pic (info)
                     && 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)
                  {
-                   (*_bfd_error_handler)
-                     (_("%B: unhandled dynamic relocation against %s"),
+                   _bfd_error_handler
+                     /* xgettext:c-format */
+                     (_("%pB: unhandled dynamic relocation against %s"),
                       input_bfd,
                       h->root.root.root.string);
                    ret_val = FALSE;
@@ -4548,25 +4592,32 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        case R_ALPHA_SREL32:
        case R_ALPHA_SREL64:
          if (dynamic_symbol_p)
-            {
-              (*_bfd_error_handler)
-                (_("%B: pc-relative relocation against dynamic symbol %s"),
-                 input_bfd, h->root.root.root.string);
-              ret_val = FALSE;
-            }
-         else if ((info->shared || info->pie) && undef_weak_ref)
-            {
-              (*_bfd_error_handler)
-                (_("%B: pc-relative relocation against undefined weak symbol %s"),
-                 input_bfd, h->root.root.root.string);
-              ret_val = FALSE;
-            }
+           {
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("%pB: pc-relative relocation against dynamic symbol %s"),
+                input_bfd, h->root.root.root.string);
+             ret_val = FALSE;
+           }
+         else if (bfd_link_pic (info)
+                  && undef_weak_ref)
+           {
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("%pB: pc-relative relocation against undefined weak symbol %s"),
+                input_bfd, h->root.root.root.string);
+             ret_val = FALSE;
+           }
 
 
          /* ??? .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 == STN_UNDEF)
+         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;
@@ -4583,13 +4634,14 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
              gotent->reloc_done = 1;
 
              /* Note that the module index for the main program is 1.  */
-             bfd_put_64 (output_bfd, !info->shared && !dynamic_symbol_p,
+             bfd_put_64 (output_bfd,
+                         !bfd_link_pic (info) && !dynamic_symbol_p,
                          sgot->contents + gotent->got_offset);
 
              /* If the symbol has been forced local, output a
                 DTPMOD64 reloc, otherwise it will be handled in
                 finish_dynamic_symbol.  */
-             if (info->shared && !dynamic_symbol_p)
+             if (bfd_link_pic (info) && !dynamic_symbol_p)
                elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
                                         gotent->got_offset, 0,
                                         R_ALPHA_DTPMOD64, 0);
@@ -4599,7 +4651,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
              else
                {
                  BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
-                 value -= dtp_base;
+                 value -= dtp_base;
                }
              bfd_put_64 (output_bfd, value,
                          sgot->contents + gotent->got_offset + 8);
@@ -4615,12 +4667,13 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        case R_ALPHA_DTPRELLO:
        case R_ALPHA_DTPREL16:
          if (dynamic_symbol_p)
-            {
-              (*_bfd_error_handler)
-                (_("%B: dtp-relative relocation against dynamic symbol %s"),
-                 input_bfd, h->root.root.root.string);
-              ret_val = FALSE;
-            }
+           {
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("%pB: dtp-relative relocation against dynamic symbol %s"),
+                input_bfd, h->root.root.root.string);
+             ret_val = FALSE;
+           }
          BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
          value -= dtp_base;
          if (r_type == R_ALPHA_DTPRELHI)
@@ -4630,20 +4683,22 @@ 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 (bfd_link_dll (info))
            {
-             (*_bfd_error_handler)
-               (_("%B: TLS local exec code cannot be linked into shared objects"),
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("%pB: TLS local exec code cannot be linked into shared objects"),
                input_bfd);
-              ret_val = FALSE;
+             ret_val = FALSE;
            }
          else if (dynamic_symbol_p)
-            {
-              (*_bfd_error_handler)
-                (_("%B: tp-relative relocation against dynamic symbol %s"),
-                 input_bfd, h->root.root.root.string);
-              ret_val = FALSE;
-            }
+           {
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("%pB: tp-relative relocation against dynamic symbol %s"),
+                input_bfd, h->root.root.root.string);
+             ret_val = FALSE;
+           }
          BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
          value -= tp_base;
          if (r_type == R_ALPHA_TPRELHI)
@@ -4668,7 +4723,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                  BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
                  if (r_type == R_ALPHA_GOTDTPREL)
                    value -= dtp_base;
-                 else if (!info->shared)
+                 else if (bfd_link_executable (info))
                    value -= tp_base;
                  else
                    {
@@ -4711,7 +4766,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)
@@ -4723,13 +4778,11 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                if (name == NULL)
                  return FALSE;
                if (*name == '\0')
-                 name = bfd_section_name (input_bfd, sec);
+                 name = bfd_section_name (sec);
              }
-           if (! ((*info->callbacks->reloc_overflow)
-                  (info, (h ? &h->root.root : NULL), name, howto->name,
-                   (bfd_vma) 0, input_bfd, input_section,
-                   rel->r_offset)))
-             ret_val = FALSE;
+           (*info->callbacks->reloc_overflow)
+             (info, (h ? &h->root.root : NULL), name, howto->name,
+              (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
          }
          break;
 
@@ -4751,7 +4804,6 @@ elf64_alpha_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info,
                                   Elf_Internal_Sym *sym)
 {
   struct alpha_elf_link_hash_entry *ah = (struct alpha_elf_link_hash_entry *)h;
-  bfd *dynobj = elf_hash_table(info)->dynobj;
 
   if (h->needs_plt)
     {
@@ -4765,9 +4817,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 = elf_hash_table (info)->splt;
       BFD_ASSERT (splt != NULL);
-      srel = bfd_get_section_by_name (dynobj, ".rela.plt");
+      srel = elf_hash_table (info)->srelplt;
       BFD_ASSERT (srel != NULL);
 
       for (gotent = ah->got_entries; gotent ; gotent = gotent->next)
@@ -4837,7 +4889,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 = elf_hash_table (info)->srelgot;
       BFD_ASSERT (srel != NULL);
 
       for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
@@ -4872,19 +4924,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;
@@ -4902,7 +4954,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)
     {
@@ -4910,8 +4962,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 = elf_hash_table (info)->splt;
+      srelaplt = elf_hash_table (info)->srelplt;
       BFD_ASSERT (splt != NULL && sdyn != NULL);
 
       plt_vma = splt->output_section->vma + splt->output_offset;
@@ -4919,7 +4971,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 = elf_hash_table (info)->sgotplt;
          BFD_ASSERT (sgotplt != NULL);
          if (sgotplt->size > 0)
            gotplt_vma = sgotplt->output_section->vma + sgotplt->output_offset;
@@ -4943,17 +4995,8 @@ elf64_alpha_finish_dynamic_sections (bfd *output_bfd,
              dyn.d_un.d_val = srelaplt ? srelaplt->size : 0;
              break;
            case DT_JMPREL:
-             dyn.d_un.d_ptr = srelaplt ? srelaplt->vma : 0;
-             break;
-
-           case DT_RELASZ:
-             /* My interpretation of the TIS v1.1 ELF document indicates
-                that RELASZ should not include JMPREL.  This is not what
-                the rest of the BFD does.  It is, however, what the
-                glibc ld.so wants.  Do this fixup here until we found
-                out who is right.  */
-             if (srelaplt)
-               dyn.d_un.d_val -= srelaplt->size;
+             dyn.d_un.d_ptr = srelaplt ? (srelaplt->output_section->vma
+                                          + srelaplt->output_offset) : 0;
              break;
            }
 
@@ -5086,7 +5129,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)
@@ -5190,7 +5233,7 @@ 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)
@@ -5237,7 +5280,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;
 
@@ -5295,7 +5338,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))
     {
@@ -5312,9 +5357,9 @@ elf64_alpha_reloc_type_class (const Elf_Internal_Rela *rela)
 \f
 static const struct bfd_elf_special_section elf64_alpha_special_sections[] =
 {
-  { STRING_COMMA_LEN (".sbss"),  -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
+  { STRING_COMMA_LEN (".sbss"),         -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
   { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
-  { NULL,                     0,  0, 0,            0 }
+  { NULL,                    0,  0, 0,            0 }
 };
 
 /* ECOFF swapping routines.  These are used when dealing with the
@@ -5394,7 +5439,7 @@ static const struct elf_size_info alpha_elf_size_info =
   bfd_elf64_swap_reloca_out
 };
 
-#define TARGET_LITTLE_SYM      bfd_elf64_alpha_vec
+#define TARGET_LITTLE_SYM      alpha_elf64_vec
 #define TARGET_LITTLE_NAME     "elf64-alpha"
 #define ELF_ARCH               bfd_arch_alpha
 #define ELF_TARGET_ID          ALPHA_ELF_DATA
@@ -5435,6 +5480,8 @@ static const struct elf_size_info alpha_elf_size_info =
   elf64_alpha_add_symbol_hook
 #define elf_backend_relocs_compatible \
   _bfd_elf_relocs_compatible
+#define elf_backend_sort_relocs_p \
+  elf64_alpha_sort_relocs_p
 #define elf_backend_check_relocs \
   elf64_alpha_check_relocs
 #define elf_backend_create_dynamic_sections \
@@ -5443,12 +5490,14 @@ 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 \
   elf64_alpha_size_dynamic_sections
 #define elf_backend_omit_section_dynsym \
-  ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
+  _bfd_elf_omit_section_dynsym_all
 #define elf_backend_relocate_section \
   elf64_alpha_relocate_section
 #define elf_backend_finish_dynamic_symbol \
@@ -5462,7 +5511,6 @@ static const struct elf_size_info alpha_elf_size_info =
 
 #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
@@ -5473,18 +5521,22 @@ static const struct elf_size_info alpha_elf_size_info =
 #define elf_backend_special_sections \
   elf64_alpha_special_sections
 
+#define elf_backend_strip_zero_sized_dynamic_sections \
+  _bfd_elf_strip_zero_sized_dynamic_sections
+
 /* A few constants that determine how the .plt section is set up.  */
 #define elf_backend_want_got_plt 0
 #define elf_backend_plt_readonly 0
 #define elf_backend_want_plt_sym 1
 #define elf_backend_got_header_size 0
+#define elf_backend_dtrel_excludes_plt 1
 
 #include "elf64-target.h"
 \f
 /* FreeBSD support.  */
 
 #undef TARGET_LITTLE_SYM
-#define TARGET_LITTLE_SYM      bfd_elf64_alpha_freebsd_vec
+#define TARGET_LITTLE_SYM      alpha_elf64_fbsd_vec
 #undef TARGET_LITTLE_NAME
 #define TARGET_LITTLE_NAME     "elf64-alpha-freebsd"
 #undef ELF_OSABI
@@ -5494,12 +5546,14 @@ static const struct elf_size_info alpha_elf_size_info =
    "FreeBSD" label in the ELF header.  So we put this label on all
    executables and (for simplicity) also all other object files.  */
 
-static void
-elf64_alpha_fbsd_post_process_headers (bfd * abfd,
-       struct bfd_link_info * link_info ATTRIBUTE_UNUSED)
+static bfd_boolean
+elf64_alpha_fbsd_init_file_header (bfd *abfd, struct bfd_link_info *info)
 {
   Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form.  */
 
+  if (!_bfd_elf_init_file_header (abfd, info))
+    return FALSE;
+
   i_ehdrp = elf_elfheader (abfd);
 
   /* Put an ABI label supported by FreeBSD >= 4.1.  */
@@ -5508,11 +5562,12 @@ elf64_alpha_fbsd_post_process_headers (bfd * abfd,
   /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard.  */
   memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8);
 #endif
+  return TRUE;
 }
 
-#undef elf_backend_post_process_headers
-#define elf_backend_post_process_headers \
-  elf64_alpha_fbsd_post_process_headers
+#undef elf_backend_init_file_header
+#define elf_backend_init_file_header \
+  elf64_alpha_fbsd_init_file_header
 
 #undef  elf64_bed
 #define elf64_bed elf64_alpha_fbsd_bed
This page took 0.055937 seconds and 4 git commands to generate.