From df923f7e0ebee1f10136bb64f9c723f2d58f8f2a Mon Sep 17 00:00:00 2001
From: Igor Tsimbalist <igor.v.tsimbalist@intel.com>
Date: Fri, 27 Oct 2017 15:44:56 +0300
Subject: [PATCH 07/21] Enable building libgcc with CET options

Enable building libgcc with CET options by default on Linux/x86 if
binutils supports CET v2.0.  It can be disabled with --disable-cet.
It is an error to configure GCC with --enable-cet if bintuiils doesn't
support CET v2.0.

ENDBR is added to __morestack_large_model since it is called indirectly.

config/
	* cet.m4: New file.

gcc/
	* config.gcc (extra_headers): Add cet.h for x86 targets.
	* config/i386/cet.h: New file.
	* doc/install.texi: Add --enable-cet/--disable-cet.

libgcc/
	* Makefile.in (configure_deps): Add $(srcdir)/../config/cet.m4.
	(CET_FLAGS): New.
	* config/i386/morestack.S: Include <cet.h>.
	(__morestack_large_model): Add _CET_ENDBR at function entrance.
	* config/i386/resms64.h: Include <cet.h>.
	* config/i386/resms64f.h: Likewise.
	* config/i386/resms64fx.h: Likewise.
	* config/i386/resms64x.h: Likewise.
	* config/i386/savms64.h: Likewise.
	* config/i386/savms64f.h: Likewise.
	* config/i386/t-linux (HOST_LIBGCC2_CFLAGS): Add $(CET_FLAGS).
	(CRTSTUFF_T_CFLAGS): Likewise.
	* configure.ac: Include ../config/cet.m4.
	Set and substitute CET_FLAGS.
	* configure: Regenerated.
---
 config/cet.m4                  | 40 ++++++++++++++++++
 gcc/config.gcc                 |  6 ++-
 gcc/config/i386/cet.h          | 93 ++++++++++++++++++++++++++++++++++++++++++
 gcc/doc/install.texi           | 13 ++++++
 libgcc/Makefile.in             |  5 ++-
 libgcc/config/i386/morestack.S |  3 ++
 libgcc/config/i386/resms64.h   |  2 +
 libgcc/config/i386/resms64f.h  |  2 +
 libgcc/config/i386/resms64fx.h |  2 +
 libgcc/config/i386/resms64x.h  |  2 +
 libgcc/config/i386/savms64.h   |  2 +
 libgcc/config/i386/savms64f.h  |  2 +
 libgcc/config/i386/t-linux     |  3 +-
 libgcc/configure               | 74 +++++++++++++++++++++++++++++++++
 libgcc/configure.ac            |  4 ++
 15 files changed, 249 insertions(+), 4 deletions(-)
 create mode 100644 config/cet.m4
 create mode 100644 gcc/config/i386/cet.h
 mode change 100644 => 100755 libgcc/configure

diff --git a/config/cet.m4 b/config/cet.m4
new file mode 100644
index 0000000..c903791
--- /dev/null
+++ b/config/cet.m4
@@ -0,0 +1,40 @@
+dnl
+dnl GCC_CET_FLAGS
+dnl    (SHELL-CODE_HANDLER)
+dnl
+AC_DEFUN([GCC_CET_FLAGS],[dnl
+GCC_ENABLE(cet, default, ,[enable Intel CET in target libraries],
+	   permit yes|no|default)
+case "$host" in
+  i[34567]86-*-linux* | x86_64-*-linux*)
+    enable_cet_compatibility=yes
+    case "$enable_cet" in
+      default)
+	# Check if assembler supports CET.
+	AC_COMPILE_IFELSE(
+	 [AC_LANG_PROGRAM(
+	  [],
+	  [asm ("setssbsy");])],
+	 [enable_cet=yes],
+	 [enable_cet=no])
+	;;
+      yes)
+	# Check if assembler supports CET.
+	AC_COMPILE_IFELSE(
+	 [AC_LANG_PROGRAM(
+	  [],
+	  [asm ("setssbsy");])],
+	 [],
+	 [AC_MSG_ERROR([assembler with CET support is required for --enable-cet])])
+	;;
+    esac
+    ;;
+  *)
+    enable_cet=no
+    enable_cet_compatibility=no
+    ;;
+esac
+if test x$enable_cet = xyes; then
+  $1="-fcf-protection -mcet"
+fi
+])
diff --git a/gcc/config.gcc b/gcc/config.gcc
index c3dab84..243d6ec 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -378,7 +378,8 @@ i[34567]86-*-*)
 		       avx512ifmaintrin.h avx512ifmavlintrin.h avx512vbmiintrin.h
 		       avx512vbmivlintrin.h avx5124fmapsintrin.h avx5124vnniwintrin.h
 		       avx512vpopcntdqintrin.h clwbintrin.h mwaitxintrin.h
-		       clzerointrin.h pkuintrin.h sgxintrin.h cetintrin.h"
+		       clzerointrin.h pkuintrin.h sgxintrin.h cetintrin.h
+		       cet.h"
 	;;
 x86_64-*-*)
 	cpu_type=i386
@@ -402,7 +403,8 @@ x86_64-*-*)
 		       avx512ifmaintrin.h avx512ifmavlintrin.h avx512vbmiintrin.h
 		       avx512vbmivlintrin.h avx5124fmapsintrin.h avx5124vnniwintrin.h
 		       avx512vpopcntdqintrin.h clwbintrin.h mwaitxintrin.h
-		       clzerointrin.h pkuintrin.h sgxintrin.h cetintrin.h"
+		       clzerointrin.h pkuintrin.h sgxintrin.h cetintrin.h
+		       cet.h"
 	;;
 ia64-*-*)
 	extra_headers=ia64intrin.h
diff --git a/gcc/config/i386/cet.h b/gcc/config/i386/cet.h
new file mode 100644
index 0000000..7300844
--- /dev/null
+++ b/gcc/config/i386/cet.h
@@ -0,0 +1,93 @@
+/* ELF program property for Intel CET.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+   This file 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, or (at your option) any
+   later version.
+
+   This file 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.
+ */
+
+/* Add x86 feature with IBT and/or SHSTK bits to ELF program property
+   if they are enabled.  Otherwise, contents in this header file are
+   unused.  Define _CET_ENDBR for assembly codes.  _CET_ENDBR should be
+   placed unconditionally at the entrance of a function whose address
+   may be taken.  */
+
+#ifndef _CET_H_INCLUDED
+#define _CET_H_INCLUDED
+
+#ifdef __ASSEMBLER__
+
+# ifdef __IBT__
+#  ifdef __x86_64__
+#   define _CET_ENDBR endbr64
+#  else
+#   define _CET_ENDBR endbr32
+#  endif
+# else
+#  define _CET_ENDBR
+# endif
+
+# ifdef __ELF__
+#  ifdef __CET__
+#   ifdef __IBT__
+/* GNU_PROPERTY_X86_FEATURE_1_IBT.  */
+#    define __PROPERTY_IBT 0x1
+#   else
+#    define __PROPERTY_IBT 0x0
+#   endif
+
+#   ifdef __SHSTK__
+/* GNU_PROPERTY_X86_FEATURE_1_SHSTK.  */
+#    define __PROPERTY_SHSTK 0x2
+#   else
+#    define __PROPERTY_SHSTK 0x0
+#   endif
+
+#   define __PROPERTY_BITS (__PROPERTY_IBT | __PROPERTY_SHSTK)
+
+#   ifdef __LP64__
+#    define __PROPERTY_ALIGN 3
+#   else
+#    define __PROPERTY_ALIGN 2
+#   endif
+
+	.pushsection ".note.gnu.property", "a"
+	.p2align __PROPERTY_ALIGN
+	.long 1f - 0f		/* name length.  */
+	.long 4f - 1f		/* data length.  */
+	/* NT_GNU_PROPERTY_TYPE_0.   */
+	.long 5			/* note type.  */
+0:
+	.asciz "GNU"		/* vendor name.  */
+1:
+	.p2align __PROPERTY_ALIGN
+	/* GNU_PROPERTY_X86_FEATURE_1_AND.  */
+	.long 0xc0000002	/* pr_type.  */
+	.long 3f - 2f		/* pr_datasz.  */
+2:
+	/* GNU_PROPERTY_X86_FEATURE_1_XXX.  */
+	.long __PROPERTY_BITS
+3:
+	.p2align __PROPERTY_ALIGN
+4:
+	.popsection
+#  endif /* __CET__ */
+# endif /* __ELF__ */
+#endif /* __ASSEMBLER__ */
+
+#endif /* _CET_H_INCLUDED */
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 34fef37..d067994 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -2084,6 +2084,19 @@ explicitly specify the directory where they are installed.  The
 shorthand for
 @option{--with-hsa-runtime-lib=@/@var{hsainstalldir}/lib} and
 @option{--with-hsa-runtime-include=@/@var{hsainstalldir}/include}.
+
+@item --enable-cet
+@itemx --disable-cet
+Enable building target run-time libraries with control-flow
+instrumentation, see @option{-fcf-protection} option.  When
+@code{--enable-cet} is specified target libraries are configured
+to add @option{-fcf-protection} and, if needed, other target
+specific options to a set of building options.
+
+The option is enabled by default on Linux/x86 if target binutils
+supports @code{Intel CET} instructions.  In this case the target
+libraries are configured to get additional @option{-fcf-protection}
+and @option{-mcet} options.
 @end table
 
 @subheading Cross-Compiler-Specific Options
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index a1a392d..eaa68b5 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -171,7 +171,8 @@ configure_deps = \
 	$(srcdir)/../config/dfp.m4 \
 	$(srcdir)/../config/unwind_ipinfo.m4 \
 	$(srcdir)/../config/gthr.m4 \
-	$(srcdir)/../config/sjlj.m4
+	$(srcdir)/../config/sjlj.m4 \
+	$(srcdir)/../config/cet.m4
 
 $(srcdir)/configure: @MAINT@ $(srcdir)/configure.ac $(configure_deps)
 	cd $(srcdir) && $(AUTOCONF)
@@ -254,6 +255,8 @@ HOST_LIBGCC2_CFLAGS =
 
 PICFLAG = @PICFLAG@
 
+CET_FLAGS = @CET_FLAGS@
+
 # Defined in libgcc2.c, included only in the static library.
 LIB2FUNCS_ST = _eprintf __gcc_bcmp
 
diff --git a/libgcc/config/i386/morestack.S b/libgcc/config/i386/morestack.S
index 9d185c1..79d5db9 100644
--- a/libgcc/config/i386/morestack.S
+++ b/libgcc/config/i386/morestack.S
@@ -91,6 +91,8 @@
 # __morestack to call __morestack_non_split instead.  We just bump the
 # requested stack space by 16K.
 
+#include <cet.h>
+
 	.global __morestack_non_split
 	.hidden	__morestack_non_split
 
@@ -701,6 +703,7 @@ DW.ref.__gcc_personality_v0:
 __morestack_large_model:
 
 	.cfi_startproc
+	_CET_ENDBR
 
 	movq	%r10, %r11
 	andl	$0xffffffff, %r10d
diff --git a/libgcc/config/i386/resms64.h b/libgcc/config/i386/resms64.h
index f01b418..45a42da 100644
--- a/libgcc/config/i386/resms64.h
+++ b/libgcc/config/i386/resms64.h
@@ -23,6 +23,8 @@ a copy of the GCC Runtime Library Exception along with this program;
 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
+#include <cet.h>
+
 #ifdef __x86_64__
 #include "i386-asm.h"
 
diff --git a/libgcc/config/i386/resms64f.h b/libgcc/config/i386/resms64f.h
index 743ec51..00805b3 100644
--- a/libgcc/config/i386/resms64f.h
+++ b/libgcc/config/i386/resms64f.h
@@ -23,6 +23,8 @@ a copy of the GCC Runtime Library Exception along with this program;
 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
+#include <cet.h>
+
 #ifdef __x86_64__
 #include "i386-asm.h"
 
diff --git a/libgcc/config/i386/resms64fx.h b/libgcc/config/i386/resms64fx.h
index 965807a..85083cd 100644
--- a/libgcc/config/i386/resms64fx.h
+++ b/libgcc/config/i386/resms64fx.h
@@ -23,6 +23,8 @@ a copy of the GCC Runtime Library Exception along with this program;
 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
+#include <cet.h>
+
 #ifdef __x86_64__
 #include "i386-asm.h"
 
diff --git a/libgcc/config/i386/resms64x.h b/libgcc/config/i386/resms64x.h
index 689a1de..fcf885e 100644
--- a/libgcc/config/i386/resms64x.h
+++ b/libgcc/config/i386/resms64x.h
@@ -23,6 +23,8 @@ a copy of the GCC Runtime Library Exception along with this program;
 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
+#include <cet.h>
+
 #ifdef __x86_64__
 #include "i386-asm.h"
 
diff --git a/libgcc/config/i386/savms64.h b/libgcc/config/i386/savms64.h
index 28d5e35..570902d 100644
--- a/libgcc/config/i386/savms64.h
+++ b/libgcc/config/i386/savms64.h
@@ -23,6 +23,8 @@ a copy of the GCC Runtime Library Exception along with this program;
 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
+#include <cet.h>
+
 #ifdef __x86_64__
 #include "i386-asm.h"
 
diff --git a/libgcc/config/i386/savms64f.h b/libgcc/config/i386/savms64f.h
index 723e108..51c9d97 100644
--- a/libgcc/config/i386/savms64f.h
+++ b/libgcc/config/i386/savms64f.h
@@ -23,6 +23,8 @@ a copy of the GCC Runtime Library Exception along with this program;
 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
+#include <cet.h>
+
 #ifdef __x86_64__
 #include "i386-asm.h"
 
diff --git a/libgcc/config/i386/t-linux b/libgcc/config/i386/t-linux
index 11bb46e..8506a63 100644
--- a/libgcc/config/i386/t-linux
+++ b/libgcc/config/i386/t-linux
@@ -3,4 +3,5 @@
 # t-slibgcc-elf-ver and t-linux
 SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/i386/libgcc-glibc.ver
 
-HOST_LIBGCC2_CFLAGS += -mlong-double-80 -DUSE_ELF_SYMVER
+HOST_LIBGCC2_CFLAGS += -mlong-double-80 -DUSE_ELF_SYMVER $(CET_FLAGS)
+CRTSTUFF_T_CFLAGS += $(CET_FLAGS)
diff --git a/libgcc/configure b/libgcc/configure
old mode 100644
new mode 100755
index 63c50c0..d3c13d5
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -573,6 +573,7 @@ vis_hide
 real_host_noncanonical
 accel_dir_suffix
 force_explicit_eh_registry
+CET_FLAGS
 fixed_point
 enable_decimal_float
 decimal_float
@@ -675,6 +676,7 @@ with_build_libsubdir
 enable_largefile
 enable_decimal_float
 with_system_libunwind
+enable_cet
 enable_explicit_exception_frame_registration
 with_glibc_version
 enable_tls
@@ -1314,6 +1316,8 @@ Optional Features:
 			enable decimal float extension to C.  Selecting 'bid'
 			or 'dpd' choses which decimal floating point format
 			to use
+  --enable-cet            enable Intel CET in target libraries
+                          [default=default]
   --enable-explicit-exception-frame-registration
                           register exception tables explicitly at module
                           start, for use e.g. for compatibility with
@@ -4773,6 +4777,76 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sjlj_exceptions" >&5
 $as_echo "$ac_cv_sjlj_exceptions" >&6; }
 
+ # Check whether --enable-cet was given.
+if test "${enable_cet+set}" = set; then :
+  enableval=$enable_cet;
+      case "$enableval" in
+       yes|no|default) ;;
+       *) as_fn_error "Unknown argument to enable/disable cet" "$LINENO" 5 ;;
+                          esac
+
+else
+  enable_cet=default
+fi
+
+
+case "$host" in
+  i3456786-*-linux* | x86_64-*-linux*)
+    enable_cet_compatibility=yes
+    case "$enable_cet" in
+      default)
+	# Check if assembler supports CET.
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+asm ("setssbsy");
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  enable_cet=yes
+else
+  enable_cet=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+	;;
+      yes)
+	# Check if assembler supports CET.
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+asm ("setssbsy");
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  as_fn_error "assembler with CET support is required for --enable-cet" "$LINENO" 5
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+	;;
+    esac
+    ;;
+  *)
+    enable_cet=no
+    enable_cet_compatibility=no
+    ;;
+esac
+if test x$enable_cet = xyes; then
+  CET_FLAGS="-fcf-protection -mcet"
+fi
+
+
+
 # Check whether --enable-explicit-exception-frame-registration was given.
 if test "${enable_explicit_exception_frame_registration+set}" = set; then :
   enableval=$enable_explicit_exception_frame_registration;
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index dd60b01..0942b25 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -11,6 +11,7 @@ sinclude(../config/dfp.m4)
 sinclude(../config/unwind_ipinfo.m4)
 sinclude(../config/gthr.m4)
 sinclude(../config/sjlj.m4)
+sinclude(../config/cet.m4)
 
 AC_PREREQ(2.64)
 AC_INIT([GNU C Runtime Library], 1.0,,[libgcc])
@@ -236,6 +237,9 @@ GCC_CHECK_UNWIND_GETIPINFO
 # Check if the compiler is configured for setjmp/longjmp exceptions.
 GCC_CHECK_SJLJ_EXCEPTIONS
 
+GCC_CET_FLAGS(CET_FLAGS)
+AC_SUBST(CET_FLAGS)
+
 AC_ARG_ENABLE([explicit-exception-frame-registration],
   [AC_HELP_STRING([--enable-explicit-exception-frame-registration],
      [register exception tables explicitly at module start, for use
-- 
1.8.3.1

