Generate the GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION marker for
-fsingle-global-definition to indicate that the object file requires
canonical function pointers and cannot be used with copy relocation.

        * configure.ac (HAVE_LD_SINGLE_GLOBAL_DEFINITION_SUPPORT): New.
        Define to 1 if linker supports -z single-global-definition.
        * output.h (emit_gnu_property): New.
        (emit_gnu_property_note): Likewise.
        * target.def (emit_gnu_property_note): Add a argetm.asm_out hook.
        * toplev.c (compile_file): Call emit_gnu_property_note before
        file_end.
        * varasm.c (emit_gnu_property): New.
        (emit_gnu_property_note): Likewise.
        * config.in: Regenerated.
        * configure: Likewise.
        * doc/tm.texi: Likewise.
        * config/i386/gnu-property.c (emit_gnu_property): Removed.
        (TARGET_ASM_EMIT_GNU_PROPERTY_NOTE): New.
        * doc/tm.texi.in: Add TARGET_ASM_EMIT_GNU_PROPERTY_NOTE.
---
 gcc/config.in                  |  6 +++++
 gcc/config/i386/gnu-property.c | 31 ----------------------
 gcc/config/i386/i386.c         |  2 ++
 gcc/configure                  | 42 +++++++++++++++++++++++++++---
 gcc/configure.ac               | 20 +++++++++++++++
 gcc/doc/tm.texi                |  5 ++++
 gcc/doc/tm.texi.in             |  2 ++
 gcc/output.h                   |  2 ++
 gcc/target.def                 |  8 ++++++
 gcc/toplev.c                   |  3 +++
 gcc/varasm.c                   | 47 ++++++++++++++++++++++++++++++++++
 11 files changed, 134 insertions(+), 34 deletions(-)

diff --git a/gcc/config.in b/gcc/config.in
index 18e627141cc..ee2a94f3847 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1690,6 +1690,12 @@
 #endif
 
 
+/* Define to 1 if your linker supports -z single-global-definition */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_SINGLE_GLOBAL_DEFINITION_SUPPORT
+#endif
+
+
 /* Define if your linker supports the *_sol2 emulations. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_LD_SOL2_EMULATION
diff --git a/gcc/config/i386/gnu-property.c b/gcc/config/i386/gnu-property.c
index 4ba04403002..9fe8d00132e 100644
--- a/gcc/config/i386/gnu-property.c
+++ b/gcc/config/i386/gnu-property.c
@@ -24,37 +24,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "output.h"
 #include "linux-common.h"
 
-static void
-emit_gnu_property (unsigned int type, unsigned int data)
-{
-  int p2align = ptr_mode == SImode ? 2 : 3;
-
-  switch_to_section (get_section (".note.gnu.property",
-                                 SECTION_NOTYPE, NULL));
-
-  ASM_OUTPUT_ALIGN (asm_out_file, p2align);
-  /* name length.  */
-  fprintf (asm_out_file, ASM_LONG "1f - 0f\n");
-  /* data length.  */
-  fprintf (asm_out_file, ASM_LONG "4f - 1f\n");
-  /* note type: NT_GNU_PROPERTY_TYPE_0.  */
-  fprintf (asm_out_file, ASM_LONG "5\n");
-  fprintf (asm_out_file, "0:\n");
-  /* vendor name: "GNU".  */
-  fprintf (asm_out_file, STRING_ASM_OP "\"GNU\"\n");
-  fprintf (asm_out_file, "1:\n");
-  ASM_OUTPUT_ALIGN (asm_out_file, p2align);
-  /* pr_type.  */
-  fprintf (asm_out_file, ASM_LONG "0x%x\n", type);
-  /* pr_datasz.  */
-  fprintf (asm_out_file, ASM_LONG "3f - 2f\n");
-  fprintf (asm_out_file, "2:\n");
-  fprintf (asm_out_file, ASM_LONG "0x%x\n", data);
-  fprintf (asm_out_file, "3:\n");
-  ASM_OUTPUT_ALIGN (asm_out_file, p2align);
-  fprintf (asm_out_file, "4:\n");
-}
-
 void
 file_end_indicate_exec_stack_and_gnu_property (void)
 {
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 9878c3126d0..b1268756322 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -24036,6 +24036,8 @@ ix86_run_selftests (void)
 #if !TARGET_MACHO && !TARGET_DLLIMPORT_DECL_ATTRIBUTES
 # undef TARGET_ASM_RELOC_RW_MASK
 # define TARGET_ASM_RELOC_RW_MASK ix86_reloc_rw_mask
+# undef TARGET_ASM_EMIT_GNU_PROPERTY_NOTE
+# define TARGET_ASM_EMIT_GNU_PROPERTY_NOTE emit_gnu_property_note
 #endif
 
 static bool ix86_libc_has_fast_function (int fcode ATTRIBUTE_UNUSED)
diff --git a/gcc/configure b/gcc/configure
index dd0194a57f4..3d53ce8cc9a 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -911,6 +911,7 @@ infodir
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -1085,6 +1086,7 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE}'
@@ -1337,6 +1339,15 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1474,7 +1485,7 @@ fi
 for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
                datadir sysconfdir sharedstatedir localstatedir includedir \
                oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-               libdir localedir mandir
+               libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1627,6 +1638,7 @@ Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -19435,7 +19447,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 19438 "configure"
+#line 19450 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -19541,7 +19553,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 19544 "configure"
+#line 19556 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -32167,6 +32179,30 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_bndplt_support" >&5
 $as_echo "$ld_bndplt_support" >&6; }
 
+# Check linker supports '-z single-global-definition'
+ld_single_global_definition=0
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker -z 
single-global-definition option" >&5
+$as_echo_n "checking linker -z single-global-definition option... " >&6; }
+if test x"$ld_is_gold" = xno; then
+  if test $in_tree_ld = yes ; then
+    if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" 
-ge 37 -o "$gcc_cv_gld_major_version" -gt 2; then
+      ld_single_global_definition=1
+    fi
+  elif test x$gcc_cv_ld != x; then
+    # Check if linker supports -z single-global-definition option
+    if $gcc_cv_ld --help 2>&1 | grep -- '-z single-global-definition' > 
/dev/null; then
+      ld_single_global_definition=1
+    fi
+  fi
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LD_SINGLE_GLOBAL_DEFINITION_SUPPORT $ld_single_global_definition
+_ACEOF
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_single_global_definition" 
>&5
+$as_echo "$ld_single_global_definition" >&6; }
+
 # Check linker supports '--push-state'/'--pop-state'
 ld_pushpopstate_support=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker 
--push-state/--pop-state options" >&5
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 5f30f80833e..14ca4f450fa 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -7473,6 +7473,26 @@ if test x"$ld_bndplt_support" = xyes; then
 fi
 AC_MSG_RESULT($ld_bndplt_support)
 
+# Check linker supports '-z single-global-definition'
+ld_single_global_definition=0
+AC_MSG_CHECKING(linker -z single-global-definition option)
+if test x"$ld_is_gold" = xno; then
+  if test $in_tree_ld = yes ; then
+    if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" 
-ge 37 -o "$gcc_cv_gld_major_version" -gt 2; then
+      ld_single_global_definition=1
+    fi
+  elif test x$gcc_cv_ld != x; then
+    # Check if linker supports -z single-global-definition option
+    if $gcc_cv_ld --help 2>&1 | grep -- '-z single-global-definition' > 
/dev/null; then
+      ld_single_global_definition=1
+    fi
+  fi
+fi
+AC_DEFINE_UNQUOTED(HAVE_LD_SINGLE_GLOBAL_DEFINITION_SUPPORT,
+       $ld_single_global_definition,
+       [Define to 1 if your linker supports -z single-global-definition])
+AC_MSG_RESULT($ld_single_global_definition)
+
 # Check linker supports '--push-state'/'--pop-state'
 ld_pushpopstate_support=no
 AC_MSG_CHECKING(linker --push-state/--pop-state options)
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 2a41ae5fba1..5b1f5c135b0 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -8073,6 +8073,11 @@ Output to @code{asm_out_file} any text which the 
assembler expects
 to find at the end of a file.  The default is to output nothing.
 @end deftypefn
 
+@deftypefn {Target Hook} void TARGET_ASM_EMIT_GNU_PROPERTY_NOTE (void)
+Output a GNU property note to @code{asm_out_file}.  The default is to
+output nothing.
+@end deftypefn
+
 @deftypefun void file_end_indicate_exec_stack ()
 Some systems use a common convention, the @samp{.note.GNU-stack}
 special section, to indicate whether or not an object file relies on
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index f881cdabe9e..7091e02ca81 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -5050,6 +5050,8 @@ This describes the overall framework of an assembly file.
 
 @hook TARGET_ASM_FILE_END
 
+@hook TARGET_ASM_EMIT_GNU_PROPERTY_NOTE
+
 @deftypefun void file_end_indicate_exec_stack ()
 Some systems use a common convention, the @samp{.note.GNU-stack}
 special section, to indicate whether or not an object file relies on
diff --git a/gcc/output.h b/gcc/output.h
index 73ca4545f4f..f9cbf7cab37 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -607,6 +607,8 @@ extern void default_asm_declare_constant_name (FILE *, 
const char *,
 extern void default_file_start (void);
 extern void file_end_indicate_exec_stack (void);
 extern void file_end_indicate_split_stack (void);
+extern void emit_gnu_property (unsigned int, unsigned int);
+extern void emit_gnu_property_note (void);
 
 extern void default_elf_asm_output_external (FILE *file, tree,
                                             const char *);
diff --git a/gcc/target.def b/gcc/target.def
index c009671c583..31e8bc0ab97 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -715,6 +715,14 @@ to find at the end of a file.  The default is to output 
nothing.",
  void, (void),
  hook_void_void)
 
+/* Output a GNU property note.  */
+DEFHOOK
+(emit_gnu_property_note,
+ "Output a GNU property note to @code{asm_out_file}.  The default is to\n\
+output nothing.",
+ void, (void),
+ hook_void_void)
+
 /* Output any boilerplate text needed at the beginning of an
    LTO output stream.  */
 DEFHOOK
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 55e7550151f..bddcfdf5bde 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -585,6 +585,9 @@ compile_file (void)
   /* Invoke registered plugin callbacks.  */
   invoke_plugin_callbacks (PLUGIN_FINISH_UNIT, NULL);
 
+  /* Output a GNU property note.  */
+  targetm.asm_out.emit_gnu_property_note ();
+
   /* This must be at the end.  Some target ports emit end of file directives
      into the assembly file here, and hence we cannot output anything to the
      assembly file after this point.  */
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 53cf6dea3f3..260b47131d8 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -7729,6 +7729,53 @@ default_file_start (void)
     }
 }
 
+/* Emit one GNU property of TYPE and DATA.  */
+
+void
+emit_gnu_property (unsigned int type, unsigned int data)
+{
+  int p2align = ptr_mode == SImode ? 2 : 3;
+
+  switch_to_section (get_section (".note.gnu.property",
+                                 SECTION_NOTYPE, NULL));
+
+  ASM_OUTPUT_ALIGN (asm_out_file, p2align);
+  /* name length.  */
+  fprintf (asm_out_file, ASM_LONG "1f - 0f\n");
+  /* data length.  */
+  fprintf (asm_out_file, ASM_LONG "4f - 1f\n");
+  /* note type: NT_GNU_PROPERTY_TYPE_0.  */
+  fprintf (asm_out_file, ASM_LONG "5\n");
+  fprintf (asm_out_file, "0:\n");
+  /* vendor name: "GNU".  */
+  fprintf (asm_out_file, STRING_ASM_OP "\"GNU\"\n");
+  fprintf (asm_out_file, "1:\n");
+  ASM_OUTPUT_ALIGN (asm_out_file, p2align);
+  /* pr_type.  */
+  fprintf (asm_out_file, ASM_LONG "0x%x\n", type);
+  /* pr_datasz.  */
+  fprintf (asm_out_file, ASM_LONG "3f - 2f\n");
+  fprintf (asm_out_file, "2:\n");
+  fprintf (asm_out_file, ASM_LONG "0x%x\n", data);
+  fprintf (asm_out_file, "3:\n");
+  ASM_OUTPUT_ALIGN (asm_out_file, p2align);
+  fprintf (asm_out_file, "4:\n");
+}
+
+/* This is a generic routine for TARGET_ASM_EMIT_GNU_PROPERTY_NOTE to
+   emit a NT_GNU_PROPERTY_TYPE_0 note.  This is primarily a GNU extension
+   to ELF but could be used on other targets.  */
+
+void
+emit_gnu_property_note (void)
+{
+  if (HAVE_LD_SINGLE_GLOBAL_DEFINITION_SUPPORT
+      && flag_single_global_definition)
+    /* Emite a GNU_PROPERTY_1_NEEDED note with
+       GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION.  */
+    emit_gnu_property (0xb0008000, (1U << 0));
+}
+
 /* This is a generic routine suitable for use as TARGET_ASM_FILE_END
    which emits a special section directive used to indicate whether or
    not this object file needs an executable stack.  This is primarily
-- 
2.31.1

Reply via email to