bfd/
[deliverable/binutils-gdb.git] / bfd / elf.c
index b8a300e4a64ae13cc1954d1cc2236e53f1332082..dcb5c3d586a32d095d266cba41710001a00307f5 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,6 +1,7 @@
 /* ELF executable support for BFD.
-   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
-   Free Software Foundation, Inc.
+
+   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+   2002, 2003, 2004 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -15,7 +16,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software 
+   along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /*  SECTION
 #include "elf-bfd.h"
 #include "libiberty.h"
 
-static INLINE struct elf_segment_map *make_mapping
-  PARAMS ((bfd *, asection **, unsigned int, unsigned int, boolean));
-static boolean map_sections_to_segments PARAMS ((bfd *));
-static int elf_sort_sections PARAMS ((const PTR, const PTR));
-static boolean assign_file_positions_for_segments PARAMS ((bfd *));
-static boolean assign_file_positions_except_relocs PARAMS ((bfd *));
-static boolean prep_headers PARAMS ((bfd *));
-static boolean swap_out_syms PARAMS ((bfd *, struct bfd_strtab_hash **, int));
-static boolean copy_private_bfd_data PARAMS ((bfd *, bfd *));
-static char *elf_read PARAMS ((bfd *, file_ptr, bfd_size_type));
-static const char *group_signature PARAMS ((bfd *, Elf_Internal_Shdr *));
-static boolean setup_group PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
-static void merge_sections_remove_hook PARAMS ((bfd *, asection *));
-static void elf_fake_sections PARAMS ((bfd *, asection *, PTR));
-static boolean assign_section_numbers PARAMS ((bfd *));
-static INLINE int sym_is_global PARAMS ((bfd *, asymbol *));
-static boolean elf_map_symbols PARAMS ((bfd *));
-static bfd_size_type get_program_header_size PARAMS ((bfd *));
-static boolean elfcore_read_notes PARAMS ((bfd *, file_ptr, bfd_size_type));
-static boolean elf_find_function PARAMS ((bfd *, asection *, asymbol **,
-                                         bfd_vma, const char **,
-                                         const char **));
-static int elfcore_make_pid PARAMS ((bfd *));
-static boolean elfcore_maybe_make_sect PARAMS ((bfd *, char *, asection *));
-static boolean elfcore_make_note_pseudosection PARAMS ((bfd *, char *,
-                                                       Elf_Internal_Note *));
-static boolean elfcore_grok_prfpreg PARAMS ((bfd *, Elf_Internal_Note *));
-static boolean elfcore_grok_prxfpreg PARAMS ((bfd *, Elf_Internal_Note *));
-static boolean elfcore_grok_note PARAMS ((bfd *, Elf_Internal_Note *));
-
-static boolean elfcore_netbsd_get_lwpid PARAMS ((Elf_Internal_Note *, int *));
-static boolean elfcore_grok_netbsd_procinfo PARAMS ((bfd *,
-                                                    Elf_Internal_Note *));
-static boolean elfcore_grok_netbsd_note PARAMS ((bfd *, Elf_Internal_Note *));
+static int elf_sort_sections (const void *, const void *);
+static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *);
+static bfd_boolean prep_headers (bfd *);
+static bfd_boolean swap_out_syms (bfd *, struct bfd_strtab_hash **, int) ;
+static bfd_boolean elfcore_read_notes (bfd *, file_ptr, bfd_size_type) ;
 
 /* Swap version information in and out.  The version information is
    currently size independent.  If that ever changes, this code will
@@ -82,10 +54,9 @@ static boolean elfcore_grok_netbsd_note PARAMS ((bfd *, Elf_Internal_Note *));
 /* Swap in a Verdef structure.  */
 
 void
-_bfd_elf_swap_verdef_in (abfd, src, dst)
-     bfd *abfd;
-     const Elf_External_Verdef *src;
-     Elf_Internal_Verdef *dst;
+_bfd_elf_swap_verdef_in (bfd *abfd,
+                        const Elf_External_Verdef *src,
+                        Elf_Internal_Verdef *dst)
 {
   dst->vd_version = H_GET_16 (abfd, src->vd_version);
   dst->vd_flags   = H_GET_16 (abfd, src->vd_flags);
@@ -99,10 +70,9 @@ _bfd_elf_swap_verdef_in (abfd, src, dst)
 /* Swap out a Verdef structure.  */
 
 void
-_bfd_elf_swap_verdef_out (abfd, src, dst)
-     bfd *abfd;
-     const Elf_Internal_Verdef *src;
-     Elf_External_Verdef *dst;
+_bfd_elf_swap_verdef_out (bfd *abfd,
+                         const Elf_Internal_Verdef *src,
+                         Elf_External_Verdef *dst)
 {
   H_PUT_16 (abfd, src->vd_version, dst->vd_version);
   H_PUT_16 (abfd, src->vd_flags, dst->vd_flags);
@@ -116,10 +86,9 @@ _bfd_elf_swap_verdef_out (abfd, src, dst)
 /* Swap in a Verdaux structure.  */
 
 void
-_bfd_elf_swap_verdaux_in (abfd, src, dst)
-     bfd *abfd;
-     const Elf_External_Verdaux *src;
-     Elf_Internal_Verdaux *dst;
+_bfd_elf_swap_verdaux_in (bfd *abfd,
+                         const Elf_External_Verdaux *src,
+                         Elf_Internal_Verdaux *dst)
 {
   dst->vda_name = H_GET_32 (abfd, src->vda_name);
   dst->vda_next = H_GET_32 (abfd, src->vda_next);
@@ -128,10 +97,9 @@ _bfd_elf_swap_verdaux_in (abfd, src, dst)
 /* Swap out a Verdaux structure.  */
 
 void
-_bfd_elf_swap_verdaux_out (abfd, src, dst)
-     bfd *abfd;
-     const Elf_Internal_Verdaux *src;
-     Elf_External_Verdaux *dst;
+_bfd_elf_swap_verdaux_out (bfd *abfd,
+                          const Elf_Internal_Verdaux *src,
+                          Elf_External_Verdaux *dst)
 {
   H_PUT_32 (abfd, src->vda_name, dst->vda_name);
   H_PUT_32 (abfd, src->vda_next, dst->vda_next);
@@ -140,10 +108,9 @@ _bfd_elf_swap_verdaux_out (abfd, src, dst)
 /* Swap in a Verneed structure.  */
 
 void
-_bfd_elf_swap_verneed_in (abfd, src, dst)
-     bfd *abfd;
-     const Elf_External_Verneed *src;
-     Elf_Internal_Verneed *dst;
+_bfd_elf_swap_verneed_in (bfd *abfd,
+                         const Elf_External_Verneed *src,
+                         Elf_Internal_Verneed *dst)
 {
   dst->vn_version = H_GET_16 (abfd, src->vn_version);
   dst->vn_cnt     = H_GET_16 (abfd, src->vn_cnt);
@@ -155,10 +122,9 @@ _bfd_elf_swap_verneed_in (abfd, src, dst)
 /* Swap out a Verneed structure.  */
 
 void
-_bfd_elf_swap_verneed_out (abfd, src, dst)
-     bfd *abfd;
-     const Elf_Internal_Verneed *src;
-     Elf_External_Verneed *dst;
+_bfd_elf_swap_verneed_out (bfd *abfd,
+                          const Elf_Internal_Verneed *src,
+                          Elf_External_Verneed *dst)
 {
   H_PUT_16 (abfd, src->vn_version, dst->vn_version);
   H_PUT_16 (abfd, src->vn_cnt, dst->vn_cnt);
@@ -170,10 +136,9 @@ _bfd_elf_swap_verneed_out (abfd, src, dst)
 /* Swap in a Vernaux structure.  */
 
 void
-_bfd_elf_swap_vernaux_in (abfd, src, dst)
-     bfd *abfd;
-     const Elf_External_Vernaux *src;
-     Elf_Internal_Vernaux *dst;
+_bfd_elf_swap_vernaux_in (bfd *abfd,
+                         const Elf_External_Vernaux *src,
+                         Elf_Internal_Vernaux *dst)
 {
   dst->vna_hash  = H_GET_32 (abfd, src->vna_hash);
   dst->vna_flags = H_GET_16 (abfd, src->vna_flags);
@@ -185,10 +150,9 @@ _bfd_elf_swap_vernaux_in (abfd, src, dst)
 /* Swap out a Vernaux structure.  */
 
 void
-_bfd_elf_swap_vernaux_out (abfd, src, dst)
-     bfd *abfd;
-     const Elf_Internal_Vernaux *src;
-     Elf_External_Vernaux *dst;
+_bfd_elf_swap_vernaux_out (bfd *abfd,
+                          const Elf_Internal_Vernaux *src,
+                          Elf_External_Vernaux *dst)
 {
   H_PUT_32 (abfd, src->vna_hash, dst->vna_hash);
   H_PUT_16 (abfd, src->vna_flags, dst->vna_flags);
@@ -200,10 +164,9 @@ _bfd_elf_swap_vernaux_out (abfd, src, dst)
 /* Swap in a Versym structure.  */
 
 void
-_bfd_elf_swap_versym_in (abfd, src, dst)
-     bfd *abfd;
-     const Elf_External_Versym *src;
-     Elf_Internal_Versym *dst;
+_bfd_elf_swap_versym_in (bfd *abfd,
+                        const Elf_External_Versym *src,
+                        Elf_Internal_Versym *dst)
 {
   dst->vs_vers = H_GET_16 (abfd, src->vs_vers);
 }
@@ -211,10 +174,9 @@ _bfd_elf_swap_versym_in (abfd, src, dst)
 /* Swap out a Versym structure.  */
 
 void
-_bfd_elf_swap_versym_out (abfd, src, dst)
-     bfd *abfd;
-     const Elf_Internal_Versym *src;
-     Elf_External_Versym *dst;
+_bfd_elf_swap_versym_out (bfd *abfd,
+                         const Elf_Internal_Versym *src,
+                         Elf_External_Versym *dst)
 {
   H_PUT_16 (abfd, src->vs_vers, dst->vs_vers);
 }
@@ -223,8 +185,7 @@ _bfd_elf_swap_versym_out (abfd, src, dst)
    cause invalid hash tables to be generated.  */
 
 unsigned long
-bfd_elf_hash (namearg)
-     const char *namearg;
+bfd_elf_hash (const char *namearg)
 {
   const unsigned char *name = (const unsigned char *) namearg;
   unsigned long h = 0;
@@ -242,7 +203,7 @@ bfd_elf_hash (namearg)
          h ^= g;
        }
     }
-  return h;
+  return h & 0xffffffff;
 }
 
 /* Read a specified number of bytes at a specified offset in an ELF
@@ -250,10 +211,7 @@ bfd_elf_hash (namearg)
    buffer.  */
 
 static char *
-elf_read (abfd, offset, size)
-     bfd *abfd;
-     file_ptr offset;
-     bfd_size_type size;
+elf_read (bfd *abfd, file_ptr offset, bfd_size_type size)
 {
   char *buf;
 
@@ -261,7 +219,7 @@ elf_read (abfd, offset, size)
     return NULL;
   if (bfd_seek (abfd, offset, SEEK_SET) != 0)
     return NULL;
-  if (bfd_bread ((PTR) buf, size, abfd) != size)
+  if (bfd_bread (buf, size, abfd) != size)
     {
       if (bfd_get_error () != bfd_error_system_call)
        bfd_set_error (bfd_error_file_truncated);
@@ -270,34 +228,29 @@ elf_read (abfd, offset, size)
   return buf;
 }
 
-boolean
-bfd_elf_mkobject (abfd)
-     bfd *abfd;
+bfd_boolean
+bfd_elf_mkobject (bfd *abfd)
 {
   /* This just does initialization.  */
   /* coff_mkobject zalloc's space for tdata.coff_obj_data ...  */
-  bfd_size_type amt = sizeof (struct elf_obj_tdata);
-  elf_tdata (abfd) = (struct elf_obj_tdata *) bfd_zalloc (abfd, amt);
+  elf_tdata (abfd) = bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
   if (elf_tdata (abfd) == 0)
-    return false;
+    return FALSE;
   /* Since everything is done at close time, do we need any
      initialization?  */
 
-  return true;
+  return TRUE;
 }
 
-boolean
-bfd_elf_mkcorefile (abfd)
-     bfd *abfd;
+bfd_boolean
+bfd_elf_mkcorefile (bfd *abfd)
 {
   /* I think this can be done just like an object file.  */
   return bfd_elf_mkobject (abfd);
 }
 
 char *
-bfd_elf_get_str_section (abfd, shindex)
-     bfd *abfd;
-     unsigned int shindex;
+bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
 {
   Elf_Internal_Shdr **i_shdrp;
   char *shstrtab = NULL;
@@ -315,16 +268,15 @@ bfd_elf_get_str_section (abfd, shindex)
       offset = i_shdrp[shindex]->sh_offset;
       shstrtabsize = i_shdrp[shindex]->sh_size;
       shstrtab = elf_read (abfd, offset, shstrtabsize);
-      i_shdrp[shindex]->contents = (PTR) shstrtab;
+      i_shdrp[shindex]->contents = shstrtab;
     }
   return shstrtab;
 }
 
 char *
-bfd_elf_string_from_elf_section (abfd, shindex, strindex)
-     bfd *abfd;
-     unsigned int shindex;
-     unsigned int strindex;
+bfd_elf_string_from_elf_section (bfd *abfd,
+                                unsigned int shindex,
+                                unsigned int strindex)
 {
   Elf_Internal_Shdr *hdr;
 
@@ -340,8 +292,8 @@ bfd_elf_string_from_elf_section (abfd, shindex, strindex)
   if (strindex >= hdr->sh_size)
     {
       (*_bfd_error_handler)
-       (_("%s: invalid string offset %u >= %lu for section `%s'"),
-        bfd_archive_filename (abfd), strindex, (unsigned long) hdr->sh_size,
+       (_("%B: invalid string offset %u >= %lu for section `%s'"),
+        abfd, strindex, (unsigned long) hdr->sh_size,
         ((shindex == elf_elfheader(abfd)->e_shstrndx
           && strindex == hdr->sh_name)
          ? ".shstrtab"
@@ -359,24 +311,22 @@ bfd_elf_string_from_elf_section (abfd, shindex, strindex)
    symbols, and symbol section index extensions, respectively.  */
 
 Elf_Internal_Sym *
-bfd_elf_get_elf_syms (ibfd, symtab_hdr, symcount, symoffset,
-                     intsym_buf, extsym_buf, extshndx_buf)
-     bfd *ibfd;
-     Elf_Internal_Shdr *symtab_hdr;
-     size_t symcount;
-     size_t symoffset;
-     Elf_Internal_Sym *intsym_buf;
-     PTR extsym_buf;
-     Elf_External_Sym_Shndx *extshndx_buf;
+bfd_elf_get_elf_syms (bfd *ibfd,
+                     Elf_Internal_Shdr *symtab_hdr,
+                     size_t symcount,
+                     size_t symoffset,
+                     Elf_Internal_Sym *intsym_buf,
+                     void *extsym_buf,
+                     Elf_External_Sym_Shndx *extshndx_buf)
 {
   Elf_Internal_Shdr *shndx_hdr;
-  PTR alloc_ext;
+  void *alloc_ext;
   const bfd_byte *esym;
   Elf_External_Sym_Shndx *alloc_extshndx;
   Elf_External_Sym_Shndx *shndx;
   Elf_Internal_Sym *isym;
   Elf_Internal_Sym *isymend;
-  struct elf_backend_data *bed;
+  const struct elf_backend_data *bed;
   size_t extsym_size;
   bfd_size_type amt;
   file_ptr pos;
@@ -417,7 +367,7 @@ bfd_elf_get_elf_syms (ibfd, symtab_hdr, symcount, symoffset,
       pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx);
       if (extshndx_buf == NULL)
        {
-         alloc_extshndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+         alloc_extshndx = bfd_malloc (amt);
          extshndx_buf = alloc_extshndx;
        }
       if (extshndx_buf == NULL
@@ -432,7 +382,7 @@ bfd_elf_get_elf_syms (ibfd, symtab_hdr, symcount, symoffset,
   if (intsym_buf == NULL)
     {
       bfd_size_type amt = symcount * sizeof (Elf_Internal_Sym);
-      intsym_buf = (Elf_Internal_Sym *) bfd_malloc (amt);
+      intsym_buf = bfd_malloc (amt);
       if (intsym_buf == NULL)
        goto out;
     }
@@ -442,7 +392,7 @@ bfd_elf_get_elf_syms (ibfd, symtab_hdr, symcount, symoffset,
   for (esym = extsym_buf, isym = intsym_buf, shndx = extshndx_buf;
        isym < isymend;
        esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL)
-    (*bed->s->swap_symbol_in) (ibfd, esym, (const PTR) shndx, isym);
+    (*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym);
 
  out:
   if (alloc_ext != NULL)
@@ -453,6 +403,21 @@ bfd_elf_get_elf_syms (ibfd, symtab_hdr, symcount, symoffset,
   return intsym_buf;
 }
 
+/* Look up a symbol name.  */
+const char *
+bfd_elf_local_sym_name (bfd *abfd, Elf_Internal_Sym *isym)
+{
+  unsigned int iname = isym->st_name;
+  unsigned int shindex = elf_tdata (abfd)->symtab_hdr.sh_link;
+  if (iname == 0 && ELF_ST_TYPE (isym->st_info) == STT_SECTION)
+    {
+      iname = elf_elfsections (abfd)[isym->st_shndx]->sh_name;
+      shindex = elf_elfheader (abfd)->e_shstrndx;
+    }
+
+  return bfd_elf_string_from_elf_section (abfd, shindex, iname);
+}
+
 /* Elf_Internal_Shdr->contents is an array of these for SHT_GROUP
    sections.  The first element is the flags, the rest are section
    pointers.  */
@@ -466,16 +431,12 @@ typedef union elf_internal_group {
    signature just a string?  */
 
 static const char *
-group_signature (abfd, ghdr)
-     bfd *abfd;
-     Elf_Internal_Shdr *ghdr;
+group_signature (bfd *abfd, Elf_Internal_Shdr *ghdr)
 {
   Elf_Internal_Shdr *hdr;
   unsigned char esym[sizeof (Elf64_External_Sym)];
   Elf_External_Sym_Shndx eshndx;
   Elf_Internal_Sym isym;
-  unsigned int iname;
-  unsigned int shindex;
 
   /* First we need to ensure the symbol table is available.  */
   if (! bfd_section_from_shdr (abfd, ghdr->sh_link))
@@ -487,25 +448,13 @@ group_signature (abfd, ghdr)
                            &isym, esym, &eshndx) == NULL)
     return NULL;
 
-  /* Look up the symbol name.  */
-  iname = isym.st_name;
-  shindex = hdr->sh_link;
-  if (iname == 0 && ELF_ST_TYPE (isym.st_info) == STT_SECTION)
-    {
-      iname = elf_elfsections (abfd)[isym.st_shndx]->sh_name;
-      shindex = elf_elfheader (abfd)->e_shstrndx;
-    }
-
-  return bfd_elf_string_from_elf_section (abfd, shindex, iname);
+  return bfd_elf_local_sym_name (abfd, &isym);
 }
 
 /* Set next_in_group list pointer, and group name for NEWSECT.  */
 
-static boolean
-setup_group (abfd, hdr, newsect)
-     bfd *abfd;
-     Elf_Internal_Shdr *hdr;
-     asection *newsect;
+static bfd_boolean
+setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
 {
   unsigned int num_group = elf_tdata (abfd)->num_group;
 
@@ -537,7 +486,7 @@ setup_group (abfd, hdr, newsect)
          bfd_size_type amt = num_group * sizeof (Elf_Internal_Shdr *);
          elf_tdata (abfd)->group_sect_ptr = bfd_alloc (abfd, amt);
          if (elf_tdata (abfd)->group_sect_ptr == NULL)
-           return false;
+           return FALSE;
 
          num_group = 0;
          for (i = 0; i < shnum; i++)
@@ -560,7 +509,7 @@ setup_group (abfd, hdr, newsect)
                      || bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0
                      || (bfd_bread (shdr->contents, shdr->sh_size, abfd)
                          != shdr->sh_size))
-                   return false;
+                   return FALSE;
 
                  /* Translate raw contents, a flag word followed by an
                     array of elf section indices all in target byte order,
@@ -586,8 +535,7 @@ setup_group (abfd, hdr, newsect)
                      if (idx >= shnum)
                        {
                          ((*_bfd_error_handler)
-                          (_("%s: invalid SHT_GROUP entry"),
-                           bfd_archive_filename (abfd)));
+                          (_("%B: invalid SHT_GROUP entry"), abfd));
                          idx = 0;
                        }
                      dest->shdr = elf_elfsections (abfd)[idx];
@@ -637,7 +585,7 @@ setup_group (abfd, hdr, newsect)
 
                    gname = group_signature (abfd, shdr);
                    if (gname == NULL)
-                     return false;
+                     return FALSE;
                    elf_group_name (newsect) = gname;
 
                    /* Start a circular list with one element.  */
@@ -657,17 +605,65 @@ setup_group (abfd, hdr, newsect)
 
   if (elf_group_name (newsect) == NULL)
     {
-      (*_bfd_error_handler) (_("%s: no group info for section %s"),
-                            bfd_archive_filename (abfd), newsect->name);
+      (*_bfd_error_handler) (_("%B: no group info for section %A"),
+                            abfd, newsect);
     }
-  return true;
+  return TRUE;
 }
 
-boolean
-bfd_elf_discard_group (abfd, group)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     asection *group;
+bfd_boolean
+_bfd_elf_setup_group_pointers (bfd *abfd)
 {
+  unsigned int i;
+  unsigned int num_group = elf_tdata (abfd)->num_group;
+  bfd_boolean result = TRUE;
+
+  if (num_group == (unsigned) -1)
+    return result;
+
+  for (i = 0; i < num_group; i++)
+    {
+      Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i];
+      Elf_Internal_Group *idx = (Elf_Internal_Group *) shdr->contents;
+      unsigned int n_elt = shdr->sh_size / 4;
+
+      while (--n_elt != 0)
+       if ((++idx)->shdr->bfd_section)
+         elf_sec_group (idx->shdr->bfd_section) = shdr->bfd_section;
+       else if (idx->shdr->sh_type == SHT_RELA
+                || idx->shdr->sh_type == SHT_REL)
+         /* We won't include relocation sections in section groups in
+            output object files. We adjust the group section size here
+            so that relocatable link will work correctly when
+            relocation sections are in section group in input object
+            files.  */
+         shdr->bfd_section->size -= 4;
+       else
+         {
+           /* There are some unknown sections in the group.  */
+           (*_bfd_error_handler)
+             (_("%B: unknown [%d] section `%s' in group [%s]"),
+              abfd,
+              (unsigned int) idx->shdr->sh_type,
+              elf_string_from_elf_strtab (abfd, idx->shdr->sh_name),
+              shdr->bfd_section->name);
+           result = FALSE;
+         }
+    }
+  return result;
+}
+
+bfd_boolean
+bfd_elf_is_group_section (bfd *abfd ATTRIBUTE_UNUSED, const asection *sec)
+{
+  return elf_next_in_group (sec) != NULL;
+}
+
+bfd_boolean
+bfd_elf_discard_group (bfd *abfd ATTRIBUTE_UNUSED,
+                      asection *group ATTRIBUTE_UNUSED)
+{
+#if 0
   asection *first = elf_next_in_group (group);
   asection *s = first;
 
@@ -679,32 +675,42 @@ bfd_elf_discard_group (abfd, group)
       if (s == first)
        break;
     }
-  return true;
+#else
+  /* FIXME: Never used. Remove it!  */
+  abort ();
+#endif
+  return TRUE;
 }
 
 /* Make a BFD section from an ELF section.  We store a pointer to the
    BFD section in the bfd_section field of the header.  */
 
-boolean
-_bfd_elf_make_section_from_shdr (abfd, hdr, name)
-     bfd *abfd;
-     Elf_Internal_Shdr *hdr;
-     const char *name;
+bfd_boolean
+_bfd_elf_make_section_from_shdr (bfd *abfd,
+                                Elf_Internal_Shdr *hdr,
+                                const char *name)
 {
   asection *newsect;
   flagword flags;
-  struct elf_backend_data *bed;
+  const struct elf_backend_data *bed;
 
   if (hdr->bfd_section != NULL)
     {
       BFD_ASSERT (strcmp (name,
                          bfd_get_section_name (abfd, hdr->bfd_section)) == 0);
-      return true;
+      return TRUE;
     }
 
   newsect = bfd_make_section_anyway (abfd, name);
   if (newsect == NULL)
-    return false;
+    return FALSE;
+
+  hdr->bfd_section = newsect;
+  elf_section_data (newsect)->this_hdr = *hdr;
+
+  /* Always use the real type/flags.  */
+  elf_section_type (newsect) = hdr->sh_type;
+  elf_section_flags (newsect) = hdr->sh_flags;
 
   newsect->filepos = hdr->sh_offset;
 
@@ -712,7 +718,7 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
       || ! bfd_set_section_size (abfd, newsect, hdr->sh_size)
       || ! bfd_set_section_alignment (abfd, newsect,
                                      bfd_log2 ((bfd_vma) hdr->sh_addralign)))
-    return false;
+    return FALSE;
 
   flags = SEC_NO_FLAGS;
   if (hdr->sh_type != SHT_NOBITS)
@@ -740,7 +746,7 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
     }
   if (hdr->sh_flags & SHF_GROUP)
     if (!setup_group (abfd, hdr, newsect))
-      return false;
+      return FALSE;
   if ((hdr->sh_flags & SHF_TLS) != 0)
     flags |= SEC_THREAD_LOCAL;
 
@@ -777,10 +783,10 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
   bed = get_elf_backend_data (abfd);
   if (bed->elf_backend_section_flags)
     if (! bed->elf_backend_section_flags (&flags, hdr))
-      return false;
+      return FALSE;
 
   if (! bfd_set_section_flags (abfd, newsect, flags))
-    return false;
+    return FALSE;
 
   if ((flags & SEC_ALLOC) != 0)
     {
@@ -848,10 +854,7 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
        }
     }
 
-  hdr->bfd_section = newsect;
-  elf_section_data (newsect)->this_hdr = *hdr;
-
-  return true;
+  return TRUE;
 }
 
 /*
@@ -870,9 +873,7 @@ DESCRIPTION
 */
 
 struct elf_internal_shdr *
-bfd_elf_find_section (abfd, name)
-     bfd *abfd;
-     char *name;
+bfd_elf_find_section (bfd *abfd, char *name)
 {
   Elf_Internal_Shdr **i_shdrp;
   char *shstrtab;
@@ -901,7 +902,7 @@ const char *const bfd_elf_section_type_names[] = {
   "SHT_NOBITS", "SHT_REL", "SHT_SHLIB", "SHT_DYNSYM",
 };
 
-/* ELF relocs are against symbols.  If we are producing relocateable
+/* ELF relocs are against symbols.  If we are producing relocatable
    output, and the reloc is against an external symbol, and nothing
    has given us any additional addend, the resulting reloc will also
    be against the same symbol.  In such a case, we don't want to
@@ -909,25 +910,18 @@ const char *const bfd_elf_section_type_names[] = {
    all be done at final link time.  Rather than put special case code
    into bfd_perform_relocation, all the reloc types use this howto
    function.  It just short circuits the reloc if producing
-   relocateable output against an external symbol.  */
+   relocatable output against an external symbol.  */
 
 bfd_reloc_status_type
-bfd_elf_generic_reloc (abfd,
-                      reloc_entry,
-                      symbol,
-                      data,
-                      input_section,
-                      output_bfd,
-                      error_message)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     arelent *reloc_entry;
-     asymbol *symbol;
-     PTR data ATTRIBUTE_UNUSED;
-     asection *input_section;
-     bfd *output_bfd;
-     char **error_message ATTRIBUTE_UNUSED;
-{
-  if (output_bfd != (bfd *) NULL
+bfd_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+                      arelent *reloc_entry,
+                      asymbol *symbol,
+                      void *data ATTRIBUTE_UNUSED,
+                      asection *input_section,
+                      bfd *output_bfd,
+                      char **error_message ATTRIBUTE_UNUSED)
+{
+  if (output_bfd != NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
       && (! reloc_entry->howto->partial_inplace
          || reloc_entry->addend == 0))
@@ -942,56 +936,67 @@ bfd_elf_generic_reloc (abfd,
 /* Make sure sec_info_type is cleared if sec_info is cleared too.  */
 
 static void
-merge_sections_remove_hook (abfd, sec)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     asection *sec;
+merge_sections_remove_hook (bfd *abfd ATTRIBUTE_UNUSED,
+                           asection *sec)
 {
-  struct bfd_elf_section_data *sec_data;
-
-  sec_data = elf_section_data (sec);
-  BFD_ASSERT (sec_data->sec_info_type == ELF_INFO_TYPE_MERGE);
-  sec_data->sec_info_type = ELF_INFO_TYPE_NONE;
+  BFD_ASSERT (sec->sec_info_type == ELF_INFO_TYPE_MERGE);
+  sec->sec_info_type = ELF_INFO_TYPE_NONE;
 }
 
 /* Finish SHF_MERGE section merging.  */
 
-boolean
-_bfd_elf_merge_sections (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+bfd_boolean
+_bfd_elf_merge_sections (bfd *abfd, struct bfd_link_info *info)
 {
-  if (!is_elf_hash_table (info))
-    return false;
-  if (elf_hash_table (info)->merge_info)
-    _bfd_merge_sections (abfd, elf_hash_table (info)->merge_info,
+  bfd *ibfd;
+  asection *sec;
+
+  if (!is_elf_hash_table (info->hash))
+    return FALSE;
+
+  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+    if ((ibfd->flags & DYNAMIC) == 0)
+      for (sec = ibfd->sections; sec != NULL; sec = sec->next)
+       if ((sec->flags & SEC_MERGE) != 0
+           && !bfd_is_abs_section (sec->output_section))
+         {
+           struct bfd_elf_section_data *secdata;
+
+           secdata = elf_section_data (sec);
+           if (! _bfd_add_merge_section (abfd,
+                                         &elf_hash_table (info)->merge_info,
+                                         sec, &secdata->sec_info))
+             return FALSE;
+           else if (secdata->sec_info)
+             sec->sec_info_type = ELF_INFO_TYPE_MERGE;
+         }
+
+  if (elf_hash_table (info)->merge_info != NULL)
+    _bfd_merge_sections (abfd, info, elf_hash_table (info)->merge_info,
                         merge_sections_remove_hook);
-  return true;
+  return TRUE;
 }
 
 void
-_bfd_elf_link_just_syms (sec, info)
-     asection *sec;
-     struct bfd_link_info *info;
+_bfd_elf_link_just_syms (asection *sec, struct bfd_link_info *info)
 {
   sec->output_section = bfd_abs_section_ptr;
   sec->output_offset = sec->vma;
-  if (!is_elf_hash_table (info))
+  if (!is_elf_hash_table (info->hash))
     return;
 
-  elf_section_data (sec)->sec_info_type = ELF_INFO_TYPE_JUST_SYMS;
+  sec->sec_info_type = ELF_INFO_TYPE_JUST_SYMS;
 }
 \f
 /* Copy the program header and other data from one object module to
    another.  */
 
-boolean
-_bfd_elf_copy_private_bfd_data (ibfd, obfd)
-     bfd *ibfd;
-     bfd *obfd;
+bfd_boolean
+_bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
 {
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return true;
+    return TRUE;
 
   BFD_ASSERT (!elf_flags_init (obfd)
              || (elf_elfheader (obfd)->e_flags
@@ -999,18 +1004,16 @@ _bfd_elf_copy_private_bfd_data (ibfd, obfd)
 
   elf_gp (obfd) = elf_gp (ibfd);
   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
-  elf_flags_init (obfd) = true;
-  return true;
+  elf_flags_init (obfd) = TRUE;
+  return TRUE;
 }
 
 /* Print out the program headers.  */
 
-boolean
-_bfd_elf_print_private_bfd_data (abfd, farg)
-     bfd *abfd;
-     PTR farg;
+bfd_boolean
+_bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
 {
-  FILE *f = (FILE *) farg;
+  FILE *f = farg;
   Elf_Internal_Phdr *p;
   asection *s;
   bfd_byte *dynbuf = NULL;
@@ -1038,6 +1041,8 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
            case PT_PHDR: pt = "PHDR"; break;
            case PT_TLS: pt = "TLS"; break;
            case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break;
+           case PT_GNU_STACK: pt = "STACK"; break;
+           case PT_GNU_RELRO: pt = "RELRO"; break;
            default: sprintf (buf, "0x%lx", p->p_type); pt = buf; break;
            }
          fprintf (f, "%8s off    0x", pt);
@@ -1068,15 +1073,11 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
       unsigned long shlink;
       bfd_byte *extdyn, *extdynend;
       size_t extdynsize;
-      void (*swap_dyn_in) PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *));
+      void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *);
 
       fprintf (f, _("\nDynamic Section:\n"));
 
-      dynbuf = (bfd_byte *) bfd_malloc (s->_raw_size);
-      if (dynbuf == NULL)
-       goto error_return;
-      if (! bfd_get_section_contents (abfd, s, (PTR) dynbuf, (file_ptr) 0,
-                                     s->_raw_size))
+      if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
        goto error_return;
 
       elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
@@ -1088,20 +1089,20 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
       swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
 
       extdyn = dynbuf;
-      extdynend = extdyn + s->_raw_size;
+      extdynend = extdyn + s->size;
       for (; extdyn < extdynend; extdyn += extdynsize)
        {
          Elf_Internal_Dyn dyn;
          const char *name;
          char ab[20];
-         boolean stringp;
+         bfd_boolean stringp;
 
-         (*swap_dyn_in) (abfd, (PTR) extdyn, &dyn);
+         (*swap_dyn_in) (abfd, extdyn, &dyn);
 
          if (dyn.d_tag == DT_NULL)
            break;
 
-         stringp = false;
+         stringp = FALSE;
          switch (dyn.d_tag)
            {
            default:
@@ -1109,7 +1110,7 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
              name = ab;
              break;
 
-           case DT_NEEDED: name = "NEEDED"; stringp = true; break;
+           case DT_NEEDED: name = "NEEDED"; stringp = TRUE; break;
            case DT_PLTRELSZ: name = "PLTRELSZ"; break;
            case DT_PLTGOT: name = "PLTGOT"; break;
            case DT_HASH: name = "HASH"; break;
@@ -1122,8 +1123,8 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
            case DT_SYMENT: name = "SYMENT"; break;
            case DT_INIT: name = "INIT"; break;
            case DT_FINI: name = "FINI"; break;
-           case DT_SONAME: name = "SONAME"; stringp = true; break;
-           case DT_RPATH: name = "RPATH"; stringp = true; break;
+           case DT_SONAME: name = "SONAME"; stringp = TRUE; break;
+           case DT_RPATH: name = "RPATH"; stringp = TRUE; break;
            case DT_SYMBOLIC: name = "SYMBOLIC"; break;
            case DT_REL: name = "REL"; break;
            case DT_RELSZ: name = "RELSZ"; break;
@@ -1137,7 +1138,7 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
            case DT_FINI_ARRAY: name = "FINI_ARRAY"; break;
            case DT_INIT_ARRAYSZ: name = "INIT_ARRAYSZ"; break;
            case DT_FINI_ARRAYSZ: name = "FINI_ARRAYSZ"; break;
-           case DT_RUNPATH: name = "RUNPATH"; stringp = true; break;
+           case DT_RUNPATH: name = "RUNPATH"; stringp = TRUE; break;
            case DT_FLAGS: name = "FLAGS"; break;
            case DT_PREINIT_ARRAY: name = "PREINIT_ARRAY"; break;
            case DT_PREINIT_ARRAYSZ: name = "PREINIT_ARRAYSZ"; break;
@@ -1149,9 +1150,9 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
            case DT_POSFLAG_1: name = "POSFLAG_1"; break;
            case DT_SYMINSZ: name = "SYMINSZ"; break;
            case DT_SYMINENT: name = "SYMINENT"; break;
-           case DT_CONFIG: name = "CONFIG"; stringp = true; break;
-           case DT_DEPAUDIT: name = "DEPAUDIT"; stringp = true; break;
-           case DT_AUDIT: name = "AUDIT"; stringp = true; break;
+           case DT_CONFIG: name = "CONFIG"; stringp = TRUE; break;
+           case DT_DEPAUDIT: name = "DEPAUDIT"; stringp = TRUE; break;
+           case DT_AUDIT: name = "AUDIT"; stringp = TRUE; break;
            case DT_PLTPAD: name = "PLTPAD"; break;
            case DT_MOVETAB: name = "MOVETAB"; break;
            case DT_SYMINFO: name = "SYMINFO"; break;
@@ -1163,9 +1164,9 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
            case DT_VERDEFNUM: name = "VERDEFNUM"; break;
            case DT_VERNEED: name = "VERNEED"; break;
            case DT_VERNEEDNUM: name = "VERNEEDNUM"; break;
-           case DT_AUXILIARY: name = "AUXILIARY"; stringp = true; break;
+           case DT_AUXILIARY: name = "AUXILIARY"; stringp = TRUE; break;
            case DT_USED: name = "USED"; break;
-           case DT_FILTER: name = "FILTER"; stringp = true; break;
+           case DT_FILTER: name = "FILTER"; stringp = TRUE; break;
            }
 
          fprintf (f, "  %-11s ", name);
@@ -1191,8 +1192,8 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
   if ((elf_dynverdef (abfd) != 0 && elf_tdata (abfd)->verdef == NULL)
       || (elf_dynverref (abfd) != 0 && elf_tdata (abfd)->verref == NULL))
     {
-      if (! _bfd_elf_slurp_version_tables (abfd))
-       return false;
+      if (! _bfd_elf_slurp_version_tables (abfd, FALSE))
+       return FALSE;
     }
 
   if (elf_dynverdef (abfd) != 0)
@@ -1234,24 +1235,23 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
        }
     }
 
-  return true;
+  return TRUE;
 
  error_return:
   if (dynbuf != NULL)
     free (dynbuf);
-  return false;
+  return FALSE;
 }
 
 /* Display ELF-specific fields of a symbol.  */
 
 void
-bfd_elf_print_symbol (abfd, filep, symbol, how)
-     bfd *abfd;
-     PTR filep;
-     asymbol *symbol;
-     bfd_print_symbol_type how;
+bfd_elf_print_symbol (bfd *abfd,
+                     void *filep,
+                     asymbol *symbol,
+                     bfd_print_symbol_type how)
 {
-  FILE *file = (FILE *) filep;
+  FILE *file = filep;
   switch (how)
     {
     case bfd_print_symbol_name:
@@ -1266,7 +1266,7 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
       {
        const char *section_name;
        const char *name = NULL;
-       struct elf_backend_data *bed;
+       const struct elf_backend_data *bed;
        unsigned char st_other;
        bfd_vma val;
 
@@ -1279,7 +1279,7 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
        if (name == NULL)
          {
            name = symbol->name;
-           bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
+           bfd_print_symbol_vandf (abfd, file, symbol);
          }
 
        fprintf (file, " %s\t", section_name);
@@ -1368,10 +1368,9 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
 /* Create an entry in an ELF linker hash table.  */
 
 struct bfd_hash_entry *
-_bfd_elf_link_hash_newfunc (entry, table, string)
-     struct bfd_hash_entry *entry;
-     struct bfd_hash_table *table;
-     const char *string;
+_bfd_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
+                           struct bfd_hash_table *table,
+                           const char *string)
 {
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
@@ -1391,24 +1390,15 @@ _bfd_elf_link_hash_newfunc (entry, table, string)
 
       /* Set local fields.  */
       ret->indx = -1;
-      ret->size = 0;
       ret->dynindx = -1;
-      ret->dynstr_index = 0;
-      ret->weakdef = NULL;
-      ret->got.refcount = htab->init_refcount;
-      ret->plt.refcount = htab->init_refcount;
-      ret->linker_section_pointer = NULL;
-      ret->verinfo.verdef = NULL;
-      ret->vtable_entries_used = NULL;
-      ret->vtable_entries_size = 0;
-      ret->vtable_parent = NULL;
-      ret->type = STT_NOTYPE;
-      ret->other = 0;
+      ret->got = ret->plt = htab->init_refcount;
+      memset (&ret->size, 0, (sizeof (struct elf_link_hash_entry)
+                             - offsetof (struct elf_link_hash_entry, size)));
       /* Assume that we have been called by a non-ELF symbol reader.
          This flag is then reset by the code which reads an ELF input
          file.  This ensures that a symbol created by a non-ELF symbol
          reader will have the flag set correctly.  */
-      ret->elf_link_hash_flags = ELF_LINK_NON_ELF;
+      ret->non_elf = 1;
     }
 
   return entry;
@@ -1418,9 +1408,9 @@ _bfd_elf_link_hash_newfunc (entry, table, string)
    old indirect symbol.  Also used for copying flags to a weakdef.  */
 
 void
-_bfd_elf_link_hash_copy_indirect (bed, dir, ind)
-     struct elf_backend_data *bed;
-     struct elf_link_hash_entry *dir, *ind;
+_bfd_elf_link_hash_copy_indirect (const struct elf_backend_data *bed,
+                                 struct elf_link_hash_entry *dir,
+                                 struct elf_link_hash_entry *ind)
 {
   bfd_signed_vma tmp;
   bfd_signed_vma lowest_valid = bed->can_refcount;
@@ -1428,12 +1418,12 @@ _bfd_elf_link_hash_copy_indirect (bed, dir, ind)
   /* Copy down any references that we may have already seen to the
      symbol which just became indirect.  */
 
-  dir->elf_link_hash_flags |=
-    (ind->elf_link_hash_flags
-     & (ELF_LINK_HASH_REF_DYNAMIC
-       | ELF_LINK_HASH_REF_REGULAR
-       | ELF_LINK_HASH_REF_REGULAR_NONWEAK
-       | ELF_LINK_NON_GOT_REF));
+  dir->ref_dynamic |= ind->ref_dynamic;
+  dir->ref_regular |= ind->ref_regular;
+  dir->ref_regular_nonweak |= ind->ref_regular_nonweak;
+  dir->non_got_ref |= ind->non_got_ref;
+  dir->needs_plt |= ind->needs_plt;
+  dir->pointer_equality_needed |= ind->pointer_equality_needed;
 
   if (ind->root.type != bfd_link_hash_indirect)
     return;
@@ -1470,16 +1460,15 @@ _bfd_elf_link_hash_copy_indirect (bed, dir, ind)
 }
 
 void
-_bfd_elf_link_hash_hide_symbol (info, h, force_local)
-     struct bfd_link_info *info;
-     struct elf_link_hash_entry *h;
-     boolean force_local;
+_bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
+                               struct elf_link_hash_entry *h,
+                               bfd_boolean force_local)
 {
-  h->plt.offset = (bfd_vma) -1;
-  h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+  h->plt = elf_hash_table (info)->init_offset;
+  h->needs_plt = 0;
   if (force_local)
     {
-      h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
+      h->forced_local = 1;
       if (h->dynindx != -1)
        {
          h->dynindx = -1;
@@ -1491,31 +1480,39 @@ _bfd_elf_link_hash_hide_symbol (info, h, force_local)
 
 /* Initialize an ELF linker hash table.  */
 
-boolean
-_bfd_elf_link_hash_table_init (table, abfd, newfunc)
-     struct elf_link_hash_table *table;
-     bfd *abfd;
-     struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
-                                               struct bfd_hash_table *,
-                                               const char *));
+bfd_boolean
+_bfd_elf_link_hash_table_init
+  (struct elf_link_hash_table *table,
+   bfd *abfd,
+   struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
+                                     struct bfd_hash_table *,
+                                     const char *))
 {
-  boolean ret;
+  bfd_boolean ret;
 
-  table->dynamic_sections_created = false;
+  table->dynamic_sections_created = FALSE;
   table->dynobj = NULL;
-  table->init_refcount = get_elf_backend_data (abfd)->can_refcount - 1;
+  /* Make sure can_refcount is extended to the width and signedness of
+     init_refcount before we subtract one from it.  */
+  table->init_refcount.refcount = get_elf_backend_data (abfd)->can_refcount;
+  table->init_refcount.refcount -= 1;
+  table->init_offset.offset = -(bfd_vma) 1;
   /* The first dynamic symbol is a dummy.  */
   table->dynsymcount = 1;
   table->dynstr = NULL;
   table->bucketcount = 0;
   table->needed = NULL;
-  table->runpath = NULL;
-  table->loaded = NULL;
   table->hgot = NULL;
-  table->stab_info = NULL;
   table->merge_info = NULL;
+  memset (&table->stab_info, 0, sizeof (table->stab_info));
+  memset (&table->eh_info, 0, sizeof (table->eh_info));
   table->dynlocal = NULL;
-  ret = _bfd_link_hash_table_init (& table->root, abfd, newfunc);
+  table->runpath = NULL;
+  table->tls_sec = NULL;
+  table->tls_size = 0;
+  table->loaded = NULL;
+
+  ret = _bfd_link_hash_table_init (&table->root, abfd, newfunc);
   table->root.type = bfd_link_elf_hash_table;
 
   return ret;
@@ -1524,14 +1521,13 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc)
 /* Create an ELF linker hash table.  */
 
 struct bfd_link_hash_table *
-_bfd_elf_link_hash_table_create (abfd)
-     bfd *abfd;
+_bfd_elf_link_hash_table_create (bfd *abfd)
 {
   struct elf_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct elf_link_hash_table);
 
-  ret = (struct elf_link_hash_table *) bfd_malloc (amt);
-  if (ret == (struct elf_link_hash_table *) NULL)
+  ret = bfd_malloc (amt);
+  if (ret == NULL)
     return NULL;
 
   if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc))
@@ -1545,38 +1541,44 @@ _bfd_elf_link_hash_table_create (abfd)
 
 /* This is a hook for the ELF emulation code in the generic linker to
    tell the backend linker what file name to use for the DT_NEEDED
-   entry for a dynamic object.  The generic linker passes name as an
-   empty string to indicate that no DT_NEEDED entry should be made.  */
+   entry for a dynamic object.  */
 
 void
-bfd_elf_set_dt_needed_name (abfd, name)
-     bfd *abfd;
-     const char *name;
+bfd_elf_set_dt_needed_name (bfd *abfd, const char *name)
 {
   if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
       && bfd_get_format (abfd) == bfd_object)
     elf_dt_name (abfd) = name;
 }
 
+int
+bfd_elf_get_dyn_lib_class (bfd *abfd)
+{
+  int lib_class;
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+      && bfd_get_format (abfd) == bfd_object)
+    lib_class = elf_dyn_lib_class (abfd);
+  else
+    lib_class = 0;
+  return lib_class;
+}
+
 void
-bfd_elf_set_dt_needed_soname (abfd, name)
-     bfd *abfd;
-     const char *name;
+bfd_elf_set_dyn_lib_class (bfd *abfd, int lib_class)
 {
   if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
       && bfd_get_format (abfd) == bfd_object)
-    elf_dt_soname (abfd) = name;
+    elf_dyn_lib_class (abfd) = lib_class;
 }
 
 /* Get the list of DT_NEEDED entries for a link.  This is a hook for
    the linker ELF emulation code.  */
 
 struct bfd_link_needed_list *
-bfd_elf_get_needed_list (abfd, info)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info;
+bfd_elf_get_needed_list (bfd *abfd ATTRIBUTE_UNUSED,
+                        struct bfd_link_info *info)
 {
-  if (info->hash->creator->flavour != bfd_target_elf_flavour)
+  if (! is_elf_hash_table (info->hash))
     return NULL;
   return elf_hash_table (info)->needed;
 }
@@ -1585,11 +1587,10 @@ bfd_elf_get_needed_list (abfd, info)
    hook for the linker ELF emulation code.  */
 
 struct bfd_link_needed_list *
-bfd_elf_get_runpath_list (abfd, info)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info;
+bfd_elf_get_runpath_list (bfd *abfd ATTRIBUTE_UNUSED,
+                         struct bfd_link_info *info)
 {
-  if (info->hash->creator->flavour != bfd_target_elf_flavour)
+  if (! is_elf_hash_table (info->hash))
     return NULL;
   return elf_hash_table (info)->runpath;
 }
@@ -1599,8 +1600,7 @@ bfd_elf_get_runpath_list (abfd, info)
    passed to bfd_elf_set_dt_needed_name, or it is the filename.  */
 
 const char *
-bfd_elf_get_dt_soname (abfd)
-     bfd *abfd;
+bfd_elf_get_dt_soname (bfd *abfd)
 {
   if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
       && bfd_get_format (abfd) == bfd_object)
@@ -1611,10 +1611,9 @@ bfd_elf_get_dt_soname (abfd)
 /* Get the list of DT_NEEDED entries from a BFD.  This is a hook for
    the ELF linker emulation code.  */
 
-boolean
-bfd_elf_get_bfd_needed_list (abfd, pneeded)
-     bfd *abfd;
-     struct bfd_link_needed_list **pneeded;
+bfd_boolean
+bfd_elf_get_bfd_needed_list (bfd *abfd,
+                            struct bfd_link_needed_list **pneeded)
 {
   asection *s;
   bfd_byte *dynbuf = NULL;
@@ -1622,24 +1621,19 @@ bfd_elf_get_bfd_needed_list (abfd, pneeded)
   unsigned long shlink;
   bfd_byte *extdyn, *extdynend;
   size_t extdynsize;
-  void (*swap_dyn_in) PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *));
+  void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *);
 
   *pneeded = NULL;
 
   if (bfd_get_flavour (abfd) != bfd_target_elf_flavour
       || bfd_get_format (abfd) != bfd_object)
-    return true;
+    return TRUE;
 
   s = bfd_get_section_by_name (abfd, ".dynamic");
-  if (s == NULL || s->_raw_size == 0)
-    return true;
-
-  dynbuf = (bfd_byte *) bfd_malloc (s->_raw_size);
-  if (dynbuf == NULL)
-    goto error_return;
+  if (s == NULL || s->size == 0)
+    return TRUE;
 
-  if (! bfd_get_section_contents (abfd, s, (PTR) dynbuf, (file_ptr) 0,
-                                 s->_raw_size))
+  if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
     goto error_return;
 
   elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
@@ -1652,12 +1646,12 @@ bfd_elf_get_bfd_needed_list (abfd, pneeded)
   swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
 
   extdyn = dynbuf;
-  extdynend = extdyn + s->_raw_size;
+  extdynend = extdyn + s->size;
   for (; extdyn < extdynend; extdyn += extdynsize)
     {
       Elf_Internal_Dyn dyn;
 
-      (*swap_dyn_in) (abfd, (PTR) extdyn, &dyn);
+      (*swap_dyn_in) (abfd, extdyn, &dyn);
 
       if (dyn.d_tag == DT_NULL)
        break;
@@ -1674,7 +1668,7 @@ bfd_elf_get_bfd_needed_list (abfd, pneeded)
            goto error_return;
 
          amt = sizeof *l;
-         l = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
+         l = bfd_alloc (abfd, amt);
          if (l == NULL)
            goto error_return;
 
@@ -1687,18 +1681,18 @@ bfd_elf_get_bfd_needed_list (abfd, pneeded)
 
   free (dynbuf);
 
-  return true;
+  return TRUE;
 
  error_return:
   if (dynbuf != NULL)
     free (dynbuf);
-  return false;
+  return FALSE;
 }
 \f
 /* Allocate an ELF string table--force the first byte to be zero.  */
 
 struct bfd_strtab_hash *
-_bfd_elf_stringtab_init ()
+_bfd_elf_stringtab_init (void)
 {
   struct bfd_strtab_hash *ret;
 
@@ -1707,7 +1701,7 @@ _bfd_elf_stringtab_init ()
     {
       bfd_size_type loc;
 
-      loc = _bfd_stringtab_add (ret, "", true, false);
+      loc = _bfd_stringtab_add (ret, "", TRUE, FALSE);
       BFD_ASSERT (loc == 0 || loc == (bfd_size_type) -1);
       if (loc == (bfd_size_type) -1)
        {
@@ -1722,14 +1716,12 @@ _bfd_elf_stringtab_init ()
 
 /* Create a new bfd section from an ELF section header.  */
 
-boolean
-bfd_section_from_shdr (abfd, shindex)
-     bfd *abfd;
-     unsigned int shindex;
+bfd_boolean
+bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
 {
   Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[shindex];
   Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd);
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   const char *name;
 
   name = elf_string_from_elf_strtab (abfd, hdr->sh_name);
@@ -1738,7 +1730,7 @@ bfd_section_from_shdr (abfd, shindex)
     {
     case SHT_NULL:
       /* Inactive section. Throw it away.  */
-      return true;
+      return TRUE;
 
     case SHT_PROGBITS: /* Normal section with contents.  */
     case SHT_NOBITS:   /* .bss section.  */
@@ -1747,11 +1739,12 @@ bfd_section_from_shdr (abfd, shindex)
     case SHT_INIT_ARRAY:       /* .init_array section.  */
     case SHT_FINI_ARRAY:       /* .fini_array section.  */
     case SHT_PREINIT_ARRAY:    /* .preinit_array section.  */
+    case SHT_GNU_LIBLIST:      /* .gnu.liblist section.  */
       return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
 
     case SHT_DYNAMIC:  /* Dynamic linking information.  */
       if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
-       return false;
+       return FALSE;
       if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB)
        {
          Elf_Internal_Shdr *dynsymhdr;
@@ -1784,7 +1777,7 @@ bfd_section_from_shdr (abfd, shindex)
 
     case SHT_SYMTAB:           /* A symbol table */
       if (elf_onesymtab (abfd) == shindex)
-       return true;
+       return TRUE;
 
       BFD_ASSERT (hdr->sh_entsize == bed->s->sizeof_sym);
       BFD_ASSERT (elf_onesymtab (abfd) == 0);
@@ -1797,18 +1790,18 @@ bfd_section_from_shdr (abfd, shindex)
          SHF_ALLOC is set, and this is a shared object, then we also
          treat this section as a BFD section.  We can not base the
          decision purely on SHF_ALLOC, because that flag is sometimes
-         set in a relocateable object file, which would confuse the
+         set in a relocatable object file, which would confuse the
          linker.  */
       if ((hdr->sh_flags & SHF_ALLOC) != 0
          && (abfd->flags & DYNAMIC) != 0
          && ! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
-       return false;
+       return FALSE;
 
-      return true;
+      return TRUE;
 
     case SHT_DYNSYM:           /* A dynamic symbol table */
       if (elf_dynsymtab (abfd) == shindex)
-       return true;
+       return TRUE;
 
       BFD_ASSERT (hdr->sh_entsize == bed->s->sizeof_sym);
       BFD_ASSERT (elf_dynsymtab (abfd) == 0);
@@ -1823,26 +1816,26 @@ bfd_section_from_shdr (abfd, shindex)
 
     case SHT_SYMTAB_SHNDX:     /* Symbol section indices when >64k sections */
       if (elf_symtab_shndx (abfd) == shindex)
-       return true;
+       return TRUE;
 
       /* Get the associated symbol table.  */
       if (! bfd_section_from_shdr (abfd, hdr->sh_link)
          || hdr->sh_link != elf_onesymtab (abfd))
-       return false;
+       return FALSE;
 
       elf_symtab_shndx (abfd) = shindex;
       elf_tdata (abfd)->symtab_shndx_hdr = *hdr;
       elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->symtab_shndx_hdr;
-      return true;
+      return TRUE;
 
     case SHT_STRTAB:           /* A string table */
       if (hdr->bfd_section != NULL)
-       return true;
+       return TRUE;
       if (ehdr->e_shstrndx == shindex)
        {
          elf_tdata (abfd)->shstrtab_hdr = *hdr;
          elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->shstrtab_hdr;
-         return true;
+         return TRUE;
        }
       {
        unsigned int i, num_sec;
@@ -1854,13 +1847,13 @@ bfd_section_from_shdr (abfd, shindex)
            if (hdr2->sh_link == shindex)
              {
                if (! bfd_section_from_shdr (abfd, i))
-                 return false;
+                 return FALSE;
                if (elf_onesymtab (abfd) == i)
                  {
                    elf_tdata (abfd)->strtab_hdr = *hdr;
                    elf_elfsections (abfd)[shindex] =
                      &elf_tdata (abfd)->strtab_hdr;
-                   return true;
+                   return TRUE;
                  }
                if (elf_dynsymtab (abfd) == i)
                  {
@@ -1901,8 +1894,8 @@ bfd_section_from_shdr (abfd, shindex)
            || hdr->sh_link >= num_sec)
          {
            ((*_bfd_error_handler)
-            (_("%s: invalid link %lu for reloc section %s (index %u)"),
-             bfd_archive_filename (abfd), hdr->sh_link, name, shindex));
+            (_("%B: invalid link %lu for reloc section %s (index %u)"),
+             abfd, hdr->sh_link, name, shindex));
            return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
          }
 
@@ -1940,7 +1933,7 @@ bfd_section_from_shdr (abfd, shindex)
        /* Get the symbol table.  */
        if (elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_SYMTAB
            && ! bfd_section_from_shdr (abfd, hdr->sh_link))
-         return false;
+         return FALSE;
 
        /* If this reloc section does not use the main symbol table we
           don't treat it as a reloc section.  BFD can't adequately
@@ -1952,10 +1945,10 @@ bfd_section_from_shdr (abfd, shindex)
          return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
 
        if (! bfd_section_from_shdr (abfd, hdr->sh_info))
-         return false;
+         return FALSE;
        target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info);
        if (target_sect == NULL)
-         return false;
+         return FALSE;
 
        if ((target_sect->flags & SEC_RELOC) == 0
            || target_sect->reloc_count == 0)
@@ -1965,7 +1958,7 @@ bfd_section_from_shdr (abfd, shindex)
            bfd_size_type amt;
            BFD_ASSERT (elf_section_data (target_sect)->rel_hdr2 == NULL);
            amt = sizeof (*hdr2);
-           hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
+           hdr2 = bfd_alloc (abfd, amt);
            elf_section_data (target_sect)->rel_hdr2 = hdr2;
          }
        *hdr2 = *hdr;
@@ -1977,10 +1970,9 @@ bfd_section_from_shdr (abfd, shindex)
        /* In the section to which the relocations apply, mark whether
           its relocations are of the REL or RELA variety.  */
        if (hdr->sh_size != 0)
-         elf_section_data (target_sect)->use_rela_p
-           = (hdr->sh_type == SHT_RELA);
+         target_sect->use_rela_p = hdr->sh_type == SHT_RELA;
        abfd->flags |= HAS_RELOC;
-       return true;
+       return TRUE;
       }
       break;
 
@@ -2003,7 +1995,7 @@ bfd_section_from_shdr (abfd, shindex)
       break;
 
     case SHT_SHLIB:
-      return true;
+      return TRUE;
 
     case SHT_GROUP:
       /* We need a BFD section for objcopy and relocatable linking,
@@ -2011,9 +2003,9 @@ bfd_section_from_shdr (abfd, shindex)
         name.  */
       name = group_signature (abfd, hdr);
       if (name == NULL)
-       return false;
+       return FALSE;
       if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name))
-       return false;
+       return FALSE;
       if (hdr->contents != NULL)
        {
          Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
@@ -2024,8 +2016,10 @@ bfd_section_from_shdr (abfd, shindex)
            hdr->bfd_section->flags
              |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
 
+         /* We try to keep the same section order as it comes in.  */
+         idx += n_elt;
          while (--n_elt != 0)
-           if ((s = (++idx)->shdr->bfd_section) != NULL
+           if ((s = (--idx)->shdr->bfd_section) != NULL
                && elf_next_in_group (s) != NULL)
              {
                elf_next_in_group (hdr->bfd_section) = s;
@@ -2043,18 +2037,17 @@ bfd_section_from_shdr (abfd, shindex)
       break;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Return the section for the local symbol specified by ABFD, R_SYMNDX.
    Return SEC for sections that have no elf section, and NULL on error.  */
 
 asection *
-bfd_section_from_r_symndx (abfd, cache, sec, r_symndx)
-     bfd *abfd;
-     struct sym_sec_cache *cache;
-     asection *sec;
-     unsigned long r_symndx;
+bfd_section_from_r_symndx (bfd *abfd,
+                          struct sym_sec_cache *cache,
+                          asection *sec,
+                          unsigned long r_symndx)
 {
   Elf_Internal_Shdr *symtab_hdr;
   unsigned char esym[sizeof (Elf64_External_Sym)];
@@ -2077,7 +2070,8 @@ bfd_section_from_r_symndx (abfd, cache, sec, r_symndx)
     }
   cache->indx[ent] = r_symndx;
   cache->sec[ent] = sec;
-  if (isym.st_shndx < SHN_LORESERVE || isym.st_shndx > SHN_HIRESERVE)
+  if ((isym.st_shndx != SHN_UNDEF && isym.st_shndx < SHN_LORESERVE)
+      || isym.st_shndx > SHN_HIRESERVE)
     {
       asection *s;
       s = bfd_section_from_elf_index (abfd, isym.st_shndx);
@@ -2091,33 +2085,153 @@ bfd_section_from_r_symndx (abfd, cache, sec, r_symndx)
    section.  */
 
 asection *
-bfd_section_from_elf_index (abfd, index)
-     bfd *abfd;
-     unsigned int index;
+bfd_section_from_elf_index (bfd *abfd, unsigned int index)
 {
   if (index >= elf_numsections (abfd))
     return NULL;
   return elf_elfsections (abfd)[index]->bfd_section;
 }
 
-boolean
-_bfd_elf_new_section_hook (abfd, sec)
-     bfd *abfd;
-     asection *sec;
+static struct bfd_elf_special_section const special_sections[] =
+{
+  { ".bss",            4, -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
+  { ".gnu.linkonce.b",15, -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
+  { ".comment",        8,  0, SHT_PROGBITS, 0 },
+  { ".data",           5, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+  { ".data1",          6,  0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+  { ".debug",          6,  0, SHT_PROGBITS, 0 },
+  { ".fini",           5,  0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+  { ".init",           5,  0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+  { ".line",           5,  0, SHT_PROGBITS, 0 },
+  { ".rodata",         7, -2, SHT_PROGBITS, SHF_ALLOC },
+  { ".rodata1",        8,  0, SHT_PROGBITS, SHF_ALLOC },
+  { ".tbss",           5, -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_TLS },
+  { ".tdata",          6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS },
+  { ".text",           5, -2, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+  { ".init_array",    11,  0, SHT_INIT_ARRAY, SHF_ALLOC + SHF_WRITE },
+  { ".fini_array",    11,  0, SHT_FINI_ARRAY, SHF_ALLOC + SHF_WRITE },
+  { ".preinit_array", 14,  0, SHT_PREINIT_ARRAY, SHF_ALLOC + SHF_WRITE },
+  { ".debug_line",    11,  0, SHT_PROGBITS, 0 },
+  { ".debug_info",    11,  0, SHT_PROGBITS, 0 },
+  { ".debug_abbrev",  13,  0, SHT_PROGBITS, 0 },
+  { ".debug_aranges", 14,  0, SHT_PROGBITS, 0 },
+  { ".dynamic",        8,  0, SHT_DYNAMIC,  SHF_ALLOC },
+  { ".dynstr",         7,  0, SHT_STRTAB,   SHF_ALLOC },
+  { ".dynsym",         7,  0, SHT_DYNSYM,   SHF_ALLOC },
+  { ".got",            4,  0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+  { ".hash",           5,  0, SHT_HASH,     SHF_ALLOC },
+  { ".interp",         7,  0, SHT_PROGBITS, 0 },
+  { ".plt",            4,  0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+  { ".shstrtab",       9,  0, SHT_STRTAB,   0 },
+  { ".strtab",         7,  0, SHT_STRTAB,   0 },
+  { ".symtab",         7,  0, SHT_SYMTAB,   0 },
+  { ".gnu.version",   12,  0, SHT_GNU_versym, 0 },
+  { ".gnu.version_d", 14,  0, SHT_GNU_verdef, 0 },
+  { ".gnu.version_r", 14,  0, SHT_GNU_verneed, 0 },
+  { ".note.GNU-stack",15,  0, SHT_PROGBITS, 0 },
+  { ".note",           5, -1, SHT_NOTE,     0 },
+  { ".rela",           5, -1, SHT_RELA,     0 },
+  { ".rel",            4, -1, SHT_REL,      0 },
+  { ".stabstr",        5,  3, SHT_STRTAB,   0 },
+  { ".gnu.liblist",   12,  0, SHT_GNU_LIBLIST, SHF_ALLOC },
+  { ".gnu.conflict",  13,  0, SHT_RELA,     SHF_ALLOC },
+  { NULL,              0,  0, 0,            0 }
+};
+
+static const struct bfd_elf_special_section *
+get_special_section (const char *name,
+                    const struct bfd_elf_special_section *special_sections,
+                    unsigned int rela)
+{
+  int i;
+  int len = strlen (name);
+
+  for (i = 0; special_sections[i].prefix != NULL; i++)
+    {
+      int suffix_len;
+      int prefix_len = special_sections[i].prefix_length;
+
+      if (len < prefix_len)
+       continue;
+      if (memcmp (name, special_sections[i].prefix, prefix_len) != 0)
+       continue;
+
+      suffix_len = special_sections[i].suffix_length;
+      if (suffix_len <= 0)
+       {
+         if (name[prefix_len] != 0)
+           {
+             if (suffix_len == 0)
+               continue;
+             if (name[prefix_len] != '.'
+                 && (suffix_len == -2
+                     || (rela && special_sections[i].type == SHT_REL)))
+               continue;
+           }
+       }
+      else
+       {
+         if (len < prefix_len + suffix_len)
+           continue;
+         if (memcmp (name + len - suffix_len,
+                     special_sections[i].prefix + prefix_len,
+                     suffix_len) != 0)
+           continue;
+       }
+      return &special_sections[i];
+    }
+
+  return NULL;
+}
+
+const struct bfd_elf_special_section *
+_bfd_elf_get_sec_type_attr (bfd *abfd, const char *name)
+{
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  const struct bfd_elf_special_section *ssect = NULL;
+
+  /* See if this is one of the special sections.  */
+  if (name)
+    {
+      unsigned int rela = bed->default_use_rela_p;
+
+      if (bed->special_sections)
+       ssect = get_special_section (name, bed->special_sections, rela);
+
+      if (! ssect)
+       ssect = get_special_section (name, special_sections, rela);
+    }
+
+  return ssect;
+}
+
+bfd_boolean
+_bfd_elf_new_section_hook (bfd *abfd, asection *sec)
 {
   struct bfd_elf_section_data *sdata;
-  bfd_size_type amt = sizeof (*sdata);
+  const struct bfd_elf_special_section *ssect;
 
-  sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd, amt);
-  if (!sdata)
-    return false;
-  sec->used_by_bfd = (PTR) sdata;
+  sdata = (struct bfd_elf_section_data *) sec->used_by_bfd;
+  if (sdata == NULL)
+    {
+      sdata = bfd_zalloc (abfd, sizeof (*sdata));
+      if (sdata == NULL)
+       return FALSE;
+      sec->used_by_bfd = sdata;
+    }
+
+  elf_section_type (sec) = SHT_NULL;
+  ssect = _bfd_elf_get_sec_type_attr (abfd, sec->name);
+  if (ssect != NULL)
+    {
+      elf_section_type (sec) = ssect->type;
+      elf_section_flags (sec) = ssect->attr;
+    }
 
   /* Indicate whether or not this section should use RELA relocations.  */
-  sdata->use_rela_p
-    = get_elf_backend_data (abfd)->default_use_rela_p;
+  sec->use_rela_p = get_elf_backend_data (abfd)->default_use_rela_p;
 
-  return true;
+  return TRUE;
 }
 
 /* Create a new bfd section from an ELF program header.
@@ -2142,12 +2256,11 @@ _bfd_elf_new_section_hook (abfd, sec)
 
  */
 
-boolean
-_bfd_elf_make_section_from_phdr (abfd, hdr, index, typename)
-     bfd *abfd;
-     Elf_Internal_Phdr *hdr;
-     int index;
-     const char *typename;
+bfd_boolean
+_bfd_elf_make_section_from_phdr (bfd *abfd,
+                                Elf_Internal_Phdr *hdr,
+                                int index,
+                                const char *typename)
 {
   asection *newsect;
   char *name;
@@ -2160,18 +2273,19 @@ _bfd_elf_make_section_from_phdr (abfd, hdr, index, typename)
            && (hdr->p_memsz > hdr->p_filesz));
   sprintf (namebuf, "%s%d%s", typename, index, split ? "a" : "");
   len = strlen (namebuf) + 1;
-  name = bfd_alloc (abfd, (bfd_size_type) len);
+  name = bfd_alloc (abfd, len);
   if (!name)
-    return false;
+    return FALSE;
   memcpy (name, namebuf, len);
   newsect = bfd_make_section (abfd, name);
   if (newsect == NULL)
-    return false;
+    return FALSE;
   newsect->vma = hdr->p_vaddr;
   newsect->lma = hdr->p_paddr;
-  newsect->_raw_size = hdr->p_filesz;
+  newsect->size = hdr->p_filesz;
   newsect->filepos = hdr->p_offset;
   newsect->flags |= SEC_HAS_CONTENTS;
+  newsect->alignment_power = bfd_log2 (hdr->p_align);
   if (hdr->p_type == PT_LOAD)
     {
       newsect->flags |= SEC_ALLOC;
@@ -2192,16 +2306,16 @@ _bfd_elf_make_section_from_phdr (abfd, hdr, index, typename)
     {
       sprintf (namebuf, "%s%db", typename, index);
       len = strlen (namebuf) + 1;
-      name = bfd_alloc (abfd, (bfd_size_type) len);
+      name = bfd_alloc (abfd, len);
       if (!name)
-       return false;
+       return FALSE;
       memcpy (name, namebuf, len);
       newsect = bfd_make_section (abfd, name);
       if (newsect == NULL)
-       return false;
+       return FALSE;
       newsect->vma = hdr->p_vaddr + hdr->p_filesz;
       newsect->lma = hdr->p_paddr + hdr->p_filesz;
-      newsect->_raw_size = hdr->p_memsz - hdr->p_filesz;
+      newsect->size = hdr->p_memsz - hdr->p_filesz;
       if (hdr->p_type == PT_LOAD)
        {
          newsect->flags |= SEC_ALLOC;
@@ -2212,16 +2326,13 @@ _bfd_elf_make_section_from_phdr (abfd, hdr, index, typename)
        newsect->flags |= SEC_READONLY;
     }
 
-  return true;
+  return TRUE;
 }
 
-boolean
-bfd_section_from_phdr (abfd, hdr, index)
-     bfd *abfd;
-     Elf_Internal_Phdr *hdr;
-     int index;
+bfd_boolean
+bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int index)
 {
-  struct elf_backend_data *bed;
+  const struct elf_backend_data *bed;
 
   switch (hdr->p_type)
     {
@@ -2239,10 +2350,10 @@ bfd_section_from_phdr (abfd, hdr, index)
 
     case PT_NOTE:
       if (! _bfd_elf_make_section_from_phdr (abfd, hdr, index, "note"))
-       return false;
-      if (! elfcore_read_notes (abfd, (file_ptr) hdr->p_offset, hdr->p_filesz))
-       return false;
-      return true;
+       return FALSE;
+      if (! elfcore_read_notes (abfd, hdr->p_offset, hdr->p_filesz))
+       return FALSE;
+      return TRUE;
 
     case PT_SHLIB:
       return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "shlib");
@@ -2250,6 +2361,16 @@ bfd_section_from_phdr (abfd, hdr, index)
     case PT_PHDR:
       return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "phdr");
 
+    case PT_GNU_EH_FRAME:
+      return _bfd_elf_make_section_from_phdr (abfd, hdr, index,
+                                             "eh_frame_hdr");
+
+    case PT_GNU_STACK:
+      return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "stack");
+
+    case PT_GNU_RELRO:
+      return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "relro");
+
     default:
       /* Check for any processor-specific program segment types.
          If no handler for them, default to making "segment" sections.  */
@@ -2262,52 +2383,48 @@ bfd_section_from_phdr (abfd, hdr, index)
 }
 
 /* Initialize REL_HDR, the section-header for new section, containing
-   relocations against ASECT.  If USE_RELA_P is true, we use RELA
+   relocations against ASECT.  If USE_RELA_P is TRUE, we use RELA
    relocations; otherwise, we use REL relocations.  */
 
-boolean
-_bfd_elf_init_reloc_shdr (abfd, rel_hdr, asect, use_rela_p)
-     bfd *abfd;
-     Elf_Internal_Shdr *rel_hdr;
-     asection *asect;
-     boolean use_rela_p;
+bfd_boolean
+_bfd_elf_init_reloc_shdr (bfd *abfd,
+                         Elf_Internal_Shdr *rel_hdr,
+                         asection *asect,
+                         bfd_boolean use_rela_p)
 {
   char *name;
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   bfd_size_type amt = sizeof ".rela" + strlen (asect->name);
 
   name = bfd_alloc (abfd, amt);
   if (name == NULL)
-    return false;
+    return FALSE;
   sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name);
   rel_hdr->sh_name =
     (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), name,
-                                       false);
+                                       FALSE);
   if (rel_hdr->sh_name == (unsigned int) -1)
-    return false;
+    return FALSE;
   rel_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL;
   rel_hdr->sh_entsize = (use_rela_p
                         ? bed->s->sizeof_rela
                         : bed->s->sizeof_rel);
-  rel_hdr->sh_addralign = bed->s->file_align;
+  rel_hdr->sh_addralign = 1 << bed->s->log_file_align;
   rel_hdr->sh_flags = 0;
   rel_hdr->sh_addr = 0;
   rel_hdr->sh_size = 0;
   rel_hdr->sh_offset = 0;
 
-  return true;
+  return TRUE;
 }
 
 /* Set up an ELF internal section header for a section.  */
 
 static void
-elf_fake_sections (abfd, asect, failedptrarg)
-     bfd *abfd;
-     asection *asect;
-     PTR failedptrarg;
+elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
 {
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  boolean *failedptr = (boolean *) failedptrarg;
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  bfd_boolean *failedptr = failedptrarg;
   Elf_Internal_Shdr *this_hdr;
 
   if (*failedptr)
@@ -2319,11 +2436,11 @@ elf_fake_sections (abfd, asect, failedptrarg)
 
   this_hdr = &elf_section_data (asect)->this_hdr;
 
-  this_hdr->sh_name = (unsigned long) _bfd_elf_strtab_add (elf_shstrtab (abfd),
-                                                          asect->name, false);
-  if (this_hdr->sh_name == (unsigned long) -1)
+  this_hdr->sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
+                                                         asect->name, FALSE);
+  if (this_hdr->sh_name == (unsigned int) -1)
     {
-      *failedptr = true;
+      *failedptr = TRUE;
       return;
     }
 
@@ -2336,7 +2453,7 @@ elf_fake_sections (abfd, asect, failedptrarg)
     this_hdr->sh_addr = 0;
 
   this_hdr->sh_offset = 0;
-  this_hdr->sh_size = asect->_raw_size;
+  this_hdr->sh_size = asect->size;
   this_hdr->sh_link = 0;
   this_hdr->sh_addralign = 1 << asect->alignment_power;
   /* The sh_entsize and sh_info fields may have been set already by
@@ -2345,55 +2462,83 @@ elf_fake_sections (abfd, asect, failedptrarg)
   this_hdr->bfd_section = asect;
   this_hdr->contents = NULL;
 
-  /* FIXME: This should not be based on section names.  */
-  if (strcmp (asect->name, ".dynstr") == 0)
-    this_hdr->sh_type = SHT_STRTAB;
-  else if (strcmp (asect->name, ".hash") == 0)
+  /* If the section type is unspecified, we set it based on
+     asect->flags.  */
+  if (this_hdr->sh_type == SHT_NULL)
     {
-      this_hdr->sh_type = SHT_HASH;
-      this_hdr->sh_entsize = bed->s->sizeof_hash_entry;
+      if ((asect->flags & SEC_GROUP) != 0)
+       {
+         /* We also need to mark SHF_GROUP here for relocatable
+            link.  */
+         struct bfd_link_order *l;
+         asection *elt;
+
+         for (l = asect->link_order_head; l != NULL; l = l->next)
+           if (l->type == bfd_indirect_link_order
+               && (elt = elf_next_in_group (l->u.indirect.section)) != NULL)
+             do
+               {
+                 /* The name is not important. Anything will do.  */
+                 elf_group_name (elt->output_section) = "G";
+                 elf_section_flags (elt->output_section) |= SHF_GROUP;
+
+                 elt = elf_next_in_group (elt);
+                 /* During a relocatable link, the lists are
+                    circular.  */
+               }
+             while (elt != elf_next_in_group (l->u.indirect.section));
+
+         this_hdr->sh_type = SHT_GROUP;
+       }
+      else if ((asect->flags & SEC_ALLOC) != 0
+         && (((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+             || (asect->flags & SEC_NEVER_LOAD) != 0))
+       this_hdr->sh_type = SHT_NOBITS;
+      else
+       this_hdr->sh_type = SHT_PROGBITS;
     }
-  else if (strcmp (asect->name, ".dynsym") == 0)
+
+  switch (this_hdr->sh_type)
     {
-      this_hdr->sh_type = SHT_DYNSYM;
+    default:
+      break;
+
+    case SHT_STRTAB:
+    case SHT_INIT_ARRAY:
+    case SHT_FINI_ARRAY:
+    case SHT_PREINIT_ARRAY:
+    case SHT_NOTE:
+    case SHT_NOBITS:
+    case SHT_PROGBITS:
+      break;
+
+    case SHT_HASH:
+      this_hdr->sh_entsize = bed->s->sizeof_hash_entry;
+      break;
+
+    case SHT_DYNSYM:
       this_hdr->sh_entsize = bed->s->sizeof_sym;
-    }
-  else if (strcmp (asect->name, ".dynamic") == 0)
-    {
-      this_hdr->sh_type = SHT_DYNAMIC;
+      break;
+
+    case SHT_DYNAMIC:
       this_hdr->sh_entsize = bed->s->sizeof_dyn;
-    }
-  else if (strncmp (asect->name, ".rela", 5) == 0
-          && get_elf_backend_data (abfd)->may_use_rela_p)
-    {
-      this_hdr->sh_type = SHT_RELA;
-      this_hdr->sh_entsize = bed->s->sizeof_rela;
-    }
-  else if (strncmp (asect->name, ".rel", 4) == 0
-          && get_elf_backend_data (abfd)->may_use_rel_p)
-    {
-      this_hdr->sh_type = SHT_REL;
-      this_hdr->sh_entsize = bed->s->sizeof_rel;
-    }
-  else if (strcmp (asect->name, ".init_array") == 0)
-    this_hdr->sh_type = SHT_INIT_ARRAY;
-  else if (strcmp (asect->name, ".fini_array") == 0)
-    this_hdr->sh_type = SHT_FINI_ARRAY;
-  else if (strcmp (asect->name, ".preinit_array") == 0)
-    this_hdr->sh_type = SHT_PREINIT_ARRAY;
-  else if (strncmp (asect->name, ".note", 5) == 0)
-    this_hdr->sh_type = SHT_NOTE;
-  else if (strncmp (asect->name, ".stab", 5) == 0
-          && strcmp (asect->name + strlen (asect->name) - 3, "str") == 0)
-    this_hdr->sh_type = SHT_STRTAB;
-  else if (strcmp (asect->name, ".gnu.version") == 0)
-    {
-      this_hdr->sh_type = SHT_GNU_versym;
+      break;
+
+    case SHT_RELA:
+      if (get_elf_backend_data (abfd)->may_use_rela_p)
+       this_hdr->sh_entsize = bed->s->sizeof_rela;
+      break;
+
+     case SHT_REL:
+      if (get_elf_backend_data (abfd)->may_use_rel_p)
+       this_hdr->sh_entsize = bed->s->sizeof_rel;
+      break;
+
+     case SHT_GNU_versym:
       this_hdr->sh_entsize = sizeof (Elf_External_Versym);
-    }
-  else if (strcmp (asect->name, ".gnu.version_d") == 0)
-    {
-      this_hdr->sh_type = SHT_GNU_verdef;
+      break;
+
+     case SHT_GNU_verdef:
       this_hdr->sh_entsize = 0;
       /* objcopy or strip will copy over sh_info, but may not set
          cverdefs.  The linker will set cverdefs, but sh_info will be
@@ -2403,10 +2548,9 @@ elf_fake_sections (abfd, asect, failedptrarg)
       else
        BFD_ASSERT (elf_tdata (abfd)->cverdefs == 0
                    || this_hdr->sh_info == elf_tdata (abfd)->cverdefs);
-    }
-  else if (strcmp (asect->name, ".gnu.version_r") == 0)
-    {
-      this_hdr->sh_type = SHT_GNU_verneed;
+      break;
+
+    case SHT_GNU_verneed:
       this_hdr->sh_entsize = 0;
       /* objcopy or strip will copy over sh_info, but may not set
          cverrefs.  The linker will set cverrefs, but sh_info will be
@@ -2416,18 +2560,12 @@ elf_fake_sections (abfd, asect, failedptrarg)
       else
        BFD_ASSERT (elf_tdata (abfd)->cverrefs == 0
                    || this_hdr->sh_info == elf_tdata (abfd)->cverrefs);
-    }
-  else if ((asect->flags & SEC_GROUP) != 0)
-    {
-      this_hdr->sh_type = SHT_GROUP;
+      break;
+
+    case SHT_GROUP:
       this_hdr->sh_entsize = 4;
+      break;
     }
-  else if ((asect->flags & SEC_ALLOC) != 0
-          && (((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
-              || (asect->flags & SEC_NEVER_LOAD) != 0))
-    this_hdr->sh_type = SHT_NOBITS;
-  else
-    this_hdr->sh_type = SHT_PROGBITS;
 
   if ((asect->flags & SEC_ALLOC) != 0)
     this_hdr->sh_flags |= SHF_ALLOC;
@@ -2447,10 +2585,10 @@ elf_fake_sections (abfd, asect, failedptrarg)
   if ((asect->flags & SEC_THREAD_LOCAL) != 0)
     {
       this_hdr->sh_flags |= SHF_TLS;
-      if (asect->_raw_size == 0 && (asect->flags & SEC_HAS_CONTENTS) == 0)
+      if (asect->size == 0 && (asect->flags & SEC_HAS_CONTENTS) == 0)
        {
          struct bfd_link_order *o;
-                                          
+
          this_hdr->sh_size = 0;
          for (o = asect->link_order_head; o != NULL; o = o->next)
            if (this_hdr->sh_size < o->offset + o->size)
@@ -2463,7 +2601,7 @@ elf_fake_sections (abfd, asect, failedptrarg)
   /* Check for processor-specific section types.  */
   if (bed->elf_backend_fake_sections
       && !(*bed->elf_backend_fake_sections) (abfd, this_hdr, asect))
-    *failedptr = true;
+    *failedptr = TRUE;
 
   /* If the section has relocs, set up a section header for the
      SHT_REL[A] section.  If two relocation sections are required for
@@ -2473,24 +2611,21 @@ elf_fake_sections (abfd, asect, failedptrarg)
       && !_bfd_elf_init_reloc_shdr (abfd,
                                    &elf_section_data (asect)->rel_hdr,
                                    asect,
-                                   elf_section_data (asect)->use_rela_p))
-    *failedptr = true;
+                                   asect->use_rela_p))
+    *failedptr = TRUE;
 }
 
 /* Fill in the contents of a SHT_GROUP section.  */
 
 void
-bfd_elf_set_group_contents (abfd, sec, failedptrarg)
-     bfd *abfd;
-     asection *sec;
-     PTR failedptrarg;
+bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg)
 {
-  boolean *failedptr = (boolean *) failedptrarg;
+  bfd_boolean *failedptr = failedptrarg;
   unsigned long symindx;
   asection *elt, *first;
   unsigned char *loc;
   struct bfd_link_order *l;
-  boolean gas;
+  bfd_boolean gas;
 
   if (elf_section_data (sec)->this_hdr.sh_type != SHT_GROUP
       || *failedptr)
@@ -2512,22 +2647,22 @@ bfd_elf_set_group_contents (abfd, sec, failedptrarg)
   elf_section_data (sec)->this_hdr.sh_info = symindx;
 
   /* The contents won't be allocated for "ld -r" or objcopy.  */
-  gas = true;
+  gas = TRUE;
   if (sec->contents == NULL)
     {
-      gas = false;
-      sec->contents = bfd_alloc (abfd, sec->_raw_size);
+      gas = FALSE;
+      sec->contents = bfd_alloc (abfd, sec->size);
 
       /* Arrange for the section to be written out.  */
       elf_section_data (sec)->this_hdr.contents = sec->contents;
       if (sec->contents == NULL)
        {
-         *failedptr = true;
+         *failedptr = TRUE;
          return;
        }
     }
 
-  loc = sec->contents + sec->_raw_size;
+  loc = sec->contents + sec->size;
 
   /* Get the pointer to the first section in the group that gas
      squirreled away here.  objcopy arranges for this to be set to the
@@ -2572,13 +2707,7 @@ bfd_elf_set_group_contents (abfd, sec, failedptrarg)
        }
       while (elt != elf_next_in_group (l->u.indirect.section));
 
-  /* With ld -r, merging SHT_GROUP sections results in wasted space
-     due to allowing for the flag word on each input.  We may well
-     duplicate entries too.  */
-  while ((loc -= 4) > sec->contents)
-    H_PUT_32 (abfd, 0, loc);
-
-  if (loc != sec->contents)
+  if ((loc -= 4) != sec->contents)
     abort ();
 
   H_PUT_32 (abfd, sec->flags & SEC_LINK_ONCE ? GRP_COMDAT : 0, loc);
@@ -2588,9 +2717,8 @@ bfd_elf_set_group_contents (abfd, sec, failedptrarg)
    too.  The link/info pointers for the standard section types are filled
    in here too, while we're at it.  */
 
-static boolean
-assign_section_numbers (abfd)
-     bfd *abfd;
+static bfd_boolean
+assign_section_numbers (bfd *abfd)
 {
   struct elf_obj_tdata *t = elf_tdata (abfd);
   asection *sec;
@@ -2650,9 +2778,9 @@ assign_section_numbers (abfd)
          t->symtab_shndx_section = section_number++;
          t->symtab_shndx_hdr.sh_name
            = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
-                                                 ".symtab_shndx", false);
+                                                 ".symtab_shndx", FALSE);
          if (t->symtab_shndx_hdr.sh_name == (unsigned int) -1)
-           return false;
+           return FALSE;
        }
       if (section_number == SHN_LORESERVE)
        section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
@@ -2671,18 +2799,17 @@ assign_section_numbers (abfd)
   /* Set up the list of section header pointers, in agreement with the
      indices.  */
   amt = section_number * sizeof (Elf_Internal_Shdr *);
-  i_shdrp = (Elf_Internal_Shdr **) bfd_alloc (abfd, amt);
+  i_shdrp = bfd_zalloc (abfd, amt);
   if (i_shdrp == NULL)
-    return false;
+    return FALSE;
 
   amt = sizeof (Elf_Internal_Shdr);
-  i_shdrp[0] = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
+  i_shdrp[0] = bfd_zalloc (abfd, amt);
   if (i_shdrp[0] == NULL)
     {
       bfd_release (abfd, i_shdrp);
-      return false;
+      return FALSE;
     }
-  memset (i_shdrp[0], 0, sizeof (Elf_Internal_Shdr));
 
   elf_elfsections (abfd) = i_shdrp;
 
@@ -2698,6 +2825,7 @@ assign_section_numbers (abfd)
       i_shdrp[t->strtab_section] = &t->strtab_hdr;
       t->symtab_hdr.sh_link = t->strtab_section;
     }
+
   for (sec = abfd->sections; sec; sec = sec->next)
     {
       struct bfd_elf_section_data *d = elf_section_data (sec);
@@ -2726,6 +2854,56 @@ assign_section_numbers (abfd)
          d->rel_hdr2->sh_info = d->this_idx;
        }
 
+      /* We need to set up sh_link for SHF_LINK_ORDER.  */
+      if ((d->this_hdr.sh_flags & SHF_LINK_ORDER) != 0)
+       {
+         s = elf_linked_to_section (sec);
+         if (s)
+           d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+         else
+           {
+             struct bfd_link_order *p;
+
+             /* Find out what the corresponding section in output
+                is.  */
+             for (p = sec->link_order_head; p != NULL; p = p->next)
+               {
+                 s = p->u.indirect.section;
+                 if (p->type == bfd_indirect_link_order
+                     && (bfd_get_flavour (s->owner)
+                         == bfd_target_elf_flavour))
+                   {
+                     Elf_Internal_Shdr ** const elf_shdrp
+                       = elf_elfsections (s->owner);
+                     int elfsec
+                       = _bfd_elf_section_from_bfd_section (s->owner, s);
+                     elfsec = elf_shdrp[elfsec]->sh_link;
+                     /* PR 290:
+                        The Intel C compiler generates SHT_IA_64_UNWIND with
+                        SHF_LINK_ORDER.  But it doesn't set theh sh_link or
+                        sh_info fields.  Hence we could get the situation
+                        where elfsec is 0.  */
+                     if (elfsec == 0)
+                       {
+                         const struct elf_backend_data *bed
+                           = get_elf_backend_data (abfd);
+                         if (bed->link_order_error_handler)
+                           bed->link_order_error_handler
+                             (_("%B: warning: sh_link not set for section `%S'"),
+                              abfd, s);
+                       }
+                     else
+                       {
+                         s = elf_shdrp[elfsec]->bfd_section->output_section;
+                         BFD_ASSERT (s != NULL);
+                         d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+                       }
+                     break;
+                   }
+               }
+           }
+       }
+
       switch (d->this_hdr.sh_type)
        {
        case SHT_REL:
@@ -2763,9 +2941,9 @@ assign_section_numbers (abfd)
              char *alc;
 
              len = strlen (sec->name);
-             alc = (char *) bfd_malloc ((bfd_size_type) (len - 2));
+             alc = bfd_malloc (len - 2);
              if (alc == NULL)
-               return false;
+               return FALSE;
              memcpy (alc, sec->name, len - 3);
              alc[len - 3] = '\0';
              s = bfd_get_section_by_name (abfd, alc);
@@ -2794,6 +2972,17 @@ assign_section_numbers (abfd)
            d->this_hdr.sh_link = elf_section_data (s)->this_idx;
          break;
 
+       case SHT_GNU_LIBLIST:
+         /* sh_link is the section header index of the prelink library
+            list 
+            used for the dynamic entries, or the symbol table, or the
+            version strings.  */
+         s = bfd_get_section_by_name (abfd, (sec->flags & SEC_ALLOC)
+                                            ? ".dynstr" : ".gnu.libstr");
+         if (s != NULL)
+           d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+         break;
+
        case SHT_HASH:
        case SHT_GNU_versym:
          /* sh_link is the section header index of the symbol table
@@ -2814,30 +3003,27 @@ assign_section_numbers (abfd)
     else
       i_shdrp[secn]->sh_name = _bfd_elf_strtab_offset (elf_shstrtab (abfd),
                                                       i_shdrp[secn]->sh_name);
-  return true;
+  return TRUE;
 }
 
 /* Map symbol from it's internal number to the external number, moving
    all local symbols to be at the head of the list.  */
 
-static INLINE int
-sym_is_global (abfd, sym)
-     bfd *abfd;
-     asymbol *sym;
+static int
+sym_is_global (bfd *abfd, asymbol *sym)
 {
   /* If the backend has a special mapping, use it.  */
-  if (get_elf_backend_data (abfd)->elf_backend_sym_is_global)
-    return ((*get_elf_backend_data (abfd)->elf_backend_sym_is_global)
-           (abfd, sym));
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  if (bed->elf_backend_sym_is_global)
+    return (*bed->elf_backend_sym_is_global) (abfd, sym);
 
   return ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
          || bfd_is_und_section (bfd_get_section (sym))
          || bfd_is_com_section (bfd_get_section (sym)));
 }
 
-static boolean
-elf_map_symbols (abfd)
-     bfd *abfd;
+static bfd_boolean
+elf_map_symbols (bfd *abfd)
 {
   unsigned int symcount = bfd_get_symcount (abfd);
   asymbol **syms = bfd_get_outsymbols (abfd);
@@ -2865,9 +3051,9 @@ elf_map_symbols (abfd)
 
   max_index++;
   amt = max_index * sizeof (asymbol *);
-  sect_syms = (asymbol **) bfd_zalloc (abfd, amt);
+  sect_syms = bfd_zalloc (abfd, amt);
   if (sect_syms == NULL)
-    return false;
+    return FALSE;
   elf_section_syms (abfd) = sect_syms;
   elf_num_section_syms (abfd) = max_index;
 
@@ -2939,10 +3125,10 @@ elf_map_symbols (abfd)
 
   /* Now sort the symbols so the local symbols are first.  */
   amt = (num_locals + num_globals) * sizeof (asymbol *);
-  new_syms = (asymbol **) bfd_alloc (abfd, amt);
+  new_syms = bfd_alloc (abfd, amt);
 
   if (new_syms == NULL)
-    return false;
+    return FALSE;
 
   for (idx = 0; idx < symcount; idx++)
     {
@@ -2977,17 +3163,14 @@ elf_map_symbols (abfd)
 
   elf_num_locals (abfd) = num_locals;
   elf_num_globals (abfd) = num_globals;
-  return true;
+  return TRUE;
 }
 
 /* Align to the maximum file alignment that could be required for any
    ELF data structure.  */
 
-static INLINE file_ptr align_file_position PARAMS ((file_ptr, int));
-static INLINE file_ptr
-align_file_position (off, align)
-     file_ptr off;
-     int align;
+static inline file_ptr
+align_file_position (file_ptr off, int align)
 {
   return (off + align - 1) & ~(align - 1);
 }
@@ -2995,11 +3178,10 @@ align_file_position (off, align)
 /* Assign a file position to a section, optionally aligning to the
    required section alignment.  */
 
-INLINE file_ptr
-_bfd_elf_assign_file_position_for_section (i_shdrp, offset, align)
-     Elf_Internal_Shdr *i_shdrp;
-     file_ptr offset;
-     boolean align;
+file_ptr
+_bfd_elf_assign_file_position_for_section (Elf_Internal_Shdr *i_shdrp,
+                                          file_ptr offset,
+                                          bfd_boolean align)
 {
   if (align)
     {
@@ -3021,37 +3203,36 @@ _bfd_elf_assign_file_position_for_section (i_shdrp, offset, align)
    otherwise prepare to begin writing out the ELF file.  If LINK_INFO
    is not NULL, this is being called by the ELF backend linker.  */
 
-boolean
-_bfd_elf_compute_section_file_positions (abfd, link_info)
-     bfd *abfd;
-     struct bfd_link_info *link_info;
+bfd_boolean
+_bfd_elf_compute_section_file_positions (bfd *abfd,
+                                        struct bfd_link_info *link_info)
 {
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  boolean failed;
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  bfd_boolean failed;
   struct bfd_strtab_hash *strtab;
   Elf_Internal_Shdr *shstrtab_hdr;
 
   if (abfd->output_has_begun)
-    return true;
+    return TRUE;
 
   /* Do any elf backend specific processing first.  */
   if (bed->elf_backend_begin_write_processing)
     (*bed->elf_backend_begin_write_processing) (abfd, link_info);
 
   if (! prep_headers (abfd))
-    return false;
+    return FALSE;
 
   /* Post process the headers if necessary.  */
   if (bed->elf_backend_post_process_headers)
     (*bed->elf_backend_post_process_headers) (abfd, link_info);
 
-  failed = false;
+  failed = FALSE;
   bfd_map_over_sections (abfd, elf_fake_sections, &failed);
   if (failed)
-    return false;
+    return FALSE;
 
   if (!assign_section_numbers (abfd))
-    return false;
+    return FALSE;
 
   /* The backend linker builds symbol table information itself.  */
   if (link_info == NULL && bfd_get_symcount (abfd) > 0)
@@ -3060,14 +3241,14 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
       int relocatable_p = ! (abfd->flags & (EXEC_P | DYNAMIC));
 
       if (! swap_out_syms (abfd, &strtab, relocatable_p))
-       return false;
+       return FALSE;
     }
 
   if (link_info == NULL)
     {
       bfd_map_over_sections (abfd, bfd_elf_set_group_contents, &failed);
       if (failed)
-       return false;
+       return FALSE;
     }
 
   shstrtab_hdr = &elf_tdata (abfd)->shstrtab_hdr;
@@ -3082,8 +3263,8 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
   /* sh_offset is set in assign_file_positions_except_relocs.  */
   shstrtab_hdr->sh_addralign = 1;
 
-  if (!assign_file_positions_except_relocs (abfd))
-    return false;
+  if (!assign_file_positions_except_relocs (abfd, link_info))
+    return FALSE;
 
   if (link_info == NULL && bfd_get_symcount (abfd) > 0)
     {
@@ -3093,14 +3274,14 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
       off = elf_tdata (abfd)->next_file_pos;
 
       hdr = &elf_tdata (abfd)->symtab_hdr;
-      off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+      off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
 
       hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
       if (hdr->sh_size != 0)
-       off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+       off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
 
       hdr = &elf_tdata (abfd)->strtab_hdr;
-      off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+      off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
 
       elf_tdata (abfd)->next_file_pos = off;
 
@@ -3108,24 +3289,23 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
          out.  */
       if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
          || ! _bfd_stringtab_emit (abfd, strtab))
-       return false;
+       return FALSE;
       _bfd_stringtab_free (strtab);
     }
 
-  abfd->output_has_begun = true;
+  abfd->output_has_begun = TRUE;
 
-  return true;
+  return TRUE;
 }
 
 /* Create a mapping from a set of sections to a program segment.  */
 
-static INLINE struct elf_segment_map *
-make_mapping (abfd, sections, from, to, phdr)
-     bfd *abfd;
-     asection **sections;
-     unsigned int from;
-     unsigned int to;
-     boolean phdr;
+static struct elf_segment_map *
+make_mapping (bfd *abfd,
+             asection **sections,
+             unsigned int from,
+             unsigned int to,
+             bfd_boolean phdr)
 {
   struct elf_segment_map *m;
   unsigned int i;
@@ -3134,7 +3314,7 @@ make_mapping (abfd, sections, from, to, phdr)
 
   amt = sizeof (struct elf_segment_map);
   amt += (to - from - 1) * sizeof (asection *);
-  m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+  m = bfd_zalloc (abfd, amt);
   if (m == NULL)
     return NULL;
   m->next = NULL;
@@ -3153,11 +3333,29 @@ make_mapping (abfd, sections, from, to, phdr)
   return m;
 }
 
+/* Create the PT_DYNAMIC segment, which includes DYNSEC.  Returns NULL
+   on failure.  */
+
+struct elf_segment_map *
+_bfd_elf_make_dynamic_segment (bfd *abfd, asection *dynsec)
+{
+  struct elf_segment_map *m;
+
+  m = bfd_zalloc (abfd, sizeof (struct elf_segment_map));
+  if (m == NULL)
+    return NULL;
+  m->next = NULL;
+  m->p_type = PT_DYNAMIC;
+  m->count = 1;
+  m->sections[0] = dynsec;
+  
+  return m;
+}
+
 /* Set up a mapping from BFD sections to program segments.  */
 
-static boolean
-map_sections_to_segments (abfd)
-     bfd *abfd;
+static bfd_boolean
+map_sections_to_segments (bfd *abfd)
 {
   asection **sections = NULL;
   asection *s;
@@ -3167,26 +3365,27 @@ map_sections_to_segments (abfd)
   struct elf_segment_map **pm;
   struct elf_segment_map *m;
   asection *last_hdr;
+  bfd_vma last_size;
   unsigned int phdr_index;
   bfd_vma maxpagesize;
   asection **hdrpp;
-  boolean phdr_in_segment = true;
-  boolean writable;
+  bfd_boolean phdr_in_segment = TRUE;
+  bfd_boolean writable;
   int tls_count = 0;
   asection *first_tls = NULL;
   asection *dynsec, *eh_frame_hdr;
   bfd_size_type amt;
 
   if (elf_tdata (abfd)->segment_map != NULL)
-    return true;
+    return TRUE;
 
   if (bfd_count_sections (abfd) == 0)
-    return true;
+    return TRUE;
 
   /* Select the allocated sections, and sort them.  */
 
   amt = bfd_count_sections (abfd) * sizeof (asection *);
-  sections = (asection **) bfd_malloc (amt);
+  sections = bfd_malloc (amt);
   if (sections == NULL)
     goto error_return;
 
@@ -3216,7 +3415,7 @@ map_sections_to_segments (abfd)
   if (s != NULL && (s->flags & SEC_LOAD) != 0)
     {
       amt = sizeof (struct elf_segment_map);
-      m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+      m = bfd_zalloc (abfd, amt);
       if (m == NULL)
        goto error_return;
       m->next = NULL;
@@ -3230,7 +3429,7 @@ map_sections_to_segments (abfd)
       pm = &m->next;
 
       amt = sizeof (struct elf_segment_map);
-      m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+      m = bfd_zalloc (abfd, amt);
       if (m == NULL)
        goto error_return;
       m->next = NULL;
@@ -3246,9 +3445,10 @@ map_sections_to_segments (abfd)
      segment when the start of the second section can be placed within
      a few bytes of the end of the first section.  */
   last_hdr = NULL;
+  last_size = 0;
   phdr_index = 0;
   maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
-  writable = false;
+  writable = FALSE;
   dynsec = bfd_get_section_by_name (abfd, ".dynamic");
   if (dynsec != NULL
       && (dynsec->flags & SEC_LOAD) == 0)
@@ -3268,13 +3468,13 @@ map_sections_to_segments (abfd)
       if ((abfd->flags & D_PAGED) == 0
          || sections[0]->lma < phdr_size
          || sections[0]->lma % maxpagesize < phdr_size % maxpagesize)
-       phdr_in_segment = false;
+       phdr_in_segment = FALSE;
     }
 
   for (i = 0, hdrpp = sections; i < count; i++, hdrpp++)
     {
       asection *hdr;
-      boolean new_segment;
+      bfd_boolean new_segment;
 
       hdr = *hdrpp;
 
@@ -3285,40 +3485,42 @@ map_sections_to_segments (abfd)
        {
          /* If we don't have a segment yet, then we don't need a new
             one (we build the last one after this loop).  */
-         new_segment = false;
+         new_segment = FALSE;
        }
       else if (last_hdr->lma - last_hdr->vma != hdr->lma - hdr->vma)
        {
          /* If this section has a different relation between the
              virtual address and the load address, then we need a new
              segment.  */
-         new_segment = true;
+         new_segment = TRUE;
        }
-      else if (BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize)
+      else if (BFD_ALIGN (last_hdr->lma + last_size, maxpagesize)
               < BFD_ALIGN (hdr->lma, maxpagesize))
        {
          /* If putting this section in this segment would force us to
              skip a page in the segment, then we need a new segment.  */
-         new_segment = true;
+         new_segment = TRUE;
        }
-      else if ((last_hdr->flags & SEC_LOAD) == 0
-              && (hdr->flags & SEC_LOAD) != 0)
+      else if ((last_hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0
+              && (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0)
        {
          /* We don't want to put a loadable section after a
-             nonloadable section in the same segment.  */
-         new_segment = true;
+             nonloadable section in the same segment.
+             Consider .tbss sections as loadable for this purpose.  */
+         new_segment = TRUE;
        }
       else if ((abfd->flags & D_PAGED) == 0)
        {
          /* If the file is not demand paged, which means that we
              don't require the sections to be correctly aligned in the
              file, then there is no other reason for a new segment.  */
-         new_segment = false;
+         new_segment = FALSE;
        }
       else if (! writable
               && (hdr->flags & SEC_READONLY) == 0
-              && (BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize)
-                  == hdr->lma))
+              && (((last_hdr->lma + last_size - 1)
+                   & ~(maxpagesize - 1))
+                  != (hdr->lma & ~(maxpagesize - 1))))
        {
          /* We don't want to put a writable section in a read only
              segment, unless they are on the same page in memory
@@ -3327,19 +3529,24 @@ map_sections_to_segments (abfd)
              only case in which the new section is not on the same
              page as the previous section is when the previous section
              ends precisely on a page boundary.  */
-         new_segment = true;
+         new_segment = TRUE;
        }
       else
        {
          /* Otherwise, we can use the same segment.  */
-         new_segment = false;
+         new_segment = FALSE;
        }
 
       if (! new_segment)
        {
          if ((hdr->flags & SEC_READONLY) == 0)
-           writable = true;
+           writable = TRUE;
          last_hdr = hdr;
+         /* .tbss sections effectively have zero size.  */
+         if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
+           last_size = hdr->size;
+         else
+           last_size = 0;
          continue;
        }
 
@@ -3354,13 +3561,18 @@ map_sections_to_segments (abfd)
       pm = &m->next;
 
       if ((hdr->flags & SEC_READONLY) == 0)
-       writable = true;
+       writable = TRUE;
       else
-       writable = false;
+       writable = FALSE;
 
       last_hdr = hdr;
+      /* .tbss sections effectively have zero size.  */
+      if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
+       last_size = hdr->size;
+      else
+       last_size = 0;
       phdr_index = i;
-      phdr_in_segment = false;
+      phdr_in_segment = FALSE;
     }
 
   /* Create a final PT_LOAD program segment.  */
@@ -3377,15 +3589,9 @@ map_sections_to_segments (abfd)
   /* If there is a .dynamic section, throw in a PT_DYNAMIC segment.  */
   if (dynsec != NULL)
     {
-      amt = sizeof (struct elf_segment_map);
-      m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+      m = _bfd_elf_make_dynamic_segment (abfd, dynsec);
       if (m == NULL)
        goto error_return;
-      m->next = NULL;
-      m->p_type = PT_DYNAMIC;
-      m->count = 1;
-      m->sections[0] = dynsec;
-
       *pm = m;
       pm = &m->next;
     }
@@ -3401,7 +3607,7 @@ map_sections_to_segments (abfd)
          && strncmp (s->name, ".note", 5) == 0)
        {
          amt = sizeof (struct elf_segment_map);
-         m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+         m = bfd_zalloc (abfd, amt);
          if (m == NULL)
            goto error_return;
          m->next = NULL;
@@ -3427,7 +3633,7 @@ map_sections_to_segments (abfd)
 
       amt = sizeof (struct elf_segment_map);
       amt += (tls_count - 1) * sizeof (asection *);
-      m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+      m = bfd_zalloc (abfd, amt);
       if (m == NULL)
        goto error_return;
       m->next = NULL;
@@ -3449,19 +3655,48 @@ map_sections_to_segments (abfd)
 
   /* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
      segment.  */
-  eh_frame_hdr = NULL;
-  if (elf_tdata (abfd)->eh_frame_hdr)
-    eh_frame_hdr = bfd_get_section_by_name (abfd, ".eh_frame_hdr");
-  if (eh_frame_hdr != NULL && (eh_frame_hdr->flags & SEC_LOAD))
+  eh_frame_hdr = elf_tdata (abfd)->eh_frame_hdr;
+  if (eh_frame_hdr != NULL
+      && (eh_frame_hdr->output_section->flags & SEC_LOAD) != 0)
     {
       amt = sizeof (struct elf_segment_map);
-      m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+      m = bfd_zalloc (abfd, amt);
       if (m == NULL)
        goto error_return;
       m->next = NULL;
       m->p_type = PT_GNU_EH_FRAME;
       m->count = 1;
-      m->sections[0] = eh_frame_hdr;
+      m->sections[0] = eh_frame_hdr->output_section;
+
+      *pm = m;
+      pm = &m->next;
+    }
+
+  if (elf_tdata (abfd)->stack_flags)
+    {
+      amt = sizeof (struct elf_segment_map);
+      m = bfd_zalloc (abfd, amt);
+      if (m == NULL)
+       goto error_return;
+      m->next = NULL;
+      m->p_type = PT_GNU_STACK;
+      m->p_flags = elf_tdata (abfd)->stack_flags;
+      m->p_flags_valid = 1;
+
+      *pm = m;
+      pm = &m->next;
+    }
+
+  if (elf_tdata (abfd)->relro)
+    {
+      amt = sizeof (struct elf_segment_map);
+      m = bfd_zalloc (abfd, amt);
+      if (m == NULL)
+       goto error_return;
+      m->next = NULL;
+      m->p_type = PT_GNU_RELRO;
+      m->p_flags = PF_R;
+      m->p_flags_valid = 1;
 
       *pm = m;
       pm = &m->next;
@@ -3471,23 +3706,22 @@ map_sections_to_segments (abfd)
   sections = NULL;
 
   elf_tdata (abfd)->segment_map = mfirst;
-  return true;
+  return TRUE;
 
  error_return:
   if (sections != NULL)
     free (sections);
-  return false;
+  return FALSE;
 }
 
 /* Sort sections by address.  */
 
 static int
-elf_sort_sections (arg1, arg2)
-     const PTR arg1;
-     const PTR arg2;
+elf_sort_sections (const void *arg1, const void *arg2)
 {
   const asection *sec1 = *(const asection **) arg1;
   const asection *sec2 = *(const asection **) arg2;
+  bfd_size_type size1, size2;
 
   /* Sort by LMA first, since this is the address used to
      place the section into a segment.  */
@@ -3505,7 +3739,7 @@ elf_sort_sections (arg1, arg2)
 
   /* Put !SEC_LOAD sections after SEC_LOAD ones.  */
 
-#define TOEND(x) (((x)->flags & SEC_LOAD) == 0)
+#define TOEND(x) (((x)->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0)
 
   if (TOEND (sec1))
     {
@@ -3527,21 +3761,52 @@ elf_sort_sections (arg1, arg2)
   /* Sort by size, to put zero sized sections
      before others at the same address.  */
 
-  if (sec1->_raw_size < sec2->_raw_size)
+  size1 = (sec1->flags & SEC_LOAD) ? sec1->size : 0;
+  size2 = (sec2->flags & SEC_LOAD) ? sec2->size : 0;
+
+  if (size1 < size2)
     return -1;
-  if (sec1->_raw_size > sec2->_raw_size)
+  if (size1 > size2)
     return 1;
 
   return sec1->target_index - sec2->target_index;
 }
 
+/* Ian Lance Taylor writes:
+
+   We shouldn't be using % with a negative signed number.  That's just
+   not good.  We have to make sure either that the number is not
+   negative, or that the number has an unsigned type.  When the types
+   are all the same size they wind up as unsigned.  When file_ptr is a
+   larger signed type, the arithmetic winds up as signed long long,
+   which is wrong.
+
+   What we're trying to say here is something like ``increase OFF by
+   the least amount that will cause it to be equal to the VMA modulo
+   the page size.''  */
+/* In other words, something like:
+
+   vma_offset = m->sections[0]->vma % bed->maxpagesize;
+   off_offset = off % bed->maxpagesize;
+   if (vma_offset < off_offset)
+     adjustment = vma_offset + bed->maxpagesize - off_offset;
+   else
+     adjustment = vma_offset - off_offset;
+     
+   which can can be collapsed into the expression below.  */
+
+static file_ptr
+vma_page_aligned_bias (bfd_vma vma, ufile_ptr off, bfd_vma maxpagesize)
+{
+  return ((vma - off) % maxpagesize);
+}
+
 /* Assign file positions to the sections based on the mapping from
    sections to segments.  This function also sets up some fields in
    the file header, and writes out the program headers.  */
 
-static boolean
-assign_file_positions_for_segments (abfd)
-     bfd *abfd;
+static bfd_boolean
+assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
 {
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   unsigned int count;
@@ -3557,7 +3822,7 @@ assign_file_positions_for_segments (abfd)
   if (elf_tdata (abfd)->segment_map == NULL)
     {
       if (! map_sections_to_segments (abfd))
-       return false;
+       return FALSE;
     }
   else
     {
@@ -3593,8 +3858,8 @@ assign_file_positions_for_segments (abfd)
 
   if (bed->elf_backend_modify_segment_map)
     {
-      if (! (*bed->elf_backend_modify_segment_map) (abfd))
-       return false;
+      if (! (*bed->elf_backend_modify_segment_map) (abfd, link_info))
+       return FALSE;
     }
 
   count = 0;
@@ -3606,7 +3871,10 @@ assign_file_positions_for_segments (abfd)
   elf_elfheader (abfd)->e_phnum = count;
 
   if (count == 0)
-    return true;
+    {
+      elf_tdata (abfd)->next_file_pos = bed->s->sizeof_ehdr;
+      return TRUE;
+    }
 
   /* If we already counted the number of program segments, make sure
      that we allocated enough space.  This happens when SIZEOF_HEADERS
@@ -3615,19 +3883,19 @@ assign_file_positions_for_segments (abfd)
   if (alloc != 0 && count > alloc)
     {
       ((*_bfd_error_handler)
-       (_("%s: Not enough room for program headers (allocated %u, need %u)"),
-       bfd_get_filename (abfd), alloc, count));
+       (_("%B: Not enough room for program headers (allocated %u, need %u)"),
+       abfd, alloc, count));
       bfd_set_error (bfd_error_bad_value);
-      return false;
+      return FALSE;
     }
 
   if (alloc == 0)
     alloc = count;
 
   amt = alloc * sizeof (Elf_Internal_Phdr);
-  phdrs = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt);
+  phdrs = bfd_alloc (abfd, amt);
   if (phdrs == NULL)
-    return false;
+    return FALSE;
 
   off = bed->s->sizeof_ehdr;
   off += alloc * bed->s->sizeof_phdr;
@@ -3655,32 +3923,77 @@ assign_file_positions_for_segments (abfd)
        qsort (m->sections, (size_t) m->count, sizeof (asection *),
               elf_sort_sections);
 
+      /* An ELF segment (described by Elf_Internal_Phdr) may contain a
+        number of sections with contents contributing to both p_filesz
+        and p_memsz, followed by a number of sections with no contents
+        that just contribute to p_memsz.  In this loop, OFF tracks next
+        available file offset for PT_LOAD and PT_NOTE segments.  VOFF is
+        an adjustment we use for segments that have no file contents
+        but need zero filled memory allocation.  */
+      voff = 0;
       p->p_type = m->p_type;
       p->p_flags = m->p_flags;
 
       if (p->p_type == PT_LOAD
-         && m->count > 0
-         && (m->sections[0]->flags & SEC_ALLOC) != 0)
+         && m->count > 0)
        {
+         bfd_size_type align;
+         bfd_vma adjust;
+
          if ((abfd->flags & D_PAGED) != 0)
-           off += (m->sections[0]->vma - off) % bed->maxpagesize;
+           align = bed->maxpagesize;
          else
            {
-             bfd_size_type align;
-
-             align = 0;
+             unsigned int align_power = 0;
              for (i = 0, secpp = m->sections; i < m->count; i++, secpp++)
                {
-                 bfd_size_type secalign;
+                 unsigned int secalign;
 
                  secalign = bfd_get_section_alignment (abfd, *secpp);
-                 if (secalign > align)
-                   align = secalign;
+                 if (secalign > align_power)
+                   align_power = secalign;
                }
+             align = (bfd_size_type) 1 << align_power;
+           }
 
-             off += (m->sections[0]->vma - off) % (1 << align);
+         adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align);
+         off += adjust;
+         if (adjust != 0
+             && !m->includes_filehdr
+             && !m->includes_phdrs
+             && (ufile_ptr) off >= align)
+           {
+             /* If the first section isn't loadable, the same holds for
+                any other sections.  Since the segment won't need file
+                space, we can make p_offset overlap some prior segment.
+                However, .tbss is special.  If a segment starts with
+                .tbss, we need to look at the next section to decide
+                whether the segment has any loadable sections.  */
+             i = 0;
+             while ((m->sections[i]->flags & SEC_LOAD) == 0)
+               {
+                 if ((m->sections[i]->flags & SEC_THREAD_LOCAL) == 0
+                     || ++i >= m->count)
+                   {
+                     off -= adjust;
+                     voff = adjust - align;
+                     break;
+                   }
+               }
            }
        }
+      /* Make sure the .dynamic section is the first section in the
+        PT_DYNAMIC segment.  */
+      else if (p->p_type == PT_DYNAMIC
+              && m->count > 1
+              && strcmp (m->sections[0]->name, ".dynamic") != 0)
+       {
+         _bfd_error_handler
+           (_("%B: The first section in the PT_DYNAMIC segment is not the .dynamic section"),
+            abfd);
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
 
       if (m->count == 0)
        p->p_vaddr = 0;
@@ -3698,7 +4011,7 @@ assign_file_positions_for_segments (abfd)
          && (abfd->flags & D_PAGED) != 0)
        p->p_align = bed->maxpagesize;
       else if (m->count == 0)
-       p->p_align = bed->s->file_align;
+       p->p_align = 1 << bed->s->log_file_align;
       else
        p->p_align = 0;
 
@@ -3720,10 +4033,10 @@ assign_file_positions_for_segments (abfd)
              if (p->p_vaddr < (bfd_vma) off)
                {
                  (*_bfd_error_handler)
-                   (_("%s: Not enough room for program headers, try linking with -N"),
-                    bfd_get_filename (abfd));
+                   (_("%B: Not enough room for program headers, try linking with -N"),
+                    abfd);
                  bfd_set_error (bfd_error_bad_value);
-                 return false;
+                 return FALSE;
                }
 
              p->p_vaddr -= off;
@@ -3779,7 +4092,7 @@ assign_file_positions_for_segments (abfd)
          || (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core))
        {
          if (! m->includes_filehdr && ! m->includes_phdrs)
-           p->p_offset = off;
+           p->p_offset = off + voff;
          else
            {
              file_ptr adjust;
@@ -3790,8 +4103,6 @@ assign_file_positions_for_segments (abfd)
            }
        }
 
-      voff = off;
-
       for (i = 0, secpp = m->sections; i < m->count; i++, secpp++)
        {
          asection *sec;
@@ -3802,107 +4113,100 @@ assign_file_positions_for_segments (abfd)
          flags = sec->flags;
          align = 1 << bfd_get_section_alignment (abfd, sec);
 
-         /* The section may have artificial alignment forced by a
-            link script.  Notice this case by the gap between the
-            cumulative phdr lma and the section's lma.  */
-         if (p->p_paddr + p->p_memsz < sec->lma)
-           {
-             bfd_vma adjust = sec->lma - (p->p_paddr + p->p_memsz);
-
-             p->p_memsz += adjust;
-             off += adjust;
-             voff += adjust;
-             if ((flags & SEC_LOAD) != 0)
-               p->p_filesz += adjust;
-           }
-
-         if (p->p_type == PT_LOAD)
+         if (p->p_type == PT_LOAD
+             || p->p_type == PT_TLS)
            {
              bfd_signed_vma adjust;
 
              if ((flags & SEC_LOAD) != 0)
                {
-                 adjust = sec->lma - (p->p_paddr + p->p_memsz);
+                 adjust = sec->lma - (p->p_paddr + p->p_filesz);
                  if (adjust < 0)
-                   adjust = 0;
+                   {
+                     (*_bfd_error_handler)
+                       (_("%B: section %A lma 0x%lx overlaps previous sections"),
+                        abfd, sec, (unsigned long) sec->lma);
+                     adjust = 0;
+                   }
+                 off += adjust;
+                 p->p_filesz += adjust;
+                 p->p_memsz += adjust;
                }
-             else if ((flags & SEC_ALLOC) != 0)
+             /* .tbss is special.  It doesn't contribute to p_memsz of
+                normal segments.  */
+             else if ((flags & SEC_THREAD_LOCAL) == 0
+                      || p->p_type == PT_TLS)
                {
                  /* The section VMA must equal the file position
-                    modulo the page size.  FIXME: I'm not sure if
-                    this adjustment is really necessary.  We used to
-                    not have the SEC_LOAD case just above, and then
-                    this was necessary, but now I'm not sure.  */
+                    modulo the page size.  */
+                 bfd_size_type page = align;
                  if ((abfd->flags & D_PAGED) != 0)
-                   adjust = (sec->vma - voff) % bed->maxpagesize;
-                 else
-                   adjust = (sec->vma - voff) % align;
-               }
-             else
-               adjust = 0;
-
-             if (adjust != 0)
-               {
-                 if (i == 0)
-                   {
-                     (* _bfd_error_handler) (_("\
-Error: First section in segment (%s) starts at 0x%x whereas the segment starts at 0x%x"),
-                                             bfd_section_name (abfd, sec),
-                                             sec->lma,
-                                             p->p_paddr);
-                     return false;
-                   }
+                   page = bed->maxpagesize;
+                 adjust = vma_page_aligned_bias (sec->vma,
+                                                 p->p_vaddr + p->p_memsz,
+                                                 page);
                  p->p_memsz += adjust;
-                 off += adjust;
-                 voff += adjust;
-                 if ((flags & SEC_LOAD) != 0)
-                   p->p_filesz += adjust;
                }
-
-             sec->filepos = off;
-
-             /* We check SEC_HAS_CONTENTS here because if NOLOAD is
-                 used in a linker script we may have a section with
-                 SEC_LOAD clear but which is supposed to have
-                 contents.  */
-             if ((flags & SEC_LOAD) != 0
-                 || (flags & SEC_HAS_CONTENTS) != 0)
-               off += sec->_raw_size;
-
-             if ((flags & SEC_ALLOC) != 0)
-               voff += sec->_raw_size;
            }
 
          if (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core)
            {
-             /* The actual "note" segment has i == 0.
-                This is the one that actually contains everything.  */
+             /* The section at i == 0 is the one that actually contains
+                everything.  */
              if (i == 0)
                {
                  sec->filepos = off;
-                 p->p_filesz = sec->_raw_size;
-                 off += sec->_raw_size;
-                 voff = off;
+                 off += sec->size;
+                 p->p_filesz = sec->size;
+                 p->p_memsz = 0;
+                 p->p_align = 1;
                }
              else
                {
-                 /* Fake sections -- don't need to be written.  */
+                 /* The rest are fake sections that shouldn't be written.  */
                  sec->filepos = 0;
-                 sec->_raw_size = 0;
-                 flags = sec->flags = 0;
+                 sec->size = 0;
+                 sec->flags = 0;
+                 continue;
                }
-             p->p_memsz = 0;
-             p->p_align = 1;
            }
          else
            {
-             p->p_memsz += sec->_raw_size;
+             if (p->p_type == PT_LOAD)
+               {
+                 sec->filepos = off;
+                 /* FIXME: The SEC_HAS_CONTENTS test here dates back to
+                    1997, and the exact reason for it isn't clear.  One
+                    plausible explanation is that it is to work around
+                    a problem we have with linker scripts using data
+                    statements in NOLOAD sections.  I don't think it
+                    makes a great deal of sense to have such a section
+                    assigned to a PT_LOAD segment, but apparently
+                    people do this.  The data statement results in a
+                    bfd_data_link_order being built, and these need
+                    section contents to write into.  Eventually, we get
+                    to _bfd_elf_write_object_contents which writes any
+                    section with contents to the output.  Make room
+                    here for the write, so that following segments are
+                    not trashed.  */
+                 if ((flags & SEC_LOAD) != 0
+                     || (flags & SEC_HAS_CONTENTS) != 0)
+                   off += sec->size;
+               }
 
              if ((flags & SEC_LOAD) != 0)
-               p->p_filesz += sec->_raw_size;
+               {
+                 p->p_filesz += sec->size;
+                 p->p_memsz += sec->size;
+               }
+             /* .tbss is special.  It doesn't contribute to p_memsz of
+                normal segments.  */
+             else if ((flags & SEC_THREAD_LOCAL) == 0
+                      || p->p_type == PT_TLS)
+               p->p_memsz += sec->size;
 
              if (p->p_type == PT_TLS
-                 && sec->_raw_size == 0
+                 && sec->size == 0
                  && (sec->flags & SEC_HAS_CONTENTS) == 0)
                {
                  struct bfd_link_order *o;
@@ -3940,6 +4244,22 @@ Error: First section in segment (%s) starts at 0x%x whereas the segment starts a
       if (p->p_type != PT_LOAD && m->count > 0)
        {
          BFD_ASSERT (! m->includes_filehdr && ! m->includes_phdrs);
+         /* If the section has not yet been assigned a file position,
+            do so now.  The ARM BPABI requires that .dynamic section
+            not be marked SEC_ALLOC because it is not part of any
+            PT_LOAD segment, so it will not be processed above.  */
+         if (p->p_type == PT_DYNAMIC && m->sections[0]->filepos == 0)
+           {
+             unsigned int i;
+             Elf_Internal_Shdr ** const i_shdrpp = elf_elfsections (abfd);
+
+             i = 1;
+             while (i_shdrpp[i]->bfd_section != m->sections[0])
+               ++i;
+             off = (_bfd_elf_assign_file_position_for_section 
+                    (i_shdrpp[i], off, TRUE));
+             p->p_filesz = m->sections[0]->size;
+           }
          p->p_offset = m->sections[0]->filepos;
        }
       if (m->count == 0)
@@ -3956,14 +4276,40 @@ Error: First section in segment (%s) starts at 0x%x whereas the segment starts a
              if (! m->p_paddr_valid)
                p->p_paddr = phdrs_paddr;
            }
+         else if (p->p_type == PT_GNU_RELRO)
+           {
+             Elf_Internal_Phdr *lp;
+
+             for (lp = phdrs; lp < phdrs + count; ++lp)
+               {
+                 if (lp->p_type == PT_LOAD
+                     && lp->p_vaddr <= link_info->relro_end
+                     && lp->p_vaddr >= link_info->relro_start
+                     && lp->p_vaddr + lp->p_filesz
+                        >= link_info->relro_end)
+                   break;
+               }
+
+             if (lp < phdrs + count
+                 && link_info->relro_end > lp->p_vaddr)
+               {
+                 p->p_vaddr = lp->p_vaddr;
+                 p->p_paddr = lp->p_paddr;
+                 p->p_offset = lp->p_offset;
+                 p->p_filesz = link_info->relro_end - lp->p_vaddr;
+                 p->p_memsz = p->p_filesz;
+                 p->p_align = 1;
+                 p->p_flags = (lp->p_flags & ~PF_W);
+               }
+             else
+               {
+                 memset (p, 0, sizeof *p);
+                 p->p_type = PT_NULL;
+               }
+           }
        }
     }
 
-  /* If additional nonloadable filepos adjustments are required,
-     do them now. */
-  if (bed->set_nonloadable_filepos)
-    (*bed->set_nonloadable_filepos) (abfd, phdrs);
-
   /* Clear out any program headers we allocated but did not use.  */
   for (; count < alloc; count++, p++)
     {
@@ -3978,9 +4324,9 @@ Error: First section in segment (%s) starts at 0x%x whereas the segment starts a
   /* Write out the program headers.  */
   if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
       || bed->s->write_out_phdrs (abfd, phdrs, alloc) != 0)
-    return false;
+    return FALSE;
 
-  return true;
+  return TRUE;
 }
 
 /* Get the size of the program header.
@@ -3995,12 +4341,11 @@ Error: First section in segment (%s) starts at 0x%x whereas the segment starts a
    will be two segments.  */
 
 static bfd_size_type
-get_program_header_size (abfd)
-     bfd *abfd;
+get_program_header_size (bfd *abfd)
 {
   size_t segs;
   asection *s;
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   /* We can't return a different result each time we're called.  */
   if (elf_tdata (abfd)->program_header_size != 0)
@@ -4037,13 +4382,24 @@ get_program_header_size (abfd)
       ++segs;
     }
 
-  if (elf_tdata (abfd)->eh_frame_hdr
-      && bfd_get_section_by_name (abfd, ".eh_frame_hdr") != NULL)
+  if (elf_tdata (abfd)->eh_frame_hdr)
     {
       /* We need a PT_GNU_EH_FRAME segment.  */
       ++segs;
     }
 
+  if (elf_tdata (abfd)->stack_flags)
+    {
+      /* We need a PT_GNU_STACK segment.  */
+      ++segs;
+    }
+
+  if (elf_tdata (abfd)->relro)
+    {
+      /* We need a PT_GNU_RELRO segment.  */
+      ++segs;
+    }
+
   for (s = abfd->sections; s != NULL; s = s->next)
     {
       if ((s->flags & SEC_LOAD) != 0
@@ -4083,23 +4439,26 @@ get_program_header_size (abfd)
    _bfd_elf_compute_section_file_positions.  All the section sizes and
    VMAs must be known before this is called.
 
-   We do not consider reloc sections at this point, unless they form
-   part of the loadable image.  Reloc sections are assigned file
-   positions in assign_file_positions_for_relocs, which is called by
-   write_object_contents and final_link.
+   Reloc sections come in two flavours: Those processed specially as
+   "side-channel" data attached to a section to which they apply, and
+   those that bfd doesn't process as relocations.  The latter sort are
+   stored in a normal bfd section by bfd_section_from_shdr.   We don't
+   consider the former sort here, unless they form part of the loadable
+   image.  Reloc sections not assigned here will be handled later by
+   assign_file_positions_for_relocs.
 
    We also don't set the positions of the .symtab and .strtab here.  */
 
-static boolean
-assign_file_positions_except_relocs (abfd)
-     bfd *abfd;
+static bfd_boolean
+assign_file_positions_except_relocs (bfd *abfd,
+                                    struct bfd_link_info *link_info)
 {
   struct elf_obj_tdata * const tdata = elf_tdata (abfd);
   Elf_Internal_Ehdr * const i_ehdrp = elf_elfheader (abfd);
   Elf_Internal_Shdr ** const i_shdrpp = elf_elfsections (abfd);
   unsigned int num_sec = elf_numsections (abfd);
   file_ptr off;
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
       && bfd_get_format (abfd) != bfd_core)
@@ -4118,8 +4477,8 @@ assign_file_positions_except_relocs (abfd)
          Elf_Internal_Shdr *hdr;
 
          hdr = *hdrpp;
-         if (hdr->sh_type == SHT_REL
-             || hdr->sh_type == SHT_RELA
+         if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
+              && hdr->bfd_section == NULL)
              || i == tdata->symtab_section
              || i == tdata->symtab_shndx_section
              || i == tdata->strtab_section)
@@ -4127,7 +4486,7 @@ assign_file_positions_except_relocs (abfd)
              hdr->sh_offset = -1;
            }
          else
-           off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+           off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
 
          if (i == SHN_LORESERVE - 1)
            {
@@ -4143,8 +4502,8 @@ assign_file_positions_except_relocs (abfd)
 
       /* Assign file positions for the loaded sections based on the
          assignment of sections to segments.  */
-      if (! assign_file_positions_for_segments (abfd))
-       return false;
+      if (! assign_file_positions_for_segments (abfd, link_info))
+       return FALSE;
 
       /* Assign file positions for the other sections.  */
 
@@ -4160,26 +4519,28 @@ assign_file_positions_except_relocs (abfd)
          else if ((hdr->sh_flags & SHF_ALLOC) != 0)
            {
              ((*_bfd_error_handler)
-              (_("%s: warning: allocated section `%s' not in segment"),
-               bfd_get_filename (abfd),
+              (_("%B: warning: allocated section `%s' not in segment"),
+               abfd,
                (hdr->bfd_section == NULL
                 ? "*unknown*"
                 : hdr->bfd_section->name)));
              if ((abfd->flags & D_PAGED) != 0)
-               off += (hdr->sh_addr - off) % bed->maxpagesize;
+               off += vma_page_aligned_bias (hdr->sh_addr, off,
+                                             bed->maxpagesize);
              else
-               off += (hdr->sh_addr - off) % hdr->sh_addralign;
+               off += vma_page_aligned_bias (hdr->sh_addr, off,
+                                             hdr->sh_addralign);
              off = _bfd_elf_assign_file_position_for_section (hdr, off,
-                                                              false);
+                                                              FALSE);
            }
-         else if (hdr->sh_type == SHT_REL
-                  || hdr->sh_type == SHT_RELA
+         else if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
+                   && hdr->bfd_section == NULL)
                   || hdr == i_shdrpp[tdata->symtab_section]
                   || hdr == i_shdrpp[tdata->symtab_shndx_section]
                   || hdr == i_shdrpp[tdata->strtab_section])
            hdr->sh_offset = -1;
          else
-           off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+           off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
 
          if (i == SHN_LORESERVE - 1)
            {
@@ -4190,31 +4551,30 @@ assign_file_positions_except_relocs (abfd)
     }
 
   /* Place the section headers.  */
-  off = align_file_position (off, bed->s->file_align);
+  off = align_file_position (off, 1 << bed->s->log_file_align);
   i_ehdrp->e_shoff = off;
   off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
 
   elf_tdata (abfd)->next_file_pos = off;
 
-  return true;
+  return TRUE;
 }
 
-static boolean
-prep_headers (abfd)
-     bfd *abfd;
+static bfd_boolean
+prep_headers (bfd *abfd)
 {
   Elf_Internal_Ehdr *i_ehdrp;  /* Elf file header, internal form */
   Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */
   Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
   struct elf_strtab_hash *shstrtab;
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   i_ehdrp = elf_elfheader (abfd);
   i_shdrp = elf_elfsections (abfd);
 
   shstrtab = _bfd_elf_strtab_init ();
   if (shstrtab == NULL)
-    return false;
+    return FALSE;
 
   elf_shstrtab (abfd) = shstrtab;
 
@@ -4252,11 +4612,8 @@ prep_headers (abfd)
         Such need can generally be supplied by replacing the tests for
         e_machine with the conditions used to determine it.  */
     default:
-      if (get_elf_backend_data (abfd) != NULL)
-       i_ehdrp->e_machine = get_elf_backend_data (abfd)->elf_machine_code;
-      else
-       i_ehdrp->e_machine = EM_NONE;
-      }
+      i_ehdrp->e_machine = bed->elf_machine_code;
+    }
 
   i_ehdrp->e_version = bed->s->ev_current;
   i_ehdrp->e_ehsize = bed->s->sizeof_ehdr;
@@ -4292,25 +4649,24 @@ prep_headers (abfd)
     }
 
   elf_tdata (abfd)->symtab_hdr.sh_name =
-    (unsigned int) _bfd_elf_strtab_add (shstrtab, ".symtab", false);
+    (unsigned int) _bfd_elf_strtab_add (shstrtab, ".symtab", FALSE);
   elf_tdata (abfd)->strtab_hdr.sh_name =
-    (unsigned int) _bfd_elf_strtab_add (shstrtab, ".strtab", false);
+    (unsigned int) _bfd_elf_strtab_add (shstrtab, ".strtab", FALSE);
   elf_tdata (abfd)->shstrtab_hdr.sh_name =
-    (unsigned int) _bfd_elf_strtab_add (shstrtab, ".shstrtab", false);
+    (unsigned int) _bfd_elf_strtab_add (shstrtab, ".shstrtab", FALSE);
   if (elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1
       || elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1
       || elf_tdata (abfd)->shstrtab_hdr.sh_name == (unsigned int) -1)
-    return false;
+    return FALSE;
 
-  return true;
+  return TRUE;
 }
 
 /* Assign file positions for all the reloc sections which are not part
    of the loadable file image.  */
 
 void
-_bfd_elf_assign_file_positions_for_relocs (abfd)
-     bfd *abfd;
+_bfd_elf_assign_file_positions_for_relocs (bfd *abfd)
 {
   file_ptr off;
   unsigned int i, num_sec;
@@ -4326,34 +4682,32 @@ _bfd_elf_assign_file_positions_for_relocs (abfd)
       shdrp = *shdrpp;
       if ((shdrp->sh_type == SHT_REL || shdrp->sh_type == SHT_RELA)
          && shdrp->sh_offset == -1)
-       off = _bfd_elf_assign_file_position_for_section (shdrp, off, true);
+       off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE);
     }
 
   elf_tdata (abfd)->next_file_pos = off;
 }
 
-boolean
-_bfd_elf_write_object_contents (abfd)
-     bfd *abfd;
+bfd_boolean
+_bfd_elf_write_object_contents (bfd *abfd)
 {
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   Elf_Internal_Ehdr *i_ehdrp;
   Elf_Internal_Shdr **i_shdrp;
-  boolean failed;
+  bfd_boolean failed;
   unsigned int count, num_sec;
 
   if (! abfd->output_has_begun
-      && ! _bfd_elf_compute_section_file_positions
-             (abfd, (struct bfd_link_info *) NULL))
-    return false;
+      && ! _bfd_elf_compute_section_file_positions (abfd, NULL))
+    return FALSE;
 
   i_shdrp = elf_elfsections (abfd);
   i_ehdrp = elf_elfheader (abfd);
 
-  failed = false;
+  failed = FALSE;
   bfd_map_over_sections (abfd, bed->s->write_relocs, &failed);
   if (failed)
-    return false;
+    return FALSE;
 
   _bfd_elf_assign_file_positions_for_relocs (abfd);
 
@@ -4369,7 +4723,7 @@ _bfd_elf_write_object_contents (abfd)
 
          if (bfd_seek (abfd, i_shdrp[count]->sh_offset, SEEK_SET) != 0
              || bfd_bwrite (i_shdrp[count]->contents, amt, abfd) != amt)
-           return false;
+           return FALSE;
        }
       if (count == SHN_LORESERVE - 1)
        count += SHN_HIRESERVE + 1 - SHN_LORESERVE;
@@ -4378,7 +4732,7 @@ _bfd_elf_write_object_contents (abfd)
   /* Write out the section header names.  */
   if (bfd_seek (abfd, elf_tdata (abfd)->shstrtab_hdr.sh_offset, SEEK_SET) != 0
       || ! _bfd_elf_strtab_emit (abfd, elf_shstrtab (abfd)))
-    return false;
+    return FALSE;
 
   if (bed->elf_backend_final_write_processing)
     (*bed->elf_backend_final_write_processing) (abfd,
@@ -4387,9 +4741,8 @@ _bfd_elf_write_object_contents (abfd)
   return bed->s->write_shdrs_and_ehdr (abfd);
 }
 
-boolean
-_bfd_elf_write_corefile_contents (abfd)
-     bfd *abfd;
+bfd_boolean
+_bfd_elf_write_corefile_contents (bfd *abfd)
 {
   /* Hopefully this can be done just like an object file.  */
   return _bfd_elf_write_object_contents (abfd);
@@ -4398,11 +4751,9 @@ _bfd_elf_write_corefile_contents (abfd)
 /* Given a section, search the header to find them.  */
 
 int
-_bfd_elf_section_from_bfd_section (abfd, asect)
-     bfd *abfd;
-     struct sec *asect;
+_bfd_elf_section_from_bfd_section (bfd *abfd, struct bfd_section *asect)
 {
-  struct elf_backend_data *bed;
+  const struct elf_backend_data *bed;
   int index;
 
   if (elf_section_data (asect) != NULL
@@ -4449,9 +4800,7 @@ _bfd_elf_section_from_bfd_section (abfd, asect)
    on error.  */
 
 int
-_bfd_elf_symbol_from_bfd_symbol (abfd, asym_ptr_ptr)
-     bfd *abfd;
-     asymbol **asym_ptr_ptr;
+_bfd_elf_symbol_from_bfd_symbol (bfd *abfd, asymbol **asym_ptr_ptr)
 {
   asymbol *asym_ptr = *asym_ptr_ptr;
   int idx;
@@ -4484,8 +4833,8 @@ _bfd_elf_symbol_from_bfd_symbol (abfd, asym_ptr_ptr)
       /* This case can occur when using --strip-symbol on a symbol
          which is used in a relocation entry.  */
       (*_bfd_error_handler)
-       (_("%s: symbol `%s' required but not present"),
-        bfd_archive_filename (abfd), bfd_asymbol_name (asym_ptr));
+       (_("%B: symbol `%s' required but not present"),
+        abfd, bfd_asymbol_name (asym_ptr));
       bfd_set_error (bfd_error_no_symbols);
       return -1;
     }
@@ -4505,31 +4854,29 @@ _bfd_elf_symbol_from_bfd_symbol (abfd, asym_ptr_ptr)
 
 /* Copy private BFD data.  This copies any program header information.  */
 
-static boolean
-copy_private_bfd_data (ibfd, obfd)
-     bfd *ibfd;
-     bfd *obfd;
-{
-  Elf_Internal_Ehdr *       iehdr;
-  struct elf_segment_map *  map;
-  struct elf_segment_map *  map_first;
-  struct elf_segment_map ** pointer_to_map;
-  Elf_Internal_Phdr *       segment;
-  asection *                section;
-  unsigned int              i;
-  unsigned int              num_segments;
-  boolean                   phdr_included = false;
-  bfd_vma                   maxpagesize;
-  struct elf_segment_map *  phdr_adjust_seg = NULL;
-  unsigned int              phdr_adjust_num = 0;
-  struct elf_backend_data * bed;
+static bfd_boolean
+copy_private_bfd_data (bfd *ibfd, bfd *obfd)
+{
+  Elf_Internal_Ehdr *iehdr;
+  struct elf_segment_map *map;
+  struct elf_segment_map *map_first;
+  struct elf_segment_map **pointer_to_map;
+  Elf_Internal_Phdr *segment;
+  asection *section;
+  unsigned int i;
+  unsigned int num_segments;
+  bfd_boolean phdr_included = FALSE;
+  bfd_vma maxpagesize;
+  struct elf_segment_map *phdr_adjust_seg = NULL;
+  unsigned int phdr_adjust_num = 0;
+  const struct elf_backend_data *bed;
 
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return true;
+    return TRUE;
 
   if (elf_tdata (ibfd)->phdr == NULL)
-    return true;
+    return TRUE;
 
   bed = get_elf_backend_data (ibfd);
   iehdr = elf_elfheader (ibfd);
@@ -4545,34 +4892,32 @@ copy_private_bfd_data (ibfd, obfd)
   (start + (segment->p_memsz > segment->p_filesz                       \
            ? segment->p_memsz : segment->p_filesz))
 
-  /* Returns true if the given section is contained within
+#define SECTION_SIZE(section, segment)                                 \
+  (((section->flags & (SEC_HAS_CONTENTS | SEC_THREAD_LOCAL))           \
+    != SEC_THREAD_LOCAL || segment->p_type == PT_TLS)                  \
+   ? section->size : 0)
+
+  /* Returns TRUE if the given section is contained within
      the given segment.  VMA addresses are compared.  */
 #define IS_CONTAINED_BY_VMA(section, segment)                          \
   (section->vma >= segment->p_vaddr                                    \
-   && (section->vma + section->_raw_size                               \
+   && (section->vma + SECTION_SIZE (section, segment)                  \
        <= (SEGMENT_END (segment, segment->p_vaddr))))
 
-  /* Returns true if the given section is contained within
+  /* Returns TRUE if the given section is contained within
      the given segment.  LMA addresses are compared.  */
 #define IS_CONTAINED_BY_LMA(section, segment, base)                    \
   (section->lma >= base                                                        \
-   && (section->lma + section->_raw_size                               \
+   && (section->lma + SECTION_SIZE (section, segment)                  \
        <= SEGMENT_END (segment, base)))
 
-  /* Returns true if the given section is contained within the
-     given segment.  Filepos addresses are compared in an elf
-     backend function. */
-#define IS_CONTAINED_BY_FILEPOS(sec, seg, bed)                         \
-  (bed->is_contained_by_filepos                                                \
-   && (*bed->is_contained_by_filepos) (sec, seg))
-
   /* Special case: corefile "NOTE" section containing regs, prpsinfo etc.  */
 #define IS_COREFILE_NOTE(p, s)                                         \
   (p->p_type == PT_NOTE                                                        \
    && bfd_get_format (ibfd) == bfd_core                                        \
    && s->vma == 0 && s->lma == 0                                       \
    && (bfd_vma) s->filepos >= p->p_offset                              \
-   && ((bfd_vma) s->filepos + s->_raw_size                             \
+   && ((bfd_vma) s->filepos + s->size                          \
        <= p->p_offset + p->p_filesz))
 
   /* The complicated case when p_vaddr is 0 is to handle the Solaris
@@ -4584,9 +4929,9 @@ copy_private_bfd_data (ibfd, obfd)
    && p->p_memsz == 0                                                  \
    && p->p_filesz > 0                                                  \
    && (s->flags & SEC_HAS_CONTENTS) != 0                               \
-   && s->_raw_size > 0                                                 \
+   && s->size > 0                                                      \
    && (bfd_vma) s->filepos >= p->p_offset                              \
-   && ((bfd_vma) s->filepos + s->_raw_size                             \
+   && ((bfd_vma) s->filepos + s->size                          \
        <= p->p_offset + p->p_filesz))
 
   /* Decide if the given section should be included in the given segment.
@@ -4595,30 +4940,44 @@ copy_private_bfd_data (ibfd, obfd)
           if that is set for the segment and the VMA otherwise,
        2. It is an allocated segment,
        3. There is an output section associated with it,
-       4. The section has not already been allocated to a previous segment.  */
+       4. The section has not already been allocated to a previous segment.
+       5. PT_GNU_STACK segments do not include any sections.
+       6. PT_TLS segment includes only SHF_TLS sections.
+       7. SHF_TLS sections are only in PT_TLS or PT_LOAD segments.  */
 #define INCLUDE_SECTION_IN_SEGMENT(section, segment, bed)              \
   ((((segment->p_paddr                                                 \
       ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr)       \
       : IS_CONTAINED_BY_VMA (section, segment))                                \
      && (section->flags & SEC_ALLOC) != 0)                             \
-    || IS_COREFILE_NOTE (segment, section)                             \
-    || (IS_CONTAINED_BY_FILEPOS (section, segment, bed)                        \
-        && (section->flags & SEC_ALLOC) == 0))                         \
+    || IS_COREFILE_NOTE (segment, section))                            \
    && section->output_section != NULL                                  \
+   && segment->p_type != PT_GNU_STACK                                  \
+   && (segment->p_type != PT_TLS                                       \
+       || (section->flags & SEC_THREAD_LOCAL))                         \
+   && (segment->p_type == PT_LOAD                                      \
+       || segment->p_type == PT_TLS                                    \
+       || (section->flags & SEC_THREAD_LOCAL) == 0)                    \
    && ! section->segment_mark)
 
-  /* Returns true iff seg1 starts after the end of seg2.  */
-#define SEGMENT_AFTER_SEGMENT(seg1, seg2)                              \
-  (seg1->p_vaddr >= SEGMENT_END (seg2, seg2->p_vaddr))
+  /* Returns TRUE iff seg1 starts after the end of seg2.  */
+#define SEGMENT_AFTER_SEGMENT(seg1, seg2, field)                       \
+  (seg1->field >= SEGMENT_END (seg2, seg2->field))
 
-  /* Returns true iff seg1 and seg2 overlap.  */
+  /* Returns TRUE iff seg1 and seg2 overlap. Segments overlap iff both
+     their VMA address ranges and their LMA address ranges overlap.
+     It is possible to have overlapping VMA ranges without overlapping LMA
+     ranges.  RedBoot images for example can have both .data and .bss mapped
+     to the same VMA range, but with the .data section mapped to a different
+     LMA.  */
 #define SEGMENT_OVERLAPS(seg1, seg2)                                   \
-  (!(SEGMENT_AFTER_SEGMENT (seg1, seg2)                                        \
-     || SEGMENT_AFTER_SEGMENT (seg2, seg1)))
+  (   !(SEGMENT_AFTER_SEGMENT (seg1, seg2, p_vaddr)                    \
+        || SEGMENT_AFTER_SEGMENT (seg2, seg1, p_vaddr))                \
+   && !(SEGMENT_AFTER_SEGMENT (seg1, seg2, p_paddr)                    \
+        || SEGMENT_AFTER_SEGMENT (seg2, seg1, p_paddr)))
 
   /* Initialise the segment mark field.  */
   for (section = ibfd->sections; section != NULL; section = section->next)
-    section->segment_mark = false;
+    section->segment_mark = FALSE;
 
   /* Scan through the segments specified in the program header
      of the input BFD.  For this first scan we look for overlaps
@@ -4636,7 +4995,7 @@ copy_private_bfd_data (ibfd, obfd)
          if (IS_SOLARIS_PT_INTERP (segment, section))
            {
              /* Mininal change so that the normal section to segment
-                assigment code will work.  */
+                assignment code will work.  */
              segment->p_vaddr = section->vma;
              break;
            }
@@ -4712,18 +5071,19 @@ copy_private_bfd_data (ibfd, obfd)
        continue;
 
       /* Compute how many sections might be placed into this segment.  */
-      section_count = 0;
-      for (section = ibfd->sections; section != NULL; section = section->next)
+      for (section = ibfd->sections, section_count = 0;
+          section != NULL;
+          section = section->next)
        if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed))
          ++section_count;
 
-      /* Allocate a segment map big enough to contain all of the
-        sections we have selected.  */
+      /* Allocate a segment map big enough to contain
+        all of the sections we have selected.  */
       amt = sizeof (struct elf_segment_map);
       amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
-      map = (struct elf_segment_map *) bfd_alloc (obfd, amt);
+      map = bfd_alloc (obfd, amt);
       if (map == NULL)
-       return false;
+       return FALSE;
 
       /* Initialise the fields of the segment map.  Default to
         using the physical address of the segment in the input BFD.  */
@@ -4750,7 +5110,7 @@ copy_private_bfd_data (ibfd, obfd)
                     + iehdr->e_phnum * iehdr->e_phentsize)));
 
          if (segment->p_type == PT_LOAD && map->includes_phdrs)
-           phdr_included = true;
+           phdr_included = TRUE;
        }
 
       if (section_count == 0)
@@ -4761,8 +5121,8 @@ copy_private_bfd_data (ibfd, obfd)
             a warning is produced.  */
          if (segment->p_type == PT_LOAD)
            (*_bfd_error_handler)
-             (_("%s: warning: Empty loadable segment detected, is this intentional ?\n"),
-              bfd_archive_filename (ibfd));
+             (_("%B: warning: Empty loadable segment detected, is this intentional ?\n"),
+              ibfd);
 
          map->count = 0;
          *pointer_to_map = map;
@@ -4790,7 +5150,7 @@ copy_private_bfd_data (ibfd, obfd)
            and possibly its LMA changed, and a new segment or segments will
            have to be created to contain the other sections.
 
-        4. The sections have been moved, but not be the same amount.
+        4. The sections have been moved, but not by the same amount.
            In this case we can change the segment's LMA to match the LMA
            of the first section and we will have to create a new segment
            or segments to contain the other sections.
@@ -4802,9 +5162,9 @@ copy_private_bfd_data (ibfd, obfd)
       /* Gcc 2.96 miscompiles this code on mips. Don't do casting here
         to work around this long long bug.  */
       amt = section_count * sizeof (asection *);
-      sections = (asection **) bfd_malloc (amt);
+      sections = bfd_malloc (amt);
       if (sections == NULL)
-       return false;
+       return FALSE;
 
       /* Step One: Scan for segment vs section LMA conflicts.
         Also add the sections to the section array allocated above.
@@ -4848,7 +5208,6 @@ copy_private_bfd_data (ibfd, obfd)
              /* Match up the physical address of the segment with the
                 LMA address of the output section.  */
              if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr)
-                 || IS_CONTAINED_BY_FILEPOS (section, segment, bed)
                  || IS_COREFILE_NOTE (segment, section)
                  || (bed->want_p_paddr_set_to_zero &&
                      IS_CONTAINED_BY_VMA (output_section, segment))
@@ -4970,10 +5329,10 @@ copy_private_bfd_data (ibfd, obfd)
                      /* If the gap between the end of the previous section
                         and the start of this section is more than
                         maxpagesize then we need to start a new segment.  */
-                     if ((BFD_ALIGN (prev_sec->lma + prev_sec->_raw_size,
+                     if ((BFD_ALIGN (prev_sec->lma + prev_sec->size,
                                      maxpagesize)
                           < BFD_ALIGN (output_section->lma, maxpagesize))
-                         || ((prev_sec->lma + prev_sec->_raw_size)
+                         || ((prev_sec->lma + prev_sec->size)
                              > output_section->lma))
                        {
                          if (suggested_lma == 0)
@@ -4986,7 +5345,7 @@ copy_private_bfd_data (ibfd, obfd)
                  map->sections[map->count++] = output_section;
                  ++isec;
                  sections[j] = NULL;
-                 section->segment_mark = true;
+                 section->segment_mark = TRUE;
                }
              else if (suggested_lma == 0)
                suggested_lma = output_section->lma;
@@ -5005,9 +5364,12 @@ copy_private_bfd_data (ibfd, obfd)
                 and carry on looping.  */
              amt = sizeof (struct elf_segment_map);
              amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
-             map = (struct elf_segment_map *) bfd_alloc (obfd, amt);
+             map = bfd_alloc (obfd, amt);
              if (map == NULL)
-               return false;
+               {
+                 free (sections);
+                 return FALSE;
+               }
 
              /* Initialise the fields of the segment map.  Set the physical
                 physical address to the LMA of the first section that has
@@ -5035,10 +5397,8 @@ copy_private_bfd_data (ibfd, obfd)
     if (map->p_paddr != 0)
       break;
   if (map == NULL)
-    {
-      for (map = map_first; map != NULL; map = map->next)
-       map->p_paddr_valid = 0;
-    }
+    for (map = map_first; map != NULL; map = map->next)
+      map->p_paddr_valid = 0;
 
   elf_tdata (obfd)->segment_map = map_first;
 
@@ -5083,64 +5443,31 @@ copy_private_bfd_data (ibfd, obfd)
 #endif
 
 #undef SEGMENT_END
+#undef SECTION_SIZE
 #undef IS_CONTAINED_BY_VMA
 #undef IS_CONTAINED_BY_LMA
-#undef IS_CONTAINED_BY_FILEPOS
 #undef IS_COREFILE_NOTE
 #undef IS_SOLARIS_PT_INTERP
 #undef INCLUDE_SECTION_IN_SEGMENT
 #undef SEGMENT_AFTER_SEGMENT
 #undef SEGMENT_OVERLAPS
-  return true;
+  return TRUE;
 }
 
 /* Copy private section information.  This copies over the entsize
    field, and sometimes the info field.  */
 
-boolean
-_bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
-     bfd *ibfd;
-     asection *isec;
-     bfd *obfd;
-     asection *osec;
+bfd_boolean
+_bfd_elf_copy_private_section_data (bfd *ibfd,
+                                   asection *isec,
+                                   bfd *obfd,
+                                   asection *osec)
 {
   Elf_Internal_Shdr *ihdr, *ohdr;
-  const struct elf_backend_data *bed = get_elf_backend_data (ibfd);
 
   if (ibfd->xvec->flavour != bfd_target_elf_flavour
       || obfd->xvec->flavour != bfd_target_elf_flavour)
-    return true;
-
-  /* Copy over private BFD data if it has not already been copied.
-     This must be done here, rather than in the copy_private_bfd_data
-     entry point, because the latter is called after the section
-     contents have been set, which means that the program headers have
-     already been worked out.  The backend function provides a way to
-     override the test conditions and code path for the call to
-     copy_private_bfd_data.  */
-  if (bed->copy_private_bfd_data_p)
-    {
-      if ((*bed->copy_private_bfd_data_p) (ibfd, isec, obfd, osec))
-        if (! copy_private_bfd_data (ibfd, obfd))
-          return false;
-    }
-  else if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL)
-    {
-       asection *s;
-
-       /* Only set up the segments if there are no more SEC_ALLOC
-          sections.  FIXME: This won't do the right thing if objcopy is
-          used to remove the last SEC_ALLOC section, since objcopy
-          won't call this routine in that case.  */
-       for (s = isec->next; s != NULL; s = s->next)
-         if ((s->flags & SEC_ALLOC) != 0)
-           break;
-       if (s == NULL)
-         {
-           if (! copy_private_bfd_data (ibfd, obfd))
-             return false;
-         }
-    }
+    return TRUE;
 
   ihdr = &elf_section_data (isec)->this_hdr;
   ohdr = &elf_section_data (osec)->this_hdr;
@@ -5159,10 +5486,32 @@ _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
   elf_next_in_group (osec) = elf_next_in_group (isec);
   elf_group_name (osec) = elf_group_name (isec);
 
-  elf_section_data (osec)->use_rela_p
-    = elf_section_data (isec)->use_rela_p;
+  osec->use_rela_p = isec->use_rela_p;
+
+  return TRUE;
+}
+
+/* Copy private header information.  */
+
+bfd_boolean
+_bfd_elf_copy_private_header_data (bfd *ibfd, bfd *obfd)
+{
+  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+    return TRUE;
+
+  /* Copy over private BFD data if it has not already been copied.
+     This must be done here, rather than in the copy_private_bfd_data
+     entry point, because the latter is called after the section
+     contents have been set, which means that the program headers have
+     already been worked out.  */
+  if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL)
+    {
+      if (! copy_private_bfd_data (ibfd, obfd))
+       return FALSE;
+    }
 
-  return true;
+  return TRUE;
 }
 
 /* Copy private symbol information.  If this symbol is in a section
@@ -5177,18 +5526,17 @@ _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
 #define MAP_SHSTRTAB  (SHN_HIOS + 4)
 #define MAP_SYM_SHNDX (SHN_HIOS + 5)
 
-boolean
-_bfd_elf_copy_private_symbol_data (ibfd, isymarg, obfd, osymarg)
-     bfd *ibfd;
-     asymbol *isymarg;
-     bfd *obfd;
-     asymbol *osymarg;
+bfd_boolean
+_bfd_elf_copy_private_symbol_data (bfd *ibfd,
+                                  asymbol *isymarg,
+                                  bfd *obfd,
+                                  asymbol *osymarg)
 {
   elf_symbol_type *isym, *osym;
 
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return true;
+    return TRUE;
 
   isym = elf_symbol_from (ibfd, isymarg);
   osym = elf_symbol_from (obfd, osymarg);
@@ -5213,18 +5561,17 @@ _bfd_elf_copy_private_symbol_data (ibfd, isymarg, obfd, osymarg)
       osym->internal_elf_sym.st_shndx = shndx;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Swap out the symbols.  */
 
-static boolean
-swap_out_syms (abfd, sttp, relocatable_p)
-     bfd *abfd;
-     struct bfd_strtab_hash **sttp;
-     int relocatable_p;
+static bfd_boolean
+swap_out_syms (bfd *abfd,
+              struct bfd_strtab_hash **sttp,
+              int relocatable_p)
 {
-  struct elf_backend_data *bed;
+  const struct elf_backend_data *bed;
   int symcount;
   asymbol **syms;
   struct bfd_strtab_hash *stt;
@@ -5235,14 +5582,15 @@ swap_out_syms (abfd, sttp, relocatable_p)
   char *outbound_shndx;
   int idx;
   bfd_size_type amt;
+  bfd_boolean name_local_sections;
 
   if (!elf_map_symbols (abfd))
-    return false;
+    return FALSE;
 
   /* Dump out the symtabs.  */
   stt = _bfd_elf_stringtab_init ();
   if (stt == NULL)
-    return false;
+    return FALSE;
 
   bed = get_elf_backend_data (abfd);
   symcount = bfd_get_symcount (abfd);
@@ -5251,7 +5599,7 @@ swap_out_syms (abfd, sttp, relocatable_p)
   symtab_hdr->sh_entsize = bed->s->sizeof_sym;
   symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1);
   symtab_hdr->sh_info = elf_num_locals (abfd) + 1;
-  symtab_hdr->sh_addralign = bed->s->file_align;
+  symtab_hdr->sh_addralign = 1 << bed->s->log_file_align;
 
   symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
   symstrtab_hdr->sh_type = SHT_STRTAB;
@@ -5259,8 +5607,11 @@ swap_out_syms (abfd, sttp, relocatable_p)
   amt = (bfd_size_type) (1 + symcount) * bed->s->sizeof_sym;
   outbound_syms = bfd_alloc (abfd, amt);
   if (outbound_syms == NULL)
-    return false;
-  symtab_hdr->contents = (PTR) outbound_syms;
+    {
+      _bfd_stringtab_free (stt);
+      return FALSE;
+    }
+  symtab_hdr->contents = outbound_syms;
 
   outbound_shndx = NULL;
   symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
@@ -5269,7 +5620,11 @@ swap_out_syms (abfd, sttp, relocatable_p)
       amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
       outbound_shndx = bfd_zalloc (abfd, amt);
       if (outbound_shndx == NULL)
-       return false;
+       {
+         _bfd_stringtab_free (stt);
+         return FALSE;
+       }
+
       symtab_shndx_hdr->contents = outbound_shndx;
       symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
       symtab_shndx_hdr->sh_size = amt;
@@ -5277,7 +5632,7 @@ swap_out_syms (abfd, sttp, relocatable_p)
       symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
     }
 
-  /* now generate the data (for "contents") */
+  /* Now generate the data (for "contents").  */
   {
     /* Fill in zeroth symbol and swap it out.  */
     Elf_Internal_Sym sym;
@@ -5293,6 +5648,10 @@ swap_out_syms (abfd, sttp, relocatable_p)
       outbound_shndx += sizeof (Elf_External_Sym_Shndx);
   }
 
+  name_local_sections
+    = (bed->elf_backend_name_local_section_symbols
+       && bed->elf_backend_name_local_section_symbols (abfd));
+
   syms = bfd_get_outsymbols (abfd);
   for (idx = 0; idx < symcount; idx++)
     {
@@ -5302,7 +5661,8 @@ swap_out_syms (abfd, sttp, relocatable_p)
       flagword flags = syms[idx]->flags;
       int type;
 
-      if ((flags & (BSF_SECTION_SYM | BSF_GLOBAL)) == BSF_SECTION_SYM)
+      if (!name_local_sections
+         && (flags & (BSF_SECTION_SYM | BSF_GLOBAL)) == BSF_SECTION_SYM)
        {
          /* Local section symbols have no name.  */
          sym.st_name = 0;
@@ -5311,9 +5671,12 @@ swap_out_syms (abfd, sttp, relocatable_p)
        {
          sym.st_name = (unsigned long) _bfd_stringtab_add (stt,
                                                            syms[idx]->name,
-                                                           true, false);
+                                                           TRUE, FALSE);
          if (sym.st_name == (unsigned long) -1)
-           return false;
+           {
+             _bfd_stringtab_free (stt);
+             return FALSE;
+           }
        }
 
       type_ptr = elf_symbol_from (abfd, syms[idx]);
@@ -5343,6 +5706,7 @@ swap_out_syms (abfd, sttp, relocatable_p)
              value += sec->output_offset;
              sec = sec->output_section;
            }
+
          /* Don't add in the section vma for relocatable output.  */
          if (! relocatable_p)
            value += sec->vma;
@@ -5394,7 +5758,17 @@ swap_out_syms (abfd, sttp, relocatable_p)
                     section of a symbol to be a section that is
                     actually in the output file.  */
                  sec2 = bfd_get_section_by_name (abfd, sec->name);
-                 BFD_ASSERT (sec2 != 0);
+                 if (sec2 == NULL)
+                   {
+                     _bfd_error_handler (_("\
+Unable to find equivalent output section for symbol '%s' from section '%s'"),
+                                         syms[idx]->name ? syms[idx]->name : "<Local sym>",
+                                         sec->name);
+                     bfd_set_error (bfd_error_invalid_operation);
+                     _bfd_stringtab_free (stt);
+                     return FALSE;
+                   }
+
                  shndx = _bfd_elf_section_from_bfd_section (abfd, sec2);
                  BFD_ASSERT (shndx != -1);
                }
@@ -5415,7 +5789,7 @@ swap_out_syms (abfd, sttp, relocatable_p)
       if (syms[idx]->section->flags & SEC_THREAD_LOCAL)
        type = STT_TLS;
 
-      /* Processor-specific types */
+      /* Processor-specific types */
       if (type_ptr != NULL
          && bed->elf_backend_get_symbol_type)
        type = ((*bed->elf_backend_get_symbol_type)
@@ -5473,7 +5847,7 @@ swap_out_syms (abfd, sttp, relocatable_p)
   symstrtab_hdr->sh_info = 0;
   symstrtab_hdr->sh_addralign = 1;
 
-  return true;
+  return TRUE;
 }
 
 /* Return the number of bytes required to hold the symtab vector.
@@ -5483,8 +5857,7 @@ swap_out_syms (abfd, sttp, relocatable_p)
    always has a dummy entry as symbol #0, so it ends up even.  */
 
 long
-_bfd_elf_get_symtab_upper_bound (abfd)
-     bfd *abfd;
+_bfd_elf_get_symtab_upper_bound (bfd *abfd)
 {
   long symcount;
   long symtab_size;
@@ -5499,8 +5872,7 @@ _bfd_elf_get_symtab_upper_bound (abfd)
 }
 
 long
-_bfd_elf_get_dynamic_symtab_upper_bound (abfd)
-     bfd *abfd;
+_bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd)
 {
   long symcount;
   long symtab_size;
@@ -5521,9 +5893,8 @@ _bfd_elf_get_dynamic_symtab_upper_bound (abfd)
 }
 
 long
-_bfd_elf_get_reloc_upper_bound (abfd, asect)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     sec_ptr asect;
+_bfd_elf_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
+                               sec_ptr asect)
 {
   return (asect->reloc_count + 1) * sizeof (arelent *);
 }
@@ -5531,17 +5902,16 @@ _bfd_elf_get_reloc_upper_bound (abfd, asect)
 /* Canonicalize the relocs.  */
 
 long
-_bfd_elf_canonicalize_reloc (abfd, section, relptr, symbols)
-     bfd *abfd;
-     sec_ptr section;
-     arelent **relptr;
-     asymbol **symbols;
+_bfd_elf_canonicalize_reloc (bfd *abfd,
+                            sec_ptr section,
+                            arelent **relptr,
+                            asymbol **symbols)
 {
   arelent *tblptr;
   unsigned int i;
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
-  if (! bed->s->slurp_reloc_table (abfd, section, symbols, false))
+  if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE))
     return -1;
 
   tblptr = section->relocation;
@@ -5554,12 +5924,10 @@ _bfd_elf_canonicalize_reloc (abfd, section, relptr, symbols)
 }
 
 long
-_bfd_elf_get_symtab (abfd, alocation)
-     bfd *abfd;
-     asymbol **alocation;
+_bfd_elf_canonicalize_symtab (bfd *abfd, asymbol **allocation)
 {
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  long symcount = bed->s->slurp_symbol_table (abfd, alocation, false);
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  long symcount = bed->s->slurp_symbol_table (abfd, allocation, FALSE);
 
   if (symcount >= 0)
     bfd_get_symcount (abfd) = symcount;
@@ -5567,12 +5935,11 @@ _bfd_elf_get_symtab (abfd, alocation)
 }
 
 long
-_bfd_elf_canonicalize_dynamic_symtab (abfd, alocation)
-     bfd *abfd;
-     asymbol **alocation;
+_bfd_elf_canonicalize_dynamic_symtab (bfd *abfd,
+                                     asymbol **allocation)
 {
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  long symcount = bed->s->slurp_symbol_table (abfd, alocation, true);
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  long symcount = bed->s->slurp_symbol_table (abfd, allocation, TRUE);
 
   if (symcount >= 0)
     bfd_get_dynamic_symcount (abfd) = symcount;
@@ -5585,8 +5952,7 @@ _bfd_elf_canonicalize_dynamic_symtab (abfd, alocation)
    considered to be a dynamic reloc section.  */
 
 long
-_bfd_elf_get_dynamic_reloc_upper_bound (abfd)
-     bfd *abfd;
+_bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
 {
   long ret;
   asection *s;
@@ -5602,7 +5968,7 @@ _bfd_elf_get_dynamic_reloc_upper_bound (abfd)
     if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
        && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
            || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
-      ret += ((s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize)
+      ret += ((s->size / elf_section_data (s)->this_hdr.sh_entsize)
              * sizeof (arelent *));
 
   return ret;
@@ -5618,12 +5984,11 @@ _bfd_elf_get_dynamic_reloc_upper_bound (abfd)
    section.  */
 
 long
-_bfd_elf_canonicalize_dynamic_reloc (abfd, storage, syms)
-     bfd *abfd;
-     arelent **storage;
-     asymbol **syms;
+_bfd_elf_canonicalize_dynamic_reloc (bfd *abfd,
+                                    arelent **storage,
+                                    asymbol **syms)
 {
-  boolean (*slurp_relocs) PARAMS ((bfd *, asection *, asymbol **, boolean));
+  bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
   asection *s;
   long ret;
 
@@ -5644,9 +6009,9 @@ _bfd_elf_canonicalize_dynamic_reloc (abfd, storage, syms)
          arelent *p;
          long count, i;
 
-         if (! (*slurp_relocs) (abfd, s, syms, true))
+         if (! (*slurp_relocs) (abfd, s, syms, TRUE))
            return -1;
-         count = s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize;
+         count = s->size / elf_section_data (s)->this_hdr.sh_entsize;
          p = s->relocation;
          for (i = 0; i < count; i++)
            *storage++ = p++;
@@ -5661,12 +6026,95 @@ _bfd_elf_canonicalize_dynamic_reloc (abfd, storage, syms)
 \f
 /* Read in the version information.  */
 
-boolean
-_bfd_elf_slurp_version_tables (abfd)
-     bfd *abfd;
+bfd_boolean
+_bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
 {
   bfd_byte *contents = NULL;
   bfd_size_type amt;
+  unsigned int freeidx = 0;
+
+  if (elf_dynverref (abfd) != 0)
+    {
+      Elf_Internal_Shdr *hdr;
+      Elf_External_Verneed *everneed;
+      Elf_Internal_Verneed *iverneed;
+      unsigned int i;
+
+      hdr = &elf_tdata (abfd)->dynverref_hdr;
+
+      amt = (bfd_size_type) hdr->sh_info * sizeof (Elf_Internal_Verneed);
+      elf_tdata (abfd)->verref = bfd_zalloc (abfd, amt);
+      if (elf_tdata (abfd)->verref == NULL)
+       goto error_return;
+
+      elf_tdata (abfd)->cverrefs = hdr->sh_info;
+
+      contents = bfd_malloc (hdr->sh_size);
+      if (contents == NULL)
+       goto error_return;
+      if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
+         || bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
+       goto error_return;
+
+      everneed = (Elf_External_Verneed *) contents;
+      iverneed = elf_tdata (abfd)->verref;
+      for (i = 0; i < hdr->sh_info; i++, iverneed++)
+       {
+         Elf_External_Vernaux *evernaux;
+         Elf_Internal_Vernaux *ivernaux;
+         unsigned int j;
+
+         _bfd_elf_swap_verneed_in (abfd, everneed, iverneed);
+
+         iverneed->vn_bfd = abfd;
+
+         iverneed->vn_filename =
+           bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
+                                            iverneed->vn_file);
+         if (iverneed->vn_filename == NULL)
+           goto error_return;
+
+         amt = iverneed->vn_cnt;
+         amt *= sizeof (Elf_Internal_Vernaux);
+         iverneed->vn_auxptr = bfd_alloc (abfd, amt);
+
+         evernaux = ((Elf_External_Vernaux *)
+                     ((bfd_byte *) everneed + iverneed->vn_aux));
+         ivernaux = iverneed->vn_auxptr;
+         for (j = 0; j < iverneed->vn_cnt; j++, ivernaux++)
+           {
+             _bfd_elf_swap_vernaux_in (abfd, evernaux, ivernaux);
+
+             ivernaux->vna_nodename =
+               bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
+                                                ivernaux->vna_name);
+             if (ivernaux->vna_nodename == NULL)
+               goto error_return;
+
+             if (j + 1 < iverneed->vn_cnt)
+               ivernaux->vna_nextptr = ivernaux + 1;
+             else
+               ivernaux->vna_nextptr = NULL;
+
+             evernaux = ((Elf_External_Vernaux *)
+                         ((bfd_byte *) evernaux + ivernaux->vna_next));
+
+             if (ivernaux->vna_other > freeidx)
+               freeidx = ivernaux->vna_other;
+           }
+
+         if (i + 1 < hdr->sh_info)
+           iverneed->vn_nextref = iverneed + 1;
+         else
+           iverneed->vn_nextref = NULL;
+
+         everneed = ((Elf_External_Verneed *)
+                     ((bfd_byte *) everneed + iverneed->vn_next));
+       }
+
+      free (contents);
+      contents = NULL;
+    }
 
   if (elf_dynverdef (abfd) != 0)
     {
@@ -5680,11 +6128,11 @@ _bfd_elf_slurp_version_tables (abfd)
 
       hdr = &elf_tdata (abfd)->dynverdef_hdr;
 
-      contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
+      contents = bfd_malloc (hdr->sh_size);
       if (contents == NULL)
        goto error_return;
       if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
-         || bfd_bread ((PTR) contents, hdr->sh_size, abfd) != hdr->sh_size)
+         || bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
        goto error_return;
 
       /* We know the number of entries in the section but not the maximum
@@ -5703,8 +6151,15 @@ _bfd_elf_slurp_version_tables (abfd)
                     ((bfd_byte *) everdef + iverdefmem.vd_next));
        }
 
+      if (default_imported_symver)
+       {
+         if (freeidx > maxidx)
+           maxidx = ++freeidx;
+         else
+           freeidx = ++maxidx;
+       }
       amt = (bfd_size_type) maxidx * sizeof (Elf_Internal_Verdef);
-      elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) bfd_zalloc (abfd, amt);
+      elf_tdata (abfd)->verdef = bfd_zalloc (abfd, amt);
       if (elf_tdata (abfd)->verdef == NULL)
        goto error_return;
 
@@ -5726,7 +6181,7 @@ _bfd_elf_slurp_version_tables (abfd)
          iverdef->vd_bfd = abfd;
 
          amt = (bfd_size_type) iverdef->vd_cnt * sizeof (Elf_Internal_Verdaux);
-         iverdef->vd_auxptr = (Elf_Internal_Verdaux *) bfd_alloc (abfd, amt);
+         iverdef->vd_auxptr = bfd_alloc (abfd, amt);
          if (iverdef->vd_auxptr == NULL)
            goto error_return;
 
@@ -5766,104 +6221,63 @@ _bfd_elf_slurp_version_tables (abfd)
       free (contents);
       contents = NULL;
     }
-
-  if (elf_dynverref (abfd) != 0)
+  else if (default_imported_symver)
     {
-      Elf_Internal_Shdr *hdr;
-      Elf_External_Verneed *everneed;
-      Elf_Internal_Verneed *iverneed;
-      unsigned int i;
-
-      hdr = &elf_tdata (abfd)->dynverref_hdr;
-
-      amt = (bfd_size_type) hdr->sh_info * sizeof (Elf_Internal_Verneed);
-      elf_tdata (abfd)->verref =
-       (Elf_Internal_Verneed *) bfd_zalloc (abfd, amt);
-      if (elf_tdata (abfd)->verref == NULL)
-       goto error_return;
-
-      elf_tdata (abfd)->cverrefs = hdr->sh_info;
+      if (freeidx < 3)
+       freeidx = 3;
+      else
+       freeidx++;
 
-      contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
-      if (contents == NULL)
-       goto error_return;
-      if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
-         || bfd_bread ((PTR) contents, hdr->sh_size, abfd) != hdr->sh_size)
+      amt = (bfd_size_type) freeidx * sizeof (Elf_Internal_Verdef);
+      elf_tdata (abfd)->verdef = bfd_zalloc (abfd, amt);
+      if (elf_tdata (abfd)->verdef == NULL)
        goto error_return;
 
-      everneed = (Elf_External_Verneed *) contents;
-      iverneed = elf_tdata (abfd)->verref;
-      for (i = 0; i < hdr->sh_info; i++, iverneed++)
-       {
-         Elf_External_Vernaux *evernaux;
-         Elf_Internal_Vernaux *ivernaux;
-         unsigned int j;
-
-         _bfd_elf_swap_verneed_in (abfd, everneed, iverneed);
-
-         iverneed->vn_bfd = abfd;
-
-         iverneed->vn_filename =
-           bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
-                                            iverneed->vn_file);
-         if (iverneed->vn_filename == NULL)
-           goto error_return;
-
-         amt = iverneed->vn_cnt;
-         amt *= sizeof (Elf_Internal_Vernaux);
-         iverneed->vn_auxptr = (Elf_Internal_Vernaux *) bfd_alloc (abfd, amt);
-
-         evernaux = ((Elf_External_Vernaux *)
-                     ((bfd_byte *) everneed + iverneed->vn_aux));
-         ivernaux = iverneed->vn_auxptr;
-         for (j = 0; j < iverneed->vn_cnt; j++, ivernaux++)
-           {
-             _bfd_elf_swap_vernaux_in (abfd, evernaux, ivernaux);
+      elf_tdata (abfd)->cverdefs = freeidx;
+    }
 
-             ivernaux->vna_nodename =
-               bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
-                                                ivernaux->vna_name);
-             if (ivernaux->vna_nodename == NULL)
-               goto error_return;
+  /* Create a default version based on the soname.  */
+  if (default_imported_symver)
+    {
+      Elf_Internal_Verdef *iverdef;
+      Elf_Internal_Verdaux *iverdaux;
 
-             if (j + 1 < iverneed->vn_cnt)
-               ivernaux->vna_nextptr = ivernaux + 1;
-             else
-               ivernaux->vna_nextptr = NULL;
+      iverdef = &elf_tdata (abfd)->verdef[freeidx - 1];;
 
-             evernaux = ((Elf_External_Vernaux *)
-                         ((bfd_byte *) evernaux + ivernaux->vna_next));
-           }
+      iverdef->vd_version = VER_DEF_CURRENT;
+      iverdef->vd_flags = 0;
+      iverdef->vd_ndx = freeidx;
+      iverdef->vd_cnt = 1;
 
-         if (i + 1 < hdr->sh_info)
-           iverneed->vn_nextref = iverneed + 1;
-         else
-           iverneed->vn_nextref = NULL;
+      iverdef->vd_bfd = abfd;
 
-         everneed = ((Elf_External_Verneed *)
-                     ((bfd_byte *) everneed + iverneed->vn_next));
-       }
+      iverdef->vd_nodename = bfd_elf_get_dt_soname (abfd);
+      if (iverdef->vd_nodename == NULL)
+       goto error_return;
+      iverdef->vd_nextdef = NULL;
+      amt = (bfd_size_type) sizeof (Elf_Internal_Verdaux);
+      iverdef->vd_auxptr = bfd_alloc (abfd, amt);
 
-      free (contents);
-      contents = NULL;
+      iverdaux = iverdef->vd_auxptr;
+      iverdaux->vda_nodename = iverdef->vd_nodename;
+      iverdaux->vda_nextptr = NULL;
     }
 
-  return true;
+  return TRUE;
 
  error_return:
-  if (contents == NULL)
+  if (contents != NULL)
     free (contents);
-  return false;
+  return FALSE;
 }
 \f
 asymbol *
-_bfd_elf_make_empty_symbol (abfd)
-     bfd *abfd;
+_bfd_elf_make_empty_symbol (bfd *abfd)
 {
   elf_symbol_type *newsym;
   bfd_size_type amt = sizeof (elf_symbol_type);
 
-  newsym = (elf_symbol_type *) bfd_zalloc (abfd, amt);
+  newsym = bfd_zalloc (abfd, amt);
   if (!newsym)
     return NULL;
   else
@@ -5874,10 +6288,9 @@ _bfd_elf_make_empty_symbol (abfd)
 }
 
 void
-_bfd_elf_get_symbol_info (ignore_abfd, symbol, ret)
-     bfd *ignore_abfd ATTRIBUTE_UNUSED;
-     asymbol *symbol;
-     symbol_info *ret;
+_bfd_elf_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
+                         asymbol *symbol,
+                         symbol_info *ret)
 {
   bfd_symbol_info (symbol, ret);
 }
@@ -5886,19 +6299,18 @@ _bfd_elf_get_symbol_info (ignore_abfd, symbol, ret)
    use this function for the is_local_label_name entry point, but some
    override it.  */
 
-boolean
-_bfd_elf_is_local_label_name (abfd, name)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     const char *name;
+bfd_boolean
+_bfd_elf_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
+                             const char *name)
 {
   /* Normal local symbols start with ``.L''.  */
   if (name[0] == '.' && name[1] == 'L')
-    return true;
+    return TRUE;
 
   /* At least some SVR4 compilers (e.g., UnixWare 2.1 cc) generate
      DWARF debugging symbols starting with ``..''.  */
   if (name[0] == '.' && name[1] == '.')
-    return true;
+    return TRUE;
 
   /* gcc will sometimes generate symbols beginning with ``_.L_'' when
      emitting DWARF debugging output.  I suspect this is actually a
@@ -5907,32 +6319,30 @@ _bfd_elf_is_local_label_name (abfd, name)
      underscore to be emitted on some ELF targets).  For ease of use,
      we treat such symbols as local.  */
   if (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_')
-    return true;
+    return TRUE;
 
-  return false;
+  return FALSE;
 }
 
 alent *
-_bfd_elf_get_lineno (ignore_abfd, symbol)
-     bfd *ignore_abfd ATTRIBUTE_UNUSED;
-     asymbol *symbol ATTRIBUTE_UNUSED;
+_bfd_elf_get_lineno (bfd *abfd ATTRIBUTE_UNUSED,
+                    asymbol *symbol ATTRIBUTE_UNUSED)
 {
   abort ();
   return NULL;
 }
 
-boolean
-_bfd_elf_set_arch_mach (abfd, arch, machine)
-     bfd *abfd;
-     enum bfd_architecture arch;
-     unsigned long machine;
+bfd_boolean
+_bfd_elf_set_arch_mach (bfd *abfd,
+                       enum bfd_architecture arch,
+                       unsigned long machine)
 {
   /* If this isn't the right architecture for this backend, and this
      isn't the generic backend, fail.  */
   if (arch != get_elf_backend_data (abfd)->arch
       && arch != bfd_arch_unknown
       && get_elf_backend_data (abfd)->arch != bfd_arch_unknown)
-    return false;
+    return FALSE;
 
   return bfd_default_set_arch_mach (abfd, arch, machine);
 }
@@ -5940,15 +6350,13 @@ _bfd_elf_set_arch_mach (abfd, arch, machine)
 /* Find the function to a particular section and offset,
    for error reporting.  */
 
-static boolean
-elf_find_function (abfd, section, symbols, offset,
-                  filename_ptr, functionname_ptr)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     asection *section;
-     asymbol **symbols;
-     bfd_vma offset;
-     const char **filename_ptr;
-     const char **functionname_ptr;
+static bfd_boolean
+elf_find_function (bfd *abfd ATTRIBUTE_UNUSED,
+                  asection *section,
+                  asymbol **symbols,
+                  bfd_vma offset,
+                  const char **filename_ptr,
+                  const char **functionname_ptr)
 {
   const char *filename;
   asymbol *func;
@@ -5965,9 +6373,6 @@ elf_find_function (abfd, section, symbols, offset,
 
       q = (elf_symbol_type *) *p;
 
-      if (bfd_get_section (&q->symbol) != section)
-       continue;
-
       switch (ELF_ST_TYPE (q->internal_elf_sym.st_info))
        {
        default:
@@ -5977,7 +6382,7 @@ elf_find_function (abfd, section, symbols, offset,
          break;
        case STT_NOTYPE:
        case STT_FUNC:
-         if (q->symbol.section == section
+         if (bfd_get_section (&q->symbol) == section
              && q->symbol.value >= low_func
              && q->symbol.value <= offset)
            {
@@ -5989,31 +6394,29 @@ elf_find_function (abfd, section, symbols, offset,
     }
 
   if (func == NULL)
-    return false;
+    return FALSE;
 
   if (filename_ptr)
     *filename_ptr = filename;
   if (functionname_ptr)
     *functionname_ptr = bfd_asymbol_name (func);
 
-  return true;
+  return TRUE;
 }
 
 /* Find the nearest line to a particular section and offset,
    for error reporting.  */
 
-boolean
-_bfd_elf_find_nearest_line (abfd, section, symbols, offset,
-                           filename_ptr, functionname_ptr, line_ptr)
-     bfd *abfd;
-     asection *section;
-     asymbol **symbols;
-     bfd_vma offset;
-     const char **filename_ptr;
-     const char **functionname_ptr;
-     unsigned int *line_ptr;
+bfd_boolean
+_bfd_elf_find_nearest_line (bfd *abfd,
+                           asection *section,
+                           asymbol **symbols,
+                           bfd_vma offset,
+                           const char **filename_ptr,
+                           const char **functionname_ptr,
+                           unsigned int *line_ptr)
 {
-  boolean found;
+  bfd_boolean found;
 
   if (_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset,
                                     filename_ptr, functionname_ptr,
@@ -6024,7 +6427,7 @@ _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
                           *filename_ptr ? NULL : filename_ptr,
                           functionname_ptr);
 
-      return true;
+      return TRUE;
     }
 
   if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
@@ -6037,32 +6440,30 @@ _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
                           *filename_ptr ? NULL : filename_ptr,
                           functionname_ptr);
 
-      return true;
+      return TRUE;
     }
 
   if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
                                             &found, filename_ptr,
                                             functionname_ptr, line_ptr,
                                             &elf_tdata (abfd)->line_info))
-    return false;
+    return FALSE;
   if (found && (*functionname_ptr || *line_ptr))
-    return true;
+    return TRUE;
 
   if (symbols == NULL)
-    return false;
+    return FALSE;
 
   if (! elf_find_function (abfd, section, symbols, offset,
                           filename_ptr, functionname_ptr))
-    return false;
+    return FALSE;
 
   *line_ptr = 0;
-  return true;
+  return TRUE;
 }
 
 int
-_bfd_elf_sizeof_headers (abfd, reloc)
-     bfd *abfd;
-     boolean reloc;
+_bfd_elf_sizeof_headers (bfd *abfd, bfd_boolean reloc)
 {
   int ret;
 
@@ -6072,57 +6473,41 @@ _bfd_elf_sizeof_headers (abfd, reloc)
   return ret;
 }
 
-boolean
-_bfd_elf_set_section_contents (abfd, section, location, offset, count)
-     bfd *abfd;
-     sec_ptr section;
-     PTR location;
-     file_ptr offset;
-     bfd_size_type count;
+bfd_boolean
+_bfd_elf_set_section_contents (bfd *abfd,
+                              sec_ptr section,
+                              const void *location,
+                              file_ptr offset,
+                              bfd_size_type count)
 {
   Elf_Internal_Shdr *hdr;
   bfd_signed_vma pos;
 
   if (! abfd->output_has_begun
-      && ! (_bfd_elf_compute_section_file_positions
-           (abfd, (struct bfd_link_info *) NULL)))
-    return false;
+      && ! _bfd_elf_compute_section_file_positions (abfd, NULL))
+    return FALSE;
 
   hdr = &elf_section_data (section)->this_hdr;
   pos = hdr->sh_offset + offset;
   if (bfd_seek (abfd, pos, SEEK_SET) != 0
       || bfd_bwrite (location, count, abfd) != count)
-    return false;
+    return FALSE;
 
-  return true;
+  return TRUE;
 }
 
 void
-_bfd_elf_no_info_to_howto (abfd, cache_ptr, dst)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     arelent *cache_ptr ATTRIBUTE_UNUSED;
-     Elf_Internal_Rela *dst ATTRIBUTE_UNUSED;
+_bfd_elf_no_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
+                          arelent *cache_ptr ATTRIBUTE_UNUSED,
+                          Elf_Internal_Rela *dst ATTRIBUTE_UNUSED)
 {
   abort ();
 }
 
-#if 0
-void
-_bfd_elf_no_info_to_howto_rel (abfd, cache_ptr, dst)
-     bfd *abfd;
-     arelent *cache_ptr;
-     Elf_Internal_Rel *dst;
-{
-  abort ();
-}
-#endif
-
 /* Try to convert a non-ELF reloc into an ELF one.  */
 
-boolean
-_bfd_elf_validate_reloc (abfd, areloc)
-     bfd *abfd;
-     arelent *areloc;
+bfd_boolean
+_bfd_elf_validate_reloc (bfd *abfd, arelent *areloc)
 {
   /* Check whether we really have an ELF howto.  */
 
@@ -6205,19 +6590,18 @@ _bfd_elf_validate_reloc (abfd, areloc)
        goto fail;
     }
 
-  return true;
+  return TRUE;
 
  fail:
   (*_bfd_error_handler)
-    (_("%s: unsupported relocation type %s"),
-     bfd_archive_filename (abfd), areloc->howto->name);
+    (_("%B: unsupported relocation type %s"),
+     abfd, areloc->howto->name);
   bfd_set_error (bfd_error_bad_value);
-  return false;
+  return FALSE;
 }
 
-boolean
-_bfd_elf_close_and_cleanup (abfd)
-     bfd *abfd;
+bfd_boolean
+_bfd_elf_close_and_cleanup (bfd *abfd)
 {
   if (bfd_get_format (abfd) == bfd_object)
     {
@@ -6234,14 +6618,11 @@ _bfd_elf_close_and_cleanup (abfd)
    this reloc.  */
 
 bfd_reloc_status_type
-_bfd_elf_rel_vtable_reloc_fn (abfd, re, symbol, data, is, obfd, errmsg)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     arelent *re ATTRIBUTE_UNUSED;
-     struct symbol_cache_entry *symbol ATTRIBUTE_UNUSED;
-     PTR data ATTRIBUTE_UNUSED;
-     asection *is ATTRIBUTE_UNUSED;
-     bfd *obfd ATTRIBUTE_UNUSED;
-     char **errmsg ATTRIBUTE_UNUSED;
+_bfd_elf_rel_vtable_reloc_fn
+  (bfd *abfd ATTRIBUTE_UNUSED, arelent *re ATTRIBUTE_UNUSED,
+   struct bfd_symbol *symbol ATTRIBUTE_UNUSED,
+   void *data ATTRIBUTE_UNUSED, asection *is ATTRIBUTE_UNUSED,
+   bfd *obfd ATTRIBUTE_UNUSED, char **errmsg ATTRIBUTE_UNUSED)
 {
   return bfd_reloc_ok;
 }
@@ -6258,8 +6639,7 @@ _bfd_elf_rel_vtable_reloc_fn (abfd, re, symbol, data, is, obfd, errmsg)
 /* FIXME: this is kinda wrong, but it's what gdb wants.  */
 
 static int
-elfcore_make_pid (abfd)
-     bfd *abfd;
+elfcore_make_pid (bfd *abfd)
 {
   return ((elf_tdata (abfd)->core_lwpid << 16)
          + (elf_tdata (abfd)->core_pid));
@@ -6270,26 +6650,23 @@ elfcore_make_pid (abfd)
    reference to NAME, so you shouldn't deallocate or
    overwrite it.  */
 
-static boolean
-elfcore_maybe_make_sect (abfd, name, sect)
-     bfd *abfd;
-     char *name;
-     asection *sect;
+static bfd_boolean
+elfcore_maybe_make_sect (bfd *abfd, char *name, asection *sect)
 {
   asection *sect2;
 
   if (bfd_get_section_by_name (abfd, name) != NULL)
-    return true;
+    return TRUE;
 
   sect2 = bfd_make_section (abfd, name);
   if (sect2 == NULL)
-    return false;
+    return FALSE;
 
-  sect2->_raw_size = sect->_raw_size;
+  sect2->size = sect->size;
   sect2->filepos = sect->filepos;
   sect2->flags = sect->flags;
   sect2->alignment_power = sect->alignment_power;
-  return true;
+  return TRUE;
 }
 
 /* Create a pseudosection containing SIZE bytes at FILEPOS.  This
@@ -6299,12 +6676,11 @@ elfcore_maybe_make_sect (abfd, name, sect)
    - For the multi-threaded case, a section named "NAME/PID", where
      PID is elfcore_make_pid (abfd).
    Both pseudosections have identical contents. */
-boolean
-_bfd_elfcore_make_pseudosection (abfd, name, size, filepos)
-     bfd *abfd;
-     char *name;
-     size_t size;
-     ufile_ptr filepos;
+bfd_boolean
+_bfd_elfcore_make_pseudosection (bfd *abfd,
+                                char *name,
+                                size_t size,
+                                ufile_ptr filepos)
 {
   char buf[100];
   char *threaded_name;
@@ -6315,15 +6691,15 @@ _bfd_elfcore_make_pseudosection (abfd, name, size, filepos)
 
   sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd));
   len = strlen (buf) + 1;
-  threaded_name = bfd_alloc (abfd, (bfd_size_type) len);
+  threaded_name = bfd_alloc (abfd, len);
   if (threaded_name == NULL)
-    return false;
+    return FALSE;
   memcpy (threaded_name, buf, len);
 
-  sect = bfd_make_section (abfd, threaded_name);
+  sect = bfd_make_section_anyway (abfd, threaded_name);
   if (sect == NULL)
-    return false;
-  sect->_raw_size = size;
+    return FALSE;
+  sect->size = size;
   sect->filepos = filepos;
   sect->flags = SEC_HAS_CONTENTS;
   sect->alignment_power = 2;
@@ -6338,21 +6714,18 @@ _bfd_elfcore_make_pseudosection (abfd, name, size, filepos)
 */
 
 #if defined (HAVE_PRSTATUS_T)
-static boolean elfcore_grok_prstatus PARAMS ((bfd *, Elf_Internal_Note *));
 
-static boolean
-elfcore_grok_prstatus (abfd, note)
-     bfd *abfd;
-     Elf_Internal_Note *note;
+static bfd_boolean
+elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
 {
-  size_t raw_size;
+  size_t size;
   int offset;
 
   if (note->descsz == sizeof (prstatus_t))
     {
       prstatus_t prstat;
 
-      raw_size = sizeof (prstat.pr_reg);
+      size = sizeof (prstat.pr_reg);
       offset   = offsetof (prstatus_t, pr_reg);
       memcpy (&prstat, note->descdata, sizeof (prstat));
 
@@ -6378,7 +6751,7 @@ elfcore_grok_prstatus (abfd, note)
       /* 64-bit host, 32-bit corefile */
       prstatus32_t prstat;
 
-      raw_size = sizeof (prstat.pr_reg);
+      size = sizeof (prstat.pr_reg);
       offset   = offsetof (prstatus32_t, pr_reg);
       memcpy (&prstat, note->descdata, sizeof (prstat));
 
@@ -6403,21 +6776,20 @@ elfcore_grok_prstatus (abfd, note)
     {
       /* Fail - we don't know how to handle any other
         note size (ie. data object type).  */
-      return true;
+      return TRUE;
     }
 
   /* Make a ".reg/999" section and a ".reg" section.  */
   return _bfd_elfcore_make_pseudosection (abfd, ".reg",
-                                         raw_size, note->descpos + offset);
+                                         size, note->descpos + offset);
 }
 #endif /* defined (HAVE_PRSTATUS_T) */
 
 /* Create a pseudosection containing the exact contents of NOTE.  */
-static boolean
-elfcore_make_note_pseudosection (abfd, name, note)
-     bfd *abfd;
-     char *name;
-     Elf_Internal_Note *note;
+static bfd_boolean
+elfcore_make_note_pseudosection (bfd *abfd,
+                                char *name,
+                                Elf_Internal_Note *note)
 {
   return _bfd_elfcore_make_pseudosection (abfd, name,
                                          note->descsz, note->descpos);
@@ -6427,10 +6799,8 @@ elfcore_make_note_pseudosection (abfd, name, note)
    but it doesn't matter, because we don't have to pick this
    data structure apart.  */
 
-static boolean
-elfcore_grok_prfpreg (abfd, note)
-     bfd *abfd;
-     Elf_Internal_Note *note;
+static bfd_boolean
+elfcore_grok_prfpreg (bfd *abfd, Elf_Internal_Note *note)
 {
   return elfcore_make_note_pseudosection (abfd, ".reg2", note);
 }
@@ -6439,10 +6809,8 @@ elfcore_grok_prfpreg (abfd, note)
    type of 5 (NT_PRXFPREG).  Just include the whole note's contents
    literally.  */
 
-static boolean
-elfcore_grok_prxfpreg (abfd, note)
-     bfd *abfd;
-     Elf_Internal_Note *note;
+static bfd_boolean
+elfcore_grok_prxfpreg (bfd *abfd, Elf_Internal_Note *note)
 {
   return elfcore_make_note_pseudosection (abfd, ".reg-xfp", note);
 }
@@ -6466,10 +6834,7 @@ typedef psinfo32_t elfcore_psinfo32_t;
    the copy will always have a terminating '\0'.  */
 
 char *
-_bfd_elfcore_strndup (abfd, start, max)
-     bfd *abfd;
-     char *start;
-     size_t max;
+_bfd_elfcore_strndup (bfd *abfd, char *start, size_t max)
 {
   char *dups;
   char *end = memchr (start, '\0', max);
@@ -6480,7 +6845,7 @@ _bfd_elfcore_strndup (abfd, start, max)
   else
     len = end - start;
 
-  dups = bfd_alloc (abfd, (bfd_size_type) len + 1);
+  dups = bfd_alloc (abfd, len + 1);
   if (dups == NULL)
     return NULL;
 
@@ -6491,12 +6856,8 @@ _bfd_elfcore_strndup (abfd, start, max)
 }
 
 #if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
-static boolean elfcore_grok_psinfo PARAMS ((bfd *, Elf_Internal_Note *));
-
-static boolean
-elfcore_grok_psinfo (abfd, note)
-     bfd *abfd;
-     Elf_Internal_Note *note;
+static bfd_boolean
+elfcore_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 {
   if (note->descsz == sizeof (elfcore_psinfo_t))
     {
@@ -6534,7 +6895,7 @@ elfcore_grok_psinfo (abfd, note)
     {
       /* Fail - we don't know how to handle any other
         note size (ie. data object type).  */
-      return true;
+      return TRUE;
     }
 
   /* Note that for some reason, a spurious space is tacked
@@ -6549,17 +6910,13 @@ elfcore_grok_psinfo (abfd, note)
       command[n - 1] = '\0';
   }
 
-  return true;
+  return TRUE;
 }
 #endif /* defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T) */
 
 #if defined (HAVE_PSTATUS_T)
-static boolean elfcore_grok_pstatus PARAMS ((bfd *, Elf_Internal_Note *));
-
-static boolean
-elfcore_grok_pstatus (abfd, note)
-     bfd *abfd;
-     Elf_Internal_Note *note;
+static bfd_boolean
+elfcore_grok_pstatus (bfd *abfd, Elf_Internal_Note *note)
 {
   if (note->descsz == sizeof (pstatus_t)
 #if defined (HAVE_PXSTATUS_T)
@@ -6588,17 +6945,13 @@ elfcore_grok_pstatus (abfd, note)
      lwpstatus_t in pstat.pr_lwp, but we'll catch it all in an
      NT_LWPSTATUS note, presumably.  */
 
-  return true;
+  return TRUE;
 }
 #endif /* defined (HAVE_PSTATUS_T) */
 
 #if defined (HAVE_LWPSTATUS_T)
-static boolean elfcore_grok_lwpstatus PARAMS ((bfd *, Elf_Internal_Note *));
-
-static boolean
-elfcore_grok_lwpstatus (abfd, note)
-     bfd *abfd;
-     Elf_Internal_Note *note;
+static bfd_boolean
+elfcore_grok_lwpstatus (bfd *abfd, Elf_Internal_Note *note)
 {
   lwpstatus_t lwpstat;
   char buf[100];
@@ -6611,7 +6964,7 @@ elfcore_grok_lwpstatus (abfd, note)
       && note->descsz != sizeof (lwpxstatus_t)
 #endif
       )
-    return true;
+    return TRUE;
 
   memcpy (&lwpstat, note->descdata, sizeof (lwpstat));
 
@@ -6622,23 +6975,23 @@ elfcore_grok_lwpstatus (abfd, note)
 
   sprintf (buf, ".reg/%d", elfcore_make_pid (abfd));
   len = strlen (buf) + 1;
-  name = bfd_alloc (abfd, (bfd_size_type) len);
+  name = bfd_alloc (abfd, len);
   if (name == NULL)
-    return false;
+    return FALSE;
   memcpy (name, buf, len);
 
-  sect = bfd_make_section (abfd, name);
+  sect = bfd_make_section_anyway (abfd, name);
   if (sect == NULL)
-    return false;
+    return FALSE;
 
 #if defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
-  sect->_raw_size = sizeof (lwpstat.pr_context.uc_mcontext.gregs);
+  sect->size = sizeof (lwpstat.pr_context.uc_mcontext.gregs);
   sect->filepos = note->descpos
     + offsetof (lwpstatus_t, pr_context.uc_mcontext.gregs);
 #endif
 
 #if defined (HAVE_LWPSTATUS_T_PR_REG)
-  sect->_raw_size = sizeof (lwpstat.pr_reg);
+  sect->size = sizeof (lwpstat.pr_reg);
   sect->filepos = note->descpos + offsetof (lwpstatus_t, pr_reg);
 #endif
 
@@ -6646,29 +6999,29 @@ elfcore_grok_lwpstatus (abfd, note)
   sect->alignment_power = 2;
 
   if (!elfcore_maybe_make_sect (abfd, ".reg", sect))
-    return false;
+    return FALSE;
 
   /* Make a ".reg2/999" section */
 
   sprintf (buf, ".reg2/%d", elfcore_make_pid (abfd));
   len = strlen (buf) + 1;
-  name = bfd_alloc (abfd, (bfd_size_type) len);
+  name = bfd_alloc (abfd, len);
   if (name == NULL)
-    return false;
+    return FALSE;
   memcpy (name, buf, len);
 
-  sect = bfd_make_section (abfd, name);
+  sect = bfd_make_section_anyway (abfd, name);
   if (sect == NULL)
-    return false;
+    return FALSE;
 
 #if defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
-  sect->_raw_size = sizeof (lwpstat.pr_context.uc_mcontext.fpregs);
+  sect->size = sizeof (lwpstat.pr_context.uc_mcontext.fpregs);
   sect->filepos = note->descpos
     + offsetof (lwpstatus_t, pr_context.uc_mcontext.fpregs);
 #endif
 
 #if defined (HAVE_LWPSTATUS_T_PR_FPREG)
-  sect->_raw_size = sizeof (lwpstat.pr_fpreg);
+  sect->size = sizeof (lwpstat.pr_fpreg);
   sect->filepos = note->descpos + offsetof (lwpstatus_t, pr_fpreg);
 #endif
 
@@ -6680,10 +7033,8 @@ elfcore_grok_lwpstatus (abfd, note)
 #endif /* defined (HAVE_LWPSTATUS_T) */
 
 #if defined (HAVE_WIN32_PSTATUS_T)
-static boolean
-elfcore_grok_win32pstatus (abfd, note)
-     bfd *abfd;
-     Elf_Internal_Note *note;
+static bfd_boolean
+elfcore_grok_win32pstatus (bfd *abfd, Elf_Internal_Note *note)
 {
   char buf[30];
   char *name;
@@ -6692,7 +7043,7 @@ elfcore_grok_win32pstatus (abfd, note)
   win32_pstatus_t pstatus;
 
   if (note->descsz < sizeof (pstatus))
-    return true;
+    return TRUE;
 
   memcpy (&pstatus, note->descdata, sizeof (pstatus));
 
@@ -6709,17 +7060,17 @@ elfcore_grok_win32pstatus (abfd, note)
       sprintf (buf, ".reg/%d", pstatus.data.thread_info.tid);
 
       len = strlen (buf) + 1;
-      name = bfd_alloc (abfd, (bfd_size_type) len);
+      name = bfd_alloc (abfd, len);
       if (name == NULL)
-       return false;
+       return FALSE;
 
       memcpy (name, buf, len);
 
-      sect = bfd_make_section (abfd, name);
+      sect = bfd_make_section_anyway (abfd, name);
       if (sect == NULL)
-       return false;
+       return FALSE;
 
-      sect->_raw_size = sizeof (pstatus.data.thread_info.thread_context);
+      sect->size = sizeof (pstatus.data.thread_info.thread_context);
       sect->filepos = (note->descpos
                       + offsetof (struct win32_pstatus,
                                   data.thread_info.thread_context));
@@ -6728,7 +7079,7 @@ elfcore_grok_win32pstatus (abfd, note)
 
       if (pstatus.data.thread_info.is_active_thread)
        if (! elfcore_maybe_make_sect (abfd, ".reg", sect))
-         return false;
+         return FALSE;
       break;
 
     case NOTE_INFO_MODULE:
@@ -6736,51 +7087,49 @@ elfcore_grok_win32pstatus (abfd, note)
       sprintf (buf, ".module/%08x", pstatus.data.module_info.base_address);
 
       len = strlen (buf) + 1;
-      name = bfd_alloc (abfd, (bfd_size_type) len);
+      name = bfd_alloc (abfd, len);
       if (name == NULL)
-       return false;
+       return FALSE;
 
       memcpy (name, buf, len);
 
-      sect = bfd_make_section (abfd, name);
+      sect = bfd_make_section_anyway (abfd, name);
 
       if (sect == NULL)
-       return false;
+       return FALSE;
 
-      sect->_raw_size = note->descsz;
+      sect->size = note->descsz;
       sect->filepos = note->descpos;
       sect->flags = SEC_HAS_CONTENTS;
       sect->alignment_power = 2;
       break;
 
     default:
-      return true;
+      return TRUE;
     }
 
-  return true;
+  return TRUE;
 }
 #endif /* HAVE_WIN32_PSTATUS_T */
 
-static boolean
-elfcore_grok_note (abfd, note)
-     bfd *abfd;
-     Elf_Internal_Note *note;
+static bfd_boolean
+elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
 {
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   switch (note->type)
     {
     default:
-      return true;
+      return TRUE;
 
     case NT_PRSTATUS:
       if (bed->elf_backend_grok_prstatus)
        if ((*bed->elf_backend_grok_prstatus) (abfd, note))
-         return true;
+         return TRUE;
 #if defined (HAVE_PRSTATUS_T)
       return elfcore_grok_prstatus (abfd, note);
 #else
-      return true;
+      return TRUE;
 #endif
 
 #if defined (HAVE_PSTATUS_T)
@@ -6802,29 +7151,41 @@ elfcore_grok_note (abfd, note)
 #endif
 
     case NT_PRXFPREG:          /* Linux SSE extension */
-      if (note->namesz == 5
-         && ! strcmp (note->namedata, "LINUX"))
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
        return elfcore_grok_prxfpreg (abfd, note);
       else
-       return true;
+       return TRUE;
 
     case NT_PRPSINFO:
     case NT_PSINFO:
       if (bed->elf_backend_grok_psinfo)
        if ((*bed->elf_backend_grok_psinfo) (abfd, note))
-         return true;
+         return TRUE;
 #if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
       return elfcore_grok_psinfo (abfd, note);
 #else
-      return true;
+      return TRUE;
 #endif
+
+    case NT_AUXV:
+      {
+       asection *sect = bfd_make_section_anyway (abfd, ".auxv");
+
+       if (sect == NULL)
+         return FALSE;
+       sect->size = note->descsz;
+       sect->filepos = note->descpos;
+       sect->flags = SEC_HAS_CONTENTS;
+       sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
+
+       return TRUE;
+      }
     }
 }
 
-static boolean
-elfcore_netbsd_get_lwpid (note, lwpidp)
-     Elf_Internal_Note *note;
-     int *lwpidp;
+static bfd_boolean
+elfcore_netbsd_get_lwpid (Elf_Internal_Note *note, int *lwpidp)
 {
   char *cp;
 
@@ -6832,15 +7193,13 @@ elfcore_netbsd_get_lwpid (note, lwpidp)
   if (cp != NULL)
     {
       *lwpidp = atoi(cp + 1);
-      return true;
+      return TRUE;
     }
-  return false;
+  return FALSE;
 }
 
-static boolean
-elfcore_grok_netbsd_procinfo (abfd, note)
-     bfd *abfd;
-     Elf_Internal_Note *note;
+static bfd_boolean
+elfcore_grok_netbsd_procinfo (bfd *abfd, Elf_Internal_Note *note)
 {
 
   /* Signal number at offset 0x08. */
@@ -6855,13 +7214,12 @@ elfcore_grok_netbsd_procinfo (abfd, note)
   elf_tdata (abfd)->core_command
     = _bfd_elfcore_strndup (abfd, note->descdata + 0x7c, 31);
 
-  return true;
+  return elfcore_make_note_pseudosection (abfd, ".note.netbsdcore.procinfo",
+                                         note);
 }
 
-static boolean
-elfcore_grok_netbsd_note (abfd, note)
-     bfd *abfd;
-     Elf_Internal_Note *note;
+static bfd_boolean
+elfcore_grok_netbsd_note (bfd *abfd, Elf_Internal_Note *note)
 {
   int lwp;
 
@@ -6884,7 +7242,7 @@ elfcore_grok_netbsd_note (abfd, note)
      understand it.  */
 
   if (note->type < NT_NETBSDCORE_FIRSTMACH)
-    return true;
+    return TRUE;
 
 
   switch (bfd_get_arch (abfd))
@@ -6903,7 +7261,7 @@ elfcore_grok_netbsd_note (abfd, note)
           return elfcore_make_note_pseudosection (abfd, ".reg2", note);
 
         default:
-          return true;
+          return TRUE;
         }
 
     /* On all other arch's, PT_GETREGS == mach+1 and
@@ -6919,12 +7277,118 @@ elfcore_grok_netbsd_note (abfd, note)
           return elfcore_make_note_pseudosection (abfd, ".reg2", note);
 
         default:
-          return true;
+          return TRUE;
         }
     }
     /* NOTREACHED */
 }
 
+static bfd_boolean
+elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, pid_t *tid)
+{
+  void *ddata = note->descdata;
+  char buf[100];
+  char *name;
+  asection *sect;
+  short sig;
+  unsigned flags;
+
+  /* nto_procfs_status 'pid' field is at offset 0.  */
+  elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, (bfd_byte *) ddata);
+
+  /* nto_procfs_status 'tid' field is at offset 4.  Pass it back.  */
+  *tid = bfd_get_32 (abfd, (bfd_byte *) ddata + 4);
+
+  /* nto_procfs_status 'flags' field is at offset 8.  */
+  flags = bfd_get_32 (abfd, (bfd_byte *) ddata + 8);
+
+  /* nto_procfs_status 'what' field is at offset 14.  */
+  if ((sig = bfd_get_16 (abfd, (bfd_byte *) ddata + 14)) > 0)
+    {
+      elf_tdata (abfd)->core_signal = sig;
+      elf_tdata (abfd)->core_lwpid = *tid;
+    }
+
+  /* _DEBUG_FLAG_CURTID (current thread) is 0x80.  Some cores
+     do not come from signals so we make sure we set the current
+     thread just in case.  */
+  if (flags & 0x00000080)
+    elf_tdata (abfd)->core_lwpid = *tid;
+
+  /* Make a ".qnx_core_status/%d" section.  */
+  sprintf (buf, ".qnx_core_status/%d", *tid);
+
+  name = bfd_alloc (abfd, strlen (buf) + 1);
+  if (name == NULL)
+    return FALSE;
+  strcpy (name, buf);
+
+  sect = bfd_make_section_anyway (abfd, name);
+  if (sect == NULL)
+    return FALSE;
+
+  sect->size            = note->descsz;
+  sect->filepos         = note->descpos;
+  sect->flags           = SEC_HAS_CONTENTS;
+  sect->alignment_power = 2;
+
+  return (elfcore_maybe_make_sect (abfd, ".qnx_core_status", sect));
+}
+
+static bfd_boolean
+elfcore_grok_nto_gregs (bfd *abfd, Elf_Internal_Note *note, pid_t tid)
+{
+  char buf[100];
+  char *name;
+  asection *sect;
+
+  /* Make a ".reg/%d" section.  */
+  sprintf (buf, ".reg/%d", tid);
+
+  name = bfd_alloc (abfd, strlen (buf) + 1);
+  if (name == NULL)
+    return FALSE;
+  strcpy (name, buf);
+
+  sect = bfd_make_section_anyway (abfd, name);
+  if (sect == NULL)
+    return FALSE;
+
+  sect->size            = note->descsz;
+  sect->filepos         = note->descpos;
+  sect->flags           = SEC_HAS_CONTENTS;
+  sect->alignment_power = 2;
+
+  /* This is the current thread.  */
+  if (elf_tdata (abfd)->core_lwpid == tid)
+    return elfcore_maybe_make_sect (abfd, ".reg", sect);
+
+  return TRUE;
+}
+
+#define BFD_QNT_CORE_INFO      7
+#define BFD_QNT_CORE_STATUS    8
+#define BFD_QNT_CORE_GREG      9
+#define BFD_QNT_CORE_FPREG     10
+
+static bfd_boolean
+elfcore_grok_nto_note (bfd *abfd, Elf_Internal_Note *note)
+{
+  /* Every GREG section has a STATUS section before it.  Store the
+     tid from the previous call to pass down to the next gregs
+     function.  */
+  static pid_t tid = 1;
+
+  switch (note->type)
+    {
+    case BFD_QNT_CORE_INFO:   return elfcore_make_note_pseudosection (abfd, ".qnx_core_info", note);
+    case BFD_QNT_CORE_STATUS: return elfcore_grok_nto_status (abfd, note, &tid);
+    case BFD_QNT_CORE_GREG:   return elfcore_grok_nto_gregs (abfd, note, tid);
+    case BFD_QNT_CORE_FPREG:  return elfcore_grok_prfpreg (abfd, note);
+    default:                  return TRUE;
+    }
+}
+
 /* Function: elfcore_write_note
 
    Inputs:
@@ -6938,14 +7402,13 @@ elfcore_grok_netbsd_note (abfd, note)
    End of buffer containing note.  */
 
 char *
-elfcore_write_note (abfd, buf, bufsiz, name, type, input, size)
-     bfd  *abfd;
-     char *buf;
-     int  *bufsiz;
-     const char *name;
-     int  type;
-     const PTR input;
-     int  size;
+elfcore_write_note (bfd  *abfd,
+                   char *buf,
+                   int  *bufsiz,
+                   const char *name,
+                   int  type,
+                   const void *input,
+                   int  size)
 {
   Elf_External_Note *xnp;
   size_t namesz;
@@ -6957,14 +7420,14 @@ elfcore_write_note (abfd, buf, bufsiz, name, type, input, size)
   pad = 0;
   if (name != NULL)
     {
-      struct elf_backend_data *bed;
+      const struct elf_backend_data *bed;
 
       namesz = strlen (name) + 1;
       bed = get_elf_backend_data (abfd);
-      pad = -namesz & (bed->s->file_align - 1);
+      pad = -namesz & ((1 << bed->s->log_file_align) - 1);
     }
 
-  newspace = sizeof (Elf_External_Note) - 1 + namesz + pad + size;
+  newspace = 12 + namesz + pad + size;
 
   p = realloc (buf, *bufsiz + newspace);
   dest = p + *bufsiz;
@@ -6990,12 +7453,11 @@ elfcore_write_note (abfd, buf, bufsiz, name, type, input, size)
 
 #if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
 char *
-elfcore_write_prpsinfo (abfd, buf, bufsiz, fname, psargs)
-     bfd  *abfd;
-     char *buf;
-     int  *bufsiz;
-     const char *fname;
-     const char *psargs;
+elfcore_write_prpsinfo (bfd  *abfd,
+                       char *buf,
+                       int  *bufsiz,
+                       const char *fname,
+                       const char *psargs)
 {
   int note_type;
   char *note_name = "CORE";
@@ -7018,13 +7480,12 @@ elfcore_write_prpsinfo (abfd, buf, bufsiz, fname, psargs)
 
 #if defined (HAVE_PRSTATUS_T)
 char *
-elfcore_write_prstatus (abfd, buf, bufsiz, pid, cursig, gregs)
-     bfd *abfd;
-     char *buf;
-     int *bufsiz;
-     long pid;
-     int cursig;
-     const PTR gregs;
+elfcore_write_prstatus (bfd *abfd,
+                       char *buf,
+                       int *bufsiz,
+                       long pid,
+                       int cursig,
+                       const void *gregs)
 {
   prstatus_t prstat;
   char *note_name = "CORE";
@@ -7040,13 +7501,12 @@ elfcore_write_prstatus (abfd, buf, bufsiz, pid, cursig, gregs)
 
 #if defined (HAVE_LWPSTATUS_T)
 char *
-elfcore_write_lwpstatus (abfd, buf, bufsiz, pid, cursig, gregs)
-     bfd *abfd;
-     char *buf;
-     int *bufsiz;
-     long pid;
-     int cursig;
-     const PTR gregs;
+elfcore_write_lwpstatus (bfd *abfd,
+                        char *buf,
+                        int *bufsiz,
+                        long pid,
+                        int cursig,
+                        const void *gregs)
 {
   lwpstatus_t lwpstat;
   char *note_name = "CORE";
@@ -7072,13 +7532,12 @@ elfcore_write_lwpstatus (abfd, buf, bufsiz, pid, cursig, gregs)
 
 #if defined (HAVE_PSTATUS_T)
 char *
-elfcore_write_pstatus (abfd, buf, bufsiz, pid, cursig, gregs)
-     bfd *abfd;
-     char *buf;
-     int *bufsiz;
-     long pid;
-     int cursig;
-     const PTR gregs;
+elfcore_write_pstatus (bfd *abfd,
+                      char *buf,
+                      int *bufsiz,
+                      long pid,
+                      int cursig,
+                      const void *gregs)
 {
   pstatus_t pstat;
   char *note_name = "CORE";
@@ -7092,12 +7551,11 @@ elfcore_write_pstatus (abfd, buf, bufsiz, pid, cursig, gregs)
 #endif /* HAVE_PSTATUS_T */
 
 char *
-elfcore_write_prfpreg (abfd, buf, bufsiz, fpregs, size)
-     bfd  *abfd;
-     char *buf;
-     int  *bufsiz;
-     const PTR fpregs;
-     int size;
+elfcore_write_prfpreg (bfd *abfd,
+                      char *buf,
+                      int *bufsiz,
+                      const void *fpregs,
+                      int size)
 {
   char *note_name = "CORE";
   return elfcore_write_note (abfd, buf, bufsiz,
@@ -7105,42 +7563,38 @@ elfcore_write_prfpreg (abfd, buf, bufsiz, fpregs, size)
 }
 
 char *
-elfcore_write_prxfpreg (abfd, buf, bufsiz, xfpregs, size)
-     bfd  *abfd;
-     char *buf;
-     int  *bufsiz;
-     const PTR xfpregs;
-     int size;
+elfcore_write_prxfpreg (bfd *abfd,
+                       char *buf,
+                       int *bufsiz,
+                       const void *xfpregs,
+                       int size)
 {
   char *note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
                             note_name, NT_PRXFPREG, xfpregs, size);
 }
 
-static boolean
-elfcore_read_notes (abfd, offset, size)
-     bfd *abfd;
-     file_ptr offset;
-     bfd_size_type size;
+static bfd_boolean
+elfcore_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size)
 {
   char *buf;
   char *p;
 
   if (size <= 0)
-    return true;
+    return TRUE;
 
   if (bfd_seek (abfd, offset, SEEK_SET) != 0)
-    return false;
+    return FALSE;
 
   buf = bfd_malloc (size);
   if (buf == NULL)
-    return false;
+    return FALSE;
 
   if (bfd_bread (buf, size, abfd) != size)
     {
     error:
       free (buf);
-      return false;
+      return FALSE;
     }
 
   p = buf;
@@ -7164,6 +7618,11 @@ elfcore_read_notes (abfd, offset, size)
           if (! elfcore_grok_netbsd_note (abfd, &in))
             goto error;
         }
+      else if (strncmp (in.namedata, "QNX", 3) == 0)
+       {
+         if (! elfcore_grok_nto_note (abfd, &in))
+           goto error;
+       }
       else
         {
           if (! elfcore_grok_note (abfd, &in))
@@ -7174,7 +7633,7 @@ elfcore_read_notes (abfd, offset, size)
     }
 
   free (buf);
-  return true;
+  return TRUE;
 }
 \f
 /* Providing external access to the ELF program header table.  */
@@ -7184,8 +7643,7 @@ elfcore_read_notes (abfd, offset, size)
    occurs; bfd_get_error will return an appropriate code.  */
 
 long
-bfd_get_elf_phdr_upper_bound (abfd)
-     bfd *abfd;
+bfd_get_elf_phdr_upper_bound (bfd *abfd)
 {
   if (abfd->xvec->flavour != bfd_target_elf_flavour)
     {
@@ -7205,9 +7663,7 @@ bfd_get_elf_phdr_upper_bound (abfd)
    error occurs; bfd_get_error will return an appropriate code.  */
 
 int
-bfd_get_elf_phdrs (abfd, phdrs)
-     bfd *abfd;
-     void *phdrs;
+bfd_get_elf_phdrs (bfd *abfd, void *phdrs)
 {
   int num_phdrs;
 
@@ -7225,10 +7681,7 @@ bfd_get_elf_phdrs (abfd, phdrs)
 }
 
 void
-_bfd_elf_sprintf_vma (abfd, buf, value)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     char *buf;
-     bfd_vma value;
+_bfd_elf_sprintf_vma (bfd *abfd ATTRIBUTE_UNUSED, char *buf, bfd_vma value)
 {
 #ifdef BFD64
   Elf_Internal_Ehdr *i_ehdrp;  /* Elf file header, internal form */
@@ -7256,10 +7709,7 @@ _bfd_elf_sprintf_vma (abfd, buf, value)
 }
 
 void
-_bfd_elf_fprintf_vma (abfd, stream, value)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     PTR stream;
-     bfd_vma value;
+_bfd_elf_fprintf_vma (bfd *abfd ATTRIBUTE_UNUSED, void *stream, bfd_vma value)
 {
 #ifdef BFD64
   Elf_Internal_Ehdr *i_ehdrp;  /* Elf file header, internal form */
@@ -7288,8 +7738,7 @@ _bfd_elf_fprintf_vma (abfd, stream, value)
 }
 
 enum elf_reloc_type_class
-_bfd_elf_reloc_type_class (rela)
-     const Elf_Internal_Rela *rela ATTRIBUTE_UNUSED;
+_bfd_elf_reloc_type_class (const Elf_Internal_Rela *rela ATTRIBUTE_UNUSED)
 {
   return reloc_class_normal;
 }
@@ -7298,12 +7747,12 @@ _bfd_elf_reloc_type_class (rela)
    relocation against a local symbol.  */
 
 bfd_vma
-_bfd_elf_rela_local_sym (abfd, sym, sec, rel)
-     bfd *abfd;
-     Elf_Internal_Sym *sym;
-     asection *sec;
-     Elf_Internal_Rela *rel;
+_bfd_elf_rela_local_sym (bfd *abfd,
+                        Elf_Internal_Sym *sym,
+                        asection **psec,
+                        Elf_Internal_Rela *rel)
 {
+  asection *sec = *psec;
   bfd_vma relocation;
 
   relocation = (sec->output_section->vma
@@ -7311,58 +7760,376 @@ _bfd_elf_rela_local_sym (abfd, sym, sec, rel)
                + sym->st_value);
   if ((sec->flags & SEC_MERGE)
       && ELF_ST_TYPE (sym->st_info) == STT_SECTION
-      && elf_section_data (sec)->sec_info_type == ELF_INFO_TYPE_MERGE)
+      && sec->sec_info_type == ELF_INFO_TYPE_MERGE)
     {
-      asection *msec;
-
-      msec = sec;
       rel->r_addend =
-       _bfd_merged_section_offset (abfd, &msec,
+       _bfd_merged_section_offset (abfd, psec,
                                    elf_section_data (sec)->sec_info,
-                                   sym->st_value + rel->r_addend,
-                                   (bfd_vma) 0)
-       - relocation;
-      rel->r_addend += msec->output_section->vma + msec->output_offset;
+                                   sym->st_value + rel->r_addend);
+      if (sec != *psec)
+       {
+         /* If we have changed the section, and our original section is
+            marked with SEC_EXCLUDE, it means that the original
+            SEC_MERGE section has been completely subsumed in some
+            other SEC_MERGE section.  In this case, we need to leave
+            some info around for --emit-relocs.  */
+         if ((sec->flags & SEC_EXCLUDE) != 0)
+           sec->kept_section = *psec;
+         sec = *psec;
+       }
+      rel->r_addend -= relocation;
+      rel->r_addend += sec->output_section->vma + sec->output_offset;
     }
   return relocation;
 }
 
 bfd_vma
-_bfd_elf_rel_local_sym (abfd, sym, psec, addend)
-     bfd *abfd;
-     Elf_Internal_Sym *sym;
-     asection **psec;
-     bfd_vma addend;
+_bfd_elf_rel_local_sym (bfd *abfd,
+                       Elf_Internal_Sym *sym,
+                       asection **psec,
+                       bfd_vma addend)
 {
   asection *sec = *psec;
 
-  if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_MERGE)
+  if (sec->sec_info_type != ELF_INFO_TYPE_MERGE)
     return sym->st_value + addend;
 
   return _bfd_merged_section_offset (abfd, psec,
                                     elf_section_data (sec)->sec_info,
-                                    sym->st_value + addend, (bfd_vma) 0);
+                                    sym->st_value + addend);
 }
 
 bfd_vma
-_bfd_elf_section_offset (abfd, info, sec, offset)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *sec;
-     bfd_vma offset;
+_bfd_elf_section_offset (bfd *abfd,
+                        struct bfd_link_info *info,
+                        asection *sec,
+                        bfd_vma offset)
 {
-  struct bfd_elf_section_data *sec_data;
-
-  sec_data = elf_section_data (sec);
-  switch (sec_data->sec_info_type)
+  switch (sec->sec_info_type)
     {
     case ELF_INFO_TYPE_STABS:
-      return _bfd_stab_section_offset
-       (abfd, &elf_hash_table (info)->merge_info, sec, &sec_data->sec_info,
-        offset);
+      return _bfd_stab_section_offset (sec, elf_section_data (sec)->sec_info,
+                                      offset);
     case ELF_INFO_TYPE_EH_FRAME:
-      return _bfd_elf_eh_frame_section_offset (abfd, sec, offset);
+      return _bfd_elf_eh_frame_section_offset (abfd, info, sec, offset);
     default:
       return offset;
     }
 }
+\f
+/* Create a new BFD as if by bfd_openr.  Rather than opening a file,
+   reconstruct an ELF file by reading the segments out of remote memory
+   based on the ELF file header at EHDR_VMA and the ELF program headers it
+   points to.  If not null, *LOADBASEP is filled in with the difference
+   between the VMAs from which the segments were read, and the VMAs the
+   file headers (and hence BFD's idea of each section's VMA) put them at.
+
+   The function TARGET_READ_MEMORY is called to copy LEN bytes from the
+   remote memory at target address VMA into the local buffer at MYADDR; it
+   should return zero on success or an `errno' code on failure.  TEMPL must
+   be a BFD for an ELF target with the word size and byte order found in
+   the remote memory.  */
+
+bfd *
+bfd_elf_bfd_from_remote_memory
+  (bfd *templ,
+   bfd_vma ehdr_vma,
+   bfd_vma *loadbasep,
+   int (*target_read_memory) (bfd_vma, char *, int))
+{
+  return (*get_elf_backend_data (templ)->elf_backend_bfd_from_remote_memory)
+    (templ, ehdr_vma, loadbasep, target_read_memory);
+}
+\f
+long
+_bfd_elf_get_synthetic_symtab (bfd *abfd,
+                              long symcount ATTRIBUTE_UNUSED,
+                              asymbol **syms ATTRIBUTE_UNUSED,
+                              long dynsymcount ATTRIBUTE_UNUSED,
+                              asymbol **dynsyms,
+                              asymbol **ret)
+{
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  asection *relplt;
+  asymbol *s;
+  const char *relplt_name;
+  bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
+  arelent *p;
+  long count, i, n;
+  size_t size;
+  Elf_Internal_Shdr *hdr;
+  char *names;
+  asection *plt;
+
+  if ((abfd->flags & (DYNAMIC | EXEC_P)) == 0)
+    return 0;
+
+  *ret = NULL;
+  if (!bed->plt_sym_val)
+    return 0;
+
+  relplt_name = bed->relplt_name;
+  if (relplt_name == NULL)
+    relplt_name = bed->default_use_rela_p ? ".rela.plt" : ".rel.plt";
+  relplt = bfd_get_section_by_name (abfd, relplt_name);
+  if (relplt == NULL)
+    return 0;
+
+  hdr = &elf_section_data (relplt)->this_hdr;
+  if (hdr->sh_link != elf_dynsymtab (abfd)
+      || (hdr->sh_type != SHT_REL && hdr->sh_type != SHT_RELA))
+    return 0;
+
+  plt = bfd_get_section_by_name (abfd, ".plt");
+  if (plt == NULL)
+    return 0;
+
+  slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
+  if (! (*slurp_relocs) (abfd, relplt, dynsyms, TRUE))
+    return -1;
+
+  count = relplt->size / hdr->sh_entsize;
+  size = count * sizeof (asymbol);
+  p = relplt->relocation;
+  for (i = 0; i < count; i++, s++, p++)
+    size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
+
+  s = *ret = bfd_malloc (size);
+  if (s == NULL)
+    return -1;
+
+  names = (char *) (s + count);
+  p = relplt->relocation;
+  n = 0;
+  for (i = 0; i < count; i++, s++, p++)
+    {
+      size_t len;
+      bfd_vma addr;
+
+      addr = bed->plt_sym_val (i, plt, p);
+      if (addr == (bfd_vma) -1)
+       continue;
+
+      *s = **p->sym_ptr_ptr;
+      s->section = plt;
+      s->value = addr - plt->vma;
+      s->name = names;
+      len = strlen ((*p->sym_ptr_ptr)->name);
+      memcpy (names, (*p->sym_ptr_ptr)->name, len);
+      names += len;
+      memcpy (names, "@plt", sizeof ("@plt"));
+      names += sizeof ("@plt");
+      ++n;
+    }
+
+  return n;
+}
+
+/* Sort symbol by binding and section. We want to put definitions
+   sorted by section at the beginning.  */
+
+static int
+elf_sort_elf_symbol (const void *arg1, const void *arg2)
+{
+  const Elf_Internal_Sym *s1;
+  const Elf_Internal_Sym *s2;
+  int shndx;
+
+  /* Make sure that undefined symbols are at the end.  */
+  s1 = (const Elf_Internal_Sym *) arg1;
+  if (s1->st_shndx == SHN_UNDEF)
+    return 1;
+  s2 = (const Elf_Internal_Sym *) arg2;
+  if (s2->st_shndx == SHN_UNDEF)
+    return -1;
+
+  /* Sorted by section index.  */
+  shndx = s1->st_shndx - s2->st_shndx;
+  if (shndx != 0)
+    return shndx;
+
+  /* Sorted by binding.  */
+  return ELF_ST_BIND (s1->st_info)  - ELF_ST_BIND (s2->st_info);
+}
+
+struct elf_symbol
+{
+  Elf_Internal_Sym *sym;
+  const char *name;
+};
+
+static int
+elf_sym_name_compare (const void *arg1, const void *arg2)
+{
+  const struct elf_symbol *s1 = (const struct elf_symbol *) arg1;
+  const struct elf_symbol *s2 = (const struct elf_symbol *) arg2;
+  return strcmp (s1->name, s2->name);
+}
+
+/* Check if 2 sections define the same set of local and global
+   symbols.  */
+
+bfd_boolean
+bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2)
+{
+  bfd *bfd1, *bfd2;
+  const struct elf_backend_data *bed1, *bed2;
+  Elf_Internal_Shdr *hdr1, *hdr2;
+  bfd_size_type symcount1, symcount2;
+  Elf_Internal_Sym *isymbuf1, *isymbuf2;
+  Elf_Internal_Sym *isymstart1 = NULL, *isymstart2 = NULL, *isym;
+  Elf_Internal_Sym *isymend;
+  struct elf_symbol *symp, *symtable1 = NULL, *symtable2 = NULL;
+  bfd_size_type count1, count2, i;
+  int shndx1, shndx2;
+  bfd_boolean result;
+
+  bfd1 = sec1->owner;
+  bfd2 = sec2->owner;
+
+  /* If both are .gnu.linkonce sections, they have to have the same
+     section name.  */
+  if (strncmp (sec1->name, ".gnu.linkonce",
+              sizeof ".gnu.linkonce" - 1) == 0
+      && strncmp (sec2->name, ".gnu.linkonce",
+                 sizeof ".gnu.linkonce" - 1) == 0)
+    return strcmp (sec1->name + sizeof ".gnu.linkonce",
+                  sec2->name + sizeof ".gnu.linkonce") == 0;
+
+  /* Both sections have to be in ELF.  */
+  if (bfd_get_flavour (bfd1) != bfd_target_elf_flavour
+      || bfd_get_flavour (bfd2) != bfd_target_elf_flavour)
+    return FALSE;
+
+  if (elf_section_type (sec1) != elf_section_type (sec2))
+    return FALSE;
+
+  if ((elf_section_flags (sec1) & SHF_GROUP) != 0
+      && (elf_section_flags (sec2) & SHF_GROUP) != 0)
+    {
+      /* If both are members of section groups, they have to have the
+        same group name.  */
+      if (strcmp (elf_group_name (sec1), elf_group_name (sec2)) != 0)
+       return FALSE;
+    }
+
+  shndx1 = _bfd_elf_section_from_bfd_section (bfd1, sec1);
+  shndx2 = _bfd_elf_section_from_bfd_section (bfd2, sec2);
+  if (shndx1 == -1 || shndx2 == -1)
+    return FALSE;
+
+  bed1 = get_elf_backend_data (bfd1);
+  bed2 = get_elf_backend_data (bfd2);
+  hdr1 = &elf_tdata (bfd1)->symtab_hdr;
+  symcount1 = hdr1->sh_size / bed1->s->sizeof_sym;
+  hdr2 = &elf_tdata (bfd2)->symtab_hdr;
+  symcount2 = hdr2->sh_size / bed2->s->sizeof_sym;
+
+  if (symcount1 == 0 || symcount2 == 0)
+    return FALSE;
+
+  isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0,
+                                  NULL, NULL, NULL);
+  isymbuf2 = bfd_elf_get_elf_syms (bfd2, hdr2, symcount2, 0,
+                                  NULL, NULL, NULL);
+
+  result = FALSE;
+  if (isymbuf1 == NULL || isymbuf2 == NULL)
+    goto done;
+
+  /* Sort symbols by binding and section. Global definitions are at
+     the beginning.  */
+  qsort (isymbuf1, symcount1, sizeof (Elf_Internal_Sym),
+        elf_sort_elf_symbol);
+  qsort (isymbuf2, symcount2, sizeof (Elf_Internal_Sym),
+        elf_sort_elf_symbol);
+
+  /* Count definitions in the section.  */
+  count1 = 0;
+  for (isym = isymbuf1, isymend = isym + symcount1;
+       isym < isymend; isym++)
+    {
+      if (isym->st_shndx == (unsigned int) shndx1)
+       {
+         if (count1 == 0)
+           isymstart1 = isym;
+         count1++;
+       }
+
+      if (count1 && isym->st_shndx != (unsigned int) shndx1)
+       break;
+    }
+
+  count2 = 0;
+  for (isym = isymbuf2, isymend = isym + symcount2;
+       isym < isymend; isym++)
+    {
+      if (isym->st_shndx == (unsigned int) shndx2)
+       {
+         if (count2 == 0)
+           isymstart2 = isym;
+         count2++;
+       }
+
+      if (count2 && isym->st_shndx != (unsigned int) shndx2)
+       break;
+    }
+
+  if (count1 == 0 || count2 == 0 || count1 != count2)
+    goto done;
+
+  symtable1 = bfd_malloc (count1 * sizeof (struct elf_symbol));
+  symtable2 = bfd_malloc (count1 * sizeof (struct elf_symbol));
+
+  if (symtable1 == NULL || symtable2 == NULL)
+    goto done;
+
+  symp = symtable1;
+  for (isym = isymstart1, isymend = isym + count1;
+       isym < isymend; isym++)
+    {
+      symp->sym = isym;
+      symp->name = bfd_elf_string_from_elf_section (bfd1,
+                                                   hdr1->sh_link,
+                                                   isym->st_name);
+      symp++;
+    }
+  symp = symtable2;
+  for (isym = isymstart2, isymend = isym + count1;
+       isym < isymend; isym++)
+    {
+      symp->sym = isym;
+      symp->name = bfd_elf_string_from_elf_section (bfd2,
+                                                   hdr2->sh_link,
+                                                   isym->st_name);
+      symp++;
+    }
+  
+  /* Sort symbol by name.  */
+  qsort (symtable1, count1, sizeof (struct elf_symbol),
+        elf_sym_name_compare);
+  qsort (symtable2, count1, sizeof (struct elf_symbol),
+        elf_sym_name_compare);
+
+  for (i = 0; i < count1; i++)
+    /* Two symbols must have the same binding, type and name.  */
+    if (symtable1 [i].sym->st_info != symtable2 [i].sym->st_info
+       || symtable1 [i].sym->st_other != symtable2 [i].sym->st_other
+       || strcmp (symtable1 [i].name, symtable2 [i].name) != 0)
+      goto done;
+
+  result = TRUE;
+
+done:
+  if (symtable1)
+    free (symtable1);
+  if (symtable2)
+    free (symtable2);
+  if (isymbuf1)
+    free (isymbuf1);
+  if (isymbuf2)
+    free (isymbuf2);
+
+  return result;
+}
This page took 0.106729 seconds and 4 git commands to generate.