]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - ld/emultempl/elf32.em
bfd/
[thirdparty/binutils-gdb.git] / ld / emultempl / elf32.em
index 2764a59d9685820cfe89668d33fd5ae9d3fc0725..4fea6a95b9156cea38caaf379725e10c5f5e5bbd 100644 (file)
@@ -8,39 +8,43 @@ if [ -z "$MACHINE" ]; then
 else
   OUTPUT_ARCH=${ARCH}:${MACHINE}
 fi
-cat >e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 /* This file is is generated by a shell script.  DO NOT EDIT! */
 
 /* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
    Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    Written by Steve Chamberlain <sac@cygnus.com>
    ELF support by Ian Lance Taylor <ian@cygnus.com>
 
-This file is part of GLD, the Gnu Linker.
+   This file is part of the GNU Binutils.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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
-Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 #define TARGET_IS_${EMULATION_NAME}
 
-#include "config.h"
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libiberty.h"
 #include "safe-ctype.h"
 #include "getopt.h"
+#include "md5.h"
+#include "sha1.h"
+#include <fcntl.h>
 
 #include "bfdlink.h"
 
@@ -53,22 +57,22 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 #include "ldemul.h"
 #include <ldgram.h>
 #include "elf/common.h"
+#include "elf-bfd.h"
+#include "filenames.h"
 
 /* Declare functions used by various EXTRA_EM_FILEs.  */
 static void gld${EMULATION_NAME}_before_parse (void);
 static void gld${EMULATION_NAME}_after_open (void);
 static void gld${EMULATION_NAME}_before_allocation (void);
-static bfd_boolean gld${EMULATION_NAME}_place_orphan
-  (lang_input_statement_type *file, asection *s);
-static void gld${EMULATION_NAME}_layout_sections_again (void);
-static void gld${EMULATION_NAME}_finish (void) ATTRIBUTE_UNUSED;
-
+static void gld${EMULATION_NAME}_after_allocation (void);
+static lang_output_section_statement_type *gld${EMULATION_NAME}_place_orphan
+  (asection *, const char *, int);
 EOF
 
 if [ "x${USE_LIBPATH}" = xyes ] ; then
   case ${target} in
     *-*-linux-* | *-*-k*bsd*-*)
-  cat >>e${EMULATION_NAME}.c <<EOF
+  fragment <<EOF
 #ifdef HAVE_GLOB
 #include <glob.h>
 #endif
@@ -79,8 +83,9 @@ fi
 
 # Import any needed special functions and/or overrides.
 #
+source_em ${srcdir}/emultempl/elf-generic.em
 if test -n "$EXTRA_EM_FILE" ; then
-. ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
+  source_em ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
 fi
 
 # Functions in this file can be overridden by setting the LDEMUL_* shell
@@ -90,7 +95,7 @@ fi
 # as presumably it is called from the overriding function.
 #
 if test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 
 static void
 gld${EMULATION_NAME}_before_parse (void)
@@ -104,31 +109,37 @@ EOF
 fi
 
 if test x"$LDEMUL_RECOGNIZED_FILE" != xgld"${EMULATION_NAME}"_load_symbols; then
-cat >>e${EMULATION_NAME}.c <<EOF
-/* Handle as_needed DT_NEEDED.  */
+fragment <<EOF
+/* Handle the generation of DT_NEEDED tags.  */
 
 static bfd_boolean
 gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *entry)
 {
-  int class = 0;
+  int link_class = 0;
 
   /* Tell the ELF linker that we don't want the output file to have a
      DT_NEEDED entry for this file, unless it is used to resolve
      references in a regular object.  */
-  if (entry->as_needed)
-    class = DYN_AS_NEEDED;
+  if (entry->add_DT_NEEDED_for_regular)
+    link_class = DYN_AS_NEEDED;
 
   /* Tell the ELF linker that we don't want the output file to have a
      DT_NEEDED entry for any dynamic library in DT_NEEDED tags from
      this file at all.  */
-  if (!entry->add_needed)
-    class |= DYN_NO_ADD_NEEDED;
+  if (!entry->add_DT_NEEDED_for_dynamic)
+    link_class |= DYN_NO_ADD_NEEDED;
 
-  if (!class
+  if (entry->just_syms_flag
+      && (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) != 0)
+    einfo (_("%P%F: --just-symbols may not be used on DSO: %B\n"),
+          entry->the_bfd);
+
+  if (link_class == 0
       || (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) == 0)
     return FALSE;
 
-  bfd_elf_set_dyn_lib_class (entry->the_bfd, class);
+  bfd_elf_set_dyn_lib_class (entry->the_bfd,
+                             (enum dynamic_lib_link_class) link_class);
 
   /* Continue on with normal load_symbols processing.  */
   return FALSE;
@@ -136,17 +147,21 @@ gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *entry)
 EOF
 fi
 
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 
 /* These variables are required to pass information back and forth
    between after_open and check_needed and stat_needed and vercheck.  */
 
 static struct bfd_link_needed_list *global_needed;
 static struct stat global_stat;
-static bfd_boolean global_found;
+static lang_input_statement_type *global_found;
 static struct bfd_link_needed_list *global_vercheck_needed;
 static bfd_boolean global_vercheck_failed;
 
+/* These variables are used to implement target options */
+
+static char *audit; /* colon (typically) separated list of libs */
+static char *depaudit; /* colon (typically) separated list of libs */
 
 /* On Linux, it's possible to have different versions of the same
    shared library linked against different versions of libc.  The
@@ -224,12 +239,14 @@ gld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s)
   const char *suffix;
   const char *soname;
 
-  if (global_found)
+  if (global_found != NULL)
     return;
   if (s->the_bfd == NULL)
     return;
-  if (s->as_needed
-      && (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0)
+
+  /* If this input file was an as-needed entry, and wasn't found to be
+     needed at the stage it was linked, then don't say we have loaded it.  */
+  if ((bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0)
     return;
 
   if (bfd_stat (s->the_bfd, &st) != 0)
@@ -249,7 +266,7 @@ gld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s)
       && st.st_ino == global_stat.st_ino
       && st.st_ino != 0)
     {
-      global_found = TRUE;
+      global_found = s;
       return;
     }
 
@@ -295,9 +312,9 @@ gld${EMULATION_NAME}_try_needed (struct dt_needed *needed,
   bfd *abfd;
   const char *name = needed->name;
   const char *soname;
-  int class;
+  int link_class;
 
-  abfd = bfd_openr (name, bfd_get_target (output_bfd));
+  abfd = bfd_openr (name, bfd_get_target (link_info.output_bfd));
   if (abfd == NULL)
     return FALSE;
   if (! bfd_check_format (abfd, bfd_object))
@@ -312,7 +329,7 @@ gld${EMULATION_NAME}_try_needed (struct dt_needed *needed,
     }
 
   /* For DT_NEEDED, they have to match.  */
-  if (abfd->xvec != output_bfd->xvec)
+  if (abfd->xvec != link_info.output_bfd->xvec)
     {
       bfd_close (abfd);
       return FALSE;
@@ -325,14 +342,14 @@ gld${EMULATION_NAME}_try_needed (struct dt_needed *needed,
 
   if (! force)
     {
-      struct bfd_link_needed_list *needed;
+      struct bfd_link_needed_list *needs;
 
-      if (! bfd_elf_get_bfd_needed_list (abfd, &needed))
+      if (! bfd_elf_get_bfd_needed_list (abfd, &needs))
        einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd);
 
-      if (needed != NULL)
+      if (needs != NULL)
        {
-         global_vercheck_needed = needed;
+         global_vercheck_needed = needs;
          global_vercheck_failed = FALSE;
          lang_for_each_input_file (gld${EMULATION_NAME}_vercheck);
          if (global_vercheck_failed)
@@ -353,12 +370,12 @@ gld${EMULATION_NAME}_try_needed (struct dt_needed *needed,
 EOF
 case ${target} in
   *-*-linux-* | *-*-k*bsd*-*)
-    cat >>e${EMULATION_NAME}.c <<EOF
+    fragment <<EOF
          {
            struct bfd_link_needed_list *l;
 
-           for (l = needed; l != NULL; l = l->next)
-             if (strncmp (l->name, "libc.so", 7) == 0)
+           for (l = needs; l != NULL; l = l->next)
+             if (CONST_STRNEQ (l->name, "libc.so"))
                break;
            if (l == NULL)
              {
@@ -370,7 +387,7 @@ case ${target} in
 EOF
     ;;
 esac
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
        }
     }
 
@@ -393,9 +410,9 @@ cat >>e${EMULATION_NAME}.c <<EOF
   if (trace_file_tries)
     info_msg (_("found %s at %s\n"), soname, name);
 
-  global_found = FALSE;
+  global_found = NULL;
   lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed);
-  if (global_found)
+  if (global_found != NULL)
     {
       /* Return TRUE to indicate that we found the file, even though
         we aren't going to do anything with it.  */
@@ -408,16 +425,16 @@ cat >>e${EMULATION_NAME}.c <<EOF
   /* Tell the ELF linker that we don't want the output file to have a
      DT_NEEDED entry for this file, unless it is used to resolve
      references in a regular object.  */
-  class = DYN_DT_NEEDED;
+  link_class = DYN_DT_NEEDED;
 
   /* Tell the ELF linker that we don't want the output file to have a
      DT_NEEDED entry for this file at all if the entry is from a file
      with DYN_NO_ADD_NEEDED.  */
   if (needed->by != NULL
       && (bfd_elf_get_dyn_lib_class (needed->by) & DYN_NO_ADD_NEEDED) != 0)
-    class |= DYN_NO_NEEDED | DYN_NO_ADD_NEEDED;
+    link_class |= DYN_NO_NEEDED | DYN_NO_ADD_NEEDED;
 
-  bfd_elf_set_dyn_lib_class (abfd, class);
+  bfd_elf_set_dyn_lib_class (abfd, (enum dynamic_lib_link_class) link_class);
 
   /* Add this file into the symbol table.  */
   if (! bfd_link_add_symbols (abfd, &link_info))
@@ -452,10 +469,21 @@ gld${EMULATION_NAME}_search_needed (const char *path,
     {
       char *filename, *sset;
 
-      s = strchr (path, ':');
+      s = strchr (path, config.rpath_separator);
       if (s == NULL)
        s = path + strlen (path);
 
+#if HAVE_DOS_BASED_FILE_SYSTEM
+      /* Assume a match on the second char is part of drive specifier.  */
+      else if (config.rpath_separator == ':'
+              && s == path + 1
+              && ISALPHA (*path))
+       {
+         s = strchr (s + 1, config.rpath_separator);
+         if (s == NULL)
+           s = path + strlen (path);
+       }
+#endif
       filename = (char *) xmalloc (s - path + len + 2);
       if (s == path)
        sset = filename;
@@ -483,9 +511,10 @@ gld${EMULATION_NAME}_search_needed (const char *path,
 
 EOF
 if [ "x${USE_LIBPATH}" = xyes ] ; then
-  cat >>e${EMULATION_NAME}.c <<EOF
+  fragment <<EOF
 
-/* Add the sysroot to every entry in a colon-separated path.  */
+/* Add the sysroot to every entry in a path separated by
+   config.rpath_separator.  */
 
 static char *
 gld${EMULATION_NAME}_add_sysroot (const char *path)
@@ -497,7 +526,7 @@ gld${EMULATION_NAME}_add_sysroot (const char *path)
   colons = 0;
   i = 0;
   while (path[i])
-    if (path[i++] == ':')
+    if (path[i++] == config.rpath_separator)
       colons++;
 
   if (path[i])
@@ -509,7 +538,7 @@ gld${EMULATION_NAME}_add_sysroot (const char *path)
   p = ret + strlen (ret);
   i = 0;
   while (path[i])
-    if (path[i] == ':')
+    if (path[i] == config.rpath_separator)
       {
        *p++ = path[i++];
        strcpy (p, ld_sysroot);
@@ -524,8 +553,70 @@ gld${EMULATION_NAME}_add_sysroot (const char *path)
 
 EOF
   case ${target} in
+    *-*-freebsd* | *-*-dragonfly*)
+      fragment <<EOF
+/* Read the system search path the FreeBSD way rather than the Linux way.  */
+#ifdef HAVE_ELF_HINTS_H
+#include <elf-hints.h>
+#else
+#include "elf-hints-local.h"
+#endif
+
+static bfd_boolean
+gld${EMULATION_NAME}_check_ld_elf_hints (const char *name, int force)
+{
+  static bfd_boolean initialized;
+  static char *ld_elf_hints;
+  struct dt_needed needed;
+
+  if (!initialized)
+    {
+      FILE *f;
+      char *tmppath;
+
+      tmppath = concat (ld_sysroot, _PATH_ELF_HINTS, (const char *) NULL);
+      f = fopen (tmppath, FOPEN_RB);
+      free (tmppath);
+      if (f != NULL)
+       {
+         struct elfhints_hdr hdr;
+
+         if (fread (&hdr, 1, sizeof (hdr), f) == sizeof (hdr)
+             && hdr.magic == ELFHINTS_MAGIC
+             && hdr.version == 1)
+           {
+             if (fseek (f, hdr.strtab + hdr.dirlist, SEEK_SET) != -1)
+               {
+                 char *b;
+
+                 b = xmalloc (hdr.dirlistlen + 1);
+                 if (fread (b, 1, hdr.dirlistlen + 1, f) ==
+                     hdr.dirlistlen + 1)
+                   ld_elf_hints = gld${EMULATION_NAME}_add_sysroot (b);
+
+                 free (b);
+               }
+           }
+         fclose (f);
+       }
+
+      initialized = TRUE;
+    }
+
+  if (ld_elf_hints == NULL)
+    return FALSE;
+
+  needed.by = NULL;
+  needed.name = name;
+  return gld${EMULATION_NAME}_search_needed (ld_elf_hints, & needed,
+                                            force);
+}
+EOF
+    # FreeBSD
+    ;;
+
     *-*-linux-* | *-*-k*bsd*-*)
-      cat >>e${EMULATION_NAME}.c <<EOF
+      fragment <<EOF
 /* For a native linker, check the file /etc/ld.so.conf for directories
    in which we may find shared libraries.  /etc/ld.so.conf is really
    only meaningful on Linux.  */
@@ -536,7 +627,7 @@ struct gld${EMULATION_NAME}_ld_so_conf
   size_t len, alloc;
 };
 
-static void
+static bfd_boolean
 gld${EMULATION_NAME}_parse_ld_so_conf
      (struct gld${EMULATION_NAME}_ld_so_conf *info, const char *filename);
 
@@ -579,7 +670,7 @@ gld${EMULATION_NAME}_parse_ld_so_conf_include
     free (newp);
 }
 
-static void
+static bfd_boolean
 gld${EMULATION_NAME}_parse_ld_so_conf
      (struct gld${EMULATION_NAME}_ld_so_conf *info, const char *filename)
 {
@@ -588,7 +679,7 @@ gld${EMULATION_NAME}_parse_ld_so_conf
   size_t linelen;
 
   if (f == NULL)
-    return;
+    return FALSE;
 
   linelen = 256;
   line = xmalloc (linelen);
@@ -629,7 +720,7 @@ gld${EMULATION_NAME}_parse_ld_so_conf
       if (p[0] == '\0')
        continue;
 
-      if (!strncmp (p, "include", 7) && (p[7] == ' ' || p[7] == '\t'))
+      if (CONST_STRNEQ (p, "include") && (p[7] == ' ' || p[7] == '\t'))
        {
          char *dir, c;
          p += 8;
@@ -676,7 +767,7 @@ gld${EMULATION_NAME}_parse_ld_so_conf
                  info->alloc += p - dir + 256;
                  info->path = xrealloc (info->path, info->alloc);
                }
-             info->path[info->len++] = ':';
+             info->path[info->len++] = config.rpath_separator;
            }
          memcpy (info->path + info->len, dir, p - dir);
          info->len += p - dir;
@@ -686,6 +777,7 @@ gld${EMULATION_NAME}_parse_ld_so_conf
   while (! feof (f));
   free (line);
   fclose (f);
+  return TRUE;
 }
 
 static bfd_boolean
@@ -700,11 +792,19 @@ gld${EMULATION_NAME}_check_ld_so_conf (const char *name, int force)
       char *tmppath;
       struct gld${EMULATION_NAME}_ld_so_conf info;
 
-      tmppath = concat (ld_sysroot, "/etc/ld.so.conf", NULL);
       info.path = NULL;
       info.len = info.alloc = 0;
-      gld${EMULATION_NAME}_parse_ld_so_conf (&info, tmppath);
+      tmppath = concat (ld_sysroot, "${prefix}/etc/ld.so.conf",
+                       (const char *) NULL);
+      if (!gld${EMULATION_NAME}_parse_ld_so_conf (&info, tmppath))
+       {
+         free (tmppath);
+         tmppath = concat (ld_sysroot, "/etc/ld.so.conf",
+                           (const char *) NULL);
+         gld${EMULATION_NAME}_parse_ld_so_conf (&info, tmppath);
+       }
       free (tmppath);
+
       if (info.path)
        {
          char *d = gld${EMULATION_NAME}_add_sysroot (info.path);
@@ -728,63 +828,224 @@ EOF
     ;;
   esac
 fi
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 
 /* See if an input file matches a DT_NEEDED entry by name.  */
 
 static void
 gld${EMULATION_NAME}_check_needed (lang_input_statement_type *s)
 {
-  if (global_found)
+  const char *soname;
+
+  /* Stop looking if we've found a loaded lib.  */
+  if (global_found != NULL
+      && (bfd_elf_get_dyn_lib_class (global_found->the_bfd)
+         & DYN_AS_NEEDED) == 0)
     return;
 
-  /* If this input file was an as-needed entry, and wasn't found to be
-     needed at the stage it was linked, then don't say we have loaded it.  */
-  if (s->as_needed
-      && (s->the_bfd == NULL
-         || (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0))
+  if (s->filename == NULL || s->the_bfd == NULL)
     return;
 
-  if (s->filename != NULL)
+  /* Don't look for a second non-loaded as-needed lib.  */
+  if (global_found != NULL
+      && (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0)
+    return;
+
+  if (strcmp (s->filename, global_needed->name) == 0)
     {
-      const char *f;
+      global_found = s;
+      return;
+    }
 
-      if (strcmp (s->filename, global_needed->name) == 0)
+  if (s->search_dirs_flag)
+    {
+      const char *f = strrchr (s->filename, '/');
+      if (f != NULL
+         && strcmp (f + 1, global_needed->name) == 0)
        {
-         global_found = TRUE;
+         global_found = s;
          return;
        }
+    }
+
+  soname = bfd_elf_get_dt_soname (s->the_bfd);
+  if (soname != NULL
+      && strcmp (soname, global_needed->name) == 0)
+    {
+      global_found = s;
+      return;
+    }
+}
+
+EOF
 
-      if (s->search_dirs_flag)
+if test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
+fragment <<EOF
+
+static bfd_size_type
+gld${EMULATION_NAME}_id_note_section_size (bfd *abfd,
+                                          struct bfd_link_info *linfo)
+{
+  const char *style = linfo->emit_note_gnu_build_id;
+  bfd_size_type size;
+
+  abfd = abfd;
+
+  size = offsetof (Elf_External_Note, name[sizeof "GNU"]);
+  size = (size + 3) & -(bfd_size_type) 4;
+
+  if (!strcmp (style, "md5") || !strcmp (style, "uuid"))
+    size += 128 / 8;
+  else if (!strcmp (style, "sha1"))
+    size += 160 / 8;
+  else if (!strncmp (style, "0x", 2))
+    {
+      /* ID is in string form (hex).  Convert to bits.  */
+      const char *id = style + 2;
+      do
        {
-         f = strrchr (s->filename, '/');
-         if (f != NULL
-             && strcmp (f + 1, global_needed->name) == 0)
+         if (ISXDIGIT (id[0]) && ISXDIGIT (id[1]))
            {
-             global_found = TRUE;
-             return;
+             ++size;
+             id += 2;
            }
-       }
+         else if (*id == '-' || *id == ':')
+           ++id;
+         else
+           {
+             size = 0;
+             break;
+           }
+       } while (*id != '\0');
     }
+  else
+    size = 0;
 
-  if (s->the_bfd != NULL)
+  return size;
+}
+
+static unsigned char
+read_hex (const char xdigit)
+{
+  if (ISDIGIT (xdigit))
+    return xdigit - '0';
+  if (ISUPPER (xdigit))
+    return xdigit - 'A' + 0xa;
+  if (ISLOWER (xdigit))
+    return xdigit - 'a' + 0xa;
+  abort ();
+  return 0;
+}
+
+struct build_id_info
+{
+  const char *style;
+  asection *sec;
+};
+
+static bfd_boolean
+gld${EMULATION_NAME}_write_build_id_section (bfd *abfd)
+{
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  struct build_id_info *info = (struct build_id_info *)
+    elf_tdata (abfd)->after_write_object_contents_info;
+  asection *asec;
+  Elf_Internal_Shdr *i_shdr;
+  unsigned char *contents, *id_bits;
+  bfd_size_type size;
+  Elf_External_Note *e_note;
+
+  asec = info->sec;
+  if (bfd_is_abs_section (asec->output_section))
     {
-      const char *soname;
+      einfo (_("%P: warning: .note.gnu.build-id section discarded,"
+              " --build-id ignored.\n"));
+      return TRUE;
+    }
+  i_shdr = &elf_section_data (asec->output_section)->this_hdr;
+
+  if (i_shdr->contents == NULL)
+    {
+      if (asec->contents == NULL)
+       asec->contents = (unsigned char *) xmalloc (asec->size);
+      contents = asec->contents;
+    }
+  else
+    contents = i_shdr->contents + asec->output_offset;
 
-      soname = bfd_elf_get_dt_soname (s->the_bfd);
-      if (soname != NULL
-         && strcmp (soname, global_needed->name) == 0)
+  e_note = (Elf_External_Note *) contents;
+  size = offsetof (Elf_External_Note, name[sizeof "GNU"]);
+  size = (size + 3) & -(bfd_size_type) 4;
+  id_bits = contents + size;
+  size = asec->size - size;
+
+  bfd_h_put_32 (abfd, sizeof "GNU", &e_note->namesz);
+  bfd_h_put_32 (abfd, size, &e_note->descsz);
+  bfd_h_put_32 (abfd, NT_GNU_BUILD_ID, &e_note->type);
+  memcpy (e_note->name, "GNU", sizeof "GNU");
+
+  if (!strcmp (info->style, "md5"))
+    {
+      struct md5_ctx ctx;
+      md5_init_ctx (&ctx);
+      if (bed->s->checksum_contents (abfd,
+                                    (void (*) (const void *, size_t, void *))
+                                    &md5_process_bytes,
+                                    &ctx))
+       md5_finish_ctx (&ctx, id_bits);
+      else
+       return FALSE;
+    }
+  else if (!strcmp (info->style, "sha1"))
+    {
+      struct sha1_ctx ctx;
+      sha1_init_ctx (&ctx);
+      if (bed->s->checksum_contents (abfd,
+                                    (void (*) (const void *, size_t, void *))
+                                    &sha1_process_bytes,
+                                    &ctx))
+       sha1_finish_ctx (&ctx, id_bits);
+      else
+       return FALSE;
+    }
+  else if (!strcmp (info->style, "uuid"))
+    {
+      int n;
+      int fd = open ("/dev/urandom", O_RDONLY);
+      if (fd < 0)
+       return FALSE;
+      n = read (fd, id_bits, size);
+      close (fd);
+      if (n < (int) size)
+       return FALSE;
+    }
+  else if (!strncmp (info->style, "0x", 2))
+    {
+      /* ID is in string form (hex).  Convert to bits.  */
+      const char *id = info->style + 2;
+      size_t n = 0;
+      do
        {
-         global_found = TRUE;
-         return;
-       }
+         if (ISXDIGIT (id[0]) && ISXDIGIT (id[1]))
+           {
+             id_bits[n] = read_hex (*id++) << 4;
+             id_bits[n++] |= read_hex (*id++);
+           }
+         else if (*id == '-' || *id == ':')
+           ++id;
+         else
+           abort ();           /* Should have been validated earlier.  */
+       } while (*id != '\0');
     }
-}
+  else
+    abort ();                  /* Should have been validated earlier.  */
 
-EOF
+  size = asec->size;
+  return (bfd_seek (abfd,
+                   i_shdr->sh_offset + asec->output_offset, SEEK_SET) == 0
+         && bfd_bwrite (contents, size, abfd) == size);
+}
 
-if test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
-cat >>e${EMULATION_NAME}.c <<EOF
 
 /* This is called after all the input files have been opened.  */
 
@@ -792,11 +1053,99 @@ static void
 gld${EMULATION_NAME}_after_open (void)
 {
   struct bfd_link_needed_list *needed, *l;
+  struct elf_link_hash_table *htab;
+
+  htab = elf_hash_table (&link_info);
+  if (!is_elf_hash_table (htab))
+    return;
+
+  if (link_info.emit_note_gnu_build_id)
+    {
+      bfd *abfd;
+      asection *s;
+      bfd_size_type size;
+
+      abfd = link_info.input_bfds;
+
+      if (abfd == NULL)
+       {
+         /* PR 10555: If there are no input files do not
+            try to create a .note.gnu-build-id section.  */
+         free (link_info.emit_note_gnu_build_id);
+         link_info.emit_note_gnu_build_id = NULL;
+       }
+      else
+       {
+         size = gld${EMULATION_NAME}_id_note_section_size (abfd, &link_info);
+         if (size == 0)
+           {
+             einfo ("%P: warning: unrecognized --build-id style ignored.\n");
+             free (link_info.emit_note_gnu_build_id);
+             link_info.emit_note_gnu_build_id = NULL;
+           }
+         else
+           {
+             s = bfd_make_section_with_flags (abfd, ".note.gnu.build-id",
+                                              SEC_ALLOC | SEC_LOAD
+                                              | SEC_IN_MEMORY | SEC_LINKER_CREATED
+                                              | SEC_READONLY | SEC_DATA);
+             if (s != NULL && bfd_set_section_alignment (abfd, s, 2))
+               {
+                 struct elf_obj_tdata *t = elf_tdata (link_info.output_bfd);
+                 struct build_id_info *b =
+                      (struct build_id_info *) xmalloc (sizeof *b);
+
+                 b->style = link_info.emit_note_gnu_build_id;
+                 b->sec = s;
+                 elf_section_type (s) = SHT_NOTE;
+                 s->size = size;
+                 t->after_write_object_contents
+                   = &gld${EMULATION_NAME}_write_build_id_section;
+                 t->after_write_object_contents_info = b;
+               }
+             else
+               {
+                 einfo ("%P: warning: Cannot create .note.gnu.build-id section,"
+                        " --build-id ignored.\n");
+                 free (link_info.emit_note_gnu_build_id);
+                 link_info.emit_note_gnu_build_id = NULL;
+               }
+           }
+       }
+    }
 
-  /* We only need to worry about this when doing a final link.  */
-  if (link_info.relocatable || !link_info.executable)
+  if (link_info.relocatable)
     return;
 
+  if (link_info.eh_frame_hdr
+      && !link_info.traditional_format)
+    {
+      bfd *abfd;
+      asection *s;
+
+      for (abfd = link_info.input_bfds; abfd; abfd = abfd->link_next)
+       {
+         s = bfd_get_section_by_name (abfd, ".eh_frame");
+         if (s && s->size > 8 && !bfd_is_abs_section (s->output_section))
+           break;
+       }
+      if (abfd)
+       {
+         const struct elf_backend_data *bed;
+
+         bed = get_elf_backend_data (abfd);
+         s = bfd_make_section_with_flags (abfd, ".eh_frame_hdr",
+                                          bed->dynamic_sec_flags
+                                          | SEC_READONLY);
+         if (s != NULL
+             && bfd_set_section_alignment (abfd, s, 2))
+           htab->eh_info.hdr_sec = s;
+         else
+           einfo ("%P: warning: Cannot create .eh_frame_hdr section,"
+                  " --eh-frame-hdr ignored.\n");
+       }
+    }
+
   /* Get the list of files which appear in DT_NEEDED entries in
      dynamic objects included in the link (often there will be none).
      For each such file, we want to track down the corresponding
@@ -806,7 +1155,9 @@ gld${EMULATION_NAME}_after_open (void)
      special action by the person doing the link.  Note that the
      needed list can actually grow while we are stepping through this
      loop.  */
-  needed = bfd_elf_get_needed_list (output_bfd, &link_info);
+  if (!link_info.executable)
+    return;
+  needed = bfd_elf_get_needed_list (link_info.output_bfd, &link_info);
   for (l = needed; l != NULL; l = l->next)
     {
       struct bfd_link_needed_list *ll;
@@ -830,9 +1181,11 @@ gld${EMULATION_NAME}_after_open (void)
 
       /* See if this file was included in the link explicitly.  */
       global_needed = l;
-      global_found = FALSE;
+      global_found = NULL;
       lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
-      if (global_found)
+      if (global_found != NULL
+         && (bfd_elf_get_dyn_lib_class (global_found->the_bfd)
+             & DYN_AS_NEEDED) == 0)
        continue;
 
       n.by = l->by;
@@ -841,6 +1194,15 @@ gld${EMULATION_NAME}_after_open (void)
       if (trace_file_tries)
        info_msg (_("%s needed by %B\n"), l->name, l->by);
 
+      /* As-needed libs specified on the command line (or linker script)
+        take priority over libs found in search dirs.  */
+      if (global_found != NULL)
+       {
+         nn.name = global_found->filename;
+         if (gld${EMULATION_NAME}_try_needed (&nn, TRUE))
+           continue;
+       }
+
       /* We need to find this file and include the symbol table.  We
         want to search for the file in the same way that the dynamic
         linker will search.  That means that we want to use
@@ -858,31 +1220,31 @@ gld${EMULATION_NAME}_after_open (void)
          search_dirs_type *search;
 EOF
 if [ "x${NATIVE}" = xyes ] ; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
          const char *lib_path;
 EOF
 fi
 if [ "x${USE_LIBPATH}" = xyes ] ; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
          struct bfd_link_needed_list *rp;
          int found;
 EOF
 fi
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 
          if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
                                                  &n, force))
            break;
 EOF
 if [ "x${USE_LIBPATH}" = xyes ] ; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
          if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
                                                  &n, force))
            break;
 EOF
 fi
 if [ "x${NATIVE}" = xyes ] ; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
          if (command_line.rpath_link == NULL
              && command_line.rpath == NULL)
            {
@@ -897,9 +1259,9 @@ cat >>e${EMULATION_NAME}.c <<EOF
 EOF
 fi
 if [ "x${USE_LIBPATH}" = xyes ] ; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
          found = 0;
-         rp = bfd_elf_get_runpath_list (output_bfd, &link_info);
+         rp = bfd_elf_get_runpath_list (link_info.output_bfd, &link_info);
          for (; !found && rp != NULL; rp = rp->next)
            {
              char *tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name);
@@ -914,7 +1276,27 @@ cat >>e${EMULATION_NAME}.c <<EOF
 
 EOF
 fi
-cat >>e${EMULATION_NAME}.c <<EOF
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+  case ${target} in
+    *-*-freebsd* | *-*-dragonfly*)
+      fragment <<EOF
+         if (gld${EMULATION_NAME}_check_ld_elf_hints (l->name, force))
+           break;
+EOF
+    # FreeBSD
+    ;;
+
+    *-*-linux-* | *-*-k*bsd*-*)
+    # Linux
+      fragment <<EOF
+         if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
+           break;
+
+EOF
+    ;;
+  esac
+fi
+fragment <<EOF
          len = strlen (l->name);
          for (search = search_head; search != NULL; search = search->next)
            {
@@ -932,18 +1314,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
          if (search != NULL)
            break;
 EOF
-if [ "x${USE_LIBPATH}" = xyes ] ; then
-  case ${target} in
-    *-*-linux-* | *-*-k*bsd*-*)
-      cat >>e${EMULATION_NAME}.c <<EOF
-         if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
-           break;
-EOF
-    # Linux
-    ;;
-  esac
-fi
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
        }
 
       if (force < 2)
@@ -957,7 +1328,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
 EOF
 fi
 
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 
 /* Look through an expression for an assignment statement.  */
 
@@ -981,8 +1352,10 @@ gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp)
         will do no harm.  */
       if (strcmp (exp->assign.dst, ".") != 0)
        {
-         if (!bfd_elf_record_link_assignment (&link_info, exp->assign.dst,
-                                              provide))
+         if (!bfd_elf_record_link_assignment (link_info.output_bfd,
+                                              &link_info,
+                                              exp->assign.dst, provide,
+                                              exp->assign.hidden))
            einfo ("%P%F: failed to record assignment to %s: %E\n",
                   exp->assign.dst);
        }
@@ -1037,7 +1410,47 @@ if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation;
   else
     ELF_INTERPRETER_SET_DEFAULT=
   fi
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
+
+/* used by before_allocation and handle_option. */
+static void 
+gld${EMULATION_NAME}_append_to_separated_string (char **to, char *op_arg)
+{
+  if (*to == NULL)
+    *to = xstrdup (op_arg);
+  else
+    {
+      size_t to_len = strlen (*to);
+      size_t op_arg_len = strlen (op_arg);
+      char *buf;
+      char *cp = *to;
+
+      /* First see whether OPTARG is already in the path.  */
+      do
+       {
+         if (strncmp (op_arg, cp, op_arg_len) == 0
+             && (cp[op_arg_len] == 0
+                 || cp[op_arg_len] == config.rpath_separator))
+           /* We found it.  */
+           break;
+
+         /* Not yet found.  */
+         cp = strchr (cp, config.rpath_separator);
+         if (cp != NULL)
+           ++cp;
+       }
+      while (cp != NULL);
+
+      if (cp == NULL)
+       {
+         buf = xmalloc (to_len + op_arg_len + 2);
+         sprintf (buf, "%s%c%s", *to,
+                  config.rpath_separator, op_arg);
+         free (*to);
+         *to = buf;
+       }
+    }
+}
 
 /* This is called after the sections have been attached to output
    sections, but before any sizes or addresses have been set.  */
@@ -1047,9 +1460,10 @@ gld${EMULATION_NAME}_before_allocation (void)
 {
   const char *rpath;
   asection *sinterp;
+  bfd *abfd;
 
   if (link_info.hash->type == bfd_link_elf_hash_table)
-    _bfd_elf_tls_setup (output_bfd, &link_info);
+    _bfd_elf_tls_setup (link_info.output_bfd, &link_info);
 
   /* If we are going to make any variable assignments, we need to let
      the ELF backend know about them in case the variables are
@@ -1061,9 +1475,39 @@ gld${EMULATION_NAME}_before_allocation (void)
   rpath = command_line.rpath;
   if (rpath == NULL)
     rpath = (const char *) getenv ("LD_RUN_PATH");
+
+  for (abfd = link_info.input_bfds; abfd; abfd = abfd->link_next)
+    {
+      const char *audit_libs = elf_dt_audit (abfd);
+
+      /* If the input bfd contains an audit entry, we need to add it as 
+         a dep audit entry.  */
+      if (audit_libs && *audit_libs != '\0')
+       {
+         char *cp = xstrdup (audit_libs);
+         do
+           {
+             int more = 0;
+             char *cp2 = strchr (cp, config.rpath_separator);
+
+             if (cp2)
+               {
+                 *cp2 = '\0';
+                 more = 1;
+               }
+             
+             if (cp != NULL && *cp != '\0')
+               gld${EMULATION_NAME}_append_to_separated_string (&depaudit, cp);
+
+             cp = more ? ++cp2 : NULL;
+           }
+         while (cp != NULL);
+       }
+    }
+
   if (! (bfd_elf_size_dynamic_sections
-        (output_bfd, command_line.soname, rpath,
-         command_line.filter_shlib,
+        (link_info.output_bfd, command_line.soname, rpath,
+         command_line.filter_shlib, audit, depaudit,
          (const char * const *) command_line.auxiliary_filters,
          &link_info, &sinterp, lang_elf_version_info)))
     einfo ("%P%F: failed to set dynamic section sizes: %E\n");
@@ -1087,10 +1531,8 @@ ${ELF_INTERPRETER_SET_DEFAULT}
       {
        asection *s;
        bfd_size_type sz;
-       bfd_size_type prefix_len;
        char *msg;
        bfd_boolean ret;
-       const char * gnu_warning_prefix = _("warning: ");
 
        if (is->just_syms_flag)
          continue;
@@ -1100,14 +1542,12 @@ ${ELF_INTERPRETER_SET_DEFAULT}
          continue;
 
        sz = s->size;
-       prefix_len = strlen (gnu_warning_prefix);
-       msg = xmalloc ((size_t) (prefix_len + sz + 1));
-       strcpy (msg, gnu_warning_prefix);
-       if (! bfd_get_section_contents (is->the_bfd, s, msg + prefix_len,
+       msg = (char *) xmalloc ((size_t) (sz + 1));
+       if (! bfd_get_section_contents (is->the_bfd, s, msg,
                                        (file_ptr) 0, sz))
          einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
                 is->the_bfd);
-       msg[prefix_len + sz] = '\0';
+       msg[sz] = '\0';
        ret = link_info.callbacks->warning (&link_info, msg,
                                            (const char *) NULL,
                                            is->the_bfd, (asection *) NULL,
@@ -1115,19 +1555,26 @@ ${ELF_INTERPRETER_SET_DEFAULT}
        ASSERT (ret);
        free (msg);
 
-       /* Clobber the section size, so that we don't waste copying the
-          warning into the output file.  */
+       /* Clobber the section size, so that we don't waste space
+          copying the warning into the output file.  If we've already
+          sized the output section, adjust its size.  The adjustment
+          is on rawsize because targets that size sections early will
+          have called lang_reset_memory_regions after sizing.  */
+       if (s->output_section != NULL
+           && s->output_section->rawsize >= s->size)
+         s->output_section->rawsize -= s->size;
+
        s->size = 0;
 
-       /* Also set SEC_EXCLUDE, so that symbols defined in the warning
-          section don't get copied to the output.  */
-       s->flags |= SEC_EXCLUDE;
+       /* Also set SEC_EXCLUDE, so that local symbols defined in the
+          warning section don't get copied to the output.  */
+       s->flags |= SEC_EXCLUDE | SEC_KEEP;
       }
   }
 
   before_allocation_default ();
 
-  if (!bfd_elf_size_dynsym_hash_dynstr (output_bfd, &link_info))
+  if (!bfd_elf_size_dynsym_hash_dynstr (link_info.output_bfd, &link_info))
     einfo ("%P%F: failed to set dynamic section sizes: %E\n");
 }
 
@@ -1135,7 +1582,7 @@ EOF
 fi
 
 if test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 
 /* Try to open a dynamic archive.  This is where we know that ELF
    dynamic libraries have an extension of .so (or .sl on oddball systems
@@ -1170,8 +1617,9 @@ gld${EMULATION_NAME}_open_dynamic_archive
   /* Try the .so extension first.  If that fails build a new filename
      using EXTRA_SHLIB_EXTENSION.  */
   if (! ldfile_try_open_bfd (string, entry))
-    sprintf (string, "%s/lib%s%s%s", search->name,
-            filename, arch, EXTRA_SHLIB_EXTENSION);
+    {
+      sprintf (string, "%s/lib%s%s%s", search->name,
+              filename, arch, EXTRA_SHLIB_EXTENSION);
 #endif
 
   if (! ldfile_try_open_bfd (string, entry))
@@ -1179,6 +1627,9 @@ gld${EMULATION_NAME}_open_dynamic_archive
       free (string);
       return FALSE;
     }
+#ifdef EXTRA_SHLIB_EXTENSION
+    }
+#endif
 
   entry->filename = string;
 
@@ -1214,7 +1665,7 @@ EOF
 fi
 
 if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 
 /* A variant of lang_output_section_find used by place_orphan.  */
 
@@ -1224,6 +1675,7 @@ output_rel_find (asection *sec, int isdyn)
   lang_output_section_statement_type *lookup;
   lang_output_section_statement_type *last = NULL;
   lang_output_section_statement_type *last_alloc = NULL;
+  lang_output_section_statement_type *last_ro_alloc = NULL;
   lang_output_section_statement_type *last_rel = NULL;
   lang_output_section_statement_type *last_rel_alloc = NULL;
   int rela = sec->name[4] == 'a';
@@ -1232,8 +1684,8 @@ output_rel_find (asection *sec, int isdyn)
        lookup != NULL;
        lookup = lookup->next)
     {
-      if (lookup->constraint != -1
-         && strncmp (".rel", lookup->name, 4) == 0)
+      if (lookup->constraint >= 0
+         && CONST_STRNEQ (lookup->name, ".rel"))
        {
          int lookrela = lookup->name[4] == 'a';
 
@@ -1258,7 +1710,11 @@ output_rel_find (asection *sec, int isdyn)
       last = lookup;
       if (lookup->bfd_section != NULL
          && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
-       last_alloc = lookup;
+       {
+         last_alloc = lookup;
+         if ((lookup->bfd_section->flags & SEC_READONLY) != 0)
+           last_ro_alloc = lookup;
+       }
     }
 
   if (last_rel_alloc)
@@ -1267,6 +1723,9 @@ output_rel_find (asection *sec, int isdyn)
   if (last_rel)
     return last_rel;
 
+  if (last_ro_alloc)
+    return last_ro_alloc;
+
   if (last_alloc)
     return last_alloc;
 
@@ -1276,8 +1735,10 @@ output_rel_find (asection *sec, int isdyn)
 /* Place an orphan section.  We use this to put random SHF_ALLOC
    sections in the right segment.  */
 
-static bfd_boolean
-gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
+static lang_output_section_statement_type *
+gld${EMULATION_NAME}_place_orphan (asection *s,
+                                  const char *secname,
+                                  int constraint)
 {
   static struct orphan_save hold[] =
     {
@@ -1301,7 +1762,10 @@ gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
        0, 0, 0, 0 },
       { ".sdata",
        SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_SMALL_DATA,
-       0, 0, 0, 0 }
+       0, 0, 0, 0 },
+      { 0,
+       SEC_HAS_CONTENTS,
+       0, 0, 0, 0 },
     };
   enum orphan_save_index
     {
@@ -1311,53 +1775,89 @@ gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
       orphan_bss,
       orphan_rel,
       orphan_interp,
-      orphan_sdata
+      orphan_sdata,
+      orphan_nonalloc
     };
   static int orphan_init_done = 0;
   struct orphan_save *place;
-  const char *secname;
   lang_output_section_statement_type *after;
   lang_output_section_statement_type *os;
+  lang_output_section_statement_type *match_by_name = NULL;
   int isdyn = 0;
-
-  secname = bfd_get_section_name (s->owner, s);
+  int iself = s->owner->xvec->flavour == bfd_target_elf_flavour;
+  unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL;
 
   if (! link_info.relocatable
       && link_info.combreloc
-      && (s->flags & SEC_ALLOC)
-      && strncmp (secname, ".rel", 4) == 0)
+      && (s->flags & SEC_ALLOC))
     {
-      if (secname[4] == 'a')
-       secname = ".rela.dyn";
-      else
-       secname = ".rel.dyn";
-      isdyn = 1;
+      if (iself)
+       switch (sh_type)
+         {
+         case SHT_RELA:
+           secname = ".rela.dyn";
+           isdyn = 1;
+           break;
+         case SHT_REL:
+           secname = ".rel.dyn";
+           isdyn = 1;
+           break;
+         default:
+           break;
+         }
+      else if (CONST_STRNEQ (secname, ".rel"))
+       {
+         secname = secname[4] == 'a' ? ".rela.dyn" : ".rel.dyn";
+         isdyn = 1;
+       }
     }
 
-  if (isdyn || (!config.unique_orphan_sections && !unique_section_p (s)))
+  /* Look through the script to see where to place this section.  */
+  if (constraint == 0)
+    for (os = lang_output_section_find (secname);
+        os != NULL;
+        os = next_matching_output_section_statement (os, 0))
+      {
+       /* If we don't match an existing output section, tell
+          lang_insert_orphan to create a new output section.  */
+       constraint = SPECIAL;
+
+       if (os->bfd_section != NULL
+           && (os->bfd_section->flags == 0
+               || (_bfd_elf_match_sections_by_type (link_info.output_bfd,
+                                                    os->bfd_section,
+                                                    s->owner, s)
+                   && ((s->flags ^ os->bfd_section->flags)
+                       & (SEC_LOAD | SEC_ALLOC)) == 0)))
+         {
+           /* We already have an output section statement with this
+              name, and its bfd section has compatible flags.
+              If the section already exists but does not have any flags
+              set, then it has been created by the linker, probably as a
+              result of a --section-start command line switch.  */
+           lang_add_section (&os->children, s, os);
+           return os;
+         }
+
+       /* Save unused output sections in case we can match them
+          against orphans later.  */
+       if (os->bfd_section == NULL)
+         match_by_name = os;
+      }
+
+  /* If we didn't match an active output section, see if we matched an
+     unused one and use that.  */
+  if (match_by_name)
     {
-      /* Look through the script to see where to place this section.  */
-      os = lang_output_section_find (secname);
-
-      if (os != NULL
-         && (os->bfd_section == NULL
-             || os->bfd_section->flags == 0
-             || ((s->flags ^ os->bfd_section->flags)
-                 & (SEC_LOAD | SEC_ALLOC)) == 0))
-       {
-         /* We already have an output section statement with this
-            name, and its bfd section, if any, has compatible flags.
-            If the section already exists but does not have any flags
-            set, then it has been created by the linker, probably as a
-            result of a --section-start command line switch.  */
-         lang_add_section (&os->children, s, os, file);
-         return TRUE;
-       }
+      lang_add_section (&match_by_name->children, s, match_by_name);
+      return match_by_name;
     }
 
   if (!orphan_init_done)
     {
+      lang_output_section_statement_type *lookup;
       struct orphan_save *ho;
+
       for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
        if (ho->name != NULL)
          {
@@ -1365,6 +1865,16 @@ gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
            if (ho->os != NULL && ho->os->flags == 0)
              ho->os->flags = ho->flags;
          }
+      lookup = hold[orphan_bss].os;
+      if (lookup == NULL)
+       lookup = &lang_output_section_statement.head->output_section_statement;
+      for (; lookup != NULL; lookup = lookup->next)
+       if ((lookup->bfd_section != NULL
+            && (lookup->bfd_section->flags & SEC_DEBUGGING) != 0)
+           || strcmp (lookup->name, ".comment") == 0)
+         break;
+      hold[orphan_nonalloc].os = lookup ? lookup->prev : NULL;
+      hold[orphan_nonalloc].name = ".comment";
       orphan_init_done = 1;
     }
 
@@ -1372,12 +1882,12 @@ gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
      sections into the .text section to get them out of the way.  */
   if (link_info.executable
       && ! link_info.relocatable
-      && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
+      && CONST_STRNEQ (s->name, ".gnu.warning.")
       && hold[orphan_text].os != NULL)
     {
-      lang_add_section (&hold[orphan_text].os->children, s,
-                       hold[orphan_text].os, file);
-      return TRUE;
+      os = hold[orphan_text].os;
+      lang_add_section (&os->children, s, os);
+      return os;
     }
 
   /* Decide which segment the section should go in based on the
@@ -1387,10 +1897,13 @@ gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
      in the first page.  */
 
   place = NULL;
-  if ((s->flags & SEC_ALLOC) == 0)
+  if ((s->flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0)
+    place = &hold[orphan_nonalloc];
+  else if ((s->flags & SEC_ALLOC) == 0)
     ;
   else if ((s->flags & SEC_LOAD) != 0
-          && strncmp (secname, ".note", 5) == 0)
+          && ((iself && sh_type == SHT_NOTE)
+              || (!iself && CONST_STRNEQ (secname, ".note"))))
     place = &hold[orphan_interp];
   else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
     place = &hold[orphan_bss];
@@ -1398,7 +1911,8 @@ gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
     place = &hold[orphan_sdata];
   else if ((s->flags & SEC_READONLY) == 0)
     place = &hold[orphan_data];
-  else if (strncmp (secname, ".rel", 4) == 0
+  else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL))
+           || (!iself && CONST_STRNEQ (secname, ".rel")))
           && (s->flags & SEC_LOAD) != 0)
     place = &hold[orphan_rel];
   else if ((s->flags & SEC_CODE) == 0)
@@ -1418,61 +1932,33 @@ gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
        }
       after = place->os;
       if (after == NULL)
-       after = lang_output_section_find_by_flags (s, &place->os);
+       after = lang_output_section_find_by_flags
+         (s, &place->os, _bfd_elf_match_sections_by_type);
       if (after == NULL)
        /* *ABS* is always the first output section statement.  */
        after = &lang_output_section_statement.head->output_section_statement;
     }
 
-  /* Choose a unique name for the section.  This will be needed if the
-     same section name appears in the input file with different
-     loadable or allocatable characteristics.  */
-  if (bfd_get_section_by_name (output_bfd, secname) != NULL)
-    {
-      static int count = 1;
-      secname = bfd_get_unique_section_name (output_bfd, secname, &count);
-      if (secname == NULL)
-       einfo ("%F%P: place_orphan failed: %E\n");
-    }
-
-  lang_insert_orphan (file, s, secname, after, place, NULL, NULL);
-
-  return TRUE;
+  return lang_insert_orphan (s, secname, constraint, after, place, NULL, NULL);
 }
 EOF
 fi
 
-if test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then
-cat >>e${EMULATION_NAME}.c <<EOF
+if test x"$LDEMUL_AFTER_ALLOCATION" != xgld"$EMULATION_NAME"_after_allocation; then
+fragment <<EOF
 
 static void
-gld${EMULATION_NAME}_layout_sections_again (void)
+gld${EMULATION_NAME}_after_allocation (void)
 {
-  lang_reset_memory_regions ();
-
-  /* Resize the sections.  */
-  lang_size_sections (NULL, TRUE);
-
-  /* Redo special stuff.  */
-  ldemul_after_allocation ();
-
-  /* Do the assignments again.  */
-  lang_do_assignments ();
-}
-
-static void
-gld${EMULATION_NAME}_finish (void)
-{
-  if (bfd_elf_discard_info (output_bfd, &link_info))
-    gld${EMULATION_NAME}_layout_sections_again ();
-
-  finish_default ();
+  bfd_boolean need_layout = bfd_elf_discard_info (link_info.output_bfd,
+                                                 &link_info);
+  gld${EMULATION_NAME}_map_segments (need_layout);
 }
 EOF
 fi
 
 if test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 
 static char *
 gld${EMULATION_NAME}_get_script (int *isfile)
@@ -1485,7 +1971,7 @@ then
 # sed commands to quote an ld script as a C string.
 sc="-f stringify.sed"
 
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 {
   *isfile = 0;
 
@@ -1505,7 +1991,7 @@ if test -n "$GENERATE_PIE_SCRIPT" ; then
 if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
 echo '  ; else if (link_info.pie && link_info.combreloc' >> e${EMULATION_NAME}.c
 echo '             && link_info.relro' >> e${EMULATION_NAME}.c
-echo '             && (link_info.flags & DT_BIND_NOW)) return' >> e${EMULATION_NAME}.c
+echo '             && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xdw                        >> e${EMULATION_NAME}.c
 echo '  ; else if (link_info.pie && link_info.combreloc) return' >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xdc                        >> e${EMULATION_NAME}.c
@@ -1517,7 +2003,7 @@ if test -n "$GENERATE_SHLIB_SCRIPT" ; then
 if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
 echo '  ; else if (link_info.shared && link_info.combreloc' >> e${EMULATION_NAME}.c
 echo '             && link_info.relro' >> e${EMULATION_NAME}.c
-echo '             && (link_info.flags & DT_BIND_NOW)) return' >> e${EMULATION_NAME}.c
+echo '             && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xsw                        >> e${EMULATION_NAME}.c
 echo '  ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xsc                        >> e${EMULATION_NAME}.c
@@ -1527,7 +2013,7 @@ sed $sc ldscripts/${EMULATION_NAME}.xs                    >> e${EMULATION_NAME}.c
 fi
 if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
 echo '  ; else if (link_info.combreloc && link_info.relro' >> e${EMULATION_NAME}.c
-echo '             && (link_info.flags & DT_BIND_NOW)) return' >> e${EMULATION_NAME}.c
+echo '             && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xw                 >> e${EMULATION_NAME}.c
 echo '  ; else if (link_info.combreloc) return'                >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xc                 >> e${EMULATION_NAME}.c
@@ -1539,7 +2025,7 @@ echo '; }'                                                >> e${EMULATION_NAME}.c
 else
 # Scripts read from the filesystem.
 
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 {
   *isfile = 1;
 
@@ -1552,51 +2038,51 @@ cat >>e${EMULATION_NAME}.c <<EOF
 EOF
 if cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then :
 else
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
   else if (!config.magic_demand_paged)
     return "ldscripts/${EMULATION_NAME}.xn";
 EOF
 fi
 if test -n "$GENERATE_PIE_SCRIPT" ; then
 if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
   else if (link_info.pie && link_info.combreloc
-          && link_info.relro && (link_info.flags & DT_BIND_NOW))
+          && link_info.relro && (link_info.flags & DF_BIND_NOW))
     return "ldscripts/${EMULATION_NAME}.xdw";
   else if (link_info.pie && link_info.combreloc)
     return "ldscripts/${EMULATION_NAME}.xdc";
 EOF
 fi
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
   else if (link_info.pie)
     return "ldscripts/${EMULATION_NAME}.xd";
 EOF
 fi
 if test -n "$GENERATE_SHLIB_SCRIPT" ; then
 if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
   else if (link_info.shared && link_info.combreloc
-          && link_info.relro && (link_info.flags & DT_BIND_NOW))
+          && link_info.relro && (link_info.flags & DF_BIND_NOW))
     return "ldscripts/${EMULATION_NAME}.xsw";
   else if (link_info.shared && link_info.combreloc)
     return "ldscripts/${EMULATION_NAME}.xsc";
 EOF
 fi
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
   else if (link_info.shared)
     return "ldscripts/${EMULATION_NAME}.xs";
 EOF
 fi
 if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
   else if (link_info.combreloc && link_info.relro
-          && (link_info.flags & DT_BIND_NOW))
+          && (link_info.flags & DF_BIND_NOW))
     return "ldscripts/${EMULATION_NAME}.xw";
   else if (link_info.combreloc)
     return "ldscripts/${EMULATION_NAME}.xc";
 EOF
 fi
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
   else
     return "ldscripts/${EMULATION_NAME}.x";
 }
@@ -1608,45 +2094,52 @@ fi
 if test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then
 
 if test -n "$PARSE_AND_LIST_PROLOGUE" ; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
  $PARSE_AND_LIST_PROLOGUE
 EOF
 fi
 
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 
 #define OPTION_DISABLE_NEW_DTAGS       (400)
 #define OPTION_ENABLE_NEW_DTAGS                (OPTION_DISABLE_NEW_DTAGS + 1)
 #define OPTION_GROUP                   (OPTION_ENABLE_NEW_DTAGS + 1)
 #define OPTION_EH_FRAME_HDR            (OPTION_GROUP + 1)
 #define OPTION_EXCLUDE_LIBS            (OPTION_EH_FRAME_HDR + 1)
-  
+#define OPTION_HASH_STYLE              (OPTION_EXCLUDE_LIBS + 1)
+#define OPTION_BUILD_ID                        (OPTION_HASH_STYLE + 1)
+#define OPTION_AUDIT                   (OPTION_BUILD_ID + 1)
+
 static void
 gld${EMULATION_NAME}_add_options
   (int ns, char **shortopts, int nl, struct option **longopts,
    int nrl ATTRIBUTE_UNUSED, struct option **really_longopts ATTRIBUTE_UNUSED)
 {
-  static const char xtra_short[] = "${PARSE_AND_LIST_SHORTOPTS}z:";
+  static const char xtra_short[] = "${PARSE_AND_LIST_SHORTOPTS}z:P:";
   static const struct option xtra_long[] = {
+    {"build-id", optional_argument, NULL, OPTION_BUILD_ID},
+    {"audit", required_argument, NULL, OPTION_AUDIT},
+    {"depaudit", required_argument, NULL, 'P'},
 EOF
 
 if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
     {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
     {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
     {"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR},
     {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
+    {"hash-style", required_argument, NULL, OPTION_HASH_STYLE},
     {"Bgroup", no_argument, NULL, OPTION_GROUP},
 EOF
 fi
 
 if test -n "$PARSE_AND_LIST_LONGOPTS" ; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
     $PARSE_AND_LIST_LONGOPTS
 EOF
 fi
 
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
     {NULL, no_argument, NULL, 0}
   };
 
@@ -1657,6 +2150,8 @@ cat >>e${EMULATION_NAME}.c <<EOF
   memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
 }
 
+#define DEFAULT_BUILD_ID_STYLE "sha1"
+
 static bfd_boolean
 gld${EMULATION_NAME}_handle_option (int optc)
 {
@@ -1665,10 +2160,28 @@ gld${EMULATION_NAME}_handle_option (int optc)
     default:
       return FALSE;
 
+    case OPTION_BUILD_ID:
+      if (link_info.emit_note_gnu_build_id != NULL)
+       {
+         free (link_info.emit_note_gnu_build_id);
+         link_info.emit_note_gnu_build_id = NULL;
+       }
+      if (optarg == NULL)
+       optarg = DEFAULT_BUILD_ID_STYLE;
+      if (strcmp (optarg, "none"))
+       link_info.emit_note_gnu_build_id = xstrdup (optarg);
+      break;
+    case OPTION_AUDIT:
+       gld${EMULATION_NAME}_append_to_separated_string (&audit, optarg); 
+       break;
+    case 'P':
+       gld${EMULATION_NAME}_append_to_separated_string (&depaudit, optarg);
+       break;
+
 EOF
 
 if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
     case OPTION_DISABLE_NEW_DTAGS:
       link_info.new_dtags = FALSE;
       break;
@@ -1692,6 +2205,22 @@ cat >>e${EMULATION_NAME}.c <<EOF
       add_excluded_libs (optarg);
       break;
 
+    case OPTION_HASH_STYLE:
+      link_info.emit_hash = FALSE;
+      link_info.emit_gnu_hash = FALSE;
+      if (strcmp (optarg, "sysv") == 0)
+       link_info.emit_hash = TRUE;
+      else if (strcmp (optarg, "gnu") == 0)
+       link_info.emit_gnu_hash = TRUE;
+      else if (strcmp (optarg, "both") == 0)
+       {
+         link_info.emit_hash = TRUE;
+         link_info.emit_gnu_hash = TRUE;
+       }
+      else
+       einfo (_("%P%F: invalid hash style \`%s'\n"), optarg);
+      break;
+
     case 'z':
       if (strcmp (optarg, "initfirst") == 0)
        link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
@@ -1712,6 +2241,11 @@ cat >>e${EMULATION_NAME}.c <<EOF
          link_info.flags |= (bfd_vma) DF_BIND_NOW;
          link_info.flags_1 |= (bfd_vma) DF_1_NOW;
        }
+      else if (strcmp (optarg, "lazy") == 0)
+       {
+         link_info.flags &= ~(bfd_vma) DF_BIND_NOW;
+         link_info.flags_1 &= ~(bfd_vma) DF_1_NOW;
+       }
       else if (strcmp (optarg, "origin") == 0)
        {
          link_info.flags |= (bfd_vma) DF_ORIGIN;
@@ -1737,22 +2271,48 @@ cat >>e${EMULATION_NAME}.c <<EOF
          link_info.noexecstack = TRUE;
          link_info.execstack = FALSE;
        }
+EOF
+
+  if test -n "$COMMONPAGESIZE"; then
+fragment <<EOF
       else if (strcmp (optarg, "relro") == 0)
        link_info.relro = TRUE;
       else if (strcmp (optarg, "norelro") == 0)
        link_info.relro = FALSE;
+EOF
+  fi
+
+fragment <<EOF
+      else if (CONST_STRNEQ (optarg, "max-page-size="))
+       {
+         char *end;
+
+         config.maxpagesize = strtoul (optarg + 14, &end, 0);
+         if (*end || (config.maxpagesize & (config.maxpagesize - 1)) != 0)
+           einfo (_("%P%F: invalid maxium page size \`%s'\n"),
+                  optarg + 14);
+       }
+      else if (CONST_STRNEQ (optarg, "common-page-size="))
+       {
+         char *end;
+         config.commonpagesize = strtoul (optarg + 17, &end, 0);
+         if (*end
+             || (config.commonpagesize & (config.commonpagesize - 1)) != 0)
+           einfo (_("%P%F: invalid common page size \`%s'\n"),
+                  optarg + 17);
+       }
       /* What about the other Solaris -z options? FIXME.  */
       break;
 EOF
 fi
 
 if test -n "$PARSE_AND_LIST_ARGS_CASES" ; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
  $PARSE_AND_LIST_ARGS_CASES
 EOF
 fi
 
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
     }
 
   return TRUE;
@@ -1761,70 +2321,125 @@ cat >>e${EMULATION_NAME}.c <<EOF
 EOF
 
 if test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 
 static void
 gld${EMULATION_NAME}_list_options (FILE * file)
 {
+  fprintf (file, _("\
+  --build-id[=STYLE]          Generate build ID note\n"));
+  fprintf (file, _("\
+  --audit=AUDITLIB            Specify a library to use for auditing\n"));
+  fprintf (file, _("\
+  -P AUDITLIB, --depaudit=AUDITLIB\n" "\
+                              Specify a library to use for auditing dependencies\n"));
 EOF
 
 if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
-cat >>e${EMULATION_NAME}.c <<EOF
-  fprintf (file, _("  -Bgroup\t\tSelects group name lookup rules for DSO\n"));
-  fprintf (file, _("  --disable-new-dtags\tDisable new dynamic tags\n"));
-  fprintf (file, _("  --enable-new-dtags\tEnable new dynamic tags\n"));
-  fprintf (file, _("  --eh-frame-hdr\tCreate .eh_frame_hdr section\n"));
-  fprintf (file, _("  -z combreloc\t\tMerge dynamic relocs into one section and sort\n"));
-  fprintf (file, _("  -z defs\t\tReport unresolved symbols in object files.\n"));
-  fprintf (file, _("  -z execstack\t\tMark executable as requiring executable stack\n"));
-  fprintf (file, _("  -z initfirst\t\tMark DSO to be initialized first at runtime\n"));
-  fprintf (file, _("  -z interpose\t\tMark object to interpose all DSOs but executable\n"));
-  fprintf (file, _("  -z loadfltr\t\tMark object requiring immediate process\n"));
-  fprintf (file, _("  -z muldefs\t\tAllow multiple definitions\n"));
-  fprintf (file, _("  -z nocombreloc\tDon't merge dynamic relocs into one section\n"));
-  fprintf (file, _("  -z nocopyreloc\tDon't create copy relocs\n"));
-  fprintf (file, _("  -z nodefaultlib\tMark object not to use default search paths\n"));
-  fprintf (file, _("  -z nodelete\t\tMark DSO non-deletable at runtime\n"));
-  fprintf (file, _("  -z nodlopen\t\tMark DSO not available to dlopen\n"));
-  fprintf (file, _("  -z nodump\t\tMark DSO not available to dldump\n"));
-  fprintf (file, _("  -z noexecstack\tMark executable as not requiring executable stack\n"));
-  fprintf (file, _("  -z norelro\t\tDon't create RELRO program header\n"));
-  fprintf (file, _("  -z now\t\tMark object non-lazy runtime binding\n"));
-  fprintf (file, _("  -z origin\t\tMark object requiring immediate \$ORIGIN processing\n\t\t\t  at runtime\n"));
-  fprintf (file, _("  -z relro\t\tCreate RELRO program header\n"));
-  fprintf (file, _("  -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
+fragment <<EOF
+  fprintf (file, _("\
+  -Bgroup                     Selects group name lookup rules for DSO\n"));
+  fprintf (file, _("\
+  --disable-new-dtags         Disable new dynamic tags\n"));
+  fprintf (file, _("\
+  --enable-new-dtags          Enable new dynamic tags\n"));
+  fprintf (file, _("\
+  --eh-frame-hdr              Create .eh_frame_hdr section\n"));
+  fprintf (file, _("\
+  --hash-style=STYLE          Set hash style to sysv, gnu or both\n"));
+  fprintf (file, _("\
+  -z combreloc                Merge dynamic relocs into one section and sort\n"));
+  fprintf (file, _("\
+  -z defs                     Report unresolved symbols in object files.\n"));
+  fprintf (file, _("\
+  -z execstack                Mark executable as requiring executable stack\n"));
+  fprintf (file, _("\
+  -z initfirst                Mark DSO to be initialized first at runtime\n"));
+  fprintf (file, _("\
+  -z interpose                Mark object to interpose all DSOs but executable\n"));
+  fprintf (file, _("\
+  -z lazy                     Mark object lazy runtime binding (default)\n"));
+  fprintf (file, _("\
+  -z loadfltr                 Mark object requiring immediate process\n"));
+  fprintf (file, _("\
+  -z muldefs                  Allow multiple definitions\n"));
+  fprintf (file, _("\
+  -z nocombreloc              Don't merge dynamic relocs into one section\n"));
+  fprintf (file, _("\
+  -z nocopyreloc              Don't create copy relocs\n"));
+  fprintf (file, _("\
+  -z nodefaultlib             Mark object not to use default search paths\n"));
+  fprintf (file, _("\
+  -z nodelete                 Mark DSO non-deletable at runtime\n"));
+  fprintf (file, _("\
+  -z nodlopen                 Mark DSO not available to dlopen\n"));
+  fprintf (file, _("\
+  -z nodump                   Mark DSO not available to dldump\n"));
+  fprintf (file, _("\
+  -z noexecstack              Mark executable as not requiring executable stack\n"));
+EOF
+
+  if test -n "$COMMONPAGESIZE"; then
+fragment <<EOF
+  fprintf (file, _("\
+  -z norelro                  Don't create RELRO program header\n"));
+EOF
+  fi
+
+fragment <<EOF
+  fprintf (file, _("\
+  -z now                      Mark object non-lazy runtime binding\n"));
+  fprintf (file, _("\
+  -z origin                   Mark object requiring immediate \$ORIGIN\n\
+                                processing at runtime\n"));
+EOF
+
+  if test -n "$COMMONPAGESIZE"; then
+fragment <<EOF
+  fprintf (file, _("\
+  -z relro                    Create RELRO program header\n"));
+EOF
+  fi
+
+fragment <<EOF
+  fprintf (file, _("\
+  -z max-page-size=SIZE       Set maximum page size to SIZE\n"));
+  fprintf (file, _("\
+  -z common-page-size=SIZE    Set common page size to SIZE\n"));
+  fprintf (file, _("\
+  -z KEYWORD                  Ignored for Solaris compatibility\n"));
 EOF
 fi
 
 if test -n "$PARSE_AND_LIST_OPTIONS" ; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
  $PARSE_AND_LIST_OPTIONS
 EOF
 fi
 
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 }
 EOF
 
 if test -n "$PARSE_AND_LIST_EPILOGUE" ; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
  $PARSE_AND_LIST_EPILOGUE
 EOF
 fi
 fi
 else
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 #define gld${EMULATION_NAME}_add_options NULL
 #define gld${EMULATION_NAME}_handle_option NULL
 EOF
 if test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 #define gld${EMULATION_NAME}_list_options NULL
 EOF
 fi
 fi
 
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 
 struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
 {
@@ -1833,14 +2448,14 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   ${LDEMUL_HLL-hll_default},
   ${LDEMUL_AFTER_PARSE-after_parse_default},
   ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},
-  ${LDEMUL_AFTER_ALLOCATION-after_allocation_default},
+  ${LDEMUL_AFTER_ALLOCATION-gld${EMULATION_NAME}_after_allocation},
   ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
   ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
   ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation},
   ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
   "${EMULATION_NAME}",
   "${OUTPUT_FORMAT}",
-  ${LDEMUL_FINISH-gld${EMULATION_NAME}_finish},
+  ${LDEMUL_FINISH-finish_default},
   ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
   ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
   ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},