ld: Add a linker configure option --enable-relro
[external/binutils.git] / ld / emultempl / elf32.em
index 7d31864..47fa549 100644 (file)
@@ -12,9 +12,7 @@ fragment <<EOF
 /* This file is is generated by a shell script.  DO NOT EDIT! */
 
 /* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
-   Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-   Free Software Foundation, Inc.
+   Copyright (C) 1991-2016 Free Software Foundation, Inc.
    Written by Steve Chamberlain <sac@cygnus.com>
    ELF support by Ian Lance Taylor <ian@cygnus.com>
 
@@ -40,11 +38,9 @@ fragment <<EOF
 #include "sysdep.h"
 #include "bfd.h"
 #include "libiberty.h"
-#include "filenames.h"
 #include "safe-ctype.h"
+#include "filenames.h"
 #include "getopt.h"
-#include "md5.h"
-#include "sha1.h"
 #include <fcntl.h>
 
 #include "bfdlink.h"
@@ -56,6 +52,7 @@ fragment <<EOF
 #include "ldlang.h"
 #include "ldfile.h"
 #include "ldemul.h"
+#include "ldbuildid.h"
 #include <ldgram.h>
 #include "elf/common.h"
 #include "elf-bfd.h"
@@ -63,6 +60,7 @@ fragment <<EOF
 
 /* Declare functions used by various EXTRA_EM_FILEs.  */
 static void gld${EMULATION_NAME}_before_parse (void);
+static void gld${EMULATION_NAME}_after_parse (void);
 static void gld${EMULATION_NAME}_after_open (void);
 static void gld${EMULATION_NAME}_before_allocation (void);
 static void gld${EMULATION_NAME}_after_allocation (void);
@@ -72,7 +70,7 @@ EOF
 
 if [ "x${USE_LIBPATH}" = xyes ] ; then
   case ${target} in
-    *-*-linux-* | *-*-k*bsd*-*)
+    *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*)
   fragment <<EOF
 #ifdef HAVE_GLOB
 #include <glob.h>
@@ -104,6 +102,25 @@ gld${EMULATION_NAME}_before_parse (void)
   ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
   input_flags.dynamic = ${DYNAMIC_LINK-TRUE};
   config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
+  config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;
+  `if test -n "$CALL_NOP_BYTE" ; then echo link_info.call_nop_byte = $CALL_NOP_BYTE; fi`;
+  link_info.check_relocs_after_open_input = `if test "x${CHECK_RELOCS_AFTER_OPEN_INPUT}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;
+  link_info.relro = DEFAULT_LD_Z_RELRO;
+}
+
+EOF
+fi
+
+if test x"$LDEMUL_AFTER_PARSE" != xgld"$EMULATION_NAME"_after_parse; then
+fragment <<EOF
+
+static void
+gld${EMULATION_NAME}_after_parse (void)
+{
+  if (bfd_link_pie (&link_info))
+    link_info.flags_1 |= (bfd_vma) DF_1_PIE;
+
+  after_parse_default ();
 }
 
 EOF
@@ -140,7 +157,7 @@ gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *entry)
     return FALSE;
 
   bfd_elf_set_dyn_lib_class (entry->the_bfd,
-                             (enum dynamic_lib_link_class) link_class);
+                            (enum dynamic_lib_link_class) link_class);
 
   /* Continue on with normal load_symbols processing.  */
   return FALSE;
@@ -164,6 +181,9 @@ static bfd_boolean global_vercheck_failed;
 static char *audit; /* colon (typically) separated list of libs */
 static char *depaudit; /* colon (typically) separated list of libs */
 
+/* Style of .note.gnu.build-id section.  */
+static const char *emit_note_gnu_build_id;
+
 /* On Linux, it's possible to have different versions of the same
    shared library linked against different versions of libc.  The
    dynamic linker somehow tags which libc version to use in
@@ -374,7 +394,7 @@ gld${EMULATION_NAME}_try_needed (struct dt_needed *needed,
 
 EOF
 case ${target} in
-  *-*-linux-* | *-*-k*bsd*-*)
+  *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*)
     fragment <<EOF
          {
            struct bfd_link_needed_list *l;
@@ -412,7 +432,7 @@ fragment <<EOF
   /* First strip off everything before the last '/'.  */
   soname = lbasename (abfd->filename);
 
-  if (trace_file_tries)
+  if (verbose)
     info_msg (_("found %s at %s\n"), soname, name);
 
   global_found = NULL;
@@ -443,7 +463,7 @@ fragment <<EOF
 
   /* Add this file into the symbol table.  */
   if (! bfd_link_add_symbols (abfd, &link_info))
-    einfo ("%F%B: could not read symbols: %E\n", abfd);
+    einfo ("%F%B: error adding symbols: %E\n", abfd);
 
   return TRUE;
 }
@@ -568,7 +588,8 @@ EOF
 #endif
 
 static bfd_boolean
-gld${EMULATION_NAME}_check_ld_elf_hints (const char *name, int force)
+gld${EMULATION_NAME}_check_ld_elf_hints (const struct bfd_link_needed_list *l,
+                                        int force)
 {
   static bfd_boolean initialized;
   static char *ld_elf_hints;
@@ -611,16 +632,15 @@ gld${EMULATION_NAME}_check_ld_elf_hints (const char *name, int force)
   if (ld_elf_hints == NULL)
     return FALSE;
 
-  needed.by = NULL;
-  needed.name = name;
-  return gld${EMULATION_NAME}_search_needed (ld_elf_hints, & needed,
-                                            force);
+  needed.by = l->by;
+  needed.name = l->name;
+  return gld${EMULATION_NAME}_search_needed (ld_elf_hints, &needed, force);
 }
 EOF
     # FreeBSD
     ;;
 
-    *-*-linux-* | *-*-k*bsd*-*)
+    *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*)
       fragment <<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
@@ -786,7 +806,8 @@ gld${EMULATION_NAME}_parse_ld_so_conf
 }
 
 static bfd_boolean
-gld${EMULATION_NAME}_check_ld_so_conf (const char *name, int force)
+gld${EMULATION_NAME}_check_ld_so_conf (const struct bfd_link_needed_list *l,
+                                      int force)
 {
   static bfd_boolean initialized;
   static char *ld_so_conf;
@@ -823,8 +844,8 @@ gld${EMULATION_NAME}_check_ld_so_conf (const char *name, int force)
     return FALSE;
 
 
-  needed.by = NULL;
-  needed.name = name;
+  needed.by = l->by;
+  needed.name = l->name;
   return gld${EMULATION_NAME}_search_needed (ld_so_conf, &needed, force);
 }
 
@@ -888,79 +909,39 @@ if test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
 fragment <<EOF
 
 static bfd_size_type
-gld${EMULATION_NAME}_id_note_section_size (bfd *abfd,
-                                          struct bfd_link_info *linfo)
+id_note_section_size (bfd *abfd ATTRIBUTE_UNUSED)
 {
-  const char *style = linfo->emit_note_gnu_build_id;
+  const char *style = emit_note_gnu_build_id;
   bfd_size_type size;
-
-  abfd = abfd;
+  bfd_size_type build_id_size;
 
   size = offsetof (Elf_External_Note, name[sizeof "GNU"]);
   size = (size + 3) & -(bfd_size_type) 4;
 
-  if (!strcmp (style, "md5") || !strcmp (style, "uuid"))
-    size += 128 / 8;
-  else if (!strcmp (style, "sha1"))
-    size += 160 / 8;
-  else if (!strncmp (style, "0x", 2))
-    {
-      /* ID is in string form (hex).  Convert to bits.  */
-      const char *id = style + 2;
-      do
-       {
-         if (ISXDIGIT (id[0]) && ISXDIGIT (id[1]))
-           {
-             ++size;
-             id += 2;
-           }
-         else if (*id == '-' || *id == ':')
-           ++id;
-         else
-           {
-             size = 0;
-             break;
-           }
-       } while (*id != '\0');
-    }
+  build_id_size = compute_build_id_size (style);
+  if (build_id_size)
+    size += build_id_size;
   else
     size = 0;
 
   return size;
 }
 
-static unsigned char
-read_hex (const char xdigit)
-{
-  if (ISDIGIT (xdigit))
-    return xdigit - '0';
-  if (ISUPPER (xdigit))
-    return xdigit - 'A' + 0xa;
-  if (ISLOWER (xdigit))
-    return xdigit - 'a' + 0xa;
-  abort ();
-  return 0;
-}
-
-struct build_id_info
-{
-  const char *style;
-  asection *sec;
-};
-
 static bfd_boolean
-gld${EMULATION_NAME}_write_build_id_section (bfd *abfd)
+write_build_id (bfd *abfd)
 {
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  struct build_id_info *info = (struct build_id_info *)
-    elf_tdata (abfd)->after_write_object_contents_info;
+  struct elf_obj_tdata *t = elf_tdata (abfd);
+  const char *style;
   asection *asec;
   Elf_Internal_Shdr *i_shdr;
   unsigned char *contents, *id_bits;
   bfd_size_type size;
+  file_ptr position;
   Elf_External_Note *e_note;
 
-  asec = info->sec;
+  style = t->o->build_id.style;
+  asec = t->o->build_id.sec;
   if (bfd_is_abs_section (asec->output_section))
     {
       einfo (_("%P: warning: .note.gnu.build-id section discarded,"
@@ -989,69 +970,49 @@ gld${EMULATION_NAME}_write_build_id_section (bfd *abfd)
   bfd_h_put_32 (abfd, NT_GNU_BUILD_ID, &e_note->type);
   memcpy (e_note->name, "GNU", sizeof "GNU");
 
-  if (!strcmp (info->style, "md5"))
-    {
-      struct md5_ctx ctx;
-      md5_init_ctx (&ctx);
-      if (bed->s->checksum_contents (abfd,
-                                    (void (*) (const void *, size_t, void *))
-                                    &md5_process_bytes,
-                                    &ctx))
-       md5_finish_ctx (&ctx, id_bits);
-      else
-       return FALSE;
-    }
-  else if (!strcmp (info->style, "sha1"))
-    {
-      struct sha1_ctx ctx;
-      sha1_init_ctx (&ctx);
-      if (bed->s->checksum_contents (abfd,
-                                    (void (*) (const void *, size_t, void *))
-                                    &sha1_process_bytes,
-                                    &ctx))
-       sha1_finish_ctx (&ctx, id_bits);
-      else
-       return FALSE;
-    }
-  else if (!strcmp (info->style, "uuid"))
+  generate_build_id (abfd, style, bed->s->checksum_contents, id_bits, size);
+
+  position = i_shdr->sh_offset + asec->output_offset;
+  size = asec->size;
+  return (bfd_seek (abfd, position, SEEK_SET) == 0
+         && bfd_bwrite (contents, size, abfd) == size);
+}
+
+/* Make .note.gnu.build-id section, and set up elf_tdata->build_id.  */
+
+static bfd_boolean
+setup_build_id (bfd *ibfd)
+{
+  asection *s;
+  bfd_size_type size;
+  flagword flags;
+
+  size = id_note_section_size (ibfd);
+  if (size == 0)
     {
-      int n;
-      int fd = open ("/dev/urandom", O_RDONLY);
-      if (fd < 0)
-       return FALSE;
-      n = read (fd, id_bits, size);
-      close (fd);
-      if (n < (int) size)
-       return FALSE;
+      einfo ("%P: warning: unrecognized --build-id style ignored.\n");
+      return FALSE;
     }
-  else if (!strncmp (info->style, "0x", 2))
+
+  flags = (SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY
+          | SEC_LINKER_CREATED | SEC_READONLY | SEC_DATA);
+  s = bfd_make_section_with_flags (ibfd, ".note.gnu.build-id", flags);
+  if (s != NULL && bfd_set_section_alignment (ibfd, s, 2))
     {
-      /* ID is in string form (hex).  Convert to bits.  */
-      const char *id = info->style + 2;
-      size_t n = 0;
-      do
-       {
-         if (ISXDIGIT (id[0]) && ISXDIGIT (id[1]))
-           {
-             id_bits[n] = read_hex (*id++) << 4;
-             id_bits[n++] |= read_hex (*id++);
-           }
-         else if (*id == '-' || *id == ':')
-           ++id;
-         else
-           abort ();           /* Should have been validated earlier.  */
-       } while (*id != '\0');
+      struct elf_obj_tdata *t = elf_tdata (link_info.output_bfd);
+      t->o->build_id.after_write_object_contents = &write_build_id;
+      t->o->build_id.style = emit_note_gnu_build_id;
+      t->o->build_id.sec = s;
+      elf_section_type (s) = SHT_NOTE;
+      s->size = size;
+      return TRUE;
     }
-  else
-    abort ();                  /* Should have been validated earlier.  */
 
-  size = asec->size;
-  return (bfd_seek (abfd,
-                   i_shdr->sh_offset + asec->output_offset, SEEK_SET) == 0
-         && bfd_bwrite (contents, size, abfd) == size);
+  einfo ("%P: warning: Cannot create .note.gnu.build-id section,"
+        " --build-id ignored.\n");
+  return FALSE;
 }
 
-
 /* This is called after all the input files have been opened.  */
 
 static void
@@ -1066,89 +1027,94 @@ gld${EMULATION_NAME}_after_open (void)
   if (!is_elf_hash_table (htab))
     return;
 
-  if (link_info.emit_note_gnu_build_id)
+  if (emit_note_gnu_build_id != NULL)
     {
       bfd *abfd;
-      asection *s;
-      bfd_size_type size;
 
       /* Find an ELF input.  */
       for (abfd = link_info.input_bfds;
-          abfd != (bfd *) NULL; abfd = abfd->link_next)
-       if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+          abfd != (bfd *) NULL; abfd = abfd->link.next)
+       if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+           && bfd_count_sections (abfd) != 0)
          break;
 
-      if (abfd == NULL)
+      /* PR 10555: If there are no ELF input files do not try to
+        create a .note.gnu-build-id section.  */
+      if (abfd == NULL
+         || !setup_build_id (abfd))
        {
-         /* PR 10555: If there are no input files do not
-            try to create a .note.gnu-build-id section.  */
-         free (link_info.emit_note_gnu_build_id);
-         link_info.emit_note_gnu_build_id = NULL;
-       }
-      else
-       {
-         size = gld${EMULATION_NAME}_id_note_section_size (abfd, &link_info);
-         if (size == 0)
-           {
-             einfo ("%P: warning: unrecognized --build-id style ignored.\n");
-             free (link_info.emit_note_gnu_build_id);
-             link_info.emit_note_gnu_build_id = NULL;
-           }
-         else
-           {
-             s = bfd_make_section_with_flags (abfd, ".note.gnu.build-id",
-                                              SEC_ALLOC | SEC_LOAD
-                                              | SEC_IN_MEMORY | SEC_LINKER_CREATED
-                                              | SEC_READONLY | SEC_DATA);
-             if (s != NULL && bfd_set_section_alignment (abfd, s, 2))
-               {
-                 struct elf_obj_tdata *t = elf_tdata (link_info.output_bfd);
-                 struct build_id_info *b =
-                      (struct build_id_info *) xmalloc (sizeof *b);
-
-                 b->style = link_info.emit_note_gnu_build_id;
-                 b->sec = s;
-                 elf_section_type (s) = SHT_NOTE;
-                 s->size = size;
-                 t->after_write_object_contents
-                   = &gld${EMULATION_NAME}_write_build_id_section;
-                 t->after_write_object_contents_info = b;
-               }
-             else
-               {
-                 einfo ("%P: warning: Cannot create .note.gnu.build-id section,"
-                        " --build-id ignored.\n");
-                 free (link_info.emit_note_gnu_build_id);
-                 link_info.emit_note_gnu_build_id = NULL;
-               }
-           }
+         free ((char *) emit_note_gnu_build_id);
+         emit_note_gnu_build_id = NULL;
        }
     }
 
-  if (link_info.relocatable)
-    return;
+  if (bfd_link_relocatable (&link_info))
+    {
+      if (link_info.execstack == ! link_info.noexecstack)
+       /* PR ld/16744: If "-z [no]execstack" has been specified on the
+          command line and we are perfoming a relocatable link then no
+          PT_GNU_STACK segment will be created and so the
+          linkinfo.[no]execstack values set in _handle_option() will have no
+          effect.  Instead we create a .note.GNU-stack section in much the
+          same way as the assembler does with its --[no]execstack option.  */
+       (void) bfd_make_section_with_flags (link_info.input_bfds,
+                                           ".note.GNU-stack",
+                                           SEC_READONLY | (link_info.execstack ? SEC_CODE : 0));
 
-  if (link_info.eh_frame_hdr
-      && !link_info.traditional_format)
+      return;
+    }
+
+  if (!link_info.traditional_format)
     {
       bfd *abfd, *elfbfd = NULL;
       bfd_boolean warn_eh_frame = FALSE;
       asection *s;
+      int seen_type = 0;
 
-      for (abfd = link_info.input_bfds; abfd; abfd = abfd->link_next)
+      for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
        {
-         if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
-           elfbfd = abfd;
-         if (!warn_eh_frame)
+         int type = 0;
+         for (s = abfd->sections; s && type < COMPACT_EH_HDR; s = s->next)
            {
-             s = bfd_get_section_by_name (abfd, ".eh_frame");
-             warn_eh_frame
-               = (s
-                  && s->size > 8
-                  && !bfd_is_abs_section (s->output_section));
+             const char *name = bfd_get_section_name (abfd, s);
+
+             if (bfd_is_abs_section (s->output_section))
+               continue;
+             if (CONST_STRNEQ (name, ".eh_frame_entry"))
+               type = COMPACT_EH_HDR;
+             else if (strcmp (name, ".eh_frame") == 0 && s->size > 8)
+               type = DWARF2_EH_HDR;
            }
-         if (elfbfd && warn_eh_frame)
-           break;
+
+         if (type != 0)
+           {
+             if (seen_type == 0)
+               {
+                 seen_type = type;
+               }
+             else if (seen_type != type)
+               {
+                 einfo (_("%P%F: compact frame descriptions incompatible with"
+                        " DWARF2 .eh_frame from %B\n"),
+                        type == DWARF2_EH_HDR ? abfd : elfbfd);
+                 break;
+               }
+
+             if (!elfbfd
+                 && (type == COMPACT_EH_HDR || link_info.eh_frame_hdr_type != 0))
+               {
+                 if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+                   elfbfd = abfd;
+
+                 warn_eh_frame = TRUE;
+               }
+           }
+
+         if (seen_type == COMPACT_EH_HDR)
+           link_info.eh_frame_hdr_type = COMPACT_EH_HDR;
+
+         if (bfd_count_sections (abfd) == 0)
+           continue;
        }
       if (elfbfd)
        {
@@ -1179,8 +1145,6 @@ gld${EMULATION_NAME}_after_open (void)
      special action by the person doing the link.  Note that the
      needed list can actually grow while we are stepping through this
      loop.  */
-  if (!link_info.executable)
-    return;
   needed = bfd_elf_get_needed_list (link_info.output_bfd, &link_info);
   for (l = needed; l != NULL; l = l->next)
     {
@@ -1194,6 +1158,13 @@ gld${EMULATION_NAME}_after_open (void)
          && (bfd_elf_get_dyn_lib_class (l->by) & DYN_AS_NEEDED) != 0)
        continue;
 
+      /* Skip the lib if --no-copy-dt-needed-entries and
+        --allow-shlib-undefined is in effect.  */
+      if (l->by != NULL
+         && link_info.unresolved_syms_in_shared_libs == RM_IGNORE
+         && (bfd_elf_get_dyn_lib_class (l->by) & DYN_NO_ADD_NEEDED) != 0)
+       continue;
+
       /* If we've already seen this file, skip it.  */
       for (ll = needed; ll != l; ll = ll->next)
        if ((ll->by == NULL
@@ -1215,7 +1186,7 @@ gld${EMULATION_NAME}_after_open (void)
       n.by = l->by;
       n.name = l->name;
       nn.by = l->by;
-      if (trace_file_tries)
+      if (verbose)
        info_msg (_("%s needed by %B\n"), l->name, l->by);
 
       /* As-needed libs specified on the command line (or linker script)
@@ -1288,12 +1259,16 @@ fragment <<EOF
          rp = bfd_elf_get_runpath_list (link_info.output_bfd, &link_info);
          for (; !found && rp != NULL; rp = rp->next)
            {
-             char *tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name);
+             const char *tmpname = rp->name;
+
+             if (IS_ABSOLUTE_PATH (tmpname))
+               tmpname = gld${EMULATION_NAME}_add_sysroot (tmpname);
              found = (rp->by == l->by
                       && gld${EMULATION_NAME}_search_needed (tmpname,
                                                              &n,
                                                              force));
-             free (tmpname);
+             if (tmpname != rp->name)
+               free ((char *) tmpname);
            }
          if (found)
            break;
@@ -1304,19 +1279,19 @@ if [ "x${USE_LIBPATH}" = xyes ] ; then
   case ${target} in
     *-*-freebsd* | *-*-dragonfly*)
       fragment <<EOF
-         if (gld${EMULATION_NAME}_check_ld_elf_hints (l->name, force))
+         if (gld${EMULATION_NAME}_check_ld_elf_hints (l, force))
            break;
 EOF
     # FreeBSD
     ;;
 
-    *-*-linux-* | *-*-k*bsd*-*)
-    # Linux
+    *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*)
       fragment <<EOF
-         if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
+         if (gld${EMULATION_NAME}_check_ld_so_conf (l, force))
            break;
 
 EOF
+    # Linux
     ;;
   esac
 fi
@@ -1347,6 +1322,10 @@ fragment <<EOF
       einfo ("%P: warning: %s, needed by %B, not found (try using -rpath or -rpath-link)\n",
             l->name, l->by);
     }
+
+  if (link_info.eh_frame_hdr_type == COMPACT_EH_HDR)
+    if (bfd_elf_parse_eh_frame_entries (NULL, &link_info) == FALSE)
+      einfo (_("%P%F: Failed to parse EH frame entries.\n"));
 }
 
 EOF
@@ -1438,7 +1417,7 @@ if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation;
 fragment <<EOF
 
 /* used by before_allocation and handle_option. */
-static void 
+static void
 gld${EMULATION_NAME}_append_to_separated_string (char **to, char *op_arg)
 {
   if (*to == NULL)
@@ -1477,6 +1456,11 @@ gld${EMULATION_NAME}_append_to_separated_string (char **to, char *op_arg)
     }
 }
 
+#if defined(__GNUC__) && GCC_VERSION < 4006
+  /* Work around a GCC uninitialized warning bug fixed in GCC 4.6.  */
+static struct bfd_link_hash_entry ehdr_start_empty;
+#endif
+
 /* This is called after the sections have been attached to output
    sections, but before any sizes or addresses have been set.  */
 
@@ -1486,14 +1470,55 @@ gld${EMULATION_NAME}_before_allocation (void)
   const char *rpath;
   asection *sinterp;
   bfd *abfd;
+  struct elf_link_hash_entry *ehdr_start = NULL;
+#if defined(__GNUC__) && GCC_VERSION < 4006
+  /* Work around a GCC uninitialized warning bug fixed in GCC 4.6.  */
+  struct bfd_link_hash_entry ehdr_start_save = ehdr_start_empty;
+#else
+  struct bfd_link_hash_entry ehdr_start_save;
+#endif
 
-  if (link_info.hash->type == bfd_link_elf_hash_table)
-    _bfd_elf_tls_setup (link_info.output_bfd, &link_info);
-
-  /* If we are going to make any variable assignments, we need to let
-     the ELF backend know about them in case the variables are
-     referred to by dynamic objects.  */
-  lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
+  if (is_elf_hash_table (link_info.hash))
+    {
+      _bfd_elf_tls_setup (link_info.output_bfd, &link_info);
+
+      /* Make __ehdr_start hidden if it has been referenced, to
+        prevent the symbol from being dynamic.  */
+      if (!bfd_link_relocatable (&link_info))
+       {
+         struct elf_link_hash_entry *h
+           = elf_link_hash_lookup (elf_hash_table (&link_info), "__ehdr_start",
+                                   FALSE, FALSE, TRUE);
+
+         /* Only adjust the export class if the symbol was referenced
+            and not defined, otherwise leave it alone.  */
+         if (h != NULL
+             && (h->root.type == bfd_link_hash_new
+                 || h->root.type == bfd_link_hash_undefined
+                 || h->root.type == bfd_link_hash_undefweak
+                 || h->root.type == bfd_link_hash_common))
+           {
+             _bfd_elf_link_hash_hide_symbol (&link_info, h, TRUE);
+             if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+               h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
+            /* Don't leave the symbol undefined.  Undefined hidden
+               symbols typically won't have dynamic relocations, but
+               we most likely will need dynamic relocations for
+               __ehdr_start if we are building a PIE or shared
+               library.  */
+            ehdr_start = h;
+            ehdr_start_save = h->root;
+            h->root.type = bfd_link_hash_defined;
+            h->root.u.def.section = bfd_abs_section_ptr;
+            h->root.u.def.value = 0;
+           }
+       }
+
+      /* If we are going to make any variable assignments, we need to
+        let the ELF backend know about them in case the variables are
+        referred to by dynamic objects.  */
+      lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
+    }
 
   /* Let the ELF backend work out the sizes of any sections required
      by dynamic linking.  */
@@ -1501,12 +1526,12 @@ gld${EMULATION_NAME}_before_allocation (void)
   if (rpath == NULL)
     rpath = (const char *) getenv ("LD_RUN_PATH");
 
-  for (abfd = link_info.input_bfds; abfd; abfd = abfd->link_next)
+  for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
     if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
       {
        const char *audit_libs = elf_dt_audit (abfd);
 
-       /* If the input bfd contains an audit entry, we need to add it as 
+       /* If the input bfd contains an audit entry, we need to add it as
           a dep audit entry.  */
        if (audit_libs && *audit_libs != '\0')
          {
@@ -1558,7 +1583,6 @@ ${ELF_INTERPRETER_SET_DEFAULT}
        asection *s;
        bfd_size_type sz;
        char *msg;
-       bfd_boolean ret;
 
        if (is->flags.just_syms)
          continue;
@@ -1574,11 +1598,9 @@ ${ELF_INTERPRETER_SET_DEFAULT}
          einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
                 is->the_bfd);
        msg[sz] = '\0';
-       ret = link_info.callbacks->warning (&link_info, msg,
-                                           (const char *) NULL,
-                                           is->the_bfd, (asection *) NULL,
-                                           (bfd_vma) 0);
-       ASSERT (ret);
+       (*link_info.callbacks->warning) (&link_info, msg,
+                                        (const char *) NULL, is->the_bfd,
+                                        (asection *) NULL, (bfd_vma) 0);
        free (msg);
 
        /* Clobber the section size, so that we don't waste space
@@ -1602,6 +1624,14 @@ ${ELF_INTERPRETER_SET_DEFAULT}
 
   if (!bfd_elf_size_dynsym_hash_dynstr (link_info.output_bfd, &link_info))
     einfo ("%P%F: failed to set dynamic section sizes: %E\n");
+
+  if (ehdr_start != NULL)
+    {
+      /* If we twiddled __ehdr_start to defined earlier, put it back
+        as it was.  */
+      ehdr_start->root.type = ehdr_start_save.type;
+      ehdr_start->root.u = ehdr_start_save.u;
+    }
 }
 
 EOF
@@ -1620,42 +1650,46 @@ gld${EMULATION_NAME}_open_dynamic_archive
 {
   const char *filename;
   char *string;
+  size_t len;
+  bfd_boolean opened = FALSE;
 
   if (! entry->flags.maybe_archive)
     return FALSE;
 
   filename = entry->filename;
+  len = strlen (search->name) + strlen (filename);
+  if (entry->flags.full_name_provided)
+    {
+      len += sizeof "/";
+      string = (char *) xmalloc (len);
+      sprintf (string, "%s/%s", search->name, filename);
+    }
+  else
+    {
+      size_t xlen = 0;
 
-  /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION
-     is defined, but it does not seem worth the headache to optimize
-     away those two bytes of space.  */
-  string = (char *) xmalloc (strlen (search->name)
-                            + strlen (filename)
-                            + strlen (arch)
+      len += strlen (arch) + sizeof "/lib.so";
 #ifdef EXTRA_SHLIB_EXTENSION
-                            + strlen (EXTRA_SHLIB_EXTENSION)
+      xlen = (strlen (EXTRA_SHLIB_EXTENSION) > 3
+             ? strlen (EXTRA_SHLIB_EXTENSION) - 3
+             : 0);
 #endif
-                            + sizeof "/lib.so");
-
-  sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
-
+      string = (char *) xmalloc (len + xlen);
+      sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
 #ifdef EXTRA_SHLIB_EXTENSION
-  /* Try the .so extension first.  If that fails build a new filename
-     using EXTRA_SHLIB_EXTENSION.  */
-  if (! ldfile_try_open_bfd (string, entry))
-    {
-      sprintf (string, "%s/lib%s%s%s", search->name,
-              filename, arch, EXTRA_SHLIB_EXTENSION);
+      /* Try the .so extension first.  If that fails build a new filename
+        using EXTRA_SHLIB_EXTENSION.  */
+      opened = ldfile_try_open_bfd (string, entry);
+      if (!opened)
+       strcpy (string + len - 4, EXTRA_SHLIB_EXTENSION);
 #endif
+    }
 
-  if (! ldfile_try_open_bfd (string, entry))
+  if (!opened && !ldfile_try_open_bfd (string, entry))
     {
       free (string);
       return FALSE;
     }
-#ifdef EXTRA_SHLIB_EXTENSION
-    }
-#endif
 
   entry->filename = string;
 
@@ -1680,7 +1714,8 @@ gld${EMULATION_NAME}_open_dynamic_archive
       /* Rather than duplicating the logic above.  Just use the
         filename we recorded earlier.  */
 
-      filename = lbasename (entry->filename);
+      if (!entry->flags.full_name_provided)
+        filename = lbasename (entry->filename);
       bfd_elf_set_dt_needed_name (entry->the_bfd, filename);
     }
 
@@ -1774,6 +1809,9 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
       { ".rodata",
        SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
        0, 0, 0, 0 },
+      { ".tdata",
+       SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_THREAD_LOCAL,
+       0, 0, 0, 0 },
       { ".data",
        SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
        0, 0, 0, 0 },
@@ -1797,6 +1835,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
     {
       orphan_text = 0,
       orphan_rodata,
+      orphan_tdata,
       orphan_data,
       orphan_bss,
       orphan_rel,
@@ -1812,8 +1851,10 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
   int isdyn = 0;
   int iself = s->owner->xvec->flavour == bfd_target_elf_flavour;
   unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL;
+  flagword flags;
+  asection *nexts;
 
-  if (! link_info.relocatable
+  if (!bfd_link_relocatable (&link_info)
       && link_info.combreloc
       && (s->flags & SEC_ALLOC))
     {
@@ -1850,18 +1891,18 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
 
        if (os->bfd_section != NULL
            && (os->bfd_section->flags == 0
-               || (_bfd_elf_match_sections_by_type (link_info.output_bfd,
-                                                    os->bfd_section,
-                                                    s->owner, s)
-                   && ((s->flags ^ os->bfd_section->flags)
-                       & (SEC_LOAD | SEC_ALLOC)) == 0)))
+               || (((s->flags ^ os->bfd_section->flags)
+                    & (SEC_LOAD | SEC_ALLOC)) == 0
+                   && _bfd_elf_match_sections_by_type (link_info.output_bfd,
+                                                       os->bfd_section,
+                                                       s->owner, s))))
          {
            /* We already have an output section statement with this
               name, and its bfd section 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);
+           lang_add_section (&os->children, s, NULL, os);
            return os;
          }
 
@@ -1875,7 +1916,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
      unused one and use that.  */
   if (match_by_name)
     {
-      lang_add_section (&match_by_name->children, s, match_by_name);
+      lang_add_section (&match_by_name->children, s, NULL, match_by_name);
       return match_by_name;
     }
 
@@ -1895,16 +1936,35 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
 
   /* 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
+  if (bfd_link_executable (&link_info)
       && CONST_STRNEQ (s->name, ".gnu.warning.")
       && hold[orphan_text].os != NULL)
     {
       os = hold[orphan_text].os;
-      lang_add_section (&os->children, s, os);
+      lang_add_section (&os->children, s, NULL, os);
       return os;
     }
 
+  flags = s->flags;
+  if (!bfd_link_relocatable (&link_info))
+    {
+      nexts = s;
+      while ((nexts = bfd_get_next_section_by_name (nexts->owner, nexts))
+            != NULL)
+       if (nexts->output_section == NULL
+           && (nexts->flags & SEC_EXCLUDE) == 0
+           && ((nexts->flags ^ flags) & (SEC_LOAD | SEC_ALLOC)) == 0
+           && (nexts->owner->flags & DYNAMIC) == 0
+           && nexts->owner->usrdata != NULL
+           && !(((lang_input_statement_type *) nexts->owner->usrdata)
+                ->flags.just_syms)
+           && _bfd_elf_match_sections_by_type (nexts->owner, nexts,
+                                               s->owner, s))
+         flags = (((flags ^ SEC_READONLY)
+                   | (nexts->flags ^ SEC_READONLY))
+                  ^ SEC_READONLY);
+    }
+
   /* Decide which segment the section should go in based on the
      section name and section flags.  We put loadable .note sections
      right after the .interp section, so that the PT_NOTE segment is
@@ -1912,25 +1972,27 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
      in the first page.  */
 
   place = NULL;
-  if ((s->flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0)
+  if ((flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0)
     place = &hold[orphan_nonalloc];
-  else if ((s->flags & SEC_ALLOC) == 0)
+  else if ((flags & SEC_ALLOC) == 0)
     ;
-  else if ((s->flags & SEC_LOAD) != 0
+  else if ((flags & SEC_LOAD) != 0
           && ((iself && sh_type == SHT_NOTE)
               || (!iself && CONST_STRNEQ (secname, ".note"))))
     place = &hold[orphan_interp];
-  else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS | SEC_THREAD_LOCAL)) == 0)
+  else if ((flags & (SEC_LOAD | SEC_HAS_CONTENTS | SEC_THREAD_LOCAL)) == 0)
     place = &hold[orphan_bss];
-  else if ((s->flags & SEC_SMALL_DATA) != 0)
+  else if ((flags & SEC_SMALL_DATA) != 0)
     place = &hold[orphan_sdata];
-  else if ((s->flags & SEC_READONLY) == 0)
+  else if ((flags & SEC_THREAD_LOCAL) != 0)
+    place = &hold[orphan_tdata];
+  else if ((flags & SEC_READONLY) == 0)
     place = &hold[orphan_data];
   else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL))
            || (!iself && CONST_STRNEQ (secname, ".rel")))
-          && (s->flags & SEC_LOAD) != 0)
+          && (flags & SEC_LOAD) != 0)
     place = &hold[orphan_rel];
-  else if ((s->flags & SEC_CODE) == 0)
+  else if ((flags & SEC_CODE) == 0)
     place = &hold[orphan_rodata];
   else
     place = &hold[orphan_text];
@@ -1947,8 +2009,9 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
        }
       after = place->os;
       if (after == NULL)
-       after = lang_output_section_find_by_flags
-         (s, &place->os, _bfd_elf_match_sections_by_type);
+       after
+         = lang_output_section_find_by_flags (s, flags, &place->os,
+                                              _bfd_elf_match_sections_by_type);
       if (after == NULL)
        /* *ABS* is always the first output section statement.  */
        after = &lang_output_section_statement.head->output_section_statement;
@@ -1965,9 +2028,12 @@ fragment <<EOF
 static void
 gld${EMULATION_NAME}_after_allocation (void)
 {
-  bfd_boolean need_layout = bfd_elf_discard_info (link_info.output_bfd,
-                                                 &link_info);
-  gld${EMULATION_NAME}_map_segments (need_layout);
+  int need_layout = bfd_elf_discard_info (link_info.output_bfd, &link_info);
+
+  if (need_layout < 0)
+    einfo ("%X%P: .eh_frame/.stab edit: %E\n");
+  else
+    gld${EMULATION_NAME}_map_segments (need_layout);
 }
 EOF
 fi
@@ -1979,7 +2045,7 @@ static char *
 gld${EMULATION_NAME}_get_script (int *isfile)
 EOF
 
-if test -n "$COMPILE_IN"
+if test x"$COMPILE_IN" = xyes
 then
 # Scripts compiled in.
 
@@ -1990,11 +2056,11 @@ fragment <<EOF
 {
   *isfile = 0;
 
-  if (link_info.relocatable && config.build_constructors)
+  if (bfd_link_relocatable (&link_info) && 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
+echo '  ; else if (bfd_link_relocatable (&link_info)) 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
@@ -2004,26 +2070,28 @@ 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 '  ; else if (bfd_link_pie (&link_info)'          >> e${EMULATION_NAME}.c
+echo '             && link_info.combreloc'             >> e${EMULATION_NAME}.c
+echo '             && link_info.relro'                 >> e${EMULATION_NAME}.c
 echo '             && (link_info.flags & DF_BIND_NOW)) return' >> 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
+echo '  ; else if (bfd_link_pie (&link_info)'          >> e${EMULATION_NAME}.c
+echo '             && link_info.combreloc) return'     >> 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
+echo '  ; else if (bfd_link_pie (&link_info)) 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 '  ; else if (bfd_link_dll (&link_info) && link_info.combreloc' >> e${EMULATION_NAME}.c
 echo '             && link_info.relro' >> e${EMULATION_NAME}.c
 echo '             && (link_info.flags & DF_BIND_NOW)) return' >> 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
+echo '  ; else if (bfd_link_dll (&link_info) && link_info.combreloc) return' >> 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
+echo '  ; else if (bfd_link_dll (&link_info)) return'  >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xs                 >> e${EMULATION_NAME}.c
 fi
 if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
@@ -2044,9 +2112,9 @@ fragment <<EOF
 {
   *isfile = 1;
 
-  if (link_info.relocatable && config.build_constructors)
+  if (bfd_link_relocatable (&link_info) && config.build_constructors)
     return "ldscripts/${EMULATION_NAME}.xu";
-  else if (link_info.relocatable)
+  else if (bfd_link_relocatable (&link_info))
     return "ldscripts/${EMULATION_NAME}.xr";
   else if (!config.text_read_only)
     return "ldscripts/${EMULATION_NAME}.xbn";
@@ -2061,30 +2129,33 @@ fi
 if test -n "$GENERATE_PIE_SCRIPT" ; then
 if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
 fragment <<EOF
-  else if (link_info.pie && link_info.combreloc
-          && link_info.relro && (link_info.flags & DF_BIND_NOW))
+  else if (bfd_link_pie (&link_info)
+          && link_info.combreloc
+          && link_info.relro
+          && (link_info.flags & DF_BIND_NOW))
     return "ldscripts/${EMULATION_NAME}.xdw";
-  else if (link_info.pie && link_info.combreloc)
+  else if (bfd_link_pie (&link_info)
+          && link_info.combreloc)
     return "ldscripts/${EMULATION_NAME}.xdc";
 EOF
 fi
 fragment <<EOF
-  else if (link_info.pie)
+  else if (bfd_link_pie (&link_info))
     return "ldscripts/${EMULATION_NAME}.xd";
 EOF
 fi
 if test -n "$GENERATE_SHLIB_SCRIPT" ; then
 if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
 fragment <<EOF
-  else if (link_info.shared && link_info.combreloc
+  else if (bfd_link_dll (&link_info) && link_info.combreloc
           && link_info.relro && (link_info.flags & DF_BIND_NOW))
     return "ldscripts/${EMULATION_NAME}.xsw";
-  else if (link_info.shared && link_info.combreloc)
+  else if (bfd_link_dll (&link_info) && link_info.combreloc)
     return "ldscripts/${EMULATION_NAME}.xsc";
 EOF
 fi
 fragment <<EOF
-  else if (link_info.shared)
+  else if (bfd_link_dll (&link_info))
     return "ldscripts/${EMULATION_NAME}.xs";
 EOF
 fi
@@ -2122,6 +2193,7 @@ fragment <<EOF
 #define OPTION_HASH_STYLE              (OPTION_EXCLUDE_LIBS + 1)
 #define OPTION_BUILD_ID                        (OPTION_HASH_STYLE + 1)
 #define OPTION_AUDIT                   (OPTION_BUILD_ID + 1)
+#define OPTION_COMPRESS_DEBUG          (OPTION_AUDIT + 1)
 
 static void
 gld${EMULATION_NAME}_add_options
@@ -2149,6 +2221,7 @@ EOF
 fi
 fragment <<EOF
     {"build-id", optional_argument, NULL, OPTION_BUILD_ID},
+    {"compress-debug-sections", required_argument, NULL, OPTION_COMPRESS_DEBUG},
 EOF
 if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
 fragment <<EOF
@@ -2187,23 +2260,36 @@ gld${EMULATION_NAME}_handle_option (int optc)
       return FALSE;
 
     case OPTION_BUILD_ID:
-      if (link_info.emit_note_gnu_build_id != NULL)
+      if (emit_note_gnu_build_id != NULL)
        {
-         free (link_info.emit_note_gnu_build_id);
-         link_info.emit_note_gnu_build_id = NULL;
+         free ((char *) emit_note_gnu_build_id);
+         emit_note_gnu_build_id = NULL;
        }
       if (optarg == NULL)
        optarg = DEFAULT_BUILD_ID_STYLE;
       if (strcmp (optarg, "none"))
-       link_info.emit_note_gnu_build_id = xstrdup (optarg);
+       emit_note_gnu_build_id = xstrdup (optarg);
       break;
 
+    case OPTION_COMPRESS_DEBUG:
+      if (strcasecmp (optarg, "none") == 0)
+       link_info.compress_debug = COMPRESS_DEBUG_NONE;
+      else if (strcasecmp (optarg, "zlib") == 0)
+       link_info.compress_debug = COMPRESS_DEBUG_GABI_ZLIB;
+      else if (strcasecmp (optarg, "zlib-gnu") == 0)
+       link_info.compress_debug = COMPRESS_DEBUG_GNU_ZLIB;
+      else if (strcasecmp (optarg, "zlib-gabi") == 0)
+       link_info.compress_debug = COMPRESS_DEBUG_GABI_ZLIB;
+      else
+       einfo (_("%P%F: invalid --compress-debug-sections option: \`%s'\n"),
+              optarg);
+      break;
 EOF
 
 if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
 fragment <<EOF
     case OPTION_AUDIT:
-       gld${EMULATION_NAME}_append_to_separated_string (&audit, optarg); 
+       gld${EMULATION_NAME}_append_to_separated_string (&audit, optarg);
        break;
 
     case 'P':
@@ -2219,7 +2305,7 @@ fragment <<EOF
       break;
 
     case OPTION_EH_FRAME_HDR:
-      link_info.eh_frame_hdr = TRUE;
+      link_info.eh_frame_hdr_type = DWARF2_EH_HDR;
       break;
 
     case OPTION_GROUP:
@@ -2275,6 +2361,17 @@ fragment <<EOF
            einfo (_("%P%F: invalid common page size \`%s'\n"),
                   optarg + 17);
        }
+      else if (CONST_STRNEQ (optarg, "stack-size="))
+       {
+         char *end;
+         link_info.stacksize = strtoul (optarg + 11, &end, 0);
+         if (*end || link_info.stacksize < 0)
+           einfo (_("%P%F: invalid stack size \`%s'\n"), optarg + 11);
+         if (!link_info.stacksize)
+           /* Use -1 for explicit no-stack, because zero means
+              'default'.   */
+           link_info.stacksize = -1;
+       }
       else if (strcmp (optarg, "execstack") == 0)
        {
          link_info.execstack = TRUE;
@@ -2286,8 +2383,11 @@ fragment <<EOF
          link_info.execstack = FALSE;
        }
 EOF
+
 if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
 fragment <<EOF
+      else if (strcmp (optarg, "global") == 0)
+       link_info.flags_1 |= (bfd_vma) DF_1_GLOBAL;
       else if (strcmp (optarg, "initfirst") == 0)
        link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
       else if (strcmp (optarg, "interpose") == 0)
@@ -2327,6 +2427,10 @@ fragment <<EOF
        link_info.relro = TRUE;
       else if (strcmp (optarg, "norelro") == 0)
        link_info.relro = FALSE;
+      else if (strcmp (optarg, "common") == 0)
+       link_info.elf_stt_common = elf_stt_common;
+      else if (strcmp (optarg, "nocommon") == 0)
+       link_info.elf_stt_common = no_elf_stt_common;
       else if (strcmp (optarg, "text") == 0)
        link_info.error_textrel = TRUE;
       else if (strcmp (optarg, "notext") == 0)
@@ -2336,6 +2440,12 @@ fragment <<EOF
 EOF
 fi
 
+if test -n "$PARSE_AND_LIST_ARGS_CASE_Z" ; then
+fragment <<EOF
+ $PARSE_AND_LIST_ARGS_CASE_Z
+EOF
+fi
+
 fragment <<EOF
       else
        einfo (_("%P: warning: -z %s ignored.\n"), optarg);
@@ -2357,106 +2467,14 @@ fragment <<EOF
 EOF
 
 if test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
+gld_list_options="gld${EMULATION_NAME}_list_options"
+if test -n "$PARSE_AND_LIST_OPTIONS"; then
 fragment <<EOF
 
 static void
 gld${EMULATION_NAME}_list_options (FILE * file)
 {
 EOF
-if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
-fragment <<EOF
-  fprintf (file, _("\
-  --audit=AUDITLIB            Specify a library to use for auditing\n"));
-  fprintf (file, _("\
-  -Bgroup                     Selects group name lookup rules for DSO\n"));
-EOF
-fi
-fragment <<EOF
-  fprintf (file, _("\
-  --build-id[=STYLE]          Generate build ID note\n"));
-EOF
-if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
-fragment <<EOF
-  fprintf (file, _("\
-  -P AUDITLIB, --depaudit=AUDITLIB\n" "\
-                              Specify a library to use for auditing dependencies\n"));
-  fprintf (file, _("\
-  --disable-new-dtags         Disable new dynamic tags\n"));
-  fprintf (file, _("\
-  --enable-new-dtags          Enable new dynamic tags\n"));
-  fprintf (file, _("\
-  --eh-frame-hdr              Create .eh_frame_hdr section\n"));
-  fprintf (file, _("\
-  --exclude-libs=LIBS         Make all symbols in LIBS hidden\n"));
-  fprintf (file, _("\
-  --hash-style=STYLE          Set hash style to sysv, gnu or both\n"));
-  fprintf (file, _("\
-  -z combreloc                Merge dynamic relocs into one section and sort\n"));
-EOF
-fi
-
-fragment <<EOF
-  fprintf (file, _("\
-  -z common-page-size=SIZE    Set common page size to SIZE\n"));
-  fprintf (file, _("\
-  -z defs                     Report unresolved symbols in object files.\n"));
-  fprintf (file, _("\
-  -z execstack                Mark executable as requiring executable stack\n"));
-EOF
-
-if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
-fragment <<EOF
-  fprintf (file, _("\
-  -z initfirst                Mark DSO to be initialized first at runtime\n"));
-  fprintf (file, _("\
-  -z interpose                Mark object to interpose all DSOs but executable\n"));
-  fprintf (file, _("\
-  -z lazy                     Mark object lazy runtime binding (default)\n"));
-  fprintf (file, _("\
-  -z loadfltr                 Mark object requiring immediate process\n"));
-EOF
-fi
-
-fragment <<EOF
-  fprintf (file, _("\
-  -z max-page-size=SIZE       Set maximum page size to SIZE\n"));
-  fprintf (file, _("\
-  -z muldefs                  Allow multiple definitions\n"));
-EOF
-
-if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
-fragment <<EOF
-  fprintf (file, _("\
-  -z nocombreloc              Don't merge dynamic relocs into one section\n"));
-  fprintf (file, _("\
-  -z nocopyreloc              Don't create copy relocs\n"));
-  fprintf (file, _("\
-  -z nodefaultlib             Mark object not to use default search paths\n"));
-  fprintf (file, _("\
-  -z nodelete                 Mark DSO non-deletable at runtime\n"));
-  fprintf (file, _("\
-  -z nodlopen                 Mark DSO not available to dlopen\n"));
-  fprintf (file, _("\
-  -z nodump                   Mark DSO not available to dldump\n"));
-EOF
-fi
-fragment <<EOF
-  fprintf (file, _("\
-  -z noexecstack              Mark executable as not requiring executable stack\n"));
-EOF
-if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
-fragment <<EOF
-  fprintf (file, _("\
-  -z norelro                  Don't create RELRO program header\n"));
-  fprintf (file, _("\
-  -z now                      Mark object non-lazy runtime binding\n"));
-  fprintf (file, _("\
-  -z origin                   Mark object requiring immediate \$ORIGIN\n\
-                                processing at runtime\n"));
-  fprintf (file, _("\
-  -z relro                    Create RELRO program header\n"));
-EOF
-fi
 
 if test -n "$PARSE_AND_LIST_OPTIONS" ; then
 fragment <<EOF
@@ -2467,6 +2485,9 @@ fi
 fragment <<EOF
 }
 EOF
+else
+  gld_list_options="NULL"
+fi
 
 if test -n "$PARSE_AND_LIST_EPILOGUE" ; then
 fragment <<EOF
@@ -2482,7 +2503,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
   ${LDEMUL_SYSLIB-syslib_default},
   ${LDEMUL_HLL-hll_default},
-  ${LDEMUL_AFTER_PARSE-after_parse_default},
+  ${LDEMUL_AFTER_PARSE-gld${EMULATION_NAME}_after_parse},
   ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},
   ${LDEMUL_AFTER_ALLOCATION-gld${EMULATION_NAME}_after_allocation},
   ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
@@ -2500,9 +2521,10 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   gld${EMULATION_NAME}_add_options,
   gld${EMULATION_NAME}_handle_option,
   ${LDEMUL_UNRECOGNIZED_FILE-NULL},
-  ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
+  ${LDEMUL_LIST_OPTIONS-${gld_list_options}},
   ${LDEMUL_RECOGNIZED_FILE-gld${EMULATION_NAME}_load_symbols},
   ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
-  ${LDEMUL_NEW_VERS_PATTERN-NULL}
+  ${LDEMUL_NEW_VERS_PATTERN-NULL},
+  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL}
 };
 EOF