Locale changes from Bruno Haible <haible@clisp.cons.org>.
[deliverable/binutils-gdb.git] / ld / emultempl / elf32.em
index a305888c3eb7d1a9737de10e8c8c58d0b5ba7af5..f2011cece4b355814363b6d220e8e36da69d44aa 100644 (file)
@@ -38,8 +38,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "bfd.h"
 #include "sysdep.h"
 #include "libiberty.h"
-
-#include <ctype.h>
+#include "safe-ctype.h"
 
 #include "bfdlink.h"
 
@@ -53,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
 
@@ -239,8 +247,7 @@ gld${EMULATION_NAME}_stat_needed (s)
   if (soname == NULL)
     soname = basename (s->filename);
 
-  if (strncmp (soname, 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, soname);
 }
@@ -263,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;
     }
 
@@ -291,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;
@@ -316,7 +323,7 @@ case ${target} in
                break;
            if (l == NULL)
              {
-               (void) bfd_close (abfd);
+               bfd_close (abfd);
                return false;
              }
          }
@@ -976,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.  */
@@ -1001,11 +1010,6 @@ output_rel_find ()
   return (lang_output_section_statement_type *) NULL;
 }
 
-EOF
-
-if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
-cat >>e${EMULATION_NAME}.c <<EOF
-
 /* Find the last output section before given output statement.
    Used by place_orphan.  */
 
@@ -1023,21 +1027,15 @@ output_prev_sec_find (os)
     {
       lookup = &u->output_section_statement;
       if (lookup == os)
-       break;
-      if (lookup->bfd_section != NULL
-          && lookup->bfd_section != bfd_abs_section_ptr
-          && lookup->bfd_section != bfd_com_section_ptr 
-          && lookup->bfd_section != bfd_und_section_ptr)
+       return s;
+
+      if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
        s = lookup->bfd_section;
     }
 
-  if (u == NULL)
-    return NULL;
-
-  return s;
+  return NULL;
 }
 
-
 /* Place an orphan section.  We use this to put random SHF_ALLOC
    sections in the right segment.  */
 
@@ -1077,12 +1075,13 @@ gld${EMULATION_NAME}_place_orphan (file, s)
       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;
        }
     }
@@ -1097,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;
     }
 
@@ -1110,7 +1109,11 @@ 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;
+    {
+      if (s->output_section == NULL)
+       s->output_section = bfd_abs_section_ptr;
+      return true;
+    }
 
   place = NULL;
   if ((s->flags & SEC_ALLOC) == 0)
@@ -1131,7 +1134,25 @@ gld${EMULATION_NAME}_place_orphan (file, s)
   else if (strncmp (secname, ".rel", 4) == 0
           && (hold_rel.os != NULL
               || (hold_rel.os = output_rel_find ()) != NULL))
-    place = &hold_rel;
+    {
+      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;
@@ -1172,7 +1193,7 @@ gld${EMULATION_NAME}_place_orphan (file, s)
       /* 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')
        {
@@ -1198,7 +1219,7 @@ 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*",
@@ -1224,36 +1245,29 @@ gld${EMULATION_NAME}_place_orphan (file, s)
 
   if (place != NULL)
     {
-      asection *snew, **pps, *bfd_section;
+      asection *snew, **pps;
 
       snew = os->bfd_section;
-      bfd_section = place->os->bfd_section;
-      if (place->section == NULL && bfd_section == NULL)
-       bfd_section = output_prev_sec_find (place->os);
 
-      if (place->section != NULL
-         || (bfd_section != NULL
-             && bfd_section != snew))
+      /* Shuffle the bfd section list to make the output file look
+        neater.  This is really only cosmetic.  */
+      if (place->section == NULL)
        {
-         /* Shuffle the section to make the output file look neater.
-            This is really only cosmetic.  */
-         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 = bfd_section->flags;
-             for (pps = &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 = &bfd_section->next;
-#endif
-           }
+         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)
            ;
@@ -1263,13 +1277,22 @@ gld${EMULATION_NAME}_place_orphan (file, s)
          snew->next = *place->section;
          *place->section = snew;
        }
-      place->section = &snew->next;    /* Save the end of this list.  */
 
+      /* 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)
        {
-         /* 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.  */
          if (place->stmt == NULL)
            {
              /* Put the new statement list right at the head.  */
@@ -1326,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
@@ -1486,6 +1513,10 @@ cat >>e${EMULATION_NAME}.c <<EOF
        }
       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
This page took 0.026924 seconds and 4 git commands to generate.