2002-03-18 David O'Brien <obrien@FreeBSD.org>
[deliverable/binutils-gdb.git] / ld / emultempl / elf32.em
index c1f5e31828e2da7ac38b41691e641808f40532b3..077a8fc0f32dbae3a41e32081a1004fcfb5cca94 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 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,38 @@ 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 void gld${EMULATION_NAME}_finish
+  PARAMS ((void));
+static char *gld${EMULATION_NAME}_get_script
+  PARAMS ((int *isfile));
 
 EOF
 
@@ -77,7 +93,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 +105,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 +147,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 +165,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,7 +186,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 +210,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 +233,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 +247,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);
 }
 
 
@@ -254,18 +265,19 @@ gld${EMULATION_NAME}_try_needed (name, force)
      int force;
 {
   bfd *abfd;
+  const char *soname;
 
   abfd = bfd_openr (name, bfd_get_target (output_bfd));
   if (abfd == NULL)
     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;
     }
 
@@ -288,7 +300,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;
@@ -313,7 +325,7 @@ case ${target} in
                break;
            if (l == NULL)
              {
-               (void) bfd_close (abfd);
+               bfd_close (abfd);
                return false;
              }
          }
@@ -337,6 +349,13 @@ cat >>e${EMULATION_NAME}.c <<EOF
 
   if (bfd_stat (abfd, &global_stat) != 0)
     einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd);
+
+  /* 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)
@@ -350,17 +369,10 @@ cat >>e${EMULATION_NAME}.c <<EOF
      DT_NEEDED entry for this file.  */
   bfd_elf_set_dt_needed_name (abfd, "");
 
-  /* 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);
+  bfd_elf_set_dt_needed_soname (abfd, soname);
 
   /* Add this file into the symbol table.  */
   if (! bfd_link_add_symbols (abfd, &link_info))
@@ -381,6 +393,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);
@@ -420,11 +435,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));
@@ -504,7 +521,9 @@ gld${EMULATION_NAME}_check_ld_so_conf (name, force)
 }
 
 EOF
-  ;;
+       # Linux
+       ;;
+    esac
   esac
 fi
 cat >>e${EMULATION_NAME}.c <<EOF
@@ -518,11 +537,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)
@@ -537,21 +571,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
@@ -599,25 +618,46 @@ gld${EMULATION_NAME}_after_open ()
       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${host}" = "x${target}" ] ; then
+  case " ${EMULATION_LIBPATH} " in
+  *" ${EMULATION_NAME} "*)
+cat >>e${EMULATION_NAME}.c <<EOF
+         const char *lib_path;
+         struct bfd_link_needed_list *rp;
+         int found;
+EOF
+  ;;
+  esac
+fi
+cat >>e${EMULATION_NAME}.c <<EOF
 
          if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
                                                  l->name, force))
            break;
+EOF
+if [ "x${host}" = "x${target}" ] ; then
+  case " ${EMULATION_LIBPATH} " in
+  *" ${EMULATION_NAME} "*)
+cat >>e${EMULATION_NAME}.c <<EOF
          if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
                                                  l->name, force))
            break;
@@ -629,14 +669,22 @@ 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;
+
+         found = 0;
+         rp = bfd_elf_get_runpath_list (output_bfd, &link_info);
+         for (; !found && rp != NULL; rp = rp->next)
+           {
+             found = (rp->by == l->by
+                      && gld${EMULATION_NAME}_search_needed (rp->name,
+                                                             l->name,
+                                                             force));
+           }
+         if (found)
+           break;
+
 EOF
   ;;
   esac
@@ -661,10 +709,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
@@ -758,6 +811,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
@@ -781,11 +846,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)
@@ -903,20 +968,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 = lbasename (entry->filename);
+      bfd_elf_set_dt_needed_name (entry->the_bfd, filename);
     }
 
   return true;
@@ -924,6 +982,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.  */
@@ -949,10 +1009,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.  */
@@ -974,26 +1055,34 @@ 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, *ps = NULL;
+  const char *secname;
   const char *outsecname;
+  const char *ps = NULL;
   lang_output_section_statement_type *os;
 
   secname = bfd_get_section_name (s->owner, s);
 
-  /* 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 (! config.unique_orphan_sections && ! unique_section_p (secname))
     {
-      /* 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)
@@ -1006,7 +1095,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;
     }
 
@@ -1019,72 +1108,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)
     {
-      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;
+      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;
@@ -1108,79 +1218,129 @@ 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->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)
+      /* 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 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;
+         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;
 }
+EOF
+fi
+
+if test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then
+cat >>e${EMULATION_NAME}.c <<EOF
+
+static void
+gld${EMULATION_NAME}_finish ()
+{
+  if (bfd_elf${ELFSIZE}_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);
 
+      /* 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
 
@@ -1211,14 +1371,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 : ; 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_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
@@ -1264,6 +1428,8 @@ 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)
+#define OPTION_EH_FRAME_HDR            (OPTION_GROUP + 1)
 
 static struct option longopts[] =
 {
@@ -1277,6 +1443,9 @@ 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},
+  {"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR},
+  {"Bgroup", no_argument, NULL, OPTION_GROUP},
+  {"Bgroup", no_argument, NULL, OPTION_GROUP},
 EOF
 fi
 
@@ -1335,6 +1504,16 @@ cat >>e${EMULATION_NAME}.c <<EOF
       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.no_undefined = true;
+      break;
+
     case 'z':
       if (strcmp (optarg, "initfirst") == 0)
        link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
@@ -1360,6 +1539,14 @@ 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;
+      else if (strcmp (optarg, "nocopyreloc") == 0)
+        link_info.nocopyreloc = true;
       /* What about the other Solaris -z options? FIXME.  */
       break;
 EOF
@@ -1393,18 +1580,23 @@ 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\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 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 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 KEYWORD\t\tIgnored for Solaris compatibility\n"));
 EOF
 fi
@@ -1454,7 +1646,7 @@ 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},
This page took 0.034259 seconds and 4 git commands to generate.