daily update
[deliverable/binutils-gdb.git] / bfd / elf64-alpha.c
index 528476bdddf680256fa5edf566ab07fd91fc85ba..968e45c685a44317e50de2a7b6d1cf8e6913f465 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-2014 Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@tamu.edu>.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -210,7 +209,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 +223,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.  */
@@ -298,6 +297,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 +335,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 +368,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 +381,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 +433,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)
 {
@@ -1376,17 +1388,17 @@ elf64_alpha_read_ecoff_info (bfd *abfd, asection *section,
     }
 
   READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
-  READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR);
-  READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR);
-  READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR);
-  READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR);
+  READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *);
+  READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, void *);
+  READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, void *);
+  READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, void *);
   READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
        union aux_ext *);
   READ (ss, cbSsOffset, issMax, sizeof (char), char *);
   READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *);
-  READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR);
-  READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR);
-  READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, PTR);
+  READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, void *);
+  READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, void *);
+  READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, void *);
 #undef READ
 
   debug->fdr = NULL;
@@ -1429,17 +1441,6 @@ elf64_alpha_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, const char *name)
   return name[0] == '$';
 }
 
-/* Alpha ELF follows MIPS ELF in using a special find_nearest_line
-   routine in order to handle the ECOFF debugging information.  We
-   still call this mips_elf_find_line because of the slot
-   find_line_info in elf_obj_tdata is declared that way.  */
-
-struct mips_elf_find_line
-{
-  struct ecoff_debug_info d;
-  struct ecoff_find_line i;
-};
-
 static bfd_boolean
 elf64_alpha_find_nearest_line (bfd *abfd, asection *section, asymbol **symbols,
                               bfd_vma offset, const char **filename_ptr,
@@ -1451,7 +1452,7 @@ elf64_alpha_find_nearest_line (bfd *abfd, asection *section, asymbol **symbols,
   if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections,
                                      section, symbols, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr, 0,
+                                    line_ptr, NULL, 0,
                                     &elf_tdata (abfd)->dwarf2_find_line_info))
     return TRUE;
 
@@ -1459,7 +1460,7 @@ elf64_alpha_find_nearest_line (bfd *abfd, asection *section, asymbol **symbols,
   if (msec != NULL)
     {
       flagword origflags;
-      struct mips_elf_find_line *fi;
+      struct alpha_elf_find_line *fi;
       const struct ecoff_debug_swap * const swap =
        get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
 
@@ -1470,16 +1471,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;
@@ -1506,9 +1507,9 @@ elf64_alpha_find_nearest_line (bfd *abfd, asection *section, asymbol **symbols,
          fraw_end = (fraw_src
                      + fi->d.symbolic_header.ifdMax * external_fdr_size);
          for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
-           (*swap->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr);
+           (*swap->swap_fdr_in) (abfd, fraw_src, fdr_ptr);
 
-         elf_tdata (abfd)->find_line_info = fi;
+         alpha_elf_tdata (abfd)->find_line_info = fi;
 
          /* Note that we don't bother to ever free this information.
              find_nearest_line is either called all the time, as in
@@ -1548,7 +1549,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;
@@ -1809,6 +1810,9 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
                 || h->root.root.type == bfd_link_hash_warning)
            h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
 
+         /* PR15323, ref flags aren't set for references in the same
+            object.  */
+         h->root.root.non_ir_ref = 1;
          h->root.ref_regular = 1;
        }
 
@@ -2102,7 +2106,7 @@ elf64_alpha_adjust_dynamic_symbol (struct bfd_link_info *info,
     {
       h->needs_plt = TRUE;
 
-      s = bfd_get_section_by_name(dynobj, ".plt");
+      s = bfd_get_linker_section (dynobj, ".plt");
       if (!s && !elf64_alpha_create_dynamic_sections (dynobj, info))
        return FALSE;
 
@@ -2391,7 +2395,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;
 
@@ -2462,7 +2466,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;
@@ -2476,7 +2481,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;
 
@@ -2517,21 +2522,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;
+           }
        }
     }
 
@@ -2543,7 +2551,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;
@@ -2588,7 +2597,7 @@ elf64_alpha_size_plt_section (struct bfd_link_info *info)
     return;
 
   dynobj = elf_hash_table(info)->dynobj;
-  splt = bfd_get_section_by_name (dynobj, ".plt");
+  splt = bfd_get_linker_section (dynobj, ".plt");
   if (splt == NULL)
     return;
 
@@ -2598,7 +2607,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 = bfd_get_linker_section (dynobj, ".rela.plt");
   entries = 0;
   if (splt->size)
     {
@@ -2614,7 +2623,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 = bfd_get_linker_section (dynobj, ".got.plt");
       sgotplt->size = entries ? 16 : 0;
     }
 }
@@ -2633,7 +2642,7 @@ elf64_alpha_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   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.  */
@@ -2773,7 +2782,7 @@ elf64_alpha_size_rela_got_1 (struct alpha_elf_link_hash_entry *h,
   if (entries > 0)
     {
       bfd *dynobj = elf_hash_table(info)->dynobj;
-      asection *srel = bfd_get_section_by_name (dynobj, ".rela.got");
+      asection *srel = bfd_get_linker_section (dynobj, ".rela.got");
       BFD_ASSERT (srel != NULL);
       srel->size += sizeof (Elf64_External_Rela) * entries;
     }
@@ -2823,7 +2832,7 @@ elf64_alpha_size_rela_got_section (struct bfd_link_info *info)
     }
 
   dynobj = elf_hash_table(info)->dynobj;
-  srel = bfd_get_section_by_name (dynobj, ".rela.got");
+  srel = bfd_get_linker_section (dynobj, ".rela.got");
   if (!srel)
     {
       BFD_ASSERT (entries == 0);
@@ -2859,7 +2868,7 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       /* Set the contents of the .interp section to the interpreter.  */
       if (info->executable)
        {
-         s = bfd_get_section_by_name (dynobj, ".interp");
+         s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
          s->size = sizeof ELF_DYNAMIC_INTERPRETER;
          s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
@@ -3069,6 +3078,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;
@@ -3169,7 +3182,7 @@ elf64_alpha_relax_opt_call (struct alpha_relax_info *info, bfd_vma symval)
       else
        {
          tsec_relocs = (_bfd_elf_link_read_relocs
-                        (info->abfd, info->tsec, (PTR) NULL,
+                        (info->abfd, info->tsec, NULL,
                         (Elf_Internal_Rela *) NULL,
                         info->link_info->keep_memory));
          if (tsec_relocs == NULL)
@@ -3209,21 +3222,27 @@ 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,
+       abfd, info->sec,
        (unsigned long) irel->r_offset));
       return TRUE;
     }
@@ -3232,25 +3251,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)
        {
@@ -3262,6 +3288,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
@@ -3279,14 +3312,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.  */
@@ -3297,15 +3336,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;
@@ -3319,14 +3359,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:
@@ -3343,18 +3388,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)
@@ -3366,27 +3408,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
@@ -3398,14 +3445,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,
@@ -3414,12 +3461,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;
                      }
                  }
              }
@@ -3428,6 +3475,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)
@@ -3447,17 +3497,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
@@ -3583,7 +3635,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 && !info->link_info->shared))
     {
     case 1:
       {
@@ -3717,6 +3771,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,15 +3787,19 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
     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)
        {
@@ -3754,7 +3813,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;
@@ -3795,24 +3854,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.  */
@@ -4107,10 +4163,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)
@@ -4139,7 +4195,7 @@ 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)
     return elf64_alpha_relocate_section_r (output_bfd, info, input_bfd,
@@ -4154,7 +4210,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
   dynobj = elf_hash_table (info)->dynobj;
   if (dynobj)
-    srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+    srelgot = bfd_get_linker_section (dynobj, ".rela.got");
   else
     srelgot = NULL;
 
@@ -4165,7 +4221,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;
@@ -4213,6 +4269,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
       bfd_vma value;
       bfd_vma addend;
       bfd_boolean dynamic_symbol_p;
+      bfd_boolean unresolved_reloc = FALSE;
       bfd_boolean undef_weak_ref = FALSE;
       unsigned long r_type;
 
@@ -4264,7 +4321,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)
            {
@@ -4293,15 +4350,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;
@@ -4316,9 +4372,9 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *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;
@@ -4527,7 +4583,12 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
            else if (info->shared
                     && 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)
                  {
@@ -4573,7 +4634,11 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
          /* ??? .eh_frame references to discarded sections will be smashed
             to relocations against SHN_UNDEF.  The .eh_frame format allows
             NULL to be encoded as 0 in any format, so this works here.  */
-         if (r_symndx == 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;
@@ -4718,7 +4783,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)
@@ -4772,9 +4837,9 @@ elf64_alpha_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info,
 
       BFD_ASSERT (h->dynindx != -1);
 
-      splt = bfd_get_section_by_name (dynobj, ".plt");
+      splt = bfd_get_linker_section (dynobj, ".plt");
       BFD_ASSERT (splt != NULL);
-      srel = bfd_get_section_by_name (dynobj, ".rela.plt");
+      srel = bfd_get_linker_section (dynobj, ".rela.plt");
       BFD_ASSERT (srel != NULL);
 
       for (gotent = ah->got_entries; gotent ; gotent = gotent->next)
@@ -4844,7 +4909,7 @@ elf64_alpha_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info,
       asection *srel;
       struct alpha_elf_got_entry *gotent;
 
-      srel = bfd_get_section_by_name (dynobj, ".rela.got");
+      srel = bfd_get_linker_section (dynobj, ".rela.got");
       BFD_ASSERT (srel != NULL);
 
       for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
@@ -4879,19 +4944,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;
@@ -4909,7 +4974,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)
     {
@@ -4917,8 +4982,8 @@ elf64_alpha_finish_dynamic_sections (bfd *output_bfd,
       Elf64_External_Dyn *dyncon, *dynconend;
       bfd_vma plt_vma, gotplt_vma;
 
-      splt = bfd_get_section_by_name (dynobj, ".plt");
-      srelaplt = bfd_get_section_by_name (output_bfd, ".rela.plt");
+      splt = bfd_get_linker_section (dynobj, ".plt");
+      srelaplt = bfd_get_linker_section (output_bfd, ".rela.plt");
       BFD_ASSERT (splt != NULL && sdyn != NULL);
 
       plt_vma = splt->output_section->vma + splt->output_offset;
@@ -4926,7 +4991,7 @@ elf64_alpha_finish_dynamic_sections (bfd *output_bfd,
       gotplt_vma = 0;
       if (elf64_alpha_use_secureplt)
        {
-         sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
+         sgotplt = bfd_get_linker_section (dynobj, ".got.plt");
          BFD_ASSERT (sgotplt != NULL);
          if (sgotplt->size > 0)
            gotplt_vma = sgotplt->output_section->vma + sgotplt->output_offset;
@@ -5093,7 +5158,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)
@@ -5197,7 +5262,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)
@@ -5244,7 +5309,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;
 
@@ -5302,7 +5367,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))
     {
@@ -5401,7 +5468,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
@@ -5493,7 +5560,7 @@ static const struct elf_size_info alpha_elf_size_info =
 /* 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.057248 seconds and 4 git commands to generate.