bfd/
[deliverable/binutils-gdb.git] / ld / emultempl / elf32.em
index 6273f0e90c81a824a6da1da33e687a784979207f..e43c8c5a8305bda13b3958c486ece65e1a46204c 100644 (file)
@@ -13,7 +13,7 @@ cat >e${EMULATION_NAME}.c <<EOF
 
 /* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
    Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004 Free Software Foundation, Inc.
+   2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    Written by Steve Chamberlain <sac@cygnus.com>
    ELF support by Ian Lance Taylor <ian@cygnus.com>
 
@@ -31,10 +31,11 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 #define TARGET_IS_${EMULATION_NAME}
 
+#include "config.h"
 #include "bfd.h"
 #include "sysdep.h"
 #include "libiberty.h"
@@ -56,18 +57,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 /* 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}_provide_init_fini_syms (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);
+static void gld${EMULATION_NAME}_layout_sections_again (void);
+static void gld${EMULATION_NAME}_finish (void) ATTRIBUTE_UNUSED;
 
 EOF
 
 if [ "x${USE_LIBPATH}" = xyes ] ; then
   case ${target} in
-    *-*-linux-gnu*)
+    *-*-linux-* | *-*-k*bsd*-*)
   cat >>e${EMULATION_NAME}.c <<EOF
+#ifdef HAVE_GLOB
 #include <glob.h>
+#endif
 EOF
     ;;
   esac
@@ -224,6 +229,9 @@ gld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s)
     return;
   if (s->the_bfd == NULL)
     return;
+  if (s->as_needed
+      && (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0)
+    return;
 
   if (bfd_stat (s->the_bfd, &st) != 0)
     {
@@ -231,8 +239,16 @@ gld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s)
       return;
     }
 
+  /* Some operating systems, e.g. Windows, do not provide a meaningful
+     st_ino; they always set it to zero.  (Windows does provide a
+     meaningful st_dev.)  Do not indicate a duplicate library in that
+     case.  While there is no guarantee that a system that provides
+     meaningful inode numbers will never set st_ino to zero, this is
+     merely an optimization, so we do not need to worry about false
+     negatives.  */
   if (st.st_dev == global_stat.st_dev
-      && st.st_ino == global_stat.st_ino)
+      && st.st_ino == global_stat.st_ino
+      && st.st_ino != 0)
     {
       global_found = TRUE;
       return;
@@ -337,7 +353,7 @@ gld${EMULATION_NAME}_try_needed (struct dt_needed *needed,
 
 EOF
 case ${target} in
-  *-*-linux-gnu*)
+  *-*-linux-* | *-*-k*bsd*-*)
     cat >>e${EMULATION_NAME}.c <<EOF
          {
            struct bfd_link_needed_list *l;
@@ -398,9 +414,8 @@ cat >>e${EMULATION_NAME}.c <<EOF
   /* Tell the ELF linker that we don't want the output file to have a
      DT_NEEDED entry for this file at all if the entry is from a file
      with DYN_NO_ADD_NEEDED.  */
-  if (needed->by
-      && (bfd_elf_get_dyn_lib_class (needed->by)
-         & DYN_NO_ADD_NEEDED) != 0)
+  if (needed->by != NULL
+      && (bfd_elf_get_dyn_lib_class (needed->by) & DYN_NO_ADD_NEEDED) != 0)
     class |= DYN_NO_NEEDED | DYN_NO_ADD_NEEDED;
 
   bfd_elf_set_dyn_lib_class (abfd, class);
@@ -510,7 +525,7 @@ gld${EMULATION_NAME}_add_sysroot (const char *path)
 
 EOF
   case ${target} in
-    *-*-linux-gnu*)
+    *-*-linux-* | *-*-k*bsd*-*)
       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
@@ -532,7 +547,9 @@ gld${EMULATION_NAME}_parse_ld_so_conf_include
       const char *pattern)
 {
   char *newp = NULL;
+#ifdef HAVE_GLOB
   glob_t gl;
+#endif
 
   if (pattern[0] != '/')
     {
@@ -545,6 +562,7 @@ gld${EMULATION_NAME}_parse_ld_so_conf_include
       pattern = newp;
     }
 
+#ifdef HAVE_GLOB
   if (glob (pattern, 0, NULL, &gl) == 0)
     {
       size_t i;
@@ -553,6 +571,10 @@ gld${EMULATION_NAME}_parse_ld_so_conf_include
        gld${EMULATION_NAME}_parse_ld_so_conf (info, gl.gl_pathv[i]);
       globfree (&gl);
     }
+#else
+  /* If we do not have glob, treat the pattern as a literal filename.  */
+  gld${EMULATION_NAME}_parse_ld_so_conf (info, pattern);
+#endif
 
   if (newp)
     free (newp);
@@ -717,6 +739,13 @@ gld${EMULATION_NAME}_check_needed (lang_input_statement_type *s)
   if (global_found)
     return;
 
+  /* If this input file was an as-needed entry, and wasn't found to be
+     needed at the stage it was linked, then don't say we have loaded it.  */
+  if (s->as_needed
+      && (s->the_bfd == NULL
+         || (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0))
+    return;
+
   if (s->filename != NULL)
     {
       const char *f;
@@ -785,9 +814,17 @@ gld${EMULATION_NAME}_after_open (void)
       struct dt_needed n, nn;
       int force;
 
+      /* If the lib that needs this one was --as-needed and wasn't
+        found to be needed, then this lib isn't needed either.  */
+      if (l->by != NULL
+         && (bfd_elf_get_dyn_lib_class (l->by) & DYN_AS_NEEDED) != 0)
+       continue;
+
       /* If we've already seen this file, skip it.  */
       for (ll = needed; ll != l; ll = ll->next)
-       if (strcmp (ll->name, l->name) == 0)
+       if ((ll->by == NULL
+            || (bfd_elf_get_dyn_lib_class (ll->by) & DYN_AS_NEEDED) == 0)
+           && strcmp (ll->name, l->name) == 0)
          break;
       if (ll != l)
        continue;
@@ -821,9 +858,13 @@ gld${EMULATION_NAME}_after_open (void)
          size_t len;
          search_dirs_type *search;
 EOF
-if [ "x${USE_LIBPATH}" = xyes ] ; then
+if [ "x${NATIVE}" = xyes ] ; then
 cat >>e${EMULATION_NAME}.c <<EOF
          const char *lib_path;
+EOF
+fi
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+cat >>e${EMULATION_NAME}.c <<EOF
          struct bfd_link_needed_list *rp;
          int found;
 EOF
@@ -894,7 +935,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
 EOF
 if [ "x${USE_LIBPATH}" = xyes ] ; then
   case ${target} in
-    *-*-linux-gnu*)
+    *-*-linux-* | *-*-k*bsd*-*)
       cat >>e${EMULATION_NAME}.c <<EOF
          if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
            break;
@@ -924,16 +965,14 @@ cat >>e${EMULATION_NAME}.c <<EOF
 static void
 gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp)
 {
-  struct bfd_link_hash_entry *h;
+  bfd_boolean provide = FALSE;
 
   switch (exp->type.node_class)
     {
     case etree_provide:
-      h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst,
-                               FALSE, FALSE, FALSE);
-      if (h == NULL)
-       break;
-
+      provide = TRUE;
+      /* Fall thru */
+    case etree_assign:
       /* We call record_link_assignment even if the symbol is defined.
         This is because if it is defined by a dynamic object, we
         actually want to use the value defined by the linker script,
@@ -941,14 +980,10 @@ gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp)
         symbols like etext).  If the symbol is defined by a regular
         object, then, as it happens, calling record_link_assignment
         will do no harm.  */
-
-      /* Fall through.  */
-    case etree_assign:
       if (strcmp (exp->assign.dst, ".") != 0)
        {
-         if (! (bfd_elf_record_link_assignment
-                (output_bfd, &link_info, exp->assign.dst,
-                 exp->type.node_class == etree_provide ? TRUE : FALSE)))
+         if (!bfd_elf_record_link_assignment (&link_info, exp->assign.dst,
+                                              provide))
            einfo ("%P%F: failed to record assignment to %s: %E\n",
                   exp->assign.dst);
        }
@@ -995,8 +1030,8 @@ if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation;
     ELF_INTERPRETER_SET_DEFAULT="
   if (sinterp != NULL)
     {
-      sinterp->contents = ${ELF_INTERPRETER_NAME};
-      sinterp->size = strlen (sinterp->contents) + 1;
+      sinterp->contents = (unsigned char *) ${ELF_INTERPRETER_NAME};
+      sinterp->size = strlen ((char *) sinterp->contents) + 1;
     }
 
 "
@@ -1005,6 +1040,47 @@ if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation;
   fi
 cat >>e${EMULATION_NAME}.c <<EOF
 
+static void
+gld${EMULATION_NAME}_provide_bound_symbols (const char *sec,
+                                           const char *start,
+                                           const char *end)
+{
+  asection *s = bfd_get_section_by_name (output_bfd, sec);
+  _bfd_elf_provide_section_bound_symbols (&link_info, s, start, end);
+}
+
+/* If not building a shared library, provide
+
+   __preinit_array_start
+   __preinit_array_end
+   __init_array_start
+   __init_array_end
+   __fini_array_start
+   __fini_array_end
+
+   They are set here rather than via PROVIDE in the linker
+   script, because using PROVIDE inside an output section
+   statement results in unnecessary output sections.  Using
+   PROVIDE outside an output section statement runs the risk of
+   section alignment affecting where the section starts.  */
+
+static void
+gld${EMULATION_NAME}_provide_init_fini_syms (void)
+{
+  if (!link_info.relocatable && link_info.executable)
+    {
+      gld${EMULATION_NAME}_provide_bound_symbols (".preinit_array",
+                                                 "__preinit_array_start",
+                                                 "__preinit_array_end");
+      gld${EMULATION_NAME}_provide_bound_symbols (".init_array",
+                                                 "__init_array_start",
+                                                 "__init_array_end");
+      gld${EMULATION_NAME}_provide_bound_symbols (".fini_array",
+                                                 "__fini_array_start",
+                                                 "__fini_array_end");
+    }
+}
+
 /* This is called after the sections have been attached to output
    sections, but before any sizes or addresses have been set.  */
 
@@ -1022,6 +1098,8 @@ gld${EMULATION_NAME}_before_allocation (void)
      referred to by dynamic objects.  */
   lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
 
+  ldemul_do_assignments ();
+
   /* Let the ELF backend work out the sizes of any sections required
      by dynamic linking.  */
   rpath = command_line.rpath;
@@ -1033,6 +1111,7 @@ gld${EMULATION_NAME}_before_allocation (void)
          (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
@@ -1083,8 +1162,17 @@ ${ELF_INTERPRETER_SET_DEFAULT}
        /* Clobber the section size, so that we don't waste copying the
           warning into the output file.  */
        s->size = 0;
+
+       /* Also set SEC_EXCLUDE, so that symbols defined in the warning
+          section don't get copied to the output.  */
+       s->flags |= SEC_EXCLUDE;
       }
   }
+
+  before_allocation_default ();
+
+  if (!bfd_elf_size_dynsym_hash_dynstr (output_bfd, &link_info))
+    einfo ("%P%F: failed to set dynamic section sizes: %E\n");
 }
 
 EOF
@@ -1172,12 +1260,11 @@ 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.  */
+/* A variant of lang_output_section_find used by place_orphan.  */
 
 static lang_output_section_statement_type *
 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;
@@ -1185,9 +1272,10 @@ output_rel_find (asection *sec, int isdyn)
   lang_output_section_statement_type *last_rel_alloc = NULL;
   int rela = sec->name[4] == 'a';
 
-  for (u = lang_output_section_statement.head; u; u = lookup->next)
+  for (lookup = &lang_output_section_statement.head->output_section_statement;
+       lookup != NULL;
+       lookup = lookup->next)
     {
-      lookup = &u->output_section_statement;
       if (lookup->constraint != -1
          && strncmp (".rel", lookup->name, 4) == 0)
        {
@@ -1229,63 +1317,52 @@ output_rel_find (asection *sec, int isdyn)
   return last;
 }
 
-/* Find the last output section before given output statement.
-   Used by place_orphan.  */
-
-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.  */
 
-struct orphan_save {
-  lang_output_section_statement_type *os;
-  asection **section;
-  lang_statement_union_type **stmt;
-  lang_statement_union_type **os_tail;
-};
-
 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;
-  static struct orphan_save hold_data;
-  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;
+  static struct orphan_save hold[] =
+    {
+      { ".text",
+       SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
+       0, 0, 0, 0 },
+      { ".rodata",
+       SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
+       0, 0, 0, 0 },
+      { ".data",
+       SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
+       0, 0, 0, 0 },
+      { ".bss",
+       SEC_ALLOC,
+       0, 0, 0, 0 },
+      { 0,
+       SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
+       0, 0, 0, 0 },
+      { ".interp",
+       SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
+       0, 0, 0, 0 },
+      { ".sdata",
+       SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_SMALL_DATA,
+       0, 0, 0, 0 }
+    };
+  enum orphan_save_index
+    {
+      orphan_text = 0,
+      orphan_rodata,
+      orphan_data,
+      orphan_bss,
+      orphan_rel,
+      orphan_interp,
+      orphan_sdata
+    };
+  static int orphan_init_done = 0;
   struct orphan_save *place;
-  lang_statement_list_type *old;
-  lang_statement_list_type add;
-  etree_type *address;
   const char *secname;
-  const char *ps = NULL;
+  lang_output_section_statement_type *after;
   lang_output_section_statement_type *os;
-  lang_statement_union_type **os_tail;
-  etree_type *load_base;
   int isdyn = 0;
-  asection *sec;
 
   secname = bfd_get_section_name (s->owner, s);
 
@@ -1308,27 +1385,42 @@ gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
 
       if (os != NULL
          && (os->bfd_section == NULL
+             || os->bfd_section->flags == 0
              || ((s->flags ^ os->bfd_section->flags)
                  & (SEC_LOAD | SEC_ALLOC)) == 0))
        {
          /* We already have an output section statement with this
-            name, and its bfd section, if any, has compatible flags.  */
+            name, and its bfd section, if any, has compatible flags.
+            If the section already exists but does not have any flags
+            set, then it has been created by the linker, probably as a
+            result of a --section-start command line switch.  */
          lang_add_section (&os->children, s, os, file);
          return TRUE;
        }
     }
 
-  if (hold_text.os == NULL)
-    hold_text.os = lang_output_section_find (".text");
+  if (!orphan_init_done)
+    {
+      struct orphan_save *ho;
+      for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
+       if (ho->name != NULL)
+         {
+           ho->os = lang_output_section_find (ho->name);
+           if (ho->os != NULL && ho->os->flags == 0)
+             ho->os->flags = ho->flags;
+         }
+      orphan_init_done = 1;
+    }
 
   /* 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.executable
       && ! link_info.relocatable
       && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
-      && hold_text.os != NULL)
+      && hold[orphan_text].os != NULL)
     {
-      lang_add_section (&hold_text.os->children, s, hold_text.os, file);
+      lang_add_section (&hold[orphan_text].os->children, s,
+                       hold[orphan_text].os, file);
       return TRUE;
     }
 
@@ -1337,220 +1429,57 @@ gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
      right after the .interp section, so that the PT_NOTE segment is
      stored right after the program headers where the OS can read it
      in the first page.  */
-#define HAVE_SECTION(hold, name) \
-(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
 
   place = NULL;
   if ((s->flags & SEC_ALLOC) == 0)
     ;
   else if ((s->flags & SEC_LOAD) != 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;
+          && strncmp (secname, ".note", 5) == 0)
+    place = &hold[orphan_interp];
+  else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+    place = &hold[orphan_bss];
+  else if ((s->flags & SEC_SMALL_DATA) != 0)
+    place = &hold[orphan_sdata];
+  else if ((s->flags & SEC_READONLY) == 0)
+    place = &hold[orphan_data];
   else if (strncmp (secname, ".rel", 4) == 0
-          && (s->flags & SEC_LOAD) != 0
-          && (hold_rel.os != NULL
-              || (hold_rel.os = output_rel_find (s, isdyn)) != NULL))
-    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_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY)
-          && hold_text.os != NULL)
-    place = &hold_text;
-
-#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 allocatable characteristics.  But if the section
-     already exists but does not have any flags set, then it has been
-     created by the linker, probably as a result of a --section-start
-     command line switch.  */
-  if ((sec = bfd_get_section_by_name (output_bfd, secname)) != NULL
-      && bfd_get_section_flags (output_bfd, sec) != 0)
-    {
-      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;
+          && (s->flags & SEC_LOAD) != 0)
+    place = &hold[orphan_rel];
+  else if ((s->flags & SEC_CODE) == 0)
+    place = &hold[orphan_rodata];
+  else
+    place = &hold[orphan_text];
 
-  /* 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.  */
+  after = NULL;
   if (place != NULL)
     {
-      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 = secname; *ps != '\0'; ps++)
-       if (! ISALNUM (*ps) && *ps != '_')
-         break;
-      if (*ps == '\0')
+      if (place->os == NULL)
        {
-         char *symname;
-         etree_type *e_align;
-
-         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 (place->name != NULL)
+           place->os = lang_output_section_find (place->name);
+         else
+           place->os = output_rel_find (s, isdyn);
        }
+      after = place->os;
+      if (after == NULL)
+       after = lang_output_section_find_by_flags (s, &place->os);
+      if (after == NULL)
+       /* *ABS* is always the first output section statement.  */
+       after = &lang_output_section_statement.head->output_section_statement;
     }
 
-  address = NULL;
-  if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
-    address = exp_intop ((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,
-                                           load_base, 0);
-
-  lang_add_section (&os->children, s, os, file);
-
-  lang_leave_output_section_statement
-    ((bfd_vma) 0, "*default*",
-     (struct lang_output_section_phdr_list *) NULL, NULL);
-
-  if (config.build_constructors && *ps == '\0')
+  /* Choose a unique name for the section.  This will be needed if the
+     same section name appears in the input file with different
+     loadable or allocatable characteristics.  */
+  if (bfd_get_section_by_name (output_bfd, secname) != NULL)
     {
-      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, ".")));
+      static int count = 1;
+      secname = bfd_get_unique_section_name (output_bfd, secname, &count);
+      if (secname == NULL)
+       einfo ("%F%P: place_orphan failed: %E\n");
     }
 
-  /* Restore the global list pointer.  */
-  stat_ptr = old;
-
-  if (place != NULL && os->bfd_section != NULL)
-    {
-      asection *snew, **pps;
-
-      snew = os->bfd_section;
-
-      /* Shuffle the bfd section list to make the output file look
-        neater.  This is really only cosmetic.  */
-      if (place->section == NULL)
-       {
-         asection *bfd_section = place->os->bfd_section;
-
-         /* 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;
-       }
-
-      if (place->section != NULL)
-       {
-         /* Unlink the section.  */
-         for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
-           ;
-         bfd_section_list_remove (output_bfd, pps);
-
-         /* Now tack it on to the "place->os" section list.  */
-         bfd_section_list_insert (output_bfd, place->section, snew);
-       }
-
-      /* 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)
-       {
-         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;
-       }
-    }
+  lang_insert_orphan (file, s, secname, after, place, NULL, NULL);
 
   return TRUE;
 }
@@ -1561,23 +1490,27 @@ if test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then
 cat >>e${EMULATION_NAME}.c <<EOF
 
 static void
-gld${EMULATION_NAME}_finish (void)
+gld${EMULATION_NAME}_layout_sections_again (void)
 {
-  if (bfd_elf_discard_info (output_bfd, &link_info))
-    {
-      lang_reset_memory_regions ();
+  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);
+  /* Resize the sections.  */
+  lang_size_sections (NULL, TRUE);
 
-      /* Redo special stuff.  */
-      ldemul_after_allocation ();
+  /* 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);
-    }
+  /* Do the assignments again.  */
+  lang_do_assignments ();
+}
+
+static void
+gld${EMULATION_NAME}_finish (void)
+{
+  if (bfd_elf_discard_info (output_bfd, &link_info))
+    gld${EMULATION_NAME}_layout_sections_again ();
+
+  finish_default ();
 }
 EOF
 fi
@@ -1603,49 +1536,49 @@ cat >>e${EMULATION_NAME}.c <<EOF
   if (link_info.relocatable && config.build_constructors)
     return
 EOF
-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
+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
+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
+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
+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
+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
 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
+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
+sed $sc ldscripts/${EMULATION_NAME}.xsc                        >> e${EMULATION_NAME}.c
 fi
-echo '  ; else if (link_info.shared) return'          >> e${EMULATION_NAME}.c
-sed $sc ldscripts/${EMULATION_NAME}.xs                 >> 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
+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
+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.
@@ -1730,7 +1663,8 @@ cat >>e${EMULATION_NAME}.c <<EOF
 #define OPTION_ENABLE_NEW_DTAGS                (OPTION_DISABLE_NEW_DTAGS + 1)
 #define OPTION_GROUP                   (OPTION_ENABLE_NEW_DTAGS + 1)
 #define OPTION_EH_FRAME_HDR            (OPTION_GROUP + 1)
-
+#define OPTION_EXCLUDE_LIBS            (OPTION_EH_FRAME_HDR + 1)
+  
 static void
 gld${EMULATION_NAME}_add_options
   (int ns, char **shortopts, int nl, struct option **longopts,
@@ -1745,6 +1679,7 @@ 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},
     {"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR},
+    {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
     {"Bgroup", no_argument, NULL, OPTION_GROUP},
 EOF
 fi
@@ -1797,6 +1732,10 @@ cat >>e${EMULATION_NAME}.c <<EOF
       link_info.unresolved_syms_in_shared_libs = RM_GENERATE_ERROR;
       break;
 
+    case OPTION_EXCLUDE_LIBS:
+      add_excluded_libs (optarg);
+      break;
+
     case 'z':
       if (strcmp (optarg, "initfirst") == 0)
        link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
@@ -1942,6 +1881,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
   ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
   ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation},
+  ${LDEMUL_DO_ASSIGNMENTS-gld${EMULATION_NAME}_provide_init_fini_syms},
   ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
   "${EMULATION_NAME}",
   "${OUTPUT_FORMAT}",
This page took 0.034952 seconds and 4 git commands to generate.