bfd_error_handler bfd_vma and bfd_size_type args
[deliverable/binutils-gdb.git] / bfd / elf64-alpha.c
index b70505040f65c7cc87b1209f0f995655d3edd76c..3e88787c179bea52dbfe32509c3ca279d1c6bd2d 100644 (file)
@@ -1,7 +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, 2012
-   Free Software Foundation, Inc.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@tamu.edu>.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -488,8 +486,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 */
@@ -1107,7 +1105,15 @@ elf64_alpha_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, 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 (_("%B: unrecognised Alpha reloc number: %d"),
+                         abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      r_type = R_ALPHA_NONE;
+    }
   cache_ptr->howto = &elf64_alpha_howto_table[r_type];
 }
 
@@ -1222,7 +1228,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
@@ -1294,6 +1300,7 @@ 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);
+  elf_hash_table (info)->splt = s;
   if (s == NULL || ! bfd_set_section_alignment (abfd, s, 4))
     return FALSE;
 
@@ -1308,6 +1315,7 @@ 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);
+  elf_hash_table (info)->srelplt = s;
   if (s == NULL || ! bfd_set_section_alignment (abfd, s, 3))
     return FALSE;
 
@@ -1315,6 +1323,7 @@ elf64_alpha_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
     {
       flags = SEC_ALLOC | SEC_LINKER_CREATED;
       s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
+      elf_hash_table (info)->sgotplt = s;
       if (s == NULL || ! bfd_set_section_alignment (abfd, s, 3))
        return FALSE;
     }
@@ -1331,6 +1340,7 @@ 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))
     return FALSE;
@@ -1444,17 +1454,19 @@ elf64_alpha_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, const char *name)
 }
 
 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, dwarf_debug_sections,
-                                     section, symbols, offset,
+  if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr, NULL, 0,
+                                    line_ptr, discriminator_ptr,
+                                    dwarf_debug_sections, 0,
                                     &elf_tdata (abfd)->dwarf2_find_line_info))
     return TRUE;
 
@@ -1534,9 +1546,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.  */
@@ -1750,6 +1762,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
@@ -1763,7 +1787,7 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
   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.
@@ -1814,7 +1838,7 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
          /* PR15323, ref flags aren't set for references in the same
             object.  */
-         h->root.root.non_ir_ref = 1;
+         h->root.root.non_ir_ref_regular = 1;
          h->root.ref_regular = 1;
        }
 
@@ -1823,7 +1847,7 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
          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
@@ -1864,7 +1888,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;
 
@@ -1884,12 +1908,12 @@ 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 && !info->pie)
+         if (bfd_link_dll (info))
            {
              info->flags |= DF_STATIC_TLS;
              need = NEED_DYNREL;
@@ -1981,7 +2005,7 @@ 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.  */
@@ -2026,7 +2050,7 @@ elf64_alpha_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
   struct alpha_elf_link_hash_entry **sym_hashes;
   const Elf_Internal_Rela *rel, *relend;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   symtab_hdr = &elf_symtab_hdr (abfd);
@@ -2108,7 +2132,7 @@ elf64_alpha_adjust_dynamic_symbol (struct bfd_link_info *info,
     {
       h->needs_plt = TRUE;
 
-      s = bfd_get_linker_section (dynobj, ".plt");
+      s = elf_hash_table(info)->splt;
       if (!s && !elf64_alpha_create_dynamic_sections (dynobj, info))
        return FALSE;
 
@@ -2199,7 +2223,7 @@ elf64_alpha_copy_indirect_symbol (struct bfd_link_info *info,
                && gi->reloc_type == gs->reloc_type
                && gi->addend == gs->addend)
              {
-               gi->use_count += gs->use_count;
+               gs->use_count += gi->use_count;
                goto got_found;
              }
          gi->next = hs->got_entries;
@@ -2468,7 +2492,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;
@@ -2482,7 +2507,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;
 
@@ -2499,7 +2524,8 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info)
           if (alpha_elf_tdata (this_got)->total_got_size > MAX_GOT_SIZE)
            {
              /* Yikes! A single object file has too many entries.  */
-             (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                (_("%B: .got subsegment exceeds 64K (size %d)"),
                 i, alpha_elf_tdata (this_got)->total_got_size);
              return FALSE;
@@ -2523,21 +2549,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;
+           }
        }
     }
 
@@ -2587,15 +2616,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_linker_section (dynobj, ".plt");
+  splt = elf_hash_table(info)->splt;
   if (splt == NULL)
     return;
 
@@ -2605,7 +2632,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_linker_section (dynobj, ".rela.plt");
+  spltrel = elf_hash_table(info)->srelplt;
   entries = 0;
   if (splt->size)
     {
@@ -2621,7 +2648,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_linker_section (dynobj, ".got.plt");
+      sgotplt = elf_hash_table(info)->sgotplt;
       sgotplt->size = entries ? 16 : 0;
     }
 }
@@ -2633,14 +2660,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;
 
-  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.  */
@@ -2724,14 +2751,15 @@ 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, info->pie);
+                                                bfd_link_pic (info),
+                                                bfd_link_pie (info));
       if (entries)
        {
          relent->srel->size +=
@@ -2767,7 +2795,7 @@ 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;
 
@@ -2775,12 +2803,12 @@ elf64_alpha_size_rela_got_1 (struct alpha_elf_link_hash_entry *h,
   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, info->pie);
+                                                 bfd_link_pic (info),
+                                                 bfd_link_pie (info));
 
   if (entries > 0)
     {
-      bfd *dynobj = elf_hash_table(info)->dynobj;
-      asection *srel = bfd_get_linker_section (dynobj, ".rela.got");
+      asection *srel = elf_hash_table(info)->srelgot;
       BFD_ASSERT (srel != NULL);
       srel->size += sizeof (Elf64_External_Rela) * entries;
     }
@@ -2794,7 +2822,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;
 
@@ -2825,12 +2853,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, info->pie));
+                           (gotent->reloc_type, 0, bfd_link_pic (info),
+                            bfd_link_pie (info)));
        }
     }
 
-  dynobj = elf_hash_table(info)->dynobj;
-  srel = bfd_get_linker_section (dynobj, ".rela.got");
+  srel = elf_hash_table(info)->srelgot;
   if (!srel)
     {
       BFD_ASSERT (entries == 0);
@@ -2851,7 +2879,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);
@@ -2864,7 +2892,7 @@ 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_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
@@ -2888,6 +2916,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;
@@ -2905,6 +2934,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.  */
@@ -2950,7 +2981,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;
@@ -2969,15 +3000,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
@@ -3045,10 +3079,10 @@ 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 */
+       (_("%B: %A+%#Lx: warning: %s relocation against unexpected insn"),
+        info->abfd, info->sec, irel->r_offset, howto->name);
       return TRUE;
     }
 
@@ -3058,7 +3092,7 @@ elf64_alpha_relax_got_load (struct alpha_relax_info *info, bfd_vma symval,
 
   /* Can't use local-exec relocations in shared libraries.  */
   if (r_type == R_ALPHA_GOTTPREL
-      && (info->link_info->shared && !info->link_info->pie))
+      && bfd_link_dll (info->link_info))
     return TRUE;
 
   if (r_type == R_ALPHA_LITERAL)
@@ -3066,7 +3100,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;
@@ -3076,6 +3110,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;
@@ -3182,7 +3220,9 @@ elf64_alpha_relax_opt_call (struct alpha_relax_info *info, bfd_vma symval)
          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.  */
@@ -3216,22 +3256,28 @@ 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 */
+       (_("%B: %A+%#Lx: warning: LITERAL relocation against unexpected insn"),
+        abfd, info->sec, irel->r_offset);
       return TRUE;
     }
 
@@ -3239,25 +3285,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)
        {
@@ -3269,6 +3322,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
@@ -3286,14 +3346,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.  */
@@ -3304,15 +3370,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;
@@ -3326,14 +3393,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:
@@ -3350,18 +3422,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)
@@ -3373,27 +3442,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
@@ -3405,14 +3479,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,
@@ -3421,12 +3495,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;
                      }
                  }
              }
@@ -3435,6 +3509,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)
@@ -3454,17 +3531,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
@@ -3486,12 +3565,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
@@ -3590,7 +3669,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;
 
-  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:
       {
@@ -3724,6 +3805,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)
@@ -3732,22 +3814,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)
        {
@@ -3802,24 +3888,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)
-       {
-       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;
+      if (r_type != R_ALPHA_LITERAL)
+        {
+          /* 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.  */
@@ -4077,7 +4160,8 @@ 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)
+         _bfd_error_handler
+           /* xgettext:c-format */
            (_("%B: unknown relocation type %d"),
             input_bfd, (int) r_type);
          bfd_set_error (bfd_error_bad_value);
@@ -4148,7 +4232,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
   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);
@@ -4160,10 +4244,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_linker_section (dynobj, ".rela.got");
-  else
-    srelgot = NULL;
+  srelgot = elf_hash_table (info)->srelgot;
 
   if (input_section->flags & SEC_ALLOC)
     {
@@ -4227,7 +4308,8 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
       r_type = ELF64_R_TYPE(rel->r_info);
       if (r_type >= R_ALPHA_max)
        {
-         (*_bfd_error_handler)
+         _bfd_error_handler
+           /* xgettext:c-format */
            (_("%B: unknown relocation type %d"),
             input_bfd, (int) r_type);
          bfd_set_error (bfd_error_bad_value);
@@ -4301,14 +4383,14 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        }
       else
        {
-         bfd_boolean warned;
+         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;
@@ -4373,7 +4455,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);
@@ -4390,7 +4474,8 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        case R_ALPHA_GPRELLOW:
          if (dynamic_symbol_p)
             {
-              (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                 (_("%B: gp-relative relocation against dynamic symbol %s"),
                  input_bfd, h->root.root.root.string);
               ret_val = FALSE;
@@ -4402,7 +4487,8 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        case R_ALPHA_GPRELHIGH:
          if (dynamic_symbol_p)
             {
-              (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                 (_("%B: gp-relative relocation against dynamic symbol %s"),
                  input_bfd, h->root.root.root.string);
               ret_val = FALSE;
@@ -4428,7 +4514,8 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        case R_ALPHA_BRADDR:
          if (dynamic_symbol_p)
             {
-              (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                 (_("%B: pc-relative relocation against dynamic symbol %s"),
                  input_bfd, h->root.root.root.string);
               ret_val = FALSE;
@@ -4456,7 +4543,8 @@ 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)
+               _bfd_error_handler
+                 /* xgettext:c-format */
                  (_("%B: change in gp: BRSGP %s"),
                   input_bfd, h->root.root.root.string);
                ret_val = FALSE;
@@ -4486,7 +4574,8 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                    else if (name[0] == 0)
                      name = bfd_section_name (input_bfd, sec);
                  }
-               (*_bfd_error_handler)
+               _bfd_error_handler
+                 /* xgettext:c-format */
                  (_("%B: !samegp reloc against symbol without .prologue: %s"),
                   input_bfd, name);
                ret_val = FALSE;
@@ -4523,7 +4612,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 || info->pie)
+               if (!bfd_link_dll (info))
                  {
                    value -= tp_base;
                    goto default_reloc;
@@ -4531,7 +4620,7 @@ 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
@@ -4543,7 +4632,8 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
              {
                if (r_type == R_ALPHA_REFLONG)
                  {
-                   (*_bfd_error_handler)
+                   _bfd_error_handler
+                     /* xgettext:c-format */
                      (_("%B: unhandled dynamic relocation against %s"),
                       input_bfd,
                       h->root.root.root.string);
@@ -4568,14 +4658,17 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        case R_ALPHA_SREL64:
          if (dynamic_symbol_p)
             {
-              (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                 (_("%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)
+         else if (bfd_link_pic (info)
+                  && undef_weak_ref)
             {
-              (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                 (_("%B: pc-relative relocation against undefined weak symbol %s"),
                  input_bfd, h->root.root.root.string);
               ret_val = FALSE;
@@ -4606,13 +4699,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);
@@ -4639,7 +4733,8 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        case R_ALPHA_DTPREL16:
          if (dynamic_symbol_p)
             {
-              (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                 (_("%B: dtp-relative relocation against dynamic symbol %s"),
                  input_bfd, h->root.root.root.string);
               ret_val = FALSE;
@@ -4653,16 +4748,18 @@ 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 && !info->pie)
+         if (bfd_link_dll (info))
            {
-             (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                (_("%B: TLS local exec code cannot be linked into shared objects"),
                input_bfd);
               ret_val = FALSE;
            }
          else if (dynamic_symbol_p)
             {
-              (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                 (_("%B: tp-relative relocation against dynamic symbol %s"),
                  input_bfd, h->root.root.root.string);
               ret_val = FALSE;
@@ -4691,7 +4788,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_pic (info))
                    value -= tp_base;
                  else
                    {
@@ -4748,11 +4845,9 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                if (*name == '\0')
                  name = bfd_section_name (input_bfd, 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;
 
@@ -4774,7 +4869,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)
     {
@@ -4788,9 +4882,9 @@ elf64_alpha_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info,
 
       BFD_ASSERT (h->dynindx != -1);
 
-      splt = bfd_get_linker_section (dynobj, ".plt");
+      splt = elf_hash_table (info)->splt;
       BFD_ASSERT (splt != NULL);
-      srel = bfd_get_linker_section (dynobj, ".rela.plt");
+      srel = elf_hash_table (info)->srelplt;
       BFD_ASSERT (srel != NULL);
 
       for (gotent = ah->got_entries; gotent ; gotent = gotent->next)
@@ -4860,7 +4954,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_linker_section (dynobj, ".rela.got");
+      srel = elf_hash_table (info)->srelgot;
       BFD_ASSERT (srel != NULL);
 
       for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
@@ -4933,8 +5027,8 @@ elf64_alpha_finish_dynamic_sections (bfd *output_bfd,
       Elf64_External_Dyn *dyncon, *dynconend;
       bfd_vma plt_vma, gotplt_vma;
 
-      splt = bfd_get_linker_section (dynobj, ".plt");
-      srelaplt = bfd_get_linker_section (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;
@@ -4942,7 +5036,7 @@ elf64_alpha_finish_dynamic_sections (bfd *output_bfd,
       gotplt_vma = 0;
       if (elf64_alpha_use_secureplt)
        {
-         sgotplt = bfd_get_linker_section (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;
@@ -4966,17 +5060,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;
            }
 
@@ -5419,7 +5504,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
@@ -5460,6 +5545,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 \
@@ -5505,13 +5592,14 @@ static const struct elf_size_info alpha_elf_size_info =
 #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
This page took 0.04291 seconds and 4 git commands to generate.