* elf64-alpha.c (elf64_alpha_relax_section): Ignore non-allocated
[external/binutils.git] / bfd / elf64-alpha.c
index a3f81eb..5a5c736 100644 (file)
@@ -1,5 +1,5 @@
 /* Alpha specific support for 64-bit ELF
-   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@tamu.edu>.
 
@@ -17,7 +17,7 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 /* We need a published ABI spec for this.  Until one comes out, don't
    assume this'll remain unchanged forever.  */
@@ -72,10 +72,8 @@ static bfd_boolean elf64_alpha_mkobject
   PARAMS ((bfd *));
 static bfd_boolean elf64_alpha_object_p
   PARAMS ((bfd *));
-static bfd_boolean elf64_alpha_section_from_shdr
-  PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
 static bfd_boolean elf64_alpha_section_flags
-  PARAMS ((flagword *, Elf_Internal_Shdr *));
+  PARAMS ((flagword *, const Elf_Internal_Shdr *));
 static bfd_boolean elf64_alpha_fake_sections
   PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
 static bfd_boolean elf64_alpha_create_got_section
@@ -123,7 +121,7 @@ static bfd_boolean elf64_alpha_size_rela_got_section
 static bfd_boolean elf64_alpha_size_rela_got_1
   PARAMS ((struct alpha_elf_link_hash_entry *, struct bfd_link_info *));
 static bfd_boolean elf64_alpha_add_symbol_hook
-  PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
+  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Sym *,
           const char **, flagword *, asection **, bfd_vma *));
 static struct alpha_elf_got_entry *get_got_entry
   PARAMS ((bfd *, struct alpha_elf_link_hash_entry *, unsigned long,
@@ -393,15 +391,6 @@ static bfd_boolean
 elf64_alpha_object_p (abfd)
      bfd *abfd;
 {
-  /* Allocate our special target data.  */
-  struct alpha_elf_obj_tdata *new_tdata;
-  bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata);
-  new_tdata = bfd_zalloc (abfd, amt);
-  if (new_tdata == NULL)
-    return FALSE;
-  new_tdata->root = *abfd->tdata.elf_obj_data;
-  abfd->tdata.any = new_tdata;
-
   /* Set the right machine number for an Alpha ELF file.  */
   return bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0);
 }
@@ -1045,6 +1034,7 @@ elf64_alpha_reloc_gpdisp (abfd, reloc_entry, sym, data, input_section,
 {
   bfd_reloc_status_type ret;
   bfd_vma gp, relocation;
+  bfd_vma high_address;
   bfd_byte *p_ldah, *p_lda;
 
   /* Don't do anything if we're not doing a final link.  */
@@ -1054,8 +1044,9 @@ elf64_alpha_reloc_gpdisp (abfd, reloc_entry, sym, data, input_section,
       return bfd_reloc_ok;
     }
 
-  if (reloc_entry->address > input_section->_cooked_size ||
-      reloc_entry->address + reloc_entry->addend > input_section->_cooked_size)
+  high_address = bfd_get_section_limit (abfd, input_section);
+  if (reloc_entry->address > high_address
+      || reloc_entry->address + reloc_entry->addend > high_address)
     return bfd_reloc_outofrange;
 
   /* The gp used in the portion of the output object to which this
@@ -1158,13 +1149,15 @@ elf64_alpha_info_to_howto (abfd, cache_ptr, dst)
   (r_type == R_ALPHA_TLSGD || r_type == R_ALPHA_TLSLDM ? 16 : 8)
 
 /* This is PT_TLS segment p_vaddr.  */
-#define alpha_get_dtprel_base(tlss) \
-  ((tlss)->start)
+#define alpha_get_dtprel_base(info) \
+  (elf_hash_table (info)->tls_sec->vma)
 
 /* Main program TLS (whose template starts at PT_TLS p_vaddr)
    is assigned offset round(16, PT_TLS p_align).  */
-#define alpha_get_tprel_base(tlss) \
-  ((tlss)->start - align_power ((bfd_vma) 16, (tlss)->align))
+#define alpha_get_tprel_base(info) \
+  (elf_hash_table (info)->tls_sec->vma                                 \
+   - align_power ((bfd_vma) 16,                                                \
+                 elf_hash_table (info)->tls_sec->alignment_power))
 \f
 /* These functions do relaxation for Alpha ELF.
 
@@ -1198,7 +1191,6 @@ struct alpha_relax_info
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Rela *relocs, *relend;
   struct bfd_link_info *link_info;
-  struct elf_link_tls_segment *tls_segment;
   bfd_vma gp;
   bfd *gotobj;
   asection *tsec;
@@ -1224,8 +1216,6 @@ static bfd_boolean elf64_alpha_relax_gprelhilo
 static bfd_boolean elf64_alpha_relax_tls_get_addr
   PARAMS((struct alpha_relax_info *info, bfd_vma symval,
           Elf_Internal_Rela *irel, bfd_boolean));
-static struct elf_link_tls_segment *elf64_alpha_relax_find_tls_segment
-  PARAMS((struct alpha_relax_info *, struct elf_link_tls_segment *));
 static bfd_boolean elf64_alpha_relax_section
   PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
          bfd_boolean *again));
@@ -1265,8 +1255,8 @@ elf64_alpha_relax_with_lituse (info, symval, irel)
   if (lit_insn >> 26 != OP_LDQ)
     {
       ((*_bfd_error_handler)
-       ("%s: %s+0x%lx: warning: LITERAL relocation against unexpected insn",
-       bfd_archive_filename (info->abfd), info->sec->name,
+       ("%B: %A+0x%lx: warning: LITERAL relocation against unexpected insn",
+       info->abfd, info->sec,
        (unsigned long) irel->r_offset));
       return TRUE;
     }
@@ -1310,9 +1300,7 @@ elf64_alpha_relax_with_lituse (info, symval, irel)
          /* Extract the displacement from the instruction, sign-extending
             it if necessary, then test whether it is within 16 or 32 bits
             displacement from GP.  */
-         insn_disp = insn & 0x0000ffff;
-         if (insn_disp & 0x8000)
-           insn_disp |= ~0xffff;  /* Negative: sign-extend.  */
+         insn_disp = ((insn & 0xffff) ^ 0x8000) - 0x8000;
 
          xdisp = disp + insn_disp;
          fits16 = (xdisp >= - (bfd_signed_vma) 0x8000 && xdisp < 0x8000);
@@ -1381,6 +1369,19 @@ elf64_alpha_relax_with_lituse (info, symval, irel)
            bfd_vma optdest, org;
            bfd_signed_vma odisp;
 
+           /* For undefined weak symbols, we're mostly interested in getting
+              rid of the got entry whenever possible, so optimize this to a
+              use of the zero register.  */
+           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);
+
+               info->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
@@ -1484,9 +1485,11 @@ elf64_alpha_relax_with_lituse (info, symval, irel)
                      info->contents + irel->r_offset);
          info->changed_contents = TRUE;
        }
-    }
 
-  return TRUE;
+      return TRUE;
+    }
+  else
+    return elf64_alpha_relax_got_load (info, symval, irel, R_ALPHA_LITERAL);
 }
 
 static bfd_vma
@@ -1578,8 +1581,8 @@ elf64_alpha_relax_got_load (info, symval, irel, r_type)
     {
       reloc_howto_type *howto = elf64_alpha_howto_table + r_type;
       ((*_bfd_error_handler)
-       ("%s: %s+0x%lx: warning: %s relocation against unexpected insn",
-       bfd_archive_filename (info->abfd), info->sec->name,
+       ("%B: %A+0x%lx: warning: %s relocation against unexpected insn",
+       info->abfd, info->sec,
        (unsigned long) irel->r_offset, howto->name));
       return TRUE;
     }
@@ -1593,26 +1596,53 @@ elf64_alpha_relax_got_load (info, symval, irel, r_type)
     return TRUE;
 
   if (r_type == R_ALPHA_LITERAL)
-    disp = symval - info->gp;
+    {
+      /* 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
+             && (symval >= (bfd_vma)-0x8000 || symval < 0x8000)))
+       {
+         disp = 0;
+         insn = (OP_LDA << 26) | (insn & (31 << 21)) | (31 << 16);
+         insn |= (symval & 0xffff);
+         r_type = R_ALPHA_NONE;
+       }
+      else
+       {
+         disp = symval - info->gp;
+         insn = (OP_LDA << 26) | (insn & 0x03ff0000);
+         r_type = R_ALPHA_GPREL16;
+       }
+    }
   else
     {
       bfd_vma dtp_base, tp_base;
 
-      BFD_ASSERT (info->tls_segment != NULL);
-      dtp_base = alpha_get_dtprel_base (info->tls_segment);
-      tp_base = alpha_get_tprel_base (info->tls_segment);
+      BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL);
+      dtp_base = alpha_get_dtprel_base (info->link_info);
+      tp_base = alpha_get_tprel_base (info->link_info);
       disp = symval - (r_type == R_ALPHA_GOTDTPREL ? dtp_base : tp_base);
+
+      insn = (OP_LDA << 26) | (insn & (31 << 21)) | (31 << 16);
+
+      switch (r_type)
+       {
+       case R_ALPHA_GOTDTPREL:
+         r_type = R_ALPHA_DTPREL16;
+         break;
+       case R_ALPHA_GOTTPREL:
+         r_type = R_ALPHA_TPREL16;
+         break;
+       default:
+         BFD_ASSERT (0);
+         return FALSE;
+       }
     }
 
   if (disp < -0x8000 || disp >= 0x8000)
     return TRUE;
 
-  /* Exchange LDQ for LDA.  In the case of the TLS relocs, we're loading
-     a constant, so force the base register to be $31.  */
-  if (r_type == R_ALPHA_LITERAL)
-    insn = (OP_LDA << 26) | (insn & 0x03ff0000);
-  else
-    insn = (OP_LDA << 26) | (insn & (31 << 21)) | (31 << 16);
   bfd_put_32 (info->abfd, (bfd_vma) insn, info->contents + irel->r_offset);
   info->changed_contents = TRUE;
 
@@ -1627,22 +1657,6 @@ elf64_alpha_relax_got_load (info, symval, irel, r_type)
     }
 
   /* Smash the existing GOT relocation for its 16-bit immediate pair.  */
-  switch (r_type)
-    {
-    case R_ALPHA_LITERAL:
-      r_type = R_ALPHA_GPREL16;
-      break;
-    case R_ALPHA_GOTDTPREL:
-      r_type = R_ALPHA_DTPREL16;
-      break;
-    case R_ALPHA_GOTTPREL:
-      r_type = R_ALPHA_TPREL16;
-      break;
-    default:
-      BFD_ASSERT (0);
-      return FALSE;
-    }
-
   irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), r_type);
   info->changed_relocs = TRUE;
 
@@ -1845,8 +1859,8 @@ elf64_alpha_relax_tls_get_addr (info, symval, irel, is_gd)
        bfd_vma tp_base;
        bfd_signed_vma disp;
 
-       BFD_ASSERT (info->tls_segment != NULL);
-       tp_base = alpha_get_tprel_base (info->tls_segment);
+       BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL);
+       tp_base = alpha_get_tprel_base (info->link_info);
        disp = symval - tp_base;
 
        if (disp >= -0x8000 && disp < 0x8000)
@@ -1961,53 +1975,6 @@ elf64_alpha_relax_tls_get_addr (info, symval, irel, is_gd)
   return TRUE;
 }
 
-static struct elf_link_tls_segment *
-elf64_alpha_relax_find_tls_segment (info, seg)
-     struct alpha_relax_info *info;
-     struct elf_link_tls_segment *seg;
-{
-  bfd *output_bfd = info->sec->output_section->owner;
-  asection *o;
-  unsigned int align;
-  bfd_vma base, end;
-
-  for (o = output_bfd->sections; o ; o = o->next)
-    if ((o->flags & SEC_THREAD_LOCAL) != 0
-        && (o->flags & SEC_LOAD) != 0)
-      break;
-  if (!o)
-    return NULL;
-
-  base = o->vma;
-  align = 0;
-
-  do
-    {
-      bfd_vma size;
-
-      if (bfd_get_section_alignment (output_bfd, o) > align)
-       align = bfd_get_section_alignment (output_bfd, o);
-
-      size = o->_raw_size;
-      if (size == 0 && (o->flags & SEC_HAS_CONTENTS) == 0)
-       {
-         struct bfd_link_order *lo;
-         for (lo = o->link_order_head; lo ; lo = lo->next)
-           if (size < lo->offset + lo->size)
-             size = lo->offset + lo->size;
-       }
-      end = o->vma + size;
-      o = o->next;
-    }
-  while (o && (o->flags & SEC_THREAD_LOCAL));
-
-  seg->start = base;
-  seg->size = end - base;
-  seg->align = align;
-
-  return seg;
-}
-
 static bfd_boolean
 elf64_alpha_relax_section (abfd, sec, link_info, again)
      bfd *abfd;
@@ -2021,21 +1988,16 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
   Elf_Internal_Sym *isymbuf = NULL;
   struct alpha_elf_got_entry **local_got_entries;
   struct alpha_relax_info info;
-  struct elf_link_tls_segment tls_segment;
 
   /* We are not currently changing any sizes, so only one pass.  */
   *again = FALSE;
 
   if (link_info->relocatable
-      || (sec->flags & SEC_RELOC) == 0
+      || ((sec->flags & (SEC_CODE | SEC_RELOC | SEC_ALLOC))
+         != (SEC_CODE | SEC_RELOC | SEC_ALLOC))
       || sec->reloc_count == 0)
     return TRUE;
 
-  /* If this is the first time we have been called for this section,
-     initialize the cooked size.  */
-  if (sec->_cooked_size == 0)
-    sec->_cooked_size = sec->_raw_size;
-
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
 
@@ -2070,20 +2032,10 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
     info.contents = elf_section_data (sec)->this_hdr.contents;
   else
     {
-      info.contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
-      if (info.contents == NULL)
-       goto error_return;
-
-      if (! bfd_get_section_contents (abfd, sec, info.contents,
-                                     (file_ptr) 0, sec->_raw_size))
+      if (!bfd_malloc_and_get_section (abfd, sec, &info.contents))
        goto error_return;
     }
 
-  /* Compute the TLS segment information.  The version normally found in
-     elf_hash_table (link_info)->tls_segment isn't built until final_link.
-     ??? Probably should look into extracting this into a common function.  */
-  info.tls_segment = elf64_alpha_relax_find_tls_segment (&info, &tls_segment);
-
   for (irel = internal_relocs; irel < irelend; irel++)
     {
       bfd_vma symval;
@@ -2137,7 +2089,7 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
          if (r_type == R_ALPHA_TLSLDM)
            {
              info.tsec = bfd_abs_section_ptr;
-             symval = alpha_get_tprel_base (info.tls_segment);
+             symval = alpha_get_tprel_base (info.link_info);
            }
          else
            {
@@ -2176,13 +2128,17 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
            h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
 
          /* If the symbol is undefined, we can't do anything with it.  */
-         if (h->root.root.type == bfd_link_hash_undefweak
-             || h->root.root.type == bfd_link_hash_undefined)
+         if (h->root.root.type == bfd_link_hash_undefined)
            continue;
 
-         /* If the symbol isn't defined in the current module, again
-            we can't do anything.  */
-         if (!(h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
+         /* If the symbol isn't defined in the current module,
+            again we can't do anything.  */
+         if (h->root.root.type == bfd_link_hash_undefweak)
+           {
+             info.tsec = bfd_abs_section_ptr;
+             symval = 0;
+           }
+         else if (!h->root.def_regular)
            {
              /* Except for TLSGD relocs, which can sometimes be
                 relaxed to GOTTPREL relocs.  */
@@ -2331,15 +2287,16 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
 #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so"
 \f
 /* Handle an Alpha specific section when reading an object file.  This
-   is called when elfcode.h finds a section with an unknown type.
+   is called when bfd_section_from_shdr finds a section with an unknown
+   type.
    FIXME: We need to handle the SHF_ALPHA_GPREL flag, but I'm not sure
    how to.  */
 
 static bfd_boolean
-elf64_alpha_section_from_shdr (abfd, hdr, name)
-     bfd *abfd;
-     Elf_Internal_Shdr *hdr;
-     const char *name;
+elf64_alpha_section_from_shdr (bfd *abfd,
+                              Elf_Internal_Shdr *hdr,
+                              const char *name,
+                              int shindex)
 {
   asection *newsect;
 
@@ -2358,7 +2315,7 @@ elf64_alpha_section_from_shdr (abfd, hdr, name)
       return FALSE;
     }
 
-  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
     return FALSE;
   newsect = hdr->bfd_section;
 
@@ -2378,7 +2335,7 @@ elf64_alpha_section_from_shdr (abfd, hdr, name)
 static bfd_boolean
 elf64_alpha_section_flags (flags, hdr)
      flagword *flags;
-     Elf_Internal_Shdr *hdr;
+     const Elf_Internal_Shdr *hdr;
 {
   if (hdr->sh_flags & SHF_ALPHA_GPREL)
     *flags |= SEC_SMALL_DATA;
@@ -2426,7 +2383,7 @@ static bfd_boolean
 elf64_alpha_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
      bfd *abfd;
      struct bfd_link_info *info;
-     const Elf_Internal_Sym *sym;
+     Elf_Internal_Sym *sym;
      const char **namep ATTRIBUTE_UNUSED;
      flagword *flagsp ATTRIBUTE_UNUSED;
      asection **secp;
@@ -2443,11 +2400,11 @@ elf64_alpha_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
 
       if (scomm == NULL)
        {
-         scomm = bfd_make_section (abfd, ".scommon");
-         if (scomm == NULL
-             || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC
-                                                      | SEC_IS_COMMON
-                                                      | SEC_LINKER_CREATED)))
+         scomm = bfd_make_section_with_flags (abfd, ".scommon",
+                                              (SEC_ALLOC
+                                               | SEC_IS_COMMON
+                                               | SEC_LINKER_CREATED));
+         if (scomm == NULL)
            return FALSE;
        }
 
@@ -2475,12 +2432,11 @@ elf64_alpha_create_got_section(abfd, info)
       return TRUE;
     }
 
-  s = bfd_make_section (abfd, ".got");
+  s = bfd_make_section_with_flags (abfd, ".got", (SEC_ALLOC | SEC_LOAD
+                                                 | SEC_HAS_CONTENTS
+                                                 | SEC_IN_MEMORY
+                                                 | SEC_LINKER_CREATED));
   if (s == NULL
-      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
-                                          | SEC_HAS_CONTENTS
-                                          | SEC_IN_MEMORY
-                                          | SEC_LINKER_CREATED))
       || !bfd_set_section_alignment (abfd, s, 3))
     return FALSE;
 
@@ -2502,13 +2458,13 @@ elf64_alpha_create_dynamic_sections (abfd, info)
 
   /* We need to create .plt, .rela.plt, .got, and .rela.got sections.  */
 
-  s = bfd_make_section (abfd, ".plt");
+  s = bfd_make_section_with_flags (abfd, ".plt",
+                                  (SEC_ALLOC | SEC_LOAD
+                                   | SEC_HAS_CONTENTS
+                                   | SEC_IN_MEMORY
+                                   | SEC_LINKER_CREATED
+                                   | SEC_CODE));
   if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
-                                           | SEC_HAS_CONTENTS
-                                           | SEC_IN_MEMORY
-                                           | SEC_LINKER_CREATED
-                                           | SEC_CODE))
       || ! bfd_set_section_alignment (abfd, s, 3))
     return FALSE;
 
@@ -2521,20 +2477,20 @@ elf64_alpha_create_dynamic_sections (abfd, info)
          get_elf_backend_data (abfd)->collect, &bh)))
     return FALSE;
   h = (struct elf_link_hash_entry *) bh;
-  h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+  h->def_regular = 1;
   h->type = STT_OBJECT;
 
   if (info->shared
-      && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+      && ! bfd_elf_link_record_dynamic_symbol (info, h))
     return FALSE;
 
-  s = bfd_make_section (abfd, ".rela.plt");
+  s = bfd_make_section_with_flags (abfd, ".rela.plt",
+                                  (SEC_ALLOC | SEC_LOAD
+                                   | SEC_HAS_CONTENTS
+                                   | SEC_IN_MEMORY
+                                   | SEC_LINKER_CREATED
+                                   | SEC_READONLY));
   if (s == NULL
-      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
-                                          | SEC_HAS_CONTENTS
-                                          | SEC_IN_MEMORY
-                                          | SEC_LINKER_CREATED
-                                          | SEC_READONLY))
       || ! bfd_set_section_alignment (abfd, s, 3))
     return FALSE;
 
@@ -2544,13 +2500,13 @@ elf64_alpha_create_dynamic_sections (abfd, info)
   if (!elf64_alpha_create_got_section (abfd, info))
     return FALSE;
 
-  s = bfd_make_section(abfd, ".rela.got");
+  s = bfd_make_section_with_flags (abfd, ".rela.got",
+                                  (SEC_ALLOC | SEC_LOAD
+                                   | SEC_HAS_CONTENTS
+                                   | SEC_IN_MEMORY
+                                   | SEC_LINKER_CREATED
+                                   | SEC_READONLY));
   if (s == NULL
-      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
-                                          | SEC_HAS_CONTENTS
-                                          | SEC_IN_MEMORY
-                                          | SEC_LINKER_CREATED
-                                          | SEC_READONLY))
       || !bfd_set_section_alignment (abfd, s, 3))
     return FALSE;
 
@@ -2565,11 +2521,11 @@ elf64_alpha_create_dynamic_sections (abfd, info)
         FALSE, get_elf_backend_data (abfd)->collect, &bh)))
     return FALSE;
   h = (struct elf_link_hash_entry *) bh;
-  h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+  h->def_regular = 1;
   h->type = STT_OBJECT;
 
   if (info->shared
-      && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+      && ! bfd_elf_link_record_dynamic_symbol (info, h))
     return FALSE;
 
   elf_hash_table (info)->hgot = h;
@@ -2635,7 +2591,6 @@ elf64_alpha_read_ecoff_info (abfd, section, debug)
 #undef READ
 
   debug->fdr = NULL;
-  debug->adjust = NULL;
 
   return TRUE;
 
@@ -2813,10 +2768,11 @@ elf64_alpha_output_extsym (h, data)
 
   if (h->root.indx == -2)
     strip = FALSE;
-  else if (((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
-           || (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
-          && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
-          && (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
+  else if ((h->root.def_dynamic
+           || h->root.ref_dynamic
+           || h->root.root.type == bfd_link_hash_new)
+          && !h->root.def_regular
+          && !h->root.ref_regular)
     strip = TRUE;
   else if (einfo->info->strip == strip_all
           || (einfo->info->strip == strip_some
@@ -2903,7 +2859,7 @@ elf64_alpha_output_extsym (h, data)
       else
        h->esym.asym.value = 0;
     }
-  else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+  else if (h->root.needs_plt)
     {
       /* Set type and value for a symbol with a function stub.  */
       h->esym.asym.st = stProc;
@@ -3033,6 +2989,15 @@ elf64_alpha_check_relocs (abfd, info, sec, relocs)
   if (info->relocatable)
     return TRUE;
 
+  /* Don't do anything special with non-loaded, non-alloced sections.
+     In particular, any relocs in such sections should not affect GOT
+     and PLT reference counting (ie. we don't allow them to create GOT
+     or PLT entries), there's no possibility or desire to optimize TLS
+     relocs, and there's not much point in propagating relocs to shared
+     libs that the dynamic linker won't relocate.  */
+  if ((sec->flags & SEC_ALLOC) == 0)
+    return TRUE;
+
   dynobj = elf_hash_table(info)->dynobj;
   if (dynobj == NULL)
     elf_hash_table(info)->dynobj = dynobj = abfd;
@@ -3070,7 +3035,7 @@ elf64_alpha_check_relocs (abfd, info, sec, relocs)
                 || h->root.root.type == bfd_link_hash_warning)
            h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
 
-         h->root.elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
+         h->root.ref_regular = 1;
        }
 
       /* We can only get preliminary data on whether a symbol is
@@ -3080,7 +3045,7 @@ elf64_alpha_check_relocs (abfd, info, sec, relocs)
       maybe_dynamic = FALSE;
       if (h && ((info->shared
                 && (!info->symbolic || info->unresolved_syms_in_shared_libs == RM_IGNORE))
-               || ! (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
+               || !h->root.def_regular
                || h->root.root.type == bfd_link_hash_defweak))
         maybe_dynamic = TRUE;
 
@@ -3118,7 +3083,7 @@ elf64_alpha_check_relocs (abfd, info, sec, relocs)
 
        case R_ALPHA_REFLONG:
        case R_ALPHA_REFQUAD:
-         if ((info->shared && (sec->flags & SEC_ALLOC)) || maybe_dynamic)
+         if (info->shared || maybe_dynamic)
            need = NEED_DYNREL;
          break;
 
@@ -3186,9 +3151,9 @@ elf64_alpha_check_relocs (abfd, info, sec, relocs)
                  /* Make a guess as to whether a .plt entry is needed.  */
                  if ((gotent_flags & ALPHA_ELF_LINK_HASH_LU_FUNC)
                      && !(gotent_flags & ~ALPHA_ELF_LINK_HASH_LU_FUNC))
-                   h->root.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+                   h->root.needs_plt = 1;
                  else
-                   h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+                   h->root.needs_plt = 0;
                }
            }
        }
@@ -3219,13 +3184,14 @@ elf64_alpha_check_relocs (abfd, info, sec, relocs)
                {
                  flagword flags;
 
-                 sreloc = bfd_make_section (dynobj, rel_sec_name);
                  flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY
                           | SEC_LINKER_CREATED | SEC_READONLY);
                  if (sec->flags & SEC_ALLOC)
                    flags |= SEC_ALLOC | SEC_LOAD;
+                 sreloc = bfd_make_section_with_flags (dynobj,
+                                                       rel_sec_name,
+                                                       flags);
                  if (sreloc == NULL
-                     || !bfd_set_section_flags (dynobj, sreloc, flags)
                      || !bfd_set_section_alignment (dynobj, sreloc, 3))
                    return FALSE;
                }
@@ -3255,8 +3221,7 @@ elf64_alpha_check_relocs (abfd, info, sec, relocs)
                  rent->srel = sreloc;
                  rent->rtype = r_type;
                  rent->count = 1;
-                 rent->reltext = ((sec->flags & (SEC_READONLY | SEC_ALLOC))
-                                  == (SEC_READONLY | SEC_ALLOC));
+                 rent->reltext = (sec->flags & SEC_READONLY) != 0;
 
                  rent->next = h->reloc_entries;
                  h->reloc_entries = rent;
@@ -3268,9 +3233,8 @@ elf64_alpha_check_relocs (abfd, info, sec, relocs)
            {
              /* If this is a shared library, and the section is to be
                 loaded into memory, we need a RELATIVE reloc.  */
-             sreloc->_raw_size += sizeof (Elf64_External_Rela);
-             if ((sec->flags & (SEC_READONLY | SEC_ALLOC))
-                 == (SEC_READONLY | SEC_ALLOC))
+             sreloc->size += sizeof (Elf64_External_Rela);
+             if (sec->flags & SEC_READONLY)
                info->flags |= DF_TEXTREL;
            }
        }
@@ -3312,18 +3276,18 @@ elf64_alpha_adjust_dynamic_symbol (info, h)
         somewhere later.  But for now don't bother.  */
       && ah->got_entries)
     {
-      h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+      h->needs_plt = 1;
 
       s = bfd_get_section_by_name(dynobj, ".plt");
       if (!s && !elf64_alpha_create_dynamic_sections (dynobj, info))
        return FALSE;
 
       /* The first bit of the .plt is reserved.  */
-      if (s->_raw_size == 0)
-       s->_raw_size = PLT_HEADER_SIZE;
+      if (s->size == 0)
+       s->size = PLT_HEADER_SIZE;
 
-      h->plt.offset = s->_raw_size;
-      s->_raw_size += PLT_ENTRY_SIZE;
+      h->plt.offset = s->size;
+      s->size += PLT_ENTRY_SIZE;
 
       /* If this symbol is not defined in a regular file, and we are not
         generating a shared library, then set the symbol to the location
@@ -3342,22 +3306,22 @@ elf64_alpha_adjust_dynamic_symbol (info, h)
       /* We also need a JMP_SLOT entry in the .rela.plt section.  */
       s = bfd_get_section_by_name (dynobj, ".rela.plt");
       BFD_ASSERT (s != NULL);
-      s->_raw_size += sizeof (Elf64_External_Rela);
+      s->size += sizeof (Elf64_External_Rela);
 
       return TRUE;
     }
   else
-    h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+    h->needs_plt = 0;
 
   /* If this is a weak symbol, and there is a real definition, the
      processor independent code will have arranged for us to see the
      real definition first, and we can just use the same value.  */
-  if (h->weakdef != NULL)
+  if (h->u.weakdef != NULL)
     {
-      BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
-                 || h->weakdef->root.type == bfd_link_hash_defweak);
-      h->root.u.def.section = h->weakdef->root.u.def.section;
-      h->root.u.def.value = h->weakdef->root.u.def.value;
+      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
+                 || h->u.weakdef->root.type == bfd_link_hash_defweak);
+      h->root.u.def.section = h->u.weakdef->root.u.def.section;
+      h->root.u.def.value = h->u.weakdef->root.u.def.value;
       return TRUE;
     }
 
@@ -3610,6 +3574,7 @@ elf64_alpha_calc_got_offsets_for_symbol (h, arg)
      struct alpha_elf_link_hash_entry *h;
      PTR arg ATTRIBUTE_UNUSED;
 {
+  bfd_boolean result = TRUE;
   struct alpha_elf_got_entry *gotent;
 
   if (h->root.root.type == bfd_link_hash_warning)
@@ -3618,14 +3583,23 @@ elf64_alpha_calc_got_offsets_for_symbol (h, arg)
   for (gotent = h->got_entries; gotent; gotent = gotent->next)
     if (gotent->use_count > 0)
       {
-       bfd_size_type *plge
-         = &alpha_elf_tdata (gotent->gotobj)->got->_raw_size;
+       struct alpha_elf_obj_tdata *td;
+       bfd_size_type *plge;
 
+       td = alpha_elf_tdata (gotent->gotobj);
+       if (td == NULL)
+         {
+           _bfd_error_handler (_("Symbol %s has no GOT subsection for offset 0x%x"),
+                               h->root.root.root.string, gotent->got_offset);
+           result = FALSE;
+           continue;
+         }
+       plge = &td->got->size;
        gotent->got_offset = *plge;
        *plge += alpha_got_entry_size (gotent->reloc_type);
       }
 
-  return TRUE;
+  return result;
 }
 
 static void
@@ -3637,7 +3611,7 @@ elf64_alpha_calc_got_offsets (info)
   /* First, zero out the .got sizes, as we may be recalculating the
      .got after optimizing it.  */
   for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next)
-    alpha_elf_tdata(i)->got->_raw_size = 0;
+    alpha_elf_tdata(i)->got->size = 0;
 
   /* Next, fill in the offsets for all the global entries.  */
   alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
@@ -3647,7 +3621,7 @@ elf64_alpha_calc_got_offsets (info)
   /* Finally, fill in the offsets for the local entries.  */
   for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next)
     {
-      bfd_size_type got_offset = alpha_elf_tdata(i)->got->_raw_size;
+      bfd_size_type got_offset = alpha_elf_tdata(i)->got->size;
       bfd *j;
 
       for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next)
@@ -3668,8 +3642,7 @@ elf64_alpha_calc_got_offsets (info)
                }
        }
 
-      alpha_elf_tdata(i)->got->_raw_size = got_offset;
-      alpha_elf_tdata(i)->got->_cooked_size = got_offset;
+      alpha_elf_tdata(i)->got->size = got_offset;
     }
 }
 
@@ -3694,16 +3667,15 @@ elf64_alpha_size_got_sections (info)
          if (this_got == NULL)
            continue;
 
-         /* We are assuming no merging has yet ocurred.  */
+         /* We are assuming no merging has yet occurred.  */
          BFD_ASSERT (this_got == i);
 
           if (alpha_elf_tdata (this_got)->total_got_size > MAX_GOT_SIZE)
            {
              /* Yikes! A single object file has too many entries.  */
              (*_bfd_error_handler)
-               (_("%s: .got subsegment exceeds 64K (size %d)"),
-                bfd_archive_filename (i),
-                alpha_elf_tdata (this_got)->total_got_size);
+               (_("%B: .got subsegment exceeds 64K (size %d)"),
+                i, alpha_elf_tdata (this_got)->total_got_size);
              return FALSE;
            }
 
@@ -3766,21 +3738,18 @@ elf64_alpha_size_plt_section (info)
   if (splt == NULL)
     return TRUE;
 
-  splt->_raw_size = 0;
+  splt->size = 0;
 
   alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
                                elf64_alpha_size_plt_section_1, splt);
 
-  splt->_cooked_size = splt->_raw_size;
-
   /* Every plt entry requires a JMP_SLOT relocation.  */
   spltrel = bfd_get_section_by_name (dynobj, ".rela.plt");
-  if (splt->_raw_size)
-    entries = (splt->_raw_size - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
+  if (splt->size)
+    entries = (splt->size - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
   else
     entries = 0;
-  spltrel->_raw_size = entries * sizeof (Elf64_External_Rela);
-  spltrel->_cooked_size = spltrel->_raw_size;
+  spltrel->size = entries * sizeof (Elf64_External_Rela);
 
   return TRUE;
 }
@@ -3794,7 +3763,7 @@ elf64_alpha_size_plt_section_1 (h, data)
   struct alpha_elf_got_entry *gotent;
 
   /* If we didn't need an entry before, we still don't.  */
-  if (!(h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT))
+  if (!h->root.needs_plt)
     return TRUE;
 
   /* There must still be a LITERAL got entry for the function.  */
@@ -3807,14 +3776,14 @@ elf64_alpha_size_plt_section_1 (h, data)
      a need for the PLT entry.  */
   if (gotent)
     {
-      if (splt->_raw_size == 0)
-       splt->_raw_size = PLT_HEADER_SIZE;
-      h->root.plt.offset = splt->_raw_size;
-      splt->_raw_size += PLT_ENTRY_SIZE;
+      if (splt->size == 0)
+       splt->size = PLT_HEADER_SIZE;
+      h->root.plt.offset = splt->size;
+      splt->size += PLT_ENTRY_SIZE;
     }
   else
     {
-      h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+      h->root.needs_plt = 0;
       h->root.plt.offset = -1;
 
       /* Undo the definition frobbing begun in adjust_dynamic_symbol.  */
@@ -3852,9 +3821,9 @@ elf64_alpha_always_size_sections (output_bfd, info)
   for ( ; i ; i = alpha_elf_tdata(i)->got_link_next)
     {
       asection *s = alpha_elf_tdata(i)->got;
-      if (s->_raw_size > 0)
+      if (s->size > 0)
        {
-         s->contents = (bfd_byte *) bfd_zalloc (i, s->_raw_size);
+         s->contents = (bfd_byte *) bfd_zalloc (i, s->size);
          if (s->contents == NULL)
            return FALSE;
        }
@@ -3916,29 +3885,32 @@ elf64_alpha_calc_dynrel_sizes (h, info)
      set.  This is done for dynamic symbols in
      elf_adjust_dynamic_symbol but this is not done for non-dynamic
      symbols, somehow.  */
-  if (((h->root.elf_link_hash_flags
-       & (ELF_LINK_HASH_DEF_REGULAR
-         | ELF_LINK_HASH_REF_REGULAR
-         | ELF_LINK_HASH_DEF_DYNAMIC))
-       == ELF_LINK_HASH_REF_REGULAR)
+  if (!h->root.def_regular
+      && h->root.ref_regular
+      && !h->root.def_dynamic
       && (h->root.root.type == bfd_link_hash_defined
          || h->root.root.type == bfd_link_hash_defweak)
       && !(h->root.root.u.def.section->owner->flags & DYNAMIC))
-    h->root.elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+    h->root.def_regular = 1;
 
   /* If the symbol is dynamic, we'll need all the relocations in their
      natural form.  If this is a shared object, and it has been forced
      local, we'll need the same number of RELATIVE relocations.  */
-
   dynamic = alpha_elf_dynamic_symbol_p (&h->root, info);
 
+  /* 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.  */
+  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);
       if (entries)
        {
-         relent->srel->_raw_size +=
+         relent->srel->size +=
            entries * sizeof (Elf64_External_Rela) * relent->count;
          if (relent->reltext)
            info->flags |= DT_TEXTREL;
@@ -3992,14 +3964,12 @@ elf64_alpha_size_rela_got_section (info)
       BFD_ASSERT (entries == 0);
       return TRUE;
     }
-  srel->_raw_size = sizeof (Elf64_External_Rela) * entries;
+  srel->size = sizeof (Elf64_External_Rela) * entries;
 
   /* Now do the non-local symbols.  */
   alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
                                elf64_alpha_size_rela_got_1, info);
 
-  srel->_cooked_size = srel->_raw_size;
-
   return TRUE;
 }
 
@@ -4021,9 +3991,14 @@ elf64_alpha_size_rela_got_1 (h, info)
   /* If the symbol is dynamic, we'll need all the relocations in their
      natural form.  If this is a shared object, and it has been forced
      local, we'll need the same number of RELATIVE relocations.  */
-
   dynamic = alpha_elf_dynamic_symbol_p (&h->root, info);
 
+  /* 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.  */
+  if (h->root.root.type == bfd_link_hash_undefweak && !dynamic)
+    return TRUE;
+
   entries = 0;
   for (gotent = h->got_entries; gotent ; gotent = gotent->next)
     if (gotent->use_count > 0)
@@ -4040,7 +4015,7 @@ elf64_alpha_size_rela_got_1 (h, info)
       bfd *dynobj = elf_hash_table(info)->dynobj;
       asection *srel = bfd_get_section_by_name (dynobj, ".rela.got");
       BFD_ASSERT (srel != NULL);
-      srel->_raw_size += sizeof (Elf64_External_Rela) * entries;
+      srel->size += sizeof (Elf64_External_Rela) * entries;
     }
 
   return TRUE;
@@ -4067,7 +4042,7 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
        {
          s = bfd_get_section_by_name (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
-         s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
+         s->size = sizeof ELF_DYNAMIC_INTERPRETER;
          s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
        }
 
@@ -4110,7 +4085,7 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
 
       if (strncmp (name, ".rela", 5) == 0)
        {
-         strip = (s->_raw_size == 0);
+         strip = (s->size == 0);
 
          if (!strip)
            {
@@ -4129,12 +4104,12 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
        }
 
       if (strip)
-       _bfd_strip_section_from_output (info, s);
+       s->flags |= SEC_EXCLUDE;
       else
        {
          /* Allocate memory for the section contents.  */
-         s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
-         if (s->contents == NULL && s->_raw_size != 0)
+         s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
+         if (s->contents == NULL && s->size != 0)
            return FALSE;
        }
     }
@@ -4147,7 +4122,7 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (info->executable)
        {
@@ -4208,8 +4183,7 @@ elf64_alpha_emit_dynrel (abfd, info, sec, srel, offset, dynindx, rtype, addend)
   loc = srel->contents;
   loc += srel->reloc_count++ * sizeof (Elf64_External_Rela);
   bfd_elf64_swap_reloca_out (abfd, &outrel, loc);
-  BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
-             <= srel->_cooked_size);
+  BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count <= srel->size);
 }
 
 /* Relocate an Alpha ELF section for a relocatable link.
@@ -4249,8 +4223,8 @@ elf64_alpha_relocate_section_r (output_bfd, info, input_bfd, input_section,
       if (r_type >= R_ALPHA_max)
        {
          (*_bfd_error_handler)
-           (_("%s: unknown relocation type %d"),
-            bfd_archive_filename (input_bfd), (int)r_type);
+           (_("%B: unknown relocation type %d"),
+            input_bfd, (int) r_type);
          bfd_set_error (bfd_error_bad_value);
          ret_val = FALSE;
          continue;
@@ -4294,13 +4268,11 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
-  struct elf_link_tls_segment *tls_segment;
   asection *sgot, *srel, *srelgot;
   bfd *dynobj, *gotobj;
   bfd_vma gp, tp_base, dtp_base;
   struct alpha_elf_got_entry **local_got_entries;
   bfd_boolean ret_val;
-  const char *section_name;
 
   /* Handle relocatable links with a smaller loop.  */
   if (info->relocatable)
@@ -4320,11 +4292,17 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
   else
     srelgot = NULL;
 
-  section_name = (bfd_elf_string_from_elf_section
-                 (input_bfd, elf_elfheader(input_bfd)->e_shstrndx,
-                  elf_section_data(input_section)->rel_hdr.sh_name));
-  BFD_ASSERT(section_name != NULL);
-  srel = bfd_get_section_by_name (dynobj, section_name);
+  if (input_section->flags & SEC_ALLOC)
+    {
+      const char *section_name;
+      section_name = (bfd_elf_string_from_elf_section
+                     (input_bfd, elf_elfheader(input_bfd)->e_shstrndx,
+                      elf_section_data(input_section)->rel_hdr.sh_name));
+      BFD_ASSERT(section_name != NULL);
+      srel = bfd_get_section_by_name (dynobj, section_name);
+    }
+  else
+    srel = NULL;
 
   /* Find the gp value for this input bfd.  */
   gotobj = alpha_elf_tdata (input_bfd)->gotobj;
@@ -4348,11 +4326,10 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
 
   local_got_entries = alpha_elf_tdata(input_bfd)->local_got_entries;
 
-  tls_segment = elf_hash_table (info)->tls_segment;
-  if (tls_segment)
+  if (elf_hash_table (info)->tls_sec != NULL)
     {
-      dtp_base = alpha_get_dtprel_base (tls_segment);
-      tp_base = alpha_get_tprel_base (tls_segment);
+      dtp_base = alpha_get_dtprel_base (info);
+      tp_base = alpha_get_tprel_base (info);
     }
   else
     dtp_base = tp_base = 0;
@@ -4377,8 +4354,8 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
       if (r_type >= R_ALPHA_max)
        {
          (*_bfd_error_handler)
-           (_("%s: unknown relocation type %d"),
-            bfd_archive_filename (input_bfd), (int)r_type);
+           (_("%B: unknown relocation type %d"),
+            input_bfd, (int) r_type);
          bfd_set_error (bfd_error_bad_value);
          ret_val = FALSE;
          continue;
@@ -4394,9 +4371,11 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
 
       if (r_symndx < symtab_hdr->sh_info)
        {
+         asection *msec;
          sym = local_syms + r_symndx;
          sec = local_sections[r_symndx];
-         value = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
+         msec = sec;
+         value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel);
 
          /* If this is a tp-relative relocation against sym 0,
             this is hackery from relax_section.  Force the value to
@@ -4424,7 +4403,6 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
              && !gotent->reloc_xlated)
            {
              struct alpha_elf_got_entry *ent;
-             asection *msec;
 
              for (ent = gotent; ent; ent = ent->next)
                {
@@ -4436,8 +4414,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
                    _bfd_merged_section_offset (output_bfd, &msec,
                                                elf_section_data (sec)->
                                                  sec_info,
-                                               sym->st_value + ent->addend,
-                                               (bfd_vma) 0);
+                                               sym->st_value + ent->addend);
                  ent->addend -= sym->st_value;
                  ent->addend += msec->output_section->vma
                                 + msec->output_offset
@@ -4453,12 +4430,12 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
          bfd_boolean warned;
          bfd_boolean unresolved_reloc;
          struct elf_link_hash_entry *hh;
-         
-         RELOC_FOR_GLOBAL_SYMBOL (hh,
-                                  (struct elf_link_hash_entry *) alpha_elf_sym_hashes (input_bfd),
-                                  r_symndx, symtab_hdr, value,
-                                  sec, unresolved_reloc, info,
-                                  warned);
+         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);
 
          if (warned)
            continue;
@@ -4519,7 +4496,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
              /* 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)
+             if (info->shared && !dynamic_symbol_p && !undef_weak_ref)
                elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
                                         gotent->got_offset, 0,
                                         R_ALPHA_RELATIVE, value);
@@ -4549,8 +4526,8 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
          if (dynamic_symbol_p)
             {
               (*_bfd_error_handler)
-                (_("%s: gp-relative relocation against dynamic symbol %s"),
-                 bfd_archive_filename (input_bfd), h->root.root.root.string);
+                (_("%B: gp-relative relocation against dynamic symbol %s"),
+                 input_bfd, h->root.root.root.string);
               ret_val = FALSE;
             }
          BFD_ASSERT(gp != 0);
@@ -4561,8 +4538,8 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
          if (dynamic_symbol_p)
             {
               (*_bfd_error_handler)
-                (_("%s: gp-relative relocation against dynamic symbol %s"),
-                 bfd_archive_filename (input_bfd), h->root.root.root.string);
+                (_("%B: gp-relative relocation against dynamic symbol %s"),
+                 input_bfd, h->root.root.root.string);
               ret_val = FALSE;
             }
          BFD_ASSERT(gp != 0);
@@ -4587,8 +4564,8 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
          if (dynamic_symbol_p)
             {
               (*_bfd_error_handler)
-                (_("%s: pc-relative relocation against dynamic symbol %s"),
-                 bfd_archive_filename (input_bfd), h->root.root.root.string);
+                (_("%B: pc-relative relocation against dynamic symbol %s"),
+                 input_bfd, h->root.root.root.string);
               ret_val = FALSE;
             }
          /* The regular PC-relative stuff measures from the start of
@@ -4615,8 +4592,8 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
                && gotobj != alpha_elf_tdata (sec->owner)->gotobj)
              {
                (*_bfd_error_handler)
-                 (_("%s: change in gp: BRSGP %s"),
-                  bfd_archive_filename (input_bfd), h->root.root.root.string);
+                 (_("%B: change in gp: BRSGP %s"),
+                  input_bfd, h->root.root.root.string);
                ret_val = FALSE;
              }
 
@@ -4645,8 +4622,8 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
                      name = bfd_section_name (input_bfd, sec);
                  }
                (*_bfd_error_handler)
-                 (_("%s: !samegp reloc against symbol without .prologue: %s"),
-                  bfd_archive_filename (input_bfd), name);
+                 (_("%B: !samegp reloc against symbol without .prologue: %s"),
+                  input_bfd, name);
                ret_val = FALSE;
                break;
              }
@@ -4674,13 +4651,13 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
              }
            else if (r_type == R_ALPHA_DTPREL64)
              {
-               BFD_ASSERT(tls_segment != NULL);
+               BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
                value -= dtp_base;
                goto default_reloc;
              }
            else if (r_type == R_ALPHA_TPREL64)
              {
-               BFD_ASSERT(tls_segment != NULL);
+               BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
                if (!info->shared)
                  {
                    value -= tp_base;
@@ -4691,13 +4668,14 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
              }
            else if (info->shared
                     && r_symndx != 0
-                    && (input_section->flags & SEC_ALLOC))
+                    && (input_section->flags & SEC_ALLOC)
+                    && !undef_weak_ref)
              {
                if (r_type == R_ALPHA_REFLONG)
                  {
                    (*_bfd_error_handler)
-                     (_("%s: unhandled dynamic relocation against %s"),
-                      bfd_archive_filename (input_bfd),
+                     (_("%B: unhandled dynamic relocation against %s"),
+                      input_bfd,
                       h->root.root.root.string);
                    ret_val = FALSE;
                  }
@@ -4708,9 +4686,10 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
            else
              goto default_reloc;
 
-           elf64_alpha_emit_dynrel (output_bfd, info, input_section,
-                                    srel, rel->r_offset, dynindx,
-                                    dyntype, dynaddend);
+           if (input_section->flags & SEC_ALLOC)
+             elf64_alpha_emit_dynrel (output_bfd, info, input_section,
+                                      srel, rel->r_offset, dynindx,
+                                      dyntype, dynaddend);
          }
          goto default_reloc;
 
@@ -4720,11 +4699,19 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
          if (dynamic_symbol_p)
             {
               (*_bfd_error_handler)
-                (_("%s: pc-relative relocation against dynamic symbol %s"),
-                 bfd_archive_filename (input_bfd), h->root.root.root.string);
+                (_("%B: pc-relative relocation against dynamic symbol %s"),
+                 input_bfd, h->root.root.root.string);
+              ret_val = FALSE;
+            }
+         else if ((info->shared || info->pie) && undef_weak_ref)
+            {
+              (*_bfd_error_handler)
+                (_("%B: pc-relative relocation against undefined weak symbol %s"),
+                 input_bfd, h->root.root.root.string);
               ret_val = FALSE;
             }
 
+
          /* ??? .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.  */
@@ -4760,7 +4747,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
                value = 0;
              else
                {
-                 BFD_ASSERT(tls_segment != NULL);
+                 BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
                  value -= dtp_base;
                }
              bfd_put_64 (output_bfd, value,
@@ -4779,11 +4766,11 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
          if (dynamic_symbol_p)
             {
               (*_bfd_error_handler)
-                (_("%s: dtp-relative relocation against dynamic symbol %s"),
-                 bfd_archive_filename (input_bfd), h->root.root.root.string);
+                (_("%B: dtp-relative relocation against dynamic symbol %s"),
+                 input_bfd, h->root.root.root.string);
               ret_val = FALSE;
             }
-         BFD_ASSERT(tls_segment != NULL);
+         BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
          value -= dtp_base;
          if (r_type == R_ALPHA_DTPRELHI)
            value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
@@ -4795,18 +4782,18 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
          if (info->shared)
            {
              (*_bfd_error_handler)
-               (_("%s: TLS local exec code cannot be linked into shared objects"),
-               bfd_archive_filename (input_bfd));
+               (_("%B: TLS local exec code cannot be linked into shared objects"),
+               input_bfd);
               ret_val = FALSE;
            }
          else if (dynamic_symbol_p)
             {
               (*_bfd_error_handler)
-                (_("%s: tp-relative relocation against dynamic symbol %s"),
-                 bfd_archive_filename (input_bfd), h->root.root.root.string);
+                (_("%B: tp-relative relocation against dynamic symbol %s"),
+                 input_bfd, h->root.root.root.string);
               ret_val = FALSE;
             }
-         BFD_ASSERT(tls_segment != NULL);
+         BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
          value -= tp_base;
          if (r_type == R_ALPHA_TPRELHI)
            value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
@@ -4827,7 +4814,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
                value = 0;
              else
                {
-                 BFD_ASSERT(tls_segment != NULL);
+                 BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
                  if (r_type == R_ALPHA_GOTDTPREL)
                    value -= dtp_base;
                  else if (!info->shared)
@@ -4877,7 +4864,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
              break;
 
            if (h != NULL)
-             name = h->root.root.root.string;
+             name = NULL;
            else
              {
                name = (bfd_elf_string_from_elf_section
@@ -4888,8 +4875,9 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
                  name = bfd_section_name (input_bfd, sec);
              }
            if (! ((*info->callbacks->reloc_overflow)
-                  (info, name, howto->name, (bfd_vma) 0,
-                   input_bfd, input_section, rel->r_offset)))
+                  (info, (h ? &h->root.root : NULL), name, howto->name,
+                   (bfd_vma) 0, input_bfd, input_section,
+                   rel->r_offset)))
              ret_val = FALSE;
          }
          break;
@@ -4969,7 +4957,7 @@ elf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym)
       loc = srel->contents + plt_index * sizeof (Elf64_External_Rela);
       bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
 
-      if (!(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
+      if (!h->def_regular)
        {
          /* Mark the symbol as undefined, rather than as defined in the
             .plt section.  Leave the value alone.  */
@@ -5088,7 +5076,7 @@ elf64_alpha_finish_dynamic_sections (output_bfd, info)
       BFD_ASSERT (splt != NULL && sdyn != NULL);
 
       dyncon = (Elf64_External_Dyn *) sdyn->contents;
-      dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+      dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size);
       for (; dyncon < dynconend; dyncon++)
        {
          Elf_Internal_Dyn dyn;
@@ -5117,10 +5105,7 @@ elf64_alpha_finish_dynamic_sections (output_bfd, info)
                 out who is right.  */
              s = bfd_get_section_by_name (output_bfd, ".rela.plt");
              if (s)
-               {
-                 dyn.d_un.d_val -=
-                   (s->_cooked_size ? s->_cooked_size : s->_raw_size);
-               }
+               dyn.d_un.d_val -= s->size;
              break;
 
            get_vma:
@@ -5130,8 +5115,7 @@ elf64_alpha_finish_dynamic_sections (output_bfd, info)
 
            get_size:
              s = bfd_get_section_by_name (output_bfd, name);
-             dyn.d_un.d_val =
-               (s->_cooked_size ? s->_cooked_size : s->_raw_size);
+             dyn.d_un.d_val = s->size;
              break;
            }
 
@@ -5139,7 +5123,7 @@ elf64_alpha_finish_dynamic_sections (output_bfd, info)
        }
 
       /* Initialize the PLT0 entry.  */
-      if (splt->_raw_size > 0)
+      if (splt->size > 0)
        {
          bfd_put_32 (output_bfd, PLT_HEADER_WORD1, splt->contents);
          bfd_put_32 (output_bfd, PLT_HEADER_WORD2, splt->contents + 4);
@@ -5250,7 +5234,7 @@ elf64_alpha_final_link (abfd, info)
                  if (s != NULL)
                    {
                      esym.asym.value = s->vma;
-                     last = s->vma + s->_raw_size;
+                     last = s->vma + s->size;
                    }
                  else
                    esym.asym.value = last;
@@ -5261,7 +5245,7 @@ elf64_alpha_final_link (abfd, info)
                }
            }
 
-         for (p = o->link_order_head;
+         for (p = o->map_head.link_order;
               p != (struct bfd_link_order *) NULL;
               p = p->next)
            {
@@ -5295,7 +5279,7 @@ elf64_alpha_final_link (abfd, info)
              input_swap = (get_elf_backend_data (input_bfd)
                            ->elf_backend_ecoff_debug_swap);
 
-             BFD_ASSERT (p->size == input_section->_raw_size);
+             BFD_ASSERT (p->size == input_section->size);
 
              /* The ECOFF linking code expects that we have already
                 read in the debugging information and set up an
@@ -5378,18 +5362,18 @@ elf64_alpha_final_link (abfd, info)
            return FALSE;
 
          /* Set the size of the .mdebug section.  */
-         o->_raw_size = bfd_ecoff_debug_size (abfd, &debug, swap);
+         o->size = bfd_ecoff_debug_size (abfd, &debug, swap);
 
          /* Skip this section later on (I don't think this currently
             matters, but someday it might).  */
-         o->link_order_head = (struct bfd_link_order *) NULL;
+         o->map_head.link_order = (struct bfd_link_order *) NULL;
 
          mdebug_sec = o;
        }
     }
 
   /* Invoke the regular ELF backend linker to do all the work.  */
-  if (! bfd_elf64_bfd_final_link (abfd, info))
+  if (! bfd_elf_final_link (abfd, info))
     return FALSE;
 
   /* Now write out the computed sections.  */
@@ -5411,7 +5395,7 @@ elf64_alpha_final_link (abfd, info)
        if (! bfd_set_section_contents (abfd, sgot->output_section,
                                        sgot->contents,
                                        (file_ptr) sgot->output_offset,
-                                       sgot->_raw_size))
+                                       sgot->size))
          return FALSE;
       }
   }
@@ -5447,14 +5431,44 @@ elf64_alpha_reloc_type_class (rela)
     }
 }
 \f
-static struct bfd_elf_special_section const elf64_alpha_special_sections[]=
+static struct bfd_elf_special_section const
+  alpha_special_sections_s[]=
+{
+  { ".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
+  { ".sbss",  5, -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
+  { NULL,     0,  0, 0,            0 }
+};
+
+static struct bfd_elf_special_section const *
+  elf64_alpha_special_sections[27] =
 {
-  { ".sdata",          0,      NULL,   0,
-    SHT_PROGBITS,      SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
-  { ".sbss",           0,      NULL,   0,
-    SHT_NOBITS,                SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
-  { NULL,              0,      NULL,   0,
-    0,                 0 }
+  NULL,                                /* 'a' */
+  NULL,                                /* 'b' */
+  NULL,                                /* 'c' */
+  NULL,                                /* 'd' */
+  NULL,                                /* 'e' */
+  NULL,                                /* 'f' */
+  NULL,                                /* 'g' */
+  NULL,                                /* 'h' */
+  NULL,                                /* 'i' */
+  NULL,                                /* 'j' */
+  NULL,                                /* 'k' */
+  NULL,                                /* 'l' */
+  NULL,                                /* 'm' */
+  NULL,                                /* 'n' */
+  NULL,                                /* 'o' */
+  NULL,                                /* 'p' */
+  NULL,                                /* 'q' */
+  NULL,                                /* 'r' */
+  alpha_special_sections_s,    /* 's' */
+  NULL,                                /* 't' */
+  NULL,                                /* 'u' */
+  NULL,                                /* 'v' */
+  NULL,                                /* 'w' */
+  NULL,                                /* 'x' */
+  NULL,                                /* 'y' */
+  NULL,                                /* 'z' */
+  NULL                         /* other */
 };
 
 /* ECOFF swapping routines.  These are used when dealing with the
@@ -5603,7 +5617,6 @@ 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_plt_header_size PLT_HEADER_SIZE
 
 #include "elf64-target.h"
 \f