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)) {