Locale changes from Bruno Haible <haible@clisp.cons.org>.
[deliverable/binutils-gdb.git] / ld / emultempl / elf32.em
index 717f931114ceca81213e6a6001378fcad8d3f7a1..f2011cece4b355814363b6d220e8e36da69d44aa 100644 (file)
@@ -3,11 +3,16 @@
 # 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
+   Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
    Free Software Foundation, Inc.
    Written by Steve Chamberlain <sac@cygnus.com>
    ELF support by Ian Lance Taylor <ian@cygnus.com>
@@ -32,8 +37,8 @@ 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 "bfdlink.h"
 
@@ -47,27 +52,36 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "ldgram.h"
 #include "elf/common.h"
 
-static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
+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}_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}_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 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 lang_output_section_statement_type *output_rel_find
+  PARAMS ((void));
+static asection *output_prev_sec_find
+  PARAMS ((lang_output_section_statement_type *));
 static boolean gld${EMULATION_NAME}_place_orphan
   PARAMS ((lang_input_statement_type *, asection *));
-static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
+static char *gld${EMULATION_NAME}_get_script
+  PARAMS ((int *isfile));
 
 EOF
 
@@ -77,7 +91,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
@@ -89,7 +103,15 @@ cat >>e${EMULATION_NAME}.c <<EOF
 static void
 gld${EMULATION_NAME}_before_parse ()
 {
-  ldfile_output_architecture = bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`;
+  const bfd_arch_info_type *arch = bfd_scan_arch ("${OUTPUT_ARCH}");
+  if (arch)
+    {
+      ldfile_output_architecture = arch->arch;
+      ldfile_output_machine = arch->mach;
+      ldfile_output_machine_name = arch->printable_name;
+    }
+  else
+    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`;
 }
@@ -123,14 +145,14 @@ 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;
 {
-  const char *soname, *f;
+  const char *soname;
   struct bfd_link_needed_list *l;
 
   if (global_vercheck_failed)
@@ -141,19 +163,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 = basename (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,7 +184,7 @@ 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
@@ -192,7 +208,6 @@ gld${EMULATION_NAME}_stat_needed (s)
   struct stat st;
   const char *suffix;
   const char *soname;
-  const char *f;
 
   if (global_found)
     return;
@@ -216,7 +231,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 +245,11 @@ gld${EMULATION_NAME}_stat_needed (s)
 
   soname = bfd_elf_get_dt_soname (s->the_bfd);
   if (soname == NULL)
-    soname = s->filename;
-
-  f = strrchr (soname, '/');
-  if (f != NULL)
-    ++f;
-  else
-    f = soname;
+    soname = basename (s->filename);
 
-  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);
 }
 
 
@@ -261,12 +270,12 @@ gld${EMULATION_NAME}_try_needed (name, force)
     return false;
   if (! bfd_check_format (abfd, bfd_object))
     {
-      (void) bfd_close (abfd);
+      bfd_close (abfd);
       return false;
     }
   if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
     {
-      (void) bfd_close (abfd);
+      bfd_close (abfd);
       return false;
     }
 
@@ -289,7 +298,7 @@ gld${EMULATION_NAME}_try_needed (name, force)
          lang_for_each_input_file (gld${EMULATION_NAME}_vercheck);
          if (global_vercheck_failed)
            {
-             (void) bfd_close (abfd);
+             bfd_close (abfd);
              /* Return false to force the caller to move on to try
                  another file on the search path.  */
              return false;
@@ -314,7 +323,7 @@ case ${target} in
                break;
            if (l == NULL)
              {
-               (void) bfd_close (abfd);
+               bfd_close (abfd);
                return false;
              }
          }
@@ -340,11 +349,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
     einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd);
 
   /* First strip off everything before the last '/'.  */
-  soname = strrchr (abfd->filename, '/');
-  if (soname)
-    soname++;
-  else
-    soname = abfd->filename;
+  soname = basename (abfd->filename);
 
   if (trace_file_tries)
     info_msg (_("found %s at %s\n"), soname, name);
@@ -362,6 +367,9 @@ cat >>e${EMULATION_NAME}.c <<EOF
      DT_NEEDED entry for this file.  */
   bfd_elf_set_dt_needed_name (abfd, "");
 
+  /* Previos basename call was clobbered in lang_for_each_input_file.  */
+  soname = basename (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.  */
@@ -386,6 +394,9 @@ gld${EMULATION_NAME}_search_needed (path, name, 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;
   len = strlen (name);
@@ -425,11 +436,13 @@ EOF
 if [ "x${host}" = "x${target}" ] ; then
   case " ${EMULATION_LIBPATH} " in
   *" ${EMULATION_NAME} "*)
-cat >>e${EMULATION_NAME}.c <<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.  */
+   only meaningful on Linux.  */
 
 static boolean gld${EMULATION_NAME}_check_ld_so_conf
   PARAMS ((const char *, int));
@@ -509,7 +522,9 @@ gld${EMULATION_NAME}_check_ld_so_conf (name, force)
 }
 
 EOF
-  ;;
+       # Linux
+       ;;
+    esac
   esac
 fi
 cat >>e${EMULATION_NAME}.c <<EOF
@@ -523,11 +538,26 @@ gld${EMULATION_NAME}_check_needed (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)
@@ -542,21 +572,6 @@ gld${EMULATION_NAME}_check_needed (s)
          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;
-         return;
-       }
-    }
 }
 
 EOF
@@ -695,10 +710,15 @@ EOF
 if [ "x${host}" = "x${target}" ] ; then
   case " ${EMULATION_LIBPATH} " in
   *" ${EMULATION_NAME} "*)
-cat >>e${EMULATION_NAME}.c <<EOF
+    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
   ;;
   esac
 fi
@@ -792,6 +812,18 @@ 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
@@ -815,11 +847,11 @@ gld${EMULATION_NAME}_before_allocation ()
     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,
+         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)
@@ -937,20 +969,13 @@ 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.
+        filename we recorded earlier.  */
 
-        First strip off everything before the last '/'.  */
-      filename = strrchr (entry->filename, '/');
-      filename++;
-
-      needed_name = (char *) xmalloc (strlen (filename) + 1);
-      strcpy (needed_name, filename);
-      bfd_elf_set_dt_needed_name (entry->the_bfd, needed_name);
+      filename = xstrdup (basename (entry->filename));
+      bfd_elf_set_dt_needed_name (entry->the_bfd, filename);
     }
 
   return true;
@@ -958,6 +983,8 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
 
 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.  */
@@ -983,10 +1010,31 @@ output_rel_find ()
   return (lang_output_section_statement_type *) NULL;
 }
 
-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 (os)
+     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.  */
@@ -1008,9 +1056,10 @@ 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 = NULL;
+  lang_statement_list_type *old;
   lang_statement_list_type add;
   etree_type *address;
   const char *secname;
@@ -1020,18 +1069,19 @@ gld${EMULATION_NAME}_place_orphan (file, s)
 
   secname = bfd_get_section_name (s->owner, s);
 
-  if (! config.unique_orphan_sections)
+  if (! config.unique_orphan_sections && ! unique_section_p (secname))
     {
-      /* Look through the script to see where to place this section.  */ 
+      /* 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)
+         && (os->bfd_section == NULL
+             || ((s->flags ^ os->bfd_section->flags)
+                 & (SEC_LOAD | SEC_ALLOC)) == 0))
        {
-         /* We have already placed a section with this name.  */
-         wild_doit (&os->children, s, os, file);
+         /* 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;
        }
     }
@@ -1046,7 +1096,7 @@ gld${EMULATION_NAME}_place_orphan (file, s)
       && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
       && hold_text.os != NULL)
     {
-      wild_doit (&hold_text.os->children, s, hold_text.os, file);
+      lang_add_section (&hold_text.os->children, s, hold_text.os, file);
       return true;
     }
 
@@ -1059,57 +1109,93 @@ gld${EMULATION_NAME}_place_orphan (file, s)
 (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->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
           && (hold_rel.os != NULL
               || (hold_rel.os = output_rel_find ()) != NULL))
-    place = &hold_rel;
-  else if ((s->flags & SEC_CODE) == 0
-          && (s->flags & SEC_READONLY) != 0
+    {
+      if (! link_info.relocateable && link_info.combreloc)
+       {
+         if (strncmp (secname, ".rela", 5) == 0)
+           os = lang_output_section_find (".rela.dyn");
+         else
+           os = lang_output_section_find (".rel.dyn");
+
+         if (os != NULL
+             && os->bfd_section != NULL
+             && ((s->flags ^ os->bfd_section->flags)
+                 & (SEC_LOAD | SEC_ALLOC)) == 0)
+           {
+             lang_add_section (&os->children, s, os, file);
+             return true;
+           }
+       }
+      place = &hold_rel;
+    }
+  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.  */
+     loadable or allocatable characteristics.  */
   outsecname = secname;
   if (bfd_get_section_by_name (output_bfd, outsecname) != NULL)
-    outsecname = bfd_get_unique_section_name (output_bfd,
-                                             outsecname,
-                                             &count);
+    {
+      outsecname = bfd_get_unique_section_name (output_bfd,
+                                               outsecname,
+                                               &count);
+      if (outsecname == 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 != '_')
+       if (! ISALNUM (*ps) && *ps != '_')
          break;
-      if (*ps == '\0' && config.build_constructors)
+      if (*ps == '\0')
        {
          char *symname;
          etree_type *e_align;
@@ -1133,52 +1219,55 @@ gld${EMULATION_NAME}_place_orphan (file, s)
                                            (etree_type *) NULL,
                                            (etree_type *) NULL);
 
-  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*");
 
+  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 - outsecname + sizeof "__stop_");
+      sprintf (symname, "__stop_%s", outsecname);
+      lang_add_assignment (exp_assop ('=', symname,
+                                     exp_nameop (NAME, ".")));
+    }
+
+  /* Restore the global list pointer.  */
+  stat_ptr = old;
+
   if (place != 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->section != NULL
-         || (place->os->bfd_section != NULL
-             && place->os->bfd_section != snew))
+      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.  */
          for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
            ;
@@ -1188,21 +1277,43 @@ gld${EMULATION_NAME}_place_orphan (file, s)
          snew->next = *place->section;
          *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;
+         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
+           {
+             /* 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;
        }
-      place->stmt = add.tail;          /* Save the end of this list.  */
     }
 
   return true;
@@ -1238,14 +1349,18 @@ echo '  ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}
 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
 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_SHLIB_SCRIPT" ; then
+echo '  ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xsc                    >> 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
-
+echo '  ; else if (link_info.combreloc) return'            >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xc                     >> e${EMULATION_NAME}.c
 echo '  ; else return'                                     >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.x                      >> e${EMULATION_NAME}.c
 echo '; }'                                                 >> e${EMULATION_NAME}.c
@@ -1291,6 +1406,7 @@ cat >>e${EMULATION_NAME}.c <<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)
 
 static struct option longopts[] =
 {
@@ -1304,6 +1420,8 @@ cat >>e${EMULATION_NAME}.c <<EOF
   {"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},
+  {"Bgroup", no_argument, NULL, OPTION_GROUP},
+  {"Bgroup", no_argument, NULL, OPTION_GROUP},
 EOF
 fi
 
@@ -1362,6 +1480,12 @@ cat >>e${EMULATION_NAME}.c <<EOF
       link_info.new_dtags = true;
       break;
 
+    case OPTION_GROUP:
+      link_info.flags_1 |= (bfd_vma) DF_1_GROUP;
+      /* Groups must be self-contained.  */
+      link_info.no_undefined = true;
+      break;
+
     case 'z':
       if (strcmp (optarg, "initfirst") == 0)
        link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
@@ -1387,6 +1511,12 @@ 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.no_undefined = true;
+      else if (strcmp (optarg, "combreloc") == 0)
+       link_info.combreloc = true;
+      else if (strcmp (optarg, "nocombreloc") == 0)
+       link_info.combreloc = false;
       /* What about the other Solaris -z options? FIXME.  */
       break;
 EOF
@@ -1420,15 +1550,17 @@ 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, _("  -z defs\t\tDisallows undefined symbols\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 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 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"));
This page took 0.042559 seconds and 4 git commands to generate.