Re: [PATCH][ARM] Fix PR target/69403: Bug in thumb2_ior_scc_strict_it pattern

2016-01-21 Thread Han Shen
Hi Kyrill, the patched gcc generates correct asm for me for the test
case.  (I'll then build the whole system to see if other it-block
related bugs are gone too.)

One short question, the newly generated RTL for
x = x |(a)
will be
orr %0, %1, #1; it ; mov%D2\\t%0, %1 (b)

The cond in (a) should be the reverse of cond in(b), right?

Thanks for your quick fix.

Han

On Thu, Jan 21, 2016 at 9:51 AM, Kyrill Tkachov
 wrote:
> Hi all,
>
> In this wrong-code PR the pattern for performing
> x = x |  for -mrestrict-it is buggy and ends up writing 1 to the
> result register rather than orring it.
>
> The offending pattern is *thumb2_ior_scc_strict_it.
> My proposed solution is to rewrite it as a splitter, remove the
> alternative for the case where operands[1] and 0 are the same reg
> that emits the bogus:
> it ; mov%0, #1; it ; orr %0, %1
>
> to emit the RTL equivalent to:
> orr %0, %1, #1; it ; mov%D2\\t%0, %1
> while marking operand 0 as an earlyclobber operand so that it doesn't
> get assigned the same register as operand 1.
>
> This way we avoid the wrong-code, make the sequence better (by eliminating
> the move of #1 into a register
> and relaxing the constraints from 'l' to 'r' since only the register move
> has to be conditional).
> and still stay within the rules for arm_restrict_it.
>
> Bootstrapped and tested on arm-none-linux-gnueabihf configured
> --with-arch=armv8-a and --with-mode=thumb.
>
> Ok for trunk, GCC 5 and 4.9?
>
> Han, can you please try this out to see if it solves the problem on your end
> as well?
>
> Thanks,
> Kyrill
>
> 2016-01-21  Kyrylo Tkachov  
>
> PR target/69403
> * config/arm/thumb2.md (*thumb2_ior_scc_strict_it): Convert to
> define_insn_and_split.  Ensure operands[1] and operands[0] do not
>     get assigned the same register.
>
> 2016-01-21  Kyrylo Tkachov  
>
> PR target/69403
> * gcc.c-torture/execute/pr69403.c: New test.



-- 
Han Shen |  Software Engineer |  shen...@google.com |  +1-650-440-3330


[google gcc-4_9]: Backport trunk:r232727 fix for PR/69403.

2016-01-28 Thread Han Shen
Backport trunk:r232727 fix for PR/69403 - wrong
thumb2_ior_scc_strict_it insn pattern.

Note this only affect armv7-a tuned for armv8 arch, tested / booted
affected ChromeOS book.

Ok for google/gcc-4_9 branch?

-- 
Han Shen
Index: gcc/ChangeLog
===
--- gcc/ChangeLog	(revision 232940)
+++ gcc/ChangeLog	(working copy)
@@ -1,3 +1,10 @@
+2016-01-22  Kyrylo Tkachov  
+
+	PR target/69403
+	* config/arm/thumb2.md (*thumb2_ior_scc_strict_it): Convert to
+	define_insn_and_split.  Ensure operands[1] and operands[0] do not
+	get assigned the same register.
+
 2015-03-26  Bill Schmidt  
 
 	Backport of r214242, r214254, and bug fix patches from mainline
Index: gcc/config/arm/thumb2.md
===
--- gcc/config/arm/thumb2.md	(revision 232940)
+++ gcc/config/arm/thumb2.md	(working copy)
@@ -642,15 +642,27 @@
(set_attr "type" "multiple")]
 )
 
-(define_insn "*thumb2_ior_scc_strict_it"
-  [(set (match_operand:SI 0 "s_register_operand" "=l,l")
+(define_insn_and_split "*thumb2_ior_scc_strict_it"
+  [(set (match_operand:SI 0 "s_register_operand" "=&r")
 	(ior:SI (match_operator:SI 2 "arm_comparison_operator"
 		 [(match_operand 3 "cc_register" "") (const_int 0)])
-		(match_operand:SI 1 "s_register_operand" "0,?l")))]
+		(match_operand:SI 1 "s_register_operand" "r")))]
   "TARGET_THUMB2 && arm_restrict_it"
-  "@
-   it\\t%d2\;mov%d2\\t%0, #1\;it\\t%d2\;orr%d2\\t%0, %1
-   mov\\t%0, #1\;orr\\t%0, %1\;it\\t%D2\;mov%D2\\t%0, %1"
+  "#" ; orr\\t%0, %1, #1\;it\\t%D2\;mov%D2\\t%0, %1
+  "&& reload_completed"
+  [(set (match_dup 0) (ior:SI (match_dup 1) (const_int 1)))
+   (cond_exec (match_dup 4)
+ (set (match_dup 0) (match_dup 1)))]
+  {
+machine_mode mode = GET_MODE (operands[3]);
+rtx_code rc = GET_CODE (operands[2]);
+
+if (mode == CCFPmode || mode == CCFPEmode)
+  rc = reverse_condition_maybe_unordered (rc);
+else
+  rc = reverse_condition (rc);
+operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
+  }
   [(set_attr "conds" "use")
(set_attr "length" "8")
(set_attr "type" "multiple")]
Index: gcc/testsuite/ChangeLog
===
--- gcc/testsuite/ChangeLog	(revision 232940)
+++ gcc/testsuite/ChangeLog	(working copy)
@@ -1,3 +1,8 @@
+2016-01-22  Kyrylo Tkachov  
+
+	PR target/69403
+	* gcc.c-torture/execute/pr69403.c: New test.
+
 2015-03-26  Bill Schmidt  
 
 	Backport r214254 and related tests from mainline
Index: .
===
--- .	(revision 232940)
+++ .	(working copy)

Property changes on: .
___
Modified: svn:mergeinfo
   Merged /trunk:r232727


Re: [PATCH] Add a new option "-fstack-protector-strong"

2013-04-16 Thread Han Shen
 smashing attack needs a frame
address to perform the attack. The frame address of function F can be
from one of the following:
 - (A) an address taking operator (&) on any local variables of F
 - (B) any address computation based on (A)
 - (C) any address casting operation from either (A) or (B)
 - (D) the name of a local array of F
 - (E) the address  from calling “alloca”
 Function F is said to be vulnerable if its frame address is
exposed via (A) ~ (E).



What about struct-returning functions?  Internally, an address is passed to
the called function.  Would they trigger this?  What about the this pointer
in C++ code?

Yes for 'this' pointer. 'this' pointer of a local class instance is 
regarded as a reference to stack address, thus it is protected. For 
example -

int
foo1 ()
{
  A a;
  a.method ();  // a.method() exposes 'this', so this function is 
protected.

  return a.state;
}

No for 'struct-returning' functions. But I regard this not an issue --- 
at the programming level, there is no way to get one's hand on the 
address of a returned structure ---

   struct Node foo();
   struct Node *p = &foo();  // compiler error - lvalue required as 
unary '&' operand.

If write this way -
   struct Node p = foo();
   struct Node *q = &p;
The protection would be triggered.





--
Florian Weimer / Red Hat Product Security Team


ChangeLog and patch below --

gcc/ChangeLog
2013-04-16  Han Shen  
* cfgexpand.c (record_or_union_type_has_array_p): Helper function
to check if a record or union contains an array field.
(expand_used_vars): Add logic handling '-fstack-protector-strong'.
* common.opt (fstack-protector-all): New option.
    * doc/cpp.texi (__SSP_STRONG__): New builtin "__SSP_STRONG__".
* doc/invoke.texi (Optimization Options): Document
"-fstack-protector-strong".
* gcc.c (LINK_SSP_SPEC): Add 'fstack-protector-strong'.

gcc/c-family/ChangeLog
2013-04-16  Han Shen  
* c-cppbuiltin.c (c_cpp_builtins): Added "__SSP_STRONG__=3".

gcc/testsuite/ChangeLog
2013-04-16  Han Shen  
Test cases for '-fstack-protector-strong'.
* gcc.dg/fstack-protector-strong.c: New.
* g++.dg/fstack-protector-strong.C: New.


diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 3e210d9..0059626 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -888,6 +888,8 @@ c_cpp_builtins (cpp_reader *pfile)
   /* Make the choice of the stack protector runtime visible to source 
code.

  The macro names and values here were chosen for compatibility with an
  earlier implementation, i.e. ProPolice.  */
+  if (flag_stack_protect == 3)
+cpp_define (pfile, "__SSP_STRONG__=3");
   if (flag_stack_protect == 2)
 cpp_define (pfile, "__SSP_ALL__=2");
   else if (flag_stack_protect == 1)
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index a651d8c..b370cdb 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -1291,6 +1291,10 @@ clear_tree_used (tree block)
 clear_tree_used (t);
 }

+#define SPCT_FLAG_ALL 2
+#define SPCT_FLAG_DEFAULT 1
+#define SPCT_FLAG_STRONG 3
+
 /* Examine TYPE and determine a bit mask of the following features.  */

 #define SPCT_HAS_LARGE_CHAR_ARRAY  1
@@ -1360,7 +1364,8 @@ stack_protect_decl_phase (tree decl)
   if (bits & SPCT_HAS_SMALL_CHAR_ARRAY)
 has_short_buffer = true;

-  if (flag_stack_protect == 2)
+  if (flag_stack_protect == SPCT_FLAG_ALL ||
+  flag_stack_protect == SPCT_FLAG_STRONG)
 {
   if ((bits & (SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_LARGE_CHAR_ARRAY))
  && !(bits & SPCT_HAS_AGGREGATE))
@@ -1514,6 +1519,27 @@ estimated_stack_frame_size (struct cgraph_node *node)
   return size;
 }

+/* Helper routine to check if a record or union contains an array field. */
+
+static int
+record_or_union_type_has_array_p (const_tree tree_type)
+{
+  tree fields = TYPE_FIELDS (tree_type);
+  tree f;
+
+  for (f = fields; f; f = DECL_CHAIN (f))
+if (TREE_CODE (f) == FIELD_DECL)
+  {
+   tree field_type = TREE_TYPE (f);
+   if (RECORD_OR_UNION_TYPE_P (field_type)
+   && record_or_union_type_has_array_p (field_type))
+ return 1;
+   if (TREE_CODE (field_type) == ARRAY_TYPE)
+ return 1;
+  }
+  return 0;
+}
+
 /* Expand all variables used in the function.  */

 static rtx
@@ -1525,6 +1551,7 @@ expand_used_vars (void)
   struct pointer_map_t *ssa_name_decls;
   unsigned i;
   unsigned len;
+  bool gen_stack_protect_signal = false;

   /* Compute the phase of the stack frame for this function.  */
   {
@@ -1576,6 +1603,24 @@ expand_used_vars (void)
 }
   pointer_map_destroy (ssa_name_decls);

+  if (flag_stack_protect == SPCT_FLAG_STRONG)
+FOR_EACH_LOCAL_DEC

[trunk] RFS: translate built-in include paths for sysroot (issue5394041)

2011-11-15 Thread Han Shen
2011-11-15   Han Shen  

* gcc/Makefile.in:
* gcc/configure:
* gcc/cppdefault.c:

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index ae4f4da..0a05783 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -615,6 +615,7 @@ gcc_tooldir = @gcc_tooldir@
 build_tooldir = $(exec_prefix)/$(target_noncanonical)
 # Directory in which the compiler finds target-independent g++ includes.
 gcc_gxx_include_dir = @gcc_gxx_include_dir@
+gcc_gxx_include_dir_add_sysroot = @gcc_gxx_include_dir_add_sysroot@
 # Directory to search for site-specific includes.
 local_includedir = $(local_prefix)/include
 includedir = $(prefix)/include
@@ -3979,6 +3980,7 @@ PREPROCESSOR_DEFINES = \
   -DGCC_INCLUDE_DIR=\"$(libsubdir)/include\" \
   -DFIXED_INCLUDE_DIR=\"$(libsubdir)/include-fixed\" \
   -DGPLUSPLUS_INCLUDE_DIR=\"$(gcc_gxx_include_dir)\" \
+  -DGPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_include_dir_add_sysroot) \
   
-DGPLUSPLUS_TOOL_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/$(target_noncanonical)\" \
   -DGPLUSPLUS_BACKWARD_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/backward\" \
   -DLOCAL_INCLUDE_DIR=\"$(local_includedir)\" \
diff --git a/gcc/configure b/gcc/configure
index 99334ce..364d8c2 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -638,6 +638,7 @@ host_xm_include_list
 host_xm_file_list
 host_exeext
 gcc_gxx_include_dir
+gcc_gxx_include_dir_add_sysroot
 gcc_config_arguments
 float_h_file
 extra_programs
@@ -3291,12 +3292,20 @@ gcc_gxx_include_dir=
 # Specify the g++ header file directory
 
 # Check whether --with-gxx-include-dir was given.
+gcc_gxx_include_dir_add_sysroot=0
 if test "${with_gxx_include_dir+set}" = set; then :
   withval=$with_gxx_include_dir; case "${withval}" in
 yes)   as_fn_error "bad value ${withval} given for g++ include directory" 
"$LINENO" 5 ;;
 no);;
 *) gcc_gxx_include_dir=$with_gxx_include_dir ;;
 esac
+  if test "${with_sysroot+set}" = set; then :
+gcc_gxx_without_sysroot=`expr "${gcc_gxx_include_dir}" : 
"${with_sysroot}"'\(.*\)'`
+if test "${gcc_gxx_without_sysroot}"; then :
+  gcc_gxx_include_dir="${gcc_gxx_without_sysroot}"
+  gcc_gxx_include_dir_add_sysroot=1
+fi
+  fi
 fi
 
 
diff --git a/gcc/cppdefault.c b/gcc/cppdefault.c
index 099899a..e8341d5 100644
--- a/gcc/cppdefault.c
+++ b/gcc/cppdefault.c
@@ -44,15 +44,15 @@ const struct default_include cpp_include_defaults[]
 = {
 #ifdef GPLUSPLUS_INCLUDE_DIR
 /* Pick up GNU C++ generic include files.  */
-{ GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, 0, 0 },
+{ GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 
},
 #endif
 #ifdef GPLUSPLUS_TOOL_INCLUDE_DIR
 /* Pick up GNU C++ target-dependent include files.  */
-{ GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1, 0, 1 },
+{ GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1, 
GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 1 },
 #endif
 #ifdef GPLUSPLUS_BACKWARD_INCLUDE_DIR
 /* Pick up GNU C++ backward and deprecated include files.  */
-{ GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, 0, 0 },
+{ GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, 
GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 },
 #endif
 #ifdef GCC_INCLUDE_DIR
 /* This is the dir for gcc's private headers.  */

--
This patch is available for review at http://codereview.appspot.com/5394041


[4.7][google] Adding a new option -fstack-protector-strong. (issue5461043)

2011-12-07 Thread Han Shen
Hi, this patch provides a new stack protection option - 
"fstack-protector-strong".

Background - some times stack-protector is too-simple while stack-protector-all 
over-kills, for example, to build one of our core systems, we forcibly add 
"-fstack-protector-all" to all compile commands, which brings big performance 
penalty (due to extra stack guard/check insns on function prologue and 
epilogue) on both atom and arm. To use "-fstack-protector" is just regarded as 
not secure enough (only "protects" <2% functions) by the system secure team. So 
I'd like to add the option "-fstack-protector-strong", that hits the balance 
between "-fstack-protector" and "-fstack-protector-all".

Benefit - gain big performance while sacrificing little security (for scenarios 
using -fstack-protector-all)

Status - implemented internally, to be up-streamed or merged to google branch 
only.

Detail - 
https://docs.google.com/a/google.com/document/d/1xXBH6rRZue4f296vGt9YQcuLVQHeE516stHwt8M9xyU/edit?hl=en_US

Tested - manually, built chrome browser using the modified compiler with 
"-fstack-protector-strong".

=
gcc/ChangeLog:
* cfgexpand.c (expand_used_vars): Add logic handling 
stack-protector-strong.
(is_local_address_taken): Internal function that returns true when 
gimple contains
an address taken on function local variables.
(record_or_union_type_has_array): New, tests if a record or union type 
contains an array.
* common.opt (fstack-protector-all): New option.

gcc/testsuite/ChangeLog
* gcc.dg/fstack-protector-strong.c: New.

==

diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 8684721..1d9df87 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -1507,6 +1507,50 @@ estimated_stack_frame_size (struct cgraph_node *node)
   return size;
 }
 
+static int is_local_address_taken(tree t) {
+  if (t && TREE_CODE(t) == ADDR_EXPR) {
+int i;
+tree local_var;
+tree v = TREE_OPERAND(t, 0);
+switch (TREE_CODE(v)) {
+case MEM_REF:
+  for (i = 0; i < TREE_OPERAND_LENGTH(v); ++i)
+if (is_local_address_taken(TREE_OPERAND(v, i)))
+  return 1;
+  return 0;
+case COMPONENT_REF:
+  while (v && TREE_CODE(v) == COMPONENT_REF)
+v = TREE_OPERAND(v, 0);
+  break;
+case VAR_DECL:
+default:
+  ;
+}
+if (v && TREE_CODE(v) == VAR_DECL && !is_global_var(v)) {
+  FOR_EACH_VEC_ELT(tree, cfun->local_decls, i, local_var) {
+if (local_var == v)
+  return 1;
+  }
+}
+  }
+  return 0;
+}
+
+static int record_or_union_type_has_array(tree tree_type) {
+  tree fields = TYPE_FIELDS(tree_type);
+  tree f;
+  for (f = fields; f; f = DECL_CHAIN (f)) {
+if (TREE_CODE(f) == FIELD_DECL) {
+  tree field_type = TREE_TYPE(f);
+  if (RECORD_OR_UNION_TYPE_P(field_type))
+return record_or_union_type_has_array(field_type);
+  if (TREE_CODE(field_type) == ARRAY_TYPE)
+return 1;
+}
+  }
+  return 0;
+}
+
 /* Expand all variables used in the function.  */
 
 static void
@@ -1516,6 +1560,8 @@ expand_used_vars (void)
   VEC(tree,heap) *maybe_local_decls = NULL;
   unsigned i;
   unsigned len;
+  int gen_stack_protect_signal = 0;
+  basic_block bb;
 
   /* Compute the phase of the stack frame for this function.  */
   {
@@ -1548,6 +1594,63 @@ expand_used_vars (void)
}
 }
 
+  /* Examine each basic block for address taking of local variables. */
+  FOR_EACH_BB(bb) {
+gimple_stmt_iterator si;
+/* Scanning phis. */
+for (si = gsi_start_phis(bb); !gsi_end_p(si); gsi_next(&si)) {
+  gimple phi_stmt = gsi_stmt(si);
+  unsigned int i;
+  for (i = 0; i < gimple_phi_num_args(phi_stmt); ++i)
+if (is_local_address_taken(gimple_phi_arg(phi_stmt, i)->def))
+  ++gen_stack_protect_signal;
+}
+/* Scanning assignments and calls. */
+for (si = gsi_start_bb(bb); !gen_stack_protect_signal && !gsi_end_p(si);
+ gsi_next(&si)) {
+  gimple stmt = gsi_stmt (si);
+  if (is_gimple_assign(stmt)) {
+switch(gimple_assign_rhs_class(stmt)) {
+case GIMPLE_TERNARY_RHS:
+  if (is_local_address_taken(gimple_assign_rhs3(stmt))) {
+++gen_stack_protect_signal;
+break;
+  }
+  /* Otherwise, fall through. */
+case GIMPLE_BINARY_RHS:
+  if (is_local_address_taken(gimple_assign_rhs2(stmt))) {
+++gen_stack_protect_signal;
+break;
+  }
+case GIMPLE_SINGLE_RHS:
+case GIMPLE_UNARY_RHS:
+  if (is_local_address_taken(gimple_assign_rhs1(stmt)))
+++gen_stack_protect_signal;
+  break;
+case GIMPLE_INVALID_RHS:
+  break;
+}
+  }
+
+  if (!gen_stack_protect_signal && is_gimple_call(stmt)) {
+int ii, num_arg = gimple_call_num_args(stmt);
+for (ii = 0; !gen_stack_protect_signal && ii < num_arg; ++ii)
+