bfd/
[deliverable/binutils-gdb.git] / ld / emultempl / elf32.em
index c6bc7c2ea4edbe68572f0d7d90dc8da38ec00464..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
@@ -1402,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
@@ -1789,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.028436 seconds and 4 git commands to generate.