Hi,

Currently bndret is generated each time we need to get bounds for returned 
pointer.  It causes bndret generated for not instrumented calls incuding 
builtin function calls.  Troubles appear when such builtin call is optimized 
out - bndret needs to be handled appropriately.  Since we don't want not 
instrumented builtin calls optimizers to be affected by instrumentation, we 
better avoid bndret for not instrumented calls.  This patch uses zero bounds 
when we don't expect call to return bounds.

Bootstrapped and tested on  x86_64-unknown-linux-gnu.  OK for trunk?

Thanks,
Ilya
--
gcc/

2014-12-02  Ilya Enkovich  <ilya.enkov...@intel.com>

        * tree-chkp.c (chkp_call_returns_bounds_p): New.
        (chkp_build_returned_bound): Use zero bounds as
        returned by calls not returning bounds.

gcc/testsuite/

2014-12-02  Ilya Enkovich  <ilya.enkov...@intel.com>

        * gcc.target/i386/chkp-bndret.c: New.
        * gcc.target/i386/chkp-strchr.c: New.


diff --git a/gcc/testsuite/gcc.target/i386/chkp-bndret.c 
b/gcc/testsuite/gcc.target/i386/chkp-bndret.c
new file mode 100644
index 0000000..3498058
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/chkp-bndret.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target mpx } */
+/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkp" } */
+/* { dg-final { scan-tree-dump-not "bndret" "chkp" } } */
+/* { dg-final { cleanup-tree-dump "chkp" } } */
+
+#include "string.h"
+
+extern int *test1 (int *p) __attribute__((bnd_legacy));
+
+int *
+test2 (int *p)
+{
+  return test1 (p);
+}
diff --git a/gcc/testsuite/gcc.target/i386/chkp-strchr.c 
b/gcc/testsuite/gcc.target/i386/chkp-strchr.c
new file mode 100644
index 0000000..94a5eaa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/chkp-strchr.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target mpx } */
+/* { dg-options "-fcheck-pointer-bounds -mmpx -O2" } */
+
+#include "string.h"
+
+static char *
+test1 (char *str)
+{
+  return strrchr (str, '_');
+}
+
+char *
+test2 ()
+{
+  return test1 ("test_string");
+}
diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c
index 3e38691..f7def51 100644
--- a/gcc/tree-chkp.c
+++ b/gcc/tree-chkp.c
@@ -2080,6 +2080,38 @@ chkp_get_nonpointer_load_bounds (void)
   return chkp_get_zero_bounds ();
 }
 
+/* Return 1 if may use bndret call to get bounds for pointer
+   returned by CALL.  */
+static bool
+chkp_call_returns_bounds_p (gcall *call)
+{
+  if (gimple_call_internal_p (call))
+    return false;
+
+  tree fndecl = gimple_call_fndecl (call);
+
+  if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
+    return false;
+
+  if (fndecl
+      && lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (fndecl)))
+    return false;
+
+  if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+    {
+      if (chkp_instrument_normal_builtin (fndecl))
+       return true;
+
+      if (!lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)))
+       return false;
+
+      struct cgraph_node *clone = chkp_maybe_create_clone (fndecl);
+      return (clone && gimple_has_body_p (clone->decl));
+    }
+
+  return true;
+}
+
 /* Build bounds returned by CALL.  */
 static tree
 chkp_build_returned_bound (gcall *call)
@@ -2154,7 +2186,7 @@ chkp_build_returned_bound (gcall *call)
 
       bounds = chkp_find_bounds (gimple_call_arg (call, argno), &iter);
     }
-  else
+  else if (chkp_call_returns_bounds_p (call))
     {
       gcc_assert (TREE_CODE (gimple_call_lhs (call)) == SSA_NAME);
 
@@ -2172,6 +2204,8 @@ chkp_build_returned_bound (gcall *call)
 
       update_stmt (stmt);
     }
+  else
+    bounds = chkp_get_zero_bounds ();
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {

Reply via email to