bfd/
[deliverable/binutils-gdb.git] / ld / emultempl / elf32.em
index 33004be1b53a63c04678be1e2772dd657ed77394..89c5d5d0e55a83abfb8d309f3e5d9f0869ab12c7 100644 (file)
@@ -3,12 +3,17 @@
 # This file is now misnamed, because it supports both 32 bit and 64 bit
 # ELF emulations.
 test -z "${ELFSIZE}" && ELFSIZE=32
+if [ -z "$MACHINE" ]; then
+  OUTPUT_ARCH=${ARCH}
+else
+  OUTPUT_ARCH=${ARCH}:${MACHINE}
+fi
 cat >e${EMULATION_NAME}.c <<EOF
 /* This file is is generated by a shell script.  DO NOT EDIT! */
 
 /* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
-   Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 99, 2000
-   Free Software Foundation, Inc.
+   Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+   2002, 2003, 2004 Free Software Foundation, Inc.
    Written by Steve Chamberlain <sac@cygnus.com>
    ELF support by Ian Lance Taylor <ian@cygnus.com>
 
@@ -32,8 +37,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
-
-#include <ctype.h>
+#include "libiberty.h"
+#include "safe-ctype.h"
+#include "getopt.h"
 
 #include "bfdlink.h"
 
@@ -44,30 +50,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "ldlang.h"
 #include "ldfile.h"
 #include "ldemul.h"
-#include "ldgram.h"
+#include <ldgram.h>
 #include "elf/common.h"
 
-static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
-static void gld${EMULATION_NAME}_vercheck
-  PARAMS ((lang_input_statement_type *));
-static void gld${EMULATION_NAME}_stat_needed
-  PARAMS ((lang_input_statement_type *));
-static boolean gld${EMULATION_NAME}_try_needed PARAMS ((const char *, int));
-static boolean gld${EMULATION_NAME}_search_needed
-  PARAMS ((const char *, const char *, int));
-static void gld${EMULATION_NAME}_check_needed
-  PARAMS ((lang_input_statement_type *));
-static void gld${EMULATION_NAME}_after_open PARAMS ((void));
-static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
-static void gld${EMULATION_NAME}_find_statement_assignment
-  PARAMS ((lang_statement_union_type *));
-static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
-static boolean gld${EMULATION_NAME}_open_dynamic_archive
-  PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *));
-static lang_output_section_statement_type *output_rel_find PARAMS ((void));
-static boolean gld${EMULATION_NAME}_place_orphan
-  PARAMS ((lang_input_statement_type *, asection *));
-static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
+/* 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}_finish (void);
 
 EOF
 
@@ -77,7 +69,7 @@ if test -n "$EXTRA_EM_FILE" ; then
 . ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
 fi
 
-# Functions in this file can be overriden by setting the LDEMUL_* shell
+# Functions in this file can be overridden by setting the LDEMUL_* shell
 # variables.  If the name of the overriding function is the same as is
 # defined in this file, then don't output this file's version.
 # If a different overriding name is given then output the standard function
@@ -87,16 +79,38 @@ if test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then
 cat >>e${EMULATION_NAME}.c <<EOF
 
 static void
-gld${EMULATION_NAME}_before_parse ()
+gld${EMULATION_NAME}_before_parse (void)
 {
-  ldfile_output_architecture = bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`;
-  config.dynamic_link = ${DYNAMIC_LINK-true};
-  config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo true ; else echo false ; fi`;
+  ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
+  config.dynamic_link = ${DYNAMIC_LINK-TRUE};
+  config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
 }
 
 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.  */
+
+static bfd_boolean
+gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *entry)
+{
+  if (!entry->as_needed
+      || (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) == 0)
+    return FALSE;
+
+  /* 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.  */
+  bfd_elf_set_dyn_lib_class (entry->the_bfd, DYN_AS_NEEDED);
+
+  /* Continue on with normal load_symbols processing.  */
+  return FALSE;
+}
+EOF
+fi
+
 cat >>e${EMULATION_NAME}.c <<EOF
 
 /* These variables are required to pass information back and forth
@@ -104,9 +118,9 @@ cat >>e${EMULATION_NAME}.c <<EOF
 
 static struct bfd_link_needed_list *global_needed;
 static struct stat global_stat;
-static boolean global_found;
+static bfd_boolean global_found;
 static struct bfd_link_needed_list *global_vercheck_needed;
-static boolean global_vercheck_failed;
+static bfd_boolean global_vercheck_failed;
 
 
 /* On Linux, it's possible to have different versions of the same
@@ -123,14 +137,13 @@ static boolean global_vercheck_failed;
 
    This is called via lang_for_each_input_file.
    GLOBAL_VERCHECK_NEEDED is the list of objects needed by the object
-   which we ar checking.  This sets GLOBAL_VERCHECK_FAILED if we find
+   which we are checking.  This sets GLOBAL_VERCHECK_FAILED if we find
    a conflicting version.  */
 
 static void
-gld${EMULATION_NAME}_vercheck (s)
-     lang_input_statement_type *s;
+gld${EMULATION_NAME}_vercheck (lang_input_statement_type *s)
 {
-  const char *soname, *f;
+  const char *soname;
   struct bfd_link_needed_list *l;
 
   if (global_vercheck_failed)
@@ -141,19 +154,13 @@ gld${EMULATION_NAME}_vercheck (s)
 
   soname = bfd_elf_get_dt_soname (s->the_bfd);
   if (soname == NULL)
-    soname = bfd_get_filename (s->the_bfd);
-
-  f = strrchr (soname, '/');
-  if (f != NULL)
-    ++f;
-  else
-    f = soname;
+    soname = lbasename (bfd_get_filename (s->the_bfd));
 
   for (l = global_vercheck_needed; l != NULL; l = l->next)
     {
       const char *suffix;
 
-      if (strcmp (f, l->name) == 0)
+      if (strcmp (soname, l->name) == 0)
        {
          /* Probably can't happen, but it's an easy check.  */
          continue;
@@ -168,14 +175,14 @@ gld${EMULATION_NAME}_vercheck (s)
 
       suffix += sizeof ".so." - 1;
 
-      if (strncmp (f, l->name, suffix - l->name) == 0)
+      if (strncmp (soname, l->name, suffix - l->name) == 0)
        {
          /* Here we know that S is a dynamic object FOO.SO.VER1, and
-             the object we are considering needs a dynamic object
-             FOO.SO.VER2, and VER1 and VER2 are different.  This
-             appears to be a version mismatch, so we tell the caller
-             to try a different version of this library.  */
-         global_vercheck_failed = true;
+            the object we are considering needs a dynamic object
+            FOO.SO.VER2, and VER1 and VER2 are different.  This
+            appears to be a version mismatch, so we tell the caller
+            to try a different version of this library.  */
+         global_vercheck_failed = TRUE;
          return;
        }
     }
@@ -186,13 +193,11 @@ gld${EMULATION_NAME}_vercheck (s)
    the file.  */
 
 static void
-gld${EMULATION_NAME}_stat_needed (s)
-     lang_input_statement_type *s;
+gld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s)
 {
   struct stat st;
   const char *suffix;
   const char *soname;
-  const char *f;
 
   if (global_found)
     return;
@@ -208,7 +213,7 @@ gld${EMULATION_NAME}_stat_needed (s)
   if (st.st_dev == global_stat.st_dev
       && st.st_ino == global_stat.st_ino)
     {
-      global_found = true;
+      global_found = TRUE;
       return;
     }
 
@@ -216,7 +221,7 @@ gld${EMULATION_NAME}_stat_needed (s)
      different versions of the same shared library.  For example,
      there may be a problem if -lc picks up libc.so.6 but some other
      shared library has a DT_NEEDED entry of libc.so.5.  This is a
-     hueristic test, and it will only work if the name looks like
+     heuristic test, and it will only work if the name looks like
      NAME.so.VERSION.  FIXME: Depending on file names is error-prone.
      If we really want to issue warnings about mixing version numbers
      of shared libraries, we need to find a better way.  */
@@ -230,17 +235,11 @@ gld${EMULATION_NAME}_stat_needed (s)
 
   soname = bfd_elf_get_dt_soname (s->the_bfd);
   if (soname == NULL)
-    soname = s->filename;
+    soname = lbasename (s->filename);
 
-  f = strrchr (soname, '/');
-  if (f != NULL)
-    ++f;
-  else
-    f = soname;
-
-  if (strncmp (f, global_needed->name, suffix - global_needed->name) == 0)
+  if (strncmp (soname, global_needed->name, suffix - global_needed->name) == 0)
     einfo ("%P: warning: %s, needed by %B, may conflict with %s\n",
-          global_needed->name, global_needed->by, f);
+          global_needed->name, global_needed->by, soname);
 }
 
 
@@ -248,25 +247,31 @@ gld${EMULATION_NAME}_stat_needed (s)
    named by a DT_NEEDED entry.  The FORCE parameter indicates whether
    to skip the check for a conflicting version.  */
 
-static boolean
-gld${EMULATION_NAME}_try_needed (name, force)
-     const char *name;
-     int force;
+static bfd_boolean
+gld${EMULATION_NAME}_try_needed (const char *name, int force)
 {
   bfd *abfd;
+  const char *soname;
 
   abfd = bfd_openr (name, bfd_get_target (output_bfd));
   if (abfd == NULL)
-    return false;
+    return FALSE;
   if (! bfd_check_format (abfd, bfd_object))
     {
-      (void) bfd_close (abfd);
-      return false;
+      bfd_close (abfd);
+      return FALSE;
     }
   if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
     {
-      (void) bfd_close (abfd);
-      return false;
+      bfd_close (abfd);
+      return FALSE;
+    }
+
+  /* For DT_NEEDED, they have to match.  */
+  if (abfd->xvec != output_bfd->xvec)
+    {
+      bfd_close (abfd);
+      return FALSE;
     }
 
   /* Check whether this object would include any conflicting library
@@ -284,22 +289,22 @@ gld${EMULATION_NAME}_try_needed (name, force)
       if (needed != NULL)
        {
          global_vercheck_needed = needed;
-         global_vercheck_failed = false;
+         global_vercheck_failed = FALSE;
          lang_for_each_input_file (gld${EMULATION_NAME}_vercheck);
          if (global_vercheck_failed)
            {
-             (void) bfd_close (abfd);
-             /* Return false to force the caller to move on to try
-                 another file on the search path.  */
-             return false;
+             bfd_close (abfd);
+             /* Return FALSE to force the caller to move on to try
+                another file on the search path.  */
+             return FALSE;
            }
 
          /* But wait!  It gets much worse.  On Linux, if a shared
-             library does not use libc at all, we are supposed to skip
-             it the first time around in case we encounter a shared
-             library later on with the same name which does use the
-             version of libc that we want.  This is much too horrible
-             to use on any system other than Linux.  */
+            library does not use libc at all, we are supposed to skip
+            it the first time around in case we encounter a shared
+            library later on with the same name which does use the
+            version of libc that we want.  This is much too horrible
+            to use on any system other than Linux.  */
 
 EOF
 case ${target} in
@@ -313,8 +318,8 @@ case ${target} in
                break;
            if (l == NULL)
              {
-               (void) bfd_close (abfd);
-               return false;
+               bfd_close (abfd);
+               return FALSE;
              }
          }
 
@@ -337,52 +342,51 @@ cat >>e${EMULATION_NAME}.c <<EOF
 
   if (bfd_stat (abfd, &global_stat) != 0)
     einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd);
-  global_found = false;
+
+  /* First strip off everything before the last '/'.  */
+  soname = lbasename (abfd->filename);
+
+  if (trace_file_tries)
+    info_msg (_("found %s at %s\n"), soname, name);
+
+  global_found = FALSE;
   lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed);
   if (global_found)
     {
-      /* Return true to indicate that we found the file, even though
-         we aren't going to do anything with it.  */
-      return true;
+      /* Return TRUE to indicate that we found the file, even though
+        we aren't going to do anything with it.  */
+      return TRUE;
     }
 
-  /* Tell the ELF backend that we don't want the output file to have a
-     DT_NEEDED entry for this file.  */
-  bfd_elf_set_dt_needed_name (abfd, "");
+  /* Specify the soname to use.  */
+  bfd_elf_set_dt_needed_name (abfd, soname);
 
-  /* First strip off everything before the last '/'.  */
-  name = strrchr (abfd->filename, '/');
-  if (name)
-    name++;
-  else
-    name = abfd->filename;
-
-  /* Tell the ELF backend that the output file needs a DT_NEEDED
-     entry for this file if it is used to resolve the reference in
-     a regular object.  */
-  bfd_elf_set_dt_needed_soname (abfd, name);
+  /* 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.  */
+  bfd_elf_set_dyn_lib_class (abfd, DYN_DT_NEEDED);
 
   /* Add this file into the symbol table.  */
   if (! bfd_link_add_symbols (abfd, &link_info))
     einfo ("%F%B: could not read symbols: %E\n", abfd);
 
-  return true;
+  return TRUE;
 }
 
 
 /* Search for a needed file in a path.  */
 
-static boolean
-gld${EMULATION_NAME}_search_needed (path, name, force)
-     const char *path;
-     const char *name;
-     int force;
+static bfd_boolean
+gld${EMULATION_NAME}_search_needed (const char *path, const char *name, int force)
 {
   const char *s;
   size_t len;
 
+  if (name[0] == '/')
+    return gld${EMULATION_NAME}_try_needed (name, force);
+
   if (path == NULL || *path == '\0')
-    return false;
+    return FALSE;
   len = strlen (name);
   while (1)
     {
@@ -404,7 +408,7 @@ gld${EMULATION_NAME}_search_needed (path, name, force)
       strcpy (sset, name);
 
       if (gld${EMULATION_NAME}_try_needed (filename, force))
-       return true;
+       return TRUE;
 
       free (filename);
 
@@ -413,35 +417,72 @@ gld${EMULATION_NAME}_search_needed (path, name, force)
       path = s + 1;
     }
 
-  return false;
+  return FALSE;
 }
 
 EOF
-if [ "x${host}" = "x${target}" ] ; then
-  case " ${EMULATION_LIBPATH} " in
-  *" ${EMULATION_NAME} "*)
-cat >>e${EMULATION_NAME}.c <<EOF
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+  cat >>e${EMULATION_NAME}.c <<EOF
 
+/* Add the sysroot to every entry in a colon-separated path.  */
+
+static char *
+gld${EMULATION_NAME}_add_sysroot (const char *path)
+{
+  int len, colons, i;
+  char *ret, *p;
+
+  len = strlen (path);
+  colons = 0;
+  i = 0;
+  while (path[i])
+    if (path[i++] == ':')
+      colons++;
+
+  if (path[i])
+    colons++;
+
+  len = len + (colons + 1) * strlen (ld_sysroot);
+  ret = xmalloc (len + 1);
+  strcpy (ret, ld_sysroot);
+  p = ret + strlen (ret);
+  i = 0;
+  while (path[i])
+    if (path[i] == ':')
+      {
+       *p++ = path[i++];
+       strcpy (p, ld_sysroot);
+       p = p + strlen (p);
+      }
+    else
+      *p++ = path[i++];
+
+  *p = 0;
+  return ret;
+}
+
+EOF
+  case ${target} in
+    *-*-linux-gnu*)
+      cat >>e${EMULATION_NAME}.c <<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, but we check it on other systems anyhow.  */
-
-static boolean gld${EMULATION_NAME}_check_ld_so_conf
-  PARAMS ((const char *, int));
+   only meaningful on Linux.  */
 
-static boolean
-gld${EMULATION_NAME}_check_ld_so_conf (name, force)
-     const char *name;
-     int force;
+static bfd_boolean
+gld${EMULATION_NAME}_check_ld_so_conf (const char *name, int force)
 {
-  static boolean initialized;
+  static bfd_boolean initialized;
   static char *ld_so_conf;
 
   if (! initialized)
     {
       FILE *f;
+      char *tmppath;
 
-      f = fopen ("/etc/ld.so.conf", FOPEN_RT);
+      tmppath = concat (ld_sysroot, "/etc/ld.so.conf", NULL);
+      f = fopen (tmppath, FOPEN_RT);
+      free (tmppath);
       if (f != NULL)
        {
          char *b;
@@ -491,20 +532,28 @@ gld${EMULATION_NAME}_check_ld_so_conf (name, force)
 
          fclose (f);
 
+         if (b)
+           {
+             char *d = gld${EMULATION_NAME}_add_sysroot (b);
+             free (b);
+             b = d;
+           }
+
          ld_so_conf = b;
        }
 
-      initialized = true;
+      initialized = TRUE;
     }
 
   if (ld_so_conf == NULL)
-    return false;
+    return FALSE;
 
   return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force);
 }
 
 EOF
-  ;;
+    # Linux
+    ;;
   esac
 fi
 cat >>e${EMULATION_NAME}.c <<EOF
@@ -512,17 +561,31 @@ cat >>e${EMULATION_NAME}.c <<EOF
 /* See if an input file matches a DT_NEEDED entry by name.  */
 
 static void
-gld${EMULATION_NAME}_check_needed (s)
-     lang_input_statement_type *s;
+gld${EMULATION_NAME}_check_needed (lang_input_statement_type *s)
 {
   if (global_found)
     return;
 
-  if (s->filename != NULL
-      && strcmp (s->filename, global_needed->name) == 0)
+  if (s->filename != NULL)
     {
-      global_found = true;
-      return;
+      const char *f;
+
+      if (strcmp (s->filename, global_needed->name) == 0)
+       {
+         global_found = TRUE;
+         return;
+       }
+
+      if (s->search_dirs_flag)
+       {
+         f = strrchr (s->filename, '/');
+         if (f != NULL
+             && strcmp (f + 1, global_needed->name) == 0)
+           {
+             global_found = TRUE;
+             return;
+           }
+       }
     }
 
   if (s->the_bfd != NULL)
@@ -533,22 +596,7 @@ gld${EMULATION_NAME}_check_needed (s)
       if (soname != NULL
          && strcmp (soname, global_needed->name) == 0)
        {
-         global_found = true;
-         return;
-       }
-    }
-         
-  if (s->search_dirs_flag
-      && s->filename != NULL
-      && strchr (global_needed->name, '/') == NULL)
-    {
-      const char *f;
-
-      f = strrchr (s->filename, '/');
-      if (f != NULL
-         && strcmp (f + 1, global_needed->name) == 0)
-       {
-         global_found = true;
+         global_found = TRUE;
          return;
        }
     }
@@ -562,12 +610,12 @@ cat >>e${EMULATION_NAME}.c <<EOF
 /* This is called after all the input files have been opened.  */
 
 static void
-gld${EMULATION_NAME}_after_open ()
+gld${EMULATION_NAME}_after_open (void)
 {
   struct bfd_link_needed_list *needed, *l;
 
   /* We only need to worry about this when doing a final link.  */
-  if (link_info.relocateable || link_info.shared)
+  if (link_info.relocatable || !link_info.executable)
     return;
 
   /* Get the list of files which appear in DT_NEEDED entries in
@@ -594,33 +642,52 @@ gld${EMULATION_NAME}_after_open ()
 
       /* See if this file was included in the link explicitly.  */
       global_needed = l;
-      global_found = false;
+      global_found = FALSE;
       lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
       if (global_found)
        continue;
 
+      if (trace_file_tries)
+       info_msg (_("%s needed by %B\n"), l->name, l->by);
+
       /* 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
         rpath_link, rpath, then the environment variable
-        LD_LIBRARY_PATH (native only), then the linker script
-        LIB_SEARCH_DIRS.  We do not search using the -L arguments.
+        LD_LIBRARY_PATH (native only), then the DT_RPATH/DT_RUNPATH
+        entries (native only), then the linker script LIB_SEARCH_DIRS.
+        We do not search using the -L arguments.
 
         We search twice.  The first time, we skip objects which may
         introduce version mismatches.  The second time, we force
         their use.  See gld${EMULATION_NAME}_vercheck comment.  */
       for (force = 0; force < 2; force++)
        {
-         const char *lib_path;
          size_t len;
          search_dirs_type *search;
+EOF
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+         const char *lib_path;
+         struct bfd_link_needed_list *rp;
+         int found;
+EOF
+fi
+cat >>e${EMULATION_NAME}.c <<EOF
 
          if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
                                                  l->name, force))
            break;
+EOF
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+cat >>e${EMULATION_NAME}.c <<EOF
          if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
                                                  l->name, force))
            break;
+EOF
+fi
+if [ "x${NATIVE}" = xyes ] ; then
+cat >>e${EMULATION_NAME}.c <<EOF
          if (command_line.rpath_link == NULL
              && command_line.rpath == NULL)
            {
@@ -629,17 +696,28 @@ gld${EMULATION_NAME}_after_open ()
                                                      force))
                break;
            }
-EOF
-if [ "x${host}" = "x${target}" ] ; then
-  case " ${EMULATION_LIBPATH} " in
-  *" ${EMULATION_NAME} "*)
-cat >>e${EMULATION_NAME}.c <<EOF
          lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
          if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force))
            break;
 EOF
-  ;;
-  esac
+fi
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+         found = 0;
+         rp = bfd_elf_get_runpath_list (output_bfd, &link_info);
+         for (; !found && rp != NULL; rp = rp->next)
+           {
+             char *tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name);
+             found = (rp->by == l->by
+                      && gld${EMULATION_NAME}_search_needed (tmpname,
+                                                             l->name,
+                                                             force));
+             free (tmpname);
+           }
+         if (found)
+           break;
+
+EOF
 fi
 cat >>e${EMULATION_NAME}.c <<EOF
          len = strlen (l->name);
@@ -658,14 +736,15 @@ cat >>e${EMULATION_NAME}.c <<EOF
          if (search != NULL)
            break;
 EOF
-if [ "x${host}" = "x${target}" ] ; then
-  case " ${EMULATION_LIBPATH} " in
-  *" ${EMULATION_NAME} "*)
-cat >>e${EMULATION_NAME}.c <<EOF
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+  case ${target} in
+    *-*-linux-gnu*)
+      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
@@ -674,7 +753,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
       if (force < 2)
        continue;
 
-      einfo ("%P: warning: %s, needed by %B, not found (try using --rpath)\n",
+      einfo ("%P: warning: %s, needed by %B, not found (try using -rpath or -rpath-link)\n",
             l->name, l->by);
     }
 }
@@ -687,8 +766,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
 /* Look through an expression for an assignment statement.  */
 
 static void
-gld${EMULATION_NAME}_find_exp_assignment (exp)
-     etree_type *exp;
+gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp)
 {
   struct bfd_link_hash_entry *h;
 
@@ -696,7 +774,7 @@ gld${EMULATION_NAME}_find_exp_assignment (exp)
     {
     case etree_provide:
       h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst,
-                               false, false, false);
+                               FALSE, FALSE, FALSE);
       if (h == NULL)
        break;
 
@@ -712,9 +790,9 @@ gld${EMULATION_NAME}_find_exp_assignment (exp)
     case etree_assign:
       if (strcmp (exp->assign.dst, ".") != 0)
        {
-         if (! (bfd_elf${ELFSIZE}_record_link_assignment
+         if (! (bfd_elf_record_link_assignment
                 (output_bfd, &link_info, exp->assign.dst,
-                 exp->type.node_class == etree_provide ? true : false)))
+                 exp->type.node_class == etree_provide ? TRUE : FALSE)))
            einfo ("%P%F: failed to record assignment to %s: %E\n",
                   exp->assign.dst);
        }
@@ -748,8 +826,7 @@ gld${EMULATION_NAME}_find_exp_assignment (exp)
    symbols which are referred to by dynamic objects.  */
 
 static void
-gld${EMULATION_NAME}_find_statement_assignment (s)
-     lang_statement_union_type *s;
+gld${EMULATION_NAME}_find_statement_assignment (lang_statement_union_type *s)
 {
   if (s->header.type == lang_assignment_statement_enum)
     gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
@@ -758,17 +835,32 @@ gld${EMULATION_NAME}_find_statement_assignment (s)
 EOF
 
 if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then
+  if test x"${ELF_INTERPRETER_NAME+set}" = xset; then
+    ELF_INTERPRETER_SET_DEFAULT="
+  if (sinterp != NULL)
+    {
+      sinterp->contents = ${ELF_INTERPRETER_NAME};
+      sinterp->_raw_size = strlen (sinterp->contents) + 1;
+    }
+
+"
+  else
+    ELF_INTERPRETER_SET_DEFAULT=
+  fi
 cat >>e${EMULATION_NAME}.c <<EOF
 
 /* This is called after the sections have been attached to output
    sections, but before any sizes or addresses have been set.  */
 
 static void
-gld${EMULATION_NAME}_before_allocation ()
+gld${EMULATION_NAME}_before_allocation (void)
 {
   const char *rpath;
   asection *sinterp;
 
+  if (link_info.hash->type == bfd_link_elf_hash_table)
+    _bfd_elf_tls_setup (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
      referred to by dynamic objects.  */
@@ -779,13 +871,13 @@ gld${EMULATION_NAME}_before_allocation ()
   rpath = command_line.rpath;
   if (rpath == NULL)
     rpath = (const char *) getenv ("LD_RUN_PATH");
-  if (! (bfd_elf${ELFSIZE}_size_dynamic_sections
-         (output_bfd, command_line.soname, rpath,
-         command_line.export_dynamic, command_line.filter_shlib,
+  if (! (bfd_elf_size_dynamic_sections
+        (output_bfd, command_line.soname, rpath,
+         command_line.filter_shlib,
          (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");
-
+${ELF_INTERPRETER_SET_DEFAULT}
   /* Let the user override the dynamic linker we are using.  */
   if (command_line.interpreter != NULL
       && sinterp != NULL)
@@ -804,8 +896,10 @@ gld${EMULATION_NAME}_before_allocation ()
       {
        asection *s;
        bfd_size_type sz;
+       bfd_size_type prefix_len;
        char *msg;
-       boolean ret;
+       bfd_boolean ret;
+       const char * gnu_warning_prefix = _("warning: ");
 
        if (is->just_syms_flag)
          continue;
@@ -815,11 +909,14 @@ gld${EMULATION_NAME}_before_allocation ()
          continue;
 
        sz = bfd_section_size (is->the_bfd, s);
-       msg = xmalloc ((size_t) sz + 1);
-       if (! bfd_get_section_contents (is->the_bfd, s, msg, (file_ptr) 0, sz))
+       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,
+                                       (file_ptr) 0, sz))
          einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
                 is->the_bfd);
-       msg[sz] = '\0';
+       msg[prefix_len + sz] = '\0';
        ret = link_info.callbacks->warning (&link_info, msg,
                                            (const char *) NULL,
                                            is->the_bfd, (asection *) NULL,
@@ -844,17 +941,15 @@ cat >>e${EMULATION_NAME}.c <<EOF
    dynamic libraries have an extension of .so (or .sl on oddball systems
    like hpux).  */
 
-static boolean
-gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
-     const char *arch;
-     search_dirs_type *search;
-     lang_input_statement_type *entry;
+static bfd_boolean
+gld${EMULATION_NAME}_open_dynamic_archive
+  (const char *arch, search_dirs_type *search, lang_input_statement_type *entry)
 {
   const char *filename;
   char *string;
 
   if (! entry->is_archive)
-    return false;
+    return FALSE;
 
   filename = entry->filename;
 
@@ -882,7 +977,7 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
   if (! ldfile_try_open_bfd (string, entry))
     {
       free (string);
-      return false;
+      return FALSE;
     }
 
   entry->filename = string;
@@ -903,56 +998,105 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
   if (bfd_check_format (entry->the_bfd, bfd_object)
       && (entry->the_bfd->flags & DYNAMIC) != 0)
     {
-      char *needed_name;
-
       ASSERT (entry->is_archive && entry->search_dirs_flag);
 
       /* Rather than duplicating the logic above.  Just use the
-        filename we recorded earlier.
-
-        First strip off everything before the last '/'.  */
-      filename = strrchr (entry->filename, '/');
-      filename++;
+        filename we recorded earlier.  */
 
-      needed_name = (char *) xmalloc (strlen (filename) + 1);
-      strcpy (needed_name, filename);
-      bfd_elf_set_dt_needed_name (entry->the_bfd, needed_name);
+      filename = lbasename (entry->filename);
+      bfd_elf_set_dt_needed_name (entry->the_bfd, filename);
     }
 
-  return true;
+  return TRUE;
 }
 
 EOF
 fi
+
+if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
 cat >>e${EMULATION_NAME}.c <<EOF
 
 /* A variant of lang_output_section_find.  Used by place_orphan.  */
 
 static lang_output_section_statement_type *
-output_rel_find ()
+output_rel_find (asection *sec, int isdyn)
 {
   lang_statement_union_type *u;
   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_rel = NULL;
+  lang_output_section_statement_type *last_rel_alloc = NULL;
+  int rela = sec->name[4] == 'a';
 
-  for (u = lang_output_section_statement.head;
-       u != (lang_statement_union_type *) NULL;
-       u = lookup->next)
+  for (u = lang_output_section_statement.head; u; u = lookup->next)
     {
       lookup = &u->output_section_statement;
-      if (strncmp (".rel", lookup->name, 4) == 0
-         && lookup->bfd_section != NULL
-         && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
+      if (lookup->constraint != -1
+         && strncmp (".rel", lookup->name, 4) == 0)
        {
-         return lookup;
+         int lookrela = lookup->name[4] == 'a';
+
+         /* .rel.dyn must come before all other reloc sections, to suit
+            GNU ld.so.  */
+         if (isdyn)
+           break;
+
+         /* Don't place after .rel.plt as doing so results in wrong
+            dynamic tags.  */
+         if (strcmp (".plt", lookup->name + 4 + lookrela) == 0)
+           break;
+
+         if (rela == lookrela || last_rel == NULL)
+           last_rel = lookup;
+         if ((rela == lookrela || last_rel_alloc == NULL)
+             && lookup->bfd_section != NULL
+             && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
+           last_rel_alloc = lookup;
        }
+
+      last = lookup;
+      if (lookup->bfd_section != NULL
+         && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
+       last_alloc = lookup;
     }
-  return (lang_output_section_statement_type *) NULL;
+
+  if (last_rel_alloc)
+    return last_rel_alloc;
+
+  if (last_rel)
+    return last_rel;
+
+  if (last_alloc)
+    return last_alloc;
+
+  return last;
 }
 
-EOF
+/* Find the last output section before given output statement.
+   Used by place_orphan.  */
 
-if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
-cat >>e${EMULATION_NAME}.c <<EOF
+static asection *
+output_prev_sec_find (lang_output_section_statement_type *os)
+{
+  asection *s = (asection *) NULL;
+  lang_statement_union_type *u;
+  lang_output_section_statement_type *lookup;
+
+  for (u = lang_output_section_statement.head;
+       u != (lang_statement_union_type *) NULL;
+       u = lookup->next)
+    {
+      lookup = &u->output_section_statement;
+      if (lookup == os)
+       return s;
+
+      if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
+       s = lookup->bfd_section;
+    }
+
+  return NULL;
+}
 
 /* Place an orphan section.  We use this to put random SHF_ALLOC
    sections in the right segment.  */
@@ -961,12 +1105,11 @@ struct orphan_save {
   lang_output_section_statement_type *os;
   asection **section;
   lang_statement_union_type **stmt;
+  lang_statement_union_type **os_tail;
 };
 
-static boolean
-gld${EMULATION_NAME}_place_orphan (file, s)
-     lang_input_statement_type *file;
-     asection *s;
+static bfd_boolean
+gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
 {
   static struct orphan_save hold_text;
   static struct orphan_save hold_rodata;
@@ -974,26 +1117,47 @@ gld${EMULATION_NAME}_place_orphan (file, s)
   static struct orphan_save hold_bss;
   static struct orphan_save hold_rel;
   static struct orphan_save hold_interp;
+  static struct orphan_save hold_sdata;
+  static int count = 1;
   struct orphan_save *place;
   lang_statement_list_type *old;
   lang_statement_list_type add;
   etree_type *address;
-  const char *secname, *ps;
-  const char *outsecname;
+  const char *secname;
+  const char *ps = NULL;
   lang_output_section_statement_type *os;
+  lang_statement_union_type **os_tail;
+  etree_type *load_base;
+  int isdyn = 0;
 
   secname = bfd_get_section_name (s->owner, s);
+  if (! link_info.relocatable
+      && link_info.combreloc
+      && (s->flags & SEC_ALLOC)
+      && strncmp (secname, ".rel", 4) == 0)
+    {
+      if (secname[4] == 'a')
+       secname = ".rela.dyn";
+      else
+       secname = ".rel.dyn";
+      isdyn = 1;
+    }
 
-  /* Look through the script to see where to place this section.  */
-  os = lang_output_section_find (secname);
-
-  if (os != NULL
-      && os->bfd_section != NULL
-      && ((s->flags ^ os->bfd_section->flags) & (SEC_LOAD | SEC_ALLOC)) == 0)
+  if (isdyn || (!config.unique_orphan_sections && !unique_section_p (s)))
     {
-      /* We have already placed a section with this name.  */
-      wild_doit (&os->children, s, os, file);
-      return true;
+      /* Look through the script to see where to place this section.  */
+      os = lang_output_section_find (secname);
+
+      if (os != NULL
+         && (os->bfd_section == NULL
+             || ((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.  */
+         lang_add_section (&os->children, s, os, file);
+         return TRUE;
+       }
     }
 
   if (hold_text.os == NULL)
@@ -1001,13 +1165,13 @@ gld${EMULATION_NAME}_place_orphan (file, s)
 
   /* If this is a final link, then always put .gnu.warning.SYMBOL
      sections into the .text section to get them out of the way.  */
-  if (! link_info.shared
-      && ! link_info.relocateable
+  if (link_info.executable
+      && ! link_info.relocatable
       && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
       && hold_text.os != NULL)
     {
-      wild_doit (&hold_text.os->children, s, hold_text.os, file);
-      return true;
+      lang_add_section (&hold_text.os->children, s, hold_text.os, file);
+      return TRUE;
     }
 
   /* Decide which segment the section should go in based on the
@@ -1018,169 +1182,250 @@ gld${EMULATION_NAME}_place_orphan (file, s)
 #define HAVE_SECTION(hold, name) \
 (hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
 
-  if (s->flags & SEC_EXCLUDE)
-    return false;
-  else if ((s->flags & SEC_ALLOC) == 0)
-    place = NULL;
+  if (((s->flags & (SEC_EXCLUDE | SEC_GROUP)) != 0 && !link_info.relocatable)
+      || ((s->flags & (SEC_EXCLUDE | SEC_DEBUGGING))
+         == (SEC_EXCLUDE | SEC_DEBUGGING)))
+    {
+      if (s->output_section == NULL)
+       s->output_section = bfd_abs_section_ptr;
+      return TRUE;
+    }
+
+  place = NULL;
+  if ((s->flags & SEC_ALLOC) == 0)
+    ;
   else if ((s->flags & SEC_LOAD) != 0
-          && strncmp (secname, ".note", 4) == 0
+          && strncmp (secname, ".note", 5) == 0
           && HAVE_SECTION (hold_interp, ".interp"))
     place = &hold_interp;
   else if ((s->flags & SEC_HAS_CONTENTS) == 0
           && HAVE_SECTION (hold_bss, ".bss"))
     place = &hold_bss;
+  else if ((s->flags & SEC_SMALL_DATA) != 0
+          && HAVE_SECTION (hold_sdata, ".sdata"))
+    place = &hold_sdata;
   else if ((s->flags & SEC_READONLY) == 0
           && HAVE_SECTION (hold_data, ".data"))
     place = &hold_data;
   else if (strncmp (secname, ".rel", 4) == 0
+          && (s->flags & SEC_LOAD) != 0
           && (hold_rel.os != NULL
-              || (hold_rel.os = output_rel_find ()) != NULL))
+              || (hold_rel.os = output_rel_find (s, isdyn)) != NULL))
     place = &hold_rel;
-  else if ((s->flags & SEC_CODE) == 0
-          && (s->flags & SEC_READONLY) != 0
+  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
           && HAVE_SECTION (hold_rodata, ".rodata"))
     place = &hold_rodata;
-  else if ((s->flags & SEC_READONLY) != 0
+  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY)
           && hold_text.os != NULL)
     place = &hold_text;
-  else
-    place = NULL;
 
 #undef HAVE_SECTION
 
   /* 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 allocateable characteristics.  */
-  outsecname = secname;
-  if (bfd_get_section_by_name (output_bfd, outsecname) != NULL)
+     loadable or allocatable characteristics.  */
+  if (bfd_get_section_by_name (output_bfd, secname) != NULL)
     {
-      unsigned int len;
-      char *newname;
-      unsigned int i;
-
-      len = strlen (outsecname);
-      newname = xmalloc (len + 5);
-      strcpy (newname, outsecname);
-      i = 0;
-      do
-       {
-         sprintf (newname + len, "%d", i);
-         ++i;
-       }
-      while (bfd_get_section_by_name (output_bfd, newname) != NULL);
-
-      outsecname = newname;
+      secname = bfd_get_unique_section_name (output_bfd, secname, &count);
+      if (secname == NULL)
+       einfo ("%F%P: place_orphan failed: %E\n");
     }
 
+  /* Start building a list of statements for this section.
+     First save the current statement pointer.  */
+  old = stat_ptr;
+
+  /* If we have found an appropriate place for the output section
+     statements for this orphan, add them to our own private list,
+     inserting them later into the global statement list.  */
   if (place != NULL)
     {
-      /* Start building a list of statements for this section.  */
-      old = stat_ptr;
       stat_ptr = &add;
       lang_list_init (stat_ptr);
+    }
 
+  if (config.build_constructors)
+    {
       /* If the name of the section is representable in C, then create
         symbols to mark the start and the end of the section.  */
-      for (ps = outsecname; *ps != '\0'; ps++)
-       if (! isalnum ((unsigned char) *ps) && *ps != '_')
+      for (ps = secname; *ps != '\0'; ps++)
+       if (! ISALNUM (*ps) && *ps != '_')
          break;
-      if (*ps == '\0' && config.build_constructors)
+      if (*ps == '\0')
        {
          char *symname;
          etree_type *e_align;
 
-         symname = (char *) xmalloc (ps - outsecname + sizeof "__start_");
-         sprintf (symname, "__start_%s", outsecname);
+         symname = (char *) xmalloc (ps - secname + sizeof "__start_");
+         sprintf (symname, "__start_%s", secname);
          e_align = exp_unop (ALIGN_K,
                              exp_intop ((bfd_vma) 1 << s->alignment_power));
          lang_add_assignment (exp_assop ('=', symname, e_align));
        }
     }
 
-  if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
+  address = NULL;
+  if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
     address = exp_intop ((bfd_vma) 0);
-  else
-    address = NULL;
 
-  os = lang_enter_output_section_statement (outsecname, address, 0,
-                                           (bfd_vma) 0,
+  load_base = NULL;
+  if (place != NULL && place->os->load_base != NULL)
+    {
+      etree_type *lma_from_vma;
+      lma_from_vma = exp_binop ('-', place->os->load_base,
+                               exp_nameop (ADDR, place->os->name));
+      load_base = exp_binop ('+', lma_from_vma,
+                            exp_nameop (ADDR, secname));
+    }
+
+  os_tail = lang_output_section_statement.tail;
+  os = lang_enter_output_section_statement (secname, address, 0,
                                            (etree_type *) NULL,
                                            (etree_type *) NULL,
-                                           (etree_type *) NULL);
+                                           load_base, 0);
 
-  wild_doit (&os->children, s, os, file);
+  lang_add_section (&os->children, s, os, file);
 
   lang_leave_output_section_statement
     ((bfd_vma) 0, "*default*",
-     (struct lang_output_section_phdr_list *) NULL, "*default*");
+     (struct lang_output_section_phdr_list *) NULL, NULL);
 
-  if (place != NULL)
+  if (config.build_constructors && *ps == '\0')
+    {
+      char *symname;
+
+      /* lang_leave_ouput_section_statement resets stat_ptr.  Put
+        stat_ptr back where we want it.  */
+      if (place != NULL)
+       stat_ptr = &add;
+
+      symname = (char *) xmalloc (ps - secname + sizeof "__stop_");
+      sprintf (symname, "__stop_%s", secname);
+      lang_add_assignment (exp_assop ('=', symname,
+                                     exp_nameop (NAME, ".")));
+    }
+
+  /* Restore the global list pointer.  */
+  stat_ptr = old;
+
+  if (place != NULL && os->bfd_section != NULL)
     {
       asection *snew, **pps;
 
-      stat_ptr = &add;
+      snew = os->bfd_section;
 
-      if (*ps == '\0' && config.build_constructors)
+      /* Shuffle the bfd section list to make the output file look
+        neater.  This is really only cosmetic.  */
+      if (place->section == NULL)
        {
-         char *symname;
+         asection *bfd_section = place->os->bfd_section;
 
-         symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
-         sprintf (symname, "__stop_%s", outsecname);
-         lang_add_assignment (exp_assop ('=', symname,
-                                         exp_nameop (NAME, ".")));
+         /* If the output statement hasn't been used to place
+            any input sections (and thus doesn't have an output
+            bfd_section), look for the closest prior output statement
+            having an output section.  */
+         if (bfd_section == NULL)
+           bfd_section = output_prev_sec_find (place->os);
+
+         if (bfd_section != NULL && bfd_section != snew)
+           place->section = &bfd_section->next;
        }
-      stat_ptr = old;
 
-      snew = os->bfd_section;
-      if (place->os->bfd_section != NULL || place->section != NULL)
+      if (place->section != NULL)
        {
-         /* Shuffle the section to make the output file look neater.  */
-         if (place->section == NULL)
-           {
-#if 0
-             /* Finding the end of the list is a little tricky.  We
-                make a wild stab at it by comparing section flags.  */
-             flagword first_flags = place->os->bfd_section->flags;
-             for (pps = &place->os->bfd_section->next;
-                  *pps != NULL && (*pps)->flags == first_flags;
-                  pps = &(*pps)->next)
-               ;
-             place->section = pps;
-#else
-             /* Put orphans after the first section on the list.  */
-             place->section = &place->os->bfd_section->next;
-#endif
-           }
-
-         /*  Unlink the section.  */
+         /* Unlink the section.  */
          for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
            ;
-         *pps = snew->next;
+         bfd_section_list_remove (output_bfd, pps);
 
          /* Now tack it on to the "place->os" section list.  */
-         snew->next = *place->section;
-         *place->section = snew;
+         bfd_section_list_insert (output_bfd, place->section, snew);
        }
-      place->section = &snew->next;    /* Save the end of this list.  */
 
-      if (place->stmt == NULL)
-       {
-         /* Put the new statement list right at the head.  */
-         *add.tail = place->os->header.next;
-         place->os->header.next = add.head;
-       }
-      else
+      /* Save the end of this list.  Further ophans of this type will
+        follow the one we've just added.  */
+      place->section = &snew->next;
+
+      /* The following is non-cosmetic.  We try to put the output
+        statements in some sort of reasonable order here, because
+        they determine the final load addresses of the orphan
+        sections.  In addition, placing output statements in the
+        wrong order may require extra segments.  For instance,
+        given a typical situation of all read-only sections placed
+        in one segment and following that a segment containing all
+        the read-write sections, we wouldn't want to place an orphan
+        read/write section before or amongst the read-only ones.  */
+      if (add.head != NULL)
        {
-         /* Put it after the last orphan statement we added.  */
-         *add.tail = *place->stmt;
-         *place->stmt = add.head;
+         lang_statement_union_type *newly_added_os;
+
+         if (place->stmt == NULL)
+           {
+             /* Put the new statement list right at the head.  */
+             *add.tail = place->os->header.next;
+             place->os->header.next = add.head;
+
+             place->os_tail = &place->os->next;
+           }
+         else
+           {
+             /* Put it after the last orphan statement we added.  */
+             *add.tail = *place->stmt;
+             *place->stmt = add.head;
+           }
+
+         /* Fix the global list pointer if we happened to tack our
+            new list at the tail.  */
+         if (*old->tail == add.head)
+           old->tail = add.tail;
+
+         /* Save the end of this list.  */
+         place->stmt = add.tail;
+
+         /* Do the same for the list of output section statements.  */
+         newly_added_os = *os_tail;
+         *os_tail = NULL;
+         newly_added_os->output_section_statement.next = *place->os_tail;
+         *place->os_tail = newly_added_os;
+         place->os_tail = &newly_added_os->output_section_statement.next;
+
+         /* Fixing the global list pointer here is a little different.
+            We added to the list in lang_enter_output_section_statement,
+            trimmed off the new output_section_statment above when
+            assigning *os_tail = NULL, but possibly added it back in
+            the same place when assigning *place->os_tail.  */
+         if (*os_tail == NULL)
+           lang_output_section_statement.tail = os_tail;
        }
-      place->stmt = add.tail;          /* Save the end of this list.  */
     }
 
-  return true;
+  return TRUE;
 }
+EOF
+fi
+
+if test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then
+cat >>e${EMULATION_NAME}.c <<EOF
+
+static void
+gld${EMULATION_NAME}_finish (void)
+{
+  if (bfd_elf_discard_info (output_bfd, &link_info))
+    {
+      lang_reset_memory_regions ();
+
+      /* Resize the sections.  */
+      lang_size_sections (stat_ptr->head, abs_output_section,
+                         &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
 
+      /* Redo special stuff.  */
+      ldemul_after_allocation ();
+
+      /* Do the assignments again.  */
+      lang_do_assignments (stat_ptr->head, abs_output_section,
+                          (fill_type *) 0, (bfd_vma) 0);
+    }
+}
 EOF
 fi
 
@@ -1188,8 +1433,7 @@ if test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
 cat >>e${EMULATION_NAME}.c <<EOF
 
 static char *
-gld${EMULATION_NAME}_get_script (isfile)
-     int *isfile;
+gld${EMULATION_NAME}_get_script (int *isfile)
 EOF
 
 if test -n "$COMPILE_IN"
@@ -1203,25 +1447,52 @@ cat >>e${EMULATION_NAME}.c <<EOF
 {
   *isfile = 0;
 
-  if (link_info.relocateable == true && config.build_constructors == true)
+  if (link_info.relocatable && config.build_constructors)
     return
 EOF
-sed $sc ldscripts/${EMULATION_NAME}.xu                     >> e${EMULATION_NAME}.c
-echo '  ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
-sed $sc ldscripts/${EMULATION_NAME}.xr                     >> e${EMULATION_NAME}.c
-echo '  ; else if (!config.text_read_only) return'         >> e${EMULATION_NAME}.c
-sed $sc ldscripts/${EMULATION_NAME}.xbn                    >> e${EMULATION_NAME}.c
-echo '  ; else if (!config.magic_demand_paged) return'     >> e${EMULATION_NAME}.c
-sed $sc ldscripts/${EMULATION_NAME}.xn                     >> e${EMULATION_NAME}.c
-
+sed $sc ldscripts/${EMULATION_NAME}.xu                 >> e${EMULATION_NAME}.c
+echo '  ; else if (link_info.relocatable) return'     >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xr                 >> e${EMULATION_NAME}.c
+echo '  ; else if (!config.text_read_only) return'     >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xbn                >> e${EMULATION_NAME}.c
+if cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then : ; else
+echo '  ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xn                 >> e${EMULATION_NAME}.c
+fi
+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
+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
+fi
+echo '  ; else if (link_info.pie) return'             >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xd                 >> e${EMULATION_NAME}.c
+fi
 if test -n "$GENERATE_SHLIB_SCRIPT" ; then
-echo '  ; else if (link_info.shared) return'              >> e${EMULATION_NAME}.c
-sed $sc ldscripts/${EMULATION_NAME}.xs                     >> e${EMULATION_NAME}.c
+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
+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
 fi
-
-echo '  ; else return'                                     >> e${EMULATION_NAME}.c
-sed $sc ldscripts/${EMULATION_NAME}.x                      >> e${EMULATION_NAME}.c
-echo '; }'                                                 >> e${EMULATION_NAME}.c
+echo '  ; else if (link_info.shared) return'          >> e${EMULATION_NAME}.c
+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
+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
+fi
+echo '  ; else return'                                 >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.x                  >> e${EMULATION_NAME}.c
+echo '; }'                                             >> e${EMULATION_NAME}.c
 
 else
 # Scripts read from the filesystem.
@@ -1230,16 +1501,60 @@ cat >>e${EMULATION_NAME}.c <<EOF
 {
   *isfile = 1;
 
-  if (link_info.relocateable == true && config.build_constructors == true)
+  if (link_info.relocatable && config.build_constructors)
     return "ldscripts/${EMULATION_NAME}.xu";
-  else if (link_info.relocateable == true)
+  else if (link_info.relocatable)
     return "ldscripts/${EMULATION_NAME}.xr";
   else if (!config.text_read_only)
     return "ldscripts/${EMULATION_NAME}.xbn";
+EOF
+if cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then :
+else
+cat >>e${EMULATION_NAME}.c <<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
+  else if (link_info.pie && link_info.combreloc
+          && link_info.relro && (link_info.flags & DT_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
+  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
+  else if (link_info.shared && link_info.combreloc
+          && link_info.relro && (link_info.flags & DT_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
   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
+  else if (link_info.combreloc && link_info.relro
+          && (link_info.flags & DT_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
   else
     return "ldscripts/${EMULATION_NAME}.x";
 }
@@ -1250,8 +1565,6 @@ fi
 
 if test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then
 
-if test x"$LDEMUL_PARSE_ARGS" != xgld_"$EMULATION_NAME"_parse_args; then
-
 if test -n "$PARSE_AND_LIST_PROLOGUE" ; then
 cat >>e${EMULATION_NAME}.c <<EOF
  $PARSE_AND_LIST_PROLOGUE
@@ -1260,77 +1573,75 @@ fi
 
 cat >>e${EMULATION_NAME}.c <<EOF
 
-#include "getopt.h"
-
 #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)
 
-static struct option longopts[] =
+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 struct option xtra_long[] = {
 EOF
 
 if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
 cat >>e${EMULATION_NAME}.c <<EOF
-  /* getopt allows abbreviations, so we do this to stop it from
-     treating -d/-e as abbreviations for these options. */
-  {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
-  {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
-  {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
-  {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
+    {"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},
+    {"Bgroup", no_argument, NULL, OPTION_GROUP},
 EOF
 fi
 
 if test -n "$PARSE_AND_LIST_LONGOPTS" ; then
 cat >>e${EMULATION_NAME}.c <<EOF
- $PARSE_AND_LIST_LONGOPTS
   $PARSE_AND_LIST_LONGOPTS
 EOF
 fi
 
 cat >>e${EMULATION_NAME}.c <<EOF
-  {NULL, no_argument, NULL, 0}
-};
-
-
-static int gld_${EMULATION_NAME}_parse_args PARAMS ((int, char **));
+    {NULL, no_argument, NULL, 0}
+  };
+
+  *shortopts = (char *) xrealloc (*shortopts, ns + sizeof (xtra_short));
+  memcpy (*shortopts + ns, &xtra_short, sizeof (xtra_short));
+  *longopts = (struct option *)
+    xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
+  memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
+}
 
-static int
-gld_${EMULATION_NAME}_parse_args (argc, argv)
-     int argc;
-     char ** argv;
+static bfd_boolean
+gld${EMULATION_NAME}_handle_option (int optc)
 {
-  int longind, optc;
-  int prevoptind = optind;
-  int prevopterr = opterr;
-  int wanterror;
-  static int lastoptind = -1;
-
-  if (lastoptind != optind)
-    opterr = 0;
-
-  wanterror  = opterr;
-  optc = getopt_long_only (argc, argv,
-                          "-${PARSE_AND_LIST_SHORTOPTS}z:", longopts,
-                          &longind);
-  opterr = prevopterr;
-
   switch (optc)
     {
     default:
-      if (wanterror)
-       xexit (1);
-      optind =  prevoptind;
-      return 0;
+      return FALSE;
 
 EOF
 
 if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
 cat >>e${EMULATION_NAME}.c <<EOF
     case OPTION_DISABLE_NEW_DTAGS:
-      link_info.new_dtags = false;
+      link_info.new_dtags = FALSE;
       break;
 
     case OPTION_ENABLE_NEW_DTAGS:
-      link_info.new_dtags = true;
+      link_info.new_dtags = TRUE;
+      break;
+
+    case OPTION_EH_FRAME_HDR:
+      link_info.eh_frame_hdr = TRUE;
+      break;
+
+    case OPTION_GROUP:
+      link_info.flags_1 |= (bfd_vma) DF_1_GROUP;
+      /* Groups must be self-contained.  */
+      link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
+      link_info.unresolved_syms_in_shared_libs = RM_GENERATE_ERROR;
       break;
 
     case 'z':
@@ -1358,6 +1669,30 @@ cat >>e${EMULATION_NAME}.c <<EOF
          link_info.flags |= (bfd_vma) DF_ORIGIN;
          link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN;
        }
+      else if (strcmp (optarg, "defs") == 0)
+       link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
+      else if (strcmp (optarg, "muldefs") == 0)
+       link_info.allow_multiple_definition = TRUE;
+      else if (strcmp (optarg, "combreloc") == 0)
+       link_info.combreloc = TRUE;
+      else if (strcmp (optarg, "nocombreloc") == 0)
+       link_info.combreloc = FALSE;
+      else if (strcmp (optarg, "nocopyreloc") == 0)
+       link_info.nocopyreloc = TRUE;
+      else if (strcmp (optarg, "execstack") == 0)
+       {
+         link_info.execstack = TRUE;
+         link_info.noexecstack = FALSE;
+       }
+      else if (strcmp (optarg, "noexecstack") == 0)
+       {
+         link_info.noexecstack = TRUE;
+         link_info.execstack = FALSE;
+       }
+      else if (strcmp (optarg, "relro") == 0)
+       link_info.relro = TRUE;
+      else if (strcmp (optarg, "norelro") == 0)
+       link_info.relro = FALSE;
       /* What about the other Solaris -z options? FIXME.  */
       break;
 EOF
@@ -1372,37 +1707,43 @@ fi
 cat >>e${EMULATION_NAME}.c <<EOF
     }
 
-  return 1;
+  return TRUE;
 }
 
 EOF
-fi
 
-if test x"$LDEMUL_LIST_OPTIONS" != xgld_"$EMULATION_NAME"_list_options; then
+if test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
 cat >>e${EMULATION_NAME}.c <<EOF
 
-static void gld_${EMULATION_NAME}_list_options PARAMS ((FILE * file));
-
 static void
-gld_${EMULATION_NAME}_list_options (file)
-     FILE * file;
+gld${EMULATION_NAME}_list_options (FILE * file)
 {
 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, _("  -z initfirst\t\tMark DSO to be initialized first at rutime\n"));
-  fprintf (file, _("  -z interpose\t\tMark object to interpose all DSOs but execuable\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 availale to dlopen\n"));
-  fprintf (file, _("  -z nodump\t\tMark DSO not availale to dldump\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"));
-  fprintf (file, _("\t\t\t  at runtime\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"));
 EOF
 fi
@@ -1424,14 +1765,13 @@ EOF
 fi
 fi
 else
-if test x"$LDEMUL_PARSE_ARGS" != xgld_"$EMULATION_NAME"_parse_args; then
 cat >>e${EMULATION_NAME}.c <<EOF
-#define gld_${EMULATION_NAME}_parse_args   NULL
+#define gld${EMULATION_NAME}_add_options NULL
+#define gld${EMULATION_NAME}_handle_option NULL
 EOF
-fi
-if test x"$LDEMUL_LIST_OPTIONS" != xgld_"$EMULATION_NAME"_list_options; then
+if test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
 cat >>e${EMULATION_NAME}.c <<EOF
-#define gld_${EMULATION_NAME}_list_options NULL
+#define gld${EMULATION_NAME}_list_options NULL
 EOF
 fi
 fi
@@ -1452,15 +1792,18 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
   "${EMULATION_NAME}",
   "${OUTPUT_FORMAT}",
-  ${LDEMUL_FINISH-NULL},
+  ${LDEMUL_FINISH-gld${EMULATION_NAME}_finish},
   ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
   ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
   ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
   ${LDEMUL_SET_SYMBOLS-NULL},
-  ${LDEMUL_PARSE_ARGS-gld_${EMULATION_NAME}_parse_args},
+  ${LDEMUL_PARSE_ARGS-NULL},
+  gld${EMULATION_NAME}_add_options,
+  gld${EMULATION_NAME}_handle_option,
   ${LDEMUL_UNRECOGNIZED_FILE-NULL},
-  ${LDEMUL_LIST_OPTIONS-gld_${EMULATION_NAME}_list_options},
-  ${LDEMUL_RECOGNIZED_FILE-NULL},
+  ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
+  ${LDEMUL_RECOGNIZED_FILE-gld${EMULATION_NAME}_load_symbols},
   ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
+  ${LDEMUL_NEW_VERS_PATTERN-NULL}
 };
 EOF
This page took 0.06043 seconds and 4 git commands to generate.