ld/
[deliverable/binutils-gdb.git] / ld / emultempl / elf32.em
index dffcff81b47081ffbef95edc038189e662af277c..28880084fa885b1b8d2a914c2761cf680f1f5da1 100644 (file)
@@ -60,8 +60,7 @@ static void gld${EMULATION_NAME}_before_parse (void);
 static void gld${EMULATION_NAME}_after_open (void);
 static void gld${EMULATION_NAME}_before_allocation (void);
 static bfd_boolean gld${EMULATION_NAME}_place_orphan (asection *s);
-static void gld${EMULATION_NAME}_layout_sections_again (void);
-static void gld${EMULATION_NAME}_finish (void) ATTRIBUTE_UNUSED;
+static void gld${EMULATION_NAME}_finish (void);
 
 EOF
 
@@ -79,6 +78,7 @@ fi
 
 # Import any needed special functions and/or overrides.
 #
+. ${srcdir}/emultempl/elf-generic.em
 if test -n "$EXTRA_EM_FILE" ; then
 . ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
 fi
@@ -148,7 +148,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
 
 static struct bfd_link_needed_list *global_needed;
 static struct stat global_stat;
-static bfd_boolean global_found;
+static lang_input_statement_type *global_found;
 static struct bfd_link_needed_list *global_vercheck_needed;
 static bfd_boolean global_vercheck_failed;
 
@@ -229,12 +229,14 @@ gld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s)
   const char *suffix;
   const char *soname;
 
-  if (global_found)
+  if (global_found != NULL)
     return;
   if (s->the_bfd == NULL)
     return;
-  if (s->as_needed
-      && (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0)
+
+  /* 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 ((bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0)
     return;
 
   if (bfd_stat (s->the_bfd, &st) != 0)
@@ -254,7 +256,7 @@ gld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s)
       && st.st_ino == global_stat.st_ino
       && st.st_ino != 0)
     {
-      global_found = TRUE;
+      global_found = s;
       return;
     }
 
@@ -363,7 +365,7 @@ case ${target} in
            struct bfd_link_needed_list *l;
 
            for (l = needed; l != NULL; l = l->next)
-             if (strncmp (l->name, "libc.so", 7) == 0)
+             if (CONST_STRNEQ (l->name, "libc.so"))
                break;
            if (l == NULL)
              {
@@ -398,9 +400,9 @@ cat >>e${EMULATION_NAME}.c <<EOF
   if (trace_file_tries)
     info_msg (_("found %s at %s\n"), soname, name);
 
-  global_found = FALSE;
+  global_found = NULL;
   lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed);
-  if (global_found)
+  if (global_found != NULL)
     {
       /* Return TRUE to indicate that we found the file, even though
         we aren't going to do anything with it.  */
@@ -569,7 +571,7 @@ gld${EMULATION_NAME}_check_ld_elf_hints (const char *name, int force)
                  if (fread (b, 1, hdr.dirlistlen + 1, f) ==
                      hdr.dirlistlen + 1)
                    ld_elf_hints = gld${EMULATION_NAME}_add_sysroot (b);
-               
+
                  free (b);
                }
            }
@@ -585,7 +587,7 @@ gld${EMULATION_NAME}_check_ld_elf_hints (const char *name, int force)
   needed.by = NULL;
   needed.name = name;
   return gld${EMULATION_NAME}_search_needed (ld_elf_hints, & needed,
-                                            force);
+                                            force);
 }
 EOF
     # FreeBSD
@@ -696,7 +698,7 @@ gld${EMULATION_NAME}_parse_ld_so_conf
       if (p[0] == '\0')
        continue;
 
-      if (!strncmp (p, "include", 7) && (p[7] == ' ' || p[7] == '\t'))
+      if (CONST_STRNEQ (p, "include") && (p[7] == ' ' || p[7] == '\t'))
        {
          char *dir, c;
          p += 8;
@@ -809,49 +811,45 @@ cat >>e${EMULATION_NAME}.c <<EOF
 static void
 gld${EMULATION_NAME}_check_needed (lang_input_statement_type *s)
 {
-  if (global_found)
+  const char *soname;
+
+  /* Stop looking if we've found a loaded lib.  */
+  if (global_found != NULL
+      && (bfd_elf_get_dyn_lib_class (global_found->the_bfd)
+         & DYN_AS_NEEDED) == 0)
     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))
+  if (s->filename == NULL || s->the_bfd == NULL)
     return;
 
-  if (s->filename != NULL)
+  /* Don't look for a second non-loaded as-needed lib.  */
+  if (global_found != NULL
+      && (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0)
+    return;
+
+  if (strcmp (s->filename, global_needed->name) == 0)
     {
-      const char *f;
+      global_found = s;
+      return;
+    }
 
-      if (strcmp (s->filename, global_needed->name) == 0)
+  if (s->search_dirs_flag)
+    {
+      const char *f = strrchr (s->filename, '/');
+      if (f != NULL
+         && strcmp (f + 1, global_needed->name) == 0)
        {
-         global_found = TRUE;
+         global_found = s;
          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)
+  soname = bfd_elf_get_dt_soname (s->the_bfd);
+  if (soname != NULL
+      && strcmp (soname, global_needed->name) == 0)
     {
-      const char *soname;
-
-      soname = bfd_elf_get_dt_soname (s->the_bfd);
-      if (soname != NULL
-         && strcmp (soname, global_needed->name) == 0)
-       {
-         global_found = TRUE;
-         return;
-       }
+      global_found = s;
+      return;
     }
 }
 
@@ -867,6 +865,42 @@ gld${EMULATION_NAME}_after_open (void)
 {
   struct bfd_link_needed_list *needed, *l;
 
+  if (link_info.eh_frame_hdr
+      && ! link_info.traditional_format
+      && ! link_info.relocatable)
+    {
+      struct elf_link_hash_table *htab;
+
+      htab = elf_hash_table (&link_info);
+      if (is_elf_hash_table (htab))
+       {
+         bfd *abfd;
+         asection *s;
+
+         for (abfd = link_info.input_bfds; abfd; abfd = abfd->link_next)
+           {
+             s = bfd_get_section_by_name (abfd, ".eh_frame");
+             if (s && s->size > 8 && !bfd_is_abs_section (s->output_section))
+                break;
+           }
+         if (abfd)
+           {
+             const struct elf_backend_data *bed;
+
+             bed = get_elf_backend_data (abfd);
+             s = bfd_make_section_with_flags (abfd, ".eh_frame_hdr",
+                                              bed->dynamic_sec_flags
+                                              | SEC_READONLY);
+             if (s != NULL
+                && bfd_set_section_alignment (abfd, s, 2))
+               htab->eh_info.hdr_sec = s;
+             else
+               einfo ("%P: warning: Cannot create .eh_frame_hdr section,"
+                      " --eh-frame-hdr ignored.\n");
+           }
+       }
+    }
+
   /* We only need to worry about this when doing a final link.  */
   if (link_info.relocatable || !link_info.executable)
     return;
@@ -904,9 +938,11 @@ gld${EMULATION_NAME}_after_open (void)
 
       /* See if this file was included in the link explicitly.  */
       global_needed = l;
-      global_found = FALSE;
+      global_found = NULL;
       lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
-      if (global_found)
+      if (global_found != NULL
+         && (bfd_elf_get_dyn_lib_class (global_found->the_bfd)
+             & DYN_AS_NEEDED) == 0)
        continue;
 
       n.by = l->by;
@@ -915,6 +951,15 @@ gld${EMULATION_NAME}_after_open (void)
       if (trace_file_tries)
        info_msg (_("%s needed by %B\n"), l->name, l->by);
 
+      /* As-needed libs specified on the command line (or linker script)
+        take priority over libs found in search dirs.  */
+      if (global_found != NULL)
+       {
+         nn.name = global_found->filename;
+         if (gld${EMULATION_NAME}_try_needed (&nn, TRUE))
+           continue;
+       }
+
       /* 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
@@ -1171,10 +1216,8 @@ ${ELF_INTERPRETER_SET_DEFAULT}
       {
        asection *s;
        bfd_size_type sz;
-       bfd_size_type prefix_len;
        char *msg;
        bfd_boolean ret;
-       const char * gnu_warning_prefix = _("warning: ");
 
        if (is->just_syms_flag)
          continue;
@@ -1184,14 +1227,12 @@ ${ELF_INTERPRETER_SET_DEFAULT}
          continue;
 
        sz = s->size;
-       prefix_len = strlen (gnu_warning_prefix);
-       msg = xmalloc ((size_t) (prefix_len + sz + 1));
-       strcpy (msg, gnu_warning_prefix);
-       if (! bfd_get_section_contents (is->the_bfd, s, msg + prefix_len,
+       msg = xmalloc ((size_t) (sz + 1));
+       if (! bfd_get_section_contents (is->the_bfd, s, msg,
                                        (file_ptr) 0, sz))
          einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
                 is->the_bfd);
-       msg[prefix_len + sz] = '\0';
+       msg[sz] = '\0';
        ret = link_info.callbacks->warning (&link_info, msg,
                                            (const char *) NULL,
                                            is->the_bfd, (asection *) NULL,
@@ -1199,13 +1240,20 @@ ${ELF_INTERPRETER_SET_DEFAULT}
        ASSERT (ret);
        free (msg);
 
-       /* Clobber the section size, so that we don't waste copying the
-          warning into the output file.  */
+       /* Clobber the section size, so that we don't waste space
+          copying the warning into the output file.  If we've already
+          sized the output section, adjust its size.  The adjustment
+          is on rawsize because targets that size sections early will
+          have called lang_reset_memory_regions after sizing.  */
+       if (s->output_section != NULL
+           && s->output_section->rawsize >= s->size)
+         s->output_section->rawsize -= s->size;
+
        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;
+       /* Also set SEC_EXCLUDE, so that local symbols defined in the
+          warning section don't get copied to the output.  */
+       s->flags |= SEC_EXCLUDE | SEC_KEEP;
       }
   }
 
@@ -1317,7 +1365,7 @@ output_rel_find (asection *sec, int isdyn)
        lookup = lookup->next)
     {
       if (lookup->constraint != -1
-         && strncmp (".rel", lookup->name, 4) == 0)
+         && CONST_STRNEQ (lookup->name, ".rel"))
        {
          int lookrela = lookup->name[4] == 'a';
 
@@ -1426,7 +1474,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s)
          default:
            break;
          }
-      else if (strncmp (secname, ".rel", 4) == 0)
+      else if (CONST_STRNEQ (secname, ".rel"))
        {
          secname = secname[4] == 'a' ? ".rela.dyn" : ".rel.dyn";
          isdyn = 1;
@@ -1474,7 +1522,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s)
      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
+      && CONST_STRNEQ (secname, ".gnu.warning.")
       && hold[orphan_text].os != NULL)
     {
       lang_add_section (&hold[orphan_text].os->children, s,
@@ -1493,7 +1541,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s)
     ;
   else if ((s->flags & SEC_LOAD) != 0
           && ((iself && sh_type == SHT_NOTE)
-              || (!iself && strncmp (secname, ".note", 5) == 0)))
+              || (!iself && CONST_STRNEQ (secname, ".note"))))
     place = &hold[orphan_interp];
   else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
     place = &hold[orphan_bss];
@@ -1502,7 +1550,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s)
   else if ((s->flags & SEC_READONLY) == 0)
     place = &hold[orphan_data];
   else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL))
-           || (!iself && strncmp (secname, ".rel", 4) == 0))
+           || (!iself && CONST_STRNEQ (secname, ".rel")))
           && (s->flags & SEC_LOAD) != 0)
     place = &hold[orphan_rel];
   else if ((s->flags & SEC_CODE) == 0)
@@ -1550,27 +1598,12 @@ fi
 if test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then
 cat >>e${EMULATION_NAME}.c <<EOF
 
-static void
-gld${EMULATION_NAME}_layout_sections_again (void)
-{
-  lang_reset_memory_regions ();
-
-  /* Resize the sections.  */
-  lang_size_sections (NULL, TRUE);
-
-  /* Redo special stuff.  */
-  ldemul_after_allocation ();
-
-  /* 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 ();
+  bfd_boolean need_layout = bfd_elf_discard_info (output_bfd, &link_info);
 
+  gld${EMULATION_NAME}_map_segments (need_layout);
   finish_default ();
 }
 EOF
@@ -1725,7 +1758,8 @@ cat >>e${EMULATION_NAME}.c <<EOF
 #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)
-  
+#define OPTION_HASH_STYLE              (OPTION_EXCLUDE_LIBS + 1)
+
 static void
 gld${EMULATION_NAME}_add_options
   (int ns, char **shortopts, int nl, struct option **longopts,
@@ -1741,6 +1775,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
     {"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},
+    {"hash-style", required_argument, NULL, OPTION_HASH_STYLE},
     {"Bgroup", no_argument, NULL, OPTION_GROUP},
 EOF
 fi
@@ -1797,6 +1832,22 @@ cat >>e${EMULATION_NAME}.c <<EOF
       add_excluded_libs (optarg);
       break;
 
+    case OPTION_HASH_STYLE:
+      link_info.emit_hash = FALSE;
+      link_info.emit_gnu_hash = FALSE;
+      if (strcmp (optarg, "sysv") == 0)
+       link_info.emit_hash = TRUE;
+      else if (strcmp (optarg, "gnu") == 0)
+       link_info.emit_gnu_hash = TRUE;
+      else if (strcmp (optarg, "both") == 0)
+       {
+         link_info.emit_hash = TRUE;
+         link_info.emit_gnu_hash = TRUE;
+       }
+      else
+       einfo (_("%P%F: invalid hash style \`%s'\n"), optarg);
+      break;
+
     case 'z':
       if (strcmp (optarg, "initfirst") == 0)
        link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
@@ -1817,6 +1868,11 @@ cat >>e${EMULATION_NAME}.c <<EOF
          link_info.flags |= (bfd_vma) DF_BIND_NOW;
          link_info.flags_1 |= (bfd_vma) DF_1_NOW;
        }
+      else if (strcmp (optarg, "lazy") == 0)
+       {
+         link_info.flags &= ~(bfd_vma) DF_BIND_NOW;
+         link_info.flags_1 &= ~(bfd_vma) DF_1_NOW;
+       }
       else if (strcmp (optarg, "origin") == 0)
        {
          link_info.flags |= (bfd_vma) DF_ORIGIN;
@@ -1842,10 +1898,35 @@ cat >>e${EMULATION_NAME}.c <<EOF
          link_info.noexecstack = TRUE;
          link_info.execstack = FALSE;
        }
+EOF
+
+  if test -n "$COMMONPAGESIZE"; then
+cat >>e${EMULATION_NAME}.c <<EOF
       else if (strcmp (optarg, "relro") == 0)
        link_info.relro = TRUE;
       else if (strcmp (optarg, "norelro") == 0)
        link_info.relro = FALSE;
+EOF
+  fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+      else if (CONST_STRNEQ (optarg, "max-page-size="))
+       {
+         char *end;
+
+         config.maxpagesize = strtoul (optarg + 14, &end, 0);
+         if (*end)
+           einfo (_("%P%F: invalid maxium page size \`%s'\n"),
+                  optarg + 14);
+       }
+      else if (CONST_STRNEQ (optarg, "common-page-size="))
+       {
+         char *end;
+         config.commonpagesize = strtoul (optarg + 17, &end, 0);
+         if (*end)
+           einfo (_("%P%F: invalid common page size \`%s'\n"),
+                  optarg + 17);
+       }
       /* What about the other Solaris -z options? FIXME.  */
       break;
 EOF
@@ -1879,11 +1960,13 @@ cat >>e${EMULATION_NAME}.c <<EOF
   fprintf (file, _("  --disable-new-dtags\tDisable new dynamic tags\n"));
   fprintf (file, _("  --enable-new-dtags\tEnable new dynamic tags\n"));
   fprintf (file, _("  --eh-frame-hdr\tCreate .eh_frame_hdr section\n"));
+  fprintf (file, _("  --hash-style=STYLE\tSet hash style to sysv, gnu or both\n"));
   fprintf (file, _("  -z combreloc\t\tMerge dynamic relocs into one section and sort\n"));
   fprintf (file, _("  -z defs\t\tReport unresolved symbols in object files.\n"));
   fprintf (file, _("  -z execstack\t\tMark executable as requiring executable stack\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 lazy\t\tMark object lazy runtime binding (default)\n"));
   fprintf (file, _("  -z loadfltr\t\tMark object requiring immediate process\n"));
   fprintf (file, _("  -z muldefs\t\tAllow multiple definitions\n"));
   fprintf (file, _("  -z nocombreloc\tDon't merge dynamic relocs into one section\n"));
@@ -1893,10 +1976,28 @@ cat >>e${EMULATION_NAME}.c <<EOF
   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 noexecstack\tMark executable as not requiring executable stack\n"));
+EOF
+
+  if test -n "$COMMONPAGESIZE"; then
+cat >>e${EMULATION_NAME}.c <<EOF
   fprintf (file, _("  -z norelro\t\tDon't create RELRO program header\n"));
+EOF
+  fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
   fprintf (file, _("  -z now\t\tMark object non-lazy runtime binding\n"));
   fprintf (file, _("  -z origin\t\tMark object requiring immediate \$ORIGIN processing\n\t\t\t  at runtime\n"));
+EOF
+
+  if test -n "$COMMONPAGESIZE"; then
+cat >>e${EMULATION_NAME}.c <<EOF
   fprintf (file, _("  -z relro\t\tCreate RELRO program header\n"));
+EOF
+  fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+  fprintf (file, _("  -z max-page-size=SIZE\tSet maximum page size to SIZE\n"));
+  fprintf (file, _("  -z common-page-size=SIZE\n\t\t\tSet common page size to SIZE\n"));
   fprintf (file, _("  -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
 EOF
 fi
This page took 0.031539 seconds and 4 git commands to generate.