]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Merge remote-tracking branch 'origin/users/hjl/linux/master' into users/hjl/linux...
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 11 Jul 2017 10:52:26 +0000 (03:52 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 11 Jul 2017 10:52:26 +0000 (03:52 -0700)
58 files changed:
1  2 
bfd/archive.c
bfd/bfd-in2.h
bfd/bfd.c
bfd/elf.c
bfd/elf32-mips.c
bfd/elf64-ia64-vms.c
bfd/elfcode.h
bfd/elflink.c
bfd/elfn32-mips.c
bfd/format.c
bfd/linker.c
bfd/opncls.c
bfd/plugin.c
bfd/plugin.h
bfd/section.c
bfd/syms.c
binutils/nm.c
binutils/objcopy.c
binutils/readelf.c
gas/config/obj-elf.c
gas/doc/as.texinfo
gas/symbols.c
gas/symbols.h
gas/testsuite/gas/elf/elf.exp
gold/testsuite/icf_safe_pie_test.sh
gold/testsuite/icf_safe_so_test.sh
gold/testsuite/icf_safe_test.sh
include/bfdlink.h
include/elf/common.h
ld/emultempl/aarch64elf.em
ld/emultempl/alphaelf.em
ld/emultempl/armelf.em
ld/emultempl/avrelf.em
ld/emultempl/elf32.em
ld/emultempl/ppc32elf.em
ld/emultempl/ppc64elf.em
ld/emultempl/spuelf.em
ld/ld.texinfo
ld/ldexp.c
ld/ldexp.h
ld/ldfile.c
ld/ldlang.c
ld/ldlang.h
ld/ldlex.h
ld/ldmain.c
ld/ldmain.h
ld/lexsup.c
ld/plugin.c
ld/plugin.h
ld/scripttempl/armbpabi.sc
ld/scripttempl/elf.sc
ld/scripttempl/elf32sh-symbian.sc
ld/scripttempl/elf64hppa.sc
ld/scripttempl/elfxtensa.sc
ld/scripttempl/mep.sc
ld/scripttempl/pe.sc
ld/scripttempl/pep.sc
ld/testsuite/ld-plugin/lto.exp

diff --cc bfd/archive.c
Simple merge
diff --cc bfd/bfd-in2.h
index 2bea73a424e8e75fbc389de32dd2f63277a0037e,1343780c8ceb57e16df15a728df2056b5bb127f3..e481509c6b8ad609b53ef10f536eb1cb588372f9
@@@ -1090,9 -1122,8 +1122,11 @@@ struct bfd_section *bfd_create_gnu_debu
  bfd_boolean bfd_fill_in_gnu_debuglink_section
     (bfd *abfd, struct bfd_section *sect, const char *filename);
  
+ char *bfd_follow_build_id_debuglink (bfd *abfd, const char *dir);
 +const char *bfd_extract_object_only_section
 +   (bfd *abfd);
 +
  /* Extracted from libbfd.c.  */
  
  /* Byte swapping macros for user section data.  */
diff --cc bfd/bfd.c
Simple merge
diff --cc bfd/elf.c
Simple merge
Simple merge
Simple merge
diff --cc bfd/elfcode.h
Simple merge
diff --cc bfd/elflink.c
index 539c28f5f7f683b9f76113212db49dc0f2582d8d,471e8adf5fa7ec5ff8fd47b2e188ab116d86864d..336df3f59c808b72eabcbf46f77d4c288196450b
@@@ -1535,20 -1581,13 +1591,17 @@@ _bfd_elf_merge_symbol (bfd *abfd
       represent variables; this can cause confusion in principle, but
       any such confusion would seem to indicate an erroneous program or
       shared library.  We also permit a common symbol in a regular
-      object to override a weak symbol in a shared object.  A common
-      symbol in executable also overrides a symbol in a shared object.
 -     object to override a weak symbol in a shared object.  */
++     object to override a weak symbol in a shared object.
 +
 +     We let a definition in a dynamic object override the old secondary
 +     symbol.  */
  
    if (newdyn
        && newdef
 +      && !oldsecondary
        && (olddef
          || (h->root.type == bfd_link_hash_common
-             && (newweak
-                 || newfunc
-                 || (!olddyn && bfd_link_executable (info))))))
+             && (newweak || newfunc))))
      {
        *override = TRUE;
        newdef = FALSE;
Simple merge
diff --cc bfd/format.c
index d9978ea609eb22feeb9c703cf33a6768fafc5855,34b2dc2a07d04a886c82d63337d416bf46b43185..c49585ca6f6ba9d08daab4ef22a732b4e63be4aa
@@@ -46,9 -46,6 +46,10 @@@ SUBSECTIO
  #include "sysdep.h"
  #include "bfd.h"
  #include "libbfd.h"
 +#if BFD_SUPPORTS_PLUGINS
++#include "plugin-api.h"
 +#include "plugin.h"
 +#endif
  
  /* IMPORT from targets.c.  */
  extern const size_t _bfd_target_vector_entries;
diff --cc bfd/linker.c
Simple merge
diff --cc bfd/opncls.c
index e3bf284a09e30fbe42528e8935571f8806c0ddaa,913341c9ffc371fb2f22cd3ea37b359d33ce110e..a5393316d1d05ad7591107b1a22ba0d7543a7718
@@@ -1696,68 -1798,261 +1798,327 @@@ bfd_fill_in_gnu_debuglink_section (bfd 
    return TRUE;
  }
  
-   file = real_fopen (name, FOPEN_WB);
+ /*
+ INTERNAL_FUNCTION
+       get_build_id
+ SYNOPSIS
+       struct bfd_build_id * get_build_id (bfd *abfd);
+ DESCRIPTION
+       Finds the build-id associated with @var{abfd}.  If the build-id is
+       extracted from the note section then a build-id structure is built
+       for it, using memory allocated to @var{abfd}, and this is then
+       attached to the @var{abfd}.
+ RETURNS
+       Returns a pointer to the build-id structure if a build-id could be
+       found.  If no build-id is found NULL is returned and error code is
+       set.
+ */
+ static struct bfd_build_id *
+ get_build_id (bfd *abfd)
+ {
+   struct bfd_build_id *build_id;
+   Elf_Internal_Note inote;
+   Elf_External_Note *enote;
+   bfd_byte *contents;
+   asection *sect;
+   bfd_size_type size;
+   BFD_ASSERT (abfd);
+   if (abfd->build_id && abfd->build_id->size > 0)
+     /* Save some time by using the already computed build-id.  */
+     return (struct bfd_build_id *) abfd->build_id;
+   sect = bfd_get_section_by_name (abfd, ".note.gnu.build-id");
+   if (sect == NULL)
+     {
+       bfd_set_error (bfd_error_no_debug_section);
+       return NULL;
+     }
+   size = bfd_get_section_size (sect);
+   /* FIXME: Should we support smaller build-id notes ?  */
+   if (size < 0x24)
+     {
+       bfd_set_error (bfd_error_invalid_operation);
+       return NULL;
+     }
+   if (!bfd_malloc_and_get_section (abfd, sect, & contents))
+     {
+       if (contents != NULL)
+       free (contents);
+       return NULL;
+     }
+   /* FIXME: Paranoia - allow for compressed build-id sections.
+      Maybe we should complain if this size is different from
+      the one obtained above...  */
+   size = bfd_get_section_size (sect);
+   if (size < sizeof (Elf_External_Note))
+     {
+       bfd_set_error (bfd_error_invalid_operation);
+       free (contents);
+       return NULL;
+     }
+   enote = (Elf_External_Note *) contents;
+   inote.type = H_GET_32 (abfd, enote->type);
+   inote.namesz = H_GET_32 (abfd, enote->namesz);
+   inote.namedata = enote->name;
+   inote.descsz = H_GET_32 (abfd, enote->descsz);
+   inote.descdata = inote.namedata + BFD_ALIGN (inote.namesz, 4);
+   /* FIXME: Should we check for extra notes in this section ?  */
+   if (inote.descsz == 0
+       || inote.type != NT_GNU_BUILD_ID
+       || inote.namesz != 4 /* sizeof "GNU"  */
+       || strncmp (inote.namedata, "GNU", 4) != 0
+       || size < (12 + BFD_ALIGN (inote.namesz, 4) + inote.descsz))
+     {
+       free (contents);
+       bfd_set_error (bfd_error_invalid_operation);
+       return NULL;
+     }
+   build_id = bfd_alloc (abfd, sizeof (struct bfd_build_id) + inote.descsz);
+   if (build_id == NULL)
+     {
+       free (contents);
+       return NULL;
+     }
+   build_id->size = inote.descsz;
+   memcpy (build_id->data, inote.descdata, inote.descsz);
+   abfd->build_id = build_id;
+   free (contents);
+   return build_id;
+ }
+ /*
+ INTERNAL_FUNCTION
+       get_build_id_name
+ SYNOPSIS
+       char * get_build_id_name (bfd *abfd, void *build_id_out_p)
+ DESCRIPTION
+       Searches @var{abfd} for a build-id, and then constructs a pathname
+       from it.  The path is computed as .build-id/NN/NN+NN.debug where
+       NNNN+NN is the build-id value as a hexadecimal string.
+ RETURNS
+       Returns the constructed filename or NULL upon error.
+       It is the caller's responsibility to free the memory used to hold the
+       filename.
+       If a filename is returned then the @var{build_id_out_p}
+       parameter (which points to a @code{struct bfd_build_id}
+       pointer) is set to a pointer to the build_id structure.
+ */
+ static char *
+ get_build_id_name (bfd *abfd, void *build_id_out_p)
+ {
+   struct bfd_build_id **build_id_out = build_id_out_p;
+   struct bfd_build_id *build_id;
+   char *name;
+   char *n;
+   bfd_size_type s;
+   bfd_byte *d;
+   if (abfd == NULL || abfd->filename == NULL || build_id_out == NULL)
+     {
+       bfd_set_error (bfd_error_invalid_operation);
+       return NULL;
+     }
+   build_id = get_build_id (abfd);
+   if (build_id == NULL)
+     return NULL;
+   /* Compute the debug pathname corresponding to the build-id.  */
+   name = bfd_malloc (strlen (".build-id/") + build_id->size * 2 + 2 + strlen (".debug"));
+   if (name == NULL)
+     {
+       bfd_set_error (bfd_error_no_memory);
+       return NULL;
+     }
+   n = name;
+   d = build_id->data;
+   s = build_id->size;
+   n += sprintf (n, ".build-id/");
+   n += sprintf (n, "%02x", (unsigned) *d++); s--;
+   n += sprintf (n, "/");
+   while (s--)
+     n += sprintf (n, "%02x", (unsigned) *d++);
+   n += sprintf (n, ".debug");
+   *build_id_out = build_id;
+   return name;
+ }
+ /*
+ INTERNAL_FUNCTION
+       check_build_id_file
+ SYNOPSIS
+       bfd_boolean check_build_id_file (char *name, void *buildid_p);
+ DESCRIPTION
+       Checks to see if @var{name} is a readable file and if its build-id
+       matches @var{buildid}.
+ RETURNS
+       Returns TRUE if the file exists, is readable, and contains a
+       build-id which matches the build-id pointed at by
+       @var{build_id_p} (which is really a @code{struct bfd_build_id **}).
+ */
+ static bfd_boolean
+ check_build_id_file (const char *name, void *buildid_p)
+ {
+   struct bfd_build_id *orig_build_id;
+   struct bfd_build_id *build_id;
+   bfd * file;
+   bfd_boolean result;
+   BFD_ASSERT (name);
+   BFD_ASSERT (buildid_p);
+   file = bfd_openr (name, NULL);
+   if (file == NULL)
+     return FALSE;
+   /* If the file is an archive, process all of its elements.  */
+   if (! bfd_check_format (file, bfd_object))
+     {
+       bfd_close (file);
+       return FALSE;
+     }
+   build_id = get_build_id (file);
+   if (build_id == NULL)
+     {
+       bfd_close (file);
+       return FALSE;
+     }
+   orig_build_id = *(struct bfd_build_id **) buildid_p;
+   result = build_id->size == orig_build_id->size
+     && memcmp (build_id->data, orig_build_id->data, build_id->size) == 0;
+   (void) bfd_close (file);
+   return result;
+ }
+ /*
+ FUNCTION
+       bfd_follow_build_id_debuglink
+ SYNOPSIS
+       char *bfd_follow_build_id_debuglink (bfd *abfd, const char *dir);
+ DESCRIPTION
+       Takes @var{abfd} and searches it for a .note.gnu.build-id section.
+       If this section is found, it extracts the value of the NT_GNU_BUILD_ID
+       note, which should be a hexadecimal value @var{NNNN+NN} (for
+       32+ hex digits).  It then searches the filesystem for a file named
+       @var{.build-id/NN/NN+NN.debug} in a set of standard locations,
+       including the directory tree rooted at @var{dir}.  The filename
+       of the first matching file to be found is returned.  A matching
+       file should contain a .note.gnu.build-id section with the same
+       @var{NNNN+NN} note as @var{abfd}, although this check is currently
+       not implemented.
+       If @var{dir} is NULL, the search will take place starting at
+       the current directory.
+ RETURNS
+       <<NULL>> on any errors or failure to locate the debug file,
+       otherwise a pointer to a heap-allocated string containing the
+       filename.  The caller is responsible for freeing this string.
+ */
+ char *
+ bfd_follow_build_id_debuglink (bfd *abfd, const char *dir)
+ {
+   struct bfd_build_id *build_id;
+   return find_separate_debug_file (abfd, dir, FALSE,
+                                  get_build_id_name,
+                                  check_build_id_file, &build_id);
+ }
++
 +/*
 +FUNCTION
 +      bfd_extract_object_only_section
 +
 +SYNOPSIS
 +      const char *bfd_extract_object_only_section
 +        (bfd *abfd);
 +
 +DESCRIPTION
 +
 +      Takes a @var{ABFD} and extract the .gnu_object_only section into
 +      a temporary file.
 +
 +RETURNS
 +      The name of the temporary file is returned if all is ok.
 +      Otherwise <<NULL>> is returned and bfd_error is set.
 +*/
 +
 +const char *
 +bfd_extract_object_only_section (bfd *abfd)
 +{
 +  asection *sec = abfd->object_only_section;
 +  const char *name;
 +  FILE *file;
 +  bfd_byte *memhunk = NULL;
 +  size_t off, size;
 +  bfd_error_type err;
 +
 +  /* Get a temporary object-only file.  */
 +  name = make_temp_file (".obj-only.o");
 +
 +  /* Open the object-only file.  */
++  file = _bfd_real_fopen (name, FOPEN_WB);
 +  if (!bfd_get_full_section_contents (abfd, sec, &memhunk))
 +    {
 +      err = bfd_get_error ();
 +
 +loser:
 +      free (memhunk);
 +      fclose (file);
 +      unlink (name);
 +      bfd_set_error (err);
 +      return NULL;
 +    }
 +
 +  off = 0;
 +  size = sec->size;
 +  while (off != size)
 +    {
 +      size_t written, nwrite = size - off;
 +
 +      written = fwrite (memhunk + off, 1, nwrite, file);
 +      if (written < nwrite && ferror (file))
 +      {
 +        err = bfd_error_system_call;
 +        goto loser;
 +      }
 +
 +      off += written;
 +    }
 +
 +  free (memhunk);
 +  fclose (file);
 +  return name;
 +}
diff --cc bfd/plugin.c
index 2c985f02b2c8f511b254e7032cd172607fe8ab74,af50be12b89cb6a4b0ee1726d1dddd56e7574d67..bc07a09bb2f23f513a3ca449c5f2e1c9289e28ba
@@@ -131,146 -132,6 +132,146 @@@ register_claim_file (ld_plugin_claim_fi
    return LDPS_OK;
  }
  
-   = BFD_FAKE_SECTION (bfd_plugin_fake_text_section, 0, 0, ".text", 0);
 +static asection bfd_plugin_fake_text_section
-   = BFD_FAKE_SECTION (bfd_plugin_fake_common_section, SEC_IS_COMMON, 0,
-                     NULL, 0);
++  = BFD_FAKE_SECTION (bfd_plugin_fake_text_section, NULL, ".text", 0, 0);
 +static asection bfd_plugin_fake_common_section
++  = BFD_FAKE_SECTION (bfd_plugin_fake_common_section, NULL, NULL,
++                    0, SEC_IS_COMMON);
 +
 +/* Get symbols from object only section.  */
 +
 +static void
 +bfd_plugin_get_symbols_in_object_only (bfd *abfd)
 +{
 +  struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
 +  const char *object_only_file;
 +  bfd *nbfd;
 +  long storage;
 +  long object_only_nsyms, added_nsyms, i;
 +  asymbol **object_only_syms, **added_syms;
 +
 +  plugin_data->object_only_syms = NULL;
 +  plugin_data->object_only_nsyms = 0;
 +
 +  if (abfd->sections == NULL && abfd->my_archive == NULL)
 +    {
 +      nbfd = bfd_openr (abfd->filename, NULL);
 +      if (nbfd == NULL)
 +      {
 +        (*_bfd_error_handler)
 +          (_("%s: failed to open to extract object only section: %s"),
 +           abfd->filename, bfd_errmsg (bfd_get_error ()));
 +        goto error_return;
 +      }
 +      else if (!bfd_check_format (nbfd, bfd_object))
 +      {
 +        /* There is no object only section if it isn't a bfd_object
 +           file.  */
 +error_return:
 +        bfd_close (nbfd);
 +        return;
 +      }
 +    }
 +  else
 +    {
 +      if (!bfd_check_format (abfd, bfd_object))
 +      {
 +        (*_bfd_error_handler)
 +          (_("%B: invalid file to extract object only section: %s"),
 +           abfd, bfd_errmsg (bfd_get_error ()));
 +        return;
 +      }
 +      nbfd = abfd;
 +    }
 +
 +  if (nbfd->lto_type == lto_mixed_object
 +      && (nbfd->flags & HAS_SYMS) != 0)
 +    {
 +      object_only_file = bfd_extract_object_only_section (nbfd);
 +      if (object_only_file == NULL)
 +      (*_bfd_error_handler)
 +        (_("%B: failed to extract object only section: %s"),
 +         abfd, bfd_errmsg (bfd_get_error ()));
 +    }
 +  else
 +    object_only_file = NULL;
 +
 +  /* Close the new bfd we just opened.  */
 +  if (nbfd != abfd)
 +    bfd_close (nbfd);
 +
 +  /* Return if there is no object only section or there is no
 +     symbol in object only section.  */
 +  if (!object_only_file)
 +    return;
 +
 +  /* Open the file containing object only section.  */
 +  nbfd = bfd_openr (object_only_file, NULL);
 +  if (!bfd_check_format (nbfd, bfd_object))
 +    {
 +      (*_bfd_error_handler)
 +      (_("%B: failed to open object only section: %s"),
 +       abfd, bfd_errmsg (bfd_get_error ()));
 +      goto quit;
 +    }
 +
 +  storage = bfd_get_symtab_upper_bound (nbfd);
 +  if (storage <= 0)
 +    {
 +      if (storage < 0)
 +      (*_bfd_error_handler)
 +        (_("%B: failed to get symbol table in object only section: %s"),
 +         abfd, bfd_errmsg (bfd_get_error ()));
 +
 +      goto quit;
 +    }
 +
 +  object_only_syms = (asymbol **) bfd_malloc (storage);
 +  object_only_nsyms = bfd_canonicalize_symtab (nbfd, object_only_syms);
 +
 +  /* FIXME: We waste some spaces if not all symbols are copied.  */
 +  added_syms = (asymbol **) bfd_alloc (abfd, storage);
 +  added_nsyms = 0;
 +
 +  /* Copy only global symbols from object only section.  */
 +  for (i = 0; i < object_only_nsyms; i++)
 +    {
 +      asection *sec = object_only_syms[i]->section;
 +      flagword flags = object_only_syms[i]->flags;
 +      asymbol *s;
 +
 +      if (bfd_is_com_section (sec))
 +      sec = &bfd_plugin_fake_common_section;
 +      else if (bfd_is_und_section (sec))
 +      ;
 +      else if ((flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0)
 +      sec = &bfd_plugin_fake_text_section;
 +      else
 +      continue;
 +
 +      s = bfd_alloc (abfd, sizeof (asymbol));
 +      BFD_ASSERT (s);
 +      added_syms[added_nsyms++] = s;
 +
 +      s->section = sec;
 +      s->the_bfd = abfd;
 +      s->name = xstrdup (object_only_syms[i]->name);
 +      s->value = 0;
 +      s->flags = flags;
 +      s->udata.p = NULL;
 +    }
 +
 +  plugin_data->object_only_syms = added_syms;
 +  plugin_data->object_only_nsyms = added_nsyms;
 +
 +  free (object_only_syms);
 +
 +quit:
 +  /* Close and remove the object only section file.  */
 +  bfd_close (nbfd);
 +  unlink (object_only_file);
 +}
 +
  static enum ld_plugin_status
  add_symbols (void * handle,
             int nsyms,
diff --cc bfd/plugin.h
Simple merge
diff --cc bfd/section.c
Simple merge
diff --cc bfd/syms.c
Simple merge
diff --cc binutils/nm.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gas/symbols.c
index 518d268ffcadad28762857594af670d01bd2dd27,19a1fa57283f1f97e759db85655121d0d58e4f6f..b6ab17b6ca1d2e8b36dbdd6acae11634f926957c
@@@ -2090,16 -2105,20 +2113,20 @@@ S_IS_DEFINED (symbolS *s
  int
  S_FORCE_RELOC (symbolS *s, int strict)
  {
+   segT sec;
    if (LOCAL_SYMBOL_CHECK (s))
-     return ((struct local_symbol *) s)->lsy_section == undefined_section;
-   return ((strict
+     sec = ((struct local_symbol *) s)->lsy_section;
+   else
+     {
+       if ((strict
 -         && ((s->bsym->flags & BSF_WEAK) != 0
 +         && ((s->bsym->flags & (BSF_WEAK | BSF_SECONDARY)) != 0
               || (EXTERN_FORCE_RELOC
                   && (s->bsym->flags & BSF_GLOBAL) != 0)))
-         || (s->bsym->flags & BSF_GNU_INDIRECT_FUNCTION) != 0
-         || s->bsym->section == undefined_section
-         || bfd_is_com_section (s->bsym->section));
+         || (s->bsym->flags & BSF_GNU_INDIRECT_FUNCTION) != 0)
+       return TRUE;
+       sec = s->bsym->section;
+     }
+   return bfd_is_und_section (sec) || bfd_is_com_section (sec);
  }
  
  int
diff --cc gas/symbols.h
Simple merge
Simple merge
index 0000000000000000000000000000000000000000,f91a80c0b95561fa4f78d9c38a1f991cd2554d47..da726da99fb47e48f76ba30aeb395d270ba7f34d
mode 000000,100755..100755
--- /dev/null
@@@ -1,0 -1,76 +1,79 @@@
 -check_fold   icf_safe_pie_test.map "_ZN1AD2Ev" "_ZN1AC2Ev"
+ #!/bin/sh
+ # icf_safe_pie_test.sh -- test --icf=safe -pie
+ # Copyright (C) 2009-2017 Free Software Foundation, Inc.
+ # Written by Sriraman Tallam <tmsriram@google.com>.
+ # Modified by Rahul Chaudhry <rahulchaudhry@google.com>.
+ # This file is part of gold.
+ # This program is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation; either version 3 of the License, or
+ # (at your option) any later version.
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ # 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., 51 Franklin Street - Fifth Floor, Boston,
+ # MA 02110-1301, USA.
+ # The goal of this program is to verify if --icf=safe works with
+ # -pie as expected. File icf_safe_test.cc is in this test. This
+ # program checks if only ctors and dtors are folded, except for
+ # the architectures which use relocation types and instruction
+ # opcodes to detect if function pointers are taken.
+ set -e
+ check_nofold()
+ {
+     func_addr_1=`grep $2 $1 | awk '{print $1}'`
+     func_addr_2=`grep $3 $1 | awk '{print $1}'`
+     if [ $func_addr_1 = $func_addr_2 ]
+     then
+         echo "Safe Identical Code Folding folded" $2 "and" $3
+       exit 1
+     fi
+ }
+ check_fold()
+ {
+     awk "
+ BEGIN { discard = 0; }
+ /^Discarded input/ { discard = 1; }
+ /^Memory map/ { discard = 0; }
+ /.*\\.text\\..*($2|$3).*/ { act[discard] = act[discard] \" \" \$0; }
+ END {
+       # printf \"kept\" act[0] \"\\nfolded\" act[1] \"\\n\";
+       if (length(act[0]) == 0 || length(act[1]) == 0)
+       {
+         printf \"Safe Identical Code Folding did not fold $2 and $3\\n\"
+         exit 1;
+       }
+     }" $1
+ }
+ arch_specific_safe_fold()
+ {
+     if grep -q -e "Advanced Micro Devices X86-64" -e "Intel 80386" -e "ARM" -e "TILE" -e "PowerPC" -e "AArch64" -e "IBM S/390" $2;
+     then
+       check_fold $3 $4 $5
+     else
+       check_nofold $1 $4 $5
+     fi
+ }
+ arch_specific_safe_fold icf_safe_pie_test_1.stdout icf_safe_pie_test_2.stdout \
+   icf_safe_pie_test.map "kept_func_1" "kept_func_2"
++if grep -q _ZN1A[CD]2Ev icf_safe_pie_test_1.stdout
++then
++    check_fold   icf_safe_pie_test.map "_ZN1AD2Ev" "_ZN1AC2Ev"
++fi
+ check_nofold icf_safe_pie_test_1.stdout "kept_func_3" "kept_func_1"
+ check_nofold icf_safe_pie_test_1.stdout "kept_func_3" "kept_func_2"
index 9a9adace6822b97081c57f0806b62f3f3e881347,28600be561552bf5ea4e6bec5075093a29501abb..bf13d381239ebfae95171b098d89b3b393df3fdd
@@@ -74,7 -76,7 +76,9 @@@ BEGIN { discard = 0; 
  /.*\\.text\\..*($2|$3).*/ { act[discard] = act[discard] \" \" \$0; }
  END {
        # printf \"kept\" act[0] \"\\nfolded\" act[1] \"\\n\";
--      if (length(act[0]) == 0 || length(act[1]) == 0)
++      # Since one or both symbols can be folded here, it is an error only
++      # if no symbol is folded.
++      if (length(act[1]) == 0)
        {
          printf \"Safe Identical Code Folding did not fold $2 and $3\\n\"
          exit 1;
index c6afd0020f54f6402ec3cbc4db4071b640654647,f048d8617d85b7b9b35c7517e3d29e0fd93a2cce..dae858203922b018f319e1fffa02e15c5711208c
@@@ -68,6 -69,6 +69,9 @@@ arch_specific_safe_fold(
  
  arch_specific_safe_fold icf_safe_test_1.stdout icf_safe_test_2.stdout \
    icf_safe_test.map "kept_func_1" "kept_func_2"
--check_fold   icf_safe_test.map "_ZN1AD2Ev" "_ZN1AC2Ev"
++if grep -q _ZN1A[CD]2Ev icf_safe_test_1.stdout
++then
++    check_fold   icf_safe_test.map "_ZN1AD2Ev" "_ZN1AC2Ev"
++fi
  check_nofold icf_safe_test_1.stdout "kept_func_3" "kept_func_1"
  check_nofold icf_safe_test_1.stdout "kept_func_3" "kept_func_2"
index b7ffe2906093e602863ae5f006778e1bf52aaef3,e7c7836f7fa3fc8fb7017f71fb2b808f7d515468..1bc0ce1f2d307f9601906a4186dcd7f4bff22a54
@@@ -108,9 -112,9 +112,12 @@@ struct bfd_link_hash_entr
       in a linker script.  */
    unsigned int linker_def : 1;
  
+   /* Symbol defined in a linker script.  */
+   unsigned int ldscript_def : 1;
 +  /* Set if it is a secondary symbol.  */
 +  unsigned int secondary : 1;
 +
    /* A union of information depending upon the type.  */
    union
      {
Simple merge
Simple merge
Simple merge
index 04e450a767e44f93644b1a807952cf2ddc5c75da,8a57727255afe983a8f67ed6afc2c9192dac147b..7a83dff49b6b558dea68b66c7724cf39e14de0eb
@@@ -434,11 -441,11 +441,11 @@@ arm_finish (void
        }
      }
  
 -  finish_default ();
 +  gld${EMULATION_NAME}_finish ();
  
-   if (thumb_entry_symbol)
+   if (params.thumb_entry_symbol)
      {
-       h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
+       h = bfd_link_hash_lookup (link_info.hash, params.thumb_entry_symbol,
                                FALSE, FALSE, TRUE);
      }
    else
Simple merge
Simple merge
Simple merge
index 10d0b7d629333c2e40b823cd933c3a1e8eb380bc,58cb798cb1254955ef810462f2bdbe0fe4bc2c7d..62d19f78ae9028741394101744fc87b5a9c12277
@@@ -593,8 -592,7 +592,7 @@@ ppc_finish (void
    if (msg != NULL)
      free (msg);
  
-   ppc64_elf_restore_symbols (&link_info);
 -  finish_default ();
 +  gld${EMULATION_NAME}_finish ();
  }
  
  
Simple merge
diff --cc ld/ld.texinfo
Simple merge
diff --cc ld/ldexp.c
Simple merge
diff --cc ld/ldexp.h
Simple merge
diff --cc ld/ldfile.c
Simple merge
diff --cc ld/ldlang.c
Simple merge
diff --cc ld/ldlang.h
Simple merge
diff --cc ld/ldlex.h
Simple merge
diff --cc ld/ldmain.c
index 6a28355d33e8fc081aa820feee25843ddb581882,ee5ab1166ade91a6de329cc97ff3179c0ed8ba61..182291c59e9106ef166194910c50a3edd1487e48
@@@ -217,11 -227,11 +227,14 @@@ main (int argc, char **argv
       leave no trace.  */
    default_bfd_assert_handler = bfd_set_assert_handler (ld_bfd_assert_handler);
  
+   /* Also hook the bfd error/warning handler for --fatal-warnings.  */
+   default_bfd_error_handler = bfd_set_error_handler (ld_bfd_error_handler);
    xatexit (ld_cleanup);
  
 +  /* Remove temporary object-only files.  */
 +  xatexit (cmdline_remove_object_only_files);
 +
    /* Set up the sysroot directory.  */
    ld_sysroot = get_sysroot (argc, argv);
    if (*ld_sysroot)
diff --cc ld/ldmain.h
Simple merge
diff --cc ld/lexsup.c
index 7fbca86177e912f43ac349066e63bc23d62f8b72,08106bcc1a9bd5d8b0aeb501c93351e25da6b479..177df0e2437dd2706a8236eb4060e35816859105
@@@ -1777,9 -1792,7 +1798,9 @@@ elf_shlib_list_options (FILE *file
    fprintf (file, _("\
    -z nocommon                 Generate common symbols with STT_OBJECT type\n"));
    fprintf (file, _("\
-   -z stacksize=SIZE           Set size of stack segment\n"));
 +  -z nosecondary              Convert secondary symbols to weak symbols\n"));
 +  fprintf (file, _("\
+   -z stack-size=SIZE          Set size of stack segment\n"));
    fprintf (file, _("\
    -z text                     Treat DT_TEXTREL in shared object as error\n"));
    fprintf (file, _("\
diff --cc ld/plugin.c
Simple merge
diff --cc ld/plugin.h
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge